@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,276 @@
1
+ /**
2
+ * Validation System
3
+ *
4
+ * Multi-validator support using Standard Schema interface.
5
+ * Works with Zod 4, Valibot v1, ArkType, Typia, and any Standard Schema compliant library.
6
+ */
7
+
8
+ import type { Context } from "../context";
9
+ import type {
10
+ Middleware,
11
+ StandardIssue,
12
+ StandardResult,
13
+ StandardSchema,
14
+ } from "../types";
15
+
16
+ // ============= Types =============
17
+
18
+ export type ValidationResult<T> =
19
+ | { success: true; data: T }
20
+ | { success: false; issues: StandardIssue[] };
21
+
22
+ export interface ValidatorOptions {
23
+ body?: StandardSchema;
24
+ query?: StandardSchema;
25
+ params?: StandardSchema;
26
+ headers?: StandardSchema;
27
+ }
28
+
29
+ // ============= Core Validation Function =============
30
+
31
+ /**
32
+ * Validate data against any Standard Schema compliant schema
33
+ *
34
+ * Supports:
35
+ * - Zod 4+ (zod)
36
+ * - Valibot v1+ (valibot)
37
+ * - ArkType (arktype)
38
+ * - Typia 7+ (typia) - use typia.createValidate<T>() for Standard Schema compatibility
39
+ * - Any library implementing Standard Schema
40
+ */
41
+ export async function validate<T>(
42
+ schema: StandardSchema<unknown, T>,
43
+ data: unknown,
44
+ ): Promise<ValidationResult<T>> {
45
+ try {
46
+ const result = await Promise.resolve(schema["~standard"].validate(data));
47
+
48
+ if ("value" in result) {
49
+ return { success: true, data: result.value };
50
+ }
51
+
52
+ return {
53
+ success: false,
54
+ issues: [...result.issues],
55
+ };
56
+ } catch (error) {
57
+ return {
58
+ success: false,
59
+ issues: [
60
+ {
61
+ message: error instanceof Error ? error.message : "Validation failed",
62
+ },
63
+ ],
64
+ };
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Synchronous validation (for sync validators only)
70
+ */
71
+ export function validateSync<T>(
72
+ schema: StandardSchema<unknown, T>,
73
+ data: unknown,
74
+ ): ValidationResult<T> {
75
+ const result = schema["~standard"].validate(data);
76
+
77
+ // Check if it's a Promise (async validator)
78
+ if (result instanceof Promise) {
79
+ throw new Error("Schema uses async validation. Use validate() instead.");
80
+ }
81
+
82
+ if ("value" in result) {
83
+ return { success: true, data: result.value };
84
+ }
85
+
86
+ return { success: false, issues: [...result.issues] };
87
+ }
88
+
89
+ // ============= Request Validation Functions =============
90
+
91
+ /**
92
+ * Validate request body
93
+ */
94
+ export async function validateBody<T>(
95
+ context: Context,
96
+ schema: StandardSchema<unknown, T>,
97
+ ): Promise<ValidationResult<T>> {
98
+ try {
99
+ const body = await context.body();
100
+ return validate(schema, body);
101
+ } catch (error) {
102
+ return {
103
+ success: false,
104
+ issues: [{ message: "Failed to parse request body" }],
105
+ };
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Validate query parameters
111
+ */
112
+ export function validateQuery<T>(
113
+ context: Context,
114
+ schema: StandardSchema<unknown, T>,
115
+ ): ValidationResult<T> {
116
+ return validateSync(schema, context.query);
117
+ }
118
+
119
+ /**
120
+ * Validate path parameters
121
+ */
122
+ export function validateParams<T>(
123
+ context: Context,
124
+ schema: StandardSchema<unknown, T>,
125
+ ): ValidationResult<T> {
126
+ return validateSync(schema, context.params);
127
+ }
128
+
129
+ /**
130
+ * Validate headers
131
+ */
132
+ export function validateHeaders<T>(
133
+ context: Context,
134
+ schema: StandardSchema<unknown, T>,
135
+ ): ValidationResult<T> {
136
+ const headers: Record<string, string> = {};
137
+ context.req.headers.forEach((value, key) => {
138
+ headers[key] = value;
139
+ });
140
+ return validateSync(schema, headers);
141
+ }
142
+
143
+ // ============= Validation Middleware =============
144
+
145
+ /**
146
+ * Create validation middleware
147
+ */
148
+ export function createValidator(options: ValidatorOptions): Middleware {
149
+ return async (context: Context, next: () => Promise<Response>) => {
150
+ // Validate body
151
+ if (options.body) {
152
+ const result = await validateBody(context, options.body);
153
+ if (!result.success) {
154
+ return context
155
+ .status(400)
156
+ .json({ error: "Validation failed", issues: result.issues });
157
+ }
158
+ context.set("validatedBody", result.data);
159
+ }
160
+
161
+ // Validate query
162
+ if (options.query) {
163
+ const result = validateQuery(context, options.query);
164
+ if (!result.success) {
165
+ return context
166
+ .status(400)
167
+ .json({ error: "Validation failed", issues: result.issues });
168
+ }
169
+ context.set("validatedQuery", result.data);
170
+ }
171
+
172
+ // Validate params
173
+ if (options.params) {
174
+ const result = validateParams(context, options.params);
175
+ if (!result.success) {
176
+ return context
177
+ .status(400)
178
+ .json({ error: "Validation failed", issues: result.issues });
179
+ }
180
+ context.set("validatedParams", result.data);
181
+ }
182
+
183
+ // Validate headers
184
+ if (options.headers) {
185
+ const result = validateHeaders(context, options.headers);
186
+ if (!result.success) {
187
+ return context
188
+ .status(400)
189
+ .json({ error: "Validation failed", issues: result.issues });
190
+ }
191
+ context.set("validatedHeaders", result.data);
192
+ }
193
+
194
+ return next();
195
+ };
196
+ }
197
+
198
+ // ============= Decorator Helpers =============
199
+
200
+ /**
201
+ * Body validation decorator for route handlers
202
+ */
203
+ export function WithBody(schema: StandardSchema) {
204
+ return (
205
+ target: unknown,
206
+ propertyKey: string | symbol,
207
+ descriptor: PropertyDescriptor,
208
+ ) => {
209
+ const original = descriptor.value;
210
+ descriptor.value = async function (context: Context) {
211
+ const result = await validateBody(context, schema);
212
+ if (!result.success) {
213
+ return context
214
+ .status(400)
215
+ .json({ error: "Validation failed", issues: result.issues });
216
+ }
217
+ context.set("body", result.data);
218
+ return original.call(this, context);
219
+ };
220
+ return descriptor;
221
+ };
222
+ }
223
+
224
+ /**
225
+ * Query validation decorator for route handlers
226
+ */
227
+ export function WithQuery(schema: StandardSchema) {
228
+ return (
229
+ target: unknown,
230
+ propertyKey: string | symbol,
231
+ descriptor: PropertyDescriptor,
232
+ ) => {
233
+ const original = descriptor.value;
234
+ descriptor.value = async function (context: Context) {
235
+ const result = validateQuery(context, schema);
236
+ if (!result.success) {
237
+ return context
238
+ .status(400)
239
+ .json({ error: "Validation failed", issues: result.issues });
240
+ }
241
+ context.set("query", result.data);
242
+ return original.call(this, context);
243
+ };
244
+ return descriptor;
245
+ };
246
+ }
247
+
248
+ // ============= Type Guards =============
249
+
250
+ /**
251
+ * Check if a value is a Standard Schema
252
+ */
253
+ export function isStandardSchema(value: unknown): value is StandardSchema {
254
+ return (
255
+ typeof value === "object" &&
256
+ value !== null &&
257
+ "~standard" in value &&
258
+ typeof (value as StandardSchema)["~standard"]?.validate === "function"
259
+ );
260
+ }
261
+
262
+ // ============= Utility: Assert Schema =============
263
+
264
+ /**
265
+ * Assert that a schema implements Standard Schema
266
+ */
267
+ export function assertStandardSchema(
268
+ schema: unknown,
269
+ name = "Schema",
270
+ ): asserts schema is StandardSchema {
271
+ if (!isStandardSchema(schema)) {
272
+ throw new Error(
273
+ `${name} must implement Standard Schema interface. Supported: Zod 4+, Valibot v1+, ArkType, Typia 7+`,
274
+ );
275
+ }
276
+ }