@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,292 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RegexRouter
|
|
3
|
+
*
|
|
4
|
+
* Balanced performance for applications with 10-100 routes.
|
|
5
|
+
* - Compiled regex patterns for fast matching
|
|
6
|
+
* - Priority-based sorting for correct route resolution
|
|
7
|
+
* - Full feature support: params, wildcards, optional params, custom regex
|
|
8
|
+
*
|
|
9
|
+
* Best for: Medium-sized APIs, general purpose routing
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type {
|
|
13
|
+
HTTPMethod,
|
|
14
|
+
MiddlewareHandler,
|
|
15
|
+
PathParams,
|
|
16
|
+
RouteHandler,
|
|
17
|
+
} from "../types";
|
|
18
|
+
|
|
19
|
+
// ============= Types =============
|
|
20
|
+
|
|
21
|
+
export interface RouteMatch {
|
|
22
|
+
handler: RouteHandler;
|
|
23
|
+
params: PathParams;
|
|
24
|
+
middleware?: MiddlewareHandler[];
|
|
25
|
+
name?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface RouteEntry {
|
|
29
|
+
method: HTTPMethod | "ALL";
|
|
30
|
+
pattern: string;
|
|
31
|
+
handler: RouteHandler;
|
|
32
|
+
middleware?: MiddlewareHandler[];
|
|
33
|
+
name?: string;
|
|
34
|
+
regex: RegExp;
|
|
35
|
+
paramNames: string[];
|
|
36
|
+
isStatic: boolean;
|
|
37
|
+
priority: number;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface RouteOptions {
|
|
41
|
+
name?: string;
|
|
42
|
+
middleware?: MiddlewareHandler | MiddlewareHandler[];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ============= Pattern Utilities =============
|
|
46
|
+
|
|
47
|
+
function patternToRegex(pattern: string): {
|
|
48
|
+
regex: RegExp;
|
|
49
|
+
paramNames: string[];
|
|
50
|
+
isStatic: boolean;
|
|
51
|
+
hasWildcard: boolean;
|
|
52
|
+
} {
|
|
53
|
+
const paramNames: string[] = [];
|
|
54
|
+
let isStatic = true;
|
|
55
|
+
let hasWildcard = false;
|
|
56
|
+
|
|
57
|
+
const segments: string[] = [];
|
|
58
|
+
let i = 0;
|
|
59
|
+
|
|
60
|
+
while (i < pattern.length) {
|
|
61
|
+
if (pattern[i] === ":") {
|
|
62
|
+
i++;
|
|
63
|
+
|
|
64
|
+
let name = "";
|
|
65
|
+
while (i < pattern.length && /[a-zA-Z0-9_]/.test(pattern[i])) {
|
|
66
|
+
name += pattern[i];
|
|
67
|
+
i++;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
let optional = false;
|
|
71
|
+
if (i < pattern.length && pattern[i] === "?") {
|
|
72
|
+
optional = true;
|
|
73
|
+
i++;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
let customRegex = "";
|
|
77
|
+
if (i < pattern.length && pattern[i] === "<") {
|
|
78
|
+
i++;
|
|
79
|
+
while (i < pattern.length && pattern[i] !== ">") {
|
|
80
|
+
customRegex += pattern[i];
|
|
81
|
+
i++;
|
|
82
|
+
}
|
|
83
|
+
i++;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
paramNames.push(name);
|
|
87
|
+
isStatic = false;
|
|
88
|
+
|
|
89
|
+
if (optional) {
|
|
90
|
+
if (segments.length > 0 && segments[segments.length - 1] === "/") {
|
|
91
|
+
segments.pop();
|
|
92
|
+
}
|
|
93
|
+
segments.push("(?:/([^/]*))?");
|
|
94
|
+
} else if (customRegex) {
|
|
95
|
+
segments.push(`(${customRegex})`);
|
|
96
|
+
} else {
|
|
97
|
+
segments.push("([^/]+)");
|
|
98
|
+
}
|
|
99
|
+
} else if (pattern[i] === "*") {
|
|
100
|
+
hasWildcard = true;
|
|
101
|
+
isStatic = false;
|
|
102
|
+
paramNames.push("*");
|
|
103
|
+
segments.push("(.*)");
|
|
104
|
+
i++;
|
|
105
|
+
} else {
|
|
106
|
+
const char = pattern[i];
|
|
107
|
+
if (/[.+^${}()|[\]\\]/.test(char)) {
|
|
108
|
+
segments.push(`\\${char}`);
|
|
109
|
+
} else {
|
|
110
|
+
segments.push(char);
|
|
111
|
+
}
|
|
112
|
+
i++;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const regexStr = `^${segments.join("")}/?$`;
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
regex: new RegExp(regexStr, "i"),
|
|
120
|
+
paramNames,
|
|
121
|
+
isStatic,
|
|
122
|
+
hasWildcard,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function extractParams(
|
|
127
|
+
regex: RegExp,
|
|
128
|
+
paramNames: string[],
|
|
129
|
+
pathname: string,
|
|
130
|
+
): PathParams {
|
|
131
|
+
const params: PathParams = {};
|
|
132
|
+
const match = pathname.match(regex);
|
|
133
|
+
|
|
134
|
+
if (match) {
|
|
135
|
+
paramNames.forEach((name, index) => {
|
|
136
|
+
if (match[index + 1] !== undefined) {
|
|
137
|
+
params[name] = match[index + 1];
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return params;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// ============= RegexRouter Class =============
|
|
146
|
+
|
|
147
|
+
export class RegexRouter {
|
|
148
|
+
private routes: RouteEntry[] = [];
|
|
149
|
+
private groupPrefix = "";
|
|
150
|
+
private groupMiddleware: MiddlewareHandler[] = [];
|
|
151
|
+
private routeCounter = 0;
|
|
152
|
+
|
|
153
|
+
private addRoute(
|
|
154
|
+
method: HTTPMethod | "ALL",
|
|
155
|
+
pattern: string,
|
|
156
|
+
handler: RouteHandler,
|
|
157
|
+
options?: RouteOptions,
|
|
158
|
+
): void {
|
|
159
|
+
const fullPattern = this.groupPrefix + pattern;
|
|
160
|
+
const { regex, paramNames, isStatic } = patternToRegex(fullPattern);
|
|
161
|
+
|
|
162
|
+
const optsMiddleware = options?.middleware;
|
|
163
|
+
const routeMiddleware: MiddlewareHandler[] = optsMiddleware
|
|
164
|
+
? Array.isArray(optsMiddleware)
|
|
165
|
+
? optsMiddleware
|
|
166
|
+
: [optsMiddleware]
|
|
167
|
+
: [];
|
|
168
|
+
|
|
169
|
+
this.routes.push({
|
|
170
|
+
method,
|
|
171
|
+
pattern: fullPattern,
|
|
172
|
+
handler,
|
|
173
|
+
middleware: [...this.groupMiddleware, ...routeMiddleware],
|
|
174
|
+
name: options?.name,
|
|
175
|
+
regex,
|
|
176
|
+
paramNames,
|
|
177
|
+
isStatic,
|
|
178
|
+
priority: this.routeCounter++,
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
this.sortRoutes();
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
private sortRoutes(): void {
|
|
185
|
+
this.routes.sort((a, b) => {
|
|
186
|
+
if (a.isStatic !== b.isStatic) {
|
|
187
|
+
return a.isStatic ? -1 : 1;
|
|
188
|
+
}
|
|
189
|
+
if (a.paramNames.length !== b.paramNames.length) {
|
|
190
|
+
return a.paramNames.length - b.paramNames.length;
|
|
191
|
+
}
|
|
192
|
+
return a.priority - b.priority;
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
match(method: HTTPMethod | "ALL", pathname: string): RouteMatch | undefined {
|
|
197
|
+
for (const route of this.routes) {
|
|
198
|
+
if (route.method !== "ALL" && route.method !== method) {
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (route.regex.test(pathname)) {
|
|
203
|
+
const params = extractParams(route.regex, route.paramNames, pathname);
|
|
204
|
+
return {
|
|
205
|
+
handler: route.handler,
|
|
206
|
+
params,
|
|
207
|
+
middleware: route.middleware,
|
|
208
|
+
name: route.name,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return undefined;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
group(
|
|
217
|
+
prefix: string,
|
|
218
|
+
options?: { middleware?: MiddlewareHandler | MiddlewareHandler[] },
|
|
219
|
+
): RegexRouter {
|
|
220
|
+
const childRouter = new RegexRouter();
|
|
221
|
+
childRouter.routes = this.routes;
|
|
222
|
+
childRouter.groupPrefix = this.groupPrefix + prefix;
|
|
223
|
+
|
|
224
|
+
const optsMiddleware = options?.middleware;
|
|
225
|
+
const middlewareArray: MiddlewareHandler[] = optsMiddleware
|
|
226
|
+
? Array.isArray(optsMiddleware)
|
|
227
|
+
? optsMiddleware
|
|
228
|
+
: [optsMiddleware]
|
|
229
|
+
: [];
|
|
230
|
+
|
|
231
|
+
childRouter.groupMiddleware = [...this.groupMiddleware, ...middlewareArray];
|
|
232
|
+
childRouter.routeCounter = this.routeCounter;
|
|
233
|
+
|
|
234
|
+
return childRouter;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
getRoutes(): Array<{
|
|
238
|
+
method: HTTPMethod | "ALL";
|
|
239
|
+
pattern: string;
|
|
240
|
+
name?: string;
|
|
241
|
+
}> {
|
|
242
|
+
return this.routes.map((r) => ({
|
|
243
|
+
method: r.method,
|
|
244
|
+
pattern: r.pattern,
|
|
245
|
+
name: r.name,
|
|
246
|
+
}));
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
getRouterType(): "regex" {
|
|
250
|
+
return "regex";
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
getRouteCount(): number {
|
|
254
|
+
return this.routes.length;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
get(pattern: string, handler: RouteHandler, options?: RouteOptions): void {
|
|
258
|
+
this.addRoute("GET", pattern, handler, options);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
post(pattern: string, handler: RouteHandler, options?: RouteOptions): void {
|
|
262
|
+
this.addRoute("POST", pattern, handler, options);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
put(pattern: string, handler: RouteHandler, options?: RouteOptions): void {
|
|
266
|
+
this.addRoute("PUT", pattern, handler, options);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
patch(pattern: string, handler: RouteHandler, options?: RouteOptions): void {
|
|
270
|
+
this.addRoute("PATCH", pattern, handler, options);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
delete(pattern: string, handler: RouteHandler, options?: RouteOptions): void {
|
|
274
|
+
this.addRoute("DELETE", pattern, handler, options);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
head(pattern: string, handler: RouteHandler, options?: RouteOptions): void {
|
|
278
|
+
this.addRoute("HEAD", pattern, handler, options);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
options(
|
|
282
|
+
pattern: string,
|
|
283
|
+
handler: RouteHandler,
|
|
284
|
+
options?: RouteOptions,
|
|
285
|
+
): void {
|
|
286
|
+
this.addRoute("OPTIONS", pattern, handler, options);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
all(pattern: string, handler: RouteHandler, options?: RouteOptions): void {
|
|
290
|
+
this.addRoute("ALL", pattern, handler, options);
|
|
291
|
+
}
|
|
292
|
+
}
|