@carno.js/core 1.0.2 → 1.0.4

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 (37) hide show
  1. package/LICENSE +21 -674
  2. package/README.md +188 -188
  3. package/dist/bun/index.js +7 -20
  4. package/dist/bun/index.js.map +28 -28
  5. package/dist/context/Context.js +2 -1
  6. package/dist/context/Context.mjs +2 -1
  7. package/dist/utils/parseQuery.js +84 -0
  8. package/dist/utils/parseQuery.mjs +63 -0
  9. package/package.json +3 -2
  10. package/src/Carno.ts +605 -605
  11. package/src/DefaultRoutes.ts +34 -34
  12. package/src/cache/CacheDriver.ts +50 -50
  13. package/src/cache/CacheService.ts +139 -139
  14. package/src/cache/MemoryDriver.ts +104 -104
  15. package/src/cache/RedisDriver.ts +116 -116
  16. package/src/compiler/JITCompiler.ts +167 -167
  17. package/src/container/Container.ts +168 -168
  18. package/src/context/Context.ts +130 -128
  19. package/src/cors/CorsHandler.ts +145 -145
  20. package/src/decorators/Controller.ts +63 -63
  21. package/src/decorators/Inject.ts +16 -16
  22. package/src/decorators/Middleware.ts +22 -22
  23. package/src/decorators/Service.ts +18 -18
  24. package/src/decorators/methods.ts +58 -58
  25. package/src/decorators/params.ts +47 -47
  26. package/src/events/Lifecycle.ts +97 -97
  27. package/src/exceptions/HttpException.ts +99 -99
  28. package/src/index.ts +92 -92
  29. package/src/metadata.ts +46 -46
  30. package/src/middleware/CarnoMiddleware.ts +14 -14
  31. package/src/router/RadixRouter.ts +225 -225
  32. package/src/testing/TestHarness.ts +177 -177
  33. package/src/utils/Metadata.ts +43 -43
  34. package/src/utils/parseQuery.ts +161 -0
  35. package/src/validation/ValibotAdapter.ts +95 -95
  36. package/src/validation/ValidatorAdapter.ts +69 -69
  37. package/src/validation/ZodAdapter.ts +102 -102
