@emkodev/emkore 1.0.3
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/CHANGELOG.md +269 -0
- package/DEVELOPER_GUIDE.md +227 -0
- package/LICENSE +21 -0
- package/README.md +126 -0
- package/bun.lock +22 -0
- package/example/README.md +200 -0
- package/example/create-user.interactor.ts +88 -0
- package/example/dto/user.dto.ts +34 -0
- package/example/entity/user.entity.ts +54 -0
- package/example/index.ts +18 -0
- package/example/interface/create-user.usecase.ts +93 -0
- package/example/interface/user.repository.ts +23 -0
- package/mod.ts +1 -0
- package/package.json +32 -0
- package/src/common/abstract.actor.ts +59 -0
- package/src/common/abstract.entity.ts +59 -0
- package/src/common/abstract.interceptor.ts +17 -0
- package/src/common/abstract.repository.ts +162 -0
- package/src/common/abstract.usecase.ts +113 -0
- package/src/common/config/config-registry.ts +190 -0
- package/src/common/config/config-section.ts +106 -0
- package/src/common/exception/authorization-exception.ts +28 -0
- package/src/common/exception/repository-exception.ts +46 -0
- package/src/common/interceptor/audit-log.interceptor.ts +181 -0
- package/src/common/interceptor/authorization.interceptor.ts +252 -0
- package/src/common/interceptor/performance.interceptor.ts +101 -0
- package/src/common/llm/api-definition.type.ts +185 -0
- package/src/common/pattern/unit-of-work.ts +78 -0
- package/src/common/platform/env.ts +38 -0
- package/src/common/registry/usecase-registry.ts +80 -0
- package/src/common/type/interceptor-context.type.ts +25 -0
- package/src/common/type/json-schema.type.ts +80 -0
- package/src/common/type/json.type.ts +5 -0
- package/src/common/type/lowercase.type.ts +48 -0
- package/src/common/type/metadata.type.ts +5 -0
- package/src/common/type/money.class.ts +384 -0
- package/src/common/type/permission.type.ts +43 -0
- package/src/common/validation/validation-result.ts +52 -0
- package/src/common/validation/validators.ts +441 -0
- package/src/index.ts +95 -0
- package/test/unit/abstract-actor.test.ts +608 -0
- package/test/unit/actor.test.ts +89 -0
- package/test/unit/api-definition.test.ts +628 -0
- package/test/unit/authorization.test.ts +101 -0
- package/test/unit/entity.test.ts +95 -0
- package/test/unit/money.test.ts +480 -0
- package/test/unit/validation.test.ts +138 -0
- package/tsconfig.json +18 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { test, expect } from "bun:test";
|
|
2
|
+
import { ValidationResult, ValidatorBuilder } from "../../mod.ts";
|
|
3
|
+
|
|
4
|
+
test("ValidationResult - success", () => {
|
|
5
|
+
const result = ValidationResult.success();
|
|
6
|
+
|
|
7
|
+
expect(result.isValid).toEqual(true);
|
|
8
|
+
expect(result.errors.length).toEqual(0);
|
|
9
|
+
expect(Object.keys(result.fieldErrors).length).toEqual(0);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test("ValidationResult - failure with errors", () => {
|
|
13
|
+
const result = ValidationResult.failure(["Error 1", "Error 2"]);
|
|
14
|
+
|
|
15
|
+
expect(result.isValid).toEqual(false);
|
|
16
|
+
expect(result.errors.length).toEqual(2);
|
|
17
|
+
expect(result.errors[0]).toEqual("Error 1");
|
|
18
|
+
expect(result.errors[1]).toEqual("Error 2");
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("ValidationResult - merge", () => {
|
|
22
|
+
const result1 = ValidationResult.failure(["Error 1"]);
|
|
23
|
+
const result2 = ValidationResult.failure(["Error 2"]);
|
|
24
|
+
|
|
25
|
+
const merged = result1.merge(result2);
|
|
26
|
+
|
|
27
|
+
expect(merged.isValid).toEqual(false);
|
|
28
|
+
expect(merged.errors.length).toEqual(2);
|
|
29
|
+
expect(merged.errors.includes("Error 1")).toEqual(true);
|
|
30
|
+
expect(merged.errors.includes("Error 2")).toEqual(true);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test("ValidatorBuilder - string validation", () => {
|
|
34
|
+
const builder = new ValidatorBuilder();
|
|
35
|
+
|
|
36
|
+
// Required string
|
|
37
|
+
const result1 = builder.string("name", "", { required: true }).build();
|
|
38
|
+
expect(result1.isValid).toEqual(false);
|
|
39
|
+
expect(result1.errors[0]).toEqual("name is required");
|
|
40
|
+
|
|
41
|
+
// Min length
|
|
42
|
+
const builder2 = new ValidatorBuilder();
|
|
43
|
+
const result2 = builder2.string("name", "ab", { minLength: 3 }).build();
|
|
44
|
+
expect(result2.isValid).toEqual(false);
|
|
45
|
+
|
|
46
|
+
// Max length
|
|
47
|
+
const builder3 = new ValidatorBuilder();
|
|
48
|
+
const result3 = builder3.string("name", "abcdef", { maxLength: 5 }).build();
|
|
49
|
+
expect(result3.isValid).toEqual(false);
|
|
50
|
+
|
|
51
|
+
// Valid string
|
|
52
|
+
const builder4 = new ValidatorBuilder();
|
|
53
|
+
const result4 = builder4.string("name", "valid", {
|
|
54
|
+
required: true,
|
|
55
|
+
minLength: 3,
|
|
56
|
+
maxLength: 10,
|
|
57
|
+
}).build();
|
|
58
|
+
expect(result4.isValid).toEqual(true);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test("ValidatorBuilder - email validation", () => {
|
|
62
|
+
const builder1 = new ValidatorBuilder();
|
|
63
|
+
const result1 = builder1.email("email", "invalid", true).build();
|
|
64
|
+
expect(result1.isValid).toEqual(false);
|
|
65
|
+
|
|
66
|
+
const builder2 = new ValidatorBuilder();
|
|
67
|
+
const result2 = builder2.email("email", "user@example.com", true).build();
|
|
68
|
+
expect(result2.isValid).toEqual(true);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("ValidatorBuilder - number validation", () => {
|
|
72
|
+
const builder1 = new ValidatorBuilder();
|
|
73
|
+
const result1 = builder1.number("age", 15, { min: 18 }).build();
|
|
74
|
+
expect(result1.isValid).toEqual(false);
|
|
75
|
+
|
|
76
|
+
const builder2 = new ValidatorBuilder();
|
|
77
|
+
const result2 = builder2.number("age", 25, { min: 18, max: 65 }).build();
|
|
78
|
+
expect(result2.isValid).toEqual(true);
|
|
79
|
+
|
|
80
|
+
const builder3 = new ValidatorBuilder();
|
|
81
|
+
const result3 = builder3.number("age", null, { required: true }).build();
|
|
82
|
+
expect(result3.isValid).toEqual(false);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test("ValidatorBuilder - array validation", () => {
|
|
86
|
+
const builder1 = new ValidatorBuilder();
|
|
87
|
+
const result1 = builder1.array("items", [], { allowEmpty: false }).build();
|
|
88
|
+
expect(result1.isValid).toEqual(false);
|
|
89
|
+
|
|
90
|
+
const builder2 = new ValidatorBuilder();
|
|
91
|
+
const result2 = builder2.array("items", ["a", "b", "c"], {
|
|
92
|
+
minItems: 2,
|
|
93
|
+
maxItems: 5,
|
|
94
|
+
}).build();
|
|
95
|
+
expect(result2.isValid).toEqual(true);
|
|
96
|
+
|
|
97
|
+
const builder3 = new ValidatorBuilder();
|
|
98
|
+
const result3 = builder3.array("items", ["a"], { minItems: 2 }).build();
|
|
99
|
+
expect(result3.isValid).toEqual(false);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test("ValidatorBuilder - entityId validation", () => {
|
|
103
|
+
const builder1 = new ValidatorBuilder();
|
|
104
|
+
const result1 = builder1.entityId(
|
|
105
|
+
"id",
|
|
106
|
+
"abcd-550e8400-e29b-41d4-a716-446655440000",
|
|
107
|
+
"abcd",
|
|
108
|
+
true,
|
|
109
|
+
).build();
|
|
110
|
+
expect(result1.isValid).toEqual(true);
|
|
111
|
+
|
|
112
|
+
const builder2 = new ValidatorBuilder();
|
|
113
|
+
const result2 = builder2.entityId(
|
|
114
|
+
"id",
|
|
115
|
+
"wxyz-550e8400-e29b-41d4-a716-446655440000",
|
|
116
|
+
"abcd",
|
|
117
|
+
true,
|
|
118
|
+
).build();
|
|
119
|
+
expect(result2.isValid).toEqual(false);
|
|
120
|
+
|
|
121
|
+
const builder3 = new ValidatorBuilder();
|
|
122
|
+
const result3 = builder3.entityId("id", "invalid-id", "abcd", true).build();
|
|
123
|
+
expect(result3.isValid).toEqual(false);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test("ValidatorBuilder - chaining multiple validations", () => {
|
|
127
|
+
const builder = new ValidatorBuilder();
|
|
128
|
+
|
|
129
|
+
const result = builder
|
|
130
|
+
.string("username", "john_doe", { required: true, minLength: 3 })
|
|
131
|
+
.email("email", "john@example.com", true)
|
|
132
|
+
.number("age", 25, { required: true, min: 18, max: 100 })
|
|
133
|
+
.array("tags", ["tag1", "tag2"], { minItems: 1 })
|
|
134
|
+
.boolean("isActive", true, { required: true })
|
|
135
|
+
.build();
|
|
136
|
+
|
|
137
|
+
expect(result.isValid).toEqual(true);
|
|
138
|
+
});
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"noEmit": true,
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
"allowImportingTsExtensions": true,
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"isolatedModules": true,
|
|
13
|
+
"verbatimModuleSyntax": true,
|
|
14
|
+
"resolveJsonModule": true,
|
|
15
|
+
"types": ["bun-types"]
|
|
16
|
+
},
|
|
17
|
+
"include": ["src/**/*.ts", "mod.ts"]
|
|
18
|
+
}
|