Skip to content

Commit 30d86d1

Browse files
Benoit Traversclaude
authored andcommitted
docs: restructure to Diátaxis and add versioned deploys
Replace the flat /guide/ layout with the four Diátaxis modes (tutorial, how-to, reference, explanation) and close the coverage gaps: signals, queries, updates, search attributes, schedules, cancellation scopes, continue-as-new, and time-skipping tests were all implemented but documented nowhere. Correctness fixes found while writing against the source: - The activity implementation map is nested by workflow; the README showed a workflow-scoped activity at the root level, which does not type-check. - An activity that declares an `errors` map returns AsyncResult to the workflow, not a plain value (activities-proxy.ts) — the old docs showed try/catch. - `match({ err })` is `errCases`; `signalWithStart` takes `signalName`; `getHandle` returns an AsyncResult. - unthrown peer range was documented as ^4.1.0, actual ^5.0.0-beta.6. - Zod 4: `z.record` needs two args, `.email()` is deprecated. - `tag(...)` was used in ~20 examples with no import shown. - The Nexus page claimed "planned for v0.5.0" at 8.0.0-beta.1. Versioned deploys are ported from btravstack/unthrown: while a prerelease is in progress, the latest stable tag builds at the root and main builds under /beta/, with a version dropdown linking the two. Two things could not be copied verbatim: - unthrown drops prereleases with `grep -v -- '-'` over whole tags. Every tag here contains a hyphen inside "@temporal-contract/", so that would discard all of them; the version is now filtered after the package prefix is stripped. - This repo's nav is nested one level deeper, so the injection script's anchor needs eight spaces of indentation, not six. Verified end to end locally: main builds at /beta/ with correct asset paths and canonicals, and a real worktree at @temporal-contract/contract@7.0.0 builds at the root with the dropdown injected. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent c6ef9b5 commit 30d86d1

63 files changed

Lines changed: 7785 additions & 6952 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.agents/rules/dependencies.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ Anything that appears in a published package's **public type signatures** must b
3939

4040
| Package | Peer dependencies |
4141
| -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
42-
| client | `@temporalio/client ^1`, `@temporalio/common ^1`, `unthrown ^4` |
43-
| worker | `@temporalio/common ^1`, `@temporalio/worker ^1`, `@temporalio/workflow ^1`, `unthrown ^4` |
44-
| contract | `unthrown ^4` (optional — only needed when using `result-async`) |
42+
| client | `@temporalio/client ^1`, `@temporalio/common ^1`, `unthrown ^5` |
43+
| worker | `@temporalio/common ^1`, `@temporalio/worker ^1`, `@temporalio/workflow ^1`, `unthrown ^5` |
44+
| contract | `unthrown ^5` (optional — only needed when using `result-async`) |
4545
| testing | `vitest ^4` (the `globalSetup` hook integrates with vitest's test runner), `@temporalio/client ^1`, `@temporalio/worker ^1` (both exposed by the `it` fixture's public types) |
4646

