Skip to content

Commit 64771fe

Browse files
authored
Merge pull request #128 from PMDevSolutions/44-ship-dts-types-and-generate-an-api-reference-with-typedoc
Ship bundled .d.ts types + hosted TypeDoc API reference
2 parents 2531899 + df0a03e commit 64771fe

22 files changed

Lines changed: 1879 additions & 83 deletions

.github/workflows/ci.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,18 @@ jobs:
4242
- name: Type check
4343
run: pnpm typecheck
4444

45+
- name: API docs coverage (TSDoc)
46+
run: pnpm docs:api:check
47+
4548
- name: Test (Vitest)
4649
run: pnpm test
4750

4851
- name: Build
4952
run: pnpm build
5053

54+
- name: Validate package exports (attw + publint)
55+
run: pnpm check:exports
56+
5157
worker:
5258
name: Validate Worker
5359
runs-on: ubuntu-latest

.github/workflows/docs.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ on:
55
branches: [main]
66
paths:
77
- "docs/**"
8+
- "widget/**"
89
- ".github/workflows/docs.yml"
910
pull_request:
1011
branches: [main]
1112
paths:
1213
- "docs/**"
14+
- "widget/**"
1315
- ".github/workflows/docs.yml"
1416
workflow_dispatch:
1517

@@ -40,6 +42,17 @@ jobs:
4042
- name: Install dependencies
4143
run: pnpm install --frozen-lockfile
4244

45+
# The hosted API reference is generated from the widget's TSDoc and copied
46+
# into docs/public/api by the docs build (scripts/copy-api.mjs). Generate
47+
# it here first so it ships with this deploy.
48+
- name: Install widget dependencies
49+
working-directory: widget
50+
run: pnpm install --frozen-lockfile
51+
52+
- name: Generate API reference (TypeDoc)
53+
working-directory: widget
54+
run: pnpm docs:api
55+
4356
- name: Build (includes Pagefind index)
4457
run: pnpm build
4558

docs/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
dist/
33
# generated types
44
.astro/
5+
# generated TypeDoc API reference (copied from ../widget/dist/api by scripts/copy-api.mjs)
6+
public/api/
57

68
# dependencies
79
node_modules/

