create-frootjs 1.0.9 → 1.0.11

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.
@@ -20,7 +20,7 @@ export const mvcTemplate = {
20
20
  test: 'node --test tests/*.test.ts',
21
21
  },
22
22
  dependencies: {
23
- frootjs: '^1.0.2',
23
+ frootjs: '^1.0.5',
24
24
  },
25
25
  devDependencies: {
26
26
  '@types/node': '^22.10.0',
@@ -30,211 +30,211 @@ export const mvcTemplate = {
30
30
  }, null, 2) + '\n',
31
31
  'tsconfig.json': COMMON_TSCONFIG,
32
32
  '.gitignore': COMMON_GITIGNORE,
33
- 'README.md': `# ${projectName}
34
-
35
- Froot application built with the **MVC / Layered Architecture** pattern.
36
-
37
- ## Directory Structure
38
-
39
- \`\`\`
40
- src/
41
- ├── controllers/ # Request handlers & HTTP response formatting
42
- │ ├── health.controller.ts
43
- │ └── user.controller.ts
44
- ├── services/ # Core business logic & database interaction
45
- │ └── user.service.ts
46
- ├── models/ # TypeScript interfaces & domain types
47
- │ └── user.model.ts
48
- ├── routes/ # Froot route definitions & sub-app mounting
49
- │ ├── health.routes.ts
50
- │ ├── user.routes.ts
51
- │ └── index.ts
52
- ├── middleware/ # Custom onion middleware
53
- │ └── request-logger.ts
54
- ├── app.ts # Application assembly
55
- └── server.ts # Server entry point
56
- \`\`\`
57
-
58
- ## Getting Started
59
-
60
- \`\`\`bash
61
- # 1. Install dependencies
62
- pnpm install
63
-
64
- # 2. Run in development mode
65
- pnpm run dev
66
-
67
- # 3. Build for production
68
- pnpm run build
69
- pnpm start
70
- \`\`\`
33
+ 'README.md': `# ${projectName}
34
+
35
+ Froot application built with the **MVC / Layered Architecture** pattern.
36
+
37
+ ## Directory Structure
38
+
39
+ \`\`\`
40
+ src/
41
+ ├── controllers/ # Request handlers & HTTP response formatting
42
+ │ ├── health.controller.ts
43
+ │ └── user.controller.ts
44
+ ├── services/ # Core business logic & database interaction
45
+ │ └── user.service.ts
46
+ ├── models/ # TypeScript interfaces & domain types
47
+ │ └── user.model.ts
48
+ ├── routes/ # Froot route definitions & sub-app mounting
49
+ │ ├── health.routes.ts
50
+ │ ├── user.routes.ts
51
+ │ └── index.ts
52
+ ├── middleware/ # Custom onion middleware
53
+ │ └── request-logger.ts
54
+ ├── app.ts # Application assembly
55
+ └── server.ts # Server entry point
56
+ \`\`\`
57
+
58
+ ## Getting Started
59
+
60
+ \`\`\`bash
61
+ # 1. Install dependencies
62
+ pnpm install
63
+
64
+ # 2. Run in development mode
65
+ pnpm run dev
66
+
67
+ # 3. Build for production
68
+ pnpm run build
69
+ pnpm start
70
+ \`\`\`
71
71
  `,
