create-kuckit-app 0.4.0 → 0.4.1

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 (41) hide show
  1. package/dist/bin.js +1 -1
  2. package/dist/{create-project-geQBZ0Ru.js → create-project-CAsuZMK5.js} +2 -1
  3. package/dist/index.js +1 -1
  4. package/package.json +1 -1
  5. package/templates/base/.claude/CLAUDE.md +83 -0
  6. package/templates/base/AGENTS.md +86 -0
  7. package/templates/base/apps/server/AGENTS.md +42 -85
  8. package/templates/base/apps/server/package.json +2 -14
  9. package/templates/base/apps/server/src/config.ts +12 -0
  10. package/templates/base/apps/server/src/modules.ts +66 -0
  11. package/templates/base/apps/server/src/server.ts +4 -46
  12. package/templates/base/apps/web/AGENTS.md +63 -85
  13. package/templates/base/apps/web/package.json +2 -6
  14. package/templates/base/apps/web/src/components/KuckitModuleRoute.tsx +29 -7
  15. package/templates/base/apps/web/src/components/dashboard/dashboard-overview.tsx +2 -2
  16. package/templates/base/apps/web/src/components/dashboard/nav-user.tsx +2 -2
  17. package/templates/base/apps/web/src/main.tsx +12 -22
  18. package/templates/base/apps/web/src/modules.client.ts +43 -9
  19. package/templates/base/apps/web/src/routes/__root.tsx +1 -1
  20. package/templates/base/apps/web/src/routes/dashboard.tsx +1 -1
  21. package/templates/base/apps/web/src/routes/index.tsx +2 -2
  22. package/templates/base/apps/web/src/routes/login.tsx +2 -2
  23. package/templates/base/drizzle.config.ts +2 -6
  24. package/templates/base/kuckit.config.ts +30 -0
  25. package/templates/base/packages/items-module/AGENTS.md +83 -0
  26. package/templates/base/apps/server/src/app.ts +0 -20
  27. package/templates/base/apps/server/src/auth.ts +0 -10
  28. package/templates/base/apps/server/src/config/modules.ts +0 -21
  29. package/templates/base/apps/server/src/container.ts +0 -83
  30. package/templates/base/apps/server/src/health.ts +0 -27
  31. package/templates/base/apps/server/src/middleware/container.ts +0 -41
  32. package/templates/base/apps/server/src/module-rest-routes.ts +0 -47
  33. package/templates/base/apps/server/src/rest-router-registry.ts +0 -32
  34. package/templates/base/apps/server/src/rpc-router-registry.ts +0 -26
  35. package/templates/base/apps/server/src/rpc.ts +0 -31
  36. package/templates/base/apps/web/src/providers/KuckitProvider.tsx +0 -123
  37. package/templates/base/apps/web/src/providers/ServicesProvider.tsx +0 -47
  38. package/templates/base/apps/web/src/services/auth-client.ts +0 -12
  39. package/templates/base/apps/web/src/services/index.ts +0 -3
  40. package/templates/base/apps/web/src/services/rpc.ts +0 -29
  41. package/templates/base/apps/web/src/services/types.ts +0 -14
package/dist/bin.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as createProject } from "./create-project-geQBZ0Ru.js";
2
+ import { t as createProject } from "./create-project-CAsuZMK5.js";
3
3
  import { program } from "commander";
4
4
  import { join } from "node:path";
5
5
  import { existsSync, readFileSync } from "node:fs";