docs/astro.config.mjs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,15 @@ export default defineConfig({
6969
},
7070
{
7171
label: "API Reference",
72-
items: [{ autogenerate: { directory: "api" } }],
72+
items: [
73+
{ autogenerate: { directory: "api" } },
74+
{
75+
label: "Generated Reference (TypeDoc)",
76+
link: "/api/",
77+
attrs: { target: "_blank", rel: "noopener noreferrer" },
78+
badge: { text: "typedoc", variant: "tip" },
79+
},
80+
],
7381
},
7482
{
7583
label: "Migration Guides",

docs/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"scripts": {
77
"dev": "astro dev",
88
"start": "astro dev",
9-
"build": "astro build",
9+
"build": "node scripts/copy-api.mjs && astro build",
1010
"preview": "astro preview",
1111
"astro": "astro"
1212
},
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# Design: TypeScript Types + Hosted API Reference
2+
3+
Date: 2026-06-16
4+
Issue: #44 — ship `.d.ts` types and generate an API reference with TypeDoc
5+
Branch: `44-ship-dts-types-and-generate-an-api-reference-with-typedoc`
6+
7+
## Goal
8+
9+
Guarantee that consumers of the `claudius-chat-widget` npm package get full
10+
TypeScript IntelliSense, and auto-generate a hosted API reference from
11+
TSDoc comments that is published under the existing docs domain.
12+
13+
## Background (current state)
14+
15+
- `widget` publishes as `claudius-chat-widget`. It already declares
16+
`types: "./dist/index.d.ts"` and ships declarations, but the build runs
17+
`tsc --emitDeclarationOnly`, which emits a **37-file tree** (including
18+
dev-only `main.d.ts`, `embed.d.ts`, and `test-utils/`) rather than one
19+
bundled entry.
20+
- The public surface is the barrel `widget/src/index.ts`: `ChatWidget` +
21+
`ChatWidgetProps`, `WidgetPosition`, translations API, locales API,
22+
`Trigger`/`TriggerAction`/`UrlPattern`, themes + theme token types,
23+
`ChatApiClient` + options, error classes, and the `Source`/`ChatMessage`/
24+
`Chat*` request/response types. Only the `theme` prop currently has a
25+
TSDoc comment.
26+
- Docs are an Astro + Starlight site in `docs/`, deployed to the
27+
`claudius-docs` Cloudflare Pages project by `.github/workflows/docs.yml`.
28+
The sidebar already has an **API Reference** group, and there is an
29+
existing precedent for linking a sibling Pages site (Storybook, with
30+
`target: _blank` and a badge).
31+
- `ci.yml` runs the widget job: lint, format:check, typecheck, test, build.
32+
There is no TypeDoc and no doc-coverage gate yet.
33+
34+
## Decisions (validated with user)
35+
36+
1. **Type bundling:** single rolled-up `dist/index.d.ts` via
37+
`vite-plugin-dts` (`rollupTypes: true`), replacing `tsc --emitDeclarationOnly`.
38+
2. **API-reference hosting:** TypeDoc emits **HTML** to `widget/dist/api`;
39+
that HTML is copied into the Astro site and deployed with the existing
40+
`claudius-docs` Pages project at **`/api/`**. One domain, one deploy,
41+
one nav link, no new Pages project or secrets.
42+
3. **Export-correctness guarantee (beyond AC):** add `@arethetypeswrong/cli`
43+
+ `publint` to prove ESM/CJS consumers resolve types correctly.
44+
4. **Visual verification (beyond AC):** screenshot the rendered `/api/`
45+
reference and the docs sidebar link as part of verification.
46+
47+
## Components
48+
49+
### 1. Single bundled `index.d.ts`
50+
- Add `vite-plugin-dts` to `widget`; configure in `vite.config.ts` (lib build
51+
only) with `rollupTypes: true`, `tsconfigPath: './tsconfig.json'`,
52+
`include: ['src']`, excluding tests and stories.
53+
- Remove `tsc --emitDeclarationOnly` from `build` / `build:lib`. Keep
54+
`typecheck: tsc --noEmit`. Simplify `tsconfig.json` emit options that the
55+
plugin now owns.
56+
- Outcome: one `dist/index.d.ts` containing only the public surface.
57+
58+
### 2. TSDoc on every public export
59+
- Document each symbol reachable from `src/index.ts`, and each member of
60+
exported interfaces (props, theme inputs, client options, message/source
61+
types). Use `@param`, `@returns`, `@defaultValue`, `@example`, `@see`.
62+
- Mark genuinely-internal helpers `@internal` so they are excluded from both
63+
the generated docs and the coverage gate.
64+
65+
### 3. TypeDoc generation — `pnpm docs:api`
66+
- Add `typedoc` to `widget`; `typedoc.json` with `entryPoints: ["src/index.ts"]`,
67+
`out: "dist/api"` (HTML), `excludeInternal/Private/Externals: true`, exclude
68+
tests/stories, `validation.notDocumented: true`, `treatWarningsAsErrors: true`.
69+
- Scripts: `docs:api` (full HTML) and `docs:api:check` (`typedoc --emit none`,
70+
fast validation-only).
71+
72+
### 4. Host under the docs domain at `/api/`
73+
- `docs/scripts/copy-api.mjs` (run as docs `prebuild`): copy `../widget/dist/api`
74+
into `docs/public/api/` when present; warn and skip when absent so docs-only
75+
local builds still succeed.
76+
- `docs.yml`: add steps to install the widget and run `pnpm docs:api` before the
77+
docs build; add `widget/**` to the path triggers so the reference rebuilds
78+
when the public API changes.
79+
- Add a sidebar item to the existing **API Reference** group:
80+
`{ label: "Generated Reference (TypeDoc)", link: "/api/", attrs: { target: "_blank", rel: "noopener noreferrer" }, badge: { text: "typedoc" } }`.
81+
- `.gitignore`: add `docs/public/api/` (generated, not committed).
82+
83+
### 5. CI doc-coverage gate
84+
- `treatWarningsAsErrors` + `validation.notDocumented` make `docs:api:check`
85+
exit non-zero on any undocumented public symbol or broken `@link`.
86+
- `ci.yml` widget job gains a **TSDoc coverage** step (`pnpm docs:api:check`)
87+
and an export-correctness step (`attw` + `publint`). The existing Build step
88+
now also exercises `vite-plugin-dts`.
89+
90+
### 6. Verification (including visual)
91+
- After `pnpm build`: assert a single `dist/index.d.ts` with no leftover
92+
`dist/components/*.d.ts`; run `attw` + `publint` on the packed tarball.
93+
- Build docs, then screenshot the rendered `/api/` reference and the docs
94+
sidebar link to confirm rendering and wiring.
95+
96+
## Acceptance-criteria mapping
97+
98+
| Acceptance criterion | Component |
99+
|---|---|
100+
| Vite build emits a single `index.d.ts` bundle | 1 |
101+
| All public exports have TSDoc comments | 2, 5 (enforced) |
102+
| `pnpm docs:api` runs TypeDoc -> HTML in `dist/api` | 3 |
103+
| Generated reference published to Cloudflare Pages + linked from docs | 4 |
104+
| CI fails if any public export lacks a TSDoc summary | 5 |
105+
106+
## Risks / notes
107+
108+
- `rollupTypes` uses `@microsoft/api-extractor` under the hood; complex type
109+
constructs can produce warnings. The public types here are simple (string
110+
unions + interfaces), so risk is low. Verify the single-file output and
111+
consumer resolution with `attw`.
112+
- Hosting at bare `/api/` is collision-free with the existing `/api/rest` and
113+
`/api/widget` content routes (no shared file/route names). Confirmed.
114+
- Local docs `dev`/`build` without first generating the widget API will show
115+
no `/api/`; the tolerant copy script makes this a warning, not a failure.
116+
117+
## Out of scope
118+
119+
- Auto-generating Markdown prop tables into the hand-written docs (that was the
120+
"Markdown in Starlight" option, not chosen). The generated reference is the
121+
canonical source; hand-written pages may link to it.
122+
- Worker package API docs (the npm consumer surface is the widget).

0 commit comments

Comments
 (0)