create-kuckit-app 0.1.1 → 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.
Files changed (92) hide show
  1. package/dist/bin.js +1 -1
  2. package/dist/{create-project-DTm05G7D.js → create-project-CP-h4Ygi.js} +7 -5
  3. package/dist/index.js +1 -1
  4. package/package.json +3 -2
  5. package/templates/base/.claude/CLAUDE.md +44 -0
  6. package/templates/base/.claude/agents/daidalos.md +76 -0
  7. package/templates/base/.claude/agents/episteme.md +79 -0
  8. package/templates/base/.claude/agents/librarian.md +132 -0
  9. package/templates/base/.claude/agents/oracle.md +210 -0
  10. package/templates/base/.claude/commands/create-plan.md +159 -0
  11. package/templates/base/.claude/commands/file-beads.md +98 -0
  12. package/templates/base/.claude/commands/review-beads.md +161 -0
  13. package/templates/base/.claude/settings.json +11 -0
  14. package/templates/base/.claude/skills/kuckit/SKILL.md +436 -0
  15. package/templates/base/.claude/skills/kuckit/references/ARCHITECTURE.md +388 -0
  16. package/templates/base/.claude/skills/kuckit/references/CLI-COMMANDS.md +365 -0
  17. package/templates/base/.claude/skills/kuckit/references/MODULE-DEVELOPMENT.md +581 -0
  18. package/templates/base/.claude/skills/kuckit/references/PACKAGES.md +112 -0
  19. package/templates/base/.claude/skills/kuckit/references/PUBLISHING.md +231 -0
  20. package/templates/base/.env.example +13 -0
  21. package/templates/base/.github/workflows/ci.yml +28 -0
  22. package/templates/base/.husky/pre-commit +1 -0
  23. package/templates/base/.prettierignore +5 -0
  24. package/templates/base/.prettierrc +8 -0
  25. package/templates/base/AGENTS.md +148 -0
  26. package/templates/base/apps/server/.env.example +18 -0
  27. package/templates/base/apps/server/AGENTS.md +37 -0
  28. package/templates/base/apps/server/package.json +13 -2
  29. package/templates/base/apps/server/src/app.ts +20 -0
  30. package/templates/base/apps/server/src/auth.ts +10 -0
  31. package/templates/base/apps/server/src/config/modules.ts +22 -0
  32. package/templates/base/apps/server/src/container.ts +81 -0
  33. package/templates/base/apps/server/src/health.ts +27 -0
  34. package/templates/base/apps/server/src/middleware/container.ts +41 -0
  35. package/templates/base/apps/server/src/rpc-router-registry.ts +26 -0
  36. package/templates/base/apps/server/src/rpc.ts +31 -0
  37. package/templates/base/apps/server/src/server.ts +42 -14
  38. package/templates/base/apps/web/.env.example +4 -0
  39. package/templates/base/apps/web/AGENTS.md +53 -0
  40. package/templates/base/apps/web/index.html +1 -1
  41. package/templates/base/apps/web/package.json +15 -2
  42. package/templates/base/apps/web/src/lib/kuckit-router.ts +42 -0
  43. package/templates/base/apps/web/src/main.tsx +26 -14
  44. package/templates/base/apps/web/src/providers/KuckitProvider.tsx +147 -0
  45. package/templates/base/apps/web/src/providers/ServicesProvider.tsx +47 -0
  46. package/templates/base/apps/web/src/routeTree.gen.ts +91 -0
  47. package/templates/base/apps/web/src/routes/__root.tsx +31 -0
  48. package/templates/base/apps/web/src/routes/index.tsx +46 -0
  49. package/templates/base/apps/web/src/routes/login.tsx +108 -0
  50. package/templates/base/apps/web/src/services/auth-client.ts +12 -0
  51. package/templates/base/apps/web/src/services/index.ts +3 -0
  52. package/templates/base/apps/web/src/services/rpc.ts +29 -0
  53. package/templates/base/apps/web/src/services/types.ts +14 -0
  54. package/templates/base/apps/web/vite.config.ts +2 -1
  55. package/templates/base/docker-compose.yml +23 -0
  56. package/templates/base/eslint.config.js +18 -0
  57. package/templates/base/package.json +32 -2
  58. package/templates/base/packages/api/AGENTS.md +27 -0
  59. package/templates/base/packages/api/package.json +35 -0
  60. package/templates/base/packages/api/src/context.ts +48 -0
  61. package/templates/base/packages/api/src/index.ts +22 -0
  62. package/templates/base/packages/api/tsconfig.json +8 -0
  63. package/templates/base/packages/auth/AGENTS.md +45 -0
  64. package/templates/base/packages/auth/package.json +27 -0
  65. package/templates/base/packages/auth/src/index.ts +22 -0
  66. package/templates/base/packages/auth/tsconfig.json +8 -0
  67. package/templates/base/packages/db/AGENTS.md +59 -0
  68. package/templates/base/packages/db/drizzle.config.ts +19 -0
  69. package/templates/base/packages/db/package.json +36 -0
  70. package/templates/base/packages/db/src/connection.ts +40 -0
  71. package/templates/base/packages/db/src/index.ts +4 -0
  72. package/templates/base/packages/db/src/migrations/0000_init.sql +54 -0
  73. package/templates/base/packages/db/src/migrations/meta/_journal.json +13 -0
  74. package/templates/base/packages/db/src/schema/auth.ts +51 -0
  75. package/templates/base/packages/db/tsconfig.json +8 -0
  76. package/templates/base/packages/items-module/AGENTS.md +112 -0
  77. package/templates/base/packages/items-module/package.json +32 -0
  78. package/templates/base/packages/items-module/src/adapters/item.drizzle.ts +66 -0
  79. package/templates/base/packages/items-module/src/api/items.router.ts +47 -0
  80. package/templates/base/packages/items-module/src/client-module.ts +39 -0
  81. package/templates/base/packages/items-module/src/domain/item.entity.ts +36 -0
  82. package/templates/base/packages/items-module/src/index.ts +15 -0
  83. package/templates/base/packages/items-module/src/module.ts +53 -0
  84. package/templates/base/packages/items-module/src/ports/item.repository.ts +13 -0
  85. package/templates/base/packages/items-module/src/ui/ItemsPage.tsx +162 -0
  86. package/templates/base/packages/items-module/src/usecases/create-item.ts +25 -0
  87. package/templates/base/packages/items-module/src/usecases/delete-item.ts +18 -0
  88. package/templates/base/packages/items-module/src/usecases/get-item.ts +19 -0
  89. package/templates/base/packages/items-module/src/usecases/list-items.ts +21 -0
  90. package/templates/base/packages/items-module/tsconfig.json +9 -0
  91. package/templates/base/turbo.json +13 -1
  92. 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,5 @@
