@totaland/create-starter-kit 2.0.0 → 2.0.2

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 (48) hide show
  1. package/README.md +27 -3
  2. package/bin/index.js +88 -30
  3. package/package.json +1 -1
  4. package/templates/backend/AGENTS.md +0 -23
  5. package/templates/backend/ARCHITECTURE.md +0 -53
  6. package/templates/backend/ORDER_SYSTEM.md +0 -93
  7. package/templates/backend/biome.json +0 -3
  8. package/templates/backend/drizzle.config.ts +0 -10
  9. package/templates/backend/knip.json +0 -10
  10. package/templates/backend/package.json +0 -55
  11. package/templates/backend/playwright.config.ts +0 -16
  12. package/templates/backend/pnpm-workspace.yaml +0 -3
  13. package/templates/backend/src/features/health/controller.ts +0 -5
  14. package/templates/backend/src/features/health/index.ts +0 -6
  15. package/templates/backend/src/features/orders/controller.ts +0 -13
  16. package/templates/backend/src/features/orders/index.ts +0 -7
  17. package/templates/backend/src/index.ts +0 -76
  18. package/templates/backend/tsconfig.build.json +0 -10
  19. package/templates/backend/tsconfig.json +0 -30
  20. package/templates/backend/vitest.config.ts +0 -24
  21. package/templates/frontend/.env.example +0 -7
  22. package/templates/frontend/README.md +0 -132
  23. package/templates/frontend/RECOMMENDED_LIBRARIES.md +0 -226
  24. package/templates/frontend/SETUP_SUMMARY.md +0 -162
  25. package/templates/frontend/biome.json +0 -47
  26. package/templates/frontend/components.json +0 -22
  27. package/templates/frontend/index.html +0 -13
  28. package/templates/frontend/package.json +0 -44
  29. package/templates/frontend/postcss.config.js +0 -6
  30. package/templates/frontend/public/vite.svg +0 -1
  31. package/templates/frontend/src/App.css +0 -42
  32. package/templates/frontend/src/App.tsx +0 -17
  33. package/templates/frontend/src/assets/react.svg +0 -1
  34. package/templates/frontend/src/components/layout/Layout.tsx +0 -31
  35. package/templates/frontend/src/components/menu-toggle-icon.tsx +0 -53
  36. package/templates/frontend/src/components/ui/button.tsx +0 -57
  37. package/templates/frontend/src/hooks/use-scroll.ts +0 -21
  38. package/templates/frontend/src/index.css +0 -121
  39. package/templates/frontend/src/lib/api-client.ts +0 -46
  40. package/templates/frontend/src/lib/utils.ts +0 -6
  41. package/templates/frontend/src/main.tsx +0 -30
  42. package/templates/frontend/src/pages/about/AboutPage.tsx +0 -50
  43. package/templates/frontend/src/pages/home/HomePage.tsx +0 -43
  44. package/templates/frontend/tailwind.config.js +0 -59
  45. package/templates/frontend/tsconfig.app.json +0 -41
  46. package/templates/frontend/tsconfig.json +0 -13
  47. package/templates/frontend/tsconfig.node.json +0 -26
  48. package/templates/frontend/vite.config.ts +0 -14
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # @totaland/create-starter-kit
2
2
 
3
- Scaffolding tool for creating new starter-kit projects with a choice between backend and frontend templates.
3
+ Scaffolding tool for creating new starter-kit projects with a choice between backend, frontend, or fullstack templates.
4
4
 
5
5
  ## Features
6
6
 
7
- - ✨ Interactive template selection (backend or frontend)
7
+ - ✨ Interactive template selection (backend, frontend, or fullstack)
8
8
  - 🎯 CLI argument support for automation
9
9
  - 📦 Clean, production-ready templates
10
10
  - 🚀 Quick project initialization
@@ -20,6 +20,7 @@ pnpm create @totaland/starter-kit my-new-project
20
20
  You'll be prompted to select a template:
21
21
  - **Backend** - Express.js + TypeScript + Drizzle ORM + Scalar API docs
22
22
  - **Frontend** - React + Vite + TypeScript + Tailwind CSS v4 + shadcn/ui + TanStack Query
23
+ - **Fullstack** - Both Backend and Frontend in one project
23
24
 
24
25
  ### With Template Argument
25
26
 