@@ -39,7 +39,8 @@ async function createProject(name, options) {
39
39
  const replacements = {
40
40
  __APP_NAME__: name,
41
41
  __APP_NAME_LOWER__: name.toLowerCase(),
42
- __APP_NAME_KEBAB__: name.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase()
42
+ __APP_NAME_KEBAB__: name.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase(),
43
+ __APP_TITLE__: name
43
44
  };
44
45
  console.log(" Copying template files...");
45
46
  await copyDir(templateDir, targetDir, replacements);
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- import { t as createProject } from "./create-project-geQBZ0Ru.js";
1
+ import { t as createProject } from "./create-project-CAsuZMK5.js";
2
2
 
3
3
  export { createProject };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-kuckit-app",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Create a new Kuckit application",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -42,3 +42,86 @@ This is a Kuckit application using Clean Architecture patterns.
42
42
  - Adapters: `*.drizzle.ts`
43
43
  - Routers: `*.router.ts`
44
44
  - Use cases: verb-noun (e.g., `create-item.ts`, `list-items.ts`)
45
+
46
+ <!-- MCP_AGENT_MAIL_AND_BEADS_SNIPPET_START -->
47
+
48
+ ## MCP Agent Mail: coordination for multi-agent workflows
49
+
50
+ What it is
51
+
52
+ - A mail-like layer that lets coding agents coordinate asynchronously via MCP tools and resources.
53
+ - Provides identities, inbox/outbox, searchable threads, and advisory file reservations, with human-auditable artifacts in Git.
54
+
55
+ Why it's useful
56
+
57
+ - Prevents agents from stepping on each other with explicit file reservations (leases) for files/globs.
58
+ - Keeps communication out of your token budget by storing messages in a per-project archive.
59
+ - Offers quick reads (`resource://inbox/...`, `resource://thread/...`) and macros that bundle common flows.
60
+
61
+ How to use effectively
62
+
63
+ 1. Same repository
64
+ - Register an identity: call `ensure_project`, then `register_agent` using this repo's absolute path as `project_key`.
65
+ - Reserve files before you edit: `file_reservation_paths(project_key, agent_name, ["src/**"], ttl_seconds=3600, exclusive=true)` to signal intent and avoid conflict.
66
+ - Communicate with threads: use `send_message(..., thread_id="FEAT-123")`; check inbox with `fetch_inbox` and acknowledge with `acknowledge_message`.
67
+ - Read fast: `resource://inbox/{Agent}?project=<abs-path>&limit=20` or `resource://thread/{id}?project=<abs-path>&include_bodies=true`.
68
+ - Tip: set `AGENT_NAME` in your environment so the pre-commit guard can block commits that conflict with others' active exclusive file reservations.
69
+
70
+ 2. Across different repos in one project (e.g., Next.js frontend + FastAPI backend)
71
+ - Option A (single project bus): register both sides under the same `project_key` (shared key/path). Keep reservation patterns specific (e.g., `frontend/**` vs `backend/**`).
72
+ - Option B (separate projects): each repo has its own `project_key`; use `macro_contact_handshake` or `request_contact`/`respond_contact` to link agents, then message directly. Keep a shared `thread_id` (e.g., ticket key) across repos for clean summaries/audits.
73
+
74
+ Macros vs granular tools
75
+
76
+ - Prefer macros when you want speed or are on a smaller model: `macro_start_session`, `macro_prepare_thread`, `macro_file_reservation_cycle`, `macro_contact_handshake`.
77
+ - Use granular tools when you need control: `register_agent`, `file_reservation_paths`, `send_message`, `fetch_inbox`, `acknowledge_message`.
78
+
79
+ Common pitfalls
80
+
81
+ - "from_agent not registered": always `register_agent` in the correct `project_key` first.
82
+ - "FILE_RESERVATION_CONFLICT": adjust patterns, wait for expiry, or use a non-exclusive reservation when appropriate.
83
+ - Auth errors: if JWT+JWKS is enabled, include a bearer token with a `kid` that matches server JWKS; static bearer is used only when JWT is disabled.
84
+
85
+ ## Integrating with Beads (dependency-aware task planning)
86
+
87
+ Beads provides a lightweight, dependency-aware issue database and a CLI (`bd`) for selecting "ready work," setting priorities, and tracking status. It complements MCP Agent Mail's messaging, audit trail, and file-reservation signals. Project: [steveyegge/beads](https://github.com/steveyegge/beads)
88
+
89
+ Recommended conventions
90
+
91
+ - **Single source of truth**: Use **Beads** for task status/priority/dependencies; use **Agent Mail** for conversation, decisions, and attachments (audit).
92
+ - **Shared identifiers**: Use the Beads issue id (e.g., `bd-123`) as the Mail `thread_id` and prefix message subjects with `[bd-123]`.
93
+ - **Reservations**: When starting a `bd-###` task, call `file_reservation_paths(...)` for the affected paths; include the issue id in the `reason` and release on completion.
94
+
95
+ Typical flow (agents)
96
+
97
+ 1. **Pick ready work** (Beads)
98
+ - `bd ready --json` → choose one item (highest priority, no blockers)
99
+ 2. **Reserve edit surface** (Mail)
100
+ - `file_reservation_paths(project_key, agent_name, ["src/**"], ttl_seconds=3600, exclusive=true, reason="bd-123")`
101
+ 3. **Announce start** (Mail)
102
+ - `send_message(..., thread_id="bd-123", subject="[bd-123] Start: <short title>", ack_required=true)`
103
+ 4. **Work and update**
104
+ - Reply in-thread with progress and attach artifacts/images; keep the discussion in one thread per issue id
105
+ 5. **Complete and release**
106
+ - `bd close bd-123 --reason "Completed"` (Beads is status authority)
107
+ - `release_file_reservations(project_key, agent_name, paths=["src/**"])`
108
+ - Final Mail reply: `[bd-123] Completed` with summary and links
109
+
110
+ Mapping cheat-sheet
111
+
112
+ - **Mail `thread_id`** ↔ `bd-###`
113
+ - **Mail subject**: `[bd-###] …`
114
+ - **File reservation `reason`**: `bd-###`
115
+ - **Commit messages (optional)**: include `bd-###` for traceability
116
+
117
+ Event mirroring (optional automation)
118
+
119
+ - On `bd update --status blocked`, send a high-importance Mail message in thread `bd-###` describing the blocker.
120
+ - On Mail "ACK overdue" for a critical decision, add a Beads label (e.g., `needs-ack`) or bump priority to surface it in `bd ready`.
121
+
122
+ Pitfalls to avoid
123
+
124
+ - Don't create or manage tasks in Mail; treat Beads as the single task queue.
125
+ - Always include `bd-###` in message `thread_id` to avoid ID drift across tools.
126
+
127
+ <!-- MCP_AGENT_MAIL_AND_BEADS_SNIPPET_END -->
@@ -1,5 +1,7 @@
1
1
  # AGENTS.md - **APP_NAME**
2
2
 
3
+ > **Main Documentation**: [Kuckit SDK](https://github.com/draphonix/kuckit)
4
+
3
5
  ## Quick Start
4
6
 
5
7
  ```bash
@@ -26,6 +28,90 @@ __APP_NAME_KEBAB__/
26
28
 
27
29
  **Note:** Core packages (`api`, `auth`, `db`, `domain`, `contracts`) are installed from npm as `@kuckit/*` dependencies, not copied into your project.
28
30
 
31
+ ## Bootstrap Architecture
32
+
33
+ Kuckit uses **bootstrap packages** to minimize boilerplate in your apps:
34
+
35
+ ### Server Bootstrap (`@kuckit/app-server`)
36
+
37
+ ```typescript
38
+ // apps/server/src/server.ts
39
+ import 'dotenv/config'
40
+ import { runKuckitServer } from '@kuckit/app-server'
41
+ import { loadConfig } from './config/server'
42
+ import { getModuleSpecs } from './config/modules'
43
+
44
+ runKuckitServer({
45
+ loadConfig,
46
+ getModuleSpecs,
47
+ }).catch((error) => {
48
+ console.error('Failed to start server:', error)
49
+ process.exit(1)
50
+ })
51
+ ```
52
+
53
+ **What `runKuckitServer` handles automatically:**
54
+
55
+ - Express app creation with CORS, JSON parsing
56
+ - DI container setup with per-request scoping
57
+ - Module loading and API route wiring
58
+ - Auth, health, metrics endpoints
59
+ - Graceful shutdown
60
+
61
+ **Customization via hooks:**
62
+
63
+ ```typescript
64
+ runKuckitServer({
65
+ loadConfig,
66
+ getModuleSpecs,
67
+ hooks: {
68
+ onAppCreated: (app) => app.use(helmet()),
69
+ onContainerReady: (container) => {
70
+ /* warm caches */
71
+ },
72
+ onServerReady: (port) => console.log(`Listening on ${port}`),
73
+ },
74
+ })
75
+ ```
76
+
77
+ ### Web Bootstrap (`@kuckit/app-web`)
78
+
79
+ ```typescript
80
+ // apps/web/src/main.tsx
81
+ import { createKuckitWebProvider } from '@kuckit/app-web'
82
+ import { createAuthClient } from 'better-auth/react'
83
+ import config from '../kuckit.config'
84
+
85
+ const authClient = createAuthClient({
86
+ baseURL: import.meta.env.VITE_API_URL,
87
+ })
88
+
89
+ const KuckitProvider = createKuckitWebProvider({
90
+ config,
91
+ authClient,
92
+ })
93
+
94
+ ReactDOM.createRoot(document.getElementById('root')!).render(
95
+ <StrictMode>
96
+ <KuckitProvider>
97
+ <App />
98
+ </KuckitProvider>
99
+ </StrictMode>
100
+ )
101
+ ```
102
+
103
+ **Access registries and auth via hooks:**
104
+
105
+ ```typescript
106
+ import { useKuckitWeb, useAuth } from '@kuckit/app-web'
107
+
108
+ function MyComponent() {
109
+ const { routeRegistry, navRegistry, slotRegistry } = useKuckitWeb()
110
+ const authClient = useAuth()
111
+ const { data: session } = authClient.useSession()
112
+ }
113
+ ```
114
+
29
115
  ## Module Development
30
116
 
31
117
  Kuckit uses a **module-based architecture** where each module contains its own Clean Architecture layers internally.
@@ -8,111 +8,68 @@ Express backend hosting oRPC API, Better-Auth authentication, and the Kuckit mod
8
8
 
9
9
  ## Key Files
10
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
- | `rpc-router-registry.ts` | Mutable router for modules |
18
- | `rest-router-registry.ts` | REST router collection |
19
- | `module-rest-routes.ts` | REST router wiring |
20
- | `auth.ts` | Better-Auth configuration |
11
+ | File | Purpose |
12
+ | ------------ | ------------------------------------------------- |
13
+ | `server.ts` | Entry point (9 lines) |
14
+ | `config.ts` | Server configuration |
15
+ | `modules.ts` | Module registration (reads from kuckit.config.ts) |
21
16
 
22
- ## Module Loading Sequence
17
+ ## How It Works
23
18
 
24
- The server bootstraps in this order:
25
-
26
- ```
27
- 1. createKuckitContainer() - Core services (db, logger, cache, etc.)
28
- 2. loadKuckitModules() with onApiRegistrations callback:
29
- ├─► register() hooks run (DI bindings)
30
- ├─► registerApi() hooks run (routers collected)
31
- ├─► onApiRegistrations() - Wire RPC and REST routers
32
- └─► onBootstrap() hooks run (startup logic)
33
- 3. setupRPC() - Create RPCHandler AFTER modules loaded
34
- 4. setupModuleRestRouters() - Mount REST routers to Express
35
- 5. Express listens
36
- ```
37
-
38
- ## Router Registry Pattern
39
-
40
- oRPC's `RPCHandler` captures the router at construction time. Modules wire their routers into a **mutable object** before the handler is created:
41
-
42
- ```typescript
43
- // rpc-router-registry.ts
44
- export const rootRpcRouter = { ...appRouter }
45
-
46
- export const wireModuleRpcRouters = (registrations: ApiRegistration[]) => {
47
- for (const reg of registrations) {
48
- if (reg.type === 'rpc-router') {
49
- rootRpcRouter[reg.name] = reg.router
50
- }
51
- }
52
- }
53
- ```
19
+ The server uses `@kuckit/app-server` which handles all the complexity internally:
54
20
 
55
21
  ```typescript
