71 lines
3.6 KiB
Markdown
71 lines
3.6 KiB
Markdown
You are a code implementer. Build ONE focused module. Write the code now.
|
|||
|
|
|
||
|
|
## HARD RULES
|
||
|
|
- Do NOT call any automaton_* tool. Do NOT read PARENT_SPEC.md or DECOMPOSITION.md.
|
||
|
|
- Start writing files within your first 2 tool calls. Read only what's listed, then build.
|
||
|
|
- You are building micro-slice 1a: the SQLite database foundation for the Investor Flow backend.
|
||
|
|
|
||
|
|
## CONTEXT (read these, then build)
|
||
|
|
The project is "Investor Flow" — a Bun + SQLite backend serving a Next.js SPA. You are creating the database layer. The schema follows DESIGN.md Section 1 (Tier A shared market cache + Tier D system).
|
||
|
|
|
||
|
|
Read this ONE file for the exact schema:
|
||
|
|
`grep -n "Tier D\|Tier A\|CREATE TABLE\|users\|sessions\|symbol_meta\|price_quotes\|price_candles\|symbol_demand" /Users/laptran/Documents/investor-flow/.automaton/tasks/investor-flow-platform-design/DESIGN.md | head -40`
|
||
|
|
|
||
|
|
If the grep doesn't give enough, read lines 17-175 of that DESIGN.md.
|
||
|
|
|
||
|
|
## BUILD EXACTLY THESE 4 FILES
|
||
|
|
|
||
|
|
### 1. `app/server/package.json`
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"name": "investor-flow-server",
|
||
|
|
"version": "0.1.0",
|
||
|
|
"type": "module",
|
||
|
|
"scripts": {
|
||
|
|
"dev": "bun run src/index.ts",
|
||
|
|
"test": "bun test"
|
||
|
|
},
|
||
|
|
"dependencies": {
|
||
|
|
"better-sqlite3": "^11.0.0",
|
||
|
|
"@trpc/server": "^11.0.0",
|
||
|
|
"argon2": "^0.40.0",
|
||
|
|
"yahoo-finance2": "^2.0.0",
|
||
|
|
"zod": "^3.23.0"
|
||
|
|
},
|
||
|
|
"devDependencies": {
|
||
|
|
"@types/better-sqlite3": "^7.6.0",
|
||
|
|
"bun-types": "^1.1.0",
|
||
|
|
"typescript": "^5.0.0"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. `app/server/tsconfig.json`
|
||
|
|
Standard Bun TypeScript config (target ESNext, module ESNext, moduleResolution bundler, strict true, types ["bun-types"], outDir ./dist).
|
||
|
|
|
||
|
|
### 3. `app/server/src/db/schema.sql`
|
||
|
|
SQLite DDL for these tables (match DESIGN.md Section 1 Tier A + Tier D):
|
||
|
|
- `users` (id TEXT PK, email TEXT UNIQUE NOT NULL, pw_hash TEXT NOT NULL, complexity TEXT DEFAULT 'beginner', risk_tolerance TEXT, created_at TEXT NOT NULL)
|
||
|
|
- `sessions` (id TEXT PK, user_id TEXT NOT NULL REFERENCES users(id), expires_at TEXT NOT NULL, created_at TEXT NOT NULL)
|
||
|
|
- `symbol_meta` (symbol TEXT PK, name TEXT, sector TEXT, industry TEXT, exchange TEXT, ticker_kind TEXT NOT NULL DEFAULT 'equity', updated_at TEXT)
|
||
|
|
- `price_quotes` (symbol TEXT NOT NULL, price REAL, bid REAL, ask REAL, change REAL, change_pct REAL, ts_observed TEXT NOT NULL, fetched_at TEXT NOT NULL, PRIMARY KEY(symbol, ts_observed))
|
||
|
|
- `price_candles` (symbol TEXT NOT NULL, tf TEXT NOT NULL, ts TEXT NOT NULL, o REAL, h REAL, l REAL, c REAL, v REAL, adj_close REAL, PRIMARY KEY(symbol, tf, ts))
|
||
|
|
- `symbol_demand` (symbol TEXT PK, refcount INTEGER NOT NULL DEFAULT 0, protected INTEGER NOT NULL DEFAULT 0)
|
||
|
|
Add indexes: on price_quotes(symbol), price_candles(symbol, ts), sessions(user_id).
|
||
|
|
|
||
|
|
### 4. `app/server/src/db/client.ts`
|
||
|
|
A `DbClient` class (or factory function) that:
|
||
|
|
- Opens a SQLite database (better-sqlite3). Accepts a path arg; default `./investor-flow.db`. For tests, accept `:memory:`.
|
||
|
|
- On init, reads and executes `schema.sql` (use `import.meta.dir` to resolve the path relative to the file).
|
||
|
|
- Exposes the raw `Database` instance via a `db` property for other modules to use prepared statements.
|
||
|
|
- Exports a `createDb(path?)` factory.
|
||
|
|
TypeScript throughout. Use `better-sqlite3` synchronous API.
|
||
|
|
|
||
|
|
## THEN
|
||
|
|
Run `cd /Users/laptran/Documents/investor-flow/app/server && bun install` to install deps.
|
||
|
|
Then run a quick smoke test: `bun -e "import {createDb} from './src/db/client'; const db = createDb(':memory:'); console.log(db.db.prepare('SELECT name FROM sqlite_master WHERE type=\"table\"').all());"` to confirm tables exist.
|
||
|
|
Print the result. Then STOP — do not build anything else.
|
||
|
|
|
||
|
|
## PRIMARY RULE
|
||
|
|
No user-facing strings in this micro-slice (it's the DB layer). Just clean typed code.
|