@@ -1,95 +1,95 @@
1
- import type { ValidatorAdapter, ValidationResult, ValidationError } from './ValidatorAdapter';
2
- import { VALIDATION_SCHEMA, getSchema } from './ValidatorAdapter';
3
- import { ValidationException } from './ZodAdapter';
4
-
5
- /**
6
- * Valibot Adapter for Turbo validation.
7
- *
8
- * Usage:
9
- * ```typescript
10
- * import * as v from 'valibot';
11
- *
12
- * @Schema(v.object({
13
- * name: v.pipe(v.string(), v.minLength(1)),
14
- * email: v.pipe(v.string(), v.email())
15
- * }))
16
- * class CreateUserDto {
17
- * name: string;
18
- * email: string;
19
- * }
20
- * ```
21
- */
22
- export class ValibotAdapter implements ValidatorAdapter {
23
- readonly name = 'ValibotAdapter';
24
-
25
- private schemaCache = new Map<any, any>();
26
- private valibot: any = null;
27
-
28
- constructor() {
29
- // Lazy load valibot
30
- try {
31
- this.valibot = require('valibot');
32
- } catch {
33
- // Will be loaded on first use
34
- }
35
- }
36
-
37
- private ensureValibot(): any {
38
- if (!this.valibot) {
39
- this.valibot = require('valibot');
40
- }
41
- return this.valibot;
42
- }
43
-
44
- hasValidation(target: any): boolean {
45
- return getSchema(target) !== undefined;
46
- }
47
-
48
- validate<T>(target: any, value: unknown): ValidationResult<T> {
49
- const schema = this.getOrCacheSchema(target);
50
-
51
- if (!schema) {
52
- return { success: true, data: value as T };
53
- }
54
-
55
- const v = this.ensureValibot();
56
- const result = v.safeParse(schema, value);
57
-
58
- if (result.success) {
59
- return { success: true, data: result.output };
60
- }
61
-
62
- return {
63
- success: false,
64
- errors: this.formatErrors(result.issues)
65
- };
66
- }
67
-
68
- validateOrThrow<T>(target: any, value: unknown): T {
69
- const result = this.validate<T>(target, value);
70
-
71
- if (result.success) {
72
- return result.data!;
73
- }
74
-
75
- throw new ValidationException(result.errors!);
76
- }
77
-
78
- private getOrCacheSchema(target: any): any {
79
- let schema = this.schemaCache.get(target);
80
-
81
- if (schema === undefined) {
82
- schema = getSchema(target) ?? null;
83
- this.schemaCache.set(target, schema);
84
- }
85
-
86
- return schema;
87
- }
88
-
89
- private formatErrors(issues: any[]): ValidationError[] {
90
- return issues.map((issue: any) => ({
91
- path: issue.path?.map((p: any) => p.key).join('.') || '',
92
- message: issue.message
93
- }));
94
- }
95
- }
1
+ import type { ValidatorAdapter, ValidationResult, ValidationError } from './ValidatorAdapter';
2
+ import { VALIDATION_SCHEMA, getSchema } from './ValidatorAdapter';
3
+ import { ValidationException } from './ZodAdapter';
4
+
5
+ /**
6
+ * Valibot Adapter for Turbo validation.
7
+ *
8
+ * Usage:
9
+ * ```typescript
10
+ * import * as v from 'valibot';
11
+ *
12
+ * @Schema(v.object({
13
+ * name: v.pipe(v.string(), v.minLength(1)),
14
+ * email: v.pipe(v.string(), v.email())
15
+ * }))
16
+ * class CreateUserDto {
17
+ * name: string;
18
+ * email: string;
19
+ * }
20
+ * ```
21
+ */
22
+ export class ValibotAdapter implements ValidatorAdapter {
23
+ readonly name = 'ValibotAdapter';
24
+
25
+ private schemaCache = new Map<any, any>();
26
+ private valibot: any = null;
27
+
28
+ constructor() {
29
+ // Lazy load valibot
30
+ try {
31
+ this.valibot = require('valibot');
32
+ } catch {
33
+ // Will be loaded on first use
34
+ }
35
+ }
36
+
37
+ private ensureValibot(): any {
38
+ if (!this.valibot) {
39
+ this.valibot = require('valibot');
40
+ }
41
+ return this.valibot;
42
+ }
43
+
44
+ hasValidation(target: any): boolean {
45
+ return getSchema(target) !== undefined;
46
+ }
47
+
48
+ validate<T>(target: any, value: unknown): ValidationResult<T> {
49
+ const schema = this.getOrCacheSchema(target);
50
+
51
+ if (!schema) {
52
+ return { success: true, data: value as T };
53
+ }
54
+
55
+ const v = this.ensureValibot();
56
+ const result = v.safeParse(schema, value);
57
+
58
+ if (result.success) {
59
+ return { success: true, data: result.output };
60
+ }
61
+
62
+ return {
63
+ success: false,
64
+ errors: this.formatErrors(result.issues)
65
+ };
66
+ }
67
+
68
+ validateOrThrow<T>(target: any, value: unknown): T {
69
+ const result = this.validate<T>(target, value);
70
+
71
+ if (result.success) {
72
+ return result.data!;
73
+ }
74
+
75
+ throw new ValidationException(result.errors!);
76
+ }
77
+
78
+ private getOrCacheSchema(target: any): any {
79
+ let schema = this.schemaCache.get(target);
80
+
81
+ if (schema === undefined) {
82
+ schema = getSchema(target) ?? null;
83
+ this.schemaCache.set(target, schema);
84
+ }
85
+
86
+ return schema;
87
+ }
88
+
89
+ private formatErrors(issues: any[]): ValidationError[] {
90
+ return issues.map((issue: any) => ({
91
+ path: issue.path?.map((p: any) => p.key).join('.') || '',
92
+ message: issue.message
93
+ }));
94
+ }
95
+ }
@@ -1,69 +1,69 @@
1
- /**
2
- * Validation result type.
3
- */
4
- export interface ValidationResult<T = any> {
5
- success: boolean;
6
- data?: T;
7
- errors?: ValidationError[];
8
- }
9
-
10
- export interface ValidationError {
11
- path: string;
12
- message: string;
13
- }
14
-
15
- /**
16
- * Base interface for validation adapters.
17
- * Adapters provide validation capabilities for different libraries.
18
- */
19
- export interface ValidatorAdapter {
20
- /**
21
- * Validator name for debugging.
22
- */
23
- readonly name: string;
24
-
25
- /**
26
- * Check if a target has validation schema.
27
- */
28
- hasValidation(target: any): boolean;
29
-
30
- /**
31
- * Validate and transform a value.
32
- * Returns result object instead of throwing for better performance.
33
- */
34
- validate<T>(target: any, value: unknown): ValidationResult<T>;
35
-
36
- /**
37
- * Validate and transform, throwing on error.
38
- * Used when you want to short-circuit on failure.
39
- */
40
- validateOrThrow<T>(target: any, value: unknown): T;
41
- }
42
-
43
- /**
44
- * Validation configuration for Turbo.
45
- */
46
- export interface ValidationConfig {
47
- adapter: ValidatorAdapter;
48
- }
49
-
50
- /**
51
- * Symbol for storing validation schema on DTOs.
52
- */
53
- export const VALIDATION_SCHEMA = Symbol('turbo:validation');
54
-
55
- /**
56
- * Decorator to attach a validation schema to a DTO class.
57
- */
58
- export function Schema(schema: any): ClassDecorator {
59
- return (target) => {
60
- Reflect.defineMetadata(VALIDATION_SCHEMA, schema, target);
61
- };
62
- }
63
-
64
- /**
65
- * Get the validation schema from a DTO class.
66
- */
67
- export function getSchema(target: any): any | undefined {
68
- return Reflect.getMetadata(VALIDATION_SCHEMA, target);
69
- }
1
+ /**
2
+ * Validation result type.
3
+ */
4
+ export interface ValidationResult<T = any> {
5
+ success: boolean;
6
+ data?: T;
7
+ errors?: ValidationError[];
8
+ }
9
+
10
+ export interface ValidationError {
11
+ path: string;
12
+ message: string;
13
+ }
14
+
15
+ /**
16
+ * Base interface for validation adapters.
17
+ * Adapters provide validation capabilities for different libraries.
18
+ */
19
+ export interface ValidatorAdapter {
20
+ /**
21
+ * Validator name for debugging.
22
+ */
23
+ readonly name: string;
24
+
25
+ /**
26
+ * Check if a target has validation schema.
27
+ */
28
+ hasValidation(target: any): boolean;
29
+
30
+ /**
31
+ * Validate and transform a value.
32
+ * Returns result object instead of throwing for better performance.
33
+ */
34
+ validate<T>(target: any, value: unknown): ValidationResult<T>;
35
+
36
+ /**
37
+ * Validate and transform, throwing on error.
38
+ * Used when you want to short-circuit on failure.
39
+ */
40
+ validateOrThrow<T>(target: any, value: unknown): T;
41
+ }
42
+
43
+ /**
44
+ * Validation configuration for Turbo.
45
+ */
46
+ export interface ValidationConfig {
47
+ adapter: ValidatorAdapter;
48
+ }
49
+
50
+ /**
51
+ * Symbol for storing validation schema on DTOs.
52
+ */
53
+ export const VALIDATION_SCHEMA = Symbol('turbo:validation');
54
+
55
+ /**
56
+ * Decorator to attach a validation schema to a DTO class.
57
+ */
58
+ export function Schema(schema: any): ClassDecorator {
59
+ return (target) => {
60
+ Reflect.defineMetadata(VALIDATION_SCHEMA, schema, target);
61
+ };
62
+ }
63
+
64
+ /**
65
+ * Get the validation schema from a DTO class.
66
+ */
67
+ export function getSchema(target: any): any | undefined {
68
+ return Reflect.getMetadata(VALIDATION_SCHEMA, target);
69
+ }
@@ -1,102 +1,102 @@
1
- import type { ValidatorAdapter, ValidationResult, ValidationError } from './ValidatorAdapter';
2
- import { VALIDATION_SCHEMA, getSchema } from './ValidatorAdapter';
3
-
4
- /**
5
- * Zod Adapter - Default validation adapter for Turbo.
6
- *
7
- * Usage:
8
- * ```typescript
9
- * import { z } from 'zod';
10
- *
11
- * @Schema(z.object({
12
- * name: z.string().min(1),
13
- * email: z.string().email()
14
- * }))
15
- * class CreateUserDto {
16
- * name: string;
17
- * email: string;
18
- * }
19
- * ```
20
- */
21
- export class ZodAdapter implements ValidatorAdapter {
22
- readonly name = 'ZodAdapter';
23
-
24
- // Cache parsed schemas for performance
25
- private schemaCache = new Map<any, any>();
26
-
27
- hasValidation(target: any): boolean {
28
- return getSchema(target) !== undefined;
29
- }
30
-
31
- validate<T>(target: any, value: unknown): ValidationResult<T> {
32
- const schema = this.getOrCacheSchema(target);
33
-
34
- if (!schema) {
35
- return { success: true, data: value as T };
36
- }
37
-
38
- const result = schema.safeParse(value);
39
-
40
- if (result.success) {
41
- return { success: true, data: result.data };
42
- }
43
-
44
- return {
45
- success: false,
46
- errors: this.formatErrors(result.error)
47
- };
48
- }
49
-
50
- validateOrThrow<T>(target: any, value: unknown): T {
51
- const schema = this.getOrCacheSchema(target);
52
-
53
- if (!schema) {
54
- return value as T;
55
- }
56
-
57
- const result = schema.safeParse(value);
58
-
59
- if (result.success) {
60
- return result.data;
61
- }
62
-
63
- const errors = this.formatErrors(result.error);
64
- throw new ValidationException(errors);
65
- }
66
-
67
- private getOrCacheSchema(target: any): any {
68
- let schema = this.schemaCache.get(target);
69
-
70
- if (schema === undefined) {
71
- schema = getSchema(target) ?? null;
72
- this.schemaCache.set(target, schema);
73
- }
74
-
75
- return schema;
76
- }
77
-
78
- private formatErrors(zodError: any): ValidationError[] {
79
- return zodError.issues.map((issue: any) => ({
80
- path: issue.path.join('.'),
81
- message: issue.message
82
- }));
83
- }
84
- }
85
-
86
- /**
87
- * Validation exception thrown when validation fails.
88
- */
89
- export class ValidationException extends Error {
90
- constructor(public readonly errors: ValidationError[]) {
91
- super(`Validation failed: ${errors.map(e => `${e.path}: ${e.message}`).join(', ')}`);
92
- this.name = 'ValidationException';
93
- }
94
-
95
- toResponse(): Response {
96
- return Response.json({
97
- statusCode: 400,
98
- message: 'Validation failed',
99
- errors: this.errors
100
- }, { status: 400 });
101
- }
102
- }
1
+ import type { ValidatorAdapter, ValidationResult, ValidationError } from './ValidatorAdapter';
2
+ import { VALIDATION_SCHEMA, getSchema } from './ValidatorAdapter';
3
+
4
+ /**
5
+ * Zod Adapter - Default validation adapter for Turbo.
6
+ *
7
+ * Usage:
8
+ * ```typescript
9
+ * import { z } from 'zod';
10
+ *
11
+ * @Schema(z.object({
12
+ * name: z.string().min(1),
13
+ * email: z.string().email()
14
+ * }))
15
+ * class CreateUserDto {
16
+ * name: string;
17
+ * email: string;
18
+ * }
19
+ * ```
20
+ */
21
+ export class ZodAdapter implements ValidatorAdapter {
22
+ readonly name = 'ZodAdapter';
23
+
24
+ // Cache parsed schemas for performance
25
+ private schemaCache = new Map<any, any>();
26
+
27
+ hasValidation(target: any): boolean {
28
+ return getSchema(target) !== undefined;
29
+ }
30
+
31
+ validate<T>(target: any, value: unknown): ValidationResult<T> {
32
+ const schema = this.getOrCacheSchema(target);
33
+
34
+ if (!schema) {
35
+ return { success: true, data: value as T };
36
+ }
37
+
38
+ const result = schema.safeParse(value);
39
+
40
+ if (result.success) {
41
+ return { success: true, data: result.data };
42
+ }
43
+
44
+ return {
45
+ success: false,
46
+ errors: this.formatErrors(result.error)
47
+ };
48
+ }
49
+
50
+ validateOrThrow<T>(target: any, value: unknown): T {
51
+ const schema = this.getOrCacheSchema(target);
52
+
53
+ if (!schema) {
54
+ return value as T;
55
+ }
56
+
57
+ const result = schema.safeParse(value);
58
+
59
+ if (result.success) {
60
+ return result.data;
61
+ }
62
+
63
+ const errors = this.formatErrors(result.error);
64
+ throw new ValidationException(errors);
65
+ }
66
+
67
+ private getOrCacheSchema(target: any): any {
68
+ let schema = this.schemaCache.get(target);
69
+
70
+ if (schema === undefined) {
71
+ schema = getSchema(target) ?? null;
72
+ this.schemaCache.set(target, schema);
73
+ }
74
+
75
+ return schema;
76
+ }
77
+
78
+ private formatErrors(zodError: any): ValidationError[] {
79
+ return zodError.issues.map((issue: any) => ({
80
+ path: issue.path.join('.'),
81
+ message: issue.message
82
+ }));
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Validation exception thrown when validation fails.
88
+ */
89
+ export class ValidationException extends Error {
90
+ constructor(public readonly errors: ValidationError[]) {
91
+ super(`Validation failed: ${errors.map(e => `${e.path}: ${e.message}`).join(', ')}`);
92
+ this.name = 'ValidationException';
93
+ }
94
+
95
+ toResponse(): Response {
96
+ return Response.json({
97
+ statusCode: 400,
98
+ message: 'Validation failed',
99
+ errors: this.errors
100
+ }, { status: 400 });
101
+ }
102
+ }