@buenojs/bueno 0.8.3 → 0.8.4

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.
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Vue Frontend Template
3
+ */
4
+
5
+ import type { FrontendTemplateResult } from '../project/types';
6
+
7
+ export function vueTemplate(): FrontendTemplateResult {
8
+ return {
9
+ files: [
10
+ {
11
+ path: 'client/index.html',
12
+ content: `<!DOCTYPE html>
13
+ <html lang="en">
14
+ <head>
15
+ <meta charset="UTF-8">
16
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
17
+ <title>Bueno App</title>
18
+ </head>
19
+ <body>
20
+ <div id="app"></div>
21
+ <script type="module" src="./src/main.ts"></script>
22
+ </body>
23
+ </html>
24
+ `,
25
+ },
26
+ {
27
+ path: 'client/src/main.ts',
28
+ content: `import { createApp } from 'vue';
29
+ import App from './App.vue';
30
+ import './styles/globals.css';
31
+
32
+ createApp(App).mount('#app');
33
+ `,
34
+ },
35
+ {
36
+ path: 'client/src/App.vue',
37
+ content: `<script setup lang="ts">
38
+ import { ref } from 'vue';
39
+
40
+ const count = ref(0);
41
+ </script>
42
+
43
+ <template>
44
+ <main class="min-h-screen bg-gradient-to-br from-slate-900 to-slate-800 text-white">
45
+ <div class="container mx-auto px-4 py-16">
46
+ <div class="max-w-2xl mx-auto text-center">
47
+ <h1 class="text-5xl font-bold mb-4 bg-gradient-to-r from-green-400 to-emerald-500 bg-clip-text text-transparent">
48
+ Welcome to Bueno
49
+ </h1>
50
+ <p class="text-xl text-slate-300 mb-8">
51
+ A Bun-native full-stack framework
52
+ </p>
53
+
54
+ <div class="bg-slate-800/50 rounded-xl p-8 backdrop-blur-sm border border-slate-700">
55
+ <button
56
+ @click="count++"
57
+ class="px-6 py-3 bg-green-500 hover:bg-green-600 rounded-lg font-medium transition-colors"
58
+ >
59
+ Count: {{ count }}
60
+ </button>
61
+ <p class="mt-4 text-slate-400 text-sm">
62
+ Click the button to test Vue reactivity
63
+ </p>
64
+ </div>
65
+
66
+ <div class="mt-8 grid grid-cols-2 gap-4 text-left">
67
+ <a
68
+ href="https://bueno.github.io"
69
+ class="p-4 bg-slate-800/50 rounded-lg border border-slate-700 hover:border-green-500 transition-colors"
70
+ >
71
+ <h3 class="font-semibold text-green-400">Documentation</h3>
72
+ <p class="text-sm text-slate-400">Learn more about Bueno</p>
73
+ </a>
74
+ <a
75
+ href="https://github.com/buenojs/bueno"
76
+ class="p-4 bg-slate-800/50 rounded-lg border border-slate-700 hover:border-green-500 transition-colors"
77
+ >
78
+ <h3 class="font-semibold text-green-400">GitHub</h3>
79
+ <p class="text-sm text-slate-400">View the source code</p>
80
+ </a>
81
+ </div>
82
+ </div>
83
+ </div>
84
+ </main>
85
+ </template>
86
+ `,
87
+ },
88
+ {
89
+ path: 'client/src/styles/globals.css',
90
+ content: `@tailwind base;
91
+ @tailwind components;
92
+ @tailwind utilities;
93
+
94
+ :root {
95
+ font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
96
+ line-height: 1.5;
97
+ font-weight: 400;
98
+ font-synthesis: none;
99
+ text-rendering: optimizeLegibility;
100
+ -webkit-font-smoothing: antialiased;
101
+ -moz-osx-font-smoothing: grayscale;
102
+ }
103
+
104
+ body {
105
+ margin: 0;
106
+ min-width: 320px;
107
+ min-height: 100vh;
108
+ }
109
+ `,
110
+ },
111
+ ],
112
+ directories: [
113
+ 'client/src/components',
114
+ 'client/src/styles',
115
+ 'client/public',
116
+ ],
117
+ dependencies: {
118
+ vue: '^3.4.0',
119
+ },
120
+ devDependencies: {
121
+ tailwindcss: '^3.4.0',
122
+ postcss: '^8.4.0',
123
+ autoprefixer: '^10.4.0',
124
+ },
125
+ scripts: {
126
+ 'dev:client': 'bun run --watch client/index.html',
127
+ 'build:client': 'bun build ./client/src/main.ts --outdir ./dist/client',
128
+ },
129
+ };
130
+ }
@@ -0,0 +1,339 @@
1
+ /**
2
+ * Generators Templates
3
+ *
4
+ * Code generator templates registry
5
+ */
6
+
7
+ // Re-export types
8
+ export type {
9
+ GeneratorType,
10
+ GeneratorConfig,
11
+ GeneratorResult,
12
+ } from './types';
13
+
14
+ export { GENERATOR_ALIASES } from './types';
15
+
16
+ import type { GeneratorType, GeneratorConfig, GeneratorResult } from './types';
17
+
18
+ /**
19
+ * Generator template function type
20
+ */
21
+ type GeneratorTemplate = (config: GeneratorConfig) => string;
22
+
23
+ /**
24
+ * Generator template registry
25
+ */
26
+ const generatorTemplates: Record<GeneratorType, GeneratorTemplate> = {
27
+ controller: (config) => getControllerTemplate(config),
28
+ service: () => getServiceTemplate(),
29
+ module: (config) => getModuleTemplate(config),
30
+ guard: (config) => getGuardTemplate(config),
31
+ interceptor: (config) => getInterceptorTemplate(config),
32
+ pipe: (config) => getPipeTemplate(config),
33
+ filter: (config) => getFilterTemplate(config),
34
+ dto: (config) => getDtoTemplate(config),
35
+ middleware: (config) => getMiddlewareTemplate(config),
36
+ migration: (config) => getMigrationTemplate(config),
37
+ };
38
+
39
+ /**
40
+ * Get generator template
41
+ */
42
+ export function getGeneratorTemplate(type: GeneratorType): GeneratorTemplate {
43
+ return generatorTemplates[type];
44
+ }
45
+
46
+ /**
47
+ * Get all available generator types
48
+ */
49
+ export function getGeneratorTypes(): GeneratorType[] {
50
+ return Object.keys(generatorTemplates) as GeneratorType[];
51
+ }
52
+
53
+ /**
54
+ * Get default directory for generator type
55
+ */
56
+ export function getDefaultDirectory(type: GeneratorType): string {
57
+ switch (type) {
58
+ case 'controller':
59
+ case 'service':
60
+ case 'module':
61
+ case 'dto':
62
+ return 'modules';
63
+ case 'guard':
64
+ return 'common/guards';
65
+ case 'interceptor':
66
+ return 'common/interceptors';
67
+ case 'pipe':
68
+ return 'common/pipes';
69
+ case 'filter':
70
+ return 'common/filters';
71
+ case 'middleware':
72
+ return 'common/middleware';
73
+ case 'migration':
74
+ return 'database/migrations';
75
+ default:
76
+ return '';
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Get file extension for generator type
82
+ */
83
+ export function getFileExtension(type: GeneratorType): string {
84
+ return type === 'dto' ? '.dto.ts' : '.ts';
85
+ }
86
+
87
+ // ============= Template Functions =============
88
+
89
+ function getControllerTemplate(config: GeneratorConfig): string {
90
+ return `import { Controller, Get, Post, Put, Delete{{#if path}} } from '@buenojs/bueno'{{/if}}{{#if service}}, { {{pascalCase service}}Service } from './{{kebabCase service}}.service'{{/if}};
91
+ import type { Context } from '@buenojs/bueno';
92
+
93
+ @Controller('{{path}}')
94
+ export class {{pascalCase name}}Controller {
95
+ {{#if service}}
96
+ constructor(private readonly {{camelCase service}}Service: {{pascalCase service}}Service) {}
97
+ {{/if}}
98
+
99
+ @Get()
100
+ async findAll(ctx: Context) {
101
+ return { message: '{{pascalCase name}} controller' };
102
+ }
103
+
104
+ @Get(':id')
105
+ async findOne(ctx: Context) {
106
+ const id = ctx.params.id;
107
+ return { id, message: '{{pascalCase name}} item' };
108
+ }
109
+
110
+ @Post()
111
+ async create(ctx: Context) {
112
+ const body = await ctx.body();
113
+ return { message: 'Created', data: body };
114
+ }
115
+
116
+ @Put(':id')
117
+ async update(ctx: Context) {
118
+ const id = ctx.params.id;
119
+ const body = await ctx.body();
120
+ return { id, message: 'Updated', data: body };
121
+ }
122
+
123
+ @Delete(':id')
124
+ async remove(ctx: Context) {
125
+ const id = ctx.params.id;
126
+ return { id, message: 'Deleted' };
127
+ }
128
+ }
129
+ `;
130
+ }
131
+
132
+ function getServiceTemplate(): string {
133
+ return `import { Injectable } from '@buenojs/bueno';
134
+
135
+ @Injectable()
136
+ export class {{pascalCase name}}Service {
137
+ async findAll() {
138
+ // TODO: Implement findAll
139
+ return [];
140
+ }
141
+
142
+ async findOne(id: string) {
143
+ // TODO: Implement findOne
144
+ return { id };
145
+ }
146
+
147
+ async create(data: unknown) {
148
+ // TODO: Implement create
149
+ return data;
150
+ }
151
+
152
+ async update(id: string, data: unknown) {
153
+ // TODO: Implement update
154
+ return { id, ...data };
155
+ }
156
+
157
+ async remove(id: string) {
158
+ // TODO: Implement remove
159
+ return { id };
160
+ }
161
+ }
162
+ `;
163
+ }
164
+
165
+ function getModuleTemplate(config: GeneratorConfig): string {
166
+ return `import { Module } from '@buenojs/bueno';
167
+ import { {{pascalCase name}}Controller } from './{{kebabCase name}}.controller';
168
+ import { {{pascalCase name}}Service } from './{{kebabCase name}}.service';
169
+
170
+ @Module({
171
+ controllers: [{{pascalCase name}}Controller],
172
+ providers: [{{pascalCase name}}Service],
173
+ exports: [{{pascalCase name}}Service],
174
+ })
175
+ export class {{pascalCase name}}Module {}
176
+ `;
177
+ }
178
+
179
+ function getGuardTemplate(config: GeneratorConfig): string {
180
+ return `import { Injectable, type CanActivate, type Context } from '@buenojs/bueno';
181
+
182
+ @Injectable()
183
+ export class {{pascalCase name}}Guard implements CanActivate {
184
+ async canActivate(ctx: Context): Promise<boolean> {
185
+ // TODO: Implement guard logic
186
+ // Return true to allow access, false to deny
187
+ return true;
188
+ }
189
+ }
190
+ `;
191
+ }
192
+
193
+ function getInterceptorTemplate(config: GeneratorConfig): string {
194
+ return `import { Injectable, type NestInterceptor, type CallHandler, type Context } from '@buenojs/bueno';
195
+ import type { Observable } from 'rxjs';
196
+
197
+ @Injectable()
198
+ export class {{pascalCase name}}Interceptor implements NestInterceptor {
199
+ async intercept(ctx: Context, next: CallHandler): Promise<Observable<unknown>> {
200
+ // Before handler execution
201
+ console.log('{{pascalCase name}}Interceptor - Before');
202
+
203
+ // Call the handler
204
+ const result = await next.handle();
205
+
206
+ // After handler execution
207
+ console.log('{{pascalCase name}}Interceptor - After');
208
+
209
+ return result;
210
+ }
211
+ }
212
+ `;
213
+ }
214
+
215
+ function getPipeTemplate(config: GeneratorConfig): string {
216
+ return `import { Injectable, type PipeTransform, type Context } from '@buenojs/bueno';
217
+
218
+ @Injectable()
219
+ export class {{pascalCase name}}Pipe implements PipeTransform {
220
+ async transform(value: unknown, ctx: Context): Promise<unknown> {
221
+ // TODO: Implement transformation/validation logic
222
+ // Throw an error to reject the value
223
+ return value;
224
+ }
225
+ }
226
+ `;
227
+ }
228
+
229
+ function getFilterTemplate(config: GeneratorConfig): string {
230
+ return `import { Injectable, type ExceptionFilter, type Context } from '@buenojs/bueno';
231
+ import type { Response } from '@buenojs/bueno';
232
+
233
+ @Injectable()
234
+ export class {{pascalCase name}}Filter implements ExceptionFilter {
235
+ async catch(exception: Error, ctx: Context): Promise<Response> {
236
+ // TODO: Implement exception handling
237
+ console.error('{{pascalCase name}}Filter caught:', exception);
238
+
239
+ return new Response(
240
+ JSON.stringify({
241
+ statusCode: 500,
242
+ message: 'Internal Server Error',
243
+ error: exception.message,
244
+ }),
245
+ {
246
+ status: 500,
247
+ headers: { 'Content-Type': 'application/json' },
248
+ }
249
+ );
250
+ }
251
+ }
252
+ `;
253
+ }
254
+
255
+ function getDtoTemplate(config: GeneratorConfig): string {
256
+ return `/**
257
+ * {{pascalCase name}} DTO
258
+ */
259
+ export interface {{pascalCase name}}Dto {
260
+ // TODO: Define properties
261
+ id?: string;
262
+ createdAt?: Date;
263
+ updatedAt?: Date;
264
+ }
265
+
266
+ /**
267
+ * Create {{pascalCase name}} DTO
268
+ */
269
+ export interface Create{{pascalCase name}}Dto {
270
+ // TODO: Define required properties for creation
271
+ }
272
+
273
+ /**
274
+ * Update {{pascalCase name}} DTO
275
+ */
276
+ export interface Update{{pascalCase name}}Dto extends Partial<Create{{pascalCase name}}Dto> {
277
+ // TODO: Define optional properties for update
278
+ }
279
+ `;
280
+ }
281
+
282
+ function getMiddlewareTemplate(config: GeneratorConfig): string {
283
+ return `import type { Middleware, Context, Handler } from '@buenojs/bueno';
284
+
285
+ /**
286
+ * {{pascalCase name}} Middleware
287
+ */
288
+ export const {{camelCase name}}Middleware: Middleware = async (
289
+ ctx: Context,
290
+ next: Handler
291
+ ) => {
292
+ // Before handler execution
293
+ console.log('{{pascalCase name}}Middleware - Before');
294
+
295
+ // Call the next handler
296
+ const result = await next();
297
+
298
+ // After handler execution
299
+ console.log('{{pascalCase name}}Middleware - After');
300
+
301
+ return result;
302
+ };
303
+ `;
304
+ }
305
+
306
+ function getMigrationTemplate(config: GeneratorConfig): string {
307
+ const migrationId = generateMigrationId();
308
+ return `import { createMigration, type MigrationRunner } from '@buenojs/bueno';
309
+
310
+ export default createMigration('${migrationId}', '{{migrationName}}')
311
+ .up(async (db: MigrationRunner) => {
312
+ // TODO: Add migration logic
313
+ // Example:
314
+ // await db.createTable({
315
+ // name: '{{tableName}}',
316
+ // columns: [
317
+ // { name: 'id', type: 'uuid', primary: true },
318
+ // { name: 'created_at', type: 'timestamp', default: 'NOW()' },
319
+ // ],
320
+ // });
321
+ })
322
+ .down(async (db: MigrationRunner) => {
323
+ // TODO: Add rollback logic
324
+ // Example:
325
+ // await db.dropTable('{{tableName}}');
326
+ });
327
+ `;
328
+ }
329
+
330
+ function generateMigrationId(): string {
331
+ const now = new Date();
332
+ const year = now.getFullYear();
333
+ const month = String(now.getMonth() + 1).padStart(2, '0');
334
+ const day = String(now.getDate()).padStart(2, '0');
335
+ const hour = String(now.getHours()).padStart(2, '0');
336
+ const minute = String(now.getMinutes()).padStart(2, '0');
337
+ const second = String(now.getSeconds()).padStart(2, '0');
338
+ return `${year}${month}${day}${hour}${minute}${second}`;
339
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Generator Types
3
+ *
4
+ * Type definitions for code generators
5
+ */
6
+
7
+ /**
8
+ * Generator types available
9
+ */
10
+ export type GeneratorType =
11
+ | 'controller'
12
+ | 'service'
13
+ | 'module'
14
+ | 'guard'
15
+ | 'interceptor'
16
+ | 'pipe'
17
+ | 'filter'
18
+ | 'dto'
19
+ | 'middleware'
20
+ | 'migration';
21
+
22
+ /**
23
+ * Generator aliases
24
+ */
25
+ export const GENERATOR_ALIASES: Record<string, GeneratorType> = {
26
+ c: 'controller',
27
+ s: 'service',
28
+ m: 'module',
29
+ gu: 'guard',
30
+ i: 'interceptor',
31
+ p: 'pipe',
32
+ f: 'filter',
33
+ d: 'dto',
34
+ mw: 'middleware',
35
+ mi: 'migration',
36
+ };
37
+
38
+ /**
39
+ * Generator configuration
40
+ */
41
+ export interface GeneratorConfig {
42
+ type: GeneratorType;
43
+ name: string;
44
+ module?: string;
45
+ path?: string;
46
+ dryRun: boolean;
47
+ force: boolean;
48
+ }
49
+
50
+ /**
51
+ * Generator result
52
+ */
53
+ export interface GeneratorResult {
54
+ filePath: string;
55
+ content: string;
56
+ }
@@ -21,4 +21,37 @@ export {
21
21
  getDeployTemplate,
22
22
  getDeployFilename,
23
23
  getDeployPlatformName,
24
- } from './deploy';
24
+ } from './deploy';
25
+
26
+ // Project templates
27
+ export {
28
+ type ProjectTemplate,
29
+ type ProjectConfig,
30
+ type FrontendFramework,
31
+ type DatabaseDriver,
32
+ getProjectTemplate,
33
+ getTemplateOptions,
34
+ } from './project';
35
+
36
+ // Database templates
37
+ export {
38
+ getDatabaseTemplate,
39
+ getDatabaseOptions,
40
+ } from './database';
41
+
42
+ // Frontend templates
43
+ export {
44
+ getFrontendTemplate,
45
+ getFrontendOptions,
46
+ } from './frontend';
47
+
48
+ // Generator templates
49
+ export {
50
+ type GeneratorType,
51
+ type GeneratorConfig,
52
+ GENERATOR_ALIASES,
53
+ getGeneratorTemplate,
54
+ getGeneratorTypes,
55
+ getDefaultDirectory,
56
+ getFileExtension,
57
+ } from './generators';
@@ -0,0 +1,80 @@
1
+ /**
2
+ * API Project Template
3
+ */
4
+
5
+ import type { ProjectConfig, ProjectTemplateResult } from './types';
6
+ import { getBuenoDependency } from '../../utils/version';
7
+
8
+ export function apiTemplate(config: ProjectConfig): ProjectTemplateResult {
9
+ return {
10
+ files: [
11
+ {
12
+ path: 'server/main.ts',
13
+ content: `import { createApp, Module, Controller, Get, Post, Injectable } from '@buenojs/bueno';
14
+ import type { Context } from '@buenojs/bueno';
15
+
16
+ // Services
17
+ @Injectable()
18
+ export class AppService {
19
+ findAll() {
20
+ return { message: 'Welcome to Bueno API!', items: [] };
21
+ }
22
+ }
23
+
24
+ // Controllers
25
+ @Controller()
26
+ export class AppController {
27
+ constructor(private readonly appService: AppService) {}
28
+
29
+ @Get()
30
+ hello() {
31
+ return { message: 'Welcome to Bueno API!', version: '1.0.0' };
32
+ }
33
+
34
+ @Get('health')
35
+ health(ctx: Context) {
36
+ return { status: 'ok', timestamp: new Date().toISOString() };
37
+ }
38
+ }
39
+
40
+ // Module
41
+ @Module({
42
+ controllers: [AppController],
43
+ providers: [AppService],
44
+ })
45
+ export class AppModule {}
46
+
47
+ // Bootstrap
48
+ const app = createApp(AppModule);
49
+ await app.listen(3000);
50
+ `,
51
+ },
52
+ ],
53
+ directories: [
54
+ 'server/modules/app',
55
+ 'server/common/middleware',
56
+ 'server/common/guards',
57
+ 'server/common/interceptors',
58
+ 'server/common/pipes',
59
+ 'server/common/filters',
60
+ 'server/database/migrations',
61
+ 'server/config',
62
+ 'tests/unit',
63
+ 'tests/integration',
64
+ ],
65
+ dependencies: {
66
+ ...getBuenoDependency(),
67
+ zod: '^3.24.0',
68
+ },
69
+ devDependencies: {
70
+ '@types/bun': 'latest',
71
+ typescript: '^5.3.0',
72
+ },
73
+ scripts: {
74
+ dev: 'bun run --watch server/main.ts',
75
+ build: 'bun build ./server/main.ts --outdir ./dist --target bun',
76
+ start: 'bun run dist/main.js',
77
+ test: 'bun test',
78
+ },
79
+ };
80
+ }