@buenojs/bueno 0.8.4 → 0.8.6

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 (234) hide show
  1. package/README.md +264 -17
  2. package/dist/cli/{index.js → bin.js} +413 -332
  3. package/dist/container/index.js +273 -0
  4. package/dist/context/index.js +219 -0
  5. package/dist/database/index.js +493 -0
  6. package/dist/frontend/index.js +7697 -0
  7. package/dist/graphql/index.js +2156 -0
  8. package/dist/health/index.js +364 -0
  9. package/dist/i18n/index.js +345 -0
  10. package/dist/index.js +9694 -5047
  11. package/dist/jobs/index.js +819 -0
  12. package/dist/lock/index.js +367 -0
  13. package/dist/logger/index.js +281 -0
  14. package/dist/metrics/index.js +289 -0
  15. package/dist/middleware/index.js +77 -0
  16. package/dist/migrations/index.js +571 -0
  17. package/dist/modules/index.js +3411 -0
  18. package/dist/notification/index.js +484 -0
  19. package/dist/observability/index.js +331 -0
  20. package/dist/openapi/index.js +795 -0
  21. package/dist/orm/index.js +1356 -0
  22. package/dist/router/index.js +886 -0
  23. package/dist/rpc/index.js +691 -0
  24. package/dist/schema/index.js +400 -0
  25. package/dist/telemetry/index.js +595 -0
  26. package/dist/template/index.js +640 -0
  27. package/dist/templates/index.js +640 -0
  28. package/dist/testing/index.js +1111 -0
  29. package/dist/types/index.js +60 -0
  30. package/llms.txt +231 -0
  31. package/package.json +125 -27
  32. package/src/cache/index.ts +2 -1
  33. package/src/cli/ARCHITECTURE.md +3 -3
  34. package/src/cli/bin.ts +2 -2
  35. package/src/cli/commands/build.ts +183 -165
  36. package/src/cli/commands/dev.ts +96 -89
  37. package/src/cli/commands/generate.ts +142 -111
  38. package/src/cli/commands/help.ts +20 -16
  39. package/src/cli/commands/index.ts +3 -6
  40. package/src/cli/commands/migration.ts +124 -105
  41. package/src/cli/commands/new.ts +294 -232
  42. package/src/cli/commands/start.ts +81 -79
  43. package/src/cli/core/args.ts +68 -50
  44. package/src/cli/core/console.ts +89 -95
  45. package/src/cli/core/index.ts +4 -4
  46. package/src/cli/core/prompt.ts +65 -62
  47. package/src/cli/core/spinner.ts +23 -20
  48. package/src/cli/index.ts +46 -38
  49. package/src/cli/templates/database/index.ts +37 -18
  50. package/src/cli/templates/database/mysql.ts +3 -3
  51. package/src/cli/templates/database/none.ts +2 -2
  52. package/src/cli/templates/database/postgresql.ts +3 -3
  53. package/src/cli/templates/database/sqlite.ts +3 -3
  54. package/src/cli/templates/deploy.ts +29 -26
  55. package/src/cli/templates/docker.ts +41 -30
  56. package/src/cli/templates/frontend/index.ts +33 -15
  57. package/src/cli/templates/frontend/none.ts +2 -2
  58. package/src/cli/templates/frontend/react.ts +18 -18
  59. package/src/cli/templates/frontend/solid.ts +15 -15
  60. package/src/cli/templates/frontend/svelte.ts +17 -17
  61. package/src/cli/templates/frontend/vue.ts +15 -15
  62. package/src/cli/templates/generators/index.ts +29 -29
  63. package/src/cli/templates/generators/types.ts +21 -21
  64. package/src/cli/templates/index.ts +6 -6
  65. package/src/cli/templates/project/api.ts +37 -36
  66. package/src/cli/templates/project/default.ts +25 -25
  67. package/src/cli/templates/project/fullstack.ts +28 -26
  68. package/src/cli/templates/project/index.ts +55 -16
  69. package/src/cli/templates/project/minimal.ts +17 -12
  70. package/src/cli/templates/project/types.ts +10 -5
  71. package/src/cli/templates/project/website.ts +15 -15
  72. package/src/cli/utils/fs.ts +55 -41
  73. package/src/cli/utils/index.ts +3 -3
  74. package/src/cli/utils/strings.ts +47 -33
  75. package/src/cli/utils/version.ts +14 -8
  76. package/src/config/env-validation.ts +100 -0
  77. package/src/config/env.ts +169 -41
  78. package/src/config/index.ts +28 -20
  79. package/src/config/loader.ts +25 -16
  80. package/src/config/merge.ts +21 -10
  81. package/src/config/types.ts +566 -25
  82. package/src/config/validation.ts +215 -7
  83. package/src/container/forward-ref.ts +22 -22
  84. package/src/container/index.ts +34 -12
  85. package/src/context/index.ts +11 -1
  86. package/src/database/index.ts +7 -190
  87. package/src/database/orm/builder.ts +457 -0
  88. package/src/database/orm/casts/index.ts +130 -0
  89. package/src/database/orm/casts/types.ts +25 -0
  90. package/src/database/orm/compiler.ts +304 -0
  91. package/src/database/orm/hooks/index.ts +114 -0
  92. package/src/database/orm/index.ts +61 -0
  93. package/src/database/orm/model-registry.ts +59 -0
  94. package/src/database/orm/model.ts +821 -0
  95. package/src/database/orm/relationships/base.ts +146 -0
  96. package/src/database/orm/relationships/belongs-to-many.ts +179 -0
  97. package/src/database/orm/relationships/belongs-to.ts +56 -0
  98. package/src/database/orm/relationships/has-many.ts +45 -0
  99. package/src/database/orm/relationships/has-one.ts +41 -0
  100. package/src/database/orm/relationships/index.ts +11 -0
  101. package/src/database/orm/scopes/index.ts +55 -0
  102. package/src/events/__tests__/event-system.test.ts +235 -0
  103. package/src/events/config.ts +238 -0
  104. package/src/events/example-usage.ts +185 -0
  105. package/src/events/index.ts +278 -0
  106. package/src/events/manager.ts +385 -0
  107. package/src/events/registry.ts +182 -0
  108. package/src/events/types.ts +124 -0
  109. package/src/frontend/api-routes.ts +65 -23
  110. package/src/frontend/bundler.ts +76 -34
  111. package/src/frontend/console-client.ts +2 -2
  112. package/src/frontend/console-stream.ts +94 -38
  113. package/src/frontend/dev-server.ts +94 -46
  114. package/src/frontend/file-router.ts +61 -19
  115. package/src/frontend/frameworks/index.ts +37 -10
  116. package/src/frontend/frameworks/react.ts +10 -8
  117. package/src/frontend/frameworks/solid.ts +11 -9
  118. package/src/frontend/frameworks/svelte.ts +15 -9
  119. package/src/frontend/frameworks/vue.ts +13 -11
  120. package/src/frontend/hmr-client.ts +12 -10
  121. package/src/frontend/hmr.ts +146 -103
  122. package/src/frontend/index.ts +14 -5
  123. package/src/frontend/islands.ts +41 -22
  124. package/src/frontend/isr.ts +59 -37
  125. package/src/frontend/layout.ts +36 -21
  126. package/src/frontend/ssr/react.ts +74 -27
  127. package/src/frontend/ssr/solid.ts +54 -20
  128. package/src/frontend/ssr/svelte.ts +48 -14
  129. package/src/frontend/ssr/vue.ts +50 -18
  130. package/src/frontend/ssr.ts +83 -39
  131. package/src/frontend/types.ts +91 -56
  132. package/src/graphql/built-in-engine.ts +598 -0
  133. package/src/graphql/context-builder.ts +110 -0
  134. package/src/graphql/decorators.ts +358 -0
  135. package/src/graphql/execution-pipeline.ts +227 -0
  136. package/src/graphql/graphql-module.ts +563 -0
  137. package/src/graphql/index.ts +101 -0
  138. package/src/graphql/metadata.ts +237 -0
  139. package/src/graphql/schema-builder.ts +319 -0
  140. package/src/graphql/subscription-handler.ts +283 -0
  141. package/src/graphql/types.ts +324 -0
  142. package/src/health/index.ts +21 -9
  143. package/src/i18n/engine.ts +305 -0
  144. package/src/i18n/index.ts +38 -0
  145. package/src/i18n/loader.ts +218 -0
  146. package/src/i18n/middleware.ts +164 -0
  147. package/src/i18n/negotiator.ts +162 -0
  148. package/src/i18n/types.ts +158 -0
  149. package/src/index.ts +182 -27
  150. package/src/jobs/drivers/memory.ts +315 -0
  151. package/src/jobs/drivers/redis.ts +459 -0
  152. package/src/jobs/index.ts +30 -0
  153. package/src/jobs/queue.ts +281 -0
  154. package/src/jobs/types.ts +295 -0
  155. package/src/jobs/worker.ts +380 -0
  156. package/src/logger/index.ts +1 -3
  157. package/src/logger/transports/index.ts +62 -22
  158. package/src/metrics/index.ts +25 -16
  159. package/src/migrations/index.ts +9 -0
  160. package/src/modules/filters.ts +13 -17
  161. package/src/modules/guards.ts +49 -26
  162. package/src/modules/index.ts +457 -299
  163. package/src/modules/interceptors.ts +58 -20
  164. package/src/modules/lazy.ts +11 -19
  165. package/src/modules/lifecycle.ts +15 -7
  166. package/src/modules/metadata.ts +15 -5
  167. package/src/modules/pipes.ts +94 -72
  168. package/src/notification/channels/base.ts +68 -0
  169. package/src/notification/channels/email.ts +105 -0
  170. package/src/notification/channels/push.ts +104 -0
  171. package/src/notification/channels/sms.ts +105 -0
  172. package/src/notification/channels/whatsapp.ts +104 -0
  173. package/src/notification/index.ts +48 -0
  174. package/src/notification/service.ts +354 -0
  175. package/src/notification/types.ts +344 -0
  176. package/src/observability/__tests__/observability.test.ts +483 -0
  177. package/src/observability/breadcrumbs.ts +114 -0
  178. package/src/observability/index.ts +136 -0
  179. package/src/observability/interceptor.ts +85 -0
  180. package/src/observability/service.ts +303 -0
  181. package/src/observability/trace.ts +37 -0
  182. package/src/observability/types.ts +196 -0
  183. package/src/openapi/__tests__/decorators.test.ts +335 -0
  184. package/src/openapi/__tests__/document-builder.test.ts +285 -0
  185. package/src/openapi/__tests__/route-scanner.test.ts +334 -0
  186. package/src/openapi/__tests__/schema-generator.test.ts +275 -0
  187. package/src/openapi/decorators.ts +328 -0
  188. package/src/openapi/document-builder.ts +274 -0
  189. package/src/openapi/index.ts +112 -0
  190. package/src/openapi/metadata.ts +112 -0
  191. package/src/openapi/route-scanner.ts +289 -0
  192. package/src/openapi/schema-generator.ts +256 -0
  193. package/src/openapi/swagger-module.ts +166 -0
  194. package/src/openapi/types.ts +398 -0
  195. package/src/orm/index.ts +10 -0
  196. package/src/rpc/index.ts +3 -1
  197. package/src/schema/index.ts +9 -0
  198. package/src/security/index.ts +15 -6
  199. package/src/ssg/index.ts +9 -8
  200. package/src/telemetry/index.ts +76 -22
  201. package/src/template/index.ts +7 -0
  202. package/src/templates/engine.ts +224 -0
  203. package/src/templates/index.ts +9 -0
  204. package/src/templates/loader.ts +331 -0
  205. package/src/templates/renderers/markdown.ts +212 -0
  206. package/src/templates/renderers/simple.ts +269 -0
  207. package/src/templates/types.ts +154 -0
  208. package/src/testing/index.ts +100 -27
  209. package/src/types/optional-deps.d.ts +347 -187
  210. package/src/validation/index.ts +92 -2
  211. package/src/validation/schemas.ts +536 -0
  212. package/tests/integration/cli.test.ts +19 -19
  213. package/tests/integration/fullstack.test.ts +4 -4
  214. package/tests/unit/cli.test.ts +1 -1
  215. package/tests/unit/database.test.ts +2 -72
  216. package/tests/unit/env-validation.test.ts +166 -0
  217. package/tests/unit/events.test.ts +910 -0
  218. package/tests/unit/graphql.test.ts +991 -0
  219. package/tests/unit/i18n.test.ts +455 -0
  220. package/tests/unit/jobs.test.ts +493 -0
  221. package/tests/unit/notification.test.ts +988 -0
  222. package/tests/unit/observability.test.ts +453 -0
  223. package/tests/unit/orm/builder.test.ts +323 -0
  224. package/tests/unit/orm/casts.test.ts +179 -0
  225. package/tests/unit/orm/compiler.test.ts +220 -0
  226. package/tests/unit/orm/eager-loading.test.ts +285 -0
  227. package/tests/unit/orm/hooks.test.ts +191 -0
  228. package/tests/unit/orm/model.test.ts +373 -0
  229. package/tests/unit/orm/relationships.test.ts +303 -0
  230. package/tests/unit/orm/scopes.test.ts +74 -0
  231. package/tests/unit/templates-simple.test.ts +53 -0
  232. package/tests/unit/templates.test.ts +454 -0
  233. package/tests/unit/validation.test.ts +18 -24
  234. package/tsconfig.json +11 -3