56
22
  // server.ts
57
- await loadKuckitModules({
58
- container,
59
- modules: getModuleSpecs(),
60
- onApiRegistrations: (registrations) => {
61
- wireModuleRpcRouters(registrations) // Wire BEFORE setupRPC()
62
- collectModuleRestRouters(registrations) // Collect REST routers
63
- },
64
- })
65
-
66
- setupRPC(app) // Now create handler with fully-wired router
67
- setupModuleRestRouters(app) // Mount REST routers at /api/<name>
68
- ```
69
-
70
- ## REST Router Pattern
23
+ import 'dotenv/config'
24
+ import { runKuckitServer } from '@kuckit/app-server'
25
+ import { loadConfig } from './config'
26
+ import { getModuleSpecs } from './modules'
71
27
 
72
- For modules that need direct Express response access (e.g., AI streaming), use REST routers:
73
-
74
- ```typescript
75
- // In your module's registerApi()
76
- ctx.addApiRegistration({
77
- type: 'rest-router',
78
- name: 'ai',
79
- router: createAiRouter(),
80
- prefix: '/ai', // Optional, defaults to /<name>
81
- })
28
+ runKuckitServer({ loadConfig, getModuleSpecs }).catch(console.error)
82
29
  ```
83
30
 
84
- REST routers are mounted at `/api<prefix>` (e.g., `/api/ai/chat`). They receive:
85
-
86
- - Per-request scoped container via `req.scope`
87
- - Session via `req.scope.cradle.session`
88
- - Full Express `Request` and `Response` objects
31
+ The `@kuckit/app-server` package handles:
89
32
 
90
- ## Per-Request Scoping
33
+ - DI container creation and setup
34
+ - Module loading with proper lifecycle hooks
35
+ - RPC router wiring (oRPC)
36
+ - REST router mounting
37
+ - Authentication (Better-Auth)
38
+ - Health endpoints
39
+ - Graceful shutdown
91
40
 
92
- Each HTTP request gets a scoped container with:
41
+ ## Adding New Modules
93
42
 
94
- - `requestId` - Unique request identifier
95
- - `requestLogger` - Logger with request context
96
- - `session` - Current user session (if authenticated)
43
+ **`kuckit.config.ts` is the single source of truth for modules.**
97
44
 
98
- Access scoped services in routers via `context.di.cradle`.
45
+ 1. Add to `kuckit.config.ts` (at project root):
99
46
 
100
- ## Adding New Modules
47
+ ```typescript
48
+ export default defineConfig({
49
+ modules: [
50
+ { package: '@__APP_NAME_KEBAB__/items-module' },
51
+ { package: '@acme/billing-module' }, // Add new module here
52
+ ],
53
+ })
54
+ ```
101
55
 
102
- 1. Install the module package
103
- 2. Add to `config/modules.ts`:
56
+ 2. Add import and mapping to `modules.ts`:
104
57
 
105
58
  ```typescript
