512 lines
12 KiB
Markdown
512 lines
12 KiB
Markdown
# opencode Monorepo Config Adoption Implementation Plan
|
||
|
||
> **For agentic workers:** REQUIRED SUB-SKILL: Use
|
||
> superpowers:subagent-driven-development (recommended) or superpowers:executing-plans
|
||
> to implement this plan task-by-task.
|
||
> Steps use checkbox (`- [ ]`) syntax for tracking.
|
||
|
||
**Goal:** Adopt opencode-style monorepo config: Turbo task orchestration, workspace dep
|
||
catalog, shared root tsconfig, bunfig.toml, and `exports` field in all packages.
|
||
|
||
**Architecture:** Pure config changes across 10 files — no source code touched.
|
||
Root config files are added/updated first, then per-package files updated to reference
|
||
them. Changes are independent within each task and safe to commit atomically.
|
||
|
||
**Tech Stack:** Bun workspaces, Turbo 2.x, @tsconfig/bun, TypeScript (tsgo /
|
||
@typescript/native-preview)
|
||
|
||
* * *
|
||
|
||
## File Map
|
||
|
||
| File | Action | Responsible for |
|
||
| --- | --- | --- |
|
||
| `package.json` | Modify | Workspace catalog, turbo devDep, @tsconfig/bun devDep, updated scripts |
|
||
| `turbo.json` | Create | Task graph: typecheck, build, test |
|
||
| `tsconfig.json` | Create | Shared TS compiler options for all packages |
|
||
| `bunfig.toml` | Create | Exact installs, root test guard |
|
||
| `packages/core/package.json` | Modify | exports field, catalog refs, script rename |
|
||
| `packages/api-server/package.json` | Modify | exports field, catalog refs, script rename |
|
||
| `packages/mcp-server/package.json` | Modify | exports field, catalog refs, script rename |
|
||
| `packages/core/tsconfig.json` | Modify | Slim — extends root, paths only |
|
||
| `packages/api-server/tsconfig.json` | Modify | Slim — extends root, paths only |
|
||
| `packages/mcp-server/tsconfig.json` | Modify | Slim — extends root, paths only |
|
||
|
||
* * *
|
||
|
||
### Task 1: Add `bunfig.toml` and `turbo.json`
|
||
|
||
Two new root config files with no dependencies on other tasks.
|
||
|
||
**Files:**
|
||
|
||
- Create: `bunfig.toml`
|
||
|
||
- Create: `turbo.json`
|
||
|
||
- [ ] **Step 1: Create `bunfig.toml`**
|
||
|
||
Write this file at repo root (`/path/to/ca-marketplace-scraper/bunfig.toml`):
|
||
|
||
```toml
|
||
[install]
|
||
exact = true
|
||
|
||
[test]
|
||
root = "./do-not-run-tests-from-root"
|
||
```
|
||
|
||
- [ ] **Step 2: Create `turbo.json`**
|
||
|
||
Write this file at repo root:
|
||
|
||
```json
|
||
{
|
||
"$schema": "https://turbo.build/schema.json",
|
||
"tasks": {
|
||
"typecheck": {},
|
||
"build": {
|
||
"dependsOn": ["^build"],
|
||
"outputs": ["dist/**"]
|
||
},
|
||
"test": {
|
||
"dependsOn": ["^build"],
|
||
"outputs": []
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 3: Verify files exist**
|
||
|
||
Run:
|
||
```bash
|
||
ls bunfig.toml turbo.json
|
||
```
|
||
Expected: both files listed, no errors.
|
||
|
||
- [ ] **Step 4: Commit**
|
||
|
||
```bash
|
||
git add bunfig.toml turbo.json
|
||
git commit -m "chore: add bunfig.toml and turbo.json"
|
||
```
|
||
|
||
* * *
|
||
|
||
### Task 2: Create root `tsconfig.json`
|
||
|
||
Shared base tsconfig all packages will extend.
|
||
Extracts the common options currently duplicated in all 3 per-package tsconfigs.
|
||
|
||
**Files:**
|
||
|
||
- Create: `tsconfig.json`
|
||
|
||
- [ ] **Step 1: Create root `tsconfig.json`**
|
||
|
||
Write this file at repo root:
|
||
|
||
```json
|
||
{
|
||
"$schema": "https://json.schemastore.org/tsconfig",
|
||
"extends": "@tsconfig/bun/tsconfig.json",
|
||
"compilerOptions": {
|
||
"lib": ["dom", "ESNext"],
|
||
"target": "ESNext",
|
||
"module": "preserve",
|
||
"moduleResolution": "bundler",
|
||
"strict": true,
|
||
"noEmit": true,
|
||
"moduleDetection": "force",
|
||
"jsx": "react-jsx",
|
||
"allowJs": true,
|
||
"allowImportingTsExtensions": true,
|
||
"verbatimModuleSyntax": true,
|
||
"skipLibCheck": true,
|
||
"noFallthroughCasesInSwitch": true,
|
||
"noUncheckedIndexedAccess": true,
|
||
"noImplicitOverride": true,
|
||
"noUnusedLocals": false,
|
||
"noUnusedParameters": false,
|
||
"noPropertyAccessFromIndexSignature": false
|
||
}
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 2: Commit**
|
||
|
||
```bash
|
||
git add tsconfig.json
|
||
git commit -m "chore: add shared root tsconfig.json"
|
||
```
|
||
|
||
* * *
|
||
|
||
### Task 3: Update root `package.json`
|
||
|
||
Add workspace catalog, `turbo` + `@tsconfig/bun` devDependencies, and update scripts to
|
||
use `turbo run`.
|
||
|
||
**Files:**
|
||
|
||
- Modify: `package.json`
|
||
|
||
- [ ] **Step 1: Replace root `package.json`**
|
||
|
||
Write this complete file:
|
||
|
||
```json
|
||
{
|
||
"name": "marketplace-scrapers-monorepo",
|
||
"version": "1.0.0",
|
||
"private": true,
|
||
"type": "module",
|
||
"packageManager": "bun@1.3.13",
|
||
"scripts": {
|
||
"typecheck": "turbo run typecheck",
|
||
"build": "bun run clean && turbo run build",
|
||
"build:api": "bun build ./packages/api-server/src/index.ts --target=bun --outdir=./dist/api --minify",
|
||
"build:mcp": "bun build ./packages/mcp-server/src/index.ts --target=bun --outdir=./dist/mcp --minify",
|
||
"build:all": "bun run build:api && bun run build:mcp",
|
||
"ci": "biome ci",
|
||
"clean": "rm -rf dist",
|
||
"start": "./scripts/start.sh"
|
||
},
|
||
"workspaces": {
|
||
"packages": [
|
||
"packages/*"
|
||
],
|
||
"catalog": {
|
||
"@tsconfig/bun": "1.0.9",
|
||
"@typescript/native-preview": "7.0.0-dev.20260428.1",
|
||
"@types/bun": "1.2.18",
|
||
"@types/cli-progress": "3.11.6",
|
||
"@types/unidecode": "1.1.0"
|
||
}
|
||
},
|
||
"devDependencies": {
|
||
"@biomejs/biome": "2.3.11",
|
||
"@tsconfig/bun": "catalog:",
|
||
"turbo": "2.5.4"
|
||
}
|
||
}
|
||
```
|
||
|
||
> **Note on catalog versions:** The catalog pins exact versions.
|
||
> The values above are taken from the current package installs.
|
||
> If `@types/bun` was `latest`, check `node_modules/@types/bun/package.json` for the
|
||
> actual installed version and use that.
|
||
> Same for `@typescript/native-preview`.
|
||
|
||
- [ ] **Step 2: Check actual installed versions**
|
||
|
||
Run:
|
||
```bash
|
||
cat node_modules/@types/bun/package.json | grep '"version"'
|
||
cat node_modules/@typescript/native-preview/package.json | grep '"version"'
|
||
cat node_modules/@types/cli-progress/package.json | grep '"version"'
|
||
cat node_modules/@types/unidecode/package.json | grep '"version"'
|
||
```
|
||
|
||
Update the catalog values in `package.json` to match the exact installed versions.
|
||
|
||
- [ ] **Step 3: Install turbo and @tsconfig/bun**
|
||
|
||
```bash
|
||
bun install
|
||
```
|
||
|
||
Expected: lock file updated, `turbo` and `@tsconfig/bun` appear in `node_modules`.
|
||
|
||
- [ ] **Step 4: Verify turbo works**
|
||
|
||
```bash
|
||
bunx turbo run typecheck --dry
|
||
```
|
||
|
||
Expected: output lists the `typecheck` task for each package (even if no `typecheck`
|
||
script exists yet — turbo will note them as skipped/missing).
|
||
|
||
- [ ] **Step 5: Commit**
|
||
|
||
```bash
|
||
git add package.json bun.lock
|
||
git commit -m "chore: add workspace catalog and turbo to root package.json"
|
||
```
|
||
|
||
* * *
|
||
|
||
### Task 4: Update per-package `package.json` files
|
||
|
||
Rename `type:check` → `typecheck`, replace `main`/`module` with `exports`, swap pinned
|
||
dep versions for `catalog:` references.
|
||
|
||
**Files:**
|
||
|
||
- Modify: `packages/core/package.json`
|
||
|
||
- Modify: `packages/api-server/package.json`
|
||
|
||
- Modify: `packages/mcp-server/package.json`
|
||
|
||
- [ ] **Step 1: Replace `packages/core/package.json`**
|
||
|
||
```json
|
||
{
|
||
"name": "@marketplace-scrapers/core",
|
||
"version": "1.0.0",
|
||
"type": "module",
|
||
"exports": {
|
||
".": "./src/index.ts"
|
||
},
|
||
"private": true,
|
||
"scripts": {
|
||
"typecheck": "bun tsgo"
|
||
},
|
||
"dependencies": {
|
||
"@typescript/native-preview": "catalog:",
|
||
"cli-progress": "^3.12.0",
|
||
"linkedom": "^0.18.12",
|
||
"unidecode": "^1.1.0"
|
||
},
|
||
"devDependencies": {
|
||
"@types/bun": "catalog:",
|
||
"@types/cli-progress": "catalog:",
|
||
"@types/unidecode": "catalog:"
|
||
},
|
||
"peerDependencies": {
|
||
"typescript": "^5"
|
||
}
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 2: Replace `packages/api-server/package.json`**
|
||
|
||
```json
|
||
{
|
||
"name": "@marketplace-scrapers/api-server",
|
||
"version": "1.0.0",
|
||
"type": "module",
|
||
"exports": {
|
||
".": "./src/index.ts"
|
||
},
|
||
"private": true,
|
||
"scripts": {
|
||
"start": "bun ./src/index.ts",
|
||
"dev": "bun --watch ./src/index.ts",
|
||
"build": "bun build ./src/index.ts --target=bun --outdir=../../dist/api",
|
||
"typecheck": "bun tsgo"
|
||
},
|
||
"dependencies": {
|
||
"@marketplace-scrapers/core": "workspace:*",
|
||
"@typescript/native-preview": "catalog:"
|
||
},
|
||
"devDependencies": {
|
||
"@types/bun": "catalog:"
|
||
},
|
||
"peerDependencies": {
|
||
"typescript": "^5"
|
||
}
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 3: Replace `packages/mcp-server/package.json`**
|
||
|
||
```json
|
||
{
|
||
"name": "@marketplace-scrapers/mcp-server",
|
||
"version": "1.0.0",
|
||
"type": "module",
|
||
"exports": {
|
||
".": "./src/index.ts"
|
||
},
|
||
"private": true,
|
||
"scripts": {
|
||
"start": "bun ./src/index.ts",
|
||
"dev": "bun --watch ./src/index.ts",
|
||
"build": "bun build ./src/index.ts --target=bun --outdir=../../dist/mcp",
|
||
"typecheck": "bun tsgo"
|
||
},
|
||
"dependencies": {
|
||
"@marketplace-scrapers/core": "workspace:*",
|
||
"@typescript/native-preview": "catalog:"
|
||
},
|
||
"devDependencies": {
|
||
"@types/bun": "catalog:"
|
||
},
|
||
"peerDependencies": {
|
||
"typescript": "^5"
|
||
}
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 4: Run `bun install` to sync lockfile**
|
||
|
||
```bash
|
||
bun install
|
||
```
|
||
|
||
Expected: no errors.
|
||
Catalog refs resolved.
|
||
`bun.lock` updated.
|
||
|
||
- [ ] **Step 5: Verify typecheck still works per-package**
|
||
|
||
```bash
|
||
cd packages/core && bun run typecheck
|
||
cd ../api-server && bun run typecheck
|
||
cd ../mcp-server && bun run typecheck
|
||
cd ../..
|
||
```
|
||
|
||
Expected: each exits 0 (or same errors as before — no new errors introduced).
|
||
|
||
- [ ] **Step 6: Commit**
|
||
|
||
```bash
|
||
git add packages/core/package.json packages/api-server/package.json packages/mcp-server/package.json bun.lock
|
||
git commit -m "chore: use exports field and catalog refs in all packages"
|
||
```
|
||
|
||
* * *
|
||
|
||
### Task 5: Slim per-package `tsconfig.json` files
|
||
|
||
Replace the duplicated full tsconfig in each package with a slim `extends`-based one
|
||
pointing to root.
|
||
|
||
**Files:**
|
||
|
||
- Modify: `packages/core/tsconfig.json`
|
||
|
||
- Modify: `packages/api-server/tsconfig.json`
|
||
|
||
- Modify: `packages/mcp-server/tsconfig.json`
|
||
|
||
- [ ] **Step 1: Replace `packages/core/tsconfig.json`**
|
||
|
||
```json
|
||
{
|
||
"extends": "../../tsconfig.json",
|
||
"compilerOptions": {
|
||
"paths": {
|
||
"@/*": ["./src/*"]
|
||
}
|
||
},
|
||
"include": ["./src", "./test"]
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 2: Replace `packages/api-server/tsconfig.json`**
|
||
|
||
```json
|
||
{
|
||
"extends": "../../tsconfig.json",
|
||
"compilerOptions": {
|
||
"paths": {
|
||
"@/*": ["./src/*"]
|
||
}
|
||
},
|
||
"include": ["./src", "./test"]
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 3: Replace `packages/mcp-server/tsconfig.json`**
|
||
|
||
```json
|
||
{
|
||
"extends": "../../tsconfig.json",
|
||
"compilerOptions": {
|
||
"paths": {
|
||
"@/*": ["./src/*"]
|
||
}
|
||
},
|
||
"include": ["./src", "./test"]
|
||
}
|
||
```
|
||
|
||
- [ ] **Step 4: Verify `@tsconfig/bun` is resolvable**
|
||
|
||
The root tsconfig extends `@tsconfig/bun/tsconfig.json`. Confirm the package is
|
||
installed:
|
||
|
||
```bash
|
||
ls node_modules/@tsconfig/bun/tsconfig.json
|
||
```
|
||
|
||
Expected: file exists.
|
||
|
||
- [ ] **Step 5: Run typecheck via Turbo**
|
||
|
||
```bash
|
||
bun run typecheck
|
||
```
|
||
|
||
Expected: Turbo runs `typecheck` for all 3 packages in parallel, all pass (or same
|
||
pre-existing errors — no new ones).
|
||
|
||
- [ ] **Step 6: Commit**
|
||
|
||
```bash
|
||
git add packages/core/tsconfig.json packages/api-server/tsconfig.json packages/mcp-server/tsconfig.json
|
||
git commit -m "chore: slim per-package tsconfigs to extend root"
|
||
```
|
||
|
||
* * *
|
||
|
||
### Task 6: Smoke test full build pipeline
|
||
|
||
Verify everything works end-to-end.
|
||
|
||
**Files:** none (verification only)
|
||
|
||
- [ ] **Step 1: Run turbo typecheck**
|
||
|
||
```bash
|
||
bun run typecheck
|
||
```
|
||
|
||
Expected: Turbo runs `typecheck` across all packages.
|
||
Exit 0.
|
||
|
||
- [ ] **Step 2: Run full build**
|
||
|
||
```bash
|
||
bun run build
|
||
```
|
||
|
||
Expected: `dist/` cleaned, Turbo runs `build` (core first, then api-server and
|
||
mcp-server in parallel), build artifacts appear in `dist/api/` and `dist/mcp/`.
|
||
|
||
- [ ] **Step 3: Verify dist artifacts**
|
||
|
||
```bash
|
||
ls dist/api/ dist/mcp/
|
||
```
|
||
|
||
Expected: compiled output files in both directories.
|
||
|
||
- [ ] **Step 4: Verify `bun install` is exact**
|
||
|
||
```bash
|
||
grep -c '\^' bun.lock | head -5
|
||
```
|
||
|
||
With `exact = true` in bunfig.toml, new installs won’t add `^` ranges.
|
||
Existing `^` ranges in `bun.lock` from before are fine — they’ll be resolved to exact on
|
||
next fresh install.
|
||
|
||
- [ ] **Step 5: Final commit if any loose files**
|
||
|
||
```bash
|
||
git status
|
||
```
|
||
|
||
If clean: done. If any files modified by `bun install` (e.g. `bun.lock`):
|
||
|
||
```bash
|
||
git add bun.lock
|
||
git commit -m "chore: sync lockfile after monorepo config adoption"
|
||
```
|