72
- 'src/models/user.model.ts': `export interface User {
73
- id: string;
74
- name: string;
75
- email: string;
76
- role: 'admin' | 'user' | 'guest';
77
- createdAt: string;
78
- }
79
-
80
- export interface CreateUserInput {
81
- name: string;
82
- email: string;
83
- role?: 'admin' | 'user' | 'guest';
84
- }
72
+ 'src/models/user.model.ts': `export interface User {
73
+ id: string;
74
+ name: string;
75
+ email: string;
76
+ role: 'admin' | 'user' | 'guest';
77
+ createdAt: string;
78
+ }
79
+
80
+ export interface CreateUserInput {
81
+ name: string;
82
+ email: string;
83
+ role?: 'admin' | 'user' | 'guest';
84
+ }
85
85
  `,
86
- 'src/services/user.service.ts': `import type { User, CreateUserInput } from '../models/user.model.js';
87
-
88
- // In-memory mock database
89
- const usersTable = new Map<string, User>([
90
- ['usr_1', { id: 'usr_1', name: 'Alice Smith', email: 'alice@example.com', role: 'admin', createdAt: new Date().toISOString() }],
91
- ['usr_2', { id: 'usr_2', name: 'Bob Jones', email: 'bob@example.com', role: 'user', createdAt: new Date().toISOString() }],
92
- ]);
93
-
94
- export class UserService {
95
- static async findAll(): Promise<User[]> {
96
- return Array.from(usersTable.values());
97
- }
98
-
99
- static async findById(id?: string): Promise<User | null> {
100
- if (!id) return null;
101
- return usersTable.get(id) ?? null;
102
- }
103
-
104
- static async create(input: CreateUserInput): Promise<User> {
105
- const id = 'usr_' + Math.random().toString(36).substring(2, 9);
106
- const user: User = {
107
- id,
108
- name: input.name,
109
- email: input.email,
110
- role: input.role ?? 'user',
111
- createdAt: new Date().toISOString(),
112
- };
113
- usersTable.set(id, user);
114
- return user;
115
- }
116
-
117
- static async delete(id?: string): Promise<boolean> {
118
- if (!id) return false;
119
- return usersTable.delete(id);
120
- }
121
- }
86
+ 'src/services/user.service.ts': `import type { User, CreateUserInput } from '../models/user.model.js';
87
+
88
+ // In-memory mock database
89
+ const usersTable = new Map<string, User>([
90
+ ['usr_1', { id: 'usr_1', name: 'Alice Smith', email: 'alice@example.com', role: 'admin', createdAt: new Date().toISOString() }],
91
+ ['usr_2', { id: 'usr_2', name: 'Bob Jones', email: 'bob@example.com', role: 'user', createdAt: new Date().toISOString() }],
92
+ ]);
93
+
94
+ export class UserService {
95
+ static async findAll(): Promise<User[]> {
96
+ return Array.from(usersTable.values());
97
+ }
98
+
99
+ static async findById(id?: string): Promise<User | null> {
100
+ if (!id) return null;
101
+ return usersTable.get(id) ?? null;
102
+ }
103
+
104
+ static async create(input: CreateUserInput): Promise<User> {
105
+ const id = 'usr_' + Math.random().toString(36).substring(2, 9);
106
+ const user: User = {
107
+ id,
108
+ name: input.name,
109
+ email: input.email,
110
+ role: input.role ?? 'user',
111
+ createdAt: new Date().toISOString(),
112
+ };
113
+ usersTable.set(id, user);
114
+ return user;
115
+ }
116
+
117
+ static async delete(id?: string): Promise<boolean> {
118
+ if (!id) return false;
119
+ return usersTable.delete(id);
120
+ }
121
+ }
122
122
  `,
