@buenojs/bueno 0.8.3 → 0.8.5
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 +136 -16
- package/dist/cli/{index.js → bin.js} +3036 -1421
- package/dist/container/index.js +250 -0
- package/dist/context/index.js +219 -0
- package/dist/database/index.js +493 -0
- package/dist/frontend/index.js +7697 -0
- package/dist/health/index.js +364 -0
- package/dist/i18n/index.js +345 -0
- package/dist/index.js +11043 -6482
- package/dist/jobs/index.js +819 -0
- package/dist/lock/index.js +367 -0
- package/dist/logger/index.js +281 -0
- package/dist/metrics/index.js +289 -0
- package/dist/middleware/index.js +77 -0
- package/dist/migrations/index.js +571 -0
- package/dist/modules/index.js +3346 -0
- package/dist/notification/index.js +484 -0
- package/dist/observability/index.js +331 -0
- package/dist/openapi/index.js +776 -0
- package/dist/orm/index.js +1356 -0
- package/dist/router/index.js +886 -0
- package/dist/rpc/index.js +691 -0
- package/dist/schema/index.js +400 -0
- package/dist/telemetry/index.js +595 -0
- package/dist/template/index.js +640 -0
- package/dist/templates/index.js +640 -0
- package/dist/testing/index.js +1111 -0
- package/dist/types/index.js +60 -0
- package/package.json +121 -27
- package/src/cache/index.ts +2 -1
- package/src/cli/bin.ts +2 -2
- package/src/cli/commands/build.ts +183 -165
- package/src/cli/commands/dev.ts +96 -89
- package/src/cli/commands/generate.ts +142 -111
- package/src/cli/commands/help.ts +20 -16
- package/src/cli/commands/index.ts +3 -6
- package/src/cli/commands/migration.ts +124 -105
- package/src/cli/commands/new.ts +392 -438
- package/src/cli/commands/start.ts +81 -79
- package/src/cli/core/args.ts +68 -50
- package/src/cli/core/console.ts +89 -95
- package/src/cli/core/index.ts +4 -4
- package/src/cli/core/prompt.ts +65 -62
- package/src/cli/core/spinner.ts +23 -20
- package/src/cli/index.ts +46 -38
- package/src/cli/templates/database/index.ts +61 -0
- package/src/cli/templates/database/mysql.ts +14 -0
- package/src/cli/templates/database/none.ts +16 -0
- package/src/cli/templates/database/postgresql.ts +14 -0
- package/src/cli/templates/database/sqlite.ts +14 -0
- package/src/cli/templates/deploy.ts +29 -26
- package/src/cli/templates/docker.ts +41 -30
- package/src/cli/templates/frontend/index.ts +63 -0
- package/src/cli/templates/frontend/none.ts +17 -0
- package/src/cli/templates/frontend/react.ts +140 -0
- package/src/cli/templates/frontend/solid.ts +134 -0
- package/src/cli/templates/frontend/svelte.ts +131 -0
- package/src/cli/templates/frontend/vue.ts +130 -0
- package/src/cli/templates/generators/index.ts +339 -0
- package/src/cli/templates/generators/types.ts +56 -0
- package/src/cli/templates/index.ts +35 -2
- package/src/cli/templates/project/api.ts +81 -0
- package/src/cli/templates/project/default.ts +140 -0
- package/src/cli/templates/project/fullstack.ts +111 -0
- package/src/cli/templates/project/index.ts +95 -0
- package/src/cli/templates/project/minimal.ts +45 -0
- package/src/cli/templates/project/types.ts +94 -0
- package/src/cli/templates/project/website.ts +263 -0
- package/src/cli/utils/fs.ts +55 -41
- package/src/cli/utils/index.ts +3 -2
- package/src/cli/utils/strings.ts +47 -33
- package/src/cli/utils/version.ts +47 -0
- package/src/config/env-validation.ts +100 -0
- package/src/config/env.ts +169 -41
- package/src/config/index.ts +28 -20
- package/src/config/loader.ts +25 -16
- package/src/config/merge.ts +21 -10
- package/src/config/types.ts +545 -25
- package/src/config/validation.ts +215 -7
- package/src/container/forward-ref.ts +22 -22
- package/src/container/index.ts +34 -12
- package/src/context/index.ts +11 -1
- package/src/database/index.ts +7 -190
- package/src/database/orm/builder.ts +457 -0
- package/src/database/orm/casts/index.ts +130 -0
- package/src/database/orm/casts/types.ts +25 -0
- package/src/database/orm/compiler.ts +304 -0
- package/src/database/orm/hooks/index.ts +114 -0
- package/src/database/orm/index.ts +61 -0
- package/src/database/orm/model-registry.ts +59 -0
- package/src/database/orm/model.ts +821 -0
- package/src/database/orm/relationships/base.ts +146 -0
- package/src/database/orm/relationships/belongs-to-many.ts +179 -0
- package/src/database/orm/relationships/belongs-to.ts +56 -0
- package/src/database/orm/relationships/has-many.ts +45 -0
- package/src/database/orm/relationships/has-one.ts +41 -0
- package/src/database/orm/relationships/index.ts +11 -0
- package/src/database/orm/scopes/index.ts +55 -0
- package/src/events/__tests__/event-system.test.ts +235 -0
- package/src/events/config.ts +238 -0
- package/src/events/example-usage.ts +185 -0
- package/src/events/index.ts +278 -0
- package/src/events/manager.ts +385 -0
- package/src/events/registry.ts +182 -0
- package/src/events/types.ts +124 -0
- package/src/frontend/api-routes.ts +65 -23
- package/src/frontend/bundler.ts +76 -34
- package/src/frontend/console-client.ts +2 -2
- package/src/frontend/console-stream.ts +94 -38
- package/src/frontend/dev-server.ts +94 -46
- package/src/frontend/file-router.ts +61 -19
- package/src/frontend/frameworks/index.ts +37 -10
- package/src/frontend/frameworks/react.ts +10 -8
- package/src/frontend/frameworks/solid.ts +11 -9
- package/src/frontend/frameworks/svelte.ts +15 -9
- package/src/frontend/frameworks/vue.ts +13 -11
- package/src/frontend/hmr-client.ts +12 -10
- package/src/frontend/hmr.ts +146 -103
- package/src/frontend/index.ts +14 -5
- package/src/frontend/islands.ts +41 -22
- package/src/frontend/isr.ts +59 -37
- package/src/frontend/layout.ts +36 -21
- package/src/frontend/ssr/react.ts +74 -27
- package/src/frontend/ssr/solid.ts +54 -20
- package/src/frontend/ssr/svelte.ts +48 -14
- package/src/frontend/ssr/vue.ts +50 -18
- package/src/frontend/ssr.ts +83 -39
- package/src/frontend/types.ts +91 -56
- package/src/health/index.ts +21 -9
- package/src/i18n/engine.ts +305 -0
- package/src/i18n/index.ts +38 -0
- package/src/i18n/loader.ts +218 -0
- package/src/i18n/middleware.ts +164 -0
- package/src/i18n/negotiator.ts +162 -0
- package/src/i18n/types.ts +158 -0
- package/src/index.ts +179 -27
- package/src/jobs/drivers/memory.ts +315 -0
- package/src/jobs/drivers/redis.ts +459 -0
- package/src/jobs/index.ts +30 -0
- package/src/jobs/queue.ts +281 -0
- package/src/jobs/types.ts +295 -0
- package/src/jobs/worker.ts +380 -0
- package/src/logger/index.ts +1 -3
- package/src/logger/transports/index.ts +62 -22
- package/src/metrics/index.ts +25 -16
- package/src/migrations/index.ts +9 -0
- package/src/modules/filters.ts +13 -17
- package/src/modules/guards.ts +49 -26
- package/src/modules/index.ts +409 -298
- package/src/modules/interceptors.ts +58 -20
- package/src/modules/lazy.ts +11 -19
- package/src/modules/lifecycle.ts +15 -7
- package/src/modules/metadata.ts +15 -5
- package/src/modules/pipes.ts +94 -72
- package/src/notification/channels/base.ts +68 -0
- package/src/notification/channels/email.ts +105 -0
- package/src/notification/channels/push.ts +104 -0
- package/src/notification/channels/sms.ts +105 -0
- package/src/notification/channels/whatsapp.ts +104 -0
- package/src/notification/index.ts +48 -0
- package/src/notification/service.ts +354 -0
- package/src/notification/types.ts +344 -0
- package/src/observability/__tests__/observability.test.ts +483 -0
- package/src/observability/breadcrumbs.ts +114 -0
- package/src/observability/index.ts +136 -0
- package/src/observability/interceptor.ts +85 -0
- package/src/observability/service.ts +303 -0
- package/src/observability/trace.ts +37 -0
- package/src/observability/types.ts +196 -0
- package/src/openapi/__tests__/decorators.test.ts +335 -0
- package/src/openapi/__tests__/document-builder.test.ts +285 -0
- package/src/openapi/__tests__/route-scanner.test.ts +334 -0
- package/src/openapi/__tests__/schema-generator.test.ts +275 -0
- package/src/openapi/decorators.ts +328 -0
- package/src/openapi/document-builder.ts +274 -0
- package/src/openapi/index.ts +112 -0
- package/src/openapi/metadata.ts +112 -0
- package/src/openapi/route-scanner.ts +289 -0
- package/src/openapi/schema-generator.ts +256 -0
- package/src/openapi/swagger-module.ts +166 -0
- package/src/openapi/types.ts +398 -0
- package/src/orm/index.ts +10 -0
- package/src/rpc/index.ts +3 -1
- package/src/schema/index.ts +9 -0
- package/src/security/index.ts +15 -6
- package/src/ssg/index.ts +9 -8
- package/src/telemetry/index.ts +76 -22
- package/src/template/index.ts +7 -0
- package/src/templates/engine.ts +224 -0
- package/src/templates/index.ts +9 -0
- package/src/templates/loader.ts +331 -0
- package/src/templates/renderers/markdown.ts +212 -0
- package/src/templates/renderers/simple.ts +269 -0
- package/src/templates/types.ts +154 -0
- package/src/testing/index.ts +100 -27
- package/src/types/optional-deps.d.ts +347 -187
- package/src/validation/index.ts +92 -2
- package/src/validation/schemas.ts +536 -0
- package/tests/integration/fullstack.test.ts +4 -4
- package/tests/unit/database.test.ts +2 -72
- package/tests/unit/env-validation.test.ts +166 -0
- package/tests/unit/events.test.ts +910 -0
- package/tests/unit/i18n.test.ts +455 -0
- package/tests/unit/jobs.test.ts +493 -0
- package/tests/unit/notification.test.ts +988 -0
- package/tests/unit/observability.test.ts +453 -0
- package/tests/unit/orm/builder.test.ts +323 -0
- package/tests/unit/orm/casts.test.ts +179 -0
- package/tests/unit/orm/compiler.test.ts +220 -0
- package/tests/unit/orm/eager-loading.test.ts +285 -0
- package/tests/unit/orm/hooks.test.ts +191 -0
- package/tests/unit/orm/model.test.ts +373 -0
- package/tests/unit/orm/relationships.test.ts +303 -0
- package/tests/unit/orm/scopes.test.ts +74 -0
- package/tests/unit/templates-simple.test.ts +53 -0
- package/tests/unit/templates.test.ts +454 -0
- package/tests/unit/validation.test.ts +18 -24
- package/tsconfig.json +11 -3
|
@@ -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 { GeneratorConfig, GeneratorResult, GeneratorType } 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/migrations';
|
|
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
|
+
}
|
|
@@ -10,7 +10,7 @@ export {
|
|
|
10
10
|
getDockerignoreTemplate,
|
|
11
11
|
getDockerComposeTemplate,
|
|
12
12
|
getDockerEnvTemplate,
|
|
13
|
-
} from
|
|
13
|
+
} from "./docker";
|
|
14
14
|
|
|
15
15
|
// Cloud platform deployment templates
|
|
16
16
|
export {
|
|
@@ -21,4 +21,37 @@ export {
|
|
|
21
21
|
getDeployTemplate,
|
|
22
22
|
getDeployFilename,
|
|
23
23
|
getDeployPlatformName,
|
|
24
|
-
} from
|
|
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,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Project Template
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { getBuenoDependency } from "../../utils/version";
|
|
6
|
+
import type { ProjectConfig, ProjectTemplateResult } from "./types";
|
|
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('/api')
|
|
26
|
+
export class AppController {
|
|
27
|
+
constructor(private readonly appService: AppService) {}
|
|
28
|
+
|
|
29
|
+
@Get()
|
|
30
|
+
hello() {
|
|
31
|
+
return Response.json({ message: 'Welcome to Bueno API!', version: '1.0.0' });
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@Get('health')
|
|
35
|
+
health(ctx: Context) {
|
|
36
|
+
return Response.json({ 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
|
+
console.log('🚀 API server running at http://localhost:3000/api');
|
|
51
|
+
`,
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
directories: [
|
|
55
|
+
"server/modules/app",
|
|
56
|
+
"server/common/middleware",
|
|
57
|
+
"server/common/guards",
|
|
58
|
+
"server/common/interceptors",
|
|
59
|
+
"server/common/pipes",
|
|
60
|
+
"server/common/filters",
|
|
61
|
+
"server/database/migrations",
|
|
62
|
+
"server/config",
|
|
63
|
+
"tests/unit",
|
|
64
|
+
"tests/integration",
|
|
65
|
+
],
|
|
66
|
+
dependencies: {
|
|
67
|
+
...getBuenoDependency(),
|
|
68
|
+
zod: "^3.24.0",
|
|
69
|
+
},
|
|
70
|
+
devDependencies: {
|
|
71
|
+
"@types/bun": "latest",
|
|
72
|
+
typescript: "^5.3.0",
|
|
73
|
+
},
|
|
74
|
+
scripts: {
|
|
75
|
+
dev: "bun run --watch server/main.ts",
|
|
76
|
+
build: "bun build ./server/main.ts --outdir ./dist --target bun",
|
|
77
|
+
start: "bun run dist/main.js",
|
|
78
|
+
test: "bun test",
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default Project Template
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { noneTemplate } from "../frontend/none";
|
|
6
|
+
import { reactTemplate } from "../frontend/react";
|
|
7
|
+
import { solidTemplate } from "../frontend/solid";
|
|
8
|
+
import { svelteTemplate } from "../frontend/svelte";
|
|
9
|
+
import { vueTemplate } from "../frontend/vue";
|
|
10
|
+
import type { ProjectConfig, ProjectTemplateResult } from "./types";
|
|
11
|
+
|
|
12
|
+
export function defaultTemplate(config: ProjectConfig): ProjectTemplateResult {
|
|
13
|
+
// Get frontend template based on framework
|
|
14
|
+
const frontendTemplates: Record<string, () => ProjectTemplateResult> = {
|
|
15
|
+
react: reactTemplate,
|
|
16
|
+
vue: vueTemplate,
|
|
17
|
+
svelte: svelteTemplate,
|
|
18
|
+
solid: solidTemplate,
|
|
19
|
+
none: noneTemplate,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const frontendTemplate = frontendTemplates[config.framework]
|
|
23
|
+
? frontendTemplates[config.framework]()
|
|
24
|
+
: reactTemplate();
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
files: [
|
|
28
|
+
{
|
|
29
|
+
path: "server/main.ts",
|
|
30
|
+
content: `import { createApp, Module, Controller, Get, Injectable } from '@buenojs/bueno';
|
|
31
|
+
import type { Context } from '@buenojs/bueno';
|
|
32
|
+
|
|
33
|
+
// Services
|
|
34
|
+
@Injectable()
|
|
35
|
+
export class AppService {
|
|
36
|
+
findAll() {
|
|
37
|
+
return { message: 'Welcome to Bueno!', items: [] };
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Controllers
|
|
42
|
+
@Controller()
|
|
43
|
+
export class AppController {
|
|
44
|
+
constructor(private readonly appService: AppService) {}
|
|
45
|
+
|
|
46
|
+
@Get()
|
|
47
|
+
hello() {
|
|
48
|
+
return new Response(\`<html>
|
|
49
|
+
<head>
|
|
50
|
+
<title>Welcome to Bueno</title>
|
|
51
|
+
<style>
|
|
52
|
+
body { font-family: system-ui, sans-serif; max-width: 800px; margin: 50px auto; padding: 20px; }
|
|
53
|
+
h1 { color: #2563eb; }
|
|
54
|
+
code { background: #f3f4f6; padding: 2px 6px; border-radius: 4px; }
|
|
55
|
+
pre { background: #f3f4f6; padding: 16px; border-radius: 8px; overflow-x: auto; }
|
|
56
|
+
a { color: #2563eb; }
|
|
57
|
+
</style>
|
|
58
|
+
</head>
|
|
59
|
+
<body>
|
|
60
|
+
<h1>🎉 Welcome to Bueno Framework!</h1>
|
|
61
|
+
<p>Your Bun-native full-stack framework is running successfully.</p>
|
|
62
|
+
|
|
63
|
+
<h2>Getting Started</h2>
|
|
64
|
+
<ul>
|
|
65
|
+
<li>Edit <code>server/main.ts</code> to modify this app</li>
|
|
66
|
+
<li>Add routes using the <code>@Get()</code>, <code>@Post()</code> decorators</li>
|
|
67
|
+
<li>Create services with <code>@Injectable()</code> and inject them in controllers</li>
|
|
68
|
+
</ul>
|
|
69
|
+
|
|
70
|
+
<h2>Documentation</h2>
|
|
71
|
+
<p>Visit <a href="https://buenojs.dev">https://buenojs.dev</a> for full documentation.</p>
|
|
72
|
+
|
|
73
|
+
<h2>Quick Example</h2>
|
|
74
|
+
<pre><code>@Controller('/api')
|
|
75
|
+
class MyController {
|
|
76
|
+
@Get('/users')
|
|
77
|
+
getUsers() {
|
|
78
|
+
return { users: [] };
|
|
79
|
+
}
|
|
80
|
+
}</code></pre>
|
|
81
|
+
</body>
|
|
82
|
+
</html>\`, {
|
|
83
|
+
headers: { 'Content-Type': 'text/html; charset=utf-8' }
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@Get('health')
|
|
88
|
+
health(ctx: Context) {
|
|
89
|
+
return { status: 'ok', timestamp: new Date().toISOString() };
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Module
|
|
94
|
+
@Module({
|
|
95
|
+
controllers: [AppController],
|
|
96
|
+
providers: [AppService],
|
|
97
|
+
})
|
|
98
|
+
export class AppModule {}
|
|
99
|
+
|
|
100
|
+
// Bootstrap
|
|
101
|
+
const app = createApp(AppModule);
|
|
102
|
+
await app.listen(3000);
|
|
103
|
+
`,
|
|
104
|
+
},
|
|
105
|
+
// Include frontend files
|
|
106
|
+
...frontendTemplate.files,
|
|
107
|
+
],
|
|
108
|
+
directories: [
|
|
109
|
+
"server/modules/app",
|
|
110
|
+
"server/common/middleware",
|
|
111
|
+
"server/common/guards",
|
|
112
|
+
"server/common/interceptors",
|
|
113
|
+
"server/common/pipes",
|
|
114
|
+
"server/common/filters",
|
|
115
|
+
"server/database/migrations",
|
|
116
|
+
"server/config",
|
|
117
|
+
"tests/unit",
|
|
118
|
+
"tests/integration",
|
|
119
|
+
// Include frontend directories
|
|
120
|
+
...frontendTemplate.directories,
|
|
121
|
+
],
|
|
122
|
+
dependencies: {
|
|
123
|
+
zod: "^3.24.0",
|
|
124
|
+
// Include frontend dependencies
|
|
125
|
+
...frontendTemplate.dependencies,
|
|
126
|
+
},
|
|
127
|
+
devDependencies: {
|
|
128
|
+
// Include frontend dev dependencies
|
|
129
|
+
...frontendTemplate.devDependencies,
|
|
130
|
+
},
|
|
131
|
+
scripts: {
|
|
132
|
+
dev: "bun run --watch server/main.ts",
|
|
133
|
+
build: "bun build ./server/main.ts --outdir ./dist --target bun",
|
|
134
|
+
start: "bun run dist/main.js",
|
|
135
|
+
test: "bun test",
|
|
136
|
+
// Include frontend scripts
|
|
137
|
+
...frontendTemplate.scripts,
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
}
|