@theholocron/holocron-plugin-fern 5.0.0-alpha.42 → 5.0.0-alpha.420
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 +5 -3
- package/dist/index.d.mts +54 -23
- package/dist/index.mjs +63 -16
- package/package.json +24 -21
package/README.md
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
<!-- alex disable host-hostess -->
|
|
2
|
+
|
|
1
3
|
<!-- editorconfig-checker-disable-file -->
|
|
2
4
|
|
|
3
5
|
# `@theholocron/holocron-plugin-fern`
|
|
@@ -42,7 +44,7 @@ pnpm add -D @theholocron/holocron-plugin-fern
|
|
|
42
44
|
| `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
45
|
| `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
46
|
|
|
45
|
-
## What `holocron setup` does
|
|
47
|
+
## What `holocron repo setup` does
|
|
46
48
|
|
|
47
49
|
1. **Writes `fern/fern.config.json`** — Fern workspace org name and pinned
|
|
48
50
|
CLI version. Always overwritten.
|
|
@@ -79,11 +81,11 @@ DNS: add one CNAME record — `wiki.theholocron.dev` →
|
|
|
79
81
|
Password protection is configured in the **Fern Dashboard**
|
|
80
82
|
(`dashboard.buildwithfern.com`) — it is not configurable via `docs.yml` or
|
|
81
83
|
any CLI flag. Configure access control manually in the dashboard after
|
|
82
|
-
running `holocron setup`.
|
|
84
|
+
running `holocron repo setup`.
|
|
83
85
|
|
|
84
86
|
## CI secrets
|
|
85
87
|
|
|
86
|
-
Add `HOLOCRON_FERN_TOKEN` to your repo's GitHub Secrets. The `wiki
|
|
88
|
+
Add `HOLOCRON_FERN_TOKEN` to your repo's GitHub Secrets. The `publish-wiki` thin caller
|
|
87
89
|
passes it to the Fern CLI during `fern generate --docs`.
|
|
88
90
|
|
|
89
91
|
| Secret | Purpose |
|
package/dist/index.d.mts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import { AuthError, DnsRecordRequest, ResolveTokenInput, Wiki, WikiProvisionOpts, WikiProxyConfig } from "@theholocron/cli";
|
|
2
|
-
|
|
3
|
-
declare const
|
|
4
|
-
|
|
1
|
+
import { AuthError, DnsRecordRequest, PluginToken, ResolveTokenInput, Wiki, WikiProvisionOpts, WikiProxyConfig } from "@theholocron/cli";
|
|
2
|
+
/** Resolves the Fern token from `--token`, `HOLOCRON_FERN_TOKEN`, `FERN_TOKEN` or the keyring entry for `fern`, and throws `AuthError` when none is set. */
|
|
3
|
+
export declare const resolveToken: import("@theholocron/cli").TokenResolver;
|
|
4
|
+
/** Every token this plugin takes, for `holocron doctor tokens`. */
|
|
5
|
+
export declare const tokens: PluginToken[];
|
|
6
|
+
/** The Fern CLI version written into `fern/fern.config.json`. */
|
|
7
|
+
export declare const FERN_VERSION = "5.114.1";
|
|
8
|
+
/** Options for the Fern `wiki` capability. */
|
|
9
|
+
interface FernWikiOptions extends ResolveTokenInput {
|
|
5
10
|
/** Absolute path to the working repo root. Injected by the loader from RuntimeContext. */
|
|
6
11
|
repoRoot?: string;
|
|
7
|
-
/** Active org name (e.g. "
|
|
12
|
+
/** Active org name (e.g. "acme"). Injected by the loader from RuntimeContext. */
|
|
8
13
|
org?: string;
|
|
9
14
|
/**
|
|
10
15
|
* "owner/name" repo coordinate. Injected by the loader from RuntimeContext.
|
|
@@ -12,15 +17,15 @@ interface FernWikiOptions {
|
|
|
12
17
|
*/
|
|
13
18
|
repo?: string;
|
|
14
19
|
/**
|
|
15
|
-
* Base domain for the Fern docs site (e.g. "wiki.
|
|
20
|
+
* Base domain for the Fern docs site (e.g. "wiki.example.dev").
|
|
16
21
|
*
|
|
17
22
|
* When provided without a path, the repo name is appended automatically:
|
|
18
|
-
* domain "wiki.
|
|
19
|
-
* → custom-domain: wiki.
|
|
23
|
+
* domain "wiki.example.dev" + repo "owner/holocron"
|
|
24
|
+
* → custom-domain: wiki.example.dev/holocron
|
|
20
25
|
* → multi-source: true
|
|
21
26
|
*
|
|
22
27
|
* You can also supply the full path explicitly:
|
|
23
|
-
* domain "wiki.
|
|
28
|
+
* domain "wiki.example.dev/holocron"
|
|
24
29
|
*
|
|
25
30
|
* Note: password protection is configured in the Fern Dashboard
|
|
26
31
|
* (https://dashboard.buildwithfern.com) — it is not configurable via docs.yml.
|
|
@@ -30,42 +35,68 @@ interface FernWikiOptions {
|
|
|
30
35
|
* Fern workspace org slug. Defaults to `org` (the GitHub org name).
|
|
31
36
|
* Set this explicitly when the Fern workspace name differs from the
|
|
32
37
|
* GitHub org — e.g. the workspace was registered as "holocron" while
|
|
33
|
-
* the GitHub org is "
|
|
38
|
+
* the GitHub org is "acme".
|
|
34
39
|
*/
|
|
35
40
|
fernOrg?: string;
|
|
36
41
|
/**
|
|
37
42
|
* One-line description shown on the global product switcher card.
|
|
38
43
|
* Falls back to the top-level `description` field in `holocron.config.ts`
|
|
39
|
-
* when omitted. Only used by `holocron sync --steps wiki`.
|
|
44
|
+
* when omitted. Only used by `holocron repo sync --steps wiki`.
|
|
40
45
|
*/
|
|
41
46
|
subtitle?: string;
|
|
42
47
|
/**
|
|
43
48
|
* Font Awesome icon class for the product switcher card (e.g. `"fa-duotone fa-gear"`).
|
|
44
|
-
* Only used by `holocron sync --steps wiki`.
|
|
49
|
+
* Only used by `holocron repo sync --steps wiki`.
|
|
45
50
|
*/
|
|
46
51
|
icon?: string;
|
|
47
52
|
}
|
|
48
|
-
|
|
53
|
+
/** `wiki` capability for Fern: writes the Fern config and docs scaffold for a repo. */
|
|
54
|
+
export declare class FernWiki implements Wiki {
|
|
49
55
|
private readonly opts;
|
|
56
|
+
/** Capability key; always `"wiki"`. */
|
|
50
57
|
readonly key: "wiki";
|
|
58
|
+
/** Provider name; always `"fern"`. */
|
|
51
59
|
readonly providerName = "fern";
|
|
52
60
|
constructor(opts: FernWikiOptions);
|
|
53
61
|
provision(callOpts?: WikiProvisionOpts): Promise<string>;
|
|
54
62
|
proxyConfig(): WikiProxyConfig | null;
|
|
63
|
+
/**
|
|
64
|
+
* Confirms `HOLOCRON_FERN_TOKEN`/`FERN_TOKEN` resolves, or a Fern token
|
|
65
|
+
* is stored in the keyring — not a live check. Fern exposes no
|
|
66
|
+
* lightweight endpoint to verify a token actually works (the only
|
|
67
|
+
* token-consuming operation is a full `fern generate`, see
|
|
68
|
+
* holocron#1079); this only confirms one is configured, the same way
|
|
69
|
+
* CI's `fern generate --docs` step would find it.
|
|
70
|
+
*
|
|
71
|
+
* Deliberately ignores `cliToken` (`--token`): CI's step only ever sees
|
|
72
|
+
* the env var from a GitHub Actions secret, never a CLI flag — and a
|
|
73
|
+
* bare `--token <value>` meant for some OTHER provider is forwarded to
|
|
74
|
+
* every loaded plugin as a fallback (see AGENTS.md), so honoring it
|
|
75
|
+
* here would report "configured" even when no Fern-specific credential
|
|
76
|
+
* exists anywhere CI would actually look.
|
|
77
|
+
*
|
|
78
|
+
* Only `AuthError` (the specific "no token found" signal) is treated as
|
|
79
|
+
* `ok: false` — any other error (e.g. a real keyring failure) is a
|
|
80
|
+
* genuine problem and must surface as a failure, not get misreported as
|
|
81
|
+
* a missing token.
|
|
82
|
+
*/
|
|
83
|
+
whoami(): Promise<{
|
|
84
|
+
ok: boolean;
|
|
85
|
+
}>;
|
|
55
86
|
dnsRecord(): DnsRecordRequest | null;
|
|
56
87
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
declare function wiki(opts: FernPluginOptions): Wiki;
|
|
64
|
-
declare function createPlugin(options?: FernPluginOptions): {
|
|
88
|
+
/** Options for the Fern plugin; the same as the `wiki` capability's. */
|
|
89
|
+
export type FernPluginOptions = FernWikiOptions;
|
|
90
|
+
/** Builds the `wiki` capability from the plugin options. */
|
|
91
|
+
export declare function wiki(opts: FernPluginOptions): Wiki;
|
|
92
|
+
/** Creates the Fern plugin: its `connection` probe and the `wiki` capability. */
|
|
93
|
+
export declare function createPlugin(options?: FernPluginOptions): {
|
|
65
94
|
name: string;
|
|
95
|
+
probes: {
|
|
96
|
+
connection: import("@theholocron/cli").Probe;
|
|
97
|
+
};
|
|
66
98
|
capabilities: {
|
|
67
99
|
wiki: () => Wiki;
|
|
68
100
|
};
|
|
69
101
|
};
|
|
70
|
-
|
|
71
|
-
export { AuthError, FERN_VERSION, FernPluginOptions, FernWiki, type FernWikiOptions, type ResolveTokenInput, createPlugin, resolveToken, wiki };
|
|
102
|
+
export { AuthError, type FernWikiOptions, type ResolveTokenInput };
|
package/dist/index.mjs
CHANGED
|
@@ -1,11 +1,26 @@
|
|
|
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
|
+
/** Resolves the Fern token from `--token`, `HOLOCRON_FERN_TOKEN`, `FERN_TOKEN` or the keyring entry for `fern`, and throws `AuthError` when none is set. */
|
|
7
|
+
const resolveToken = createResolveToken({
|
|
8
|
+
envName: "HOLOCRON_FERN_TOKEN",
|
|
9
|
+
vendorEnvName: "FERN_TOKEN",
|
|
10
|
+
keyringService: "fern",
|
|
11
|
+
errorMessage: "no Fern token found. Set HOLOCRON_FERN_TOKEN / FERN_TOKEN, or run: holocron auth set fern <token>"
|
|
12
|
+
});
|
|
13
|
+
/** Every token this plugin takes, for `holocron doctor tokens`. */
|
|
14
|
+
const tokens = [resolveToken.token];
|
|
15
|
+
// src/capabilities/wiki.ts
|
|
16
|
+
/** The Fern CLI version written into `fern/fern.config.json`. */
|
|
5
17
|
const FERN_VERSION = "5.114.1";
|
|
18
|
+
/** `wiki` capability for Fern: writes the Fern config and docs scaffold for a repo. */
|
|
6
19
|
var FernWiki = class {
|
|
7
20
|
opts;
|
|
21
|
+
/** Capability key; always `"wiki"`. */
|
|
8
22
|
key = "wiki";
|
|
23
|
+
/** Provider name; always `"fern"`. */
|
|
9
24
|
providerName = "fern";
|
|
10
25
|
constructor(opts) {
|
|
11
26
|
this.opts = opts;
|
|
@@ -33,6 +48,38 @@ var FernWiki = class {
|
|
|
33
48
|
headers: { "X-Fern-Host": this.opts.domain.split("/")[0] }
|
|
34
49
|
};
|
|
35
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Confirms `HOLOCRON_FERN_TOKEN`/`FERN_TOKEN` resolves, or a Fern token
|
|
53
|
+
* is stored in the keyring — not a live check. Fern exposes no
|
|
54
|
+
* lightweight endpoint to verify a token actually works (the only
|
|
55
|
+
* token-consuming operation is a full `fern generate`, see
|
|
56
|
+
* holocron#1079); this only confirms one is configured, the same way
|
|
57
|
+
* CI's `fern generate --docs` step would find it.
|
|
58
|
+
*
|
|
59
|
+
* Deliberately ignores `cliToken` (`--token`): CI's step only ever sees
|
|
60
|
+
* the env var from a GitHub Actions secret, never a CLI flag — and a
|
|
61
|
+
* bare `--token <value>` meant for some OTHER provider is forwarded to
|
|
62
|
+
* every loaded plugin as a fallback (see AGENTS.md), so honoring it
|
|
63
|
+
* here would report "configured" even when no Fern-specific credential
|
|
64
|
+
* exists anywhere CI would actually look.
|
|
65
|
+
*
|
|
66
|
+
* Only `AuthError` (the specific "no token found" signal) is treated as
|
|
67
|
+
* `ok: false` — any other error (e.g. a real keyring failure) is a
|
|
68
|
+
* genuine problem and must surface as a failure, not get misreported as
|
|
69
|
+
* a missing token.
|
|
70
|
+
*/
|
|
71
|
+
async whoami() {
|
|
72
|
+
try {
|
|
73
|
+
resolveToken({
|
|
74
|
+
...this.opts,
|
|
75
|
+
cliToken: void 0
|
|
76
|
+
});
|
|
77
|
+
return { ok: true };
|
|
78
|
+
} catch (err) {
|
|
79
|
+
if (err instanceof AuthError) return { ok: false };
|
|
80
|
+
throw err;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
36
83
|
dnsRecord() {
|
|
37
84
|
const { org, domain, fernOrg } = this.opts;
|
|
38
85
|
if (!domain) return null;
|
|
@@ -52,10 +99,10 @@ async function writeFernConfig({ repoRoot, fernOrg }) {
|
|
|
52
99
|
const fernDir = join(repoRoot, "fern");
|
|
53
100
|
await mkdir(fernDir, { recursive: true });
|
|
54
101
|
const org = fernOrg ?? "holocron";
|
|
55
|
-
const content =
|
|
102
|
+
const content = stringifyJson({
|
|
56
103
|
organization: org,
|
|
57
104
|
version: FERN_VERSION
|
|
58
|
-
}
|
|
105
|
+
});
|
|
59
106
|
await writeFile(join(fernDir, "fern.config.json"), content, "utf8");
|
|
60
107
|
return `fern.config.json: org=${org}, version=${FERN_VERSION}`;
|
|
61
108
|
}
|
|
@@ -130,24 +177,24 @@ function updateInstancesBlock(content, instanceUrl, customDomain, multiSource, r
|
|
|
130
177
|
if (match[0] === newBlock) return content;
|
|
131
178
|
return content.replace(blockRe, newBlock);
|
|
132
179
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
const resolveToken = createResolveToken({
|
|
136
|
-
envName: "HOLOCRON_FERN_TOKEN",
|
|
137
|
-
vendorEnvName: "FERN_TOKEN",
|
|
138
|
-
keyringService: "fern",
|
|
139
|
-
errorMessage: "no Fern token found. Set HOLOCRON_FERN_TOKEN / FERN_TOKEN, or run: holocron auth set fern <token>"
|
|
140
|
-
});
|
|
141
|
-
//#endregion
|
|
142
|
-
//#region src/index.ts
|
|
180
|
+
// src/index.ts
|
|
181
|
+
/** Builds the `wiki` capability from the plugin options. */
|
|
143
182
|
function wiki(opts) {
|
|
144
183
|
return new FernWiki(opts);
|
|
145
184
|
}
|
|
185
|
+
/** Creates the Fern plugin: its `connection` probe and the `wiki` capability. */
|
|
146
186
|
function createPlugin(options = {}) {
|
|
147
187
|
return {
|
|
148
188
|
name: "@theholocron/holocron-plugin-fern",
|
|
189
|
+
probes: { connection: connectionProbe({
|
|
190
|
+
provider: "Fern",
|
|
191
|
+
token: () => resolveToken(options),
|
|
192
|
+
verify: async () => ({
|
|
193
|
+
ok: true,
|
|
194
|
+
subject: "a token is set (Fern cannot check it from here)"
|
|
195
|
+
})
|
|
196
|
+
}) },
|
|
149
197
|
capabilities: { wiki: () => wiki(options) }
|
|
150
198
|
};
|
|
151
199
|
}
|
|
152
|
-
|
|
153
|
-
export { AuthError, FERN_VERSION, FernWiki, createPlugin, resolveToken, wiki };
|
|
200
|
+
export { AuthError, FERN_VERSION, FernWiki, createPlugin, resolveToken, tokens, 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.420",
|
|
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://
|
|
11
|
+
"homepage": "https://docs.theholocron.dev/holocron/plugins/fern/",
|
|
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.17.0-alpha.4"
|
|
34
|
+
},
|
|
32
35
|
"devDependencies": {
|
|
33
|
-
"@theholocron/eslint-config": "^8.0.0",
|
|
34
|
-
"@theholocron/tsconfig": "^8.0.0",
|
|
35
|
-
"@theholocron/tsdown-config": "^8.0.0",
|
|
36
|
-
"@theholocron/vitest-config": "^8.0.0",
|
|
37
36
|
"@types/node": "^26",
|
|
38
|
-
"@vitest/coverage-v8": "^
|
|
39
|
-
"@vitest/eslint-plugin": "^1.6.
|
|
40
|
-
"eslint": "^10.
|
|
41
|
-
"eslint-plugin-n": "^18.
|
|
42
|
-
"globals": "^17.
|
|
43
|
-
"tsdown": "^0.
|
|
44
|
-
"tsx": "4.23.
|
|
37
|
+
"@vitest/coverage-v8": "^5.1.0",
|
|
38
|
+
"@vitest/eslint-plugin": "^1.6.28",
|
|
39
|
+
"eslint": "^10.14.0",
|
|
40
|
+
"eslint-plugin-n": "^18.5.0",
|
|
41
|
+
"globals": "^17.14.0",
|
|
42
|
+
"tsdown": "^0.23.5",
|
|
43
|
+
"tsx": "4.23.15",
|
|
45
44
|
"typescript": "^5.9.3",
|
|
46
|
-
"vitest": "^
|
|
47
|
-
"@theholocron/cli": "5.0.0-alpha.
|
|
45
|
+
"vitest": "^5.1.0",
|
|
46
|
+
"@theholocron/cli": "5.0.0-alpha.420",
|
|
47
|
+
"@theholocron/tsconfig": "^8.9.0-alpha.16",
|
|
48
|
+
"@theholocron/tsdown-config": "^8.9.0-alpha.16",
|
|
49
|
+
"@theholocron/vitest-config": "^8.9.0-alpha.16",
|
|
50
|
+
"@theholocron/eslint-config": "^8.9.0-alpha.16"
|
|
48
51
|
},
|
|
49
52
|
"peerDependencies": {
|
|
50
|
-
"@theholocron/cli": "5.0.0-alpha.
|
|
53
|
+
"@theholocron/cli": "5.0.0-alpha.420"
|
|
51
54
|
},
|
|
52
55
|
"engines": {
|
|
53
56
|
"node": ">=22"
|
|
@@ -56,10 +59,10 @@
|
|
|
56
59
|
"access": "public"
|
|
57
60
|
},
|
|
58
61
|
"scripts": {
|
|
59
|
-
"
|
|
60
|
-
"
|
|
62
|
+
"build": "tsdown",
|
|
63
|
+
"lint:code": "eslint .",
|
|
64
|
+
"test:unit": "vitest run --coverage",
|
|
61
65
|
"test:watch": "vitest",
|
|
62
|
-
"
|
|
63
|
-
"verification.unitTests": "holocron run verification.unitTests --"
|
|
66
|
+
"typecheck": "tsc --noEmit"
|
|
64
67
|
}
|
|
65
68
|
}
|