123
- 'src/controllers/health.controller.ts': `import type { Context } from 'frootjs';
124
-
125
- export class HealthController {
126
- static getHealth(c: Context) {
127
- return c.json({
128
- status: 'ok',
129
- uptime: process.uptime(),
130
- timestamp: new Date().toISOString(),
131
- });
132
- }
133
- }
123
+ 'src/controllers/health.controller.ts': `import type { Context } from 'frootjs';
124
+
125
+ export class HealthController {
126
+ static getHealth(c: Context) {
127
+ return c.json({
128
+ status: 'ok',
129
+ uptime: process.uptime(),
130
+ timestamp: new Date().toISOString(),
131
+ });
132
+ }
133
+ }
134
134
  `,
135
- 'src/controllers/user.controller.ts': `import type { Context } from 'frootjs';
136
- import { UserService } from '../services/user.service.js';
137
- import type { CreateUserInput } from '../models/user.model.js';
138
-
139
- export class UserController {
140
- static async list(c: Context) {
141
- const users = await UserService.findAll();
142
- return c.json(users);
143
- }
144
-
145
- static async getById(c: Context) {
146
- const id = c.req.param('id');
147
- const user = await UserService.findById(id);
148
- if (!user) {
149
- return c.json({ error: 'User not found' }, 404);
150
- }
151
- return c.json(user);
152
- }
153
-
154
- static async create(c: Context) {
155
- const body = await c.req.json<CreateUserInput>();
156
- if (!body.name || !body.email) {
157
- return c.json({ error: 'Name and email are required' }, 400);
158
- }
159
- const user = await UserService.create(body);
160
- return c.json(user, 201);
161
- }
162
-
163
- static async remove(c: Context) {
164
- const id = c.req.param('id');
165
- const ok = await UserService.delete(id);
166
- if (!ok) {
167
- return c.json({ error: 'User not found' }, 404);
168
- }
169
- return c.json({ success: true, message: 'User deleted' });
170
- }
171
- }
135
+ 'src/controllers/user.controller.ts': `import type { Context } from 'frootjs';
136
+ import { UserService } from '../services/user.service.js';
137
+ import type { CreateUserInput } from '../models/user.model.js';
138
+
139
+ export class UserController {
140
+ static async list(c: Context) {
141
+ const users = await UserService.findAll();
142
+ return c.json(users);
143
+ }
144
+
145
+ static async getById(c: Context) {
146
+ const id = c.req.param('id');
147
+ const user = await UserService.findById(id);
148
+ if (!user) {
149
+ return c.json({ error: 'User not found' }, 404);
150
+ }
151
+ return c.json(user);
152
+ }
153
+
154
+ static async create(c: Context) {
155
+ const body = await c.req.json<CreateUserInput>();
156
+ if (!body.name || !body.email) {
157
+ return c.json({ error: 'Name and email are required' }, 400);
158
+ }
159
+ const user = await UserService.create(body);
160
+ return c.json(user, 201);
161
+ }
162
+
163
+ static async remove(c: Context) {
164
+ const id = c.req.param('id');
165
+ const ok = await UserService.delete(id);
166
+ if (!ok) {
167
+ return c.json({ error: 'User not found' }, 404);
168
+ }
169
+ return c.json({ success: true, message: 'User deleted' });
170
+ }
171
+ }
172
172
  `,
173
- 'src/routes/health.routes.ts': `import { Froot } from 'frootjs';
174
- import { HealthController } from '../controllers/health.controller.js';
175
-
176
- export const healthRoutes = new Froot();
177
-
178
- healthRoutes.get('/health', HealthController.getHealth);
173
+ 'src/routes/health.routes.ts': `import { Froot } from 'frootjs';
174
+ import { HealthController } from '../controllers/health.controller.js';
175
+
176
+ export const healthRoutes = new Froot();
177
+
178
+ healthRoutes.get('/health', HealthController.getHealth);
179
179
  `,
180
- 'src/routes/user.routes.ts': `import { Froot } from 'frootjs';
181
- import { UserController } from '../controllers/user.controller.js';
182
-
183
- export const userRoutes = new Froot();
184
-
185
- userRoutes.get('/users', UserController.list);
186
- userRoutes.get('/users/:id', UserController.getById);
187
- userRoutes.post('/users', UserController.create);
188
- userRoutes.delete('/users/:id', UserController.remove);
180
+ 'src/routes/user.routes.ts': `import { Froot } from 'frootjs';
181
+ import { UserController } from '../controllers/user.controller.js';
182
+
183
+ export const userRoutes = new Froot();
184
+
185
+ userRoutes.get('/users', UserController.list);
186
+ userRoutes.get('/users/:id', UserController.getById);
187
+ userRoutes.post('/users', UserController.create);
188
+ userRoutes.delete('/users/:id', UserController.remove);
189
189
  `,