@@ -31,6 +32,9 @@ pnpm create @totaland/starter-kit my-backend backend
31
32
 
32
33
  # Create frontend project
33
34
  pnpm create @totaland/starter-kit my-frontend frontend
35
+
36
+ # Create fullstack project (both backend and frontend)
37
+ pnpm create @totaland/starter-kit my-app fullstack
34
38
  ```
35
39
 
36
40
  ### Alternative Package Managers
@@ -107,10 +111,29 @@ pnpm dev
107
111
  pnpm dlx shadcn@latest add button card dialog
108
112
  ```
109
113
 
114
+ ### Fullstack Template
115
+
116
+ Creates both backend and frontend in separate subdirectories.
117
+
118
+ **After Creation:**
119
+ ```bash
120
+ cd my-app
121
+
122
+ # Run backend
123
+ cd backend
124
+ pnpm install
125
+ pnpm dev
126
+
127
+ # Run frontend (in another terminal)
128
+ cd frontend
129
+ pnpm install
130
+ pnpm dev
131
+ ```
132
+
110
133
  ## What It Does
111
134
 
112
135
  1. ✅ Creates a new directory with your project name
113
- 2. ✅ Copies the selected template (backend or frontend)
136
+ 2. ✅ Copies the selected template (backend, frontend, or both for fullstack)
114
137
  3. ✅ Updates the `package.json` name field to match your project name
115
138
  4. ✅ Provides next steps for installation and running the project
116
139
 
@@ -139,6 +162,7 @@ To test this locally before publishing:
139
162
  # Or specify template directly
140
163
  pnpm create @totaland/starter-kit test-backend backend
141
164
  pnpm create @totaland/starter-kit test-frontend frontend
