@kava/kava-api-core 1.0.0 → 1.0.2

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 (133) hide show
  1. package/.github/workflows/publish.yml +40 -0
  2. package/dist/{auth.util.d.ts → auth/auth.d.ts} +1 -5
  3. package/dist/{auth.util.js → auth/auth.js} +38 -30
  4. package/dist/auth/auth.js.map +1 -0
  5. package/dist/auth/index.d.ts +1 -0
  6. package/dist/auth/index.js +2 -0
  7. package/dist/auth/index.js.map +1 -0
  8. package/dist/{context.util.js → context/context.js} +1 -1
  9. package/dist/context/context.js.map +1 -0
  10. package/dist/context/index.d.ts +1 -0
  11. package/dist/context/index.js +2 -0
  12. package/dist/context/index.js.map +1 -0
  13. package/dist/{controller.util.js → controller/controller.js} +1 -1
  14. package/dist/controller/controller.js.map +1 -0
  15. package/dist/controller/index.d.ts +1 -0
  16. package/dist/controller/index.js +2 -0
  17. package/dist/controller/index.js.map +1 -0
  18. package/dist/{conversion.util.js → conversion/conversion.js} +1 -1
  19. package/dist/conversion/conversion.js.map +1 -0
  20. package/dist/conversion/index.d.ts +1 -0
  21. package/dist/conversion/index.js +2 -0
  22. package/dist/conversion/index.js.map +1 -0
  23. package/dist/{db.util.d.ts → db/db.d.ts} +9 -5
  24. package/dist/{db.util.js → db/db.js} +40 -29
  25. package/dist/db/db.js.map +1 -0
  26. package/dist/db/index.d.ts +1 -0
  27. package/dist/db/index.js +2 -0
  28. package/dist/db/index.js.map +1 -0
  29. package/dist/index.d.ts +14 -13
  30. package/dist/index.js +14 -13
  31. package/dist/index.js.map +1 -1
  32. package/dist/logger/index.d.ts +1 -0
  33. package/dist/logger/index.js +2 -0
  34. package/dist/logger/index.js.map +1 -0
  35. package/dist/{logger.util.js → logger/logger.js} +16 -7
  36. package/dist/logger/logger.js.map +1 -0
  37. package/dist/mail/index.d.ts +1 -0
  38. package/dist/mail/index.js +2 -0
  39. package/dist/mail/index.js.map +1 -0
  40. package/dist/{mail.util.js → mail/mail.js} +1 -1
  41. package/dist/mail/mail.js.map +1 -0
  42. package/dist/middleware/index.d.ts +1 -0
  43. package/dist/middleware/index.js +2 -0
  44. package/dist/middleware/index.js.map +1 -0
  45. package/dist/{middleware.util.js → middleware/middleware.js} +1 -1
  46. package/dist/middleware/middleware.js.map +1 -0
  47. package/dist/model/index.d.ts +1 -0
  48. package/dist/model/index.js +2 -0
  49. package/dist/model/index.js.map +1 -0
  50. package/dist/{model.util.js → model/model.js} +1 -1
  51. package/dist/model/model.js.map +1 -0
  52. package/dist/permission/index.d.ts +1 -0
  53. package/dist/permission/index.js +2 -0
  54. package/dist/permission/index.js.map +1 -0
  55. package/dist/{permission.util.js → permission/permission.js} +1 -1
  56. package/dist/permission/permission.js.map +1 -0
  57. package/dist/registry/index.d.ts +1 -0
  58. package/dist/registry/index.js +2 -0
  59. package/dist/registry/index.js.map +1 -0
  60. package/dist/registry/registry.d.ts +28 -0
  61. package/dist/registry/registry.js +19 -0
  62. package/dist/registry/registry.js.map +1 -0
  63. package/dist/route/index.d.ts +1 -0
  64. package/dist/route/index.js +2 -0
  65. package/dist/route/index.js.map +1 -0
  66. package/dist/{route.util.js → route/route.js} +1 -1
  67. package/dist/route/route.js.map +1 -0
  68. package/dist/storage/index.d.ts +1 -0
  69. package/dist/storage/index.js +2 -0
  70. package/dist/storage/index.js.map +1 -0
  71. package/dist/{storage.util.js → storage/storage.js} +2 -2
  72. package/dist/storage/storage.js.map +1 -0
  73. package/dist/validation/index.d.ts +1 -0
  74. package/dist/validation/index.js +2 -0
  75. package/dist/validation/index.js.map +1 -0
  76. package/dist/{validation.util.js → validation/validation.js} +1 -1
  77. package/dist/validation/validation.js.map +1 -0
  78. package/package.json +2 -2
  79. package/src/{auth.util.ts → auth/auth.ts} +255 -241
  80. package/src/auth/index.ts +1 -0
  81. package/src/{context.util.ts → context/context.ts} +17 -17
  82. package/src/context/index.ts +1 -0
  83. package/src/{controller.util.ts → controller/controller.ts} +236 -236
  84. package/src/controller/index.ts +1 -0
  85. package/src/{conversion.util.ts → conversion/conversion.ts} +64 -64
  86. package/src/conversion/index.ts +1 -0
  87. package/src/{db.util.ts → db/db.ts} +420 -405
  88. package/src/db/index.ts +1 -0
  89. package/src/index.ts +14 -13
  90. package/src/logger/index.ts +1 -0
  91. package/src/{logger.util.ts → logger/logger.ts} +176 -169
  92. package/src/mail/index.ts +1 -0
  93. package/src/{mail.util.ts → mail/mail.ts} +85 -85
  94. package/src/middleware/index.ts +1 -0
  95. package/src/{middleware.util.ts → middleware/middleware.ts} +288 -288
  96. package/src/model/index.ts +1 -0
  97. package/src/{model.util.ts → model/model.ts} +2210 -2210
  98. package/src/permission/index.ts +1 -0
  99. package/src/{permission.util.ts → permission/permission.ts} +136 -136
  100. package/src/registry/index.ts +1 -0
  101. package/src/registry/registry.ts +37 -0
  102. package/src/route/index.ts +1 -0
  103. package/src/{route.util.ts → route/route.ts} +11 -11
  104. package/src/storage/index.ts +1 -0
  105. package/src/{storage.util.ts → storage/storage.ts} +101 -101
  106. package/src/validation/index.ts +1 -0
  107. package/src/{validation.util.ts → validation/validation.ts} +338 -338
  108. package/tsconfig.json +1 -1
  109. package/bun.lock +0 -160
  110. package/dist/auth.util.js.map +0 -1
  111. package/dist/context.util.js.map +0 -1
  112. package/dist/controller.util.js.map +0 -1
  113. package/dist/conversion.util.js.map +0 -1
  114. package/dist/db.util.js.map +0 -1
  115. package/dist/logger.util.js.map +0 -1
  116. package/dist/mail.util.js.map +0 -1
  117. package/dist/middleware.util.js.map +0 -1
  118. package/dist/model.util.js.map +0 -1
  119. package/dist/permission.util.js.map +0 -1
  120. package/dist/route.util.js.map +0 -1
  121. package/dist/storage.util.js.map +0 -1
  122. package/dist/validation.util.js.map +0 -1
  123. /package/dist/{context.util.d.ts → context/context.d.ts} +0 -0
  124. /package/dist/{controller.util.d.ts → controller/controller.d.ts} +0 -0
  125. /package/dist/{conversion.util.d.ts → conversion/conversion.d.ts} +0 -0
  126. /package/dist/{logger.util.d.ts → logger/logger.d.ts} +0 -0
  127. /package/dist/{mail.util.d.ts → mail/mail.d.ts} +0 -0
  128. /package/dist/{middleware.util.d.ts → middleware/middleware.d.ts} +0 -0
  129. /package/dist/{model.util.d.ts → model/model.d.ts} +0 -0
  130. /package/dist/{permission.util.d.ts → permission/permission.d.ts} +0 -0
  131. /package/dist/{route.util.d.ts → route/route.d.ts} +0 -0
  132. /package/dist/{storage.util.d.ts → storage/storage.d.ts} +0 -0
  133. /package/dist/{validation.util.d.ts → validation/validation.d.ts} +0 -0
