vitek-plugin 0.1.0-beta
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/README.md +908 -0
- package/dist/adapters/vite/dev-server.d.ts +23 -0
- package/dist/adapters/vite/dev-server.d.ts.map +1 -0
- package/dist/adapters/vite/dev-server.js +428 -0
- package/dist/adapters/vite/logger.d.ts +33 -0
- package/dist/adapters/vite/logger.d.ts.map +1 -0
- package/dist/adapters/vite/logger.js +112 -0
- package/dist/core/context/create-context.d.ts +39 -0
- package/dist/core/context/create-context.d.ts.map +1 -0
- package/dist/core/context/create-context.js +34 -0
- package/dist/core/file-system/scan-api-dir.d.ts +26 -0
- package/dist/core/file-system/scan-api-dir.d.ts.map +1 -0
- package/dist/core/file-system/scan-api-dir.js +83 -0
- package/dist/core/file-system/watch-api-dir.d.ts +18 -0
- package/dist/core/file-system/watch-api-dir.d.ts.map +1 -0
- package/dist/core/file-system/watch-api-dir.js +40 -0
- package/dist/core/middleware/compose.d.ts +12 -0
- package/dist/core/middleware/compose.d.ts.map +1 -0
- package/dist/core/middleware/compose.js +27 -0
- package/dist/core/middleware/get-applicable-middlewares.d.ts +17 -0
- package/dist/core/middleware/get-applicable-middlewares.d.ts.map +1 -0
- package/dist/core/middleware/get-applicable-middlewares.js +47 -0
- package/dist/core/middleware/load-global.d.ts +13 -0
- package/dist/core/middleware/load-global.d.ts.map +1 -0
- package/dist/core/middleware/load-global.js +37 -0
- package/dist/core/normalize/normalize-path.d.ts +25 -0
- package/dist/core/normalize/normalize-path.d.ts.map +1 -0
- package/dist/core/normalize/normalize-path.js +76 -0
- package/dist/core/routing/route-matcher.d.ts +10 -0
- package/dist/core/routing/route-matcher.d.ts.map +1 -0
- package/dist/core/routing/route-matcher.js +32 -0
- package/dist/core/routing/route-parser.d.ts +28 -0
- package/dist/core/routing/route-parser.d.ts.map +1 -0
- package/dist/core/routing/route-parser.js +52 -0
- package/dist/core/routing/route-types.d.ts +43 -0
- package/dist/core/routing/route-types.d.ts.map +1 -0
- package/dist/core/routing/route-types.js +5 -0
- package/dist/core/types/extract-ast.d.ts +18 -0
- package/dist/core/types/extract-ast.d.ts.map +1 -0
- package/dist/core/types/extract-ast.js +26 -0
- package/dist/core/types/generate.d.ts +22 -0
- package/dist/core/types/generate.d.ts.map +1 -0
- package/dist/core/types/generate.js +576 -0
- package/dist/core/types/schema.d.ts +21 -0
- package/dist/core/types/schema.d.ts.map +1 -0
- package/dist/core/types/schema.js +17 -0
- package/dist/core/validation/types.d.ts +27 -0
- package/dist/core/validation/types.d.ts.map +1 -0
- package/dist/core/validation/types.js +5 -0
- package/dist/core/validation/validator.d.ts +22 -0
- package/dist/core/validation/validator.d.ts.map +1 -0
- package/dist/core/validation/validator.js +131 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/plugin.d.ts +27 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +54 -0
- package/dist/shared/constants.d.ts +13 -0
- package/dist/shared/constants.d.ts.map +1 -0
- package/dist/shared/constants.js +12 -0
- package/dist/shared/errors.d.ts +75 -0
- package/dist/shared/errors.d.ts.map +1 -0
- package/dist/shared/errors.js +118 -0
- package/dist/shared/response-helpers.d.ts +61 -0
- package/dist/shared/response-helpers.d.ts.map +1 -0
- package/dist/shared/response-helpers.js +100 -0
- package/dist/shared/utils.d.ts +17 -0
- package/dist/shared/utils.d.ts.map +1 -0
- package/dist/shared/utils.js +27 -0
- package/package.json +48 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation logic
|
|
3
|
+
* Core logic - runtime agnostic
|
|
4
|
+
*/
|
|
5
|
+
import { ValidationError } from '../../shared/errors.js';
|
|
6
|
+
/**
|
|
7
|
+
* Validates a value against a validation rule
|
|
8
|
+
*/
|
|
9
|
+
function validateField(value, fieldName, rule) {
|
|
10
|
+
// Check required
|
|
11
|
+
if (rule.required && (value === undefined || value === null || value === '')) {
|
|
12
|
+
return `${fieldName} is required`;
|
|
13
|
+
}
|
|
14
|
+
// If not required and value is empty, skip other validations
|
|
15
|
+
if (!rule.required && (value === undefined || value === null || value === '')) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
// Type validation
|
|
19
|
+
switch (rule.type) {
|
|
20
|
+
case 'string':
|
|
21
|
+
if (typeof value !== 'string') {
|
|
22
|
+
return `${fieldName} must be a string`;
|
|
23
|
+
}
|
|
24
|
+
if (rule.min !== undefined && value.length < rule.min) {
|
|
25
|
+
return `${fieldName} must be at least ${rule.min} characters`;
|
|
26
|
+
}
|
|
27
|
+
if (rule.max !== undefined && value.length > rule.max) {
|
|
28
|
+
return `${fieldName} must be at most ${rule.max} characters`;
|
|
29
|
+
}
|
|
30
|
+
if (rule.pattern) {
|
|
31
|
+
const regex = typeof rule.pattern === 'string' ? new RegExp(rule.pattern) : rule.pattern;
|
|
32
|
+
if (!regex.test(value)) {
|
|
33
|
+
return `${fieldName} does not match the required pattern`;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
break;
|
|
37
|
+
case 'number':
|
|
38
|
+
const numValue = typeof value === 'string' ? Number(value) : value;
|
|
39
|
+
if (typeof numValue !== 'number' || isNaN(numValue)) {
|
|
40
|
+
return `${fieldName} must be a number`;
|
|
41
|
+
}
|
|
42
|
+
if (rule.min !== undefined && numValue < rule.min) {
|
|
43
|
+
return `${fieldName} must be at least ${rule.min}`;
|
|
44
|
+
}
|
|
45
|
+
if (rule.max !== undefined && numValue > rule.max) {
|
|
46
|
+
return `${fieldName} must be at most ${rule.max}`;
|
|
47
|
+
}
|
|
48
|
+
break;
|
|
49
|
+
case 'boolean':
|
|
50
|
+
if (typeof value !== 'boolean') {
|
|
51
|
+
// Try to convert string to boolean
|
|
52
|
+
if (typeof value === 'string') {
|
|
53
|
+
const lower = value.toLowerCase();
|
|
54
|
+
if (lower !== 'true' && lower !== 'false') {
|
|
55
|
+
return `${fieldName} must be a boolean`;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
return `${fieldName} must be a boolean`;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
break;
|
|
63
|
+
case 'object':
|
|
64
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
65
|
+
return `${fieldName} must be an object`;
|
|
66
|
+
}
|
|
67
|
+
break;
|
|
68
|
+
case 'array':
|
|
69
|
+
if (!Array.isArray(value)) {
|
|
70
|
+
return `${fieldName} must be an array`;
|
|
71
|
+
}
|
|
72
|
+
if (rule.min !== undefined && value.length < rule.min) {
|
|
73
|
+
return `${fieldName} must have at least ${rule.min} items`;
|
|
74
|
+
}
|
|
75
|
+
if (rule.max !== undefined && value.length > rule.max) {
|
|
76
|
+
return `${fieldName} must have at most ${rule.max} items`;
|
|
77
|
+
}
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
// Custom validation
|
|
81
|
+
if (rule.custom) {
|
|
82
|
+
const customResult = rule.custom(value);
|
|
83
|
+
if (customResult !== true) {
|
|
84
|
+
return typeof customResult === 'string' ? customResult : `${fieldName} is invalid`;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Validates an object against a validation schema
|
|
91
|
+
*/
|
|
92
|
+
export function validate(data, schema) {
|
|
93
|
+
const errors = {};
|
|
94
|
+
for (const [fieldName, rule] of Object.entries(schema)) {
|
|
95
|
+
const value = data?.[fieldName];
|
|
96
|
+
const error = validateField(value, fieldName, rule);
|
|
97
|
+
if (error) {
|
|
98
|
+
if (!errors[fieldName]) {
|
|
99
|
+
errors[fieldName] = [];
|
|
100
|
+
}
|
|
101
|
+
errors[fieldName].push(error);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
valid: Object.keys(errors).length === 0,
|
|
106
|
+
errors: Object.keys(errors).length > 0 ? errors : undefined,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Validates and throws ValidationError if invalid
|
|
111
|
+
*/
|
|
112
|
+
export function validateOrThrow(data, schema) {
|
|
113
|
+
const result = validate(data, schema);
|
|
114
|
+
if (!result.valid) {
|
|
115
|
+
throw new ValidationError('Validation failed', result.errors);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Validates body parameters
|
|
120
|
+
*/
|
|
121
|
+
export function validateBody(body, schema) {
|
|
122
|
+
validateOrThrow(body, schema);
|
|
123
|
+
return body;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Validates query parameters
|
|
127
|
+
*/
|
|
128
|
+
export function validateQuery(query, schema) {
|
|
129
|
+
validateOrThrow(query, schema);
|
|
130
|
+
return query;
|
|
131
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Export público do pacote Vitek
|
|
3
|
+
*/
|
|
4
|
+
export { vitek } from './plugin.js';
|
|
5
|
+
export type { VitekOptions } from './plugin.js';
|
|
6
|
+
export type { VitekContext, VitekRequest, } from './core/context/create-context.js';
|
|
7
|
+
export type { Route, RouteHandler, Middleware, RouteMatch, } from './core/routing/route-types.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,YAAY,EACV,YAAY,EACZ,YAAY,GACb,MAAM,kCAAkC,CAAC;AAE1C,YAAY,EACV,KAAK,EACL,YAAY,EACZ,UAAU,EACV,UAAU,GACX,MAAM,+BAA+B,CAAC"}
|
package/dist/index.js
ADDED
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main Vite plugin
|
|
3
|
+
* Thin layer that registers the plugin and connects with adapters
|
|
4
|
+
*/
|
|
5
|
+
import type { Plugin } from 'vite';
|
|
6
|
+
export interface VitekOptions {
|
|
7
|
+
/** API directory (relative to root) */
|
|
8
|
+
apiDir?: string;
|
|
9
|
+
/** API base path (default: /api) */
|
|
10
|
+
apiBasePath?: string;
|
|
11
|
+
/** Enable request validation (default: false) */
|
|
12
|
+
enableValidation?: boolean;
|
|
13
|
+
/** Logging configuration */
|
|
14
|
+
logging?: {
|
|
15
|
+
/** Log level: 'debug' | 'info' | 'warn' | 'error' (default: 'info') */
|
|
16
|
+
level?: 'debug' | 'info' | 'warn' | 'error';
|
|
17
|
+
/** Enable request/response logging (default: false) */
|
|
18
|
+
enableRequestLogging?: boolean;
|
|
19
|
+
/** Enable route matching logs (default: true) */
|
|
20
|
+
enableRouteLogging?: boolean;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Vite plugin for Vitek
|
|
25
|
+
*/
|
|
26
|
+
export declare function vitek(options?: VitekOptions): Plugin;
|
|
27
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAOnC,MAAM,WAAW,YAAY;IAC3B,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,4BAA4B;IAC5B,OAAO,CAAC,EAAE;QACR,uEAAuE;QACvE,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;QAC5C,uDAAuD;QACvD,oBAAoB,CAAC,EAAE,OAAO,CAAC;QAC/B,iDAAiD;QACjD,kBAAkB,CAAC,EAAE,OAAO,CAAC;KAC9B,CAAC;CACH;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,OAAO,GAAE,YAAiB,GAAG,MAAM,CAoDxD"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main Vite plugin
|
|
3
|
+
* Thin layer that registers the plugin and connects with adapters
|
|
4
|
+
*/
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
import * as fs from 'fs';
|
|
7
|
+
import { createViteDevServerMiddleware } from './adapters/vite/dev-server.js';
|
|
8
|
+
import { createViteLogger } from './adapters/vite/logger.js';
|
|
9
|
+
import { API_DIR_NAME } from './shared/constants.js';
|
|
10
|
+
/**
|
|
11
|
+
* Vite plugin for Vitek
|
|
12
|
+
*/
|
|
13
|
+
export function vitek(options = {}) {
|
|
14
|
+
const apiDir = options.apiDir || `src/${API_DIR_NAME}`;
|
|
15
|
+
let root;
|
|
16
|
+
let cleanupFn = null;
|
|
17
|
+
return {
|
|
18
|
+
name: 'vitek',
|
|
19
|
+
configResolved(config) {
|
|
20
|
+
root = config.root;
|
|
21
|
+
},
|
|
22
|
+
configureServer(server) {
|
|
23
|
+
const fullApiDir = path.resolve(root, apiDir);
|
|
24
|
+
// Check if directory exists
|
|
25
|
+
if (!fs.existsSync(fullApiDir)) {
|
|
26
|
+
server.config.logger.warn(`[vitek] API directory not found: ${fullApiDir}`);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
// Create logger and middleware
|
|
30
|
+
const logger = createViteLogger(server.config.logger, options.logging);
|
|
31
|
+
const { middleware, cleanup } = createViteDevServerMiddleware({
|
|
32
|
+
root,
|
|
33
|
+
apiDir: fullApiDir,
|
|
34
|
+
logger,
|
|
35
|
+
viteServer: server,
|
|
36
|
+
enableValidation: options.enableValidation || false,
|
|
37
|
+
});
|
|
38
|
+
cleanupFn = cleanup;
|
|
39
|
+
// Register middleware in Vite server
|
|
40
|
+
server.middlewares.use(middleware);
|
|
41
|
+
logger.info('Vitek plugin initialized');
|
|
42
|
+
// Show relative path to root
|
|
43
|
+
const relativeApiDir = path.relative(root, fullApiDir);
|
|
44
|
+
logger.info(`API directory: ./${relativeApiDir.replace(/\\/g, '/')}`);
|
|
45
|
+
},
|
|
46
|
+
buildEnd() {
|
|
47
|
+
// Clean up resources when build ends
|
|
48
|
+
if (cleanupFn) {
|
|
49
|
+
cleanupFn();
|
|
50
|
+
cleanupFn = null;
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constantes compartilhadas do Vitek
|
|
3
|
+
*/
|
|
4
|
+
export declare const HTTP_METHODS: readonly ["get", "post", "put", "patch", "delete", "head", "options"];
|
|
5
|
+
export type HttpMethod = typeof HTTP_METHODS[number];
|
|
6
|
+
export declare const API_BASE_PATH = "/api";
|
|
7
|
+
export declare const API_DIR_NAME = "api";
|
|
8
|
+
export declare const GENERATED_TYPES_FILE = "api.types.ts";
|
|
9
|
+
export declare const GENERATED_SERVICES_FILE = "api.services.ts";
|
|
10
|
+
export declare const ROUTE_FILE_PATTERN: RegExp;
|
|
11
|
+
export declare const MIDDLEWARE_FILE_PATTERN: RegExp;
|
|
12
|
+
export declare const PARAM_PATTERN: RegExp;
|
|
13
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/shared/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,YAAY,uEAAwE,CAAC;AAClG,MAAM,MAAM,UAAU,GAAG,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC;AAErD,eAAO,MAAM,aAAa,SAAS,CAAC;AACpC,eAAO,MAAM,YAAY,QAAQ,CAAC;AAClC,eAAO,MAAM,oBAAoB,iBAAiB,CAAC;AACnD,eAAO,MAAM,uBAAuB,oBAAoB,CAAC;AAGzD,eAAO,MAAM,kBAAkB,QAA8D,CAAC;AAC9F,eAAO,MAAM,uBAAuB,QAA0B,CAAC;AAC/D,eAAO,MAAM,aAAa,QAA2B,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constantes compartilhadas do Vitek
|
|
3
|
+
*/
|
|
4
|
+
export const HTTP_METHODS = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options'];
|
|
5
|
+
export const API_BASE_PATH = '/api';
|
|
6
|
+
export const API_DIR_NAME = 'api';
|
|
7
|
+
export const GENERATED_TYPES_FILE = 'api.types.ts';
|
|
8
|
+
export const GENERATED_SERVICES_FILE = 'api.services.ts';
|
|
9
|
+
// Padrões de nomeação de arquivos
|
|
10
|
+
export const ROUTE_FILE_PATTERN = /^(.+)\.(get|post|put|patch|delete|head|options)\.(ts|js)$/;
|
|
11
|
+
export const MIDDLEWARE_FILE_PATTERN = /^middleware\.(ts|js)$/;
|
|
12
|
+
export const PARAM_PATTERN = /\[(\.\.\.)?([^\]]+)\]/g;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom Vitek errors
|
|
3
|
+
*/
|
|
4
|
+
export declare class VitekError extends Error {
|
|
5
|
+
code?: string | undefined;
|
|
6
|
+
constructor(message: string, code?: string | undefined);
|
|
7
|
+
}
|
|
8
|
+
export declare class RouteError extends VitekError {
|
|
9
|
+
route?: string | undefined;
|
|
10
|
+
constructor(message: string, route?: string | undefined);
|
|
11
|
+
}
|
|
12
|
+
export declare class MiddlewareError extends VitekError {
|
|
13
|
+
constructor(message: string);
|
|
14
|
+
}
|
|
15
|
+
export declare class TypeGenerationError extends VitekError {
|
|
16
|
+
constructor(message: string);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Base HTTP error class with status code
|
|
20
|
+
*/
|
|
21
|
+
export declare class HttpError extends VitekError {
|
|
22
|
+
statusCode: number;
|
|
23
|
+
constructor(message: string, statusCode?: number, code?: string);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* 400 Bad Request error
|
|
27
|
+
*/
|
|
28
|
+
export declare class BadRequestError extends HttpError {
|
|
29
|
+
constructor(message?: string);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 401 Unauthorized error
|
|
33
|
+
*/
|
|
34
|
+
export declare class UnauthorizedError extends HttpError {
|
|
35
|
+
constructor(message?: string);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* 403 Forbidden error
|
|
39
|
+
*/
|
|
40
|
+
export declare class ForbiddenError extends HttpError {
|
|
41
|
+
constructor(message?: string);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 404 Not Found error
|
|
45
|
+
*/
|
|
46
|
+
export declare class NotFoundError extends HttpError {
|
|
47
|
+
route?: string | undefined;
|
|
48
|
+
constructor(message?: string, route?: string | undefined);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* 409 Conflict error
|
|
52
|
+
*/
|
|
53
|
+
export declare class ConflictError extends HttpError {
|
|
54
|
+
constructor(message?: string);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* 422 Unprocessable Entity error (validation errors)
|
|
58
|
+
*/
|
|
59
|
+
export declare class ValidationError extends HttpError {
|
|
60
|
+
errors?: Record<string, string[]> | undefined;
|
|
61
|
+
constructor(message?: string, errors?: Record<string, string[]> | undefined);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* 429 Too Many Requests error
|
|
65
|
+
*/
|
|
66
|
+
export declare class TooManyRequestsError extends HttpError {
|
|
67
|
+
constructor(message?: string);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* 500 Internal Server Error
|
|
71
|
+
*/
|
|
72
|
+
export declare class InternalServerError extends HttpError {
|
|
73
|
+
constructor(message?: string);
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/shared/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,qBAAa,UAAW,SAAQ,KAAK;IACC,IAAI,CAAC,EAAE,MAAM;gBAArC,OAAO,EAAE,MAAM,EAAS,IAAI,CAAC,EAAE,MAAM,YAAA;CAIlD;AAED,qBAAa,UAAW,SAAQ,UAAU;IACJ,KAAK,CAAC,EAAE,MAAM;gBAAtC,OAAO,EAAE,MAAM,EAAS,KAAK,CAAC,EAAE,MAAM,YAAA;CAInD;AAED,qBAAa,eAAgB,SAAQ,UAAU;gBACjC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,mBAAoB,SAAQ,UAAU;gBACrC,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,qBAAa,SAAU,SAAQ,UAAU;IAG9B,UAAU,EAAE,MAAM;gBADzB,OAAO,EAAE,MAAM,EACR,UAAU,GAAE,MAAY,EAC/B,IAAI,CAAC,EAAE,MAAM;CAKhB;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,SAAS;gBAChC,OAAO,GAAE,MAAsB;CAI5C;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,SAAS;gBAClC,OAAO,GAAE,MAAuB;CAI7C;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,SAAS;gBAC/B,OAAO,GAAE,MAAoB;CAI1C;AAED;;GAEG;AACH,qBAAa,aAAc,SAAQ,SAAS;IACQ,KAAK,CAAC,EAAE,MAAM;gBAApD,OAAO,GAAE,MAAoB,EAAS,KAAK,CAAC,EAAE,MAAM,YAAA;CAIjE;AAED;;GAEG;AACH,qBAAa,aAAc,SAAQ,SAAS;gBAC9B,OAAO,GAAE,MAAmB;CAIzC;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,SAAS;IAGnC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;gBADxC,OAAO,GAAE,MAA2B,EAC7B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,YAAA;CAK3C;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,SAAS;gBACrC,OAAO,GAAE,MAA4B;CAIlD;AAED;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;gBACpC,OAAO,GAAE,MAAgC;CAItD"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom Vitek errors
|
|
3
|
+
*/
|
|
4
|
+
export class VitekError extends Error {
|
|
5
|
+
code;
|
|
6
|
+
constructor(message, code) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.code = code;
|
|
9
|
+
this.name = 'VitekError';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export class RouteError extends VitekError {
|
|
13
|
+
route;
|
|
14
|
+
constructor(message, route) {
|
|
15
|
+
super(message, 'ROUTE_ERROR');
|
|
16
|
+
this.route = route;
|
|
17
|
+
this.name = 'RouteError';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export class MiddlewareError extends VitekError {
|
|
21
|
+
constructor(message) {
|
|
22
|
+
super(message, 'MIDDLEWARE_ERROR');
|
|
23
|
+
this.name = 'MiddlewareError';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export class TypeGenerationError extends VitekError {
|
|
27
|
+
constructor(message) {
|
|
28
|
+
super(message, 'TYPE_GENERATION_ERROR');
|
|
29
|
+
this.name = 'TypeGenerationError';
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Base HTTP error class with status code
|
|
34
|
+
*/
|
|
35
|
+
export class HttpError extends VitekError {
|
|
36
|
+
statusCode;
|
|
37
|
+
constructor(message, statusCode = 500, code) {
|
|
38
|
+
super(message, code);
|
|
39
|
+
this.statusCode = statusCode;
|
|
40
|
+
this.name = 'HttpError';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 400 Bad Request error
|
|
45
|
+
*/
|
|
46
|
+
export class BadRequestError extends HttpError {
|
|
47
|
+
constructor(message = 'Bad request') {
|
|
48
|
+
super(message, 400, 'BAD_REQUEST');
|
|
49
|
+
this.name = 'BadRequestError';
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* 401 Unauthorized error
|
|
54
|
+
*/
|
|
55
|
+
export class UnauthorizedError extends HttpError {
|
|
56
|
+
constructor(message = 'Unauthorized') {
|
|
57
|
+
super(message, 401, 'UNAUTHORIZED');
|
|
58
|
+
this.name = 'UnauthorizedError';
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* 403 Forbidden error
|
|
63
|
+
*/
|
|
64
|
+
export class ForbiddenError extends HttpError {
|
|
65
|
+
constructor(message = 'Forbidden') {
|
|
66
|
+
super(message, 403, 'FORBIDDEN');
|
|
67
|
+
this.name = 'ForbiddenError';
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* 404 Not Found error
|
|
72
|
+
*/
|
|
73
|
+
export class NotFoundError extends HttpError {
|
|
74
|
+
route;
|
|
75
|
+
constructor(message = 'Not found', route) {
|
|
76
|
+
super(message, 404, 'NOT_FOUND');
|
|
77
|
+
this.route = route;
|
|
78
|
+
this.name = 'NotFoundError';
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* 409 Conflict error
|
|
83
|
+
*/
|
|
84
|
+
export class ConflictError extends HttpError {
|
|
85
|
+
constructor(message = 'Conflict') {
|
|
86
|
+
super(message, 409, 'CONFLICT');
|
|
87
|
+
this.name = 'ConflictError';
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* 422 Unprocessable Entity error (validation errors)
|
|
92
|
+
*/
|
|
93
|
+
export class ValidationError extends HttpError {
|
|
94
|
+
errors;
|
|
95
|
+
constructor(message = 'Validation error', errors) {
|
|
96
|
+
super(message, 422, 'VALIDATION_ERROR');
|
|
97
|
+
this.errors = errors;
|
|
98
|
+
this.name = 'ValidationError';
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* 429 Too Many Requests error
|
|
103
|
+
*/
|
|
104
|
+
export class TooManyRequestsError extends HttpError {
|
|
105
|
+
constructor(message = 'Too many requests') {
|
|
106
|
+
super(message, 429, 'TOO_MANY_REQUESTS');
|
|
107
|
+
this.name = 'TooManyRequestsError';
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* 500 Internal Server Error
|
|
112
|
+
*/
|
|
113
|
+
export class InternalServerError extends HttpError {
|
|
114
|
+
constructor(message = 'Internal server error') {
|
|
115
|
+
super(message, 500, 'INTERNAL_SERVER_ERROR');
|
|
116
|
+
this.name = 'InternalServerError';
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response helper functions for route handlers
|
|
3
|
+
* Provides convenient functions to create HTTP responses with status codes and headers
|
|
4
|
+
*/
|
|
5
|
+
import type { VitekResponse } from '../core/context/create-context.js';
|
|
6
|
+
/**
|
|
7
|
+
* Creates a JSON response with status code and optional headers
|
|
8
|
+
*/
|
|
9
|
+
export declare function json(body: any, options?: {
|
|
10
|
+
status?: number;
|
|
11
|
+
headers?: Record<string, string>;
|
|
12
|
+
}): VitekResponse;
|
|
13
|
+
/**
|
|
14
|
+
* Creates a 200 OK response
|
|
15
|
+
*/
|
|
16
|
+
export declare function ok(body: any, headers?: Record<string, string>): VitekResponse;
|
|
17
|
+
/**
|
|
18
|
+
* Creates a 201 Created response
|
|
19
|
+
*/
|
|
20
|
+
export declare function created(body: any, headers?: Record<string, string>): VitekResponse;
|
|
21
|
+
/**
|
|
22
|
+
* Creates a 204 No Content response
|
|
23
|
+
*/
|
|
24
|
+
export declare function noContent(headers?: Record<string, string>): VitekResponse;
|
|
25
|
+
/**
|
|
26
|
+
* Creates a 400 Bad Request response
|
|
27
|
+
*/
|
|
28
|
+
export declare function badRequest(body?: any, headers?: Record<string, string>): VitekResponse;
|
|
29
|
+
/**
|
|
30
|
+
* Creates a 401 Unauthorized response
|
|
31
|
+
*/
|
|
32
|
+
export declare function unauthorized(body?: any, headers?: Record<string, string>): VitekResponse;
|
|
33
|
+
/**
|
|
34
|
+
* Creates a 403 Forbidden response
|
|
35
|
+
*/
|
|
36
|
+
export declare function forbidden(body?: any, headers?: Record<string, string>): VitekResponse;
|
|
37
|
+
/**
|
|
38
|
+
* Creates a 404 Not Found response
|
|
39
|
+
*/
|
|
40
|
+
export declare function notFound(body?: any, headers?: Record<string, string>): VitekResponse;
|
|
41
|
+
/**
|
|
42
|
+
* Creates a 409 Conflict response
|
|
43
|
+
*/
|
|
44
|
+
export declare function conflict(body?: any, headers?: Record<string, string>): VitekResponse;
|
|
45
|
+
/**
|
|
46
|
+
* Creates a 422 Unprocessable Entity response (validation errors)
|
|
47
|
+
*/
|
|
48
|
+
export declare function unprocessableEntity(body?: any, headers?: Record<string, string>): VitekResponse;
|
|
49
|
+
/**
|
|
50
|
+
* Creates a 429 Too Many Requests response
|
|
51
|
+
*/
|
|
52
|
+
export declare function tooManyRequests(body?: any, headers?: Record<string, string>): VitekResponse;
|
|
53
|
+
/**
|
|
54
|
+
* Creates a 500 Internal Server Error response
|
|
55
|
+
*/
|
|
56
|
+
export declare function internalServerError(body?: any, headers?: Record<string, string>): VitekResponse;
|
|
57
|
+
/**
|
|
58
|
+
* Creates a redirect response (301, 302, 307, 308)
|
|
59
|
+
*/
|
|
60
|
+
export declare function redirect(url: string, permanent?: boolean, preserveMethod?: boolean): VitekResponse;
|
|
61
|
+
//# sourceMappingURL=response-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response-helpers.d.ts","sourceRoot":"","sources":["../../src/shared/response-helpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAEvE;;GAEG;AACH,wBAAgB,IAAI,CAClB,IAAI,EAAE,GAAG,EACT,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAO,GAClE,aAAa,CASf;AAED;;GAEG;AACH,wBAAgB,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,aAAa,CAE7E;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,aAAa,CAElF;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,aAAa,CAMzE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,GAAE,GAA8B,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,aAAa,CAEhH;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,GAAE,GAA+B,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,aAAa,CAEnH;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,GAAE,GAA4B,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,aAAa,CAE7G;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,GAAE,GAA4B,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,aAAa,CAE5G;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,GAAE,GAA2B,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,aAAa,CAE3G;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,GAAE,GAAmC,EACzC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,aAAa,CAEf;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,IAAI,GAAE,GAAoC,EAC1C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,aAAa,CAEf;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,GAAE,GAAwC,EAC9C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,aAAa,CAEf;AAED;;GAEG;AACH,wBAAgB,QAAQ,CACtB,GAAG,EAAE,MAAM,EACX,SAAS,GAAE,OAAe,EAC1B,cAAc,GAAE,OAAe,GAC9B,aAAa,CASf"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response helper functions for route handlers
|
|
3
|
+
* Provides convenient functions to create HTTP responses with status codes and headers
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Creates a JSON response with status code and optional headers
|
|
7
|
+
*/
|
|
8
|
+
export function json(body, options = {}) {
|
|
9
|
+
return {
|
|
10
|
+
status: options.status || 200,
|
|
11
|
+
headers: {
|
|
12
|
+
'Content-Type': 'application/json',
|
|
13
|
+
...options.headers,
|
|
14
|
+
},
|
|
15
|
+
body,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Creates a 200 OK response
|
|
20
|
+
*/
|
|
21
|
+
export function ok(body, headers) {
|
|
22
|
+
return json(body, { status: 200, headers });
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Creates a 201 Created response
|
|
26
|
+
*/
|
|
27
|
+
export function created(body, headers) {
|
|
28
|
+
return json(body, { status: 201, headers });
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Creates a 204 No Content response
|
|
32
|
+
*/
|
|
33
|
+
export function noContent(headers) {
|
|
34
|
+
return {
|
|
35
|
+
status: 204,
|
|
36
|
+
headers: headers || {},
|
|
37
|
+
body: undefined,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Creates a 400 Bad Request response
|
|
42
|
+
*/
|
|
43
|
+
export function badRequest(body = { error: 'Bad request' }, headers) {
|
|
44
|
+
return json(body, { status: 400, headers });
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Creates a 401 Unauthorized response
|
|
48
|
+
*/
|
|
49
|
+
export function unauthorized(body = { error: 'Unauthorized' }, headers) {
|
|
50
|
+
return json(body, { status: 401, headers });
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Creates a 403 Forbidden response
|
|
54
|
+
*/
|
|
55
|
+
export function forbidden(body = { error: 'Forbidden' }, headers) {
|
|
56
|
+
return json(body, { status: 403, headers });
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Creates a 404 Not Found response
|
|
60
|
+
*/
|
|
61
|
+
export function notFound(body = { error: 'Not found' }, headers) {
|
|
62
|
+
return json(body, { status: 404, headers });
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Creates a 409 Conflict response
|
|
66
|
+
*/
|
|
67
|
+
export function conflict(body = { error: 'Conflict' }, headers) {
|
|
68
|
+
return json(body, { status: 409, headers });
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Creates a 422 Unprocessable Entity response (validation errors)
|
|
72
|
+
*/
|
|
73
|
+
export function unprocessableEntity(body = { error: 'Validation error' }, headers) {
|
|
74
|
+
return json(body, { status: 422, headers });
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Creates a 429 Too Many Requests response
|
|
78
|
+
*/
|
|
79
|
+
export function tooManyRequests(body = { error: 'Too many requests' }, headers) {
|
|
80
|
+
return json(body, { status: 429, headers });
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Creates a 500 Internal Server Error response
|
|
84
|
+
*/
|
|
85
|
+
export function internalServerError(body = { error: 'Internal server error' }, headers) {
|
|
86
|
+
return json(body, { status: 500, headers });
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Creates a redirect response (301, 302, 307, 308)
|
|
90
|
+
*/
|
|
91
|
+
export function redirect(url, permanent = false, preserveMethod = false) {
|
|
92
|
+
const status = permanent ? (preserveMethod ? 308 : 301) : preserveMethod ? 307 : 302;
|
|
93
|
+
return {
|
|
94
|
+
status,
|
|
95
|
+
headers: {
|
|
96
|
+
Location: url,
|
|
97
|
+
},
|
|
98
|
+
body: undefined,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utilities
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Normalizes a path by removing double slashes and ensuring consistent format
|
|
6
|
+
* Preserves the leading slash if present
|
|
7
|
+
*/
|
|
8
|
+
export declare function normalizePath(path: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Checks if a string is a valid HTTP method
|
|
11
|
+
*/
|
|
12
|
+
export declare function isHttpMethod(str: string): str is 'get' | 'post' | 'put' | 'patch' | 'delete' | 'head' | 'options';
|
|
13
|
+
/**
|
|
14
|
+
* Capitalizes the first letter of a string
|
|
15
|
+
*/
|
|
16
|
+
export declare function capitalize(str: string): string;
|
|
17
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/shared/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOlD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,IAAI,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAEjH;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE9C"}
|