Skip to content

Commit d1a7c2e

Browse files
committed
yay docs viewer :eyeroll:
1 parent 9b4950e commit d1a7c2e

9 files changed

+306
-1
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,6 @@ benchmarks/results/*.json
5656
!.vscode/
5757
.idea/
5858
*.iml
59+
60+
# Ignore the cloned repos for docs viewer
61+
docs-viewer/projects

docs-viewer/README.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#
2+
3+
Running this script will
4+
5+
- install the appropriate packages as siblings to

docs-viewer/package.json

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"name": "@warp-drive/internal-docs-viewer",
3+
"version": "5.4.0-alpha.142",
4+
"description": "API Docs Viewer for the WarpDrive Project Monorepo | Unpublished",
5+
"private": true,
6+
"type": "module",
7+
"files": [
8+
"src"
9+
],
10+
"bin": {
11+
"preview-api-docs": "./src/preview-docs.ts"
12+
},
13+
"dependencies": {
14+
"@types/bun": "^1.2.4",
15+
"typescript": "^5.8.2",
16+
"chalk": "5.4.1",
17+
"debug": "4.4.0",
18+
"@pnpm/find-workspace-dir": "1000.1.0",
19+
"@types/debug": "4.1.12"
20+
},
21+
"engines": {
22+
"node": ">= 18.20.7"
23+
},
24+
"volta": {
25+
"extends": "../package.json"
26+
}
27+
}

docs-viewer/projects/.gitkeep

Whitespace-only changes.

docs-viewer/src/preview-docs.ts

+201
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
#! /usr/bin/env bun
2+
/**
3+
* Sets up the docs viewer app
4+
*/
5+
import chalk from 'chalk';
6+
import path from 'path';
7+
import fs from 'fs';
8+
import { findWorkspaceDir } from '@pnpm/find-workspace-dir';
9+
10+
const EMBER_API_DOCS_REPO = `git@github.com:ember-learn/ember-api-docs.git`;
11+
const EMBER_JSONAPI_DOCS_REPO = `git@github.com:ember-learn/ember-jsonapi-docs.git`;
12+
const EMBER_API_DOCS_DATA_REPO = `git@github.com:ember-learn/ember-api-docs-data.git`;
13+
14+
const workspaceRoot = (await findWorkspaceDir(process.cwd())) as string;
15+
16+
if (!workspaceRoot) {
17+
throw new Error('Could not find workspace root');
18+
}
19+
20+
const docsViewerRoot = path.join(workspaceRoot, 'docs-viewer');
21+
22+
function log(message: string) {
23+
console.log(chalk.grey(`[docs-viewer]\t${message}`));
24+
}
25+
26+
function repoDetails(gitUrl: string) {
27+
const repoPath = gitUrl.replace('.git', '').replace('git@github.com:', '');
28+
const [org, name] = repoPath.split('/');
29+
const installPathFromRoot = path.join('./projects', name);
30+
const location = path.join(docsViewerRoot, installPathFromRoot);
31+
32+
return {
33+
org,
34+
name,
35+
repoPath,
36+
gitUrl,
37+
installPathFromRoot,
38+
location,
39+
relativePath: path.relative(__dirname, path.join(docsViewerRoot, installPathFromRoot)),
40+
};
41+
}
42+
43+
async function getCurrentVersion(tool: string) {
44+
const proc = Bun.spawn([tool, '--version'], {
45+
env: process.env,
46+
stdio: ['inherit', 'pipe', 'inherit'],
47+
});
48+
await proc.exited;
49+
const version = await new Response(proc.stdout).text();
50+
return version.trim().replace('v', '');
51+
}
52+
53+
function determinePackageManager(dir: string) {
54+
if (fs.existsSync(path.join(dir, 'pnpm-lock.yaml'))) {
55+
return 'pnpm';
56+
}
57+
if (fs.existsSync(path.join(dir, 'package-lock.json'))) {
58+
return 'npm';
59+
}
60+
if (fs.existsSync(path.join(dir, 'yarn.lock'))) {
61+
return 'yarn';
62+
}
63+
64+
return 'npm';
65+
}
66+
67+
async function getOrUpdateRepo(gitUrl: string) {
68+
const details = repoDetails(gitUrl);
69+
70+
if (fs.existsSync(details.location)) {
71+
await getLatest(details);
72+
} else {
73+
await cloneRepo(details);
74+
}
75+
76+
// install dependencies
77+
const packageManager = determinePackageManager(details.location);
78+
79+
if (packageManager === 'pnpm') {
80+
// get the version to use from package.json
81+
const packageJson = require(path.join(details.location, 'package.json'));
82+
83+
let nodeVersion = await getCurrentVersion('node');
84+
const pnpmVersion = await getCurrentVersion('pnpm');
85+
86+
// ember-api-docs requires an older node due to node-sass
87+
if (packageJson.name === 'ember-api-docs') {
88+
nodeVersion = '20.19.0';
89+
}
90+
91+
if (
92+
!packageJson.volta ||
93+
packageJson.volta.node !== nodeVersion ||
94+
packageJson.volta.pnpm !== pnpmVersion ||
95+
packageJson.packageManager ||
96+
packageJson.engines?.node !== nodeVersion
97+
) {
98+
delete packageJson.packageManager;
99+
packageJson.volta = {
100+
node: nodeVersion,
101+
pnpm: pnpmVersion,
102+
};
103+
packageJson.engines = packageJson.engines || {};
104+
packageJson.engines.node = nodeVersion;
105+
106+
fs.writeFileSync(path.join(details.location, 'package.json'), JSON.stringify(packageJson, null, 2));
107+
const proc = Bun.spawn(['git', 'commit', '-am', '"ensure volta works as expected"'], {
108+
cwd: details.location,
109+
env: process.env,
110+
stdio: ['inherit', 'inherit', 'inherit'],
111+
});
112+
await proc.exited;
113+
}
114+
}
115+
116+
log(`Installing dependencies in ${chalk.green(details.installPathFromRoot)} using ${chalk.yellow(packageManager)}`);
117+
const proc = Bun.spawn(
118+
[packageManager, 'install', packageManager === 'pnpm' ? '--ignore-workspace' : ''].filter(Boolean),
119+
{
120+
cwd: details.location,
121+
env: process.env,
122+
stdio: ['inherit', 'inherit', 'inherit'],
123+
}
124+
);
125+
await proc.exited;
126+
}
127+
128+
async function getLatest(details: ReturnType<typeof repoDetails>) {
129+
log(`Updating ${chalk.green(details.repoPath)} in ${chalk.green(details.installPathFromRoot)} to latest`);
130+
const mainBranch = details.name === 'ember-jsonapi-docs' ? 'master' : 'main';
131+
const proc = Bun.spawn(['git', 'fetch', 'origin', mainBranch, '--depth=1'], {
132+
cwd: details.location,
133+
});
134+
await proc.exited;
135+
const proc2 = Bun.spawn(['git', 'reset', '--hard', `origin/${mainBranch}`], {
136+
cwd: details.location,
137+
});
138+
await proc2.exited;
139+
}
140+
141+
async function cloneRepo(details: ReturnType<typeof repoDetails>) {
142+
const relativePath = path.join('./projects', details.name);
143+
log(`Cloning ${chalk.green(details.repoPath)} to ${chalk.green(relativePath)}`);
144+
const proc = Bun.spawn(['git', 'clone', details.gitUrl, relativePath, '--depth=1'], {
145+
cwd: docsViewerRoot,
146+
});
147+
await proc.exited;
148+
}
149+
150+
async function main() {
151+
log('Setting up the docs viewer');
152+
log(`\tCurrent working directory: ${chalk.green(process.cwd())}`);
153+
154+
// clone repos
155+
await getOrUpdateRepo(EMBER_API_DOCS_DATA_REPO);
156+
await getOrUpdateRepo(EMBER_JSONAPI_DOCS_REPO);
157+
await getOrUpdateRepo(EMBER_API_DOCS_REPO);
158+
159+
// symlink our own project root into projects as 'ember-data'
160+
const emberDataLocation = path.join(docsViewerRoot, './projects/ember-data');
161+
if (!fs.existsSync(emberDataLocation)) {
162+
log(`Symlinking ${chalk.green('ember-data')} to ${chalk.green('./projects/ember-data')}`);
163+
fs.symlinkSync(workspaceRoot, emberDataLocation);
164+
}
165+
166+
// symlink `ember-api-docs-data` to `ember-api-docs`
167+
const projectRoot = path.join(docsViewerRoot, './projects');
168+
const emberApiDocsData = path.join(projectRoot, 'ember-api-docs-data');
169+
const symLinkLocation = path.join(projectRoot, 'ember-api-docs/ember-api-docs-data');
170+
171+
if (!fs.existsSync(symLinkLocation)) {
172+
log(`Symlinking ${chalk.green('ember-api-docs-data')} to ${chalk.green('ember-api-docs')}`);
173+
fs.symlinkSync(emberApiDocsData, symLinkLocation);
174+
}
175+
176+
log('Docs viewer setup complete');
177+
178+
log('Generating the current docs in ember-jsonapi-docs (these will be inserted into ember-api-docs-data)');
179+
const currentVersion = require(path.join(workspaceRoot, 'package.json')).version;
180+
const absoluteVersion = currentVersion.split('-')[0];
181+
const command = ['bun', 'gen', '--project', 'ember-data', '--version', absoluteVersion];
182+
183+
const proc = Bun.spawn(command, {
184+
cwd: path.join(projectRoot, 'ember-jsonapi-docs'),
185+
env: process.env,
186+
stdio: ['inherit', 'inherit', 'inherit'],
187+
});
188+
await proc.exited;
189+
190+
log('Docs generated. Run `bun regenerate-docs` to update the docs with any changes');
191+
log('Starting the docs viewer');
192+
193+
const proc2 = Bun.spawn(['pnpm', 'start'], {
194+
cwd: path.join(projectRoot, 'ember-api-docs'),
195+
env: process.env,
196+
stdio: ['inherit', 'inherit', 'inherit'],
197+
});
198+
await proc2.exited;
199+
}
200+
201+
main();