@@ -0,0 +1 @@
1
+ export * from "./permission";
@@ -1,136 +1,136 @@
1
- import { ControllerContext } from "elysia"
2
-
3
- type KeyDigit = "0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"
4
- export type KeyFeature = `${"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"}${KeyDigit}${KeyDigit}`
5
- export type KeyAccess = `${KeyDigit}${KeyDigit}`
6
- export type KeyPermission = `${KeyFeature}.${KeyAccess}` | KeyAccess
7
-
8
- const features = new Map<KeyFeature, { key: KeyFeature; name: string }>()
9
- const accesses = new Map<KeyAccess, any>()
10
-
11
- type FeatureAccess = Partial<Record<KeyFeature, {
12
- name: string
13
- accesses: Partial<Record<KeyAccess, string>>
14
- }>>
15
-
16
- export const permission = {
17
- register: (def: FeatureAccess) => {
18
- const featureAccessMap = new Map<string, string>()
19
- let defaultFeature: KeyFeature | null = null
20
-
21
- for (const [featureKey, feature] of Object.entries(def)) {
22
- if (!defaultFeature) defaultFeature = featureKey as KeyFeature
23
-
24
- registerFeature({
25
- key: featureKey as KeyFeature,
26
- name: feature.name
27
- })
28
-
29
- for (const [accessKey, accessName] of Object.entries(feature.accesses)) {
30
- const permKey =
31
- `${featureKey}.${String(accessKey).padStart(2, "0")}`
32
-
33
- registerAccess({
34
- featureKey,
35
- accessKey,
36
- accessName,
37
- permKey
38
- })
39
-
40
- featureAccessMap.set(
41
- `${featureKey}.${accessKey}`,
42
- permKey
43
- )
44
- }
45
- }
46
-
47
- return createScopeApi(defaultFeature!)
48
- },
49
-
50
- getFeatures: () => [...features.values()],
51
-
52
- getAccesses: () => {
53
- const result: Record<string, {
54
- key: string
55
- name: string
56
- accesses: { key: string; name: string }[]
57
- }> = {}
58
-
59
- for (const feature of features.values()) {
60
- result[String(feature.key)] = {
61
- key: String(feature.key),
62
- name: feature.name,
63
- accesses: []
64
- }
65
- }
66
-
67
- for (const access of accesses.values()) {
68
- const featureKey = String(access.featureKey)
69
-
70
- if (!result[featureKey]) continue
71
-
72
- result[featureKey].accesses.push({
73
- key: String(access.accessKey).padStart(2, "0"),
74
- name: access.accessName
75
- })
76
- }
77
-
78
- return Object.values(result)
79
- },
80
- }
81
-
82
-
83
- function normalize(
84
- raw: KeyPermission,
85
- defaultFeature?: KeyFeature
86
- ): KeyPermission {
87
- if (!raw.includes(".") && defaultFeature) {
88
- return `${defaultFeature}.${String(raw).padStart(2, "0") as KeyAccess}`
89
- }
90
-
91
- return raw
92
- }
93
-
94
- function registerFeature(f: { key: KeyFeature; name: string }) {
95
- if (!features.has(f.key)) {
96
- features.set(f.key, f)
97
- }
98
- }
99
-
100
- function registerAccess(a: any) {
101
- if (!accesses.has(a.permKey)) {
102
- accesses.set(a.permKey, a)
103
- }
104
- }
105
-
106
- function createPermission(keys: KeyPermission[]) {
107
- return {
108
- keys,
109
-
110
- orHave(raw: KeyPermission) {
111
- return createPermission([
112
- ...this.keys,
113
- normalize(raw) as KeyPermission
114
- ])
115
- },
116
-
117
- guard(c: ControllerContext) {
118
- const permissions = new Set(c.permissions || [])
119
-
120
- const ok = this.keys.some(k => permissions?.has(k))
121
- if (!ok) {
122
- c.responseForbidden()
123
- }
124
- }
125
- }
126
- }
127
-
128
- export function createScopeApi(defaultFeature: KeyFeature) {
129
- return {
130
- have(raw: KeyPermission) {
131
- const key = normalize(raw, defaultFeature)
132
- return createPermission([key])
133
- }
134
- }
135
- }
136
-
1
+ import { ControllerContext } from "elysia"
2
+
3
+ type KeyDigit = "0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"
4
+ export type KeyFeature = `${"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"}${KeyDigit}${KeyDigit}`
5
+ export type KeyAccess = `${KeyDigit}${KeyDigit}`
6
+ export type KeyPermission = `${KeyFeature}.${KeyAccess}` | KeyAccess
7
+
8
+ const features = new Map<KeyFeature, { key: KeyFeature; name: string }>()
9
+ const accesses = new Map<KeyAccess, any>()
10
+
11
+ type FeatureAccess = Partial<Record<KeyFeature, {
12
+ name: string
13
+ accesses: Partial<Record<KeyAccess, string>>
14
+ }>>
15
+
16
+ export const permission = {
17
+ register: (def: FeatureAccess) => {
18
+ const featureAccessMap = new Map<string, string>()
19
+ let defaultFeature: KeyFeature | null = null
20
+
21
+ for (const [featureKey, feature] of Object.entries(def)) {
22
+ if (!defaultFeature) defaultFeature = featureKey as KeyFeature
23
+
24
+ registerFeature({
25
+ key: featureKey as KeyFeature,
26
+ name: feature.name
27
+ })
28
+
29
+ for (const [accessKey, accessName] of Object.entries(feature.accesses)) {
30
+ const permKey =
31
+ `${featureKey}.${String(accessKey).padStart(2, "0")}`
32
+
33
+ registerAccess({
34
+ featureKey,
35
+ accessKey,
36
+ accessName,
37
+ permKey
38
+ })
39
+
40
+ featureAccessMap.set(
41
+ `${featureKey}.${accessKey}`,
42
+ permKey
43
+ )
44
+ }
45
+ }
46
+
47
+ return createScopeApi(defaultFeature!)
48
+ },
49
+
50
+ getFeatures: () => [...features.values()],
51
+
52
+ getAccesses: () => {
53
+ const result: Record<string, {
54
+ key: string
55
+ name: string
56
+ accesses: { key: string; name: string }[]
57
+ }> = {}
58
+
59
+ for (const feature of features.values()) {
60
+ result[String(feature.key)] = {
61
+ key: String(feature.key),
62
+ name: feature.name,
63
+ accesses: []
64
+ }
65
+ }
66
+
67
+ for (const access of accesses.values()) {
68
+ const featureKey = String(access.featureKey)
69
+
70
+ if (!result[featureKey]) continue
71
+
72
+ result[featureKey].accesses.push({
73
+ key: String(access.accessKey).padStart(2, "0"),
74
+ name: access.accessName
75
+ })
76
+ }
77
+
78
+ return Object.values(result)
79
+ },
80
+ }
81
+
82
+
83
+ function normalize(
84
+ raw: KeyPermission,
85
+ defaultFeature?: KeyFeature
86
+ ): KeyPermission {
87
+ if (!raw.includes(".") && defaultFeature) {
88
+ return `${defaultFeature}.${String(raw).padStart(2, "0") as KeyAccess}`
89
+ }
90
+
91
+ return raw
92
+ }
93
+
94
+ function registerFeature(f: { key: KeyFeature; name: string }) {
95
+ if (!features.has(f.key)) {
96
+ features.set(f.key, f)
97
+ }
98
+ }
99
+
100
+ function registerAccess(a: any) {
101
+ if (!accesses.has(a.permKey)) {
102
+ accesses.set(a.permKey, a)
103
+ }
104
+ }
105
+
106
+ function createPermission(keys: KeyPermission[]) {
107
+ return {
108
+ keys,
109
+
110
+ orHave(raw: KeyPermission) {
111
+ return createPermission([
112
+ ...this.keys,
113
+ normalize(raw) as KeyPermission
114
+ ])
115
+ },
116
+
117
+ guard(c: ControllerContext) {
118
+ const permissions = new Set(c.permissions || [])
119
+
120
+ const ok = this.keys.some(k => permissions?.has(k))
121
+ if (!ok) {
122
+ c.responseForbidden()
123
+ }
124
+ }
125
+ }
126
+ }
127
+
128
+ export function createScopeApi(defaultFeature: KeyFeature) {
129
+ return {
130
+ have(raw: KeyPermission) {
131
+ const key = normalize(raw, defaultFeature)
132
+ return createPermission([key])
133
+ }
134
+ }
135
+ }
136
+
@@ -0,0 +1 @@
1
+ export * from "./registry";
@@ -0,0 +1,37 @@
1
+ export interface RedisService {
2
+ get(key: string): Promise<string | null>;
3
+ setex(key: string, ttl: number, value: string): Promise<any>;
4
+ del(key: string | string[]): Promise<any>;
5
+ [key: string]: any;
6
+ }
7
+
8
+ export interface QueueService {
9
+ add(name: string, data: any, options?: any): Promise<any>;
10
+ [key: string]: any;
11
+ }
12
+
13
+ export interface Registry {
14
+ redis?: RedisService;
15
+ queue?: QueueService;
16
+ [key: string]: any;
17
+ }
18
+
19
+ class ServiceRegistry {
20
+ private services: Registry = {};
21
+
22
+ /**
23
+ * Register an optional service instance.
24
+ */
25
+ register<K extends keyof Registry>(name: K, service: Registry[K]): void {
26
+ this.services[name] = service;
27
+ }
28
+
29
+ /**
30
+ * Retrieve a registered service instance.
31
+ */
32
+ get<K extends keyof Registry>(name: K): Registry[K] {
33
+ return this.services[name];
34
+ }
35
+ }
36
+
37
+ export const registry = new ServiceRegistry();
@@ -0,0 +1 @@
1
+ export * from "./route";
@@ -1,12 +1,12 @@
1
- // ================================>
2
- // ## Route: Basic api routers
3
- // ================================>
4
- export function api(app: any, basePath: string, controller: any) {
5
- return app.group(basePath, (group: any) => group
6
- .get("/", controller.index)
7
- .post("/", controller.store)
8
- .get("/:id", controller.show)
9
- .put("/:id", controller.update)
10
- .delete("/:id", controller.destroy)
11
- )
1
+ // ================================>
2
+ // ## Route: Basic api routers
3
+ // ================================>
4
+ export function api(app: any, basePath: string, controller: any) {
5
+ return app.group(basePath, (group: any) => group
6
+ .get("/", controller.index)
7
+ .post("/", controller.store)
8
+ .get("/:id", controller.show)
9
+ .put("/:id", controller.update)
10
+ .delete("/:id", controller.destroy)
11
+ )
12
12
  }
@@ -0,0 +1 @@
1
+ export * from "./storage";
@@ -1,102 +1,102 @@
1
- import fs from "fs";
2
- import path from "path";
3
- import { Elysia } from "elysia";
4
- import { db } from "@utils/db.util";
5
-
6
-
7
-
8
- // ================================>
9
- // ## Storage: Middleware storage handler
10
- // ================================>
11
- export const storage = (app: Elysia) => app.get("/storage/*", async ({ params, set, user }: Record<string, any>) => {
12
- const requestedPath = params["*"];
13
- const baseDir = path.resolve("storage", "public");
14
- const targetPath = path.resolve(baseDir, requestedPath);
15
-
16
- if (!targetPath.startsWith(baseDir)) {
17
- set.status = 400;
18
- return { error: "Invalid path" };
19
- }
20
-
21
- if (fs.existsSync(targetPath)) {
22
- const ext = path.extname(targetPath).toLowerCase();
23
- const mimeTypes: Record<string, string> = {
24
- ".jpg" : "image/jpeg",
25
- ".jpeg" : "image/jpeg",
26
- ".png" : "image/png",
27
- ".webp" : "image/webp",
28
- ".gif" : "image/gif",
29
- ".pdf" : "application/pdf",
30
- ".txt" : "text/plain",
31
- ".json" : "application/json",
32
- ".svg" : "image/svg+xml",
33
- };
34
-
35
- const buffer = fs.readFileSync(targetPath);
36
-
37
- set.headers["Content-Type"] = mimeTypes[ext] || "application/octet-stream";
38
- set.headers["Content-Length"] = buffer.length.toString();
39
-
40
- return new Response(buffer);
41
- } else {
42
- const baseDir = path.resolve("storage", "private");
43
- const targetPath = path.resolve(baseDir, requestedPath);
44
-
45
- if (fs.existsSync(targetPath)) {
46
- if (!user) {
47
- set.status = 404
48
- return { error: "File not found" };
49
- }
50
-
51
- const file = await db("storages").where({ path: requestedPath, disk: "private" }).first()
52
-
53
- if (!file) {
54
- set.status = 404
55
- return { error: "File not found" }
56
- }
57
-
58
- let hasAccess = file.user_id === user.id
59
-
60
- if (!hasAccess) {
61
- hasAccess = await db("storage_permissions").where("storage_id", file.id)
62
- .andWhere((q) => {
63
- q.where("user_id", user.id)
64
- .orWhere("role_id", user.role_id)
65
- })
66
- .first().then(Boolean)
67
- }
68
-
69
-
70
- if (!hasAccess) {
71
- set.status = 404
72
- return { error: "File not found" }
73
- }
74
-
75
- } else {
76
- set.status = 404;
77
- return { error: "File not found" };
78
- }
79
-
80
- const ext = path.extname(targetPath).toLowerCase();
81
- const mimeTypes: Record<string, string> = {
82
- ".jpg" : "image/jpeg",
83
- ".jpeg" : "image/jpeg",
84
- ".png" : "image/png",
85
- ".webp" : "image/webp",
86
- ".gif" : "image/gif",
87
- ".pdf" : "application/pdf",
88
- ".txt" : "text/plain",
89
- ".json" : "application/json",
90
- ".svg" : "image/svg+xml",
91
- };
92
-
93
- const buffer = fs.readFileSync(targetPath);
94
-
95
- set.headers["Content-Type"] = mimeTypes[ext] || "application/octet-stream";
96
- set.headers["Content-Length"] = buffer.length.toString();
97
-
98
- return new Response(buffer);
99
- }
100
-
101
-
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { Elysia } from "elysia";
4
+ import { db } from "@utils";
5
+
6
+
7
+
8
+ // ================================>
9
+ // ## Storage: Middleware storage handler
10
+ // ================================>
11
+ export const storage = (app: Elysia) => app.get("/storage/*", async ({ params, set, user }: Record<string, any>) => {
12
+ const requestedPath = params["*"];
13
+ const baseDir = path.resolve("storage", "public");
14
+ const targetPath = path.resolve(baseDir, requestedPath);
15
+
16
+ if (!targetPath.startsWith(baseDir)) {
17
+ set.status = 400;
18
+ return { error: "Invalid path" };
19
+ }
20
+
21
+ if (fs.existsSync(targetPath)) {
22
+ const ext = path.extname(targetPath).toLowerCase();
23
+ const mimeTypes: Record<string, string> = {
24
+ ".jpg" : "image/jpeg",
25
+ ".jpeg" : "image/jpeg",
26
+ ".png" : "image/png",
27
+ ".webp" : "image/webp",
28
+ ".gif" : "image/gif",
29
+ ".pdf" : "application/pdf",
30
+ ".txt" : "text/plain",
31
+ ".json" : "application/json",
32
+ ".svg" : "image/svg+xml",
33
+ };
34
+
35
+ const buffer = fs.readFileSync(targetPath);
36
+
37
+ set.headers["Content-Type"] = mimeTypes[ext] || "application/octet-stream";
38
+ set.headers["Content-Length"] = buffer.length.toString();
39
+
40
+ return new Response(buffer);
41
+ } else {
42
+ const baseDir = path.resolve("storage", "private");
43
+ const targetPath = path.resolve(baseDir, requestedPath);
44
+
45
+ if (fs.existsSync(targetPath)) {
46
+ if (!user) {
47
+ set.status = 404
48
+ return { error: "File not found" };
49
+ }
50
+
51
+ const file = await db("storages").where({ path: requestedPath, disk: "private" }).first()
52
+
53
+ if (!file) {
54
+ set.status = 404
55
+ return { error: "File not found" }
56
+ }
57
+
58
+ let hasAccess = file.user_id === user.id
59
+
60
+ if (!hasAccess) {
61
+ hasAccess = await db("storage_permissions").where("storage_id", file.id)
62
+ .andWhere((q) => {
63
+ q.where("user_id", user.id)
64
+ .orWhere("role_id", user.role_id)
65
+ })
66
+ .first().then(Boolean)
67
+ }
68
+
69
+
70
+ if (!hasAccess) {
71
+ set.status = 404
72
+ return { error: "File not found" }
73
+ }
74
+
75
+ } else {
76
+ set.status = 404;
77
+ return { error: "File not found" };
78
+ }
79
+
80
+ const ext = path.extname(targetPath).toLowerCase();
81
+ const mimeTypes: Record<string, string> = {
82
+ ".jpg" : "image/jpeg",
83
+ ".jpeg" : "image/jpeg",
84
+ ".png" : "image/png",
85
+ ".webp" : "image/webp",
86
+ ".gif" : "image/gif",
87
+ ".pdf" : "application/pdf",
88
+ ".txt" : "text/plain",
89
+ ".json" : "application/json",
90
+ ".svg" : "image/svg+xml",
91
+ };
92
+
93
+ const buffer = fs.readFileSync(targetPath);
94
+
95
+ set.headers["Content-Type"] = mimeTypes[ext] || "application/octet-stream";
96
+ set.headers["Content-Length"] = buffer.length.toString();
97
+
98
+ return new Response(buffer);
99
+ }
100
+
101
+
102
102
  });
@@ -0,0 +1 @@
1
+ export * from "./validation";