create-kuckit-app 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +11 -5
- package/dist/{create-project-DTm05G7D.js → create-project-CP-h4Ygi.js} +7 -5
- package/dist/index.js +1 -1
- package/package.json +3 -2
- package/templates/base/.claude/CLAUDE.md +44 -0
- package/templates/base/.claude/agents/daidalos.md +76 -0
- package/templates/base/.claude/agents/episteme.md +79 -0
- package/templates/base/.claude/agents/librarian.md +132 -0
- package/templates/base/.claude/agents/oracle.md +210 -0
- package/templates/base/.claude/commands/create-plan.md +159 -0
- package/templates/base/.claude/commands/file-beads.md +98 -0
- package/templates/base/.claude/commands/review-beads.md +161 -0
- package/templates/base/.claude/settings.json +11 -0
- package/templates/base/.claude/skills/kuckit/SKILL.md +436 -0
- package/templates/base/.claude/skills/kuckit/references/ARCHITECTURE.md +388 -0
- package/templates/base/.claude/skills/kuckit/references/CLI-COMMANDS.md +365 -0
- package/templates/base/.claude/skills/kuckit/references/MODULE-DEVELOPMENT.md +581 -0
- package/templates/base/.claude/skills/kuckit/references/PACKAGES.md +112 -0
- package/templates/base/.claude/skills/kuckit/references/PUBLISHING.md +231 -0
- package/templates/base/.env.example +13 -0
- package/templates/base/.github/workflows/ci.yml +28 -0
- package/templates/base/.husky/pre-commit +1 -0
- package/templates/base/.prettierignore +5 -0
- package/templates/base/.prettierrc +8 -0
- package/templates/base/AGENTS.md +148 -0
- package/templates/base/apps/server/.env.example +18 -0
- package/templates/base/apps/server/AGENTS.md +37 -0
- package/templates/base/apps/server/package.json +13 -4
- package/templates/base/apps/server/src/app.ts +20 -0
- package/templates/base/apps/server/src/auth.ts +10 -0
- package/templates/base/apps/server/src/config/modules.ts +14 -6
- package/templates/base/apps/server/src/container.ts +81 -0
- package/templates/base/apps/server/src/health.ts +27 -0
- package/templates/base/apps/server/src/middleware/container.ts +41 -0
- package/templates/base/apps/server/src/rpc-router-registry.ts +26 -0
- package/templates/base/apps/server/src/rpc.ts +31 -0
- package/templates/base/apps/server/src/server.ts +39 -29
- package/templates/base/apps/web/.env.example +4 -0
- package/templates/base/apps/web/AGENTS.md +53 -0
- package/templates/base/apps/web/index.html +1 -1
- package/templates/base/apps/web/package.json +15 -3
- package/templates/base/apps/web/src/lib/kuckit-router.ts +42 -0
- package/templates/base/apps/web/src/main.tsx +26 -14
- package/templates/base/apps/web/src/providers/KuckitProvider.tsx +147 -0
- package/templates/base/apps/web/src/providers/ServicesProvider.tsx +47 -0
- package/templates/base/apps/web/src/routeTree.gen.ts +91 -0
- package/templates/base/apps/web/src/routes/__root.tsx +31 -0
- package/templates/base/apps/web/src/routes/index.tsx +46 -0
- package/templates/base/apps/web/src/routes/login.tsx +108 -0
- package/templates/base/apps/web/src/services/auth-client.ts +12 -0
- package/templates/base/apps/web/src/services/index.ts +3 -0
- package/templates/base/apps/web/src/services/rpc.ts +29 -0
- package/templates/base/apps/web/src/services/types.ts +14 -0
- package/templates/base/apps/web/vite.config.ts +2 -1
- package/templates/base/docker-compose.yml +23 -0
- package/templates/base/eslint.config.js +18 -0
- package/templates/base/package.json +32 -2
- package/templates/base/packages/api/AGENTS.md +27 -0
- package/templates/base/packages/api/package.json +35 -0
- package/templates/base/packages/api/src/context.ts +48 -0
- package/templates/base/packages/api/src/index.ts +22 -0
- package/templates/base/packages/api/tsconfig.json +8 -0
- package/templates/base/packages/auth/AGENTS.md +45 -0
- package/templates/base/packages/auth/package.json +27 -0
- package/templates/base/packages/auth/src/index.ts +22 -0
- package/templates/base/packages/auth/tsconfig.json +8 -0
- package/templates/base/packages/db/AGENTS.md +59 -0
- package/templates/base/packages/db/drizzle.config.ts +19 -0
- package/templates/base/packages/db/package.json +36 -0
- package/templates/base/packages/db/src/connection.ts +40 -0
- package/templates/base/packages/db/src/index.ts +4 -0
- package/templates/base/packages/db/src/migrations/0000_init.sql +54 -0
- package/templates/base/packages/db/src/migrations/meta/_journal.json +13 -0
- package/templates/base/packages/db/src/schema/auth.ts +51 -0
- package/templates/base/packages/db/tsconfig.json +8 -0
- package/templates/base/packages/items-module/AGENTS.md +112 -0
- package/templates/base/packages/items-module/package.json +32 -0
- package/templates/base/packages/items-module/src/adapters/item.drizzle.ts +66 -0
- package/templates/base/packages/items-module/src/api/items.router.ts +47 -0
- package/templates/base/packages/items-module/src/client-module.ts +39 -0
- package/templates/base/packages/items-module/src/domain/item.entity.ts +36 -0
- package/templates/base/packages/items-module/src/index.ts +15 -0
- package/templates/base/packages/items-module/src/module.ts +53 -0
- package/templates/base/packages/items-module/src/ports/item.repository.ts +13 -0
- package/templates/base/packages/items-module/src/ui/ItemsPage.tsx +162 -0
- package/templates/base/packages/items-module/src/usecases/create-item.ts +25 -0
- package/templates/base/packages/items-module/src/usecases/delete-item.ts +18 -0
- package/templates/base/packages/items-module/src/usecases/get-item.ts +19 -0
- package/templates/base/packages/items-module/src/usecases/list-items.ts +21 -0
- package/templates/base/packages/items-module/tsconfig.json +9 -0
- package/templates/base/turbo.json +13 -1
- package/templates/base/apps/web/src/App.tsx +0 -16
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# Publishing Kuckit Packages
|
|
2
|
+
|
|
3
|
+
## Preferred Method: Git Tags + CI/CD
|
|
4
|
+
|
|
5
|
+
The recommended way to publish kuckit packages is via Git tags, which trigger GitHub Actions to handle the npm publish.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## SDK Packages (Changeset Workflow)
|
|
10
|
+
|
|
11
|
+
SDK packages use **Changesets** for version management. This is a **multi-step process** that must be followed exactly.
|
|
12
|
+
|
|
13
|
+
### Complete Release Flow
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# 1. Create a changeset (describes what changed)
|
|
17
|
+
bunx changeset
|
|
18
|
+
|
|
19
|
+
# 2. Consume changesets and bump versions
|
|
20
|
+
bun run version-packages
|
|
21
|
+
|
|
22
|
+
# NOTE: version-packages requires GITHUB_TOKEN for changelog generation.
|
|
23
|
+
# If you don't have GITHUB_TOKEN set, use gh CLI:
|
|
24
|
+
export GITHUB_TOKEN=$(gh auth token)
|
|
25
|
+
|
|
26
|
+
# 3. Commit the version bumps and changelog updates
|
|
27
|
+
git add packages/*/package.json packages/*/CHANGELOG.md .changeset/
|
|
28
|
+
git commit -m "chore(release): bump SDK packages to X.Y.Z"
|
|
29
|
+
git push
|
|
30
|
+
|
|
31
|
+
# 4. Create and push a tag to trigger publish
|
|
32
|
+
git tag sdk-v1.0.X
|
|
33
|
+
git push origin sdk-v1.0.X
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### What Each Step Does
|
|
37
|
+
|
|
38
|
+
| Step | Command | What It Does |
|
|
39
|
+
| ---------------- | -------------------------- | ----------------------------------------------------------------------------- |
|
|
40
|
+
| Create changeset | `bunx changeset` | Creates a `.changeset/*.md` file describing the change |
|
|
41
|
+
| Version packages | `bun run version-packages` | Consumes changeset files, bumps `package.json` versions, generates CHANGELOGs |
|
|
42
|
+
| Push tag | `git tag sdk-v*` | Triggers CI workflow which runs `changeset publish` |
|
|
43
|
+
|
|
44
|
+
### Fixed Package Groups
|
|
45
|
+
|
|
46
|
+
The SDK packages are configured as a **fixed** group in `.changeset/config.json`. This means they always share the same version number:
|
|
47
|
+
|
|
48
|
+
- `@kuckit/domain`
|
|
49
|
+
- `@kuckit/application`
|
|
50
|
+
- `@kuckit/infrastructure`
|
|
51
|
+
- `@kuckit/api`
|
|
52
|
+
- `@kuckit/contracts`
|
|
53
|
+
- `@kuckit/auth`
|
|
54
|
+
- `@kuckit/db`
|
|
55
|
+
- `@kuckit/sdk`
|
|
56
|
+
- `@kuckit/sdk-react`
|
|
57
|
+
- `@kuckit/users-module`
|
|
58
|
+
|
|
59
|
+
When you bump one, they all bump together.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Common Pitfalls
|
|
64
|
+
|
|
65
|
+
### Pushing a tag without running `version-packages`
|
|
66
|
+
|
|
67
|
+
**Symptom:** CI workflow runs successfully but outputs "No unpublished projects to publish". Packages stay at their old version on npm.
|
|
68
|
+
|
|
69
|
+
**Cause:** A changeset file exists (`.changeset/*.md`) but `bun run version-packages` was never run. The tag triggers `changeset publish`, which only publishes packages whose `package.json` version is higher than what's on npm.
|
|
70
|
+
|
|
71
|
+
**Fix:**
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# Run the version step you missed
|
|
75
|
+
bun run version-packages
|
|
76
|
+
|
|
77
|
+
# Commit the version bumps
|
|
78
|
+
git add packages/*/package.json packages/*/CHANGELOG.md .changeset/
|
|
79
|
+
git commit -m "chore(release): bump SDK packages to X.Y.Z"
|
|
80
|
+
git push
|
|
81
|
+
|
|
82
|
+
# Delete the old tag and create a new one
|
|
83
|
+
git tag -d sdk-vX.Y.Z
|
|
84
|
+
git push origin :refs/tags/sdk-vX.Y.Z
|
|
85
|
+
git tag sdk-vX.Y.Z
|
|
86
|
+
git push origin sdk-vX.Y.Z
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Forgetting to create a changeset
|
|
90
|
+
|
|
91
|
+
**Symptom:** `bun run version-packages` does nothing.
|
|
92
|
+
|
|
93
|
+
**Cause:** No changeset files exist in `.changeset/`.
|
|
94
|
+
|
|
95
|
+
**Fix:** Run `bunx changeset` first to create a changeset describing your changes.
|
|
96
|
+
|
|
97
|
+
### Version already published
|
|
98
|
+
|
|
99
|
+
**Symptom:** npm publish fails with "You cannot publish over previously published versions"
|
|
100
|
+
|
|
101
|
+
**Cause:** The version in `package.json` already exists on npm.
|
|
102
|
+
|
|
103
|
+
**Fix:** Create a new changeset and run `version-packages` again to bump to a new version.
|
|
104
|
+
|
|
105
|
+
### Missing GITHUB_TOKEN for version-packages
|
|
106
|
+
|
|
107
|
+
**Symptom:** `bun run version-packages` fails or hangs without clear explanation.
|
|
108
|
+
|
|
109
|
+
**Cause:** The `version-packages` command requires `GITHUB_TOKEN` to be set for changelog generation (fetching PR/commit info from GitHub).
|
|
110
|
+
|
|
111
|
+
**Fix:** Set the token using the `gh` CLI:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
export GITHUB_TOKEN=$(gh auth token)
|
|
115
|
+
bun run version-packages
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## CLI & Create-App Packages (Direct Publish)
|
|
121
|
+
|
|
122
|
+
For `@kuckit/cli` and `create-kuckit-app`, these are published directly (not via changesets):
|
|
123
|
+
|
|
124
|
+
### Workflow
|
|
125
|
+
|
|
126
|
+
1. **Bump version** in the package's `package.json` (e.g., `packages/kuckit-cli/package.json`)
|
|
127
|
+
|
|
128
|
+
2. **Commit and push:**
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
git commit -am "chore(cli): release @kuckit/cli v0.2.0"
|
|
132
|
+
git push
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
3. **Create and push a tag:**
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
git tag cli-v0.2.0
|
|
139
|
+
git push origin cli-v0.2.0
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
4. **GitHub Actions handles the rest** - builds and publishes to npm
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Tag Patterns
|
|
147
|
+
|
|
148
|
+
| Tag Pattern | Publishes | Method |
|
|
149
|
+
| --------------- | ------------------------------------------ | ------------------ |
|
|
150
|
+
| `sdk-v*` | All SDK packages (fixed group) | Changesets |
|
|
151
|
+
| `cli-v*` | Only `@kuckit/cli` | Direct npm publish |
|
|
152
|
+
| `create-app-v*` | Only `create-kuckit-app` | Direct npm publish |
|
|
153
|
+
| `v*` | Both `@kuckit/cli` and `create-kuckit-app` | Direct npm publish |
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Commands Reference
|
|
158
|
+
|
|
159
|
+
| Command | Description |
|
|
160
|
+
| -------------------------- | --------------------------------------------------------------- |
|
|
161
|
+
| `bunx changeset` | Create a new changeset file describing your changes |
|
|
162
|
+
| `bun run version-packages` | Consume changesets, bump versions, generate CHANGELOGs |
|
|
163
|
+
| `bunx changeset status` | Check what changesets exist and which packages will be affected |
|
|
164
|
+
| `bunx changeset publish` | Publish packages (run by CI, not locally) |
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Pre-publish Check (Optional)
|
|
169
|
+
|
|
170
|
+
Before tagging, you can verify the package builds correctly:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
cd packages/kuckit-cli
|
|
174
|
+
bun run prepublishOnly
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
This runs:
|
|
178
|
+
|
|
179
|
+
1. `tsdown` build
|
|
180
|
+
2. Workspace protocol check (ensures no `workspace:` or `catalog:` protocols leak into published package)
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## CI/CD Workflow
|
|
185
|
+
|
|
186
|
+
The publish workflow is located at `.github/workflows/publish.yml`.
|
|
187
|
+
|
|
188
|
+
**What it does:**
|
|
189
|
+
|
|
190
|
+
1. Triggers on tag push matching the patterns above
|
|
191
|
+
2. Runs `bun install --frozen-lockfile`
|
|
192
|
+
3. Builds the package(s)
|
|
193
|
+
4. Resolves workspace protocols (converts `workspace:*` and `catalog:` to real versions)
|
|
194
|
+
5. Publishes to npm
|
|
195
|
+
|
|
196
|
+
**Required secret:** `NPM_TOKEN` must be configured in GitHub repository secrets.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Key Files
|
|
201
|
+
|
|
202
|
+
| File | Purpose |
|
|
203
|
+
| ----------------------------------------- | ------------------------------------------------- |
|
|
204
|
+
| `.changeset/config.json` | Changeset configuration with fixed package groups |
|
|
205
|
+
| `scripts/resolve-workspace-protocols.cjs` | Resolves workspace:\*/catalog: before publish |
|
|
206
|
+
| `.github/workflows/publish.yml` | CI workflow that handles publishing |
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Why Git Tags over Local Publish?
|
|
211
|
+
|
|
212
|
+
While the repo has Changesets configured, **local publishing doesn't work well** because:
|
|
213
|
+
|
|
214
|
+
- npm requires 2FA for publishing
|
|
215
|
+
- Local tokens don't have 2FA bypass permissions
|
|
216
|
+
- The CI/CD workflow has a granular access token (`NPM_TOKEN` secret) with proper permissions
|
|
217
|
+
|
|
218
|
+
**Use Changesets for:** Version management and changelog generation. Rely on Git tags for actual publishing.
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Troubleshooting
|
|
223
|
+
|
|
224
|
+
| Issue | Solution |
|
|
225
|
+
| ------------------------------------------------------- | ---------------------------------------------------------------- |
|
|
226
|
+
| "No unpublished projects to publish" | Run `bun run version-packages` first, then push a new tag |
|
|
227
|
+
| "You cannot publish over previously published versions" | Bump the version in package.json first |
|
|
228
|
+
| "Two-factor authentication required" | Use Git tags + CI/CD instead of local publish |
|
|
229
|
+
| Build fails in CI | Check `bun run prepublishOnly` locally first |
|
|
230
|
+
| Changeset file exists but versions didn't bump | Run `bun run version-packages` to consume the changeset |
|
|
231
|
+
| `version-packages` fails or hangs | Set `GITHUB_TOKEN` first: `export GITHUB_TOKEN=$(gh auth token)` |
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Database
|
|
2
|
+
DATABASE_URL=postgresql://postgres:password@localhost:5432/__APP_NAME_KEBAB__
|
|
3
|
+
|
|
4
|
+
# Auth
|
|
5
|
+
BETTER_AUTH_SECRET=your-secret-key-change-in-production
|
|
6
|
+
BETTER_AUTH_URL=http://localhost:3000
|
|
7
|
+
|
|
8
|
+
# Server
|
|
9
|
+
PORT=3000
|
|
10
|
+
NODE_ENV=development
|
|
11
|
+
|
|
12
|
+
# Web
|
|
13
|
+
VITE_API_URL=http://localhost:3000
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
branches: [main]
|
|
6
|
+
push:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
quality:
|
|
11
|
+
name: Code Quality
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- name: Checkout
|
|
16
|
+
uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- name: Setup Bun
|
|
19
|
+
uses: oven-sh/setup-bun@v2
|
|
20
|
+
|
|
21
|
+
- name: Install dependencies
|
|
22
|
+
run: bun install --frozen-lockfile
|
|
23
|
+
|
|
24
|
+
- name: Lint
|
|
25
|
+
run: bun run lint
|
|
26
|
+
|
|
27
|
+
- name: Type check
|
|
28
|
+
run: bun run check-types
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
bun run lint-staged
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# AGENTS.md - **APP_NAME**
|
|
2
|
+
|
|
3
|
+
## Quick Start
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
bun install # Install dependencies
|
|
7
|
+
docker compose up -d # Start PostgreSQL
|
|
8
|
+
bun run db:migrate # Run database migrations
|
|
9
|
+
bun run dev # Start dev servers (web + server)
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Project Structure
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
__APP_NAME_KEBAB__/
|
|
16
|
+
├── apps/
|
|
17
|
+
│ ├── server/ # Express + oRPC backend (port 3000)
|
|
18
|
+
│ └── web/ # React + TanStack Router frontend (port 3001)
|
|
19
|
+
├── packages/
|
|
20
|
+
│ ├── api/ # Shared API context and types
|
|
21
|
+
│ ├── auth/ # Better-Auth configuration
|
|
22
|
+
│ ├── db/ # Drizzle ORM, migrations, schema
|
|
23
|
+
│ └── items-module/ # Example Kuckit module (reference implementation)
|
|
24
|
+
├── .env.example # Environment template
|
|
25
|
+
├── docker-compose.yml # PostgreSQL container
|
|
26
|
+
└── turbo.json # Turborepo configuration
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Module Development
|
|
30
|
+
|
|
31
|
+
Kuckit uses a **module-based architecture** where each module contains its own Clean Architecture layers internally.
|
|
32
|
+
|
|
33
|
+
### Module Structure
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
packages/your-module/
|
|
37
|
+
├── src/
|
|
38
|
+
│ ├── domain/ # Entities with Zod schemas
|
|
39
|
+
│ ├── ports/ # Repository interfaces
|
|
40
|
+
│ ├── adapters/ # Drizzle implementations
|
|
41
|
+
│ ├── usecases/ # Business logic
|
|
42
|
+
│ ├── api/ # oRPC routers
|
|
43
|
+
│ ├── ui/ # React components (optional)
|
|
44
|
+
│ ├── module.ts # Server module definition
|
|
45
|
+
│ └── client-module.ts # Client module definition
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Creating a New Module
|
|
49
|
+
|
|
50
|
+
1. Copy `packages/items-module` as a template
|
|
51
|
+
2. Rename and update `package.json`
|
|
52
|
+
3. Implement your domain entities in `domain/`
|
|
53
|
+
4. Define repository interfaces in `ports/`
|
|
54
|
+
5. Implement adapters in `adapters/`
|
|
55
|
+
6. Create use cases in `usecases/`
|
|
56
|
+
7. Expose API in `api/` via oRPC router
|
|
57
|
+
8. Register module in `apps/server/src/config/modules.ts`
|
|
58
|
+
9. Add client module to `apps/web/src/modules.client.ts`
|
|
59
|
+
|
|
60
|
+
### Dependency Rules
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
domain → No dependencies (pure Zod schemas)
|
|
64
|
+
↓
|
|
65
|
+
ports → Depends on domain only
|
|
66
|
+
↓
|
|
67
|
+
usecases → Depends on ports and domain
|
|
68
|
+
↓
|
|
69
|
+
adapters → Implements ports, depends on domain
|
|
70
|
+
↓
|
|
71
|
+
api → Wires everything together
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Common Tasks
|
|
75
|
+
|
|
76
|
+
### Add a new API endpoint
|
|
77
|
+
|
|
78
|
+
1. Define input/output schemas in `domain/`
|
|
79
|
+
2. Create use case in `usecases/`
|
|
80
|
+
3. Add to router in `api/`
|
|
81
|
+
|
|
82
|
+
### Add a new database table
|
|
83
|
+
|
|
84
|
+
1. Define schema in your module's `adapters/` or `packages/db/src/schema/`
|
|
85
|
+
2. Run `bun run db:generate`
|
|
86
|
+
3. Run `bun run db:migrate`
|
|
87
|
+
|
|
88
|
+
### Add authentication to an endpoint
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
import { protectedProcedure } from '@__APP_NAME_KEBAB__/api'
|
|
92
|
+
|
|
93
|
+
export const myRouter = {
|
|
94
|
+
protectedRoute: protectedProcedure.input(mySchema).handler(async ({ input, context }) => {
|
|
95
|
+
const { user } = context // Authenticated user
|
|
96
|
+
// ...
|
|
97
|
+
}),
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Scripts
|
|
102
|
+
|
|
103
|
+
| Command | Description |
|
|
104
|
+
| ---------------------- | -------------------------------------- |
|
|
105
|
+
| `bun run dev` | Start all dev servers |
|
|
106
|
+
| `bun run build` | Build all packages |
|
|
107
|
+
| `bun run check-types` | Type check all packages |
|
|
108
|
+
| `bun run lint` | Run ESLint on all packages |
|
|
109
|
+
| `bun run lint:fix` | Fix ESLint issues automatically |
|
|
110
|
+
| `bun run format` | Format code with Prettier |
|
|
111
|
+
| `bun run format:check` | Check formatting without changes |
|
|
112
|
+
| `bun run db:generate` | Generate migration from schema changes |
|
|
113
|
+
| `bun run db:migrate` | Apply pending migrations |
|
|
114
|
+
| `bun run db:studio` | Open Drizzle Studio |
|
|
115
|
+
|
|
116
|
+
## Code Quality
|
|
117
|
+
|
|
118
|
+
This project includes pre-configured code quality tools:
|
|
119
|
+
|
|
120
|
+
- **ESLint** - TypeScript linting with recommended rules
|
|
121
|
+
- **Prettier** - Code formatting
|
|
122
|
+
- **Husky** - Git hooks for pre-commit checks
|
|
123
|
+
- **lint-staged** - Run linters on staged files only
|
|
124
|
+
|
|
125
|
+
Pre-commit hooks automatically run `lint-staged` which:
|
|
126
|
+
|
|
127
|
+
1. Runs ESLint on staged `.ts/.tsx/.js/.jsx` files
|
|
128
|
+
2. Runs Prettier on all staged files
|
|
129
|
+
|
|
130
|
+
To bypass hooks (not recommended): `git commit --no-verify`
|
|
131
|
+
|
|
132
|
+
## Environment Variables
|
|
133
|
+
|
|
134
|
+
See `.env.example` for required variables:
|
|
135
|
+
|
|
136
|
+
- `DATABASE_URL` - PostgreSQL connection string
|
|
137
|
+
- `BETTER_AUTH_SECRET` - Auth session secret
|
|
138
|
+
- `BETTER_AUTH_URL` - Auth callback URL
|
|
139
|
+
- `PORT` - Server port (default: 3000)
|
|
140
|
+
- `VITE_API_URL` - API URL for frontend
|
|
141
|
+
|
|
142
|
+
## Related Documentation
|
|
143
|
+
|
|
144
|
+
- [Kuckit SDK](https://github.com/draphonix/kuckit)
|
|
145
|
+
- [oRPC](https://orpc.dev)
|
|
146
|
+
- [Better-Auth](https://better-auth.com)
|
|
147
|
+
- [Drizzle ORM](https://orm.drizzle.team)
|
|
148
|
+
- [TanStack Router](https://tanstack.com/router)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Server Environment Variables
|
|
2
|
+
|
|
3
|
+
# Database connection
|
|
4
|
+
DATABASE_URL=postgresql://postgres:password@localhost:5432/__APP_NAME_KEBAB__
|
|
5
|
+
|
|
6
|
+
# Authentication
|
|
7
|
+
BETTER_AUTH_SECRET=your-secret-key-change-in-production
|
|
8
|
+
BETTER_AUTH_URL=http://localhost:3000
|
|
9
|
+
|
|
10
|
+
# Server configuration
|
|
11
|
+
PORT=3000
|
|
12
|
+
NODE_ENV=development
|
|
13
|
+
CORS_ORIGIN=http://localhost:3001
|
|
14
|
+
|
|
15
|
+
# Logging (optional)
|
|
16
|
+
LOG_LEVEL=INFO
|
|
17
|
+
ENABLE_FILE_LOGGING=false
|
|
18
|
+
LOG_DIR=./logs
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# AGENTS.md - Server App
|
|
2
|
+
|
|
3
|
+
> See root [AGENTS.md](../../AGENTS.md) for project overview
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
Express backend hosting oRPC API, Better-Auth authentication, and the Kuckit module system.
|
|
8
|
+
|
|
9
|
+
## Key Files
|
|
10
|
+
|
|
11
|
+
| File | Purpose |
|
|
12
|
+
| ------------------- | ------------------------- |
|
|
13
|
+
| `server.ts` | Entry point, bootstrap |
|
|
14
|
+
| `container.ts` | DI container setup |
|
|
15
|
+
| `config/modules.ts` | Module registration |
|
|
16
|
+
| `rpc.ts` | oRPC handler setup |
|
|
17
|
+
| `auth.ts` | Better-Auth configuration |
|
|
18
|
+
|
|
19
|
+
## Adding New Modules
|
|
20
|
+
|
|
21
|
+
1. Install the module package
|
|
22
|
+
2. Add to `config/modules.ts`:
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { kuckitModule as myModule } from '@__APP_NAME_KEBAB__/my-module'
|
|
26
|
+
|
|
27
|
+
export const getModuleSpecs = () => [
|
|
28
|
+
{ module: itemsModule },
|
|
29
|
+
{ module: myModule }, // Add here
|
|
30
|
+
]
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
3. Restart the server
|
|
34
|
+
|
|
35
|
+
## Environment Variables
|
|
36
|
+
|
|
37
|
+
See `.env.example` in this directory.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "__APP_NAME_KEBAB__
|
|
2
|
+
"name": "@__APP_NAME_KEBAB__/server",
|
|
3
|
+
"private": true,
|
|
3
4
|
"type": "module",
|
|
4
5
|
"scripts": {
|
|
5
6
|
"build": "tsdown",
|
|
@@ -7,16 +8,24 @@
|
|
|
7
8
|
"dev": "bun run --hot src/server.ts"
|
|
8
9
|
},
|
|
9
10
|
"dependencies": {
|
|
10
|
-
"@kuckit/sdk": "^0.1.0",
|
|
11
|
-
"@kuckit/users-module": "^0.1.0",
|
|
12
11
|
"express": "^5.1.0",
|
|
13
12
|
"cors": "^2.8.5",
|
|
14
13
|
"dotenv": "^17.2.2",
|
|
15
|
-
"awilix": "^12.0.5"
|
|
14
|
+
"awilix": "^12.0.5",
|
|
15
|
+
"pg": "^8.14.1",
|
|
16
|
+
"@orpc/server": "^1.10.0",
|
|
17
|
+
"@orpc/zod": "^1.10.0",
|
|
18
|
+
"better-auth": "^1.3.28",
|
|
19
|
+
"zod": "^4.1.11",
|
|
20
|
+
"@kuckit/sdk": "^1.0.0",
|
|
21
|
+
"@__APP_NAME_KEBAB__/api": "workspace:*",
|
|
22
|
+
"@__APP_NAME_KEBAB__/auth": "workspace:*",
|
|
23
|
+
"@__APP_NAME_KEBAB__/db": "workspace:*"
|
|
16
24
|
},
|
|
17
25
|
"devDependencies": {
|
|
18
26
|
"@types/express": "^5.0.1",
|
|
19
27
|
"@types/cors": "^2.8.17",
|
|
28
|
+
"@types/pg": "^8.11.11",
|
|
20
29
|
"typescript": "^5.8.2",
|
|
21
30
|
"tsdown": "^0.15.5"
|
|
22
31
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import express, { type Express } from 'express'
|
|
2
|
+
import cors from 'cors'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Create and configure Express app
|
|
6
|
+
*/
|
|
7
|
+
export const createApp = (): Express => {
|
|
8
|
+
const app = express()
|
|
9
|
+
|
|
10
|
+
app.use(
|
|
11
|
+
cors({
|
|
12
|
+
origin: process.env.CORS_ORIGIN || 'http://localhost:3001',
|
|
13
|
+
methods: ['GET', 'POST', 'OPTIONS'],
|
|
14
|
+
allowedHeaders: ['Content-Type', 'Authorization'],
|
|
15
|
+
credentials: true,
|
|
16
|
+
})
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
return app
|
|
20
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { auth } from '@__APP_NAME_KEBAB__/auth'
|
|
2
|
+
import { toNodeHandler } from 'better-auth/node'
|
|
3
|
+
import type { Express } from 'express'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Setup Better-Auth routes
|
|
7
|
+
*/
|
|
8
|
+
export const setupAuth = (app: Express) => {
|
|
9
|
+
app.all('/api/auth{/*path}', toNodeHandler(auth))
|
|
10
|
+
}
|
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
import type { ModuleSpec } from '@kuckit/sdk'
|
|
2
|
-
import { kuckitModule as usersModule } from '@kuckit/users-module'
|
|
3
2
|
|
|
3
|
+
// Import your modules here
|
|
4
|
+
// import { kuckitModule as itemsModule } from '@__APP_NAME_KEBAB__/items-module'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Module specifications for the server application
|
|
8
|
+
*
|
|
9
|
+
* Add modules here to configure the server's functionality.
|
|
10
|
+
* Modules are loaded in order, with dependencies resolved automatically.
|
|
11
|
+
*/
|
|
4
12
|
export const getModuleSpecs = (): ModuleSpec[] => {
|
|
5
13
|
const modules: ModuleSpec[] = [
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
14
|
+
// Add your modules here:
|
|
15
|
+
// {
|
|
16
|
+
// module: itemsModule,
|
|
17
|
+
// config: { ... },
|
|
18
|
+
// },
|
|
11
19
|
]
|
|
12
20
|
|
|
13
21
|
return modules
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { AwilixContainer } from 'awilix'
|
|
2
|
+
import {
|
|
3
|
+
createKuckitContainer,
|
|
4
|
+
loadKuckitModules,
|
|
5
|
+
type CoreConfig,
|
|
6
|
+
type CoreCradle,
|
|
7
|
+
} from '@kuckit/sdk'
|
|
8
|
+
import type { Pool } from 'pg'
|
|
9
|
+
import { ensureDatabaseUrl } from '@__APP_NAME_KEBAB__/db/connection'
|
|
10
|
+
import { getModuleSpecs } from './config/modules'
|
|
11
|
+
import { wireModuleRpcRouters } from './rpc-router-registry'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Server configuration
|
|
15
|
+
*/
|
|
16
|
+
export interface ServerConfig extends CoreConfig {
|
|
17
|
+
port: number
|
|
18
|
+
corsOrigin: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Server DI container cradle
|
|
23
|
+
*/
|
|
24
|
+
export interface ServerCradle extends CoreCradle {
|
|
25
|
+
config: ServerConfig
|
|
26
|
+
dbPool: Pool
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type AppContainer = AwilixContainer<ServerCradle>
|
|
30
|
+
export type { ServerConfig as Config, ServerCradle as Cradle }
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Load configuration from environment
|
|
34
|
+
*/
|
|
35
|
+
const loadConfig = (): ServerConfig => {
|
|
36
|
+
const databaseUrl = ensureDatabaseUrl()
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
databaseUrl,
|
|
40
|
+
enableFileLogging: process.env.ENABLE_FILE_LOGGING === 'true',
|
|
41
|
+
logDir: process.env.LOG_DIR || './logs',
|
|
42
|
+
logLevel: (process.env.LOG_LEVEL || 'INFO') as 'DEBUG' | 'INFO' | 'WARN' | 'ERROR',
|
|
43
|
+
env: process.env.NODE_ENV || 'development',
|
|
44
|
+
port: parseInt(process.env.PORT || '3000', 10),
|
|
45
|
+
corsOrigin: process.env.CORS_ORIGIN || 'http://localhost:3001',
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Build root container with all modules
|
|
51
|
+
*/
|
|
52
|
+
export const buildRootContainer = async (): Promise<AppContainer> => {
|
|
53
|
+
const config = loadConfig()
|
|
54
|
+
|
|
55
|
+
const container = await createKuckitContainer({ config })
|
|
56
|
+
|
|
57
|
+
await loadKuckitModules({
|
|
58
|
+
container,
|
|
59
|
+
env: config.env,
|
|
60
|
+
modules: getModuleSpecs(),
|
|
61
|
+
onApiRegistrations: (registrations) => {
|
|
62
|
+
wireModuleRpcRouters(registrations)
|
|
63
|
+
console.log(`Loaded ${registrations.length} API registrations from modules`)
|
|
64
|
+
},
|
|
65
|
+
onComplete: () => {
|
|
66
|
+
console.log('All modules loaded successfully')
|
|
67
|
+
},
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
return container as AppContainer
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Cleanup container resources
|
|
75
|
+
*/
|
|
76
|
+
export const disposeContainer = async (container: AppContainer): Promise<void> => {
|
|
77
|
+
const { dbPool } = container.cradle
|
|
78
|
+
if (dbPool && typeof dbPool.end === 'function') {
|
|
79
|
+
await dbPool.end()
|
|
80
|
+
}
|
|
81
|
+
}
|