create-kuckit-app 0.1.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/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # create-kuckit-app
2
+
3
+ Create a new Kuckit application with a single command.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ npx create-kuckit-app my-app
9
+ cd my-app
10
+ bun run dev
11
+ ```
12
+
13
+ ## Prerequisites
14
+
15
+ - Node.js 18+
16
+ - [Bun](https://bun.sh) package manager
17
+ - A Kuckit account at [kuckit.dev](https://kuckit.dev)
18
+
19
+ ## Authentication
20
+
21
+ You need to authenticate before creating a project:
22
+
23
+ ```bash
24
+ npx @kuckit/cli auth login
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ ```bash
30
+ npx create-kuckit-app <project-name> [options]
31
+ ```
32
+
33
+ ### Options
34
+
35
+ - `--skip-install` - Skip running package manager install
36
+ - `--template <template>` - Template to use (default: `base`)
37
+
38
+ ## What's Included
39
+
40
+ The generated project includes:
41
+
42
+ - **Monorepo structure** with apps and packages
43
+ - **Server** - Express + oRPC API with Better-Auth
44
+ - **Web** - React + TanStack Router frontend
45
+ - **Database** - Drizzle ORM with PostgreSQL
46
+ - **Kuckit SDK** - Module system ready to go
47
+
48
+ ## Project Structure
49
+
50
+ ```
51
+ my-app/
52
+ ├── apps/
53
+ │ ├── server/ # Backend API
54
+ │ └── web/ # Frontend app
55
+ ├── packages/ # Shared packages & modules
56
+ └── kuckit.config.ts
57
+ ```
58
+
59
+ ## Next Steps
60
+
61
+ After creating your app:
62
+
63
+ 1. Set up your database (see `packages/db/docker-compose.yml`)
64
+ 2. Run migrations: `bun run db:push`
65
+ 3. Start development: `bun run dev`
66
+ 4. Add modules: `npx @kuckit/cli add <module>`
67
+
68
+ ## License
69
+
70
+ MIT
package/dist/bin.d.ts ADDED
@@ -0,0 +1 @@
1
+ export { };
package/dist/bin.js ADDED
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env node
2
+ import { t as createProject } from "./create-project-DTm05G7D.js";
3
+ import { program } from "commander";
4
+ import { join } from "node:path";
5
+ import { existsSync, readFileSync } from "node:fs";
6
+ import { homedir } from "node:os";
7
+
8
+ //#region src/lib/require-auth.ts
9
+ const CONFIG_PATH = join(homedir(), ".kuckit", "config.json");
10
+ function loadConfig() {
11
+ try {
12
+ if (!existsSync(CONFIG_PATH)) return null;
13
+ const content = readFileSync(CONFIG_PATH, "utf-8");
14
+ return JSON.parse(content);
15
+ } catch {
16
+ return null;
17
+ }
18
+ }
19
+ function isTokenExpired(config) {
20
+ if (!config.tokenExpiresAt) return false;
21
+ return new Date(config.tokenExpiresAt) < /* @__PURE__ */ new Date();
22
+ }
23
+ /**
24
+ * Checks if the user is authenticated with a valid token.
25
+ * Exits the process with an error message if not authenticated.
26
+ */
27
+ function requireAuth() {
28
+ const config = loadConfig();
29
+ if (!config?.cliToken) {
30
+ console.error("\nError: Not logged in. Run 'kuckit auth login' first.\n");
31
+ process.exit(1);
32
+ }
33
+ if (isTokenExpired(config)) {
34
+ console.error("\nError: Session expired. Run 'kuckit auth login' to refresh.\n");
35
+ process.exit(1);
36
+ }
37
+ }
38
+
39
+ //#endregion
40
+ //#region src/bin.ts
41
+ program.name("create-kuckit-app").description("Create a new Kuckit application").version("0.1.0").argument("<project-name>", "Name of the project to create").option("--skip-install", "Skip running package manager install", false).option("--template <template>", "Template to use", "base").action(async (projectName, options) => {
42
+ requireAuth();
43
+ await createProject(projectName, options);
44
+ });
45
+ program.parse();
46
+
47
+ //#endregion
48
+ export { };
@@ -0,0 +1,85 @@
1
+ import { mkdir, readFile, readdir, stat, writeFile } from "node:fs/promises";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { execSync } from "node:child_process";
5
+
6
+ //#region src/create-project.ts
7
+ const __dirname = dirname(fileURLToPath(import.meta.url));
8
+ async function copyDir(src, dest, replacements) {
9
+ await mkdir(dest, { recursive: true });
10
+ const entries = await readdir(src, { withFileTypes: true });
11
+ for (const entry of entries) {
12
+ const srcPath = join(src, entry.name);
13
+ const destPath = join(dest, entry.name.replace(/__APP_NAME__/g, replacements["__APP_NAME__"]));
14
+ if (entry.isDirectory()) await copyDir(srcPath, destPath, replacements);
15
+ else {
16
+ let processed = await readFile(srcPath, "utf-8");
17
+ for (const [placeholder, value] of Object.entries(replacements)) processed = processed.replace(new RegExp(placeholder, "g"), value);
18
+ await writeFile(destPath, processed);
19
+ }
20
+ }
21
+ }
22
+ async function createProject(name, options) {
23
+ const targetDir = join(process.cwd(), name);
24
+ console.log(`\nCreating Kuckit app: ${name}`);
25
+ console.log(` Directory: ${targetDir}\n`);
26
+ let templateDir = join(__dirname, "..", "templates", options.template);
27
+ try {
28
+ await stat(templateDir);
29
+ } catch {
30
+ templateDir = join(__dirname, "templates", options.template);
31
+ }
32
+ try {
33
+ await stat(templateDir);
34
+ } catch {
35
+ console.error(`Error: Template "${options.template}" not found.`);
36
+ console.error(`Looked in: ${templateDir}`);
37
+ process.exit(1);
38
+ }
39
+ const replacements = {
40
+ __APP_NAME__: name,
41
+ __APP_NAME_LOWER__: name.toLowerCase(),
42
+ __APP_NAME_KEBAB__: name.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase()
43
+ };
44
+ console.log(" Copying template files...");
45
+ await copyDir(templateDir, targetDir, replacements);
46
+ console.log(" Initializing git repository...");
47
+ try {
48
+ execSync("git init", {
49
+ cwd: targetDir,
50
+ stdio: "ignore"
51
+ });
52
+ } catch {
53
+ console.warn(" Warning: Could not initialize git repository");
54
+ }
55
+ if (!options.skipInstall) {
56
+ console.log(" Installing dependencies...");
57
+ try {
58
+ execSync("bun install", {
59
+ cwd: targetDir,
60
+ stdio: "inherit"
61
+ });
62
+ } catch {
63
+ console.warn(" Warning: Could not install dependencies. Run \"bun install\" manually.");
64
+ }
65
+ }
66
+ console.log(`
67
+ Success! Created ${name} at ${targetDir}
68
+
69
+ Inside that directory, you can run:
70
+
71
+ bun run dev Start the development server
72
+ bun run build Build for production
73
+ bun run check-types Run type checking
74
+
75
+ We suggest that you begin by typing:
76
+
77
+ cd ${name}
78
+ bun run dev
79
+
80
+ Happy hacking!
81
+ `);
82
+ }
83
+
84
+ //#endregion
85
+ export { createProject as t };
@@ -0,0 +1,8 @@
1
+ //#region src/create-project.d.ts
2
+ interface CreateProjectOptions {
3
+ skipInstall: boolean;
4
+ template: string;
5
+ }
6
+ declare function createProject(name: string, options: CreateProjectOptions): Promise<void>;
7
+ //#endregion
8
+ export { createProject };
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ import { t as createProject } from "./create-project-DTm05G7D.js";
2
+
3
+ export { createProject };
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "create-kuckit-app",
3
+ "version": "0.1.0",
4
+ "description": "Create a new Kuckit application",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/draphonix/kuckit.git",
10
+ "directory": "packages/create-kuckit-app"
11
+ },
12
+ "homepage": "https://kuckit.dev",
13
+ "bugs": "https://github.com/draphonix/kuckit/issues",
14
+ "keywords": [
15
+ "kuckit",
16
+ "create",
17
+ "app",
18
+ "scaffolding",
19
+ "fullstack",
20
+ "starter"
21
+ ],
22
+ "engines": {
23
+ "node": ">=18"
24
+ },
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "bin": {
29
+ "create-kuckit-app": "dist/bin.js"
30
+ },
31
+ "files": [
32
+ "dist",
33
+ "templates"
34
+ ],
35
+ "exports": {
36
+ ".": {
37
+ "types": "./dist/index.d.ts",
38
+ "default": "./dist/index.js"
39
+ }
40
+ },
41
+ "scripts": {
42
+ "build": "tsdown"
43
+ },
44
+ "dependencies": {
45
+ "commander": "^13.1.0"
46
+ },
47
+ "devDependencies": {
48
+ "@types/node": "^22.13.13",
49
+ "tsdown": "catalog:"
50
+ }
51
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "__APP_NAME_KEBAB__-server",
3
+ "type": "module",
4
+ "scripts": {
5
+ "build": "tsdown",
6
+ "check-types": "tsc -b",
7
+ "dev": "bun run --hot src/server.ts"
8
+ },
9
+ "dependencies": {
10
+ "@kuckit/sdk": "^0.1.0",
11
+ "@kuckit/users-module": "^0.1.0",
12
+ "express": "^5.1.0",
13
+ "cors": "^2.8.5",
14
+ "dotenv": "^17.2.2",
15
+ "awilix": "^12.0.5"
16
+ },
17
+ "devDependencies": {
18
+ "@types/express": "^5.0.1",
19
+ "@types/cors": "^2.8.17",
20
+ "typescript": "^5.8.2",
21
+ "tsdown": "^0.15.5"
22
+ }
23
+ }
@@ -0,0 +1,14 @@
1
+ import type { ModuleSpec } from '@kuckit/sdk'
2
+ import { kuckitModule as usersModule } from '@kuckit/users-module'
3
+
4
+ export const getModuleSpecs = (): ModuleSpec[] => {
5
+ const modules: ModuleSpec[] = [
6
+ { module: usersModule },
7
+
8
+ // KUCKIT_MODULES_START
9
+ // Modules installed via 'kuckit add' will be added here
10
+ // KUCKIT_MODULES_END
11
+ ]
12
+
13
+ return modules
14
+ }
@@ -0,0 +1,39 @@
1
+ import 'dotenv/config'
2
+ import express from 'express'
3
+ import cors from 'cors'
4
+ import { createKuckitContainer, loadKuckitModules } from '@kuckit/sdk'
5
+ import { getModuleSpecs } from './config/modules.js'
6
+
7
+ const app = express()
8
+ const port = process.env.PORT ?? 3000
9
+
10
+ app.use(cors())
11
+ app.use(express.json())
12
+
13
+ async function bootstrap() {
14
+ // Create DI container
15
+ const container = createKuckitContainer({
16
+ env: process.env.NODE_ENV ?? 'development',
17
+ })
18
+
19
+ // Load modules
20
+ await loadKuckitModules({
21
+ container,
22
+ env: process.env.NODE_ENV ?? 'development',
23
+ modules: getModuleSpecs(),
24
+ onComplete: () => {
25
+ console.log('All modules loaded')
26
+ },
27
+ })
28
+
29
+ // Health check
30
+ app.get('/health', (_req, res) => {
31
+ res.json({ status: 'ok' })
32
+ })
33
+
34
+ app.listen(port, () => {
35
+ console.log(`Server running at http://localhost:${port}`)
36
+ })
37
+ }
38
+
39
+ bootstrap().catch(console.error)
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "outDir": "dist",
5
+ "rootDir": "src"
6
+ },
7
+ "include": ["src"]
8
+ }
@@ -0,0 +1,12 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>__APP_NAME__</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ <script type="module" src="/src/main.tsx"></script>
11
+ </body>
12
+ </html>
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "__APP_NAME_KEBAB__-web",
3
+ "type": "module",
4
+ "scripts": {
5
+ "dev": "vite --port=3001",
6
+ "build": "vite build",
7
+ "check-types": "tsc --noEmit"
8
+ },
9
+ "dependencies": {
10
+ "@kuckit/sdk-react": "^0.1.0",
11
+ "@tanstack/react-query": "^5.85.5",
12
+ "react": "^19.1.0",
13
+ "react-dom": "^19.1.0"
14
+ },
15
+ "devDependencies": {
16
+ "@types/react": "~19.1.10",
17
+ "@types/react-dom": "^19.0.4",
18
+ "@vitejs/plugin-react": "^4.3.4",
19
+ "typescript": "^5.8.2",
20
+ "vite": "^6.2.2"
21
+ }
22
+ }
@@ -0,0 +1,16 @@
1
+ export function App() {
2
+ return (
3
+ <div style={{ fontFamily: 'system-ui', padding: '2rem' }}>
4
+ <h1>Welcome to __APP_NAME__</h1>
5
+ <p>Your Kuckit application is ready!</p>
6
+ <ul>
7
+ <li>
8
+ Server: <a href="http://localhost:3000/health">http://localhost:3000/health</a>
9
+ </li>
10
+ <li>
11
+ Web: <a href="http://localhost:3001">http://localhost:3001</a>
12
+ </li>
13
+ </ul>
14
+ </div>
15
+ )
16
+ }
@@ -0,0 +1,14 @@
1
+ import { StrictMode } from 'react'
2
+ import { createRoot } from 'react-dom/client'
3
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
4
+ import { App } from './App.js'
5
+
6
+ const queryClient = new QueryClient()
7
+
8
+ createRoot(document.getElementById('root')!).render(
9
+ <StrictMode>
10
+ <QueryClientProvider client={queryClient}>
11
+ <App />
12
+ </QueryClientProvider>
13
+ </StrictMode>
14
+ )
@@ -0,0 +1,16 @@
1
+ import type { ClientModuleSpec } from '@kuckit/sdk-react'
2
+
3
+ /**
4
+ * Client modules configuration
5
+ *
6
+ * Modules installed via 'kuckit add' will be added here automatically.
7
+ */
8
+ export const getClientModuleSpecs = (): ClientModuleSpec[] => {
9
+ const modules: ClientModuleSpec[] = [
10
+ // KUCKIT_MODULES_START
11
+ // Client modules will be added here
12
+ // KUCKIT_MODULES_END
13
+ ]
14
+
15
+ return modules
16
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "lib": ["DOM", "DOM.Iterable", "ESNext"],
5
+ "jsx": "react-jsx",
6
+ "noEmit": true
7
+ },
8
+ "include": ["src"]
9
+ }
@@ -0,0 +1,6 @@
1
+ import { defineConfig } from 'vite'
2
+ import react from '@vitejs/plugin-react'
3
+
4
+ export default defineConfig({
5
+ plugins: [react()],
6
+ })
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "__APP_NAME_KEBAB__",
3
+ "private": true,
4
+ "type": "module",
5
+ "workspaces": [
6
+ "apps/*",
7
+ "packages/*"
8
+ ],
9
+ "scripts": {
10
+ "dev": "turbo dev",
11
+ "build": "turbo build",
12
+ "check-types": "turbo check-types"
13
+ },
14
+ "devDependencies": {
15
+ "turbo": "^2.5.4",
16
+ "typescript": "^5.8.2"
17
+ },
18
+ "packageManager": "bun@1.2.21"
19
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "esModuleInterop": true,
7
+ "skipLibCheck": true,
8
+ "strict": true,
9
+ "declaration": true,
10
+ "declarationMap": true,
11
+ "sourceMap": true,
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "noUnusedLocals": true,
15
+ "noUnusedParameters": true,
16
+ "noFallthroughCasesInSwitch": true,
17
+ "verbatimModuleSyntax": true
18
+ }
19
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "$schema": "https://turbo.build/schema.json",
3
+ "tasks": {
4
+ "build": {
5
+ "dependsOn": ["^build"],
6
+ "outputs": ["dist/**"]
7
+ },
8
+ "dev": {
9
+ "cache": false,
10
+ "persistent": true
11
+ },
12
+ "check-types": {
13
+ "dependsOn": ["^build"]
14
+ }
15
+ }
16
+ }