106
- import { kuckitModule as myModule } from '@__APP_NAME_KEBAB__/my-module'
107
-
108
- export const getModuleSpecs = () => [
109
- { module: itemsModule },
110
- { module: myModule }, // Add here
111
- ]
59
+ import { kuckitModule as billingModule } from '@acme/billing-module'
60
+
61
+ const KNOWN_MODULES = {
62
+ // ...existing
63
+ '@acme/billing-module': {
64
+ module: billingModule,
65
+ },
66
+ }
112
67
  ```
113
68
 
114
69
  3. Restart the server
115
70
 
71
+ The CLI command `bunx kuckit add @acme/billing-module` automates both steps.
72
+
116
73
  ## Environment Variables
117
74
 
118
75
  See `.env.example` in this directory.
@@ -5,27 +5,15 @@
5
5
  "scripts": {
6
6
  "build": "tsdown",
7
7
  "check-types": "tsc -b",
8
- "dev": "bun run --hot src/server.ts"
8
+ "dev": "kuckit dev"
9
9
  },
10
10
  "dependencies": {
11
- "express": "^5.1.0",
12
- "cors": "^2.8.5",
13
11
  "dotenv": "^17.0.0",
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.0",
19
- "zod": "^3.23.0",
12
+ "@kuckit/app-server": "^2.0.0",
20
13
  "@kuckit/sdk": "^2.0.0",
21
- "@kuckit/api": "^2.0.0",
22
- "@kuckit/auth": "^2.0.0",
23
14
  "@kuckit/db": "^2.0.0"
24
15
  },
25
16
  "devDependencies": {
26
- "@types/express": "^5.0.1",
27
- "@types/cors": "^2.8.17",
28
- "@types/pg": "^8.11.11",
29
17
  "typescript": "^5.8.2",
30
18
  "tsdown": "^0.15.5"
31
19
  }
@@ -0,0 +1,12 @@
1
+ import { ensureDatabaseUrl } from '@kuckit/db/connection'
2
+ import type { KuckitServerConfig } from '@kuckit/app-server'
3
+
4
+ export const loadConfig = (): KuckitServerConfig => ({
5
+ databaseUrl: ensureDatabaseUrl(),
6
+ enableFileLogging: process.env.ENABLE_FILE_LOGGING === 'true',
7
+ logDir: process.env.LOG_DIR || './logs',
8
+ logLevel: (process.env.LOG_LEVEL || 'INFO') as 'DEBUG' | 'INFO' | 'WARN' | 'ERROR',
9
+ env: process.env.NODE_ENV || 'development',
10
+ port: parseInt(process.env.PORT || '3000', 10),
11
+ corsOrigin: process.env.CORS_ORIGIN || 'http://localhost:3001',
12
+ })
@@ -0,0 +1,66 @@
1
+ import type { ModuleSpec, KuckitConfig } from '@kuckit/sdk'
2
+ import { tryLoadKuckitConfig } from '@kuckit/sdk'
3
+ import { kuckitModule as itemsModule } from '@__APP_NAME_KEBAB__/items-module'
4
+
5
+ /**
6
+ * Known modules mapping: package name → direct module import
7
+ *
8
+ * This enables config-driven module loading while keeping direct imports
9
+ * for workspace packages (required for monorepo compatibility).
10
+ *
11
+ * When adding a new module:
12
+ * 1. Add to kuckit.config.ts (source of truth)
13
+ * 2. Add import and mapping here
14
+ */
15
+ const KNOWN_MODULES: Record<string, { module: unknown; defaultConfig?: unknown }> = {
16
+ // KUCKIT_KNOWN_MODULES_START
17
+ '@__APP_NAME_KEBAB__/items-module': {
18
+ module: itemsModule,
19
+ },
20
+ // KUCKIT_KNOWN_MODULES_END
21
+ }
22
+
23
+ /**
24
+ * Convert unified config to ModuleSpec array.
25
+ * For known modules, uses direct imports. For npm packages, uses package-based loading.
26
+ */
27
+ function configToModuleSpecs(config: KuckitConfig): ModuleSpec[] {
28
+ return config.modules
29
+ .filter((m) => m.enabled !== false)
30
+ .map((m) => {
31
+ const known = KNOWN_MODULES[m.package]
32
+ if (known) {
33
+ return {
34
+ module: known.module,
35
+ config: m.config ?? known.defaultConfig,
36
+ } as ModuleSpec
37
+ }
38
+ // For npm packages, use package-based loading
39
+ return {
40
+ package: m.package,
41
+ config: m.config,
42
+ } as ModuleSpec
43
+ })
44
+ }
45
+
46
+ /**
47
+ * Fallback module specs (used when kuckit.config.ts is not found)
48
+ */
49
+ const getFallbackModuleSpecs = (): ModuleSpec[] => [{ module: itemsModule }]
50
+
51
+ /**
52
+ * Get module specs from kuckit.config.ts (single source of truth).
53
+ * Falls back to direct module specs if config is not found.
54
+ */
55
+ export const getModuleSpecs = async (): Promise<ModuleSpec[]> => {
56
+ const config = await tryLoadKuckitConfig()
57
+
58
+ if (config) {
59
+ console.log(`[kuckit] Loading modules from: ${config._configPath}`)
60
+ return configToModuleSpecs(config)
61
+ }
62
+
63
+ // Fallback for legacy projects without kuckit.config.ts
64
+ console.log('[kuckit] No config found, using fallback module specs')
65
+ return getFallbackModuleSpecs()
66
+ }
@@ -1,51 +1,9 @@
1
1
  import 'dotenv/config'
2
- import { createApp } from './app'
3
- import { setupContainerMiddleware, getRootContainer } from './middleware/container'
4
- import { setupAuth } from './auth'
5
- import { setupRPC } from './rpc'
6
- import { setupModuleRestRouters } from './module-rest-routes'
7
- import { setupHealth } from './health'
8
- import { disposeContainer } from './container'
2
+ import { runKuckitServer } from '@kuckit/app-server'
3
+ import { loadConfig } from './config'
4
+ import { getModuleSpecs } from './modules'
9
5
 
10
- /**
11
- * Bootstrap and start server
12
- */
13
- const bootstrap = async () => {
14
- const app = createApp()
15
-
16
- await setupContainerMiddleware(app)
17
- const rootContainer = getRootContainer()
18
-
19
- setupAuth(app)
20
- setupRPC(app)
21
- setupModuleRestRouters(app)
22
- setupHealth(app, rootContainer)
23
-
24
- const port = process.env.PORT || 3000
25
- const server = app.listen(port, () => {
26
- console.log(`Server is running on port ${port}`)
27
- })
28
-
29
- const shutdown = async () => {
30
- console.log('Shutting down gracefully...')
31
-
32
- server.close(async () => {
33
- await disposeContainer(rootContainer)
34
- console.log('Server closed')
35
- process.exit(0)
36
- })
37
-
38
- setTimeout(() => {
39
- console.error('Forced shutdown')
40
- process.exit(1)
41
- }, 10000)
42
- }
43
-
44
- process.on('SIGTERM', shutdown)
45
- process.on('SIGINT', shutdown)
46
- }
47
-
48
- bootstrap().catch((error) => {
6
+ runKuckitServer({ loadConfig, getModuleSpecs }).catch((error) => {
49
7
  console.error('Failed to start server:', error)
50
8
  process.exit(1)
51
9
  })