@rainfw/core 0.1.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/LICENSE +21 -0
- package/cli/commands/db.js +399 -0
- package/cli/index.js +206 -0
- package/cli/templates/drizzle-config.js +15 -0
- package/cli/templates/schema.js +16 -0
- package/cli/utils/process.js +23 -0
- package/cli/utils/sanitize.d.ts +1 -0
- package/cli/utils/sanitize.js +8 -0
- package/cli/utils/toml-parser.d.ts +10 -0
- package/cli/utils/toml-parser.js +58 -0
- package/dist/bindings.d.ts +3 -0
- package/dist/bindings.d.ts.map +1 -0
- package/dist/bindings.js +17 -0
- package/dist/bindings.js.map +1 -0
- package/dist/context.d.ts +53 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +246 -0
- package/dist/context.js.map +1 -0
- package/dist/cookie.d.ts +12 -0
- package/dist/cookie.d.ts.map +1 -0
- package/dist/cookie.js +68 -0
- package/dist/cookie.js.map +1 -0
- package/dist/errors.d.ts +5 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +8 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/jsx/createElement.d.ts +4 -0
- package/dist/jsx/createElement.d.ts.map +1 -0
- package/dist/jsx/createElement.js +19 -0
- package/dist/jsx/createElement.js.map +1 -0
- package/dist/jsx/escape.d.ts +2 -0
- package/dist/jsx/escape.d.ts.map +1 -0
- package/dist/jsx/escape.js +12 -0
- package/dist/jsx/escape.js.map +1 -0
- package/dist/jsx/index.d.ts +6 -0
- package/dist/jsx/index.d.ts.map +1 -0
- package/dist/jsx/index.js +5 -0
- package/dist/jsx/index.js.map +1 -0
- package/dist/jsx/jsx-namespace.d.ts +23 -0
- package/dist/jsx/jsx-namespace.d.ts.map +1 -0
- package/dist/jsx/jsx-namespace.js +2 -0
- package/dist/jsx/jsx-namespace.js.map +1 -0
- package/dist/jsx/jsx-runtime.d.ts +6 -0
- package/dist/jsx/jsx-runtime.d.ts.map +1 -0
- package/dist/jsx/jsx-runtime.js +20 -0
- package/dist/jsx/jsx-runtime.js.map +1 -0
- package/dist/jsx/render.d.ts +4 -0
- package/dist/jsx/render.d.ts.map +1 -0
- package/dist/jsx/render.js +134 -0
- package/dist/jsx/render.js.map +1 -0
- package/dist/jsx/types.d.ts +11 -0
- package/dist/jsx/types.d.ts.map +1 -0
- package/dist/jsx/types.js +2 -0
- package/dist/jsx/types.js.map +1 -0
- package/dist/jsx-runtime.d.ts +23 -0
- package/dist/jsx-runtime.d.ts.map +1 -0
- package/dist/jsx-runtime.js +2 -0
- package/dist/jsx-runtime.js.map +1 -0
- package/dist/middleware/cors.d.ts +12 -0
- package/dist/middleware/cors.d.ts.map +1 -0
- package/dist/middleware/cors.js +75 -0
- package/dist/middleware/cors.js.map +1 -0
- package/dist/middleware/session.d.ts +24 -0
- package/dist/middleware/session.d.ts.map +1 -0
- package/dist/middleware/session.js +124 -0
- package/dist/middleware/session.js.map +1 -0
- package/dist/package.json +1 -0
- package/dist/renderers/react.d.ts +9 -0
- package/dist/renderers/react.d.ts.map +1 -0
- package/dist/renderers/react.js +40 -0
- package/dist/renderers/react.js.map +1 -0
- package/dist/router.d.ts +36 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +363 -0
- package/dist/router.js.map +1 -0
- package/dist/types.d.ts +29 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/regexp.d.ts +2 -0
- package/dist/utils/regexp.d.ts.map +1 -0
- package/dist/utils/regexp.js +4 -0
- package/dist/utils/regexp.js.map +1 -0
- package/dist/utils/url.d.ts +2 -0
- package/dist/utils/url.d.ts.map +1 -0
- package/dist/utils/url.js +9 -0
- package/dist/utils/url.js.map +1 -0
- package/package.json +81 -0
- package/scripts/dev.js +58 -0
- package/scripts/generate.js +660 -0
package/dist/router.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { ErrorHandler, Handler, LayoutHandler, Middleware, PageHandler, RainConfig, RainOptions } from "./types";
|
|
2
|
+
export declare class Rain {
|
|
3
|
+
private routes;
|
|
4
|
+
private globalMiddlewares;
|
|
5
|
+
private errorHandler;
|
|
6
|
+
private csrfProtection;
|
|
7
|
+
private securityHeaders;
|
|
8
|
+
constructor(options?: RainConfig | RainOptions);
|
|
9
|
+
use(...middlewares: Middleware[]): void;
|
|
10
|
+
private addRoute;
|
|
11
|
+
onError(handler: ErrorHandler): void;
|
|
12
|
+
get(path: string, handler: Handler, middlewares?: Middleware[]): void;
|
|
13
|
+
post(path: string, handler: Handler, middlewares?: Middleware[]): void;
|
|
14
|
+
put(path: string, handler: Handler, middlewares?: Middleware[]): void;
|
|
15
|
+
delete(path: string, handler: Handler, middlewares?: Middleware[]): void;
|
|
16
|
+
patch(path: string, handler: Handler, middlewares?: Middleware[]): void;
|
|
17
|
+
head(path: string, handler: Handler, middlewares?: Middleware[]): void;
|
|
18
|
+
options(path: string, handler: Handler, middlewares?: Middleware[]): void;
|
|
19
|
+
page(path: string, handler: PageHandler, layouts?: LayoutHandler[], middlewares?: Middleware[], doctype?: boolean): void;
|
|
20
|
+
private composeMiddlewares;
|
|
21
|
+
fetch(request: Request, env?: Env, executionCtx?: ExecutionContext): Promise<Response>;
|
|
22
|
+
private mergeMiddlewares;
|
|
23
|
+
private handleRequest;
|
|
24
|
+
private matchRoute;
|
|
25
|
+
private executeHeadFallback;
|
|
26
|
+
private executeRoute;
|
|
27
|
+
private buildMethodNotAllowed;
|
|
28
|
+
private applySecurityHeaders;
|
|
29
|
+
private applyCookies;
|
|
30
|
+
private validateCsrf;
|
|
31
|
+
private extractOrigin;
|
|
32
|
+
private csrfForbiddenResponse;
|
|
33
|
+
private handleError;
|
|
34
|
+
private tryServeStaticAsset;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/framework/router.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,YAAY,EACZ,OAAO,EACP,aAAa,EACb,UAAU,EACV,WAAW,EACX,UAAU,EACV,WAAW,EACZ,MAAM,SAAS,CAAC;AAmCjB,qBAAa,IAAI;IACf,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,YAAY,CAA2B;IAC/C,OAAO,CAAC,cAAc,CAAU;IAChC,OAAO,CAAC,eAAe,CAA2C;gBAEtD,OAAO,CAAC,EAAE,UAAU,GAAG,WAAW;IAW9C,GAAG,CAAC,GAAG,WAAW,EAAE,UAAU,EAAE,GAAG,IAAI;IAIvC,OAAO,CAAC,QAAQ;IAsChB,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAIpC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,UAAU,EAAE,GAAG,IAAI;IAIrE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,UAAU,EAAE,GAAG,IAAI;IAItE,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,UAAU,EAAE,GAAG,IAAI;IAIrE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,UAAU,EAAE,GAAG,IAAI;IAIxE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,UAAU,EAAE,GAAG,IAAI;IAIvE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,UAAU,EAAE,GAAG,IAAI;IAItE,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,UAAU,EAAE,GAAG,IAAI;IAIzE,IAAI,CACF,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE,aAAa,EAAO,EAC7B,WAAW,GAAE,UAAU,EAAO,EAC9B,OAAO,UAAQ,GACd,IAAI;IA2BP,OAAO,CAAC,kBAAkB;IA0B1B,KAAK,CACH,OAAO,EAAE,OAAO,EAChB,GAAG,CAAC,EAAE,GAAG,EACT,YAAY,CAAC,EAAE,gBAAgB,GAC9B,OAAO,CAAC,QAAQ,CAAC;IAYpB,OAAO,CAAC,gBAAgB;YASV,aAAa;IAuD3B,OAAO,CAAC,UAAU;YA0CJ,mBAAmB;YAwBnB,YAAY;YAsCZ,qBAAqB;IAqBnC,OAAO,CAAC,oBAAoB;IAkB5B,OAAO,CAAC,YAAY;IAcpB,OAAO,CAAC,YAAY;IA2BpB,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,qBAAqB;YAiBf,WAAW;YA0BX,mBAAmB;CAsBlC"}
|
package/dist/router.js
ADDED
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
import { runWithBindings } from "./bindings";
|
|
2
|
+
import { Context } from "./context";
|
|
3
|
+
import { HttpError } from "./errors";
|
|
4
|
+
import { renderToString } from "./jsx";
|
|
5
|
+
import { escapeRegExp } from "./utils/regexp";
|
|
6
|
+
import { safeDecodeURIComponent } from "./utils/url";
|
|
7
|
+
const DEFAULT_SECURITY_HEADERS = [
|
|
8
|
+
["X-Content-Type-Options", "nosniff"],
|
|
9
|
+
["X-Frame-Options", "DENY"],
|
|
10
|
+
["Referrer-Policy", "strict-origin-when-cross-origin"],
|
|
11
|
+
["X-XSS-Protection", "0"],
|
|
12
|
+
];
|
|
13
|
+
const STATE_CHANGING_METHODS = new Set(["POST", "PUT", "DELETE", "PATCH"]);
|
|
14
|
+
function resolveSecurityHeaders(config) {
|
|
15
|
+
if (config === false)
|
|
16
|
+
return [];
|
|
17
|
+
if (!config)
|
|
18
|
+
return DEFAULT_SECURITY_HEADERS;
|
|
19
|
+
const merged = new Map(DEFAULT_SECURITY_HEADERS.map(([k, v]) => [k, v]));
|
|
20
|
+
for (const [key, value] of Object.entries(config)) {
|
|
21
|
+
merged.set(key, value);
|
|
22
|
+
}
|
|
23
|
+
return [...merged.entries()].map(([k, v]) => [k, v]);
|
|
24
|
+
}
|
|
25
|
+
export class Rain {
|
|
26
|
+
routes = [];
|
|
27
|
+
globalMiddlewares = [];
|
|
28
|
+
errorHandler;
|
|
29
|
+
csrfProtection;
|
|
30
|
+
securityHeaders;
|
|
31
|
+
constructor(options) {
|
|
32
|
+
const csrf = options?.csrf ??
|
|
33
|
+
options?.csrfProtection ??
|
|
34
|
+
true;
|
|
35
|
+
this.csrfProtection = csrf;
|
|
36
|
+
this.securityHeaders = resolveSecurityHeaders(options?.securityHeaders);
|
|
37
|
+
}
|
|
38
|
+
use(...middlewares) {
|
|
39
|
+
this.globalMiddlewares.push(...middlewares);
|
|
40
|
+
}
|
|
41
|
+
addRoute(method, path, handler, middlewares = []) {
|
|
42
|
+
const paramNames = [];
|
|
43
|
+
const segments = path.split("/");
|
|
44
|
+
const regexPath = segments
|
|
45
|
+
.map((segment) => {
|
|
46
|
+
if (segment.startsWith(":")) {
|
|
47
|
+
paramNames.push(segment.slice(1));
|
|
48
|
+
return "([^/]+)";
|
|
49
|
+
}
|
|
50
|
+
return escapeRegExp(segment);
|
|
51
|
+
})
|
|
52
|
+
.join("/");
|
|
53
|
+
const seen = new Set();
|
|
54
|
+
for (const name of paramNames) {
|
|
55
|
+
if (seen.has(name)) {
|
|
56
|
+
throw new Error(`Duplicate parameter name ':${name}' in route ${path}. ` +
|
|
57
|
+
"Rename the directory so that parameter names are unique.");
|
|
58
|
+
}
|
|
59
|
+
seen.add(name);
|
|
60
|
+
}
|
|
61
|
+
this.routes.push({
|
|
62
|
+
method,
|
|
63
|
+
pattern: new RegExp(`^${regexPath}$`),
|
|
64
|
+
paramNames,
|
|
65
|
+
handler,
|
|
66
|
+
middlewares,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
onError(handler) {
|
|
70
|
+
this.errorHandler = handler;
|
|
71
|
+
}
|
|
72
|
+
get(path, handler, middlewares) {
|
|
73
|
+
this.addRoute("GET", path, handler, middlewares);
|
|
74
|
+
}
|
|
75
|
+
post(path, handler, middlewares) {
|
|
76
|
+
this.addRoute("POST", path, handler, middlewares);
|
|
77
|
+
}
|
|
78
|
+
put(path, handler, middlewares) {
|
|
79
|
+
this.addRoute("PUT", path, handler, middlewares);
|
|
80
|
+
}
|
|
81
|
+
delete(path, handler, middlewares) {
|
|
82
|
+
this.addRoute("DELETE", path, handler, middlewares);
|
|
83
|
+
}
|
|
84
|
+
patch(path, handler, middlewares) {
|
|
85
|
+
this.addRoute("PATCH", path, handler, middlewares);
|
|
86
|
+
}
|
|
87
|
+
head(path, handler, middlewares) {
|
|
88
|
+
this.addRoute("HEAD", path, handler, middlewares);
|
|
89
|
+
}
|
|
90
|
+
options(path, handler, middlewares) {
|
|
91
|
+
this.addRoute("OPTIONS", path, handler, middlewares);
|
|
92
|
+
}
|
|
93
|
+
page(path, handler, layouts = [], middlewares = [], doctype = false) {
|
|
94
|
+
const wrappedHandler = async (ctx) => {
|
|
95
|
+
let content = await handler(ctx);
|
|
96
|
+
for (let i = layouts.length - 1; i >= 0; i--) {
|
|
97
|
+
try {
|
|
98
|
+
content = await layouts[i](ctx, content);
|
|
99
|
+
}
|
|
100
|
+
catch (cause) {
|
|
101
|
+
const depth = layouts.length - i;
|
|
102
|
+
const total = layouts.length;
|
|
103
|
+
throw new Error(`[Rain] Layout error at depth ${depth}/${total}` +
|
|
104
|
+
` while rendering page '${path}'.` +
|
|
105
|
+
" Check your layout.tsx files for this route.", { cause });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const html = renderToString(content);
|
|
109
|
+
const body = doctype ? `<!DOCTYPE html>\n${html}` : html;
|
|
110
|
+
return new Response(body, {
|
|
111
|
+
status: 200,
|
|
112
|
+
headers: { "content-type": "text/html; charset=UTF-8" },
|
|
113
|
+
});
|
|
114
|
+
};
|
|
115
|
+
this.addRoute("GET", path, wrappedHandler, middlewares);
|
|
116
|
+
}
|
|
117
|
+
composeMiddlewares(middlewares, handler) {
|
|
118
|
+
return (ctx) => {
|
|
119
|
+
let index = -1;
|
|
120
|
+
const dispatch = (i) => {
|
|
121
|
+
if (i <= index) {
|
|
122
|
+
return Promise.reject(new Error("[Rain] next() was called multiple times in a middleware. " +
|
|
123
|
+
"Each middleware must call next() at most once."));
|
|
124
|
+
}
|
|
125
|
+
index = i;
|
|
126
|
+
if (i < middlewares.length) {
|
|
127
|
+
const mw = middlewares[i];
|
|
128
|
+
return Promise.resolve(mw(ctx, () => dispatch(i + 1)));
|
|
129
|
+
}
|
|
130
|
+
return Promise.resolve(handler(ctx));
|
|
131
|
+
};
|
|
132
|
+
return dispatch(0);
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
fetch(request, env, executionCtx) {
|
|
136
|
+
const resolvedEnv = env ?? {};
|
|
137
|
+
return runWithBindings(resolvedEnv, async () => {
|
|
138
|
+
const response = await this.handleRequest(request, resolvedEnv, executionCtx);
|
|
139
|
+
return this.applySecurityHeaders(response);
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
mergeMiddlewares(routeMiddlewares) {
|
|
143
|
+
if (this.globalMiddlewares.length === 0 && routeMiddlewares.length === 0) {
|
|
144
|
+
return [];
|
|
145
|
+
}
|
|
146
|
+
if (this.globalMiddlewares.length === 0)
|
|
147
|
+
return routeMiddlewares;
|
|
148
|
+
if (routeMiddlewares.length === 0)
|
|
149
|
+
return this.globalMiddlewares;
|
|
150
|
+
return [...this.globalMiddlewares, ...routeMiddlewares];
|
|
151
|
+
}
|
|
152
|
+
async handleRequest(request, env, executionCtx) {
|
|
153
|
+
const csrfResponse = this.validateCsrf(request);
|
|
154
|
+
if (csrfResponse)
|
|
155
|
+
return csrfResponse;
|
|
156
|
+
const { pathname } = new URL(request.url);
|
|
157
|
+
const method = request.method;
|
|
158
|
+
try {
|
|
159
|
+
const result = this.matchRoute(method, pathname);
|
|
160
|
+
if (result.route) {
|
|
161
|
+
return await this.executeRoute(result.route, result.match, request, env, executionCtx, method, pathname);
|
|
162
|
+
}
|
|
163
|
+
if (method === "HEAD" && result.getFallback) {
|
|
164
|
+
return await this.executeHeadFallback(result.getFallback.route, result.getFallback.match, request, env, executionCtx, pathname);
|
|
165
|
+
}
|
|
166
|
+
if (result.pathMatched) {
|
|
167
|
+
return this.buildMethodNotAllowed(request, env, executionCtx, result.firstMiddlewares ?? []);
|
|
168
|
+
}
|
|
169
|
+
const assetResponse = await this.tryServeStaticAsset(request, env);
|
|
170
|
+
if (assetResponse)
|
|
171
|
+
return assetResponse;
|
|
172
|
+
return new Response("Not Found", { status: 404 });
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
return this.handleError(error, request, pathname);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
matchRoute(method, pathname) {
|
|
179
|
+
let pathMatched = false;
|
|
180
|
+
let firstMiddlewares;
|
|
181
|
+
let getFallback;
|
|
182
|
+
const trackGetFallback = method === "HEAD";
|
|
183
|
+
for (const route of this.routes) {
|
|
184
|
+
const match = pathname.match(route.pattern);
|
|
185
|
+
if (!match)
|
|
186
|
+
continue;
|
|
187
|
+
pathMatched = true;
|
|
188
|
+
firstMiddlewares ??= route.middlewares;
|
|
189
|
+
if (route.method === method) {
|
|
190
|
+
return { route, match, pathMatched, firstMiddlewares };
|
|
191
|
+
}
|
|
192
|
+
if (trackGetFallback && route.method === "GET" && !getFallback) {
|
|
193
|
+
getFallback = { route, match };
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
const base = {
|
|
197
|
+
match: [],
|
|
198
|
+
pathMatched,
|
|
199
|
+
firstMiddlewares,
|
|
200
|
+
};
|
|
201
|
+
if (getFallback) {
|
|
202
|
+
return { ...base, getFallback };
|
|
203
|
+
}
|
|
204
|
+
return base;
|
|
205
|
+
}
|
|
206
|
+
async executeHeadFallback(route, match, request, env, executionCtx, pathname) {
|
|
207
|
+
const response = await this.executeRoute(route, match, request, env, executionCtx, "HEAD", pathname);
|
|
208
|
+
return new Response(null, {
|
|
209
|
+
status: response.status,
|
|
210
|
+
statusText: response.statusText,
|
|
211
|
+
headers: response.headers,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
async executeRoute(route, match, request, env, executionCtx, method, pathname) {
|
|
215
|
+
const params = {};
|
|
216
|
+
route.paramNames.forEach((name, i) => {
|
|
217
|
+
const value = match[i + 1];
|
|
218
|
+
if (value !== undefined) {
|
|
219
|
+
params[name] = safeDecodeURIComponent(value);
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
const ctx = new Context(request, params, env, executionCtx);
|
|
223
|
+
const allMiddlewares = this.mergeMiddlewares(route.middlewares);
|
|
224
|
+
const composed = this.composeMiddlewares(allMiddlewares, route.handler);
|
|
225
|
+
const response = await composed(ctx);
|
|
226
|
+
if (!(response instanceof Response)) {
|
|
227
|
+
const detail = `Route handler for ${method} ${pathname}` +
|
|
228
|
+
" did not return a Response object.";
|
|
229
|
+
const fix = "Return a Response from your handler:" +
|
|
230
|
+
" return ctx.text('Hello') or return new Response(...)";
|
|
231
|
+
console.error(`[Rain] ${detail} ${fix}`);
|
|
232
|
+
return new Response("Internal Server Error", {
|
|
233
|
+
status: 500,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
return this.applyCookies(response, ctx);
|
|
237
|
+
}
|
|
238
|
+
async buildMethodNotAllowed(request, env, executionCtx, routeMiddlewares) {
|
|
239
|
+
const allMiddlewares = this.mergeMiddlewares(routeMiddlewares);
|
|
240
|
+
const ctx = new Context(request, {}, env, executionCtx);
|
|
241
|
+
if (allMiddlewares.length === 0) {
|
|
242
|
+
return this.applyCookies(new Response("Method Not Allowed", { status: 405 }), ctx);
|
|
243
|
+
}
|
|
244
|
+
const methodNotAllowed = () => new Response("Method Not Allowed", { status: 405 });
|
|
245
|
+
const composed = this.composeMiddlewares(allMiddlewares, methodNotAllowed);
|
|
246
|
+
const response = await composed(ctx);
|
|
247
|
+
return this.applyCookies(response, ctx);
|
|
248
|
+
}
|
|
249
|
+
applySecurityHeaders(response) {
|
|
250
|
+
if (this.securityHeaders.length === 0)
|
|
251
|
+
return response;
|
|
252
|
+
const headers = new Headers(response.headers);
|
|
253
|
+
let modified = false;
|
|
254
|
+
for (const [name, value] of this.securityHeaders) {
|
|
255
|
+
if (!headers.has(name)) {
|
|
256
|
+
headers.set(name, value);
|
|
257
|
+
modified = true;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
if (!modified)
|
|
261
|
+
return response;
|
|
262
|
+
return new Response(response.body, {
|
|
263
|
+
status: response.status,
|
|
264
|
+
statusText: response.statusText,
|
|
265
|
+
headers,
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
applyCookies(response, ctx) {
|
|
269
|
+
const pending = ctx.getPendingCookies();
|
|
270
|
+
if (pending.length === 0)
|
|
271
|
+
return response;
|
|
272
|
+
const headers = new Headers(response.headers);
|
|
273
|
+
for (const cookie of pending) {
|
|
274
|
+
headers.append("Set-Cookie", cookie);
|
|
275
|
+
}
|
|
276
|
+
return new Response(response.body, {
|
|
277
|
+
status: response.status,
|
|
278
|
+
statusText: response.statusText,
|
|
279
|
+
headers,
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
validateCsrf(request) {
|
|
283
|
+
if (!this.csrfProtection)
|
|
284
|
+
return null;
|
|
285
|
+
if (!STATE_CHANGING_METHODS.has(request.method)) {
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
const requestOrigin = new URL(request.url).origin;
|
|
289
|
+
const origin = request.headers.get("Origin");
|
|
290
|
+
if (origin) {
|
|
291
|
+
if (origin !== requestOrigin) {
|
|
292
|
+
return this.csrfForbiddenResponse(origin, requestOrigin);
|
|
293
|
+
}
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
const referer = request.headers.get("Referer");
|
|
297
|
+
if (referer) {
|
|
298
|
+
const refererOrigin = this.extractOrigin(referer);
|
|
299
|
+
if (refererOrigin && refererOrigin !== requestOrigin) {
|
|
300
|
+
return this.csrfForbiddenResponse(refererOrigin, requestOrigin);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
305
|
+
extractOrigin(url) {
|
|
306
|
+
try {
|
|
307
|
+
return new URL(url).origin;
|
|
308
|
+
}
|
|
309
|
+
catch {
|
|
310
|
+
return null;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
csrfForbiddenResponse(received, expected) {
|
|
314
|
+
const message = "[Rain] CSRF validation failed: " +
|
|
315
|
+
`Origin '${received}' does not match ` +
|
|
316
|
+
`request origin '${expected}'. ` +
|
|
317
|
+
"If this is a legitimate cross-origin " +
|
|
318
|
+
"request, configure CORS or disable " +
|
|
319
|
+
"CSRF protection: " +
|
|
320
|
+
"new Rain({ csrf: false })";
|
|
321
|
+
return new Response(message, {
|
|
322
|
+
status: 403,
|
|
323
|
+
headers: {
|
|
324
|
+
"content-type": "text/plain; charset=UTF-8",
|
|
325
|
+
},
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
async handleError(error, request, pathname) {
|
|
329
|
+
if (this.errorHandler) {
|
|
330
|
+
try {
|
|
331
|
+
return await this.errorHandler(error, request);
|
|
332
|
+
}
|
|
333
|
+
catch (onErrorError) {
|
|
334
|
+
console.error("[Rain] Error in onError handler.", onErrorError);
|
|
335
|
+
return new Response("Internal Server Error", { status: 500 });
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
if (error instanceof HttpError) {
|
|
339
|
+
return new Response(error.message, { status: error.status });
|
|
340
|
+
}
|
|
341
|
+
console.error(`[Rain] Unhandled error on ${request.method} ${pathname}.`, "Use app.onError() to add custom error handling.", error);
|
|
342
|
+
return new Response("Internal Server Error", { status: 500 });
|
|
343
|
+
}
|
|
344
|
+
async tryServeStaticAsset(request, env) {
|
|
345
|
+
if (request.method !== "GET" && request.method !== "HEAD") {
|
|
346
|
+
return null;
|
|
347
|
+
}
|
|
348
|
+
const assets = env.ASSETS;
|
|
349
|
+
if (!assets)
|
|
350
|
+
return null;
|
|
351
|
+
try {
|
|
352
|
+
const response = await assets.fetch(request);
|
|
353
|
+
if (response.status === 404)
|
|
354
|
+
return null;
|
|
355
|
+
return response;
|
|
356
|
+
}
|
|
357
|
+
catch (error) {
|
|
358
|
+
console.error("[Rain] Static asset fetch failed.", "Check the [assets] configuration in wrangler.toml.", error);
|
|
359
|
+
return null;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
//# sourceMappingURL=router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../src/framework/router.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Context } from "./context";
|
|
2
|
+
import type { RainElement } from "./jsx/types";
|
|
3
|
+
declare global {
|
|
4
|
+
interface Env {
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
export interface StateKey<T> {
|
|
8
|
+
readonly id: string;
|
|
9
|
+
readonly _brand: T;
|
|
10
|
+
}
|
|
11
|
+
export declare function defineKey<T>(id: string): StateKey<T>;
|
|
12
|
+
export interface RainConfig {
|
|
13
|
+
routesDir?: string;
|
|
14
|
+
outDir?: string;
|
|
15
|
+
csrf?: boolean;
|
|
16
|
+
securityHeaders?: Record<string, string> | false;
|
|
17
|
+
}
|
|
18
|
+
export interface RainOptions {
|
|
19
|
+
csrfProtection?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export type Handler = (ctx: Context) => Response | Promise<Response>;
|
|
22
|
+
export type PageHandler = (ctx: Context) => RainElement | Promise<RainElement>;
|
|
23
|
+
export type LayoutHandler = (ctx: Context, children: RainElement) => RainElement | Promise<RainElement>;
|
|
24
|
+
export type Middleware = (ctx: Context, next: () => Promise<Response>) => Response | Promise<Response>;
|
|
25
|
+
export type ErrorHandler = (error: unknown, req: Request) => Response | Promise<Response>;
|
|
26
|
+
export interface Schema<T> {
|
|
27
|
+
parse(data: unknown): T;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/framework/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,GAAG;KAAG;CACjB;AAED,MAAM,WAAW,QAAQ,CAAC,CAAC;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;CACpB;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,CAEpD;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC;CAClD;AAED,MAAM,WAAW,WAAW;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,MAAM,OAAO,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAErE,MAAM,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;AAE/E,MAAM,MAAM,aAAa,GAAG,CAC1B,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,WAAW,KAClB,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;AAExC,MAAM,MAAM,UAAU,GAAG,CACvB,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,KAC1B,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAElC,MAAM,MAAM,YAAY,GAAG,CACzB,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,OAAO,KACT,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAElC,MAAM,WAAW,MAAM,CAAC,CAAC;IACvB,KAAK,CAAC,IAAI,EAAE,OAAO,GAAG,CAAC,CAAC;CACzB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/framework/types.ts"],"names":[],"mappings":"AAYA,MAAM,UAAU,SAAS,CAAI,EAAU;IACrC,OAAO,EAAE,EAAE,EAAiB,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"regexp.d.ts","sourceRoot":"","sources":["../../src/framework/utils/regexp.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"regexp.js","sourceRoot":"","sources":["../../src/framework/utils/regexp.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,OAAO,GAAG,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AACpD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../src/framework/utils/url.ts"],"names":[],"mappings":"AAAA,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAM5D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url.js","sourceRoot":"","sources":["../../src/framework/utils/url.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,sBAAsB,CAAC,KAAa;IAClD,IAAI,CAAC;QACH,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rainfw/core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A lightweight TypeScript web framework for Cloudflare Workers with file-based routing",
|
|
5
|
+
"bin": {
|
|
6
|
+
"rainjs": "./cli/index.js"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"dev": "node scripts/dev.js",
|
|
10
|
+
"build": "node scripts/generate.js",
|
|
11
|
+
"lint": "biome lint .",
|
|
12
|
+
"format": "biome format --write .",
|
|
13
|
+
"check": "biome check --write .",
|
|
14
|
+
"typecheck": "tsc --noEmit",
|
|
15
|
+
"typecheck:db": "tsc --noEmit -p tsconfig.db.json",
|
|
16
|
+
"ci": "biome ci . && tsc --noEmit",
|
|
17
|
+
"test": "vitest run",
|
|
18
|
+
"test:watch": "vitest",
|
|
19
|
+
"test:generate": "node --test tests/generate.test.js",
|
|
20
|
+
"bench": "node scripts/bench.js",
|
|
21
|
+
"build:pkg": "tsc -p tsconfig.build.json && node -e \"require('fs').writeFileSync('dist/package.json',JSON.stringify({type:'module'}))\"",
|
|
22
|
+
"prepublishOnly": "npm run build:pkg"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"cloudflare-workers",
|
|
26
|
+
"web-framework",
|
|
27
|
+
"typescript",
|
|
28
|
+
"file-based-routing",
|
|
29
|
+
"jsx"
|
|
30
|
+
],
|
|
31
|
+
"author": "",
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"type": "commonjs",
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"drizzle-orm": ">=0.40.0",
|
|
36
|
+
"typescript": ">=5.0.0"
|
|
37
|
+
},
|
|
38
|
+
"peerDependenciesMeta": {
|
|
39
|
+
"drizzle-orm": {
|
|
40
|
+
"optional": true
|
|
41
|
+
},
|
|
42
|
+
"typescript": {
|
|
43
|
+
"optional": false
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"exports": {
|
|
47
|
+
".": {
|
|
48
|
+
"types": "./dist/index.d.ts",
|
|
49
|
+
"import": "./dist/index.js"
|
|
50
|
+
},
|
|
51
|
+
"./jsx-runtime": {
|
|
52
|
+
"types": "./dist/jsx-runtime.d.ts",
|
|
53
|
+
"import": "./dist/jsx-runtime.js"
|
|
54
|
+
},
|
|
55
|
+
"./db": {
|
|
56
|
+
"types": "./dist/db.d.ts",
|
|
57
|
+
"import": "./dist/db.js"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"@biomejs/biome": "^2.4.8",
|
|
62
|
+
"@cloudflare/workers-types": "^4.20260317.1",
|
|
63
|
+
"@types/node": "^25.5.0",
|
|
64
|
+
"drizzle-kit": "^0.31.10",
|
|
65
|
+
"drizzle-orm": "^0.45.2",
|
|
66
|
+
"typescript": "^5.9.3",
|
|
67
|
+
"vitest": "^4.1.1",
|
|
68
|
+
"wrangler": "^4.76.0"
|
|
69
|
+
},
|
|
70
|
+
"repository": {
|
|
71
|
+
"type": "git",
|
|
72
|
+
"url": "https://github.com/rainfw/core.git"
|
|
73
|
+
},
|
|
74
|
+
"homepage": "https://github.com/rainfw/core",
|
|
75
|
+
"files": [
|
|
76
|
+
"dist/",
|
|
77
|
+
"cli/",
|
|
78
|
+
"scripts/dev.js",
|
|
79
|
+
"scripts/generate.js"
|
|
80
|
+
]
|
|
81
|
+
}
|
package/scripts/dev.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const fs = require("node:fs");
|
|
2
|
+
const { spawn } = require("node:child_process");
|
|
3
|
+
const { generate, ROUTES_DIR } = require("./generate");
|
|
4
|
+
|
|
5
|
+
generate();
|
|
6
|
+
|
|
7
|
+
let debounceTimer = null;
|
|
8
|
+
try {
|
|
9
|
+
const watcher = fs.watch(
|
|
10
|
+
ROUTES_DIR,
|
|
11
|
+
{ recursive: true },
|
|
12
|
+
(eventType, filename) => {
|
|
13
|
+
if (!(filename?.endsWith(".ts") || filename?.endsWith(".tsx"))) return;
|
|
14
|
+
clearTimeout(debounceTimer);
|
|
15
|
+
debounceTimer = setTimeout(() => {
|
|
16
|
+
console.log(`[watch] ${eventType}: ${filename}`);
|
|
17
|
+
generate();
|
|
18
|
+
}, 100);
|
|
19
|
+
},
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
watcher.on("error", (err) => {
|
|
23
|
+
console.error(
|
|
24
|
+
"[Rain] Error: File watcher encountered an error.\n" +
|
|
25
|
+
` \u2192 ${err.message}\n` +
|
|
26
|
+
" \u2192 The dev server will continue running, " +
|
|
27
|
+
"but route changes won't be detected automatically.\n" +
|
|
28
|
+
' \u2192 Run "npm run build" manually after ' +
|
|
29
|
+
"making route changes.",
|
|
30
|
+
);
|
|
31
|
+
});
|
|
32
|
+
} catch (watchError) {
|
|
33
|
+
console.error(
|
|
34
|
+
"[Rain] Error: Failed to start file watcher " +
|
|
35
|
+
"on src/routes/.\n" +
|
|
36
|
+
` \u2192 ${watchError.message}\n` +
|
|
37
|
+
" \u2192 The dev server will still run, " +
|
|
38
|
+
"but route changes won't be detected automatically.\n" +
|
|
39
|
+
' \u2192 Run "npm run build" manually after ' +
|
|
40
|
+
"making route changes.",
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
console.log("[watch] Watching src/routes/ for changes...");
|
|
44
|
+
|
|
45
|
+
const wrangler = spawn("npx", ["wrangler", "dev"], {
|
|
46
|
+
stdio: "inherit",
|
|
47
|
+
shell: true,
|
|
48
|
+
cwd: process.cwd(),
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
process.on("SIGINT", () => {
|
|
52
|
+
wrangler.kill();
|
|
53
|
+
process.exit(0);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
wrangler.on("close", (code) => {
|
|
57
|
+
process.exit(code ?? 0);
|
|
58
|
+
});
|