4747
When you add a peer dep, also add it to `devDependencies` (with the same `"catalog:"` reference) so the local workspace build still resolves it. The workspace has `autoInstallPeers: false`, so peers must be present somewhere on the install side.
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
// Inject the docs version dropdown into a LEGACY VitePress site — one built
2+
// from a stable tag that predates the native `DOCS_VERSIONS` support in
3+
// docs/.vitepress/config.ts. The deploy workflow builds the stable site from
4+
// that tag's own tree (so its docs stay faithful to the released version:
5+
// pages, sidebar, API reference), and this script patches ONLY the version UI:
6+
//
7+
// 1. the nav — the dropdown is inserted right AFTER the `btravstack` hub item,
8+
// the same position the native config appends it, so the picker sits in the
9+
// same place on every version of the site;
10+
// 2. the theme — the same-page/same-tab switch enhancement (the runtime click
11+
// interceptor `docs/.vitepress/theme/version-switch.ts` ships natively) is
12+
// appended to the tag's theme entry, so switching versions from a legacy
13+
// site also preserves the visitor's place.
14+
//
15+
// Usage: tsx inject-docs-version-nav.ts <path-to-docs/.vitepress>
16+
// with DOCS_VERSIONS set to the same JSON the native config consumes:
17+
// { "current": "v7.0.0", "items": [{ "text", "link", "target" }, ...] }
18+
//
19+
// No-op (exit 0) when the config already supports DOCS_VERSIONS natively —
20+
// once the latest stable tag is >= the version that shipped native support,
21+
// this script stops doing anything and can be deleted.
22+
23+
import { readFileSync, writeFileSync } from "node:fs";
24+
import { join } from "node:path";
25+
26+
type VersionMenu = {
27+
current: string;
28+
items: { text: string; link: string; target?: string }[];
29+
};
30+
31+
const [, , vitepressDir] = process.argv;
32+
const raw = process.env["DOCS_VERSIONS"];
33+
if (!vitepressDir || !raw) {
34+
console.error("usage: DOCS_VERSIONS='{...}' tsx inject-docs-version-nav.ts <docs/.vitepress>");
35+
process.exit(1);
36+
}
37+
38+
const configPath = join(vitepressDir, "config.ts");
39+
const source = readFileSync(configPath, "utf8");
40+
41+
if (source.includes("DOCS_VERSIONS")) {
42+
console.log("config supports DOCS_VERSIONS natively — no injection needed");
43+
process.exit(0);
44+
}
45+
46+
// --- 1. Nav dropdown, positioned as the native config positions it. ---
47+
// NOTE: this repo's nav array is nested one level deeper than unthrown's
48+
// (inside `withMermaid(defineConfig({...}))`), so the anchor carries EIGHT
49+
// spaces of indentation, not six. Verified against
50+
// `@temporal-contract/contract@7.0.0:docs/.vitepress/config.ts`.
51+
const versions = JSON.parse(raw) as VersionMenu;
52+
const anchor = ` { text: "btravstack", link: "https://btravstack.github.io/" },\n`;
53+
if (!source.includes(anchor)) {
54+
console.error(
55+
`no btravstack nav anchor found in ${configPath} — layout changed, refusing to guess`,
56+
);
57+
process.exit(1);
58+
}
59+
const entry = ` // Version dropdown — injected at deploy time (this tag predates native
60+
// DOCS_VERSIONS support in the config; see inject-docs-version-nav.ts).
61+
${JSON.stringify({ text: versions.current, items: versions.items })},\n`;
62+
writeFileSync(configPath, source.replace(anchor, anchor + entry));
63+
console.log(`injected version dropdown into ${configPath}`);
64+
65+
// --- 2. Same-page/same-tab switch enhancement, appended to the theme entry. ---
66+
// Inlined (not imported from the main tree) so the patched tag tree stays
67+
// self-contained; keep in sync with docs/.vitepress/theme/version-switch.ts.
68+
const themePath = join(vitepressDir, "theme", "index.ts");
69+
const theme = readFileSync(themePath, "utf8");
70+
const enhancement = `
71+
// Same-page/same-tab version switching — appended at deploy time (this tag
72+
// predates the native docs/.vitepress/theme/version-switch.ts).
73+
if (typeof window !== "undefined") {
74+
document.addEventListener(
75+
"click",
76+
(event) => {
77+
if (
78+
event.defaultPrevented ||
79+
event.button !== 0 ||
80+
event.metaKey ||
81+
event.ctrlKey ||
82+
event.shiftKey ||
83+
event.altKey
84+
) {
85+
return; // modified or non-left click — keep native new-tab/window behavior
86+
}
87+
const target = event.target instanceof Element ? event.target : null;
88+
const anchor = target?.closest("a[href]");
89+
const match = anchor
90+
?.getAttribute("href")
91+
?.match(/^https:\\/\\/btravstack\\.github\\.io(\\/temporal-contract\\/(?:beta\\/)?)$/);
92+
if (!anchor || !match?.[1]) {
93+
return;
94+
}
95+
const targetBase = match[1];
96+
const ownBase = import.meta.env.BASE_URL;
97+
if (targetBase === ownBase) {
98+
return;
99+
}
100+
const path = window.location.pathname.startsWith(ownBase)
101+
? window.location.pathname.slice(ownBase.length)
102+
: "";
103+
event.preventDefault();
104+
window.location.href =
105+
"https://btravstack.github.io" +
106+
targetBase +
107+
path +
108+
window.location.search +
109+
window.location.hash;
110+
},
111+
true,
112+
);
113+
}
114+
`;
115+
writeFileSync(themePath, theme + enhancement);
116+
console.log(`appended version-switch enhancement to ${themePath}`);

.github/workflows/deploy-docs.yml

Lines changed: 93 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ name: Deploy Documentation
33
# Publish docs when a version is released (changesets creates a GitHub Release on publish), so the
44
# site documents the latest *released* library — and also when the docs themselves change on main
55
# (theme bumps, content edits), since those need no library release to be worth shipping.
6+
#
7+
# Versioned deploys: while a prerelease is in progress (`.changeset/pre.json` on main), the site is
8+
# built TWICE — the latest stable tag's docs at the root (the default a visitor lands on) and
9+
# main's docs under /beta/ — with a version dropdown linking the two. When no prerelease is in
10+
# progress, main IS the stable line and deploys alone to the root, exactly as before. Pages deploys
11+
# replace the whole site, so every run assembles all versions into one artifact.
612
on:
713
release:
814
types: [published]
@@ -12,6 +18,7 @@ on:
1218
- "docs/**"
1319
- "pnpm-workspace.yaml"
1420
- ".github/workflows/deploy-docs.yml"
21+
- ".github/scripts/inject-docs-version-nav.ts"
1522
workflow_dispatch:
1623

1724
permissions:
@@ -31,26 +38,109 @@ env:
3138
jobs:
3239
build:
3340
runs-on: ubuntu-latest
34-
timeout-minutes: 15
41+
timeout-minutes: 20
3542
steps:
3643
- name: Checkout
3744
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
3845
with:
46+
# Full history + tags: the stable site is built from the latest stable tag.
3947
fetch-depth: 0
4048

