hapta 1.0.13 → 1.0.15
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/helpers/HTTP/Request/Context.ts +3 -1
- package/index.ts +56 -3
- package/package.json +1 -1
- package/bun.lock +0 -48
|
@@ -94,11 +94,12 @@ type TokenOptions = {
|
|
|
94
94
|
iat: number
|
|
95
95
|
}
|
|
96
96
|
type VerifyFn = (token: string) => Promise<Principal>;
|
|
97
|
-
|
|
97
|
+
type DecodeFn = (token: string) => Promise<any>;
|
|
98
98
|
export type ServiceConfigs = {
|
|
99
99
|
Authenticate: AuthenticateFn;
|
|
100
100
|
Register: RegisterFn;
|
|
101
101
|
Verify?: VerifyFn;
|
|
102
|
+
Decode?:DecodeFn
|
|
102
103
|
};
|
|
103
104
|
|
|
104
105
|
// ---
|
|
@@ -113,6 +114,7 @@ export type RequestMetadata = {
|
|
|
113
114
|
ipAddress?: string;
|
|
114
115
|
userAgent?: string;
|
|
115
116
|
body: any,
|
|
117
|
+
token: string,
|
|
116
118
|
json: {},
|
|
117
119
|
headers: Headers | {};
|
|
118
120
|
query:{},
|
package/index.ts
CHANGED
|
@@ -39,7 +39,7 @@ if (!config.Database?.url || !config.Database?.Admin_Password || !config.Databas
|
|
|
39
39
|
export const pb = new Pocketbase(config.Database?.url || "");
|
|
40
40
|
pb.autoCancellation(false)
|
|
41
41
|
try {
|
|
42
|
-
await pb.collection("_superusers").authWithPassword(config.Database?.Admin_Email || "", config.Database?.Admin_Password || "");
|
|
42
|
+
await pb.collection("_superusers").authWithPassword(config.Database?.Admin_Email || "", config.Database?.Admin_Password || "");
|
|
43
43
|
} catch (_) { }
|
|
44
44
|
|
|
45
45
|
const cache = new Cache();
|
|
@@ -169,6 +169,43 @@ async function createServeConfig(): Promise<Serve> {
|
|
|
169
169
|
const origin = req.headers.get("origin");
|
|
170
170
|
const corsHeaders = buildCorsHeaders(origin, defaultCorsConfig);
|
|
171
171
|
|
|
172
|
+
if (url.pathname.startsWith("/files")) {
|
|
173
|
+
const filePath = url.pathname.replace("/files", "");
|
|
174
|
+
|
|
175
|
+
// 1️⃣ Cache hit
|
|
176
|
+
const cached = cache.get(filePath);
|
|
177
|
+
if (cached) {
|
|
178
|
+
return new Response(cached.body, {
|
|
179
|
+
headers: cached.headers,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const res = await fetch(config.Database!.url + "/api/files/" + filePath);
|
|
184
|
+
console.log(res)
|
|
185
|
+
|
|
186
|
+
if (!res.ok) {
|
|
187
|
+
return new Response("File not found", { status: 404 });
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// 3️⃣ Read once
|
|
191
|
+
const buffer = await res.arrayBuffer();
|
|
192
|
+
|
|
193
|
+
const headers = {
|
|
194
|
+
"Content-Type": res.headers.get("content-type") ?? "application/octet-stream",
|
|
195
|
+
"Cache-Control": "public, max-age=31536000",
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
// 4️⃣ Store bytes, not Response
|
|
199
|
+
cache.set(filePath, {
|
|
200
|
+
body: buffer,
|
|
201
|
+
headers,
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// 5️⃣ Return fresh Response
|
|
205
|
+
return new Response(buffer, { headers });
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
|
|
172
209
|
const method = req.method.toUpperCase();
|
|
173
210
|
// Handle CORS preflight
|
|
174
211
|
if (req.method === "OPTIONS") {
|
|
@@ -244,7 +281,7 @@ async function createServeConfig(): Promise<Serve> {
|
|
|
244
281
|
return new Response(
|
|
245
282
|
JSON.stringify({
|
|
246
283
|
success: false,
|
|
247
|
-
data: {error: validation[key]?.error.flatten()}
|
|
284
|
+
data: { error: validation[key]?.error.flatten() }
|
|
248
285
|
}),
|
|
249
286
|
{
|
|
250
287
|
status: 400,
|
|
@@ -409,7 +446,7 @@ async function Register(data: { username: string; email: string; password: strin
|
|
|
409
446
|
} catch (err: any) {
|
|
410
447
|
const fieldErrors: Record<string, { code: string; message: string }> = {};
|
|
411
448
|
|
|
412
|
-
if (err?.data) {
|
|
449
|
+
if (err?.data) {
|
|
413
450
|
for (const key in err.data) {
|
|
414
451
|
let value = err.data[key];
|
|
415
452
|
|
|
@@ -497,11 +534,27 @@ async function buildRequestContext(req: Request, headers: Headers): Promise<Cont
|
|
|
497
534
|
}
|
|
498
535
|
},
|
|
499
536
|
Register,
|
|
537
|
+
async Verify(token: string) {
|
|
538
|
+
try {
|
|
539
|
+
// Returns the decoded payload if valid, throws if expired/tampered
|
|
540
|
+
return jwt.verify(token, config.Server.JWT_Secret);
|
|
541
|
+
} catch (error) {
|
|
542
|
+
// Specifically catching JsonWebTokenError or TokenExpiredError
|
|
543
|
+
return false;
|
|
544
|
+
}
|
|
545
|
+
},
|
|
546
|
+
|
|
547
|
+
Decode(token: string) {
|
|
548
|
+
// decode() just reads the data without checking the signature.
|
|
549
|
+
// Useful for checking expiration or UI logic without needing the Secret.
|
|
550
|
+
return jwt.decode(token);
|
|
551
|
+
}
|
|
500
552
|
|
|
501
553
|
},
|
|
502
554
|
metadata: {
|
|
503
555
|
requestID: crypto.randomUUID(),
|
|
504
556
|
timestamp: new Date(),
|
|
557
|
+
token,
|
|
505
558
|
params: {},
|
|
506
559
|
query: {},
|
|
507
560
|
json: reqJSON,
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"bin": {
|
|
4
4
|
"hapta": "./index.ts"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.0.
|
|
6
|
+
"version": "1.0.15",
|
|
7
7
|
"description": "modular, scalable, and feature-rich backend framework designed to extend Pocketbase with authentication, schema validation, caching, and tenant-based service orchestration.",
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"jsonwebtoken": "^9.0.3",
|
package/bun.lock
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"lockfileVersion": 1,
|
|
3
|
-
"configVersion": 1,
|
|
4
|
-
"workspaces": {
|
|
5
|
-
"": {
|
|
6
|
-
"dependencies": {
|
|
7
|
-
"jsonwebtoken": "^9.0.3",
|
|
8
|
-
"pocketbase": "latest",
|
|
9
|
-
"zod": "latest",
|
|
10
|
-
},
|
|
11
|
-
},
|
|
12
|
-
},
|
|
13
|
-
"packages": {
|
|
14
|
-
"buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="],
|
|
15
|
-
|
|
16
|
-
"ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="],
|
|
17
|
-
|
|
18
|
-
"jsonwebtoken": ["jsonwebtoken@9.0.3", "", { "dependencies": { "jws": "^4.0.1", "lodash.includes": "^4.3.0", "lodash.isboolean": "^3.0.3", "lodash.isinteger": "^4.0.4", "lodash.isnumber": "^3.0.3", "lodash.isplainobject": "^4.0.6", "lodash.isstring": "^4.0.1", "lodash.once": "^4.0.0", "ms": "^2.1.1", "semver": "^7.5.4" } }, "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g=="],
|
|
19
|
-
|
|
20
|
-
"jwa": ["jwa@2.0.1", "", { "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg=="],
|
|
21
|
-
|
|
22
|
-
"jws": ["jws@4.0.1", "", { "dependencies": { "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA=="],
|
|
23
|
-
|
|
24
|
-
"lodash.includes": ["lodash.includes@4.3.0", "", {}, "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="],
|
|
25
|
-
|
|
26
|
-
"lodash.isboolean": ["lodash.isboolean@3.0.3", "", {}, "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="],
|
|
27
|
-
|
|
28
|
-
"lodash.isinteger": ["lodash.isinteger@4.0.4", "", {}, "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="],
|
|
29
|
-
|
|
30
|
-
"lodash.isnumber": ["lodash.isnumber@3.0.3", "", {}, "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw=="],
|
|
31
|
-
|
|
32
|
-
"lodash.isplainobject": ["lodash.isplainobject@4.0.6", "", {}, "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="],
|
|
33
|
-
|
|
34
|
-
"lodash.isstring": ["lodash.isstring@4.0.1", "", {}, "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="],
|
|
35
|
-
|
|
36
|
-
"lodash.once": ["lodash.once@4.1.1", "", {}, "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="],
|
|
37
|
-
|
|
38
|
-
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
|
39
|
-
|
|
40
|
-
"pocketbase": ["pocketbase@0.26.8", "", {}, "sha512-aQ/ewvS7ncvAE8wxoW10iAZu6ElgbeFpBhKPnCfvRovNzm2gW8u/sQNPGN6vNgVEagz44kK//C61oKjfa+7Low=="],
|
|
41
|
-
|
|
42
|
-
"safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
|
|
43
|
-
|
|
44
|
-
"semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
|
45
|
-
|
|
46
|
-
"zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="],
|
|
47
|
-
}
|
|
48
|
-
}
|