create-frootjs 1.0.9 → 1.0.10

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 openapiTemplate = {
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,176 +30,176 @@ export const openapiTemplate = {
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 **OpenAPI 3.1 & Interactive Docs** pattern.
36
-
37
- ## Features
38
-
39
- - **Automatic OpenAPI 3.1 Spec**: Machine-readable spec available at \`/openapi.json\`
40
- - **Scalar Interactive UI**: Modern, high-performance API reference documentation at \`/docs\`
41
- - **Typed Schema Contracts**: Schemas defined inline with routes, supporting JSON Schema, Standard Schema v1, and Zod
42
-
43
- ## Getting Started
44
-
45
- \`\`\`bash
46
- # 1. Install dependencies
47
- pnpm install
48
-
49
- # 2. Run in development mode
50
- pnpm run dev
51
-
52
- # 3. Explore Interactive Docs
53
- http://localhost:3000/docs
54
- \`\`\`
33
+ 'README.md': `# ${projectName}
34
+
35
+ Froot application built with the **OpenAPI 3.1 & Interactive Docs** pattern.
36
+
37
+ ## Features
38
+
39
+ - **Automatic OpenAPI 3.1 Spec**: Machine-readable spec available at \`/openapi.json\`
40
+ - **Scalar Interactive UI**: Modern, high-performance API reference documentation at \`/docs\`
41
+ - **Typed Schema Contracts**: Schemas defined inline with routes, supporting JSON Schema, Standard Schema v1, and Zod
42
+
43
+ ## Getting Started
44
+
45
+ \`\`\`bash
46
+ # 1. Install dependencies
47
+ pnpm install
48
+
49
+ # 2. Run in development mode
50
+ pnpm run dev
51
+
52
+ # 3. Explore Interactive Docs
53
+ http://localhost:3000/docs
54
+ \`\`\`
55
55
  `,
56
- 'src/schemas.ts': `export const TaskSchema = {
57
- type: 'object',
58
- properties: {
59
- id: { type: 'string', description: 'Unique task identifier' },
60
- title: { type: 'string', description: 'Task title' },
61
- completed: { type: 'boolean', description: 'Completion status' },
62
- createdAt: { type: 'string', format: 'date-time' },
63
- },
64
- required: ['id', 'title', 'completed', 'createdAt'],
65
- };
66
-
67
- export const CreateTaskInputSchema = {
68
- type: 'object',
69
- properties: {
70
- title: { type: 'string', description: 'Title of the new task' },
71
- },
72
- required: ['title'],
73
- };
74
-
75
- export const ErrorResponseSchema = {
76
- type: 'object',
77
- properties: {
78
- error: { type: 'string', description: 'Error message' },
79
- },
80
- required: ['error'],
81
- };
56
+ 'src/schemas.ts': `export const TaskSchema = {
57
+ type: 'object',
58
+ properties: {
59
+ id: { type: 'string', description: 'Unique task identifier' },
60
+ title: { type: 'string', description: 'Task title' },
61
+ completed: { type: 'boolean', description: 'Completion status' },
62
+ createdAt: { type: 'string', format: 'date-time' },
63
+ },
64
+ required: ['id', 'title', 'completed', 'createdAt'],
65
+ };
66
+
67
+ export const CreateTaskInputSchema = {
68
+ type: 'object',
69
+ properties: {
70
+ title: { type: 'string', description: 'Title of the new task' },
71
+ },
72
+ required: ['title'],
73
+ };
74
+
75
+ export const ErrorResponseSchema = {
76
+ type: 'object',
77
+ properties: {
78
+ error: { type: 'string', description: 'Error message' },
79
+ },
80
+ required: ['error'],
81
+ };
82
82
  `,
83
- 'src/routes/tasks.ts': `import { Froot } from 'frootjs';
84
- import { TaskSchema, CreateTaskInputSchema, ErrorResponseSchema } from '../schemas.js';
85
-
86
- export interface Task {
87
- id: string;
88
- title: string;
89
- completed: boolean;
90
- createdAt: string;
91
- }
92
-
93
- const tasks: Task[] = [
94
- { id: 'task_1', title: 'Spin up Froot project', completed: true, createdAt: new Date().toISOString() },
95
- { id: 'task_2', title: 'Explore Scalar documentation at /docs', completed: false, createdAt: new Date().toISOString() },
96
- ];
97
-
98
- export const taskRoutes = new Froot();
99
-
100
- // List tasks
101
- taskRoutes.get(
102
- '/tasks',
103
- {
104
- summary: 'List all tasks',
105
- description: 'Retrieves the complete list of scheduled tasks.',
106
- tags: ['Tasks'],
107
- operationId: 'listTasks',
108
- response: {
109
- type: 'array',
110
- items: TaskSchema,
111
- },
112
- },
113
- (c) => c.json(tasks)
114
- );
115
-
116
- // Get task by ID
117
- taskRoutes.get(
118
- '/tasks/:id',
119
- {
120
- summary: 'Get task by ID',
121
- tags: ['Tasks'],
122
- operationId: 'getTaskById',
123
- params: {
124
- type: 'object',
125
- properties: {
126
- id: { type: 'string', description: 'Task ID' },
127
- },
128
- required: ['id'],
129
- },
130
- response: TaskSchema,
131
- errors: {
132
- 404: ErrorResponseSchema,
133
- },
134
- },
135
- (c) => {
136
- const id = c.req.param('id');
137
- const task = tasks.find((t) => t.id === id);
138
- if (!task) {
139
- return c.json({ error: 'Task not found' }, 404);
140
- }
141
- return c.json(task);
142
- }
143
- );
144
-
145
- // Create task
146
- taskRoutes.post(
147
- '/tasks',
148
- {
149
- summary: 'Create a new task',
150
- tags: ['Tasks'],
151
- operationId: 'createTask',
152
- body: CreateTaskInputSchema,
153
- response: TaskSchema,
154
- errors: {
155
- 400: ErrorResponseSchema,
156
- },
157
- },
158
- async (c) => {
159
- const body = await c.req.json<{ title?: string }>();
160
- if (!body.title) {
161
- return c.json({ error: 'Title is required' }, 400);
162
- }
163
- const newTask: Task = {
164
- id: 'task_' + Math.random().toString(36).substring(2, 9),
165
- title: body.title,
166
- completed: false,
167
- createdAt: new Date().toISOString(),
168
- };
169
- tasks.push(newTask);
170
- return c.json(newTask, 201);
171
- }
172
- );
83
+ 'src/routes/tasks.ts': `import { Froot } from 'frootjs';
84
+ import { TaskSchema, CreateTaskInputSchema, ErrorResponseSchema } from '../schemas.js';
85
+
86
+ export interface Task {
87
+ id: string;
88
+ title: string;
89
+ completed: boolean;
90
+ createdAt: string;
91
+ }
92
+
93
+ const tasks: Task[] = [
94
+ { id: 'task_1', title: 'Spin up Froot project', completed: true, createdAt: new Date().toISOString() },
95
+ { id: 'task_2', title: 'Explore Scalar documentation at /docs', completed: false, createdAt: new Date().toISOString() },
96
+ ];
97
+
98
+ export const taskRoutes = new Froot();
99
+
100
+ // List tasks
101
+ taskRoutes.get(
102
+ '/tasks',
103
+ {
104
+ summary: 'List all tasks',
105
+ description: 'Retrieves the complete list of scheduled tasks.',
106
+ tags: ['Tasks'],
107
+ operationId: 'listTasks',
108
+ response: {
109
+ type: 'array',
110
+ items: TaskSchema,
111
+ },
112
+ },
113
+ (c) => c.json(tasks)
114
+ );
115
+
116
+ // Get task by ID
117
+ taskRoutes.get(
118
+ '/tasks/:id',
119
+ {
120
+ summary: 'Get task by ID',
121
+ tags: ['Tasks'],
122
+ operationId: 'getTaskById',
123
+ params: {
124
+ type: 'object',
125
+ properties: {
126
+ id: { type: 'string', description: 'Task ID' },
127
+ },
128
+ required: ['id'],
129
+ },
130
+ response: TaskSchema,
131
+ errors: {
132
+ 404: ErrorResponseSchema,
133
+ },
134
+ },
135
+ (c) => {
136
+ const id = c.req.param('id');
137
+ const task = tasks.find((t) => t.id === id);
138
+ if (!task) {
139
+ return c.json({ error: 'Task not found' }, 404);
140
+ }
141
+ return c.json(task);
142
+ }
143
+ );
144
+
145
+ // Create task
146
+ taskRoutes.post(
147
+ '/tasks',
148
+ {
149
+ summary: 'Create a new task',
150
+ tags: ['Tasks'],
151
+ operationId: 'createTask',
152
+ body: CreateTaskInputSchema,
153
+ response: TaskSchema,
154
+ errors: {
155
+ 400: ErrorResponseSchema,
156
+ },
157
+ },
158
+ async (c) => {
159
+ const body = await c.req.json<{ title?: string }>();
160
+ if (!body.title) {
161
+ return c.json({ error: 'Title is required' }, 400);
162
+ }
163
+ const newTask: Task = {
164
+ id: 'task_' + Math.random().toString(36).substring(2, 9),
165
+ title: body.title,
166
+ completed: false,
167
+ createdAt: new Date().toISOString(),
168
+ };
169
+ tasks.push(newTask);
170
+ return c.json(newTask, 201);
171
+ }
172
+ );
173
173
  `,
174
- 'src/server.ts': `import { Froot } from 'frootjs';
175
- import { cors } from 'frootjs/cors';
176
- import { taskRoutes } from './routes/tasks.js';
177
-
178
- export const app = new Froot();
179
-
180
- app.use(cors());
181
-
182
- // Mount sub-routes
183
- app.route('/api', taskRoutes);
184
-
185
- // Root redirect to /docs
186
- app.get('/', (c) => {
187
- return c.redirect('/docs');
188
- });
189
-
190
- // Auto-mount OpenAPI 3.1 specification (/openapi.json) and Scalar UI (/docs)
191
- app.openapi({
192
- title: '${projectName} API',
193
- version: '1.0.0',
194
- description: 'Self-documenting API powered by Froot OpenAPI 3.1 & Scalar Reference UI.',
195
- });
196
-
197
- const PORT = Number(process.env.PORT) || 3000;
198
- app.listen(PORT, () => {
199
- console.log(\`Server running on http://localhost:\${PORT}\`);
200
- console.log(\`Interactive Docs available at http://localhost:\${PORT}/docs\`);
201
- console.log(\`OpenAPI JSON available at http://localhost:\${PORT}/openapi.json\`);
202
- });
174
+ 'src/server.ts': `import { Froot } from 'frootjs';
175
+ import { cors } from 'frootjs/cors';
176
+ import { taskRoutes } from './routes/tasks.js';
177
+
178
+ export const app = new Froot();
179
+
180
+ app.use(cors());
181
+
182
+ // Mount sub-routes
183
+ app.route('/api', taskRoutes);
184
+
185
+ // Root redirect to /docs
186
+ app.get('/', (c) => {
187
+ return c.redirect('/docs');
188
+ });
189
+
190
+ // Auto-mount OpenAPI 3.1 specification (/openapi.json) and Scalar UI (/docs)
191
+ app.openapi({
192
+ title: '${projectName} API',
193
+ version: '1.0.0',
194
+ description: 'Self-documenting API powered by Froot OpenAPI 3.1 & Scalar Reference UI.',
195
+ });
196
+
197
+ const PORT = Number(process.env.PORT) || 3000;
198
+ app.listen(PORT, () => {
199
+ console.log(\`Server running on http://localhost:\${PORT}\`);
200
+ console.log(\`Interactive Docs available at http://localhost:\${PORT}/docs\`);
201
+ console.log(\`OpenAPI JSON available at http://localhost:\${PORT}/openapi.json\`);
202
+ });
203
203
  `,
204
204
  };
205
205
  },