docs-viewer/tsconfig.json

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"compilerOptions": {
3+
// Enable latest features
4+
"lib": ["ESNext"],
5+
"target": "ESNext",
6+
"module": "ESNext",
7+
"moduleDetection": "force",
8+
"allowJs": true,
9+
10+
// Bundler mode
11+
"moduleResolution": "bundler",
12+
"allowImportingTsExtensions": true,
13+
"verbatimModuleSyntax": true,
14+
"noEmit": true,
15+
16+
// Best practices
17+
"strict": true,
18+
"skipLibCheck": true,
19+
"noFallthroughCasesInSwitch": true,
20+
21+
// Some stricter flags (disabled by default)
22+
"noUnusedLocals": false,
23+
"noUnusedParameters": false,
24+
"noPropertyAccessFromIndexSignature": false
25+
}
26+
}

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
},
3636
"devDependencies": {
3737
"@warp-drive/internal-tooling": "workspace:*",
38+
"@warp-drive/internal-docs-viewer": "workspace:*",
3839
"@babel/core": "^7.26.9",
3940
"@glimmer/component": "^1.1.2",
4041
"@glint/core": "1.5.2",

pnpm-lock.yaml

+41-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pnpm-workspace.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
packages:
22
- "packages/*"
33
- "internal-tooling"
4+
- "docs-viewer"
5+
- "!docs-viewer/projects/*"
46
- "tests/*"
57
- "config"

0 commit comments

Comments
 (0)