@vyckr/tachyon 0.1.0 → 0.3.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/Dockerfile +11 -7
- package/README.md +4 -4
- package/package.json +1 -1
- package/routes/byos/[primary]/{doc.ts → doc/index.ts} +1 -1
- package/routes/byos/[primary]/{docs.ts → docs/index.ts} +1 -1
- package/routes/byos/[primary]/join/[secondary]/{docs.ts → docs/index.ts} +1 -1
- package/routes/byos/[primary]/stream/{doc.ts → doc/index.ts} +1 -1
- package/routes/byos/[primary]/stream/{docs.ts → docs/index.ts} +1 -1
- package/routes/proxy.ts +8 -0
- package/src/Tach.ts +104 -163
- /package/routes/byos/[primary]/{schema.ts → schema/index.ts} +0 -0
- /package/routes/{_utils → utils}/validation.ts +0 -0
package/Dockerfile
CHANGED
|
@@ -16,28 +16,32 @@ RUN unzip bun-lambda-layer.zip -d /tmp
|
|
|
16
16
|
|
|
17
17
|
WORKDIR /tmp
|
|
18
18
|
|
|
19
|
-
COPY ./src/Tach.ts .
|
|
20
|
-
|
|
21
19
|
COPY package.json .
|
|
22
20
|
|
|
23
21
|
RUN bun install
|
|
24
22
|
|
|
25
|
-
RUN bun build --target=bun Tach.ts --outfile lambda
|
|
26
|
-
|
|
27
23
|
FROM public.ecr.aws/lambda/provided:al2
|
|
28
24
|
|
|
29
|
-
COPY --from=build /tmp/
|
|
25
|
+
COPY --from=build /tmp/node_modules ${LAMBDA_TASK_ROOT}/node_modules
|
|
26
|
+
|
|
27
|
+
COPY --from=build /tmp/package.json ${LAMBDA_TASK_ROOT}/package.json
|
|
30
28
|
|
|
31
29
|
COPY --from=build /tmp/bootstrap ${LAMBDA_RUNTIME_DIR}
|
|
32
30
|
|
|
33
31
|
COPY --from=build /tmp/bun /opt
|
|
34
32
|
|
|
33
|
+
COPY ./src/Tach.ts ${LAMBDA_TASK_ROOT}
|
|
34
|
+
|
|
35
|
+
COPY ./tsconfig.json ${LAMBDA_TASK_ROOT}
|
|
36
|
+
|
|
35
37
|
COPY ./src/runtime.ts /opt
|
|
36
38
|
|
|
37
39
|
RUN chmod 777 /opt/bun
|
|
38
40
|
|
|
39
|
-
RUN chmod 777
|
|
41
|
+
RUN chmod 777 /opt/runtime.ts
|
|
42
|
+
|
|
43
|
+
RUN chmod 777 ${LAMBDA_TASK_ROOT}/Tach.ts
|
|
40
44
|
|
|
41
45
|
RUN chmod 777 ${LAMBDA_RUNTIME_DIR}/bootstrap
|
|
42
46
|
|
|
43
|
-
CMD ["
|
|
47
|
+
CMD ["Tach.fetch"]
|
package/README.md
CHANGED
|
@@ -60,12 +60,12 @@ Make sure you have set the 'SCHEMA_PATH' if 'SCHEMA' is set to 'STRICT'. The sch
|
|
|
60
60
|
### Requirements
|
|
61
61
|
- Make sure to have a 'routes' directory in the root of your project
|
|
62
62
|
- Dynamic routes should be enclosed in square brackets
|
|
63
|
-
- The first parameter should NOT be a dynamic route (e.g. /[version]/doc.ts)
|
|
64
|
-
- All dynamic routes should be within odd indexes (e.g. /v1/[path]/login/[id]/name.ts)
|
|
65
|
-
- The last parameter in the route should not be a dynamic route (e.g. /v1/[path]/login/[id]/name.ts)
|
|
63
|
+
- The first parameter should NOT be a dynamic route (e.g. /[version]/doc/index.ts)
|
|
64
|
+
- All dynamic routes should be within odd indexes (e.g. /v1/[path]/login/[id]/name/index.ts)
|
|
65
|
+
- The last parameter in the route should not be a dynamic route (e.g. /v1/[path]/login/[id]/name/index.ts)
|
|
66
66
|
|
|
67
67
|
```typescript
|
|
68
|
-
// routes/v1/[collection]/doc.ts
|
|
68
|
+
// routes/v1/[collection]/doc/index.ts
|
|
69
69
|
import Silo from "@vyckr/byos"
|
|
70
70
|
imoprt { VALIDATE } from "../utils/decorators"
|
|
71
71
|
|
package/package.json
CHANGED
package/routes/proxy.ts
ADDED
package/src/Tach.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
2
|
import { watch } from "node:fs";
|
|
3
|
-
import { exists } from "node:fs/promises";
|
|
4
3
|
import Silo from "@vyckr/byos";
|
|
5
4
|
import { Glob, Server } from "bun";
|
|
6
5
|
|
|
@@ -39,18 +38,73 @@ const Tach = {
|
|
|
39
38
|
|
|
40
39
|
routesPath: process.env.LAMBDA_TASK_ROOT ? `${process.env.LAMBDA_TASK_ROOT}/routes` : `${process.cwd()}/routes`,
|
|
41
40
|
|
|
42
|
-
|
|
41
|
+
proxyMod: null,
|
|
43
42
|
|
|
43
|
+
async proxy(req: Request, server?: Server) {
|
|
44
|
+
|
|
45
|
+
const request = req.clone()
|
|
46
|
+
|
|
47
|
+
const logs: _log[] = []
|
|
48
|
+
|
|
49
|
+
const url = new URL(req.url)
|
|
50
|
+
|
|
51
|
+
const startTime = Date.now()
|
|
52
|
+
|
|
53
|
+
const ipAddress = server && server.requestIP ? server.requestIP(req)!.address : '0.0.0.0'
|
|
54
|
+
|
|
55
|
+
return await Tach.context.run(logs, async () => {
|
|
56
|
+
|
|
57
|
+
let res: Response
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
|
|
61
|
+
const data = await Tach.processRequest(req, { ipAddress, request: req, requestTime: startTime, logs, slugs: new Map<string, any>() })
|
|
62
|
+
|
|
63
|
+
res = Tach.processResponse(200, data)
|
|
64
|
+
|
|
65
|
+
if(logs.length > 0 && Tach.saveLogs && Tach.dbPath) await Promise.all(logs.map(log => {
|
|
66
|
+
return Silo.putData(Tach.logsTableName, { ipAddress, path: url.pathname, method: req.method, ...log })
|
|
67
|
+
}))
|
|
68
|
+
|
|
69
|
+
if(!Tach.isAsyncIterator(data)) {
|
|
70
|
+
|
|
71
|
+
const status = res.status
|
|
72
|
+
const response_size = typeof data !== "undefined" ? String(data).length : 0
|
|
73
|
+
const url = new URL(req.url)
|
|
74
|
+
const method = req.method
|
|
75
|
+
const date = Date.now()
|
|
76
|
+
const duration = date - startTime
|
|
77
|
+
|
|
78
|
+
console.info(`"${method} ${url.pathname}" ${status} - ${duration}ms - ${response_size} byte(s)`)
|
|
79
|
+
|
|
80
|
+
if(Tach.dbPath && Tach.saveStats) await Silo.putData(Tach.statsTableName, { ipAddress, cpu: process.cpuUsage(), memory: process.memoryUsage(), date: Date.now() })
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
} catch(e) {
|
|
84
|
+
|
|
85
|
+
const method = request.method
|
|
86
|
+
|
|
87
|
+
await Tach.logError(e as Error, ipAddress, url, method, logs, startTime)
|
|
88
|
+
|
|
89
|
+
if(Tach.dbPath && Tach.saveStats) await Silo.putData(Tach.statsTableName, { ipAddress, cpu: process.cpuUsage(), memory: process.memoryUsage(), date: Date.now() })
|
|
90
|
+
|
|
91
|
+
res = Response.json({ detail: (e as Error).message }, { status: (e as Error).cause as number ?? 500, headers: Tach.headers })
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return res
|
|
95
|
+
})
|
|
96
|
+
},
|
|
97
|
+
|
|
44
98
|
pathsMatch(routeSegs: string[], pathSegs: string[]) {
|
|
45
99
|
|
|
46
100
|
if (routeSegs.length !== pathSegs.length) {
|
|
47
101
|
return false;
|
|
48
102
|
}
|
|
49
103
|
|
|
50
|
-
const slugs = Tach.routeSlugs.get(`${routeSegs.join('/')}.ts`) || Tach.routeSlugs.get(`${routeSegs.join('/')}.js`) || new Map<string, number>()
|
|
104
|
+
const slugs = Tach.routeSlugs.get(`${routeSegs.join('/')}/index.ts`) || Tach.routeSlugs.get(`${routeSegs.join('/')}/index.js`) || new Map<string, number>()
|
|
51
105
|
|
|
52
106
|
for (let i = 0; i < routeSegs.length; i++) {
|
|
53
|
-
if (!slugs.has(routeSegs[i]) && routeSegs[i]
|
|
107
|
+
if (!slugs.has(routeSegs[i]) && routeSegs[i] !== pathSegs[i]) {
|
|
54
108
|
return false;
|
|
55
109
|
}
|
|
56
110
|
}
|
|
@@ -73,7 +127,11 @@ const Tach = {
|
|
|
73
127
|
let bestMatchLength = -1;
|
|
74
128
|
|
|
75
129
|
for (const [routeKey] of Tach.indexedRoutes) {
|
|
76
|
-
|
|
130
|
+
|
|
131
|
+
const routeSegs = routeKey.split('/')
|
|
132
|
+
|
|
133
|
+
routeSegs.pop()
|
|
134
|
+
|
|
77
135
|
const isMatch = Tach.pathsMatch(routeSegs, paths.slice(0, routeSegs.length));
|
|
78
136
|
|
|
79
137
|
if (isMatch && routeSegs.length > bestMatchLength) {
|
|
@@ -110,43 +168,35 @@ const Tach = {
|
|
|
110
168
|
|
|
111
169
|
formatMsg(...msg: any[]) {
|
|
112
170
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
else if(msg instanceof Map) return "\n" + JSON.stringify(Object.fromEntries(msg), null, 2)
|
|
116
|
-
|
|
117
|
-
else if(msg instanceof FormData) {
|
|
118
|
-
const formEntries: Record<string, any> = {}
|
|
119
|
-
msg.forEach((val, key) => formEntries[key] = val)
|
|
120
|
-
return "\n" + JSON.stringify(formEntries, null, 2)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
else if(Array.isArray(msg)
|
|
124
|
-
|| (typeof msg === 'object' && !Array.isArray(msg))
|
|
125
|
-
|| (typeof msg === 'object' && msg !== null)) return "\n" + JSON.stringify(msg, null, 2)
|
|
171
|
+
const formatted: string[] = []
|
|
126
172
|
|
|
127
|
-
|
|
128
|
-
},
|
|
129
|
-
|
|
130
|
-
configLogger() {
|
|
173
|
+
for(const arg of msg) {
|
|
131
174
|
|
|
132
|
-
|
|
175
|
+
if(arg instanceof Set) formatted.push(JSON.stringify(Array.from(arg), null, 2))
|
|
133
176
|
|
|
134
|
-
|
|
177
|
+
else if(arg instanceof Map) formatted.push(JSON.stringify(Object.fromEntries(arg), null, 2))
|
|
135
178
|
|
|
136
|
-
if
|
|
137
|
-
|
|
179
|
+
else if(arg instanceof FormData) {
|
|
180
|
+
const formEntries: Record<string, any> = {}
|
|
181
|
+
arg.forEach((val, key) => formEntries[key] = val)
|
|
182
|
+
formatted.push(JSON.stringify(formEntries, null, 2))
|
|
138
183
|
}
|
|
139
184
|
|
|
140
|
-
|
|
185
|
+
else if(Array.isArray(arg) || (typeof arg === 'object' && !Array.isArray(arg)) || (typeof arg === 'object' && arg !== null)) formatted.push(JSON.stringify(arg, null, 2))
|
|
141
186
|
|
|
142
|
-
|
|
187
|
+
else formatted.push(arg)
|
|
143
188
|
}
|
|
144
189
|
|
|
190
|
+
return formatted.join('\n\n')
|
|
191
|
+
},
|
|
192
|
+
|
|
193
|
+
configLogger() {
|
|
194
|
+
|
|
145
195
|
const reset = '\x1b[0m'
|
|
146
196
|
|
|
147
197
|
console.info = (...args: any[]) => {
|
|
148
198
|
const info = `[${Tach.formatDate()}]\x1b[32m INFO${reset} (${process.pid}) ${Tach.formatMsg(...args)}`
|
|
149
|
-
log(info)
|
|
199
|
+
console.log(info)
|
|
150
200
|
if(Tach.context.getStore()) {
|
|
151
201
|
const logWriter = Tach.context.getStore()
|
|
152
202
|
if(logWriter && Tach.dbPath && Tach.saveLogs) logWriter.push({ date: Date.now(), msg: `${info.replace(reset, '').replace('\x1b[32m', '')}\n`, type: "info" })
|
|
@@ -155,7 +205,7 @@ const Tach = {
|
|
|
155
205
|
|
|
156
206
|
console.error = (...args: any[]) => {
|
|
157
207
|
const err = `[${Tach.formatDate()}]\x1b[31m ERROR${reset} (${process.pid}) ${Tach.formatMsg(...args)}`
|
|
158
|
-
log(err)
|
|
208
|
+
console.log(err)
|
|
159
209
|
if(Tach.context.getStore()) {
|
|
160
210
|
const logWriter = Tach.context.getStore()
|
|
161
211
|
if(logWriter && Tach.dbPath && Tach.saveLogs) logWriter.push({ date: Date.now(), msg: `${err.replace(reset, '').replace('\x1b[31m', '')}\n`, type: "error" })
|
|
@@ -164,7 +214,7 @@ const Tach = {
|
|
|
164
214
|
|
|
165
215
|
console.debug = (...args: any[]) => {
|
|
166
216
|
const bug = `[${Tach.formatDate()}]\x1b[36m DEBUG${reset} (${process.pid}) ${Tach.formatMsg(...args)}`
|
|
167
|
-
log(bug)
|
|
217
|
+
console.log(bug)
|
|
168
218
|
if(Tach.context.getStore()) {
|
|
169
219
|
const logWriter = Tach.context.getStore()
|
|
170
220
|
if(logWriter && Tach.dbPath && Tach.saveLogs) logWriter.push({ date: Date.now(), msg: `${bug.replace(reset, '').replace('\x1b[36m', '')}\n`, type: "debug" })
|
|
@@ -173,7 +223,7 @@ const Tach = {
|
|
|
173
223
|
|
|
174
224
|
console.warn = (...args: any[]) => {
|
|
175
225
|
const warn = `[${Tach.formatDate()}]\x1b[33m WARN${reset} (${process.pid}) ${Tach.formatMsg(...args)}`
|
|
176
|
-
log(warn)
|
|
226
|
+
console.log(warn)
|
|
177
227
|
if(Tach.context.getStore()) {
|
|
178
228
|
const logWriter = Tach.context.getStore()
|
|
179
229
|
if(logWriter && Tach.dbPath && Tach.saveLogs) logWriter.push({ date: Date.now(), msg: `${warn.replace(reset, '').replace('\x1b[33m', '')}\n`, type: "warn" })
|
|
@@ -182,7 +232,7 @@ const Tach = {
|
|
|
182
232
|
|
|
183
233
|
console.trace = (...args: any[]) => {
|
|
184
234
|
const trace = `[${Tach.formatDate()}]\x1b[35m TRACE${reset} (${process.pid}) ${Tach.formatMsg(...args)}`
|
|
185
|
-
log(trace)
|
|
235
|
+
console.log(trace)
|
|
186
236
|
if(Tach.context.getStore()) {
|
|
187
237
|
const logWriter = Tach.context.getStore()
|
|
188
238
|
if(logWriter && Tach.dbPath && Tach.saveLogs) logWriter.push({ date: Date.now(), msg: `${trace.replace(reset, '').replace('\x1b[35m', '')}\n`, type: "trace" })
|
|
@@ -230,19 +280,9 @@ const Tach = {
|
|
|
230
280
|
|
|
231
281
|
if(searchParams.size > 0) queryParams = Tach.parseKVParams(searchParams)
|
|
232
282
|
|
|
233
|
-
const middlewarePath = await exists(`${Tach.routesPath}/_middleware.ts`) ? `${Tach.routesPath}/_middleware.ts` : `${Tach.routesPath}/_middleware.js`
|
|
234
|
-
|
|
235
283
|
if(params.length > 0 && !queryParams && !data) {
|
|
236
284
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
if(Tach.hasMiddleware) {
|
|
240
|
-
|
|
241
|
-
const middleware = (await import(middlewarePath)).default
|
|
242
|
-
|
|
243
|
-
res = await middleware(async () => handler(...params, context))
|
|
244
|
-
|
|
245
|
-
} else res = await handler(...params, context)
|
|
285
|
+
const res = await handler(...params, context)
|
|
246
286
|
|
|
247
287
|
await Tach.logRequest(request, 200, context)
|
|
248
288
|
|
|
@@ -250,15 +290,7 @@ const Tach = {
|
|
|
250
290
|
|
|
251
291
|
} else if(params.length === 0 && queryParams && !data) {
|
|
252
292
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
if(Tach.hasMiddleware) {
|
|
256
|
-
|
|
257
|
-
const middleware = (await import(middlewarePath)).default
|
|
258
|
-
|
|
259
|
-
res = await middleware(async () => handler(queryParams, context))
|
|
260
|
-
|
|
261
|
-
} else res = await handler(queryParams, context)
|
|
293
|
+
const res = await handler(queryParams, context)
|
|
262
294
|
|
|
263
295
|
await Tach.logRequest(request, 200, context)
|
|
264
296
|
|
|
@@ -266,15 +298,7 @@ const Tach = {
|
|
|
266
298
|
|
|
267
299
|
} else if(params.length === 0 && !queryParams && data) {
|
|
268
300
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
if(Tach.hasMiddleware) {
|
|
272
|
-
|
|
273
|
-
const middleware = (await import(middlewarePath)).default
|
|
274
|
-
|
|
275
|
-
res = await middleware(async () => handler(data, context))
|
|
276
|
-
|
|
277
|
-
} else res = await handler(data, context)
|
|
301
|
+
const res = await handler(data, context)
|
|
278
302
|
|
|
279
303
|
await Tach.logRequest(request, 200, context, await body.text())
|
|
280
304
|
|
|
@@ -282,15 +306,7 @@ const Tach = {
|
|
|
282
306
|
|
|
283
307
|
} else if(params.length > 0 && queryParams && !data) {
|
|
284
308
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
if(Tach.hasMiddleware) {
|
|
288
|
-
|
|
289
|
-
const middleware = (await import(middlewarePath)).default
|
|
290
|
-
|
|
291
|
-
res = await middleware(async () => handler(...params, queryParams, context))
|
|
292
|
-
|
|
293
|
-
} else res = await handler(...params, queryParams, context)
|
|
309
|
+
const res = await handler(...params, queryParams, context)
|
|
294
310
|
|
|
295
311
|
await Tach.logRequest(request, 200, context)
|
|
296
312
|
|
|
@@ -298,15 +314,7 @@ const Tach = {
|
|
|
298
314
|
|
|
299
315
|
} else if(params.length > 0 && !queryParams && data) {
|
|
300
316
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
if(Tach.hasMiddleware) {
|
|
304
|
-
|
|
305
|
-
const middleware = (await import(middlewarePath)).default
|
|
306
|
-
|
|
307
|
-
res = await middleware(async () => handler(...params, data, context))
|
|
308
|
-
|
|
309
|
-
} else res = await handler(...params, data, context)
|
|
317
|
+
const res = await handler(...params, data, context)
|
|
310
318
|
|
|
311
319
|
await Tach.logRequest(request, 200, context, await body.text())
|
|
312
320
|
|
|
@@ -314,15 +322,7 @@ const Tach = {
|
|
|
314
322
|
|
|
315
323
|
} else if(params.length === 0 && data && queryParams) {
|
|
316
324
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
if(Tach.hasMiddleware) {
|
|
320
|
-
|
|
321
|
-
const middleware = (await import(middlewarePath)).default
|
|
322
|
-
|
|
323
|
-
res = await middleware(async () => handler(queryParams, data, context))
|
|
324
|
-
|
|
325
|
-
} else res = await handler(queryParams, data, context)
|
|
325
|
+
const res = await handler(queryParams, data, context)
|
|
326
326
|
|
|
327
327
|
await Tach.logRequest(request, 200, context, await body.text())
|
|
328
328
|
|
|
@@ -330,15 +330,7 @@ const Tach = {
|
|
|
330
330
|
|
|
331
331
|
} else if(params.length > 0 && data && queryParams) {
|
|
332
332
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
if(Tach.hasMiddleware) {
|
|
336
|
-
|
|
337
|
-
const middleware = (await import(middlewarePath)).default
|
|
338
|
-
|
|
339
|
-
res = await middleware(async () => handler(...params, queryParams, data, context))
|
|
340
|
-
|
|
341
|
-
} else res = await handler(...params, queryParams, data, context)
|
|
333
|
+
const res = await handler(...params, queryParams, data, context)
|
|
342
334
|
|
|
343
335
|
await Tach.logRequest(request, 200, context, await body.text())
|
|
344
336
|
|
|
@@ -346,15 +338,7 @@ const Tach = {
|
|
|
346
338
|
|
|
347
339
|
} else {
|
|
348
340
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
if(Tach.hasMiddleware) {
|
|
352
|
-
|
|
353
|
-
const middleware = (await import(middlewarePath)).default
|
|
354
|
-
|
|
355
|
-
res = await middleware(async () => handler(context))
|
|
356
|
-
|
|
357
|
-
} else res = await handler(context)
|
|
341
|
+
const res = await handler(context)
|
|
358
342
|
|
|
359
343
|
await Tach.logRequest(request, 200, context)
|
|
360
344
|
|
|
@@ -415,57 +399,14 @@ const Tach = {
|
|
|
415
399
|
|
|
416
400
|
async fetch(req: Request, server: Server) {
|
|
417
401
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
const logs: _log[] = []
|
|
421
|
-
|
|
422
|
-
const url = new URL(req.url)
|
|
423
|
-
|
|
424
|
-
const startTime = Date.now()
|
|
402
|
+
if(Tach.proxyMod) {
|
|
425
403
|
|
|
426
|
-
|
|
404
|
+
const middleware = (Tach.proxyMod as any).default
|
|
427
405
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
let res: Response
|
|
431
|
-
|
|
432
|
-
try {
|
|
433
|
-
|
|
434
|
-
const data = await Tach.processRequest(req, { ipAddress, request: req, requestTime: startTime, logs, slugs: new Map<string, any>() })
|
|
435
|
-
|
|
436
|
-
res = Tach.processResponse(200, data)
|
|
437
|
-
|
|
438
|
-
if(logs.length > 0 && Tach.saveLogs && Tach.dbPath) await Promise.all(logs.map(log => {
|
|
439
|
-
return Silo.putData(Tach.logsTableName, { ipAddress, path: url.pathname, method: req.method, ...log })
|
|
440
|
-
}))
|
|
441
|
-
|
|
442
|
-
if(!Tach.isAsyncIterator(data)) {
|
|
443
|
-
|
|
444
|
-
const status = res.status
|
|
445
|
-
const response_size = typeof data !== "undefined" ? String(data).length : 0
|
|
446
|
-
const url = new URL(req.url)
|
|
447
|
-
const method = req.method
|
|
448
|
-
const date = Date.now()
|
|
449
|
-
const duration = date - startTime
|
|
450
|
-
|
|
451
|
-
console.info(`"${method} ${url.pathname}" ${status} - ${duration}ms - ${response_size} byte(s)`)
|
|
452
|
-
|
|
453
|
-
if(Tach.dbPath && Tach.saveStats) await Silo.putData(Tach.statsTableName, { ipAddress, cpu: process.cpuUsage(), memory: process.memoryUsage(), date: Date.now() })
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
} catch(e) {
|
|
457
|
-
|
|
458
|
-
const method = request.method
|
|
459
|
-
|
|
460
|
-
await Tach.logError(e as Error, ipAddress, url, method, logs, startTime)
|
|
461
|
-
|
|
462
|
-
if(Tach.dbPath && Tach.saveStats) await Silo.putData(Tach.statsTableName, { ipAddress, cpu: process.cpuUsage(), memory: process.memoryUsage(), date: Date.now() })
|
|
406
|
+
if(middleware) return await middleware(req, Tach.proxy)
|
|
407
|
+
}
|
|
463
408
|
|
|
464
|
-
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
return res
|
|
468
|
-
})
|
|
409
|
+
return await Tach.proxy(req, server)
|
|
469
410
|
},
|
|
470
411
|
|
|
471
412
|
async validateRoutes(route?: string) {
|
|
@@ -480,19 +421,17 @@ const Tach = {
|
|
|
480
421
|
|
|
481
422
|
const slugs = new Map<string, number>()
|
|
482
423
|
|
|
424
|
+
if(pattern.test(paths[0]) || pattern.test(paths[paths.length - 1])) throw new Error(`Invalid route ${route}`)
|
|
425
|
+
|
|
483
426
|
paths.forEach((path, idx) => {
|
|
484
427
|
|
|
485
|
-
if(pattern.test(path) && (idx
|
|
428
|
+
if(pattern.test(path) && (pattern.test(paths[idx - 1]) || pattern.test(paths[idx + 1]))) {
|
|
486
429
|
throw new Error(`Invalid route ${route}`)
|
|
487
430
|
}
|
|
488
431
|
|
|
489
432
|
if(pattern.test(path)) slugs.set(path, idx)
|
|
490
433
|
})
|
|
491
434
|
|
|
492
|
-
const idx = paths.findIndex((path) => pattern.test(path))
|
|
493
|
-
|
|
494
|
-
if(idx > -1 && (idx % 2 === 0 || paths[idx].includes('.ts') || paths[idx].includes('.js'))) throw new Error(`Invalid route ${route}`)
|
|
495
|
-
|
|
496
435
|
const staticPath = paths.filter((path) => !pattern.test(path)).join(',')
|
|
497
436
|
|
|
498
437
|
if(staticPaths.includes(staticPath)) throw new Error(`Duplicate route ${route}`)
|
|
@@ -520,11 +459,13 @@ const Tach = {
|
|
|
520
459
|
|
|
521
460
|
if(route) return await validateRoute(route)
|
|
522
461
|
|
|
523
|
-
const
|
|
462
|
+
const routes = Array.from(new Glob(`**/*/index.{ts,js}`).scanSync({ cwd: Tach.routesPath }))
|
|
463
|
+
|
|
464
|
+
for(const route of routes) await validateRoute(route)
|
|
524
465
|
|
|
525
|
-
const
|
|
466
|
+
const proxy = Array.from(new Glob(`**/proxy.{ts,js}`).scanSync({ cwd: Tach.routesPath }))
|
|
526
467
|
|
|
527
|
-
|
|
468
|
+
if(proxy[0]) Tach.proxyMod = await import(`${Tach.routesPath}/${proxy[0]}`)
|
|
528
469
|
},
|
|
529
470
|
|
|
530
471
|
parseParams(input: string[]) {
|
|
File without changes
|
|
File without changes
|