@@ -78,6 +78,17 @@ export interface MetricsConfig {
78
78
  maxHistorySize?: number;
79
79
  }
80
80
 
81
+ // ============= Observability Configuration =============
82
+
83
+ export interface ObservabilityConfig {
84
+ /** Enable the observability integration layer */
85
+ enabled?: boolean;
86
+ /** Maximum breadcrumb ring buffer size (default: 20) */
87
+ breadcrumbsSize?: number;
88
+ /** HTTP status codes to suppress from error reporting (e.g. [404, 401]) */
89
+ ignoreStatusCodes?: number[];
90
+ }
91
+
81
92
  // ============= Telemetry Configuration =============
82
93
 
83
94
  export interface TelemetryConfig {
@@ -91,6 +102,139 @@ export interface TelemetryConfig {
91
102
  sampleRate?: number;
92
103
  }
93
104
 
105
+ // ============= Jobs Configuration =============
106
+
107
+ export interface JobsConfig {
108
+ /** Enable background jobs */
109
+ enabled?: boolean;
110
+ /** Job queue driver type */
111
+ driver?: "redis" | "memory";
112
+ /** Redis connection URL */
113
+ url?: string;
114
+ /** Key prefix for jobs (default: 'jobs:') */
115
+ keyPrefix?: string;
116
+ /** Max concurrent jobs (default: 10) */
117
+ concurrency?: number;
118
+ /** Max retry attempts (default: 3) */
119
+ maxRetries?: number;
120
+ /** Retry delay in seconds (default: 1) */
121
+ retryDelay?: number;
122
+ /** Job batch size (default: 10) */
123
+ batchSize?: number;
124
+ /** Poll interval in milliseconds (default: 1000) */
125
+ pollInterval?: number;
126
+ /** Job timeout in milliseconds (default: 300000 / 5 minutes) */
127
+ jobTimeout?: number;
128
+ /** Enable metrics collection */
129
+ enableMetrics?: boolean;
130
+ }
131
+
132
+ // ============= Template Configuration =============
133
+
134
+ export interface TemplateConfig {
135
+ /** Enable template system */
136
+ enabled?: boolean;
137
+ /** Base path to templates directory (default: 'resources/templates') */
138
+ basePath?: string;
139
+ /** Cache configuration */
140
+ cache?: {
141
+ /** Enable template caching (default: true) */
142
+ enabled?: boolean;
143
+ /** Cache TTL in seconds (default: 3600) */
144
+ ttl?: number;
145
+ /** Maximum templates in cache (default: 100) */
146
+ maxSize?: number;
147
+ };
148
+ /** Enable file watching for hot reload in development */
149
+ watch?: boolean;
150
+ /** Default output format: 'html' or 'text' */
151
+ defaultFormat?: "html" | "text";
152
+ /** Channel to variant mapping for auto-detection */
153
+ channelVariantMap?: Record<string, string>;
154
+ }
155
+
156
+ // ============= Notification Configuration =============
157
+
158
+ export interface NotificationConfig {
159
+ /** Enable notification service */
160
+ enabled?: boolean;
161
+ /** Enable metrics collection */
162
+ enableMetrics?: boolean;
163
+ /** Default channel for sending */
164
+ defaultChannel?: string;
165
+ /** Enable job queue integration for async sending */
166
+ queue?: boolean;
167
+ /** Email channel configuration */
168
+ email?: {
169
+ enabled?: boolean;
170
+ driver?: "smtp" | "sendgrid" | "brevo" | "resend";
171
+ from?: string;
172
+ fromName?: string;
173
+ dryRun?: boolean;
174
+ smtp?: {
175
+ host?: string;
176
+ port?: number;
177
+ secure?: boolean;
178
+ username?: string;
179
+ password?: string;
180
+ };
181
+ apiKey?: string;
182
+ };
183
+ /** SMS channel configuration */
184
+ sms?: {
185
+ enabled?: boolean;
186
+ driver?: "twilio" | "aws-sns" | "custom";
187
+ dryRun?: boolean;
188
+ accountSid?: string;
189
+ authToken?: string;
190
+ fromNumber?: string;
191
+ apiKey?: string;
192
+ };
193
+ /** WhatsApp channel configuration */
194
+ whatsapp?: {
195
+ enabled?: boolean;
196
+ driver?: "twilio" | "custom";
197
+ dryRun?: boolean;
198
+ accountSid?: string;
199
+ authToken?: string;
200
+ businessPhoneNumber?: string;
201
+ apiKey?: string;
202
+ };
203
+ /** Push notification channel configuration */
204
+ push?: {
205
+ enabled?: boolean;
206
+ driver?: "firebase" | "apns" | "custom";
207
+ dryRun?: boolean;
208
+ serverKey?: string;
209
+ certificatePath?: string;
210
+ apiKey?: string;
211
+ };
212
+ }
213
+
214
+ // ============= i18n Configuration =============
215
+
216
+ export interface I18nConfig {
217
+ /** Enable i18n system */
218
+ enabled?: boolean;
219
+ /** Default locale — used as fallback when requested locale has missing keys (default: "en") */
220
+ defaultLocale?: string;
221
+ /** List of supported locale identifiers (default: ["en"]) */
222
+ supportedLocales?: string[];
223
+ /** Base directory for locale JSON files (default: "resources/i18n") */
224
+ basePath?: string;
225
+ /**
226
+ * Fall back to defaultLocale when a key is missing in the requested locale.
227
+ * (default: true)
228
+ */
229
+ fallbackToDefault?: boolean;
230
+ /** Cookie name used to persist locale choice (default: "bueno_locale") */
231
+ cookieName?: string;
232
+ /** Cookie max-age in seconds (default: 31536000 — 1 year) */
233
+ cookieMaxAge?: number;
234
+ /** Enable file watching for hot reload in development */
235
+ watch?: boolean;
236
+ }
237
+
94
238
  // ============= Frontend Configuration =============
95
239
 
96
240
  export interface FrontendConfig {
@@ -102,6 +246,25 @@ export interface FrontendConfig {
102
246
  port?: number;
103
247
  }
104
248
 
249
+ // ============= GraphQL Configuration =============
250
+
251
+ export interface GraphQLConfig {
252
+ /** Enable GraphQL support (default: false) */
253
+ enabled?: boolean;
254
+ /** HTTP path for GraphQL endpoint (default: '/graphql') */
255
+ path?: string;
256
+ /** Enable GraphiQL playground (default: auto — true with adapter, false with built-in) */
257
+ playground?: boolean;
258
+ /** Enable SDL introspection endpoint at GET <path>/schema (default: true) */
259
+ introspection?: boolean;
260
+ /** Maximum query complexity score (default: 1000) */
261
+ complexityLimit?: number;
262
+ /** Maximum query depth (default: 10) */
263
+ maxDepth?: number;
264
+ /** Enable WebSocket subscriptions (default: false) */
265
+ subscriptions?: boolean;
266
+ }
267
+
105
268
  // ============= Main Configuration Interface =============
106
269
 
107
270
  /**
@@ -114,6 +277,14 @@ export interface BuenoConfig {
114
277
  database?: DatabaseConfig;
115
278
  /** Cache configuration */
116
279
  cache?: CacheConfig;
280
+ /** Jobs configuration */
281
+ jobs?: JobsConfig;
282
+ /** Template configuration */
283
+ template?: TemplateConfig;
284
+ /** Notification configuration */
285
+ notification?: NotificationConfig;
286
+ /** i18n configuration */
287
+ i18n?: I18nConfig;
117
288
  /** Logger configuration */
118
289
  logger?: LoggerConfig;
119
290
  /** Health check configuration */
@@ -122,8 +293,12 @@ export interface BuenoConfig {
122
293
  metrics?: MetricsConfig;
123
294
  /** Telemetry configuration */
124
295
  telemetry?: TelemetryConfig;
296
+ /** Observability / error tracking configuration */
297
+ observability?: ObservabilityConfig;
125
298
  /** Frontend configuration */
126
299
  frontend?: FrontendConfig;
300
+ /** GraphQL configuration */
301
+ graphql?: GraphQLConfig;
127
302
  }
128
303
 
129
304
  // ============= Configuration Manager Options =============
@@ -197,20 +372,23 @@ export type UserConfig<T extends BuenoConfig = BuenoConfig> = DeepPartial<T>;
197
372
  /**
198
373
  * User configuration function type
199
374
  */
200
- export type UserConfigFn<T extends BuenoConfig = BuenoConfig> = (env: string) => UserConfig<T> | Promise<UserConfig<T>>;
375
+ export type UserConfigFn<T extends BuenoConfig = BuenoConfig> = (
376
+ env: string,
377
+ ) => UserConfig<T> | Promise<UserConfig<T>>;
201
378
 
202
379
  /**
203
380
  * Configuration value type for a given key path
204
381
  */
205
- export type ConfigValueForKey<TKey extends string> = TKey extends `${infer T}.${infer Rest}`
206
- ? T extends keyof BuenoConfig
207
- ? Rest extends string
208
- ? ConfigValueForKey<Rest>
209
- : BuenoConfig[T]
210
- : unknown
211
- : TKey extends keyof BuenoConfig
212
- ? BuenoConfig[TKey]
213
- : unknown;
382
+ export type ConfigValueForKey<TKey extends string> =
383
+ TKey extends `${infer T}.${infer Rest}`
384
+ ? T extends keyof BuenoConfig
385
+ ? Rest extends string
386
+ ? ConfigValueForKey<Rest>
387
+ : BuenoConfig[T]
388
+ : unknown
389
+ : TKey extends keyof BuenoConfig
390
+ ? BuenoConfig[TKey]
391
+ : unknown;
214
392
 
215
393
  // ============= Default Configuration =============
216
394
 
@@ -233,6 +411,75 @@ export const DEFAULT_CONFIG: Required<BuenoConfig> = {
233
411
  keyPrefix: "",
234
412
  enableMetrics: true,
235
413
  },
414
+ jobs: {
415
+ enabled: false,
416
+ driver: "memory",
417
+ url: undefined,
418
+ keyPrefix: "jobs:",
419
+ concurrency: 10,
420
+ maxRetries: 3,
421
+ retryDelay: 1,
422
+ batchSize: 10,
423
+ pollInterval: 1000,
424
+ jobTimeout: 300000,
425
+ enableMetrics: true,
426
+ },
427
+ template: {
428
+ enabled: true,
429
+ basePath: "resources/templates",
430
+ cache: {
431
+ enabled: true,
432
+ ttl: 3600,
433
+ maxSize: 100,
434
+ },
435
+ watch: false,
436
+ defaultFormat: "html",
437
+ channelVariantMap: {
438
+ email: "email",
439
+ sms: "sms",
440
+ push: "push",
441
+ whatsapp: "whatsapp",
442
+ web: "web",
443
+ },
444
+ },
445
+ notification: {
446
+ enabled: false,
447
+ enableMetrics: true,
448
+ queue: false,
449
+ defaultChannel: "email",
450
+ email: {
451
+ enabled: true,
452
+ driver: "smtp",
453
+ from: "noreply@example.com",
454
+ fromName: "Bueno App",
455
+ dryRun: false,
456
+ },
457
+ sms: {
458
+ enabled: false,
459
+ driver: "twilio",
460
+ dryRun: false,
461
+ },
462
+ whatsapp: {
463
+ enabled: false,
464
+ driver: "twilio",
465
+ dryRun: false,
466
+ },
467
+ push: {
468
+ enabled: false,
469
+ driver: "firebase",
470
+ dryRun: false,
471
+ },
472
+ },
473
+ i18n: {
474
+ enabled: false,
475
+ defaultLocale: "en",
476
+ supportedLocales: ["en"],
477
+ basePath: "resources/i18n",
478
+ fallbackToDefault: true,
479
+ cookieName: "bueno_locale",
480
+ cookieMaxAge: 31536000,
481
+ watch: false,
482
+ },
236
483
  logger: {
237
484
  level: "info",
238
485
  pretty: true,
@@ -274,47 +521,341 @@ export interface EnvMapping {
274
521
 
275
522
  export const ENV_MAPPINGS: EnvMapping[] = [
276
523
  // Server
277
- { envVar: "BUENO_PORT", configKey: "server.port", transform: (v) => parseInt(v, 10) },
524
+ {
525
+ envVar: "BUENO_PORT",
526
+ configKey: "server.port",
527
+ transform: (v) => Number.parseInt(v, 10),
528
+ },
278
529
  { envVar: "BUENO_HOST", configKey: "server.host" },
279
- { envVar: "BUENO_DEV", configKey: "server.development", transform: (v) => v === "true" },
280
- { envVar: "PORT", configKey: "server.port", transform: (v) => parseInt(v, 10) },
530
+ {
531
+ envVar: "BUENO_DEV",
532
+ configKey: "server.development",
533
+ transform: (v) => v === "true",
534
+ },
535
+ {
536
+ envVar: "PORT",
537
+ configKey: "server.port",
538
+ transform: (v) => Number.parseInt(v, 10),
539
+ },
281
540
  { envVar: "HOST", configKey: "server.host" },
282
541
 
283
542
  // Database
284
543
  { envVar: "DATABASE_URL", configKey: "database.url" },
285
544
  { envVar: "BUENO_DATABASE_URL", configKey: "database.url" },
286
- { envVar: "BUENO_DB_POOL_SIZE", configKey: "database.poolSize", transform: (v) => parseInt(v, 10) },
287
- { envVar: "BUENO_DB_METRICS", configKey: "database.enableMetrics", transform: (v) => v === "true" },
288
- { envVar: "BUENO_DB_SLOW_QUERY", configKey: "database.slowQueryThreshold", transform: (v) => parseInt(v, 10) },
545
+ {
546
+ envVar: "BUENO_DB_POOL_SIZE",
547
+ configKey: "database.poolSize",
548
+ transform: (v) => Number.parseInt(v, 10),
549
+ },
550
+ {
551
+ envVar: "BUENO_DB_METRICS",
552
+ configKey: "database.enableMetrics",
553
+ transform: (v) => v === "true",
554
+ },
555
+ {
556
+ envVar: "BUENO_DB_SLOW_QUERY",
557
+ configKey: "database.slowQueryThreshold",
558
+ transform: (v) => Number.parseInt(v, 10),
559
+ },
289
560
 
290
561
  // Cache
291
562
  { envVar: "REDIS_URL", configKey: "cache.url" },
292
563
  { envVar: "BUENO_REDIS_URL", configKey: "cache.url" },
293
564
  { envVar: "BUENO_CACHE_DRIVER", configKey: "cache.driver" },
294
- { envVar: "BUENO_CACHE_TTL", configKey: "cache.ttl", transform: (v) => parseInt(v, 10) },
565
+ {
566
+ envVar: "BUENO_CACHE_TTL",
567
+ configKey: "cache.ttl",
568
+ transform: (v) => Number.parseInt(v, 10),
569
+ },
295
570
  { envVar: "BUENO_CACHE_PREFIX", configKey: "cache.keyPrefix" },
296
571
 
572
+ // Jobs
573
+ {
574
+ envVar: "BUENO_JOBS_ENABLED",
575
+ configKey: "jobs.enabled",
576
+ transform: (v) => v === "true",
577
+ },
578
+ { envVar: "BUENO_JOBS_DRIVER", configKey: "jobs.driver" },
579
+ { envVar: "BUENO_JOBS_URL", configKey: "jobs.url" },
580
+ {
581
+ envVar: "BUENO_JOBS_CONCURRENCY",
582
+ configKey: "jobs.concurrency",
583
+ transform: (v) => Number.parseInt(v, 10),
584
+ },
585
+ {
586
+ envVar: "BUENO_JOBS_MAX_RETRIES",
587
+ configKey: "jobs.maxRetries",
588
+ transform: (v) => Number.parseInt(v, 10),
589
+ },
590
+ {
591
+ envVar: "BUENO_JOBS_RETRY_DELAY",
592
+ configKey: "jobs.retryDelay",
593
+ transform: (v) => Number.parseInt(v, 10),
594
+ },
595
+ {
596
+ envVar: "BUENO_JOBS_BATCH_SIZE",
597
+ configKey: "jobs.batchSize",
598
+ transform: (v) => Number.parseInt(v, 10),
599
+ },
600
+ {
601
+ envVar: "BUENO_JOBS_POLL_INTERVAL",
602
+ configKey: "jobs.pollInterval",
603
+ transform: (v) => Number.parseInt(v, 10),
604
+ },
605
+ {
606
+ envVar: "BUENO_JOBS_TIMEOUT",
607
+ configKey: "jobs.jobTimeout",
608
+ transform: (v) => Number.parseInt(v, 10),
609
+ },
610
+
611
+ // Template
612
+ {
613
+ envVar: "BUENO_TEMPLATE_ENABLED",
614
+ configKey: "template.enabled",
615
+ transform: (v) => v === "true",
616
+ },
617
+ { envVar: "BUENO_TEMPLATE_BASE_PATH", configKey: "template.basePath" },
618
+ {
619
+ envVar: "BUENO_TEMPLATE_CACHE_ENABLED",
620
+ configKey: "template.cache.enabled",
621
+ transform: (v) => v === "true",
622
+ },
623
+ {
624
+ envVar: "BUENO_TEMPLATE_CACHE_TTL",
625
+ configKey: "template.cache.ttl",
626
+ transform: (v) => Number.parseInt(v, 10),
627
+ },
628
+ {
629
+ envVar: "BUENO_TEMPLATE_CACHE_MAX_SIZE",
630
+ configKey: "template.cache.maxSize",
631
+ transform: (v) => Number.parseInt(v, 10),
632
+ },
633
+ {
634
+ envVar: "BUENO_TEMPLATE_WATCH",
635
+ configKey: "template.watch",
636
+ transform: (v) => v === "true",
637
+ },
638
+ {
639
+ envVar: "BUENO_TEMPLATE_DEFAULT_FORMAT",
640
+ configKey: "template.defaultFormat",
641
+ },
642
+
643
+ // Notification
644
+ {
645
+ envVar: "BUENO_NOTIFICATION_ENABLED",
646
+ configKey: "notification.enabled",
647
+ transform: (v) => v === "true",
648
+ },
649
+ {
650
+ envVar: "BUENO_NOTIFICATION_METRICS",
651
+ configKey: "notification.enableMetrics",
652
+ transform: (v) => v === "true",
653
+ },
654
+ {
655
+ envVar: "BUENO_NOTIFICATION_QUEUE",
656
+ configKey: "notification.queue",
657
+ transform: (v) => v === "true",
658
+ },
659
+ {
660
+ envVar: "BUENO_NOTIFICATION_DEFAULT",
661
+ configKey: "notification.defaultChannel",
662
+ },
663
+
664
+ // Email Channel
665
+ {
666
+ envVar: "BUENO_EMAIL_ENABLED",
667
+ configKey: "notification.email.enabled",
668
+ transform: (v) => v === "true",
669
+ },
670
+ { envVar: "BUENO_EMAIL_DRIVER", configKey: "notification.email.driver" },
671
+ { envVar: "BUENO_EMAIL_FROM", configKey: "notification.email.from" },
672
+ { envVar: "BUENO_EMAIL_FROM_NAME", configKey: "notification.email.fromName" },
673
+ { envVar: "BUENO_EMAIL_API_KEY", configKey: "notification.email.apiKey" },
674
+ {
675
+ envVar: "BUENO_EMAIL_DRY_RUN",
676
+ configKey: "notification.email.dryRun",
677
+ transform: (v) => v === "true",
678
+ },
679
+ { envVar: "BUENO_SMTP_HOST", configKey: "notification.email.smtp.host" },
680
+ {
681
+ envVar: "BUENO_SMTP_PORT",
682
+ configKey: "notification.email.smtp.port",
683
+ transform: (v) => Number.parseInt(v, 10),
684
+ },
685
+ { envVar: "BUENO_SMTP_USER", configKey: "notification.email.smtp.username" },
686
+ {
687
+ envVar: "BUENO_SMTP_PASSWORD",
688
+ configKey: "notification.email.smtp.password",
689
+ },
690
+ {
691
+ envVar: "BUENO_SMTP_SECURE",
692
+ configKey: "notification.email.smtp.secure",
693
+ transform: (v) => v === "true",
694
+ },
695
+
696
+ // SMS Channel
697
+ {
698
+ envVar: "BUENO_SMS_ENABLED",
699
+ configKey: "notification.sms.enabled",
700
+ transform: (v) => v === "true",
701
+ },
702
+ { envVar: "BUENO_SMS_DRIVER", configKey: "notification.sms.driver" },
703
+ {
704
+ envVar: "BUENO_SMS_DRY_RUN",
705
+ configKey: "notification.sms.dryRun",
706
+ transform: (v) => v === "true",
707
+ },
708
+ { envVar: "BUENO_SMS_ACCOUNT_SID", configKey: "notification.sms.accountSid" },
709
+ { envVar: "BUENO_SMS_AUTH_TOKEN", configKey: "notification.sms.authToken" },
710
+ { envVar: "BUENO_SMS_FROM_NUMBER", configKey: "notification.sms.fromNumber" },
711
+
712
+ // WhatsApp Channel
713
+ {
714
+ envVar: "BUENO_WHATSAPP_ENABLED",
715
+ configKey: "notification.whatsapp.enabled",
716
+ transform: (v) => v === "true",
717
+ },
718
+ {
719
+ envVar: "BUENO_WHATSAPP_DRIVER",
720
+ configKey: "notification.whatsapp.driver",
721
+ },
722
+ {
723
+ envVar: "BUENO_WHATSAPP_DRY_RUN",
724
+ configKey: "notification.whatsapp.dryRun",
725
+ transform: (v) => v === "true",
726
+ },
727
+ {
728
+ envVar: "BUENO_WHATSAPP_ACCOUNT_SID",
729
+ configKey: "notification.whatsapp.accountSid",
730
+ },
731
+ {
732
+ envVar: "BUENO_WHATSAPP_AUTH_TOKEN",
733
+ configKey: "notification.whatsapp.authToken",
734
+ },
735
+ {
736
+ envVar: "BUENO_WHATSAPP_BUSINESS_PHONE",
737
+ configKey: "notification.whatsapp.businessPhoneNumber",
738
+ },
739
+
740
+ // Push Channel
741
+ {
742
+ envVar: "BUENO_PUSH_ENABLED",
743
+ configKey: "notification.push.enabled",
744
+ transform: (v) => v === "true",
745
+ },
746
+ { envVar: "BUENO_PUSH_DRIVER", configKey: "notification.push.driver" },
747
+ {
748
+ envVar: "BUENO_PUSH_DRY_RUN",
749
+ configKey: "notification.push.dryRun",
750
+ transform: (v) => v === "true",
751
+ },
752
+ { envVar: "BUENO_PUSH_SERVER_KEY", configKey: "notification.push.serverKey" },
753
+ {
754
+ envVar: "BUENO_PUSH_CERTIFICATE_PATH",
755
+ configKey: "notification.push.certificatePath",
756
+ },
757
+
758
+ // i18n
759
+ {
760
+ envVar: "BUENO_I18N_ENABLED",
761
+ configKey: "i18n.enabled",
762
+ transform: (v) => v === "true",
763
+ },
764
+ { envVar: "BUENO_I18N_DEFAULT_LOCALE", configKey: "i18n.defaultLocale" },
765
+ {
766
+ envVar: "BUENO_I18N_SUPPORTED_LOCALES",
767
+ configKey: "i18n.supportedLocales",
768
+ transform: (v) => v.split(",").map((s) => s.trim()),
769
+ },
770
+ { envVar: "BUENO_I18N_BASE_PATH", configKey: "i18n.basePath" },
771
+ {
772
+ envVar: "BUENO_I18N_FALLBACK",
773
+ configKey: "i18n.fallbackToDefault",
774
+ transform: (v) => v === "true",
775
+ },
776
+ { envVar: "BUENO_I18N_COOKIE_NAME", configKey: "i18n.cookieName" },
777
+ {
778
+ envVar: "BUENO_I18N_COOKIE_MAX_AGE",
779
+ configKey: "i18n.cookieMaxAge",
780
+ transform: (v) => Number.parseInt(v, 10),
781
+ },
782
+ {
783
+ envVar: "BUENO_I18N_WATCH",
784
+ configKey: "i18n.watch",
785
+ transform: (v) => v === "true",
786
+ },
787
+
297
788
  // Logger
298
789
  { envVar: "LOG_LEVEL", configKey: "logger.level" },
299
790
  { envVar: "BUENO_LOG_LEVEL", configKey: "logger.level" },
300
- { envVar: "BUENO_LOG_PRETTY", configKey: "logger.pretty", transform: (v) => v === "true" },
791
+ {
792
+ envVar: "BUENO_LOG_PRETTY",
793
+ configKey: "logger.pretty",
794
+ transform: (v) => v === "true",
795
+ },
301
796
 
302
797
  // Health
303
- { envVar: "BUENO_HEALTH_ENABLED", configKey: "health.enabled", transform: (v) => v === "true" },
798
+ {
799
+ envVar: "BUENO_HEALTH_ENABLED",
800
+ configKey: "health.enabled",
801
+ transform: (v) => v === "true",
802
+ },
304
803
  { envVar: "BUENO_HEALTH_PATH", configKey: "health.healthPath" },
305
804
  { envVar: "BUENO_READY_PATH", configKey: "health.readyPath" },
306
805
 
307
806
  // Metrics
308
- { envVar: "BUENO_METRICS_ENABLED", configKey: "metrics.enabled", transform: (v) => v === "true" },
309
- { envVar: "BUENO_METRICS_INTERVAL", configKey: "metrics.collectInterval", transform: (v) => parseInt(v, 10) },
807
+ {
808
+ envVar: "BUENO_METRICS_ENABLED",
809
+ configKey: "metrics.enabled",
810
+ transform: (v) => v === "true",
811
+ },
812
+ {
813
+ envVar: "BUENO_METRICS_INTERVAL",
814
+ configKey: "metrics.collectInterval",
815
+ transform: (v) => Number.parseInt(v, 10),
816
+ },
310
817
 
311
818
  // Telemetry
312
- { envVar: "BUENO_TELEMETRY_ENABLED", configKey: "telemetry.enabled", transform: (v) => v === "true" },
819
+ {
820
+ envVar: "BUENO_TELEMETRY_ENABLED",
821
+ configKey: "telemetry.enabled",
822
+ transform: (v) => v === "true",
823
+ },
313
824
  { envVar: "BUENO_SERVICE_NAME", configKey: "telemetry.serviceName" },
314
825
  { envVar: "BUENO_OTEL_ENDPOINT", configKey: "telemetry.endpoint" },
315
826
  { envVar: "OTEL_EXPORTER_OTLP_ENDPOINT", configKey: "telemetry.endpoint" },
316
827
 
828
+ // Observability
829
+ {
830
+ envVar: "BUENO_OBSERVABILITY_ENABLED",
831
+ configKey: "observability.enabled",
832
+ transform: (v) => v === "true",
833
+ },
834
+ {
835
+ envVar: "BUENO_OBSERVABILITY_BREADCRUMBS_SIZE",
836
+ configKey: "observability.breadcrumbsSize",
837
+ transform: (v) => Number.parseInt(v, 10),
838
+ },
839
+ {
840
+ envVar: "BUENO_OBSERVABILITY_IGNORE_STATUS_CODES",
841
+ configKey: "observability.ignoreStatusCodes",
842
+ transform: (v) =>
843
+ v
844
+ .split(",")
845
+ .map((s) => s.trim())
846
+ .filter(Boolean)
847
+ .map((s) => Number.parseInt(s, 10)),
848
+ },
849
+
317
850
  // Frontend
318
- { envVar: "BUENO_FRONTEND_PORT", configKey: "frontend.port", transform: (v) => parseInt(v, 10) },
319
- { envVar: "BUENO_HMR", configKey: "frontend.hmr", transform: (v) => v === "true" },
320
- ];
851
+ {
852
+ envVar: "BUENO_FRONTEND_PORT",
853
+ configKey: "frontend.port",
854
+ transform: (v) => Number.parseInt(v, 10),
855
+ },
856
+ {
857
+ envVar: "BUENO_HMR",
858
+ configKey: "frontend.hmr",
859
+ transform: (v) => v === "true",
860
+ },
861
+ ];