vector-framework 1.0.0 → 1.1.1
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/README.md +6 -5
- package/dist/cache/manager.d.ts +5 -2
- package/dist/cache/manager.d.ts.map +1 -1
- package/dist/cache/manager.js +21 -7
- package/dist/cache/manager.js.map +1 -1
- package/dist/cli/index.js +62 -83
- package/dist/cli/index.js.map +1 -1
- package/dist/cli.js +108 -37
- package/dist/core/config-loader.d.ts +2 -2
- package/dist/core/config-loader.d.ts.map +1 -1
- package/dist/core/config-loader.js +16 -18
- package/dist/core/config-loader.js.map +1 -1
- package/dist/core/router.d.ts +2 -0
- package/dist/core/router.d.ts.map +1 -1
- package/dist/core/router.js +52 -16
- package/dist/core/router.js.map +1 -1
- package/dist/core/server.d.ts +4 -3
- package/dist/core/server.d.ts.map +1 -1
- package/dist/core/server.js +39 -18
- package/dist/core/server.js.map +1 -1
- package/dist/core/vector.d.ts +7 -7
- package/dist/core/vector.d.ts.map +1 -1
- package/dist/core/vector.js +20 -21
- package/dist/core/vector.js.map +1 -1
- package/dist/dev/route-scanner.d.ts +1 -1
- package/dist/dev/route-scanner.d.ts.map +1 -1
- package/dist/dev/route-scanner.js +40 -42
- package/dist/dev/route-scanner.js.map +1 -1
- package/dist/http.d.ts +2 -2
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +70 -63
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +4 -4
- package/dist/index.mjs +4 -4
- package/dist/middleware/manager.d.ts +1 -1
- package/dist/middleware/manager.d.ts.map +1 -1
- package/dist/middleware/manager.js.map +1 -1
- package/dist/utils/path.d.ts +1 -0
- package/dist/utils/path.d.ts.map +1 -1
- package/dist/utils/path.js +9 -3
- package/dist/utils/path.js.map +1 -1
- package/package.json +12 -8
- package/src/cache/manager.ts +23 -14
- package/src/cli/index.ts +66 -89
- package/src/core/config-loader.ts +18 -20
- package/src/core/router.ts +52 -18
- package/src/core/server.ts +42 -28
- package/src/core/vector.ts +25 -35
- package/src/dev/route-scanner.ts +41 -47
- package/src/http.ts +82 -112
- package/src/index.ts +3 -3
- package/src/middleware/manager.ts +4 -11
- package/src/utils/path.ts +13 -4
package/src/http.ts
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import { cors, type IRequest, type RouteEntry, withContent } from
|
|
2
|
-
import {
|
|
1
|
+
import { cors, type IRequest, type RouteEntry, withContent } from 'itty-router';
|
|
2
|
+
import { buildRouteRegex } from './utils/path';
|
|
3
|
+
import { CONTENT_TYPES, HTTP_STATUS } from './constants';
|
|
3
4
|
import type {
|
|
4
5
|
CacheOptions,
|
|
5
6
|
DefaultVectorTypes,
|
|
6
7
|
GetAuthType,
|
|
7
8
|
VectorRequest,
|
|
8
9
|
VectorTypes,
|
|
9
|
-
} from
|
|
10
|
-
import { getVectorInstance } from
|
|
10
|
+
} from './types';
|
|
11
|
+
import { getVectorInstance } from './core/vector';
|
|
11
12
|
|
|
12
|
-
export interface ProtectedRequest<
|
|
13
|
-
|
|
14
|
-
> extends IRequest {
|
|
13
|
+
export interface ProtectedRequest<TTypes extends VectorTypes = DefaultVectorTypes>
|
|
14
|
+
extends IRequest {
|
|
15
15
|
authUser?: GetAuthType<TTypes>;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export const { preflight, corsify } = cors({
|
|
19
|
-
origin:
|
|
19
|
+
origin: '*',
|
|
20
20
|
credentials: true,
|
|
21
|
-
allowHeaders:
|
|
22
|
-
allowMethods:
|
|
23
|
-
exposeHeaders:
|
|
21
|
+
allowHeaders: 'Content-Type, Authorization',
|
|
22
|
+
allowMethods: 'GET, POST, PUT, PATCH, DELETE, OPTIONS',
|
|
23
|
+
exposeHeaders: 'Authorization',
|
|
24
24
|
maxAge: 86_400,
|
|
25
25
|
});
|
|
26
26
|
|
|
@@ -29,9 +29,7 @@ interface ExtendedApiOptions extends ApiOptions {
|
|
|
29
29
|
path: string;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
export interface RouteDefinition<
|
|
33
|
-
TTypes extends VectorTypes = DefaultVectorTypes
|
|
34
|
-
> {
|
|
32
|
+
export interface RouteDefinition<TTypes extends VectorTypes = DefaultVectorTypes> {
|
|
35
33
|
entry: RouteEntry;
|
|
36
34
|
options: ExtendedApiOptions;
|
|
37
35
|
handler: (req: VectorRequest<TTypes>) => Promise<unknown>;
|
|
@@ -45,16 +43,7 @@ export function route<TTypes extends VectorTypes = DefaultVectorTypes>(
|
|
|
45
43
|
|
|
46
44
|
const entry: RouteEntry = [
|
|
47
45
|
options.method.toUpperCase(),
|
|
48
|
-
|
|
49
|
-
`^${
|
|
50
|
-
options.path
|
|
51
|
-
.replace(/\/+(\/|$)/g, "$1") // strip double & trailing splash
|
|
52
|
-
.replace(/(\/?\.?):(\w+)\+/g, "($1(?<$2>*))") // greedy params
|
|
53
|
-
.replace(/(\/?\.?):(\w+)/g, "($1(?<$2>[^$1/]+?))") // named params and image format
|
|
54
|
-
.replace(/\./g, "\\.") // dot in path
|
|
55
|
-
.replace(/(\/?)\*/g, "($1.*)?") // wildcard
|
|
56
|
-
}/*$`
|
|
57
|
-
),
|
|
46
|
+
buildRouteRegex(options.path),
|
|
58
47
|
[handler],
|
|
59
48
|
options.path,
|
|
60
49
|
];
|
|
@@ -66,24 +55,30 @@ export function route<TTypes extends VectorTypes = DefaultVectorTypes>(
|
|
|
66
55
|
};
|
|
67
56
|
}
|
|
68
57
|
|
|
58
|
+
function hasBigInt(value: unknown, depth = 0): boolean {
|
|
59
|
+
if (typeof value === 'bigint') return true;
|
|
60
|
+
if (depth > 4 || value === null || typeof value !== 'object') return false;
|
|
61
|
+
for (const v of Object.values(value as object)) {
|
|
62
|
+
if (hasBigInt(v, depth + 1)) return true;
|
|
63
|
+
}
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
|
|
69
67
|
function stringifyData(data: unknown): string {
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
const val = data ?? null;
|
|
69
|
+
if (!hasBigInt(val)) return JSON.stringify(val);
|
|
70
|
+
return JSON.stringify(val, (_key, value) =>
|
|
71
|
+
typeof value === 'bigint' ? value.toString() : value
|
|
72
72
|
);
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
const ApiResponse = {
|
|
76
|
-
success: <T>(data: T, contentType?: string) =>
|
|
77
|
-
createResponse(HTTP_STATUS.OK, data, contentType),
|
|
76
|
+
success: <T>(data: T, contentType?: string) => createResponse(HTTP_STATUS.OK, data, contentType),
|
|
78
77
|
created: <T>(data: T, contentType?: string) =>
|
|
79
78
|
createResponse(HTTP_STATUS.CREATED, data, contentType),
|
|
80
79
|
};
|
|
81
80
|
|
|
82
|
-
function createErrorResponse(
|
|
83
|
-
code: number,
|
|
84
|
-
message: string,
|
|
85
|
-
contentType?: string
|
|
86
|
-
): Response {
|
|
81
|
+
function createErrorResponse(code: number, message: string, contentType?: string): Response {
|
|
87
82
|
const errorBody = {
|
|
88
83
|
error: true,
|
|
89
84
|
message,
|
|
@@ -96,144 +91,129 @@ function createErrorResponse(
|
|
|
96
91
|
|
|
97
92
|
export const APIError = {
|
|
98
93
|
// 4xx Client Errors
|
|
99
|
-
badRequest: (msg =
|
|
94
|
+
badRequest: (msg = 'Bad Request', contentType?: string) =>
|
|
100
95
|
createErrorResponse(HTTP_STATUS.BAD_REQUEST, msg, contentType),
|
|
101
96
|
|
|
102
|
-
unauthorized: (msg =
|
|
97
|
+
unauthorized: (msg = 'Unauthorized', contentType?: string) =>
|
|
103
98
|
createErrorResponse(HTTP_STATUS.UNAUTHORIZED, msg, contentType),
|
|
104
99
|
|
|
105
|
-
paymentRequired: (msg =
|
|
100
|
+
paymentRequired: (msg = 'Payment Required', contentType?: string) =>
|
|
106
101
|
createErrorResponse(402, msg, contentType),
|
|
107
102
|
|
|
108
|
-
forbidden: (msg =
|
|
103
|
+
forbidden: (msg = 'Forbidden', contentType?: string) =>
|
|
109
104
|
createErrorResponse(HTTP_STATUS.FORBIDDEN, msg, contentType),
|
|
110
105
|
|
|
111
|
-
notFound: (msg =
|
|
106
|
+
notFound: (msg = 'Not Found', contentType?: string) =>
|
|
112
107
|
createErrorResponse(HTTP_STATUS.NOT_FOUND, msg, contentType),
|
|
113
108
|
|
|
114
|
-
methodNotAllowed: (msg =
|
|
109
|
+
methodNotAllowed: (msg = 'Method Not Allowed', contentType?: string) =>
|
|
115
110
|
createErrorResponse(405, msg, contentType),
|
|
116
111
|
|
|
117
|
-
notAcceptable: (msg =
|
|
112
|
+
notAcceptable: (msg = 'Not Acceptable', contentType?: string) =>
|
|
118
113
|
createErrorResponse(406, msg, contentType),
|
|
119
114
|
|
|
120
|
-
requestTimeout: (msg =
|
|
115
|
+
requestTimeout: (msg = 'Request Timeout', contentType?: string) =>
|
|
121
116
|
createErrorResponse(408, msg, contentType),
|
|
122
117
|
|
|
123
|
-
conflict: (msg =
|
|
118
|
+
conflict: (msg = 'Conflict', contentType?: string) =>
|
|
124
119
|
createErrorResponse(HTTP_STATUS.CONFLICT, msg, contentType),
|
|
125
120
|
|
|
126
|
-
gone: (msg =
|
|
127
|
-
createErrorResponse(410, msg, contentType),
|
|
121
|
+
gone: (msg = 'Gone', contentType?: string) => createErrorResponse(410, msg, contentType),
|
|
128
122
|
|
|
129
|
-
lengthRequired: (msg =
|
|
123
|
+
lengthRequired: (msg = 'Length Required', contentType?: string) =>
|
|
130
124
|
createErrorResponse(411, msg, contentType),
|
|
131
125
|
|
|
132
|
-
preconditionFailed: (msg =
|
|
126
|
+
preconditionFailed: (msg = 'Precondition Failed', contentType?: string) =>
|
|
133
127
|
createErrorResponse(412, msg, contentType),
|
|
134
128
|
|
|
135
|
-
payloadTooLarge: (msg =
|
|
129
|
+
payloadTooLarge: (msg = 'Payload Too Large', contentType?: string) =>
|
|
136
130
|
createErrorResponse(413, msg, contentType),
|
|
137
131
|
|
|
138
|
-
uriTooLong: (msg =
|
|
132
|
+
uriTooLong: (msg = 'URI Too Long', contentType?: string) =>
|
|
139
133
|
createErrorResponse(414, msg, contentType),
|
|
140
134
|
|
|
141
|
-
unsupportedMediaType: (
|
|
142
|
-
msg
|
|
143
|
-
contentType?: string
|
|
144
|
-
) => createErrorResponse(415, msg, contentType),
|
|
135
|
+
unsupportedMediaType: (msg = 'Unsupported Media Type', contentType?: string) =>
|
|
136
|
+
createErrorResponse(415, msg, contentType),
|
|
145
137
|
|
|
146
|
-
rangeNotSatisfiable: (msg =
|
|
138
|
+
rangeNotSatisfiable: (msg = 'Range Not Satisfiable', contentType?: string) =>
|
|
147
139
|
createErrorResponse(416, msg, contentType),
|
|
148
140
|
|
|
149
|
-
expectationFailed: (msg =
|
|
141
|
+
expectationFailed: (msg = 'Expectation Failed', contentType?: string) =>
|
|
150
142
|
createErrorResponse(417, msg, contentType),
|
|
151
143
|
|
|
152
144
|
imATeapot: (msg = "I'm a teapot", contentType?: string) =>
|
|
153
145
|
createErrorResponse(418, msg, contentType),
|
|
154
146
|
|
|
155
|
-
misdirectedRequest: (msg =
|
|
147
|
+
misdirectedRequest: (msg = 'Misdirected Request', contentType?: string) =>
|
|
156
148
|
createErrorResponse(421, msg, contentType),
|
|
157
149
|
|
|
158
|
-
unprocessableEntity: (msg =
|
|
150
|
+
unprocessableEntity: (msg = 'Unprocessable Entity', contentType?: string) =>
|
|
159
151
|
createErrorResponse(HTTP_STATUS.UNPROCESSABLE_ENTITY, msg, contentType),
|
|
160
152
|
|
|
161
|
-
locked: (msg =
|
|
162
|
-
createErrorResponse(423, msg, contentType),
|
|
153
|
+
locked: (msg = 'Locked', contentType?: string) => createErrorResponse(423, msg, contentType),
|
|
163
154
|
|
|
164
|
-
failedDependency: (msg =
|
|
155
|
+
failedDependency: (msg = 'Failed Dependency', contentType?: string) =>
|
|
165
156
|
createErrorResponse(424, msg, contentType),
|
|
166
157
|
|
|
167
|
-
tooEarly: (msg =
|
|
168
|
-
createErrorResponse(425, msg, contentType),
|
|
158
|
+
tooEarly: (msg = 'Too Early', contentType?: string) => createErrorResponse(425, msg, contentType),
|
|
169
159
|
|
|
170
|
-
upgradeRequired: (msg =
|
|
160
|
+
upgradeRequired: (msg = 'Upgrade Required', contentType?: string) =>
|
|
171
161
|
createErrorResponse(426, msg, contentType),
|
|
172
162
|
|
|
173
|
-
preconditionRequired: (msg =
|
|
163
|
+
preconditionRequired: (msg = 'Precondition Required', contentType?: string) =>
|
|
174
164
|
createErrorResponse(428, msg, contentType),
|
|
175
165
|
|
|
176
|
-
tooManyRequests: (msg =
|
|
166
|
+
tooManyRequests: (msg = 'Too Many Requests', contentType?: string) =>
|
|
177
167
|
createErrorResponse(429, msg, contentType),
|
|
178
168
|
|
|
179
|
-
requestHeaderFieldsTooLarge: (
|
|
180
|
-
msg
|
|
181
|
-
contentType?: string
|
|
182
|
-
) => createErrorResponse(431, msg, contentType),
|
|
169
|
+
requestHeaderFieldsTooLarge: (msg = 'Request Header Fields Too Large', contentType?: string) =>
|
|
170
|
+
createErrorResponse(431, msg, contentType),
|
|
183
171
|
|
|
184
|
-
unavailableForLegalReasons: (
|
|
185
|
-
msg
|
|
186
|
-
contentType?: string
|
|
187
|
-
) => createErrorResponse(451, msg, contentType),
|
|
172
|
+
unavailableForLegalReasons: (msg = 'Unavailable For Legal Reasons', contentType?: string) =>
|
|
173
|
+
createErrorResponse(451, msg, contentType),
|
|
188
174
|
|
|
189
175
|
// 5xx Server Errors
|
|
190
|
-
internalServerError: (msg =
|
|
176
|
+
internalServerError: (msg = 'Internal Server Error', contentType?: string) =>
|
|
191
177
|
createErrorResponse(HTTP_STATUS.INTERNAL_SERVER_ERROR, msg, contentType),
|
|
192
178
|
|
|
193
|
-
notImplemented: (msg =
|
|
179
|
+
notImplemented: (msg = 'Not Implemented', contentType?: string) =>
|
|
194
180
|
createErrorResponse(501, msg, contentType),
|
|
195
181
|
|
|
196
|
-
badGateway: (msg =
|
|
182
|
+
badGateway: (msg = 'Bad Gateway', contentType?: string) =>
|
|
197
183
|
createErrorResponse(502, msg, contentType),
|
|
198
184
|
|
|
199
|
-
serviceUnavailable: (msg =
|
|
185
|
+
serviceUnavailable: (msg = 'Service Unavailable', contentType?: string) =>
|
|
200
186
|
createErrorResponse(503, msg, contentType),
|
|
201
187
|
|
|
202
|
-
gatewayTimeout: (msg =
|
|
188
|
+
gatewayTimeout: (msg = 'Gateway Timeout', contentType?: string) =>
|
|
203
189
|
createErrorResponse(504, msg, contentType),
|
|
204
190
|
|
|
205
|
-
httpVersionNotSupported: (
|
|
206
|
-
msg
|
|
207
|
-
contentType?: string
|
|
208
|
-
) => createErrorResponse(505, msg, contentType),
|
|
191
|
+
httpVersionNotSupported: (msg = 'HTTP Version Not Supported', contentType?: string) =>
|
|
192
|
+
createErrorResponse(505, msg, contentType),
|
|
209
193
|
|
|
210
|
-
variantAlsoNegotiates: (
|
|
211
|
-
msg
|
|
212
|
-
contentType?: string
|
|
213
|
-
) => createErrorResponse(506, msg, contentType),
|
|
194
|
+
variantAlsoNegotiates: (msg = 'Variant Also Negotiates', contentType?: string) =>
|
|
195
|
+
createErrorResponse(506, msg, contentType),
|
|
214
196
|
|
|
215
|
-
insufficientStorage: (msg =
|
|
197
|
+
insufficientStorage: (msg = 'Insufficient Storage', contentType?: string) =>
|
|
216
198
|
createErrorResponse(507, msg, contentType),
|
|
217
199
|
|
|
218
|
-
loopDetected: (msg =
|
|
200
|
+
loopDetected: (msg = 'Loop Detected', contentType?: string) =>
|
|
219
201
|
createErrorResponse(508, msg, contentType),
|
|
220
202
|
|
|
221
|
-
notExtended: (msg =
|
|
203
|
+
notExtended: (msg = 'Not Extended', contentType?: string) =>
|
|
222
204
|
createErrorResponse(510, msg, contentType),
|
|
223
205
|
|
|
224
|
-
networkAuthenticationRequired: (
|
|
225
|
-
msg
|
|
226
|
-
contentType?: string
|
|
227
|
-
) => createErrorResponse(511, msg, contentType),
|
|
206
|
+
networkAuthenticationRequired: (msg = 'Network Authentication Required', contentType?: string) =>
|
|
207
|
+
createErrorResponse(511, msg, contentType),
|
|
228
208
|
|
|
229
209
|
// Aliases for common use cases
|
|
230
|
-
invalidArgument: (msg =
|
|
210
|
+
invalidArgument: (msg = 'Invalid Argument', contentType?: string) =>
|
|
231
211
|
createErrorResponse(HTTP_STATUS.UNPROCESSABLE_ENTITY, msg, contentType),
|
|
232
212
|
|
|
233
|
-
rateLimitExceeded: (msg =
|
|
213
|
+
rateLimitExceeded: (msg = 'Rate Limit Exceeded', contentType?: string) =>
|
|
234
214
|
createErrorResponse(429, msg, contentType),
|
|
235
215
|
|
|
236
|
-
maintenance: (msg =
|
|
216
|
+
maintenance: (msg = 'Service Under Maintenance', contentType?: string) =>
|
|
237
217
|
createErrorResponse(503, msg, contentType),
|
|
238
218
|
|
|
239
219
|
// Helper to create custom error with any status code
|
|
@@ -250,13 +230,11 @@ export function createResponse(
|
|
|
250
230
|
|
|
251
231
|
return new Response(body as string, {
|
|
252
232
|
status: statusCode,
|
|
253
|
-
headers: {
|
|
233
|
+
headers: { 'content-type': contentType },
|
|
254
234
|
});
|
|
255
235
|
}
|
|
256
236
|
|
|
257
|
-
export const protectedRoute = async <
|
|
258
|
-
TTypes extends VectorTypes = DefaultVectorTypes
|
|
259
|
-
>(
|
|
237
|
+
export const protectedRoute = async <TTypes extends VectorTypes = DefaultVectorTypes>(
|
|
260
238
|
request: VectorRequest<TTypes>,
|
|
261
239
|
responseContentType?: string
|
|
262
240
|
) => {
|
|
@@ -265,10 +243,7 @@ export const protectedRoute = async <
|
|
|
265
243
|
|
|
266
244
|
const protectedHandler = vector.getProtectedHandler();
|
|
267
245
|
if (!protectedHandler) {
|
|
268
|
-
throw APIError.unauthorized(
|
|
269
|
-
"Authentication not configured",
|
|
270
|
-
responseContentType
|
|
271
|
-
);
|
|
246
|
+
throw APIError.unauthorized('Authentication not configured', responseContentType);
|
|
272
247
|
}
|
|
273
248
|
|
|
274
249
|
try {
|
|
@@ -276,7 +251,7 @@ export const protectedRoute = async <
|
|
|
276
251
|
request.authUser = authUser as GetAuthType<TTypes>;
|
|
277
252
|
} catch (error) {
|
|
278
253
|
throw APIError.unauthorized(
|
|
279
|
-
error instanceof Error ? error.message :
|
|
254
|
+
error instanceof Error ? error.message : 'Authentication failed',
|
|
280
255
|
responseContentType
|
|
281
256
|
);
|
|
282
257
|
}
|
|
@@ -307,15 +282,12 @@ export function api<TTypes extends VectorTypes = DefaultVectorTypes>(
|
|
|
307
282
|
// This wrapper is only used when routes are NOT auto-discovered
|
|
308
283
|
return async (request: IRequest) => {
|
|
309
284
|
if (!expose) {
|
|
310
|
-
return APIError.forbidden(
|
|
285
|
+
return APIError.forbidden('Forbidden');
|
|
311
286
|
}
|
|
312
287
|
|
|
313
288
|
try {
|
|
314
289
|
if (auth) {
|
|
315
|
-
await protectedRoute(
|
|
316
|
-
request as any as VectorRequest<TTypes>,
|
|
317
|
-
responseContentType
|
|
318
|
-
);
|
|
290
|
+
await protectedRoute(request as any as VectorRequest<TTypes>, responseContentType);
|
|
319
291
|
}
|
|
320
292
|
|
|
321
293
|
if (!rawRequest) {
|
|
@@ -325,9 +297,7 @@ export function api<TTypes extends VectorTypes = DefaultVectorTypes>(
|
|
|
325
297
|
// Cache handling is now done in the router
|
|
326
298
|
const result = await fn(request as any as VectorRequest<TTypes>);
|
|
327
299
|
|
|
328
|
-
return rawResponse
|
|
329
|
-
? result
|
|
330
|
-
: ApiResponse.success(result, responseContentType);
|
|
300
|
+
return rawResponse ? result : ApiResponse.success(result, responseContentType);
|
|
331
301
|
} catch (err: unknown) {
|
|
332
302
|
// Ensure we return a Response object
|
|
333
303
|
if (err instanceof Response) {
|
package/src/index.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
// Public exports for route definitions only
|
|
2
|
-
import { route } from
|
|
2
|
+
import { route } from './http';
|
|
3
3
|
|
|
4
4
|
// Export route function for defining routes
|
|
5
5
|
export { route };
|
|
6
6
|
|
|
7
7
|
// Export utilities for route handlers
|
|
8
|
-
export { APIError, createResponse } from
|
|
8
|
+
export { APIError, createResponse } from './http';
|
|
9
9
|
|
|
10
10
|
// Export types for TypeScript users
|
|
11
|
-
export * from
|
|
11
|
+
export * from './types';
|
|
12
12
|
|
|
13
13
|
// Note: Vector framework is now config-driven and runs via CLI
|
|
14
14
|
// Usage: Create vector.config.ts and run 'vector dev' or 'vector start'
|
|
@@ -4,11 +4,9 @@ import type {
|
|
|
4
4
|
DefaultVectorTypes,
|
|
5
5
|
VectorRequest,
|
|
6
6
|
VectorTypes,
|
|
7
|
-
} from
|
|
7
|
+
} from '../types';
|
|
8
8
|
|
|
9
|
-
export class MiddlewareManager<
|
|
10
|
-
TTypes extends VectorTypes = DefaultVectorTypes
|
|
11
|
-
> {
|
|
9
|
+
export class MiddlewareManager<TTypes extends VectorTypes = DefaultVectorTypes> {
|
|
12
10
|
private beforeHandlers: BeforeMiddlewareHandler<TTypes>[] = [];
|
|
13
11
|
private finallyHandlers: AfterMiddlewareHandler<TTypes>[] = [];
|
|
14
12
|
|
|
@@ -20,9 +18,7 @@ export class MiddlewareManager<
|
|
|
20
18
|
this.finallyHandlers.push(...handlers);
|
|
21
19
|
}
|
|
22
20
|
|
|
23
|
-
async executeBefore(
|
|
24
|
-
request: VectorRequest<TTypes>
|
|
25
|
-
): Promise<VectorRequest<TTypes> | Response> {
|
|
21
|
+
async executeBefore(request: VectorRequest<TTypes>): Promise<VectorRequest<TTypes> | Response> {
|
|
26
22
|
let currentRequest = request;
|
|
27
23
|
|
|
28
24
|
for (const handler of this.beforeHandlers) {
|
|
@@ -38,10 +34,7 @@ export class MiddlewareManager<
|
|
|
38
34
|
return currentRequest;
|
|
39
35
|
}
|
|
40
36
|
|
|
41
|
-
async executeFinally(
|
|
42
|
-
response: Response,
|
|
43
|
-
request: VectorRequest<TTypes>
|
|
44
|
-
): Promise<Response> {
|
|
37
|
+
async executeFinally(response: Response, request: VectorRequest<TTypes>): Promise<Response> {
|
|
45
38
|
let currentResponse = response;
|
|
46
39
|
|
|
47
40
|
for (const handler of this.finallyHandlers) {
|
package/src/utils/path.ts
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
export function toFileUrl(path: string): string {
|
|
2
|
-
return process.platform === 'win32'
|
|
3
|
-
? `file:///${path.replace(/\\/g, '/')}`
|
|
4
|
-
: path;
|
|
2
|
+
return process.platform === 'win32' ? `file:///${path.replace(/\\/g, '/')}` : path;
|
|
5
3
|
}
|
|
6
4
|
|
|
7
5
|
export function normalizePath(path: string): string {
|
|
8
6
|
return path.replace(/\\/g, '/').replace(/\/+/g, '/');
|
|
9
|
-
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function buildRouteRegex(path: string): RegExp {
|
|
10
|
+
return RegExp(
|
|
11
|
+
`^${path
|
|
12
|
+
.replace(/\/+(\/|$)/g, '$1')
|
|
13
|
+
.replace(/(\/?\.?):(\w+)\+/g, '($1(?<$2>[\\s\\S]+))')
|
|
14
|
+
.replace(/(\/?\.?):(\w+)/g, '($1(?<$2>[^$1/]+?))')
|
|
15
|
+
.replace(/\./g, '\\.')
|
|
16
|
+
.replace(/(\/?)\*/g, '($1.*)?')}/*$`
|
|
17
|
+
);
|
|
18
|
+
}
|