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.
Files changed (72) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +908 -0
  3. package/dist/adapters/vite/dev-server.d.ts +23 -0
  4. package/dist/adapters/vite/dev-server.d.ts.map +1 -0
  5. package/dist/adapters/vite/dev-server.js +428 -0
  6. package/dist/adapters/vite/logger.d.ts +33 -0
  7. package/dist/adapters/vite/logger.d.ts.map +1 -0
  8. package/dist/adapters/vite/logger.js +112 -0
  9. package/dist/core/context/create-context.d.ts +39 -0
  10. package/dist/core/context/create-context.d.ts.map +1 -0
  11. package/dist/core/context/create-context.js +34 -0
  12. package/dist/core/file-system/scan-api-dir.d.ts +26 -0
  13. package/dist/core/file-system/scan-api-dir.d.ts.map +1 -0
  14. package/dist/core/file-system/scan-api-dir.js +83 -0
  15. package/dist/core/file-system/watch-api-dir.d.ts +18 -0
  16. package/dist/core/file-system/watch-api-dir.d.ts.map +1 -0
  17. package/dist/core/file-system/watch-api-dir.js +40 -0
  18. package/dist/core/middleware/compose.d.ts +12 -0
  19. package/dist/core/middleware/compose.d.ts.map +1 -0
  20. package/dist/core/middleware/compose.js +27 -0
  21. package/dist/core/middleware/get-applicable-middlewares.d.ts +17 -0
  22. package/dist/core/middleware/get-applicable-middlewares.d.ts.map +1 -0
  23. package/dist/core/middleware/get-applicable-middlewares.js +47 -0
  24. package/dist/core/middleware/load-global.d.ts +13 -0
  25. package/dist/core/middleware/load-global.d.ts.map +1 -0
  26. package/dist/core/middleware/load-global.js +37 -0
  27. package/dist/core/normalize/normalize-path.d.ts +25 -0
  28. package/dist/core/normalize/normalize-path.d.ts.map +1 -0
  29. package/dist/core/normalize/normalize-path.js +76 -0
  30. package/dist/core/routing/route-matcher.d.ts +10 -0
  31. package/dist/core/routing/route-matcher.d.ts.map +1 -0
  32. package/dist/core/routing/route-matcher.js +32 -0
  33. package/dist/core/routing/route-parser.d.ts +28 -0
  34. package/dist/core/routing/route-parser.d.ts.map +1 -0
  35. package/dist/core/routing/route-parser.js +52 -0
  36. package/dist/core/routing/route-types.d.ts +43 -0
  37. package/dist/core/routing/route-types.d.ts.map +1 -0
  38. package/dist/core/routing/route-types.js +5 -0
  39. package/dist/core/types/extract-ast.d.ts +18 -0
  40. package/dist/core/types/extract-ast.d.ts.map +1 -0
  41. package/dist/core/types/extract-ast.js +26 -0
  42. package/dist/core/types/generate.d.ts +22 -0
  43. package/dist/core/types/generate.d.ts.map +1 -0
  44. package/dist/core/types/generate.js +576 -0
  45. package/dist/core/types/schema.d.ts +21 -0
  46. package/dist/core/types/schema.d.ts.map +1 -0
  47. package/dist/core/types/schema.js +17 -0
  48. package/dist/core/validation/types.d.ts +27 -0
  49. package/dist/core/validation/types.d.ts.map +1 -0
  50. package/dist/core/validation/types.js +5 -0
  51. package/dist/core/validation/validator.d.ts +22 -0
  52. package/dist/core/validation/validator.d.ts.map +1 -0
  53. package/dist/core/validation/validator.js +131 -0
  54. package/dist/index.d.ts +8 -0
  55. package/dist/index.d.ts.map +1 -0
  56. package/dist/index.js +4 -0
  57. package/dist/plugin.d.ts +27 -0
  58. package/dist/plugin.d.ts.map +1 -0
  59. package/dist/plugin.js +54 -0
  60. package/dist/shared/constants.d.ts +13 -0
  61. package/dist/shared/constants.d.ts.map +1 -0
  62. package/dist/shared/constants.js +12 -0
  63. package/dist/shared/errors.d.ts +75 -0
  64. package/dist/shared/errors.d.ts.map +1 -0
  65. package/dist/shared/errors.js +118 -0
  66. package/dist/shared/response-helpers.d.ts +61 -0
  67. package/dist/shared/response-helpers.d.ts.map +1 -0
  68. package/dist/shared/response-helpers.js +100 -0
  69. package/dist/shared/utils.d.ts +17 -0
  70. package/dist/shared/utils.d.ts.map +1 -0
  71. package/dist/shared/utils.js +27 -0
  72. 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
+ }
@@ -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
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Export público do pacote Vitek
3
+ */
4
+ export { vitek } from './plugin.js';
@@ -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"}