@gennext/lb-infra 0.1.0 → 0.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 CHANGED
@@ -95,12 +95,6 @@ await executePromiseWithLimit({
95
95
  - `src/helpers`: Các module bổ trợ quan trọng (Logger, Redis).
96
96
  - `src/utilities`: Các hàm tiện ích dùng chung.
97
97
 
98
- ## 📖 Tài liệu chi tiết
99
-
100
- - [Tài liệu cấu hình Logger](docs/ENHANCED_LOGGER_USAGE.md)
101
- - [Hướng dẫn cấu hình chung](docs/CONFIG_USAGE.md)
102
- - [Chi tiết hệ thống xử lý lỗi](docs/ERROR_HANDLING.md)
103
-
104
98
  ## 🛠️ Scripts hỗ trợ (Maintainer)
105
99
 
106
100
  - `bun run build`: Biên dịch mã nguồn sang thư mục `dist`.
package/dist/index.d.ts CHANGED
@@ -7,4 +7,5 @@ export * from './common';
7
7
  export * from './datasources';
8
8
  export * from './helpers';
9
9
  export * from './utilities';
10
+ export * from './validators';
10
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC"}
package/dist/index.js CHANGED
@@ -23,4 +23,5 @@ __exportStar(require("./common"), exports);
23
23
  __exportStar(require("./datasources"), exports);
24
24
  __exportStar(require("./helpers"), exports);
25
25
  __exportStar(require("./utilities"), exports);
26
+ __exportStar(require("./validators"), exports);
26
27
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA;;;GAGG;AACH,yCAAuB;AACvB,2CAAyB;AACzB,gDAA8B;AAC9B,4CAA0B;AAC1B,8CAA4B"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA;;;GAGG;AACH,yCAAuB;AACvB,2CAAyB;AACzB,gDAA8B;AAC9B,4CAA0B;AAC1B,8CAA4B;AAC5B,+CAA6B"}
@@ -0,0 +1,57 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Common validation patterns designed for reuse across the application.
4
+ * Build domain-specific schemas by composing these primitives.
5
+ */
6
+ export declare const BaseSchemas: {
7
+ /** Standard UUID v4 */
8
+ UUID: z.ZodString;
9
+ /** Flexible ID – accepts UUID string or positive integer */
10
+ ID: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
11
+ Email: z.ZodString;
12
+ Username: z.ZodString;
13
+ Password: z.ZodString;
14
+ PhoneNumber: z.ZodString;
15
+ URL: z.ZodString;
16
+ /** Non-empty, trimmed string */
17
+ NonEmptyString: z.ZodString;
18
+ /** Short description / label field */
19
+ Description: z.ZodOptional<z.ZodString>;
20
+ Port: z.ZodNumber;
21
+ PositiveInt: z.ZodNumber;
22
+ NonNegativeInt: z.ZodNumber;
23
+ SafeInt: z.ZodNumber;
24
+ /** ISO-8601 datetime string */
25
+ ISODate: z.ZodString;
26
+ UnixTimestamp: z.ZodNumber;
27
+ Tags: z.ZodDefault<z.ZodArray<z.ZodString>>;
28
+ Pagination: z.ZodObject<{
29
+ page: z.ZodDefault<z.ZodNumber>;
30
+ limit: z.ZodDefault<z.ZodNumber>;
31
+ offset: z.ZodOptional<z.ZodNumber>;
32
+ }, z.core.$strip>;
33
+ };
34
+ /**
35
+ * Wraps a shape in a standard auditable entity object.
36
+ *
37
+ * @example
38
+ * const UserSchema = createEntitySchema({ name: z.string() });
39
+ * type User = z.infer<typeof UserSchema>;
40
+ */
41
+ export declare const createEntitySchema: <T extends z.ZodRawShape>(shape: T) => z.ZodObject<{
42
+ id: z.ZodString;
43
+ createdAt: z.ZodDate;
44
+ updatedAt: z.ZodDate;
45
+ deletedAt: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
46
+ } & T extends infer T_1 ? { -readonly [P in keyof T_1]: T_1[P]; } : never, z.core.$strip>;
47
+ /**
48
+ * Wraps a shape using numeric primary-key convention (mirrors
49
+ * the {@link TBaseIdEntity} pattern used in lb-infra models).
50
+ */
51
+ export declare const createNumericEntitySchema: <T extends z.ZodRawShape>(shape: T) => z.ZodObject<{
52
+ id: z.ZodNumber;
53
+ createdAt: z.ZodDate;
54
+ updatedAt: z.ZodDate;
55
+ deletedAt: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
56
+ } & T extends infer T_1 ? { -readonly [P in keyof T_1]: T_1[P]; } : never, z.core.$strip>;
57
+ //# sourceMappingURL=base.schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.schema.d.ts","sourceRoot":"","sources":["../../src/validators/base.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;GAGG;AACH,eAAO,MAAM,WAAW;IAEtB,uBAAuB;;IAEvB,4DAA4D;;;;;;;IAkB5D,gCAAgC;;IAEhC,sCAAsC;;;;;;IAUtC,+BAA+B;;;;;;;;;CAkBhC,CAAC;AAIF;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,GAAI,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,OAAO,CAAC;;;;;yFAOhE,CAAC;AAEL;;;GAGG;AACH,eAAO,MAAM,yBAAyB,GAAI,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,OAAO,CAAC;;;;;yFAOvE,CAAC"}
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createNumericEntitySchema = exports.createEntitySchema = exports.BaseSchemas = void 0;
4
+ const zod_1 = require("zod");
5
+ /**
6
+ * Common validation patterns designed for reuse across the application.
7
+ * Build domain-specific schemas by composing these primitives.
8
+ */
9
+ exports.BaseSchemas = {
10
+ // ─── Identity ────────────────────────────────────────────────────────────
11
+ /** Standard UUID v4 */
12
+ UUID: zod_1.z.string().uuid('Invalid UUID format'),
13
+ /** Flexible ID – accepts UUID string or positive integer */
14
+ ID: zod_1.z.union([
15
+ zod_1.z.string().uuid('Invalid UUID format'),
16
+ zod_1.z.number().int().positive('ID must be a positive integer'),
17
+ ]),
18
+ // ─── Strings ─────────────────────────────────────────────────────────────
19
+ Email: zod_1.z.string().email('Invalid email format'),
20
+ Username: zod_1.z
21
+ .string()
22
+ .min(3, 'Username must be at least 3 characters')
23
+ .max(50, 'Username must be at most 50 characters'),
24
+ Password: zod_1.z
25
+ .string()
26
+ .min(8, 'Password must be at least 8 characters')
27
+ .max(128, 'Password must be at most 128 characters'),
28
+ PhoneNumber: zod_1.z.string().regex(/^\+?[\d\s\-()\\.]{7,}$/, 'Invalid phone number format'),
29
+ URL: zod_1.z.string().url('Invalid URL format'),
30
+ /** Non-empty, trimmed string */
31
+ NonEmptyString: zod_1.z.string().trim().min(1, 'Value must not be empty'),
32
+ /** Short description / label field */
33
+ Description: zod_1.z.string().max(500, 'Description must be at most 500 characters').optional(),
34
+ // ─── Numbers ─────────────────────────────────────────────────────────────
35
+ Port: zod_1.z.number().int().min(1, 'Port must be >= 1').max(65535, 'Port must be <= 65535'),
36
+ PositiveInt: zod_1.z.number().int().positive('Must be a positive integer'),
37
+ NonNegativeInt: zod_1.z.number().int().min(0, 'Must be >= 0'),
38
+ SafeInt: zod_1.z.number().int().safe(),
39
+ // ─── Dates ───────────────────────────────────────────────────────────────
40
+ /** ISO-8601 datetime string */
41
+ ISODate: zod_1.z.string().datetime({ message: 'Must be a valid ISO 8601 datetime string' }),
42
+ UnixTimestamp: zod_1.z.number().int().positive('Unix timestamp must be positive'),
43
+ // ─── Collections ─────────────────────────────────────────────────────────
44
+ Tags: zod_1.z.array(zod_1.z.string()).default([]),
45
+ // ─── Pagination ──────────────────────────────────────────────────────────
46
+ Pagination: zod_1.z.object({
47
+ page: zod_1.z.number().int().min(1, 'Page must be >= 1').default(1),
48
+ limit: zod_1.z
49
+ .number()
50
+ .int()
51
+ .min(1, 'Limit must be >= 1')
52
+ .max(1000, 'Limit must be <= 1000')
53
+ .default(20),
54
+ offset: zod_1.z.number().int().min(0).optional(),
55
+ }),
56
+ };
57
+ // ─── Entity Helpers ──────────────────────────────────────────────────────────
58
+ /**
59
+ * Wraps a shape in a standard auditable entity object.
60
+ *
61
+ * @example
62
+ * const UserSchema = createEntitySchema({ name: z.string() });
63
+ * type User = z.infer<typeof UserSchema>;
64
+ */
65
+ const createEntitySchema = (shape) => zod_1.z.object({
66
+ id: exports.BaseSchemas.UUID,
67
+ createdAt: zod_1.z.date(),
68
+ updatedAt: zod_1.z.date(),
69
+ deletedAt: zod_1.z.date().nullable().optional(),
70
+ ...shape,
71
+ });
72
+ exports.createEntitySchema = createEntitySchema;
73
+ /**
74
+ * Wraps a shape using numeric primary-key convention (mirrors
75
+ * the {@link TBaseIdEntity} pattern used in lb-infra models).
76
+ */
77
+ const createNumericEntitySchema = (shape) => zod_1.z.object({
78
+ id: exports.BaseSchemas.PositiveInt,
79
+ createdAt: zod_1.z.date(),
80
+ updatedAt: zod_1.z.date(),
81
+ deletedAt: zod_1.z.date().nullable().optional(),
82
+ ...shape,
83
+ });
84
+ exports.createNumericEntitySchema = createNumericEntitySchema;
85
+ //# sourceMappingURL=base.schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.schema.js","sourceRoot":"","sources":["../../src/validators/base.schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ import { z } from 'zod';
2
+ export declare const LoginSchema: z.ZodObject<{
3
+ email: z.ZodString;
4
+ password: z.ZodString;
5
+ rememberMe: z.ZodDefault<z.ZodBoolean>;
6
+ }, z.core.$strip>;
7
+ export type TLoginInput = z.infer<typeof LoginSchema>;
8
+ export declare const RegisterSchema: z.ZodObject<{
9
+ email: z.ZodString;
10
+ password: z.ZodString;
11
+ confirmPassword: z.ZodString;
12
+ firstName: z.ZodString;
13
+ lastName: z.ZodString;
14
+ }, z.core.$strip>;
15
+ export type TRegisterInput = z.infer<typeof RegisterSchema>;
16
+ export declare const ChangePasswordSchema: z.ZodObject<{
17
+ currentPassword: z.ZodString;
18
+ newPassword: z.ZodString;
19
+ confirmPassword: z.ZodString;
20
+ }, z.core.$strip>;
21
+ export type TChangePasswordInput = z.infer<typeof ChangePasswordSchema>;
22
+ export declare const UserEntitySchema: z.ZodObject<{
23
+ id: z.ZodString;
24
+ createdAt: z.ZodDate;
25
+ updatedAt: z.ZodDate;
26
+ deletedAt: z.ZodOptional<z.ZodNullable<z.ZodDate>>;
27
+ email: z.ZodString;
28
+ firstName: z.ZodString;
29
+ lastName: z.ZodString;
30
+ phone: z.ZodOptional<z.ZodString>;
31
+ isActive: z.ZodDefault<z.ZodBoolean>;
32
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
33
+ }, z.core.$strip>;
34
+ export type TUserEntity = z.infer<typeof UserEntitySchema>;
35
+ /** Partial update – id, createdAt, deletedAt are immutable */
36
+ export declare const UpdateUserSchema: z.ZodObject<{
37
+ email: z.ZodOptional<z.ZodString>;
38
+ updatedAt: z.ZodOptional<z.ZodDate>;
39
+ firstName: z.ZodOptional<z.ZodString>;
40
+ lastName: z.ZodOptional<z.ZodString>;
41
+ phone: z.ZodOptional<z.ZodOptional<z.ZodString>>;
42
+ isActive: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
43
+ metadata: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
44
+ }, z.core.$strip>;
45
+ export type TUpdateUserInput = z.infer<typeof UpdateUserSchema>;
46
+ export declare const ListQuerySchema: z.ZodObject<{
47
+ sortBy: z.ZodOptional<z.ZodString>;
48
+ sortOrder: z.ZodDefault<z.ZodEnum<{
49
+ desc: "desc";
50
+ asc: "asc";
51
+ }>>;
52
+ search: z.ZodOptional<z.ZodString>;
53
+ page: z.ZodDefault<z.ZodNumber>;
54
+ limit: z.ZodDefault<z.ZodNumber>;
55
+ offset: z.ZodOptional<z.ZodNumber>;
56
+ }, z.core.$strip>;
57
+ export type TListQuery = z.infer<typeof ListQuerySchema>;
58
+ /**
59
+ * Wraps any Zod schema in the standard API response envelope.
60
+ *
61
+ * @example
62
+ * const UserResponseSchema = ApiResponseSchema(UserEntitySchema);
63
+ */
64
+ export declare const ApiResponseSchema: <T extends z.ZodTypeAny>(dataSchema: T) => z.ZodObject<{
65
+ success: z.ZodBoolean;
66
+ code: z.ZodString;
67
+ message: z.ZodString;
68
+ data: z.ZodOptional<T>;
69
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
70
+ }, z.core.$strip>;
71
+ export declare const PaginatedResponseSchema: <T extends z.ZodTypeAny>(itemSchema: T) => z.ZodObject<{
72
+ items: z.ZodArray<T>;
73
+ total: z.ZodNumber;
74
+ page: z.ZodNumber;
75
+ limit: z.ZodNumber;
76
+ hasMore: z.ZodBoolean;
77
+ }, z.core.$strip>;
78
+ export declare const DatabaseConfigSchema: z.ZodObject<{
79
+ host: z.ZodString;
80
+ port: z.ZodDefault<z.ZodNumber>;
81
+ database: z.ZodString;
82
+ username: z.ZodString;
83
+ password: z.ZodString;
84
+ ssl: z.ZodDefault<z.ZodBoolean>;
85
+ }, z.core.$strip>;
86
+ export type TDatabaseConfig = z.infer<typeof DatabaseConfigSchema>;
87
+ export declare const RedisConfigSchema: z.ZodObject<{
88
+ host: z.ZodString;
89
+ port: z.ZodDefault<z.ZodNumber>;
90
+ password: z.ZodOptional<z.ZodString>;
91
+ db: z.ZodDefault<z.ZodNumber>;
92
+ }, z.core.$strip>;
93
+ export type TRedisConfig = z.infer<typeof RedisConfigSchema>;
94
+ //# sourceMappingURL=common.schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common.schema.d.ts","sourceRoot":"","sources":["../../src/validators/common.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,WAAW;;;;iBAItB,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEtD,eAAO,MAAM,cAAc;;;;;;iBAWvB,CAAC;AACL,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAE5D,eAAO,MAAM,oBAAoB;;;;iBAa7B,CAAC;AACL,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAIxE,eAAO,MAAM,gBAAgB;;;;;;;;;;;iBAO3B,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE3D,8DAA8D;AAC9D,eAAO,MAAM,gBAAgB;;;;;;;;iBAI3B,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAIhE,eAAO,MAAM,eAAe;;;;;;;;;;iBAK1B,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAIzD;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAAI,CAAC,SAAS,CAAC,CAAC,UAAU,EAAE,YAAY,CAAC;;;;;;iBAOnE,CAAC;AAEL,eAAO,MAAM,uBAAuB,GAAI,CAAC,SAAS,CAAC,CAAC,UAAU,EAAE,YAAY,CAAC;;;;;;iBAOzE,CAAC;AAIL,eAAO,MAAM,oBAAoB;;;;;;;iBAO/B,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAEnE,eAAO,MAAM,iBAAiB;;;;;iBAK5B,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC"}
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RedisConfigSchema = exports.DatabaseConfigSchema = exports.PaginatedResponseSchema = exports.ApiResponseSchema = exports.ListQuerySchema = exports.UpdateUserSchema = exports.UserEntitySchema = exports.ChangePasswordSchema = exports.RegisterSchema = exports.LoginSchema = void 0;
4
+ const zod_1 = require("zod");
5
+ const base_schema_1 = require("./base.schema");
6
+ // ─── Auth ────────────────────────────────────────────────────────────────────
7
+ exports.LoginSchema = zod_1.z.object({
8
+ email: base_schema_1.BaseSchemas.Email,
9
+ password: zod_1.z.string().min(1, 'Password is required'),
10
+ rememberMe: zod_1.z.boolean().default(false),
11
+ });
12
+ exports.RegisterSchema = zod_1.z
13
+ .object({
14
+ email: base_schema_1.BaseSchemas.Email,
15
+ password: base_schema_1.BaseSchemas.Password,
16
+ confirmPassword: zod_1.z.string(),
17
+ firstName: base_schema_1.BaseSchemas.NonEmptyString,
18
+ lastName: base_schema_1.BaseSchemas.NonEmptyString,
19
+ })
20
+ .refine(data => data.password === data.confirmPassword, {
21
+ message: 'Passwords do not match',
22
+ path: ['confirmPassword'],
23
+ });
24
+ exports.ChangePasswordSchema = zod_1.z
25
+ .object({
26
+ currentPassword: zod_1.z.string().min(1, 'Current password is required'),
27
+ newPassword: base_schema_1.BaseSchemas.Password,
28
+ confirmPassword: zod_1.z.string(),
29
+ })
30
+ .refine(data => data.newPassword !== data.currentPassword, {
31
+ message: 'New password must differ from current password',
32
+ path: ['newPassword'],
33
+ })
34
+ .refine(data => data.newPassword === data.confirmPassword, {
35
+ message: 'Passwords do not match',
36
+ path: ['confirmPassword'],
37
+ });
38
+ // ─── User ────────────────────────────────────────────────────────────────────
39
+ exports.UserEntitySchema = (0, base_schema_1.createEntitySchema)({
40
+ email: base_schema_1.BaseSchemas.Email,
41
+ firstName: zod_1.z.string(),
42
+ lastName: zod_1.z.string(),
43
+ phone: base_schema_1.BaseSchemas.PhoneNumber.optional(),
44
+ isActive: zod_1.z.boolean().default(true),
45
+ metadata: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()).optional(),
46
+ });
47
+ /** Partial update – id, createdAt, deletedAt are immutable */
48
+ exports.UpdateUserSchema = exports.UserEntitySchema.partial().omit({
49
+ id: true,
50
+ createdAt: true,
51
+ deletedAt: true,
52
+ });
53
+ // ─── Pagination & Query ──────────────────────────────────────────────────────
54
+ exports.ListQuerySchema = zod_1.z.object({
55
+ ...base_schema_1.BaseSchemas.Pagination.shape,
56
+ sortBy: zod_1.z.string().optional(),
57
+ sortOrder: zod_1.z.enum(['asc', 'desc']).default('asc'),
58
+ search: zod_1.z.string().optional(),
59
+ });
60
+ // ─── Generic API Response Wrappers ───────────────────────────────────────────
61
+ /**
62
+ * Wraps any Zod schema in the standard API response envelope.
63
+ *
64
+ * @example
65
+ * const UserResponseSchema = ApiResponseSchema(UserEntitySchema);
66
+ */
67
+ const ApiResponseSchema = (dataSchema) => zod_1.z.object({
68
+ success: zod_1.z.boolean(),
69
+ code: zod_1.z.string(),
70
+ message: zod_1.z.string(),
71
+ data: dataSchema.optional(),
72
+ metadata: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()).optional(),
73
+ });
74
+ exports.ApiResponseSchema = ApiResponseSchema;
75
+ const PaginatedResponseSchema = (itemSchema) => zod_1.z.object({
76
+ items: zod_1.z.array(itemSchema),
77
+ total: zod_1.z.number().int().min(0),
78
+ page: zod_1.z.number().int().min(1),
79
+ limit: zod_1.z.number().int().min(1),
80
+ hasMore: zod_1.z.boolean(),
81
+ });
82
+ exports.PaginatedResponseSchema = PaginatedResponseSchema;
83
+ // ─── Environment / Config ────────────────────────────────────────────────────
84
+ exports.DatabaseConfigSchema = zod_1.z.object({
85
+ host: zod_1.z.string().min(1, 'DB host is required'),
86
+ port: base_schema_1.BaseSchemas.Port.default(5432),
87
+ database: zod_1.z.string().min(1, 'DB name is required'),
88
+ username: zod_1.z.string().min(1, 'DB username is required'),
89
+ password: zod_1.z.string().min(1, 'DB password is required'),
90
+ ssl: zod_1.z.boolean().default(false),
91
+ });
92
+ exports.RedisConfigSchema = zod_1.z.object({
93
+ host: zod_1.z.string().min(1, 'Redis host is required'),
94
+ port: base_schema_1.BaseSchemas.Port.default(6379),
95
+ password: zod_1.z.string().optional(),
96
+ db: zod_1.z.number().int().min(0).default(0),
97
+ });
98
+ //# sourceMappingURL=common.schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common.schema.js","sourceRoot":"","sources":["../../src/validators/common.schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @module validators
3
+ *
4
+ * Zod-based validation layer for @gennext/lb-infra.
5
+ *
6
+ * @example
7
+ * import { safeParse, LoginSchema, BaseSchemas } from '@gennext/lb-infra/validators';
8
+ *
9
+ * const loginData = safeParse(LoginSchema, req.body, 'Login');
10
+ */
11
+ export { BaseSchemas, createEntitySchema, createNumericEntitySchema } from './base.schema';
12
+ export { LoginSchema, RegisterSchema, ChangePasswordSchema, UserEntitySchema, UpdateUserSchema, ListQuerySchema, ApiResponseSchema, PaginatedResponseSchema, DatabaseConfigSchema, RedisConfigSchema, } from './common.schema';
13
+ export type { TLoginInput, TRegisterInput, TChangePasswordInput, TUserEntity, TUpdateUserInput, TListQuery, TDatabaseConfig, TRedisConfig, } from './common.schema';
14
+ export { TInfer, zodToValidationError, safeParse, safeParseAsync, validate, createValidationMiddleware, } from './with-zod';
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/validators/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAG3F,OAAO,EAEL,WAAW,EACX,cAAc,EACd,oBAAoB,EAEpB,gBAAgB,EAChB,gBAAgB,EAEhB,eAAe,EAEf,iBAAiB,EACjB,uBAAuB,EAEvB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EACV,WAAW,EACX,cAAc,EACd,oBAAoB,EACpB,WAAW,EACX,gBAAgB,EAChB,UAAU,EACV,eAAe,EACf,YAAY,GACb,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,MAAM,EACN,oBAAoB,EACpB,SAAS,EACT,cAAc,EACd,QAAQ,EACR,0BAA0B,GAC3B,MAAM,YAAY,CAAC"}
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ /**
3
+ * @module validators
4
+ *
5
+ * Zod-based validation layer for @gennext/lb-infra.
6
+ *
7
+ * @example
8
+ * import { safeParse, LoginSchema, BaseSchemas } from '@gennext/lb-infra/validators';
9
+ *
10
+ * const loginData = safeParse(LoginSchema, req.body, 'Login');
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.createValidationMiddleware = exports.validate = exports.safeParseAsync = exports.safeParse = exports.zodToValidationError = exports.RedisConfigSchema = exports.DatabaseConfigSchema = exports.PaginatedResponseSchema = exports.ApiResponseSchema = exports.ListQuerySchema = exports.UpdateUserSchema = exports.UserEntitySchema = exports.ChangePasswordSchema = exports.RegisterSchema = exports.LoginSchema = exports.createNumericEntitySchema = exports.createEntitySchema = exports.BaseSchemas = void 0;
14
+ // Base schemas & entity builders
15
+ var base_schema_1 = require("./base.schema");
16
+ Object.defineProperty(exports, "BaseSchemas", { enumerable: true, get: function () { return base_schema_1.BaseSchemas; } });
17
+ Object.defineProperty(exports, "createEntitySchema", { enumerable: true, get: function () { return base_schema_1.createEntitySchema; } });
18
+ Object.defineProperty(exports, "createNumericEntitySchema", { enumerable: true, get: function () { return base_schema_1.createNumericEntitySchema; } });
19
+ // Application-level schemas
20
+ var common_schema_1 = require("./common.schema");
21
+ // Auth
22
+ Object.defineProperty(exports, "LoginSchema", { enumerable: true, get: function () { return common_schema_1.LoginSchema; } });
23
+ Object.defineProperty(exports, "RegisterSchema", { enumerable: true, get: function () { return common_schema_1.RegisterSchema; } });
24
+ Object.defineProperty(exports, "ChangePasswordSchema", { enumerable: true, get: function () { return common_schema_1.ChangePasswordSchema; } });
25
+ // User
26
+ Object.defineProperty(exports, "UserEntitySchema", { enumerable: true, get: function () { return common_schema_1.UserEntitySchema; } });
27
+ Object.defineProperty(exports, "UpdateUserSchema", { enumerable: true, get: function () { return common_schema_1.UpdateUserSchema; } });
28
+ // Query & Pagination
29
+ Object.defineProperty(exports, "ListQuerySchema", { enumerable: true, get: function () { return common_schema_1.ListQuerySchema; } });
30
+ // Response wrappers
31
+ Object.defineProperty(exports, "ApiResponseSchema", { enumerable: true, get: function () { return common_schema_1.ApiResponseSchema; } });
32
+ Object.defineProperty(exports, "PaginatedResponseSchema", { enumerable: true, get: function () { return common_schema_1.PaginatedResponseSchema; } });
33
+ // Config
34
+ Object.defineProperty(exports, "DatabaseConfigSchema", { enumerable: true, get: function () { return common_schema_1.DatabaseConfigSchema; } });
35
+ Object.defineProperty(exports, "RedisConfigSchema", { enumerable: true, get: function () { return common_schema_1.RedisConfigSchema; } });
36
+ // Zod integration utilities
37
+ var with_zod_1 = require("./with-zod");
38
+ Object.defineProperty(exports, "zodToValidationError", { enumerable: true, get: function () { return with_zod_1.zodToValidationError; } });
39
+ Object.defineProperty(exports, "safeParse", { enumerable: true, get: function () { return with_zod_1.safeParse; } });
40
+ Object.defineProperty(exports, "safeParseAsync", { enumerable: true, get: function () { return with_zod_1.safeParseAsync; } });
41
+ Object.defineProperty(exports, "validate", { enumerable: true, get: function () { return with_zod_1.validate; } });
42
+ Object.defineProperty(exports, "createValidationMiddleware", { enumerable: true, get: function () { return with_zod_1.createValidationMiddleware; } });
43
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/validators/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;AAEH,iCAAiC;AACjC,6CAA2F;AAAlF,0GAAA,WAAW,OAAA;AAAE,iHAAA,kBAAkB,OAAA;AAAE,wHAAA,yBAAyB,OAAA;AAEnE,4BAA4B;AAC5B,iDAgByB;AAfvB,OAAO;AACP,4GAAA,WAAW,OAAA;AACX,+GAAA,cAAc,OAAA;AACd,qHAAA,oBAAoB,OAAA;AACpB,OAAO;AACP,iHAAA,gBAAgB,OAAA;AAChB,iHAAA,gBAAgB,OAAA;AAChB,qBAAqB;AACrB,gHAAA,eAAe,OAAA;AACf,oBAAoB;AACpB,kHAAA,iBAAiB,OAAA;AACjB,wHAAA,uBAAuB,OAAA;AACvB,SAAS;AACT,qHAAA,oBAAoB,OAAA;AACpB,kHAAA,iBAAiB,OAAA;AAcnB,4BAA4B;AAC5B,uCAOoB;AALlB,gHAAA,oBAAoB,OAAA;AACpB,qGAAA,SAAS,OAAA;AACT,0GAAA,cAAc,OAAA;AACd,oGAAA,QAAQ,OAAA;AACR,sHAAA,0BAA0B,OAAA"}
@@ -0,0 +1,66 @@
1
+ import { z } from 'zod';
2
+ import { ValidationError } from '../utilities/error.utility';
3
+ /** Shorthand for `z.infer<typeof schema>` */
4
+ export type TInfer<T extends z.ZodTypeAny> = z.infer<T>;
5
+ /**
6
+ * Flatten a {@link z.ZodError} into a field-keyed record and wrap it
7
+ * in the project's {@link ValidationError}.
8
+ *
9
+ * @param error - The raw Zod validation error
10
+ * @param context - Optional human-readable context label (e.g. "Login validation")
11
+ *
12
+ * @example
13
+ * try {
14
+ * LoginSchema.parse(body);
15
+ * } catch (err) {
16
+ * if (err instanceof z.ZodError) {
17
+ * throw zodToValidationError(err, 'Login');
18
+ * }
19
+ * }
20
+ */
21
+ export declare function zodToValidationError(error: z.ZodError, context?: string): ValidationError;
22
+ /**
23
+ * Parse `data` against `schema`, converting any ZodError into a
24
+ * {@link ValidationError} automatically.
25
+ *
26
+ * @throws {@link ValidationError} when validation fails
27
+ *
28
+ * @example
29
+ * const loginInput = safeParse(LoginSchema, req.body, 'Login');
30
+ */
31
+ export declare function safeParse<T>(schema: z.ZodSchema<T>, data: unknown, context?: string): T;
32
+ /**
33
+ * Async variant of {@link safeParse} – necessary when the schema uses
34
+ * `.refine()` with an async callback.
35
+ *
36
+ * @throws {@link ValidationError} when validation fails
37
+ */
38
+ export declare function safeParseAsync<T>(schema: z.ZodSchema<T>, data: unknown, context?: string): Promise<T>;
39
+ /**
40
+ * Method decorator that validates the **first argument** of the decorated
41
+ * method against `schema` before the original method body executes.
42
+ *
43
+ * @example
44
+ * class UserService {
45
+ * \@validate(LoginSchema)
46
+ * async login(data: LoginInput) { ... }
47
+ * }
48
+ */
49
+ export declare function validate<T>(schema: z.ZodSchema<T>, context?: string): (_target: object, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
50
+ /**
51
+ * Builds an Express-compatible middleware that validates `req.body` against
52
+ * `schema`. On success, the parsed + transformed data is assigned to
53
+ * `req.validatedBody`. On failure, a `400` JSON response is returned.
54
+ *
55
+ * @example
56
+ * router.post('/login', createValidationMiddleware(LoginSchema), loginHandler);
57
+ */
58
+ export declare function createValidationMiddleware<T>(schema: z.ZodSchema<T>, context?: string): (req: {
59
+ body: unknown;
60
+ validatedBody?: T;
61
+ }, res: {
62
+ status: (c: number) => {
63
+ json: (b: unknown) => void;
64
+ };
65
+ }, next: (err?: unknown) => void) => void;
66
+ //# sourceMappingURL=with-zod.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"with-zod.d.ts","sourceRoot":"","sources":["../../src/validators/with-zod.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAI5D,6CAA6C;AAC7C,MAAM,MAAM,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAIxD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,eAAe,CAgBzF;AAID;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,CAAC,CAMvF;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,CAAC,EACpC,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EACtB,IAAI,EAAE,OAAO,EACb,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,CAAC,CAAC,CAMZ;AAID;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,IACjD,SAAS,MAAM,EAAE,aAAa,MAAM,EAAE,YAAY,kBAAkB,wBAUtF;AAID;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,IAElF,KAAK;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,CAAC,CAAA;CAAE,EACzC,KAAK;IAAE,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK;QAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;KAAE,CAAA;CAAE,EAC9D,MAAM,CAAC,GAAG,CAAC,EAAE,OAAO,KAAK,IAAI,UAiBhC"}
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.zodToValidationError = zodToValidationError;
4
+ exports.safeParse = safeParse;
5
+ exports.safeParseAsync = safeParseAsync;
6
+ exports.validate = validate;
7
+ exports.createValidationMiddleware = createValidationMiddleware;
8
+ const error_utility_1 = require("../utilities/error.utility");
9
+ // ─── Error Conversion ────────────────────────────────────────────────────────
10
+ /**
11
+ * Flatten a {@link z.ZodError} into a field-keyed record and wrap it
12
+ * in the project's {@link ValidationError}.
13
+ *
14
+ * @param error - The raw Zod validation error
15
+ * @param context - Optional human-readable context label (e.g. "Login validation")
16
+ *
17
+ * @example
18
+ * try {
19
+ * LoginSchema.parse(body);
20
+ * } catch (err) {
21
+ * if (err instanceof z.ZodError) {
22
+ * throw zodToValidationError(err, 'Login');
23
+ * }
24
+ * }
25
+ */
26
+ function zodToValidationError(error, context) {
27
+ const fieldErrors = {};
28
+ for (const issue of error.issues) {
29
+ const path = issue.path.join('.') || '_root';
30
+ const msg = issue.message;
31
+ const existing = fieldErrors[path];
32
+ if (existing !== undefined) {
33
+ fieldErrors[path] = Array.isArray(existing) ? [...existing, msg] : [existing, msg];
34
+ }
35
+ else {
36
+ fieldErrors[path] = msg;
37
+ }
38
+ }
39
+ return new error_utility_1.ValidationError(context ?? 'Validation failed', fieldErrors);
40
+ }
41
+ // ─── Safe Parse ──────────────────────────────────────────────────────────────
42
+ /**
43
+ * Parse `data` against `schema`, converting any ZodError into a
44
+ * {@link ValidationError} automatically.
45
+ *
46
+ * @throws {@link ValidationError} when validation fails
47
+ *
48
+ * @example
49
+ * const loginInput = safeParse(LoginSchema, req.body, 'Login');
50
+ */
51
+ function safeParse(schema, data, context) {
52
+ const result = schema.safeParse(data);
53
+ if (!result.success) {
54
+ throw zodToValidationError(result.error, context);
55
+ }
56
+ return result.data;
57
+ }
58
+ /**
59
+ * Async variant of {@link safeParse} – necessary when the schema uses
60
+ * `.refine()` with an async callback.
61
+ *
62
+ * @throws {@link ValidationError} when validation fails
63
+ */
64
+ async function safeParseAsync(schema, data, context) {
65
+ const result = await schema.safeParseAsync(data);
66
+ if (!result.success) {
67
+ throw zodToValidationError(result.error, context);
68
+ }
69
+ return result.data;
70
+ }
71
+ // ─── Method Decorator ────────────────────────────────────────────────────────
72
+ /**
73
+ * Method decorator that validates the **first argument** of the decorated
74
+ * method against `schema` before the original method body executes.
75
+ *
76
+ * @example
77
+ * class UserService {
78
+ * \@validate(LoginSchema)
79
+ * async login(data: LoginInput) { ... }
80
+ * }
81
+ */
82
+ function validate(schema, context) {
83
+ return function (_target, propertyKey, descriptor) {
84
+ const originalMethod = descriptor.value;
85
+ descriptor.value = async function (data, ...rest) {
86
+ const validated = safeParse(schema, data, context ?? propertyKey);
87
+ return originalMethod.call(this, validated, ...rest);
88
+ };
89
+ return descriptor;
90
+ };
91
+ }
92
+ // ─── Express / LoopBack Middleware ───────────────────────────────────────────
93
+ /**
94
+ * Builds an Express-compatible middleware that validates `req.body` against
95
+ * `schema`. On success, the parsed + transformed data is assigned to
96
+ * `req.validatedBody`. On failure, a `400` JSON response is returned.
97
+ *
98
+ * @example
99
+ * router.post('/login', createValidationMiddleware(LoginSchema), loginHandler);
100
+ */
101
+ function createValidationMiddleware(schema, context) {
102
+ return (req, res, next) => {
103
+ const result = schema.safeParse(req.body);
104
+ if (!result.success) {
105
+ const validationError = zodToValidationError(result.error, context);
106
+ res.status(400).json({
107
+ code: 'VALIDATION_ERROR',
108
+ message: validationError.message,
109
+ details: validationError.context,
110
+ });
111
+ return;
112
+ }
113
+ req.validatedBody = result.data;
114
+ next();
115
+ };
116
+ }
117
+ //# sourceMappingURL=with-zod.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"with-zod.js","sourceRoot":"","sources":["../../src/validators/with-zod.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gennext/lb-infra",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "dependencies": {
5
5
  "@gennext/dev-configs": "^0.0.3",
6
6
  "@loopback/authentication": "^12.0.6",
@@ -25,7 +25,8 @@
25
25
  "uuid": "^13.0.0",
26
26
  "winston": "^3.19.0",
27
27
  "winston-daily-rotate-file": "^5.0.0",
28
- "winston-transport": "^4.9.0"
28
+ "winston-transport": "^4.9.0",
29
+ "zod": "^4.3.6"
29
30
  },
30
31
  "devDependencies": {
31
32
  "@gennext/eslint-node": "^0.0.2",