165
+ pnpm create @totaland/starter-kit test-fullstack fullstack
142
166
  ```
143
167
 
144
168
  ## Publishing
package/bin/index.js CHANGED
@@ -21,12 +21,12 @@ const templateArg = process.argv[3]; // Optional template argument
21
21
  if (!projectName) {
22
22
  console.error('Error: Please provide a project name');
23
23
  console.log('Usage: pnpm create @totaland/starter-kit <project-name> [template]');
24
- console.log('Templates: backend, frontend');
24
+ console.log('Templates: backend, frontend, fullstack');
25
25
  process.exit(1);
26
26
  }
27
27
 
28
- // Resolve paths
29
- const templatesDir = resolve(__dirname, '../templates');
28
+ // Resolve paths - use sibling directories from the starter-kit root
29
+ const monorepoRoot = resolve(__dirname, '../..');
30
30
  const targetDir = resolve(process.cwd(), projectName);
31
31
 
32
32
  // Check if target directory already exists
@@ -35,20 +35,45 @@ if (existsSync(targetDir)) {
35
35
  process.exit(1);
36
36
  }
37
37
 
38
- // Available templates
38
+ // Available templates - reference sibling directories in the monorepo
39
39
  const TEMPLATES = {
40
40
  backend: {
41
41
  name: 'Backend',
42
42
  description: 'Express.js backend with TypeScript, Drizzle ORM, and Scalar API docs',
43
- dir: 'backend',
43
+ sourceDir: join(monorepoRoot, 'backend'),
44
44
  },
45
45
  frontend: {
46
46
  name: 'Frontend',
47
47
  description: 'React + Vite with TypeScript, Tailwind CSS v4, shadcn/ui, and TanStack Query',
48
- dir: 'frontend',
48
+ sourceDir: join(monorepoRoot, 'frontend'),
49
+ },
50
+ fullstack: {
51
+ name: 'Fullstack',
52
+ description: 'Both Backend and Frontend templates combined',
53
+ sourceDirs: [
54
+ { name: 'backend', path: join(monorepoRoot, 'backend') },
55
+ { name: 'frontend', path: join(monorepoRoot, 'frontend') },
56
+ ],
49
57
  },
50
58
  };
51
59
 
60
+ // Directories and files to exclude when copying
61
+ const EXCLUDE = new Set([
62
+ 'node_modules',
63
+ '.git',
64
+ 'dist',
65
+ 'build',
66
+ '.turbo',
67
+ '.next',
68
+ '.nuxt',
69
+ '.output',
70
+ '.cache',
71
+ 'coverage',
72
+ '.env',
73
+ '.env.local',
74
+ '.DS_Store',
75
+ ]);
76
+
52
77
  // Function to recursively copy directory
53
78
  function copyDir(src, dest) {
54
79
  mkdirSync(dest, { recursive: true });
@@ -56,6 +81,11 @@ function copyDir(src, dest) {
56
81
  const entries = readdirSync(src, { withFileTypes: true });
57
82
 
58
83
  for (const entry of entries) {
84
+ // Skip excluded files and directories
85
+ if (EXCLUDE.has(entry.name)) {
86
+ continue;
87
+ }
88
+
59
89
  const srcPath = join(src, entry.name);
60
90
  const destPath = join(dest, entry.name);
61
91
 
@@ -75,10 +105,11 @@ async function promptTemplate() {
75
105
  });
76
106
 
77
107
  console.log('\n📦 Select a template:\n');
78
- console.log('1. Backend - Express.js + TypeScript + Drizzle ORM');
79
- console.log('2. Frontend - React + Vite + Tailwind CSS v4 + shadcn/ui\n');
108
+ console.log('1. Backend - Express.js + TypeScript + Drizzle ORM');
109
+ console.log('2. Frontend - React + Vite + Tailwind CSS v4 + shadcn/ui');
110
+ console.log('3. Fullstack - Both Backend and Frontend\n');
80
111
 
81
- const answer = await rl.question('Enter your choice (1 or 2): ');
112
+ const answer = await rl.question('Enter your choice (1, 2, or 3): ');
82
113
  rl.close();
83
114
 
84
115
  if (answer === '1' || answer.toLowerCase() === 'backend') {
@@ -87,6 +118,9 @@ async function promptTemplate() {
87
118
  if (answer === '2' || answer.toLowerCase() === 'frontend') {
88
119
  return 'frontend';
89
120
  }
121
+ if (answer === '3' || answer.toLowerCase() === 'fullstack') {
122
+ return 'fullstack';
123
+ }
90
124
 
91
125
  console.error('Invalid choice. Please run the command again.');
92
126
  process.exit(1);
@@ -102,7 +136,7 @@ async function main() {
102
136
  templateKey = templateArg.toLowerCase();
103
137
  if (!TEMPLATES[templateKey]) {
104
138
  console.error(`Error: Invalid template "${templateArg}"`);
105
- console.log('Available templates: backend, frontend');
139
+ console.log('Available templates: backend, frontend, fullstack');
106
140
  process.exit(1);
107
141
  }
108
142
  } else {
@@ -111,37 +145,61 @@ async function main() {
111
145
  }
112
146
 
113
147
  const template = TEMPLATES[templateKey];
114
- const templateDir = join(templatesDir, template.dir);
115
-
116
- // Verify template directory exists
117
- if (!existsSync(templateDir)) {
118
- console.error(`Error: Template directory not found: ${templateDir}`);
119
- process.exit(1);
120
- }
121
148
 
122
149
  console.log(`\n🚀 Creating ${template.name} project: ${projectName}`);
123
150
  console.log(`📁 ${template.description}\n`);
124
151
 
125
- // Copy template to target directory
126
- copyDir(templateDir, targetDir);
127
-
128
- // Update package.json with the new project name
129
- const packageJsonPath = join(targetDir, 'package.json');
130
- if (existsSync(packageJsonPath)) {
131
- const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
132
- packageJson.name = projectName;
133
- writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n');
152
+ // Handle fullstack (multiple templates) or single template
153
+ if (template.sourceDirs) {
154
+ // Fullstack: copy each template to a subdirectory
155
+ for (const { name, path: sourceDir } of template.sourceDirs) {
156
+ if (!existsSync(sourceDir)) {
157
+ console.error(`Error: Source directory not found: ${sourceDir}`);
158
+ process.exit(1);
159
+ }
160
+ const subTargetDir = join(targetDir, name);
161
+ copyDir(sourceDir, subTargetDir);
162
+
163
+ // Update package.json name for each sub-project
164
+ const packageJsonPath = join(subTargetDir, 'package.json');
165
+ if (existsSync(packageJsonPath)) {
166
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
167
+ packageJson.name = `${projectName}-${name}`;
168
+ writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n');
169
+ }
170
+ }
171
+ } else {
172
+ // Single template
173
+ if (!existsSync(template.sourceDir)) {
174
+ console.error(`Error: Source directory not found: ${template.sourceDir}`);
175
+ process.exit(1);
176
+ }
177
+ copyDir(template.sourceDir, targetDir);
178
+
179
+ // Update package.json with the new project name
180
+ const packageJsonPath = join(targetDir, 'package.json');
181
+ if (existsSync(packageJsonPath)) {
182
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
183
+ packageJson.name = projectName;
184
+ writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n');
185
+ }
134
186
  }
135
187
 
136
188
  console.log('✅ Project created successfully!\n');
137
189
  console.log('📝 Next steps:');
138
190
  console.log(` cd ${projectName}`);
139
- console.log(' pnpm install');
140
- console.log(' pnpm dev\n');
191
+ if (templateKey === 'fullstack') {
192
+ console.log(' cd backend && pnpm install && pnpm dev');
193
+ console.log(' cd frontend && pnpm install && pnpm dev\n');
194
+ } else {
195
+ console.log(' pnpm install');
196
+ console.log(' pnpm dev\n');
197
+ }
141
198
 
142
- if (templateKey === 'frontend') {
199
+ if (templateKey === 'frontend' || templateKey === 'fullstack') {
143
200
  console.log('💡 Tip: Add shadcn/ui components with:');
144
- console.log(' pnpm dlx shadcn@latest add button card dialog\n');
201
+ const cdPath = templateKey === 'fullstack' ? 'cd frontend && ' : '';
202
+ console.log(` ${cdPath}pnpm dlx shadcn@latest add button card dialog\n`);
145
203
  }
146
204
  } catch (error) {
147
205
  console.error('Error creating project:', error.message);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@totaland/create-starter-kit",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "Scaffolding tool for creating new starter-kit projects",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -1,23 +0,0 @@
1
- # Repository Guidelines
2
-
3
- ## Project Structure & Module Organization
4
- TypeScript sources live in `src/`, with graph traversal logic under `src/graph/` (crawl policy, state hashing, trajectory storage) and telemetry helpers in `src/telemetry.ts`. Example entrypoints such as `src/demo.ts` show how agents orchestrate flows. Generated JavaScript lands in `build/` (never hand-edit). Documentation and design notes are under `docs/`, and replay artifacts persist to `storage/` while running crawls or demo scripts. Keep tests adjacent to the code (for example `src/graph/xstate.test.ts`).
5
-
6
- ## Build, Test, and Development Commands
7
- - `pnpm install`: sets up dependencies for both the CLI and Playwright runtime.
8
- - `pnpm typecheck`: runs `tsc --noEmit` against `tsconfig.json` to catch type regressions early.
9
- - `pnpm build`: compiles `src/` to ESM output in `build/` via SWC; use `pnpm build:debug` when you need source maps.
10
- - `pnpm test`, `pnpm test:watch`, `pnpm test:ui`: execute the Vitest suite in batch, watch, or UI mode.
11
- - `pnpm knip`: detects unused files, exports, and dependencies—fix warnings before raising a PR.
12
-
13
- ## Coding Style & Naming Conventions
14
- Follow the repository's Biome configuration (`biome.json`) and run `npx biome check .` if needed. Use 2-space indentation, TypeScript `strict` semantics, and ECMAScript modules (`import/export`). Exported symbols and files should read as actions or nouns (`discoverState`, `persist.ts`). Tests mirror the file under test (`xstate.test.ts`). Prefer descriptive async function names reflecting their side effects.
15
-
16
- ## Testing Guidelines
17
- Vitest drives all unit and integration coverage. Name suites after the module (`describe("bfs")`) and isolate Playwright-heavy tests behind capability checks to keep CI fast. New behavior must include at least one test validating failure handling and a corresponding happy path. Run `pnpm test` locally before committing; `storage/` fixtures may be stubbed with lightweight mocks to avoid hitting real browsers.
18
-
19
- ## Commit & Pull Request Guidelines
20
- Use imperative, conventional messages observed in history (`feat:`, `chore:`, `fix:`). One logical change per commit, referencing an issue ID when relevant. Pull requests should describe motivation, summarize testing (`pnpm test` output, screenshots for Playwright interactions), and link design docs in `docs/` if expanded. Request review from an owner when touching crawl policy or telemetry layers, and ensure CI (typecheck, build, tests) passes before assignment.
21
-
22
- ## Environment & Configuration Tips
23
- Configure credentials through `.env` files consumed by Crawlee/Playwright—never hard-code tokens. For telemetry, set OpenTelemetry exporters via environment variables before running demos. Heavy crawls persist checkpoints to `storage/`; clean stale runs before committing to keep diffs focused.
@@ -1,53 +0,0 @@
1
- # Architecture Pattern Examples
2
-
3
- This starter kit demonstrates a blend of patterns from **"Designing Data-Intensive Applications"** and **"Patterns of Enterprise Application Architecture"**.
4
-
5
- ## Order System Example
6
-
7
- ### From Designing Data-Intensive Applications (DDIA):
8
-
9
- 1. **Event Sourcing** - All state changes stored as immutable events
10
- - `order.entity.ts`: Events are the source of truth
11
- - Events: `OrderCreated`, `ItemAdded`, `OrderPlaced`
12
-
13
- 2. **CQRS (Command Query Responsibility Segregation)**
14
- - Commands: `commands.usecase.ts` - Write operations that generate events
15
- - Queries: `queries.usecase.ts` - Read operations from materialized views
16
-
17
- 3. **Materialized Views** - Denormalized data for fast queries
18
- - `order.repository.impl.ts`: `readModel` maintains pre-computed summaries
19
- - User index for O(1) lookups by user ID
20
-
21
- 4. **Append-Only Log** - Event store never modifies existing data
22
- - New events are appended, never updated or deleted
23
-
24
- ### From Patterns of Enterprise Application Architecture (PEAA):
25
-
26
- 1. **Repository Pattern** - Abstract data access
27
- - `order.repository.ts`: Interface defining data operations
28
- - Separates domain logic from persistence
29
-
30
- 2. **Domain Model** - Rich business logic in entities
31
- - `order.entity.ts`: Order entity with business rules and validation
32
-
33
- 3. **Use Case / Service Layer** - Application logic orchestration
34
- - Commands and queries as separate use cases
35
- - Transaction boundaries and workflow management
36
-
37
- ## API Endpoints
38
-
39
- ```
40
- POST /orders # Create new order
41
- POST /orders/:id/items # Add item to order
42
- POST /orders/:id/place # Place order
43
- GET /orders/:id # Get order details
44
- GET /orders/user/:userId # Get user's orders (fast via materialized view)
45
- GET /orders/:id/events # Get event stream (audit log)
46
- ```
47
-
48
- ## Key Benefits
49
-
50
- - **Scalability**: Read/write separation allows independent scaling
51
- - **Auditability**: Complete event history for compliance/debugging
52
- - **Performance**: Materialized views optimize common queries
53
- - **Maintainability**: Clean architecture with separated concerns
@@ -1,93 +0,0 @@
1
- # Order System with Drizzle ORM
2
-
3
- ## Setup
4
-
5
- ### 1. Environment Variables
6
-
7
- Create a `.env` file:
8
-
9
- ```bash
10
- # Optional: PostgreSQL connection (if not set, uses in-memory)
11
- DATABASE_URL=postgres://user:password@localhost:5432/orders_db
12
-
13
- PORT=3000
14
- ```
15
-
16
- ### 2. Database Setup (Optional - for PostgreSQL)
17
-
18
- If you want to use PostgreSQL instead of in-memory storage:
19
-
20
- ```bash
21
- # Generate migration
22
- pnpm drizzle-kit generate
23
-
24
- # Run migration
25
- pnpm drizzle-kit migrate
26
-
27
- # Or use push for development
28
- pnpm drizzle-kit push
29
- ```
30
-
31
- ### 3. Run the Server
32
-
33
- ```bash
34
- # Development
35
- pnpm dev
36
-
37
- # Production
38
- pnpm build
39
- pnpm start
40
- ```
41
-
42
- ## API Endpoints
43
-
44
- Base URL: `http://localhost:3000/api`
45
-
46
- ### Create Order
47
- ```bash
48
- POST /api/orders
49
- Content-Type: application/json
50
-
51
- {
52
- "userId": "550e8400-e29b-41d4-a716-446655440000"
53
- }
54
- ```
55
-
56
- ### Add Item to Order
57
- ```bash
58
- POST /api/orders/:orderId/items
59
- Content-Type: application/json
60
-
61
- {
62
- "productId": "660e8400-e29b-41d4-a716-446655440000",
63
- "quantity": 2,
64
- "price": 29.99
65
- }
66
- ```
67
-
68
- ### Place Order
69
- ```bash
70
- POST /api/orders/:orderId/place
71
- ```
72
-
73
- ### Get Order Details
74
- ```bash
75
- GET /api/orders/:orderId
76
- ```
77
-
78
- ### Get User's Orders (Fast - from materialized view)
79
- ```bash
80
- GET /api/orders/user/:userId
81
- ```
82
-
83
- ### Get Order Event Stream (Audit log)
84
- ```bash
85
- GET /api/orders/:orderId/events
86
- ```
87
-
88
- ## Architecture
89
-
90
- - **No DATABASE_URL**: Uses in-memory repository (for testing/demo)
91
- - **With DATABASE_URL**: Uses Drizzle ORM with PostgreSQL
92
- - Event Sourcing with materialized views for optimal read performance
93
- - CQRS pattern with separate command and query operations
@@ -1,3 +0,0 @@
1
- {
2
- "extends": ["../biome.json"]
3
- }
@@ -1,10 +0,0 @@
1
- import { defineConfig } from 'drizzle-kit';
2
-
3
- export default defineConfig({
4
- schema: './src/infrastructure/database/schema.ts',
5
- out: './drizzle',
6
- dialect: 'postgresql',
7
- dbCredentials: {
8
- url: process.env.DATABASE_URL || 'postgres://localhost:5432/orders_db',
9
- },
10
- });
@@ -1,10 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/knip@5/schema.json",
3
- "ignoreExportsUsedInFile": {
4
- "interface": true,
5
- "type": true
6
- },
7
- "tags": [
8
- "-lintignore"
9
- ]
10
- }
@@ -1,55 +0,0 @@
1
- {
2
- "name": "ultimate-express-starter",
3
- "version": "1.0.0",
4
- "description": "Fast TypeScript backend starter kit with Ultimate Express, Scalar API docs, and Drizzle ORM.",
5
- "type": "module",
6
- "main": "build/index.js",
7
- "scripts": {
8
- "start": "node build/index.js",
9
- "dev": "swc src -d build --strip-leading-paths --copy-files --watch & node --watch build/index.js",
10
- "typecheck": "npx tsc --noEmit",
11
- "build": "swc src -d build --strip-leading-paths --copy-files",
12
- "build:debug": "swc src -d build --strip-leading-paths --copy-files --source-maps",
13
- "test": "vitest run",
14
- "test:watch": "vitest",
15
- "test:ui": "vitest --ui",
16
- "prebuild": "rm -rf build",
17
- "knip": "knip",
18
- "db:generate": "drizzle-kit generate",
19
- "db:migrate": "drizzle-kit migrate",
20
- "db:push": "drizzle-kit push",
21
- "db:studio": "drizzle-kit studio"
22
- },
23
- "files": [
24
- "build"
25
- ],
26
- "devDependencies": {
27
- "@biomejs/biome": "2.0.6",
28
- "@swc-node/register": "^1.11.1",
29
- "@swc/cli": "0.7.7",
30
- "@swc/core": "^1.10.1",
31
- "@types/bun": "1.2.14",
32
- "@types/cors": "^2.8.19",
33
- "@types/node": "24.0.7",
34
- "@vitest/ui": "^3.2.4",
35
- "knip": "^5.69.1",
36
- "tsx": "^4.20.6",
37
- "typescript": "^5.8.3",
38
- "vitest": "^4.0.10"
39
- },
40
- "dependencies": {
41
- "@scalar/express-api-reference": "^0.8.25",
42
- "cors": "^2.8.5",
43
- "dotenv": "17.0.0",
44
- "drizzle-kit": "^0.31.7",
45
- "drizzle-orm": "^0.44.7",
46
- "lru-cache": "^11.2.2",
47
- "postgres": "^3.4.7",
48
- "ultimate-express": "^2.0.12",
49
- "ultimate-ws": "^2.0.6",
50
- "zod": "^4.1.12"
51
- },
52
- "trustedDependencies": [
53
- "@swc/core"
54
- ]
55
- }
@@ -1,16 +0,0 @@
1
- import { defineConfig } from "@playwright/test";
2
- import { config as loadEnv } from "dotenv";
3
-
4
- // Load environment variables (e.g. PLAYWRIGHT_BASE_URL) before tests spin up.
5
- loadEnv();
6
-
7
- export default defineConfig({
8
- testDir: "src/generated/tests",
9
- reporter: [
10
- ["line"],
11
- ["html", { outputFolder: "playwright-report", open: "never" }],
12
- ],
13
- use: {
14
- baseURL: process.env.PLAYWRIGHT_BASE_URL ?? "http://localhost:3000",
15
- },
16
- });
@@ -1,3 +0,0 @@
1
- onlyBuiltDependencies:
2
- - '@swc/core'
3
- - esbuild
@@ -1,5 +0,0 @@
1
- import type { Request, Response } from 'ultimate-express';
2
-
3
- export const getHealth = (req: Request, res: Response) => {
4
- res.json({ status: 'ok', timestamp: new Date().toISOString() });
5
- };
@@ -1,6 +0,0 @@
1
- import { Router } from 'ultimate-express';
2
- import { getHealth } from './controller.js';
3
-
4
- export const healthRouter = Router();
5
-
6
- healthRouter.get('/', getHealth);
@@ -1,13 +0,0 @@
1
- import type { Request, Response } from 'ultimate-express';
2
-
3
- export const getOrders = (req: Request, res: Response) => {
4
- res.json([
5
- { id: 1, item: 'Laptop', price: 1200 },
6
- { id: 2, item: 'Mouse', price: 25 },
7
- ]);
8
- };
9
-
10
- export const createOrder = (req: Request, res: Response) => {
11
- const { item, price } = req.body;
12
- res.status(201).json({ id: 3, item, price });
13
- };
@@ -1,7 +0,0 @@
1
- import { Router } from 'ultimate-express';
2
- import { createOrder, getOrders } from './controller.js';
3
-
4
- export const ordersRouter = Router();
5
-
6
- ordersRouter.get('/', getOrders);
7
- ordersRouter.post('/', createOrder);
@@ -1,76 +0,0 @@
1
- // example backend with ultimate-express
2
- import 'dotenv/config';
3
- import express from 'ultimate-express';
4
- import type { Request, Response } from 'ultimate-express';
5
- import cors from 'cors';
6
- import { ordersRouter } from './features/orders/index.js';
7
- import { healthRouter } from './features/health/index.js';
8
- import { apiReference } from '@scalar/express-api-reference';
9
-
10
- const app = express();
11
-
12
- app.use(cors());
13
- app.use(express.json());
14
-
15
- app.get('/', (req: Request, res: Response) => {
16
- res.send('Hello, Ultimate Express!');
17
- });
18
-
19
- // Mount feature routes
20
- app.use('/api/orders', ordersRouter);
21
- app.use('/api/health', healthRouter);
22
-
23
- // API Documentation with Scalar
24
- app.use(
25
- '/api/docs',
26
- apiReference({
27
- spec: {
28
- url: '/openapi.json',
29
- },
30
- }),
31
- );
32
-
33
- // Example OpenAPI spec endpoint
34
- app.get('/openapi.json', (req: Request, res: Response) => {
35
- res.json({
36
- openapi: '3.1.0',
37
- info: {
38
- title: 'Ultimate Express API',
39
- version: '1.0.0',
40
- description: 'API documentation for Ultimate Express starter kit',
41
- },
42
- servers: [
43
- {
44
- url: `http://localhost:${process.env.PORT || 3000}`,
45
- description: 'Development server',
46
- },
47
- ],
48
- paths: {
49
- '/': {
50
- get: {
51
- summary: 'Hello endpoint',
52
- description: 'Returns a greeting message',
53
- responses: {
54
- '200': {
55
- description: 'Successful response',
56
- content: {
57
- 'text/html': {
58
- schema: {
59
- type: 'string',
60
- example: 'Hello, Ultimate Express!',
61
- },
62
- },
63
- },
64
- },
65
- },
66
- },
67
- },
68
- },
69
- });
70
- });
71
-
72
- const PORT = process.env.PORT || 3000;
73
- app.listen(PORT, () => {
74
- console.log(`Server is running on http://localhost:${PORT}`);
75
- console.log(`API Documentation available at http://localhost:${PORT}/api/docs`);
76
- });
@@ -1,10 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "compilerOptions": {
4
- "noEmit": false,
5
- "declaration": true,
6
- "declarationMap": true,
7
- "sourceMap": true
8
- },
9
- "exclude": ["node_modules", "build", "**/*.test.ts", "**/*.spec.ts"]
10
- }