190
- 'src/routes/index.ts': `import { Froot } from 'frootjs';
191
- import { healthRoutes } from './health.routes.js';
192
- import { userRoutes } from './user.routes.js';
193
-
194
- export const apiRoutes = new Froot();
195
-
196
- // Mount sub-apps
197
- apiRoutes.route('/api', healthRoutes);
198
- apiRoutes.route('/api', userRoutes);
190
+ 'src/routes/index.ts': `import { Froot } from 'frootjs';
191
+ import { healthRoutes } from './health.routes.js';
192
+ import { userRoutes } from './user.routes.js';
193
+
194
+ export const apiRoutes = new Froot();
195
+
196
+ // Mount sub-apps
197
+ apiRoutes.route('/api', healthRoutes);
198
+ apiRoutes.route('/api', userRoutes);
199
199
  `,
200
- 'src/middleware/request-logger.ts': `import type { MiddlewareHandler } from 'frootjs';
201
-
202
- export const requestLogger: MiddlewareHandler = async (c, next) => {
203
- const start = performance.now();
204
- await next();
205
- const duration = (performance.now() - start).toFixed(2);
206
- console.log(\`[\${c.req.method}] \${c.req.path} - \${c.statusCode} (\${duration}ms)\`);
207
- };
200
+ 'src/middleware/request-logger.ts': `import type { MiddlewareHandler } from 'frootjs';
201
+
202
+ export const requestLogger: MiddlewareHandler = async (c, next) => {
203
+ const start = performance.now();
204
+ await next();
205
+ const duration = (performance.now() - start).toFixed(2);
206
+ console.log(\`[\${c.req.method}] \${c.req.path} - \${c.statusCode} (\${duration}ms)\`);
207
+ };
208
208
  `,
209
- 'src/app.ts': `import { Froot } from 'frootjs';
210
- import { cors } from 'frootjs/cors';
211
- import { requestLogger } from './middleware/request-logger.js';
212
- import { apiRoutes } from './routes/index.js';
213
-
214
- export const app = new Froot();
215
-
216
- // Global middleware
217
- app.use(cors());
218
- app.use(requestLogger);
219
-
220
- // Mount API routes
221
- app.route('', apiRoutes);
222
-
223
- // Root route
224
- app.get('/', (c) => {
225
- return c.json({
226
- message: 'Welcome to Froot MVC API',
227
- docs: '/api/health',
228
- });
229
- });
209
+ 'src/app.ts': `import { Froot } from 'frootjs';
210
+ import { cors } from 'frootjs/cors';
211
+ import { requestLogger } from './middleware/request-logger.js';
212
+ import { apiRoutes } from './routes/index.js';
213
+
214
+ export const app = new Froot();
215
+
216
+ // Global middleware
217
+ app.use(cors());
218
+ app.use(requestLogger);
219
+
220
+ // Mount API routes
221
+ app.route('', apiRoutes);
222
+
223
+ // Root route
224
+ app.get('/', (c) => {
225
+ return c.json({
226
+ message: 'Welcome to Froot MVC API',
227
+ docs: '/api/health',
228
+ });
229
+ });
230
230
  `,
231
- 'src/server.ts': `import { app } from './app.js';
232
-
233
- const PORT = Number(process.env.PORT) || 3000;
234
-
235
- app.listen(PORT, () => {
236
- console.log(\`Server is running on http://localhost:\${PORT}\`);
237
- });
231
+ 'src/server.ts': `import { app } from './app.js';
232
+
233
+ const PORT = Number(process.env.PORT) || 3000;
234
+
235
+ app.listen(PORT, () => {
236
+ console.log(\`Server is running on http://localhost:\${PORT}\`);
237
+ });
238
238
  `,
239
239
  };
240
240
  },