@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.
- package/.env.example +109 -0
- package/.github/workflows/ci.yml +31 -0
- package/LICENSE +21 -0
- package/README.md +892 -0
- package/architecture.md +652 -0
- package/bun.lock +70 -0
- package/dist/cli/index.js +3233 -0
- package/dist/index.js +9014 -0
- package/package.json +77 -0
- package/src/cache/index.ts +795 -0
- package/src/cli/ARCHITECTURE.md +837 -0
- package/src/cli/bin.ts +10 -0
- package/src/cli/commands/build.ts +425 -0
- package/src/cli/commands/dev.ts +248 -0
- package/src/cli/commands/generate.ts +541 -0
- package/src/cli/commands/help.ts +55 -0
- package/src/cli/commands/index.ts +112 -0
- package/src/cli/commands/migration.ts +355 -0
- package/src/cli/commands/new.ts +804 -0
- package/src/cli/commands/start.ts +208 -0
- package/src/cli/core/args.ts +283 -0
- package/src/cli/core/console.ts +349 -0
- package/src/cli/core/index.ts +60 -0
- package/src/cli/core/prompt.ts +424 -0
- package/src/cli/core/spinner.ts +265 -0
- package/src/cli/index.ts +135 -0
- package/src/cli/templates/deploy.ts +295 -0
- package/src/cli/templates/docker.ts +307 -0
- package/src/cli/templates/index.ts +24 -0
- package/src/cli/utils/fs.ts +428 -0
- package/src/cli/utils/index.ts +8 -0
- package/src/cli/utils/strings.ts +197 -0
- package/src/config/env.ts +408 -0
- package/src/config/index.ts +506 -0
- package/src/config/loader.ts +329 -0
- package/src/config/merge.ts +285 -0
- package/src/config/types.ts +320 -0
- package/src/config/validation.ts +441 -0
- package/src/container/forward-ref.ts +143 -0
- package/src/container/index.ts +386 -0
- package/src/context/index.ts +360 -0
- package/src/database/index.ts +1142 -0
- package/src/database/migrations/index.ts +371 -0
- package/src/database/schema/index.ts +619 -0
- package/src/frontend/api-routes.ts +640 -0
- package/src/frontend/bundler.ts +643 -0
- package/src/frontend/console-client.ts +419 -0
- package/src/frontend/console-stream.ts +587 -0
- package/src/frontend/dev-server.ts +846 -0
- package/src/frontend/file-router.ts +611 -0
- package/src/frontend/frameworks/index.ts +106 -0
- package/src/frontend/frameworks/react.ts +85 -0
- package/src/frontend/frameworks/solid.ts +104 -0
- package/src/frontend/frameworks/svelte.ts +110 -0
- package/src/frontend/frameworks/vue.ts +92 -0
- package/src/frontend/hmr-client.ts +663 -0
- package/src/frontend/hmr.ts +728 -0
- package/src/frontend/index.ts +342 -0
- package/src/frontend/islands.ts +552 -0
- package/src/frontend/isr.ts +555 -0
- package/src/frontend/layout.ts +475 -0
- package/src/frontend/ssr/react.ts +446 -0
- package/src/frontend/ssr/solid.ts +523 -0
- package/src/frontend/ssr/svelte.ts +546 -0
- package/src/frontend/ssr/vue.ts +504 -0
- package/src/frontend/ssr.ts +699 -0
- package/src/frontend/types.ts +2274 -0
- package/src/health/index.ts +604 -0
- package/src/index.ts +410 -0
- package/src/lock/index.ts +587 -0
- package/src/logger/index.ts +444 -0
- package/src/logger/transports/index.ts +969 -0
- package/src/metrics/index.ts +494 -0
- package/src/middleware/built-in.ts +360 -0
- package/src/middleware/index.ts +94 -0
- package/src/modules/filters.ts +458 -0
- package/src/modules/guards.ts +405 -0
- package/src/modules/index.ts +1256 -0
- package/src/modules/interceptors.ts +574 -0
- package/src/modules/lazy.ts +418 -0
- package/src/modules/lifecycle.ts +478 -0
- package/src/modules/metadata.ts +90 -0
- package/src/modules/pipes.ts +626 -0
- package/src/router/index.ts +339 -0
- package/src/router/linear.ts +371 -0
- package/src/router/regex.ts +292 -0
- package/src/router/tree.ts +562 -0
- package/src/rpc/index.ts +1263 -0
- package/src/security/index.ts +436 -0
- package/src/ssg/index.ts +631 -0
- package/src/storage/index.ts +456 -0
- package/src/telemetry/index.ts +1097 -0
- package/src/testing/index.ts +1586 -0
- package/src/types/index.ts +236 -0
- package/src/types/optional-deps.d.ts +219 -0
- package/src/validation/index.ts +276 -0
- package/src/websocket/index.ts +1004 -0
- package/tests/integration/cli.test.ts +1016 -0
- package/tests/integration/fullstack.test.ts +234 -0
- package/tests/unit/cache.test.ts +174 -0
- package/tests/unit/cli-commands.test.ts +892 -0
- package/tests/unit/cli.test.ts +1258 -0
- package/tests/unit/container.test.ts +279 -0
- package/tests/unit/context.test.ts +221 -0
- package/tests/unit/database.test.ts +183 -0
- package/tests/unit/linear-router.test.ts +280 -0
- package/tests/unit/lock.test.ts +336 -0
- package/tests/unit/middleware.test.ts +184 -0
- package/tests/unit/modules.test.ts +142 -0
- package/tests/unit/pubsub.test.ts +257 -0
- package/tests/unit/regex-router.test.ts +265 -0
- package/tests/unit/router.test.ts +373 -0
- package/tests/unit/rpc.test.ts +1248 -0
- package/tests/unit/security.test.ts +174 -0
- package/tests/unit/telemetry.test.ts +371 -0
- package/tests/unit/test-cache.test.ts +110 -0
- package/tests/unit/test-database.test.ts +282 -0
- package/tests/unit/tree-router.test.ts +325 -0
- package/tests/unit/validation.test.ts +794 -0
- 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
|
+
}
|