@buenojs/bueno 0.8.0

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 (120) hide show
  1. package/.env.example +109 -0
  2. package/.github/workflows/ci.yml +31 -0
  3. package/LICENSE +21 -0
  4. package/README.md +892 -0
  5. package/architecture.md +652 -0
  6. package/bun.lock +70 -0
  7. package/dist/cli/index.js +3233 -0
  8. package/dist/index.js +9014 -0
  9. package/package.json +77 -0
  10. package/src/cache/index.ts +795 -0
  11. package/src/cli/ARCHITECTURE.md +837 -0
  12. package/src/cli/bin.ts +10 -0
  13. package/src/cli/commands/build.ts +425 -0
  14. package/src/cli/commands/dev.ts +248 -0
  15. package/src/cli/commands/generate.ts +541 -0
  16. package/src/cli/commands/help.ts +55 -0
  17. package/src/cli/commands/index.ts +112 -0
  18. package/src/cli/commands/migration.ts +355 -0
  19. package/src/cli/commands/new.ts +804 -0
  20. package/src/cli/commands/start.ts +208 -0
  21. package/src/cli/core/args.ts +283 -0
  22. package/src/cli/core/console.ts +349 -0
  23. package/src/cli/core/index.ts +60 -0
  24. package/src/cli/core/prompt.ts +424 -0
  25. package/src/cli/core/spinner.ts +265 -0
  26. package/src/cli/index.ts +135 -0
  27. package/src/cli/templates/deploy.ts +295 -0
  28. package/src/cli/templates/docker.ts +307 -0
  29. package/src/cli/templates/index.ts +24 -0
  30. package/src/cli/utils/fs.ts +428 -0
  31. package/src/cli/utils/index.ts +8 -0
  32. package/src/cli/utils/strings.ts +197 -0
  33. package/src/config/env.ts +408 -0
  34. package/src/config/index.ts +506 -0
  35. package/src/config/loader.ts +329 -0
  36. package/src/config/merge.ts +285 -0
  37. package/src/config/types.ts +320 -0
  38. package/src/config/validation.ts +441 -0
  39. package/src/container/forward-ref.ts +143 -0
  40. package/src/container/index.ts +386 -0
  41. package/src/context/index.ts +360 -0
  42. package/src/database/index.ts +1142 -0
  43. package/src/database/migrations/index.ts +371 -0
  44. package/src/database/schema/index.ts +619 -0
  45. package/src/frontend/api-routes.ts +640 -0
  46. package/src/frontend/bundler.ts +643 -0
  47. package/src/frontend/console-client.ts +419 -0
  48. package/src/frontend/console-stream.ts +587 -0
  49. package/src/frontend/dev-server.ts +846 -0
  50. package/src/frontend/file-router.ts +611 -0
  51. package/src/frontend/frameworks/index.ts +106 -0
  52. package/src/frontend/frameworks/react.ts +85 -0
  53. package/src/frontend/frameworks/solid.ts +104 -0
  54. package/src/frontend/frameworks/svelte.ts +110 -0
  55. package/src/frontend/frameworks/vue.ts +92 -0
  56. package/src/frontend/hmr-client.ts +663 -0
  57. package/src/frontend/hmr.ts +728 -0
  58. package/src/frontend/index.ts +342 -0
  59. package/src/frontend/islands.ts +552 -0
  60. package/src/frontend/isr.ts +555 -0
  61. package/src/frontend/layout.ts +475 -0
  62. package/src/frontend/ssr/react.ts +446 -0
  63. package/src/frontend/ssr/solid.ts +523 -0
  64. package/src/frontend/ssr/svelte.ts +546 -0
  65. package/src/frontend/ssr/vue.ts +504 -0
  66. package/src/frontend/ssr.ts +699 -0
  67. package/src/frontend/types.ts +2274 -0
  68. package/src/health/index.ts +604 -0
  69. package/src/index.ts +410 -0
  70. package/src/lock/index.ts +587 -0
  71. package/src/logger/index.ts +444 -0
  72. package/src/logger/transports/index.ts +969 -0
  73. package/src/metrics/index.ts +494 -0
  74. package/src/middleware/built-in.ts +360 -0
  75. package/src/middleware/index.ts +94 -0
  76. package/src/modules/filters.ts +458 -0
  77. package/src/modules/guards.ts +405 -0
  78. package/src/modules/index.ts +1256 -0
  79. package/src/modules/interceptors.ts +574 -0
  80. package/src/modules/lazy.ts +418 -0
  81. package/src/modules/lifecycle.ts +478 -0
  82. package/src/modules/metadata.ts +90 -0
  83. package/src/modules/pipes.ts +626 -0
  84. package/src/router/index.ts +339 -0
  85. package/src/router/linear.ts +371 -0
  86. package/src/router/regex.ts +292 -0
  87. package/src/router/tree.ts +562 -0
  88. package/src/rpc/index.ts +1263 -0
  89. package/src/security/index.ts +436 -0
  90. package/src/ssg/index.ts +631 -0
  91. package/src/storage/index.ts +456 -0
  92. package/src/telemetry/index.ts +1097 -0
  93. package/src/testing/index.ts +1586 -0
  94. package/src/types/index.ts +236 -0
  95. package/src/types/optional-deps.d.ts +219 -0
  96. package/src/validation/index.ts +276 -0
  97. package/src/websocket/index.ts +1004 -0
  98. package/tests/integration/cli.test.ts +1016 -0
  99. package/tests/integration/fullstack.test.ts +234 -0
  100. package/tests/unit/cache.test.ts +174 -0
  101. package/tests/unit/cli-commands.test.ts +892 -0
  102. package/tests/unit/cli.test.ts +1258 -0
  103. package/tests/unit/container.test.ts +279 -0
  104. package/tests/unit/context.test.ts +221 -0
  105. package/tests/unit/database.test.ts +183 -0
  106. package/tests/unit/linear-router.test.ts +280 -0
  107. package/tests/unit/lock.test.ts +336 -0
  108. package/tests/unit/middleware.test.ts +184 -0
  109. package/tests/unit/modules.test.ts +142 -0
  110. package/tests/unit/pubsub.test.ts +257 -0
  111. package/tests/unit/regex-router.test.ts +265 -0
  112. package/tests/unit/router.test.ts +373 -0
  113. package/tests/unit/rpc.test.ts +1248 -0
  114. package/tests/unit/security.test.ts +174 -0
  115. package/tests/unit/telemetry.test.ts +371 -0
  116. package/tests/unit/test-cache.test.ts +110 -0
  117. package/tests/unit/test-database.test.ts +282 -0
  118. package/tests/unit/tree-router.test.ts +325 -0
  119. package/tests/unit/validation.test.ts +794 -0
  120. package/tsconfig.json +27 -0
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Bueno CLI Entry Point
3
+ *
4
+ * Main entry point for the Bueno CLI
5
+ */
6
+
7
+ import { parseArgs, hasFlag, generateGlobalHelpText, generateHelpText, type ParsedArgs } from './core/args';
8
+ import { cliConsole, colors, setColorEnabled } from './core/console';
9
+ import { registry } from './commands';
10
+
11
+ // Import commands to register them
12
+ import './commands/new';
13
+ import './commands/generate';
14
+ import './commands/migration';
15
+ import './commands/dev';
16
+ import './commands/build';
17
+ import './commands/start';
18
+ import './commands/help';
19
+
20
+ // CLI version (should match package.json)
21
+ const VERSION = '0.1.0';
22
+
23
+ /**
24
+ * CLI error types
25
+ */
26
+ export enum CLIErrorType {
27
+ INVALID_ARGS = 'INVALID_ARGS',
28
+ FILE_EXISTS = 'FILE_EXISTS',
29
+ FILE_NOT_FOUND = 'FILE_NOT_FOUND',
30
+ MODULE_NOT_FOUND = 'MODULE_NOT_FOUND',
31
+ TEMPLATE_ERROR = 'TEMPLATE_ERROR',
32
+ DATABASE_ERROR = 'DATABASE_ERROR',
33
+ NETWORK_ERROR = 'NETWORK_ERROR',
34
+ PERMISSION_ERROR = 'PERMISSION_ERROR',
35
+ NOT_FOUND = 'NOT_FOUND',
36
+ }
37
+
38
+ /**
39
+ * CLI Error class
40
+ */
41
+ export class CLIError extends Error {
42
+ constructor(
43
+ message: string,
44
+ public readonly type: CLIErrorType,
45
+ public readonly exitCode = 1,
46
+ ) {
47
+ super(message);
48
+ this.name = 'CLIError';
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Run the CLI
54
+ */
55
+ export async function run(argv: string[] = process.argv.slice(2)): Promise<void> {
56
+ // Parse arguments
57
+ const args = parseArgs(argv);
58
+
59
+ // Handle global options
60
+ if (hasFlag(args, 'no-color')) {
61
+ setColorEnabled(false);
62
+ }
63
+
64
+ if (hasFlag(args, 'verbose')) {
65
+ process.env.BUENO_VERBOSE = 'true';
66
+ }
67
+
68
+ if (hasFlag(args, 'quiet')) {
69
+ process.env.BUENO_QUIET = 'true';
70
+ }
71
+
72
+ // Show version
73
+ if (hasFlag(args, 'version') || hasFlag(args, 'v')) {
74
+ cliConsole.log(`bueno v${VERSION}`);
75
+ process.exit(0);
76
+ }
77
+
78
+ // Show help if no command or help flag
79
+ if (!args.command || hasFlag(args, 'help') || hasFlag(args, 'h')) {
80
+ if (args.command && registry.has(args.command)) {
81
+ // Show command-specific help
82
+ const cmd = registry.get(args.command);
83
+ if (cmd) {
84
+ cliConsole.log(generateHelpText(cmd.definition));
85
+ }
86
+ } else {
87
+ // Show global help
88
+ cliConsole.log(generateGlobalHelpText(registry.getAll()));
89
+ }
90
+ process.exit(0);
91
+ }
92
+
93
+ // Execute command
94
+ try {
95
+ await registry.execute(args.command, args);
96
+ } catch (error) {
97
+ if (error instanceof CLIError) {
98
+ cliConsole.error(error.message);
99
+ process.exit(error.exitCode);
100
+ }
101
+
102
+ if (error instanceof Error) {
103
+ if (process.env.BUENO_VERBOSE === 'true') {
104
+ cliConsole.error(error.stack ?? error.message);
105
+ } else {
106
+ cliConsole.error(error.message);
107
+ }
108
+ }
109
+ process.exit(1);
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Run CLI and handle process events
115
+ */
116
+ export async function main(): Promise<void> {
117
+ // Handle Ctrl+C gracefully
118
+ process.on('SIGINT', () => {
119
+ cliConsole.newline();
120
+ process.exit(130);
121
+ });
122
+
123
+ // Handle unhandled rejections
124
+ process.on('unhandledRejection', (reason) => {
125
+ cliConsole.error('Unhandled rejection:', reason);
126
+ process.exit(1);
127
+ });
128
+
129
+ await run();
130
+ }
131
+
132
+ // Export for programmatic use
133
+ export { registry, defineCommand, command } from './commands';
134
+ export * from './core';
135
+ export * from './utils';
@@ -0,0 +1,295 @@
1
+ /**
2
+ * Cloud Platform Deployment Templates
3
+ *
4
+ * Template functions for generating deployment configuration files
5
+ * for various cloud platforms (Render, Fly.io, Railway)
6
+ */
7
+
8
+ /**
9
+ * Valid deployment platforms
10
+ */
11
+ export type DeployPlatform = 'render' | 'fly' | 'railway';
12
+
13
+ /**
14
+ * Get Render.com deployment configuration (render.yaml)
15
+ *
16
+ * Blueprint format for Render.com with web service and optional database
17
+ */
18
+ export function getRenderYamlTemplate(projectName: string, database?: string): string {
19
+ const kebabName = projectName.toLowerCase().replace(/[^a-z0-9-]/g, '-');
20
+
21
+ let databaseSection = '';
22
+ let envVars = '';
23
+
24
+ if (database === 'postgresql') {
25
+ databaseSection = `
26
+ # PostgreSQL Database
27
+ - type: pserv
28
+ name: ${kebabName}-db
29
+ env: docker
30
+ region: oregon
31
+ plan: starter
32
+ envVars:
33
+ - key: POSTGRES_USER
34
+ generateValue: true
35
+ - key: POSTGRES_PASSWORD
36
+ generateValue: true
37
+ - key: POSTGRES_DB
38
+ value: ${kebabName}
39
+ disk:
40
+ name: postgres-data
41
+ mountPath: /var/lib/postgresql/data
42
+ sizeGB: 10
43
+
44
+ `;
45
+ envVars = `
46
+ envVars:
47
+ - key: DATABASE_URL
48
+ fromDatabase:
49
+ name: ${kebabName}-db
50
+ property: connectionString
51
+ - key: NODE_ENV
52
+ value: production
53
+ - key: BUN_ENV
54
+ value: production
55
+ `;
56
+ } else if (database === 'mysql') {
57
+ databaseSection = `
58
+ # MySQL Database (using Render's managed MySQL)
59
+ - type: pserv
60
+ name: ${kebabName}-db
61
+ env: docker
62
+ region: oregon
63
+ plan: starter
64
+ envVars:
65
+ - key: MYSQL_ROOT_PASSWORD
66
+ generateValue: true
67
+ - key: MYSQL_USER
68
+ generateValue: true
69
+ - key: MYSQL_PASSWORD
70
+ generateValue: true
71
+ - key: MYSQL_DATABASE
72
+ value: ${kebabName}
73
+ disk:
74
+ name: mysql-data
75
+ mountPath: /var/lib/mysql
76
+ sizeGB: 10
77
+
78
+ `;
79
+ envVars = `
80
+ envVars:
81
+ - key: DATABASE_URL
82
+ fromDatabase:
83
+ name: ${kebabName}-db
84
+ property: connectionString
85
+ - key: NODE_ENV
86
+ value: production
87
+ - key: BUN_ENV
88
+ value: production
89
+ `;
90
+ } else {
91
+ envVars = `
92
+ envVars:
93
+ - key: NODE_ENV
94
+ value: production
95
+ - key: BUN_ENV
96
+ value: production
97
+ `;
98
+ }
99
+
100
+ return `# ${projectName} - Render.com Deployment Configuration
101
+ # https://render.com/docs/blueprint-spec
102
+
103
+ services:
104
+ # Web Service
105
+ - type: web
106
+ name: ${kebabName}
107
+ env: docker
108
+ region: oregon
109
+ plan: starter
110
+ branch: main
111
+ dockerfilePath: ./Dockerfile
112
+ # dockerContext: .
113
+ numInstances: 1
114
+ healthCheckPath: /health
115
+ ${envVars} # Auto-deploy on push to main branch
116
+ autoDeploy: true
117
+ ${databaseSection}
118
+ # Blueprint metadata
119
+ metadata:
120
+ name: ${projectName}
121
+ description: A Bueno application deployed on Render
122
+ `;
123
+ }
124
+
125
+ /**
126
+ * Get Fly.io deployment configuration (fly.toml)
127
+ *
128
+ * Fly.io app configuration with HTTP service and auto-scaling
129
+ */
130
+ export function getFlyTomlTemplate(projectName: string): string {
131
+ const kebabName = projectName.toLowerCase().replace(/[^a-z0-9-]/g, '-');
132
+
133
+ return `# ${projectName} - Fly.io Deployment Configuration
134
+ # https://fly.io/docs/reference/configuration/
135
+
136
+ app = "${kebabName}"
137
+ primary_region = "sea"
138
+
139
+ [build]
140
+ dockerfile = "Dockerfile"
141
+
142
+ [env]
143
+ NODE_ENV = "production"
144
+ BUN_ENV = "production"
145
+ PORT = "3000"
146
+
147
+ [http_service]
148
+ internal_port = 3000
149
+ force_https = true
150
+ auto_stop_machines = "stop"
151
+ auto_start_machines = true
152
+ min_machines_running = 0
153
+ processes = ["app"]
154
+
155
+ [http_service.concurrency]
156
+ type = "connections"
157
+ hard_limit = 100
158
+ soft_limit = 80
159
+
160
+ [[http_service.checks]]
161
+ grace_period = "10s"
162
+ interval = "30s"
163
+ method = "GET"
164
+ timeout = "5s"
165
+ path = "/health"
166
+
167
+ [http_service.checks.headers]
168
+ Content-Type = "application/json"
169
+
170
+ [[vm]]
171
+ cpu_kind = "shared"
172
+ cpus = 1
173
+ memory_mb = 512
174
+
175
+ [[mounts]]
176
+ source = "data"
177
+ destination = "/app/data"
178
+ initial_size = "1GB"
179
+
180
+ # Scale configuration
181
+ # Use: fly scale count 2 # Scale to 2 machines
182
+ # Use: fly scale vm shared-cpu-2x --memory 1024 # Upgrade VM
183
+
184
+ # Secrets (set via: fly secrets set KEY=VALUE)
185
+ # DATABASE_URL=your-database-url
186
+ # Any other sensitive environment variables
187
+ `;
188
+ }
189
+
190
+ /**
191
+ * Get Railway deployment configuration (railway.toml)
192
+ *
193
+ * Railway configuration with builder settings and health checks
194
+ */
195
+ export function getRailwayTomlTemplate(projectName: string): string {
196
+ const kebabName = projectName.toLowerCase().replace(/[^a-z0-9-]/g, '-');
197
+
198
+ return `# ${projectName} - Railway Deployment Configuration
199
+ # https://docs.railway.app/reference/config-as-code
200
+
201
+ [build]
202
+ builder = "DOCKERFILE"
203
+ dockerfilePath = "Dockerfile"
204
+
205
+ [deploy]
206
+ startCommand = "bun run dist/main.js"
207
+ healthcheckPath = "/health"
208
+ healthcheckTimeout = 300
209
+ restartPolicyType = "ON_FAILURE"
210
+ restartPolicyMaxRetries = 3
211
+
212
+ # Environment variables
213
+ # Set these in Railway dashboard or via CLI:
214
+ # railway variables set NODE_ENV=production
215
+ # railway variables set DATABASE_URL=your-database-url
216
+
217
+ [[services]]
218
+ name = "${kebabName}"
219
+
220
+ [services.variables]
221
+ NODE_ENV = "production"
222
+ BUN_ENV = "production"
223
+ PORT = "3000"
224
+
225
+ # Health check configuration
226
+ [[services.healthchecks]]
227
+ path = "/health"
228
+ interval = 30
229
+ timeout = 10
230
+ threshold = 3
231
+
232
+ # Resource configuration
233
+ # Adjust in Railway dashboard or via CLI:
234
+ # railway up --memory 512 --cpu 0.5
235
+
236
+ # Scaling configuration
237
+ # Use Railway's autoscaling in dashboard:
238
+ # Min instances: 0 (scale to zero)
239
+ # Max instances: 3
240
+ # Target CPU: 70%
241
+ # Target Memory: 80%
242
+ `;
243
+ }
244
+
245
+ /**
246
+ * Get deployment template for a specific platform
247
+ */
248
+ export function getDeployTemplate(
249
+ platform: DeployPlatform,
250
+ projectName: string,
251
+ database?: string,
252
+ ): string {
253
+ switch (platform) {
254
+ case 'render':
255
+ return getRenderYamlTemplate(projectName, database);
256
+ case 'fly':
257
+ return getFlyTomlTemplate(projectName);
258
+ case 'railway':
259
+ return getRailwayTomlTemplate(projectName);
260
+ default:
261
+ throw new Error(`Unknown deployment platform: ${platform}`);
262
+ }
263
+ }
264
+
265
+ /**
266
+ * Get the filename for a deployment configuration
267
+ */
268
+ export function getDeployFilename(platform: DeployPlatform): string {
269
+ switch (platform) {
270
+ case 'render':
271
+ return 'render.yaml';
272
+ case 'fly':
273
+ return 'fly.toml';
274
+ case 'railway':
275
+ return 'railway.toml';
276
+ default:
277
+ throw new Error(`Unknown deployment platform: ${platform}`);
278
+ }
279
+ }
280
+
281
+ /**
282
+ * Get deployment platform display name
283
+ */
284
+ export function getDeployPlatformName(platform: DeployPlatform): string {
285
+ switch (platform) {
286
+ case 'render':
287
+ return 'Render.com';
288
+ case 'fly':
289
+ return 'Fly.io';
290
+ case 'railway':
291
+ return 'Railway';
292
+ default:
293
+ return platform;
294
+ }
295
+ }