1
+ node_modules
2
+ dist
3
+ .turbo
4
+ bun.lockb
5
+ *.log
@@ -0,0 +1,8 @@
1
+ {
2
+ "semi": false,
3
+ "singleQuote": true,
4
+ "tabWidth": 2,
5
+ "useTabs": true,
6
+ "trailingComma": "es5",
7
+ "printWidth": 100
8
+ }
@@ -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__-server",
2
+ "name": "@__APP_NAME_KEBAB__/server",
3
+ "private": true,
3
4
  "type": "module",
4
5
  "scripts": {
5
6
  "build": "tsdown",
@@ -10,11 +11,21 @@
10
11
  "express": "^5.1.0",
11
12
  "cors": "^2.8.5",
12
13
  "dotenv": "^17.2.2",
13
- "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:*"
14
24
  },
15
25
  "devDependencies": {
16
26
  "@types/express": "^5.0.1",
17
27
  "@types/cors": "^2.8.17",
28
+ "@types/pg": "^8.11.11",
18
29
  "typescript": "^5.8.2",
19
30
  "tsdown": "^0.15.5"
20
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
+ }
@@ -0,0 +1,22 @@
1
+ import type { ModuleSpec } from '@kuckit/sdk'
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
+ */
12
+ export const getModuleSpecs = (): ModuleSpec[] => {
13
+ const modules: ModuleSpec[] = [
14
+ // Add your modules here:
15
+ // {
16
+ // module: itemsModule,
17
+ // config: { ... },
18
+ // },
19
+ ]
20
+
21
+ return modules
22
+ }
@@ -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
+ }
@@ -0,0 +1,27 @@
1
+ import type { Express } from 'express'
2
+ import type { AppContainer } from './container'
3
+
4
+ export const setupHealth = (app: Express, container: AppContainer) => {
5
+ app.get('/health', async (_req, res) => {
6
+ const { dbPool } = container.cradle
7
+
8
+ try {
9
+ const client = await dbPool.connect()
10
+ await client.query('SELECT 1')
11
+ client.release()
12
+
13
+ res.status(200).json({
14
+ status: 'healthy',
15
+ timestamp: new Date().toISOString(),
16
+ checks: { database: 'ok' },
17
+ })
18
+ } catch (error) {
19
+ console.error('[Health] Database check failed:', error)
20
+ res.status(503).json({
21
+ status: 'unhealthy',
22
+ timestamp: new Date().toISOString(),
23
+ checks: { database: 'failed' },
24
+ })
25
+ }
26
+ })
27
+ }