4149
- name: Setup
4250
uses: ./.github/actions/setup
4351

52+
- name: Determine versions
53+
id: meta
54+
run: |
55+
# NOTE: every tag here contains a hyphen inside "@temporal-contract/", so a bare
56+
# `grep -v -- '-'` over whole tags would discard ALL of them. Strip the package
57+
# prefix first, then filter prereleases on the version alone.
58+
stable_version=$(git tag -l '@temporal-contract/contract@*' \
59+
| sed 's|^@temporal-contract/contract@||' \
60+
| grep -v -- '-' \
61+
| sort -V \
62+
| tail -1)
63+
if [ -z "$stable_version" ]; then
64+
echo "::error::no stable @temporal-contract/contract@* tag found"
65+
exit 1
66+
fi
67+
stable_tag="@temporal-contract/contract@${stable_version}"
68+
echo "stable_tag=$stable_tag" >> "$GITHUB_OUTPUT"
69+
echo "stable_version=$stable_version" >> "$GITHUB_OUTPUT"
70+
if [ -f .changeset/pre.json ]; then
71+
beta_version=$(node -p "require('./packages/contract/package.json').version")
72+
echo "prerelease=true" >> "$GITHUB_OUTPUT"
73+
echo "beta_version=$beta_version" >> "$GITHUB_OUTPUT"
74+
STABLE_VERSION="$stable_version" BETA_VERSION="$beta_version" node -e "
75+
// target: '_self' — cross-version links are same-site; without it
76+
// VitePress treats the absolute URLs as external and opens a new tab
77+
// (the client-side enhancement also preserves the current page).
78+
const stable = {
79+
text: 'v' + process.env.STABLE_VERSION + ' (stable)',
80+
link: 'https://btravstack.github.io/temporal-contract/',
81+
target: '_self',
82+
};
83+
const beta = {
84+
text: 'v' + process.env.BETA_VERSION + ' (beta)',
85+
link: 'https://btravstack.github.io/temporal-contract/beta/',
86+
target: '_self',
87+
};
88+
const out = [
89+
'versions_stable=' + JSON.stringify({ current: 'v' + process.env.STABLE_VERSION, items: [stable, beta] }),
90+
'versions_beta=' + JSON.stringify({ current: 'v' + process.env.BETA_VERSION, items: [stable, beta] }),
91+
'',
92+
].join('\n');
93+
require('fs').appendFileSync(process.env.GITHUB_OUTPUT, out);
94+
"
95+
else
96+
echo "prerelease=false" >> "$GITHUB_OUTPUT"
97+
fi
98+
4499
- name: Setup Pages
45100
uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6
46101

47-
- name: Build documentation
102+
# --- Single-version path: main is the stable line; deploy it alone to the root. ---
103+
- name: Build documentation (stable line)
104+
if: steps.meta.outputs.prerelease == 'false'
105+
run: |
106+
pnpm --filter ./docs exec turbo build
107+
mkdir -p site
108+
cp -r docs/.vitepress/dist/* site/
109+
110+
# --- Versioned path: stable tag at the root, main under /beta/. ---
111+
- name: Build beta documentation (main)
112+
if: steps.meta.outputs.prerelease == 'true'
113+
env:
114+
DOCS_BASE: /temporal-contract/beta/
115+
DOCS_VERSIONS: ${{ steps.meta.outputs.versions_beta }}
48116
run: pnpm --filter ./docs exec turbo build
49117

118+
- name: Build stable documentation (latest stable tag)
119+
if: steps.meta.outputs.prerelease == 'true'
120+
env:
121+
DOCS_VERSIONS: ${{ steps.meta.outputs.versions_stable }}
122+
run: |
123+
git worktree add /tmp/stable-docs "${{ steps.meta.outputs.stable_tag }}"
124+
# A tag that predates native DOCS_VERSIONS support in the config gets the
125+
# version dropdown injected; a no-op once the stable tag carries it natively.
126+
# (Runs with the main checkout's docs toolchain — tsx lives there.)
127+
pnpm --filter ./docs exec tsx "$GITHUB_WORKSPACE/.github/scripts/inject-docs-version-nav.ts" \
128+
/tmp/stable-docs/docs/.vitepress
129+
cd /tmp/stable-docs
130+
pnpm install --frozen-lockfile
131+
pnpm --filter ./docs exec turbo build
132+
133+
- name: Assemble versioned site
134+
if: steps.meta.outputs.prerelease == 'true'
135+
run: |
136+
mkdir -p site/beta
137+
cp -r /tmp/stable-docs/docs/.vitepress/dist/* site/
138+
cp -r docs/.vitepress/dist/* site/beta/
139+
50140
- name: Upload artifact
51141
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5
52142
with:
53-
path: docs/.vitepress/dist
143+
path: site
54144

55145
deploy:
56146
environment:

0 commit comments

Comments
 (0)