@dangao/bun-server 1.7.1 → 1.8.0
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 +129 -21
- package/dist/di/decorators.d.ts +37 -0
- package/dist/di/decorators.d.ts.map +1 -1
- package/dist/di/index.d.ts +1 -1
- package/dist/di/index.d.ts.map +1 -1
- package/dist/di/module-registry.d.ts +17 -0
- package/dist/di/module-registry.d.ts.map +1 -1
- package/dist/events/decorators.d.ts +52 -0
- package/dist/events/decorators.d.ts.map +1 -0
- package/dist/events/event-module.d.ts +97 -0
- package/dist/events/event-module.d.ts.map +1 -0
- package/dist/events/index.d.ts +5 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/service.d.ts +76 -0
- package/dist/events/service.d.ts.map +1 -0
- package/dist/events/types.d.ts +184 -0
- package/dist/events/types.d.ts.map +1 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1511 -11
- package/dist/security/filter.d.ts +23 -0
- package/dist/security/filter.d.ts.map +1 -1
- package/dist/security/guards/builtin/auth-guard.d.ts +44 -0
- package/dist/security/guards/builtin/auth-guard.d.ts.map +1 -0
- package/dist/security/guards/builtin/index.d.ts +3 -0
- package/dist/security/guards/builtin/index.d.ts.map +1 -0
- package/dist/security/guards/builtin/roles-guard.d.ts +66 -0
- package/dist/security/guards/builtin/roles-guard.d.ts.map +1 -0
- package/dist/security/guards/decorators.d.ts +50 -0
- package/dist/security/guards/decorators.d.ts.map +1 -0
- package/dist/security/guards/execution-context.d.ts +56 -0
- package/dist/security/guards/execution-context.d.ts.map +1 -0
- package/dist/security/guards/guard-registry.d.ts +67 -0
- package/dist/security/guards/guard-registry.d.ts.map +1 -0
- package/dist/security/guards/index.d.ts +7 -0
- package/dist/security/guards/index.d.ts.map +1 -0
- package/dist/security/guards/reflector.d.ts +57 -0
- package/dist/security/guards/reflector.d.ts.map +1 -0
- package/dist/security/guards/types.d.ts +126 -0
- package/dist/security/guards/types.d.ts.map +1 -0
- package/dist/security/index.d.ts +1 -0
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/security-module.d.ts +20 -0
- package/dist/security/security-module.d.ts.map +1 -1
- package/dist/validation/class-validator.d.ts +108 -0
- package/dist/validation/class-validator.d.ts.map +1 -0
- package/dist/validation/custom-validator.d.ts +130 -0
- package/dist/validation/custom-validator.d.ts.map +1 -0
- package/dist/validation/errors.d.ts +22 -2
- package/dist/validation/errors.d.ts.map +1 -1
- package/dist/validation/index.d.ts +7 -1
- package/dist/validation/index.d.ts.map +1 -1
- package/dist/validation/rules/array.d.ts +33 -0
- package/dist/validation/rules/array.d.ts.map +1 -0
- package/dist/validation/rules/common.d.ts +90 -0
- package/dist/validation/rules/common.d.ts.map +1 -0
- package/dist/validation/rules/conditional.d.ts +30 -0
- package/dist/validation/rules/conditional.d.ts.map +1 -0
- package/dist/validation/rules/index.d.ts +5 -0
- package/dist/validation/rules/index.d.ts.map +1 -0
- package/dist/validation/rules/object.d.ts +30 -0
- package/dist/validation/rules/object.d.ts.map +1 -0
- package/dist/validation/types.d.ts +52 -1
- package/dist/validation/types.d.ts.map +1 -1
- package/docs/events.md +494 -0
- package/docs/guards.md +376 -0
- package/docs/guide.md +309 -1
- package/docs/request-lifecycle.md +444 -0
- package/docs/validation.md +407 -0
- package/docs/zh/events.md +494 -0
- package/docs/zh/guards.md +376 -0
- package/docs/zh/guide.md +309 -1
- package/docs/zh/request-lifecycle.md +444 -0
- package/docs/zh/validation.md +407 -0
- package/package.json +1 -1
- package/src/di/decorators.ts +46 -0
- package/src/di/index.ts +10 -1
- package/src/di/module-registry.ts +39 -0
- package/src/events/decorators.ts +103 -0
- package/src/events/event-module.ts +272 -0
- package/src/events/index.ts +32 -0
- package/src/events/service.ts +352 -0
- package/src/events/types.ts +223 -0
- package/src/index.ts +133 -1
- package/src/security/filter.ts +88 -8
- package/src/security/guards/builtin/auth-guard.ts +68 -0
- package/src/security/guards/builtin/index.ts +3 -0
- package/src/security/guards/builtin/roles-guard.ts +165 -0
- package/src/security/guards/decorators.ts +124 -0
- package/src/security/guards/execution-context.ts +152 -0
- package/src/security/guards/guard-registry.ts +164 -0
- package/src/security/guards/index.ts +7 -0
- package/src/security/guards/reflector.ts +99 -0
- package/src/security/guards/types.ts +144 -0
- package/src/security/index.ts +1 -0
- package/src/security/security-module.ts +72 -2
- package/src/validation/class-validator.ts +322 -0
- package/src/validation/custom-validator.ts +289 -0
- package/src/validation/errors.ts +50 -2
- package/src/validation/index.ts +103 -1
- package/src/validation/rules/array.ts +118 -0
- package/src/validation/rules/common.ts +286 -0
- package/src/validation/rules/conditional.ts +52 -0
- package/src/validation/rules/index.ts +51 -0
- package/src/validation/rules/object.ts +86 -0
- package/src/validation/types.ts +61 -1
- package/tests/di/global-module.test.ts +487 -0
- package/tests/events/event-decorators.test.ts +173 -0
- package/tests/events/event-emitter.test.ts +373 -0
- package/tests/events/event-module.test.ts +373 -0
- package/tests/security/guards/guards-integration.test.ts +371 -0
- package/tests/security/guards/guards.test.ts +775 -0
- package/tests/security/security-module.test.ts +2 -2
- package/tests/validation/class-validator.test.ts +349 -0
- package/tests/validation/custom-validator.test.ts +335 -0
- package/tests/validation/rules.test.ts +543 -0
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ var __create = Object.create;
|
|
|
3
3
|
var __getProtoOf = Object.getPrototypeOf;
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
8
|
var __toESM = (mod, isNodeMode, target) => {
|
|
8
9
|
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
@@ -15,6 +16,20 @@ var __toESM = (mod, isNodeMode, target) => {
|
|
|
15
16
|
});
|
|
16
17
|
return to;
|
|
17
18
|
};
|
|
19
|
+
var __moduleCache = /* @__PURE__ */ new WeakMap;
|
|
20
|
+
var __toCommonJS = (from) => {
|
|
21
|
+
var entry = __moduleCache.get(from), desc;
|
|
22
|
+
if (entry)
|
|
23
|
+
return entry;
|
|
24
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
25
|
+
if (from && typeof from === "object" || typeof from === "function")
|
|
26
|
+
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
|
|
27
|
+
get: () => from[key],
|
|
28
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
29
|
+
}));
|
|
30
|
+
__moduleCache.set(from, entry);
|
|
31
|
+
return entry;
|
|
32
|
+
};
|
|
18
33
|
var __export = (target, all) => {
|
|
19
34
|
for (var name in all)
|
|
20
35
|
__defProp(target, name, {
|
|
@@ -136,10 +151,19 @@ function getTypeReference(constructor, parameterIndex) {
|
|
|
136
151
|
}
|
|
137
152
|
return;
|
|
138
153
|
}
|
|
139
|
-
|
|
154
|
+
function Global() {
|
|
155
|
+
return (target) => {
|
|
156
|
+
Reflect.defineMetadata(GLOBAL_MODULE_METADATA_KEY, true, target);
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function isGlobalModule(target) {
|
|
160
|
+
return Reflect.getMetadata(GLOBAL_MODULE_METADATA_KEY, target) === true;
|
|
161
|
+
}
|
|
162
|
+
var DEPENDENCY_METADATA_KEY, INJECTABLE_METADATA_KEY, GLOBAL_MODULE_METADATA_KEY, typeReferenceMap;
|
|
140
163
|
var init_decorators = __esm(() => {
|
|
141
164
|
DEPENDENCY_METADATA_KEY = Symbol("dependency:metadata");
|
|
142
165
|
INJECTABLE_METADATA_KEY = Symbol("injectable");
|
|
166
|
+
GLOBAL_MODULE_METADATA_KEY = Symbol("@dangao/bun-server:global-module");
|
|
143
167
|
typeReferenceMap = new WeakMap;
|
|
144
168
|
});
|
|
145
169
|
|
|
@@ -1437,6 +1461,31 @@ var init_errors = __esm(() => {
|
|
|
1437
1461
|
this.name = "ValidationError";
|
|
1438
1462
|
this.issues = issues;
|
|
1439
1463
|
}
|
|
1464
|
+
getFlattened() {
|
|
1465
|
+
const flatten = (issues, prefix = "") => {
|
|
1466
|
+
const result = [];
|
|
1467
|
+
for (const issue of issues) {
|
|
1468
|
+
const propertyPath = prefix ? `${prefix}.${issue.property ?? ""}` : issue.property ?? "";
|
|
1469
|
+
if (issue.children && issue.children.length > 0) {
|
|
1470
|
+
result.push(...flatten(issue.children, propertyPath));
|
|
1471
|
+
} else {
|
|
1472
|
+
result.push({
|
|
1473
|
+
...issue,
|
|
1474
|
+
property: propertyPath || undefined
|
|
1475
|
+
});
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
return result;
|
|
1479
|
+
};
|
|
1480
|
+
return flatten(this.issues);
|
|
1481
|
+
}
|
|
1482
|
+
toJSON() {
|
|
1483
|
+
return {
|
|
1484
|
+
name: this.name,
|
|
1485
|
+
message: this.message,
|
|
1486
|
+
issues: this.issues
|
|
1487
|
+
};
|
|
1488
|
+
}
|
|
1440
1489
|
};
|
|
1441
1490
|
});
|
|
1442
1491
|
|
|
@@ -1488,11 +1537,614 @@ var init_validator = __esm(() => {
|
|
|
1488
1537
|
init_errors();
|
|
1489
1538
|
});
|
|
1490
1539
|
|
|
1540
|
+
// src/validation/rules/object.ts
|
|
1541
|
+
function IsObject(options = {}) {
|
|
1542
|
+
return {
|
|
1543
|
+
name: "isObject",
|
|
1544
|
+
message: options.message ?? "\u5FC5\u987B\u662F\u5BF9\u8C61",
|
|
1545
|
+
validate: (value) => typeof value === "object" && value !== null && !Array.isArray(value)
|
|
1546
|
+
};
|
|
1547
|
+
}
|
|
1548
|
+
function IsNotEmpty(options = {}) {
|
|
1549
|
+
return {
|
|
1550
|
+
name: "isNotEmpty",
|
|
1551
|
+
message: options.message ?? "\u4E0D\u80FD\u4E3A\u7A7A",
|
|
1552
|
+
validate: (value) => {
|
|
1553
|
+
if (value === null || value === undefined) {
|
|
1554
|
+
return false;
|
|
1555
|
+
}
|
|
1556
|
+
if (typeof value === "string") {
|
|
1557
|
+
return value.trim().length > 0;
|
|
1558
|
+
}
|
|
1559
|
+
if (Array.isArray(value)) {
|
|
1560
|
+
return value.length > 0;
|
|
1561
|
+
}
|
|
1562
|
+
if (typeof value === "object") {
|
|
1563
|
+
return Object.keys(value).length > 0;
|
|
1564
|
+
}
|
|
1565
|
+
return true;
|
|
1566
|
+
}
|
|
1567
|
+
};
|
|
1568
|
+
}
|
|
1569
|
+
function IsNotEmptyObject(options = {}) {
|
|
1570
|
+
return {
|
|
1571
|
+
name: "isNotEmptyObject",
|
|
1572
|
+
message: options.message ?? "\u5FC5\u987B\u662F\u975E\u7A7A\u5BF9\u8C61",
|
|
1573
|
+
validate: (value) => {
|
|
1574
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
1575
|
+
return false;
|
|
1576
|
+
}
|
|
1577
|
+
return Object.keys(value).length > 0;
|
|
1578
|
+
}
|
|
1579
|
+
};
|
|
1580
|
+
}
|
|
1581
|
+
function ValidateNested(options = {}) {
|
|
1582
|
+
return {
|
|
1583
|
+
name: "validateNested",
|
|
1584
|
+
message: options.message ?? "\u5D4C\u5957\u5BF9\u8C61\u9A8C\u8BC1\u5931\u8D25",
|
|
1585
|
+
nested: true,
|
|
1586
|
+
each: options.each ?? false,
|
|
1587
|
+
validate: (value) => {
|
|
1588
|
+
if (options.each) {
|
|
1589
|
+
return Array.isArray(value);
|
|
1590
|
+
}
|
|
1591
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1592
|
+
}
|
|
1593
|
+
};
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1596
|
+
// src/validation/rules/array.ts
|
|
1597
|
+
function IsArray(options = {}) {
|
|
1598
|
+
return {
|
|
1599
|
+
name: "isArray",
|
|
1600
|
+
message: options.message ?? "\u5FC5\u987B\u662F\u6570\u7EC4",
|
|
1601
|
+
validate: (value) => Array.isArray(value)
|
|
1602
|
+
};
|
|
1603
|
+
}
|
|
1604
|
+
function ArrayMinSize(min, options = {}) {
|
|
1605
|
+
return {
|
|
1606
|
+
name: "arrayMinSize",
|
|
1607
|
+
message: options.message ?? `\u6570\u7EC4\u957F\u5EA6\u4E0D\u80FD\u5C0F\u4E8E ${min}`,
|
|
1608
|
+
validate: (value) => Array.isArray(value) && value.length >= min
|
|
1609
|
+
};
|
|
1610
|
+
}
|
|
1611
|
+
function ArrayMaxSize(max, options = {}) {
|
|
1612
|
+
return {
|
|
1613
|
+
name: "arrayMaxSize",
|
|
1614
|
+
message: options.message ?? `\u6570\u7EC4\u957F\u5EA6\u4E0D\u80FD\u5927\u4E8E ${max}`,
|
|
1615
|
+
validate: (value) => Array.isArray(value) && value.length <= max
|
|
1616
|
+
};
|
|
1617
|
+
}
|
|
1618
|
+
function ArrayUnique(options = {}) {
|
|
1619
|
+
return {
|
|
1620
|
+
name: "arrayUnique",
|
|
1621
|
+
message: options.message ?? "\u6570\u7EC4\u5143\u7D20\u5FC5\u987B\u552F\u4E00",
|
|
1622
|
+
validate: (value) => {
|
|
1623
|
+
if (!Array.isArray(value)) {
|
|
1624
|
+
return false;
|
|
1625
|
+
}
|
|
1626
|
+
const seen = new Set;
|
|
1627
|
+
for (const item of value) {
|
|
1628
|
+
const key = typeof item === "object" ? JSON.stringify(item) : item;
|
|
1629
|
+
if (seen.has(key)) {
|
|
1630
|
+
return false;
|
|
1631
|
+
}
|
|
1632
|
+
seen.add(key);
|
|
1633
|
+
}
|
|
1634
|
+
return true;
|
|
1635
|
+
}
|
|
1636
|
+
};
|
|
1637
|
+
}
|
|
1638
|
+
function ArrayContains(values, options = {}) {
|
|
1639
|
+
return {
|
|
1640
|
+
name: "arrayContains",
|
|
1641
|
+
message: options.message ?? `\u6570\u7EC4\u5FC5\u987B\u5305\u542B ${values.join(", ")}`,
|
|
1642
|
+
validate: (value) => {
|
|
1643
|
+
if (!Array.isArray(value)) {
|
|
1644
|
+
return false;
|
|
1645
|
+
}
|
|
1646
|
+
return values.every((v) => {
|
|
1647
|
+
if (typeof v === "object") {
|
|
1648
|
+
const vStr = JSON.stringify(v);
|
|
1649
|
+
return value.some((item) => JSON.stringify(item) === vStr);
|
|
1650
|
+
}
|
|
1651
|
+
return value.includes(v);
|
|
1652
|
+
});
|
|
1653
|
+
}
|
|
1654
|
+
};
|
|
1655
|
+
}
|
|
1656
|
+
function ArrayNotContains(values, options = {}) {
|
|
1657
|
+
return {
|
|
1658
|
+
name: "arrayNotContains",
|
|
1659
|
+
message: options.message ?? `\u6570\u7EC4\u4E0D\u80FD\u5305\u542B ${values.join(", ")}`,
|
|
1660
|
+
validate: (value) => {
|
|
1661
|
+
if (!Array.isArray(value)) {
|
|
1662
|
+
return false;
|
|
1663
|
+
}
|
|
1664
|
+
return values.every((v) => {
|
|
1665
|
+
if (typeof v === "object") {
|
|
1666
|
+
const vStr = JSON.stringify(v);
|
|
1667
|
+
return !value.some((item) => JSON.stringify(item) === vStr);
|
|
1668
|
+
}
|
|
1669
|
+
return !value.includes(v);
|
|
1670
|
+
});
|
|
1671
|
+
}
|
|
1672
|
+
};
|
|
1673
|
+
}
|
|
1674
|
+
function ArrayNotEmpty(options = {}) {
|
|
1675
|
+
return {
|
|
1676
|
+
name: "arrayNotEmpty",
|
|
1677
|
+
message: options.message ?? "\u6570\u7EC4\u4E0D\u80FD\u4E3A\u7A7A",
|
|
1678
|
+
validate: (value) => Array.isArray(value) && value.length > 0
|
|
1679
|
+
};
|
|
1680
|
+
}
|
|
1681
|
+
|
|
1682
|
+
// src/validation/rules/common.ts
|
|
1683
|
+
function IsBoolean(options = {}) {
|
|
1684
|
+
return {
|
|
1685
|
+
name: "isBoolean",
|
|
1686
|
+
message: options.message ?? "\u5FC5\u987B\u662F\u5E03\u5C14\u503C",
|
|
1687
|
+
validate: (value) => typeof value === "boolean"
|
|
1688
|
+
};
|
|
1689
|
+
}
|
|
1690
|
+
function IsInt(options = {}) {
|
|
1691
|
+
return {
|
|
1692
|
+
name: "isInt",
|
|
1693
|
+
message: options.message ?? "\u5FC5\u987B\u662F\u6574\u6570",
|
|
1694
|
+
validate: (value) => typeof value === "number" && Number.isInteger(value)
|
|
1695
|
+
};
|
|
1696
|
+
}
|
|
1697
|
+
function IsPositive(options = {}) {
|
|
1698
|
+
return {
|
|
1699
|
+
name: "isPositive",
|
|
1700
|
+
message: options.message ?? "\u5FC5\u987B\u662F\u6B63\u6570",
|
|
1701
|
+
validate: (value) => typeof value === "number" && value > 0
|
|
1702
|
+
};
|
|
1703
|
+
}
|
|
1704
|
+
function IsNegative(options = {}) {
|
|
1705
|
+
return {
|
|
1706
|
+
name: "isNegative",
|
|
1707
|
+
message: options.message ?? "\u5FC5\u987B\u662F\u8D1F\u6570",
|
|
1708
|
+
validate: (value) => typeof value === "number" && value < 0
|
|
1709
|
+
};
|
|
1710
|
+
}
|
|
1711
|
+
function Min(min, options = {}) {
|
|
1712
|
+
return {
|
|
1713
|
+
name: "min",
|
|
1714
|
+
message: options.message ?? `\u4E0D\u80FD\u5C0F\u4E8E ${min}`,
|
|
1715
|
+
validate: (value) => typeof value === "number" && value >= min
|
|
1716
|
+
};
|
|
1717
|
+
}
|
|
1718
|
+
function Max(max, options = {}) {
|
|
1719
|
+
return {
|
|
1720
|
+
name: "max",
|
|
1721
|
+
message: options.message ?? `\u4E0D\u80FD\u5927\u4E8E ${max}`,
|
|
1722
|
+
validate: (value) => typeof value === "number" && value <= max
|
|
1723
|
+
};
|
|
1724
|
+
}
|
|
1725
|
+
function IsDate(options = {}) {
|
|
1726
|
+
return {
|
|
1727
|
+
name: "isDate",
|
|
1728
|
+
message: options.message ?? "\u5FC5\u987B\u662F\u6709\u6548\u7684\u65E5\u671F",
|
|
1729
|
+
validate: (value) => {
|
|
1730
|
+
if (value instanceof Date) {
|
|
1731
|
+
return !Number.isNaN(value.getTime());
|
|
1732
|
+
}
|
|
1733
|
+
if (typeof value === "string" || typeof value === "number") {
|
|
1734
|
+
const date = new Date(value);
|
|
1735
|
+
return !Number.isNaN(date.getTime());
|
|
1736
|
+
}
|
|
1737
|
+
return false;
|
|
1738
|
+
}
|
|
1739
|
+
};
|
|
1740
|
+
}
|
|
1741
|
+
function IsUUID(version = "all", options = {}) {
|
|
1742
|
+
return {
|
|
1743
|
+
name: "isUUID",
|
|
1744
|
+
message: options.message ?? `\u5FC5\u987B\u662F\u6709\u6548\u7684 UUID${version !== "all" ? ` (v${version})` : ""}`,
|
|
1745
|
+
validate: (value) => typeof value === "string" && UUID_PATTERNS[version].test(value)
|
|
1746
|
+
};
|
|
1747
|
+
}
|
|
1748
|
+
function Length(min, max, options = {}) {
|
|
1749
|
+
const maxMsg = max !== undefined ? ` \u4E14\u4E0D\u80FD\u5927\u4E8E ${max}` : "";
|
|
1750
|
+
return {
|
|
1751
|
+
name: "length",
|
|
1752
|
+
message: options.message ?? `\u957F\u5EA6\u4E0D\u80FD\u5C0F\u4E8E ${min}${maxMsg}`,
|
|
1753
|
+
validate: (value) => {
|
|
1754
|
+
if (typeof value !== "string") {
|
|
1755
|
+
return false;
|
|
1756
|
+
}
|
|
1757
|
+
if (value.length < min) {
|
|
1758
|
+
return false;
|
|
1759
|
+
}
|
|
1760
|
+
if (max !== undefined && value.length > max) {
|
|
1761
|
+
return false;
|
|
1762
|
+
}
|
|
1763
|
+
return true;
|
|
1764
|
+
}
|
|
1765
|
+
};
|
|
1766
|
+
}
|
|
1767
|
+
function MaxLength(max, options = {}) {
|
|
1768
|
+
return {
|
|
1769
|
+
name: "maxLength",
|
|
1770
|
+
message: options.message ?? `\u957F\u5EA6\u4E0D\u80FD\u5927\u4E8E ${max}`,
|
|
1771
|
+
validate: (value) => typeof value === "string" && value.length <= max
|
|
1772
|
+
};
|
|
1773
|
+
}
|
|
1774
|
+
function Matches(pattern, options = {}) {
|
|
1775
|
+
return {
|
|
1776
|
+
name: "matches",
|
|
1777
|
+
message: options.message ?? `\u5FC5\u987B\u5339\u914D\u683C\u5F0F ${pattern.toString()}`,
|
|
1778
|
+
validate: (value) => typeof value === "string" && pattern.test(value)
|
|
1779
|
+
};
|
|
1780
|
+
}
|
|
1781
|
+
function IsIn(values, options = {}) {
|
|
1782
|
+
return {
|
|
1783
|
+
name: "isIn",
|
|
1784
|
+
message: options.message ?? `\u5FC5\u987B\u662F\u4EE5\u4E0B\u503C\u4E4B\u4E00: ${values.join(", ")}`,
|
|
1785
|
+
validate: (value) => values.includes(value)
|
|
1786
|
+
};
|
|
1787
|
+
}
|
|
1788
|
+
function IsNotIn(values, options = {}) {
|
|
1789
|
+
return {
|
|
1790
|
+
name: "isNotIn",
|
|
1791
|
+
message: options.message ?? `\u4E0D\u80FD\u662F\u4EE5\u4E0B\u503C\u4E4B\u4E00: ${values.join(", ")}`,
|
|
1792
|
+
validate: (value) => !values.includes(value)
|
|
1793
|
+
};
|
|
1794
|
+
}
|
|
1795
|
+
function IsUrl(options = {}) {
|
|
1796
|
+
return {
|
|
1797
|
+
name: "isUrl",
|
|
1798
|
+
message: options.message ?? "\u5FC5\u987B\u662F\u6709\u6548\u7684 URL",
|
|
1799
|
+
validate: (value) => {
|
|
1800
|
+
if (typeof value !== "string") {
|
|
1801
|
+
return false;
|
|
1802
|
+
}
|
|
1803
|
+
try {
|
|
1804
|
+
new URL(value);
|
|
1805
|
+
return true;
|
|
1806
|
+
} catch {
|
|
1807
|
+
return false;
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1810
|
+
};
|
|
1811
|
+
}
|
|
1812
|
+
function IsJSON(options = {}) {
|
|
1813
|
+
return {
|
|
1814
|
+
name: "isJSON",
|
|
1815
|
+
message: options.message ?? "\u5FC5\u987B\u662F\u6709\u6548\u7684 JSON \u5B57\u7B26\u4E32",
|
|
1816
|
+
validate: (value) => {
|
|
1817
|
+
if (typeof value !== "string") {
|
|
1818
|
+
return false;
|
|
1819
|
+
}
|
|
1820
|
+
try {
|
|
1821
|
+
JSON.parse(value);
|
|
1822
|
+
return true;
|
|
1823
|
+
} catch {
|
|
1824
|
+
return false;
|
|
1825
|
+
}
|
|
1826
|
+
}
|
|
1827
|
+
};
|
|
1828
|
+
}
|
|
1829
|
+
function Equals(comparison, options = {}) {
|
|
1830
|
+
return {
|
|
1831
|
+
name: "equals",
|
|
1832
|
+
message: options.message ?? `\u5FC5\u987B\u7B49\u4E8E ${comparison}`,
|
|
1833
|
+
validate: (value) => value === comparison
|
|
1834
|
+
};
|
|
1835
|
+
}
|
|
1836
|
+
function NotEquals(comparison, options = {}) {
|
|
1837
|
+
return {
|
|
1838
|
+
name: "notEquals",
|
|
1839
|
+
message: options.message ?? `\u4E0D\u80FD\u7B49\u4E8E ${comparison}`,
|
|
1840
|
+
validate: (value) => value !== comparison
|
|
1841
|
+
};
|
|
1842
|
+
}
|
|
1843
|
+
function IsDefined(options = {}) {
|
|
1844
|
+
return {
|
|
1845
|
+
name: "isDefined",
|
|
1846
|
+
message: options.message ?? "\u5FC5\u987B\u5B9A\u4E49",
|
|
1847
|
+
validate: (value) => value !== null && value !== undefined
|
|
1848
|
+
};
|
|
1849
|
+
}
|
|
1850
|
+
function IsAlphanumeric(options = {}) {
|
|
1851
|
+
return {
|
|
1852
|
+
name: "isAlphanumeric",
|
|
1853
|
+
message: options.message ?? "\u53EA\u80FD\u5305\u542B\u5B57\u6BCD\u548C\u6570\u5B57",
|
|
1854
|
+
validate: (value) => typeof value === "string" && /^[a-zA-Z0-9]+$/.test(value)
|
|
1855
|
+
};
|
|
1856
|
+
}
|
|
1857
|
+
function IsAlpha(options = {}) {
|
|
1858
|
+
return {
|
|
1859
|
+
name: "isAlpha",
|
|
1860
|
+
message: options.message ?? "\u53EA\u80FD\u5305\u542B\u5B57\u6BCD",
|
|
1861
|
+
validate: (value) => typeof value === "string" && /^[a-zA-Z]+$/.test(value)
|
|
1862
|
+
};
|
|
1863
|
+
}
|
|
1864
|
+
function IsNumberString(options = {}) {
|
|
1865
|
+
return {
|
|
1866
|
+
name: "isNumberString",
|
|
1867
|
+
message: options.message ?? "\u53EA\u80FD\u5305\u542B\u6570\u5B57",
|
|
1868
|
+
validate: (value) => typeof value === "string" && /^[0-9]+$/.test(value)
|
|
1869
|
+
};
|
|
1870
|
+
}
|
|
1871
|
+
var UUID_PATTERNS;
|
|
1872
|
+
var init_common = __esm(() => {
|
|
1873
|
+
UUID_PATTERNS = {
|
|
1874
|
+
"3": /^[0-9a-f]{8}-[0-9a-f]{4}-3[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,
|
|
1875
|
+
"4": /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,
|
|
1876
|
+
"5": /^[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,
|
|
1877
|
+
all: /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
|
|
1878
|
+
};
|
|
1879
|
+
});
|
|
1880
|
+
|
|
1881
|
+
// src/validation/rules/conditional.ts
|
|
1882
|
+
function ValidateIf(condition, options = {}) {
|
|
1883
|
+
return {
|
|
1884
|
+
name: "validateIf",
|
|
1885
|
+
message: options.message ?? "",
|
|
1886
|
+
condition,
|
|
1887
|
+
validate: () => true
|
|
1888
|
+
};
|
|
1889
|
+
}
|
|
1890
|
+
function Transform(transformFn, options = {}) {
|
|
1891
|
+
return {
|
|
1892
|
+
name: "transform",
|
|
1893
|
+
message: options.message ?? "",
|
|
1894
|
+
transform: transformFn,
|
|
1895
|
+
validate: () => true
|
|
1896
|
+
};
|
|
1897
|
+
}
|
|
1898
|
+
|
|
1899
|
+
// src/validation/custom-validator.ts
|
|
1900
|
+
function createCustomValidator(name, validate, defaultMessage) {
|
|
1901
|
+
return (...args) => (options = {}) => {
|
|
1902
|
+
const message = options.message ?? (typeof defaultMessage === "function" ? defaultMessage(...args) : defaultMessage);
|
|
1903
|
+
return {
|
|
1904
|
+
name,
|
|
1905
|
+
message,
|
|
1906
|
+
validate: (value) => validate(value, ...args)
|
|
1907
|
+
};
|
|
1908
|
+
};
|
|
1909
|
+
}
|
|
1910
|
+
function createSimpleValidator(name, validate, defaultMessage) {
|
|
1911
|
+
return (options = {}) => ({
|
|
1912
|
+
name,
|
|
1913
|
+
message: options.message ?? defaultMessage,
|
|
1914
|
+
validate
|
|
1915
|
+
});
|
|
1916
|
+
}
|
|
1917
|
+
function createRegexValidator(name, pattern, defaultMessage) {
|
|
1918
|
+
return createSimpleValidator(name, (value) => typeof value === "string" && pattern.test(value), defaultMessage);
|
|
1919
|
+
}
|
|
1920
|
+
var IsPhoneNumber, IsIdCard, IsIPv4, IsPort, IsPostalCode, IsCreditCard, IsHexColor, IsMacAddress, IsSemVer, IsDivisibleBy, IsBetween, Contains, NotContains;
|
|
1921
|
+
var init_custom_validator = __esm(() => {
|
|
1922
|
+
IsPhoneNumber = createSimpleValidator("isPhoneNumber", (value) => typeof value === "string" && /^1[3-9]\d{9}$/.test(value), "\u5FC5\u987B\u662F\u6709\u6548\u7684\u624B\u673A\u53F7\u7801");
|
|
1923
|
+
IsIdCard = createSimpleValidator("isIdCard", (value) => {
|
|
1924
|
+
if (typeof value !== "string")
|
|
1925
|
+
return false;
|
|
1926
|
+
const pattern15 = /^[1-9]\d{5}\d{2}((0[1-9])|(1[0-2]))(([0-2]\d)|30|31)\d{3}$/;
|
|
1927
|
+
const pattern18 = /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2]\d)|30|31)\d{3}[0-9Xx]$/;
|
|
1928
|
+
return pattern15.test(value) || pattern18.test(value);
|
|
1929
|
+
}, "\u5FC5\u987B\u662F\u6709\u6548\u7684\u8EAB\u4EFD\u8BC1\u53F7\u7801");
|
|
1930
|
+
IsIPv4 = createSimpleValidator("isIPv4", (value) => {
|
|
1931
|
+
if (typeof value !== "string")
|
|
1932
|
+
return false;
|
|
1933
|
+
const parts = value.split(".");
|
|
1934
|
+
if (parts.length !== 4)
|
|
1935
|
+
return false;
|
|
1936
|
+
return parts.every((part) => {
|
|
1937
|
+
const num = parseInt(part, 10);
|
|
1938
|
+
return !Number.isNaN(num) && num >= 0 && num <= 255 && String(num) === part;
|
|
1939
|
+
});
|
|
1940
|
+
}, "\u5FC5\u987B\u662F\u6709\u6548\u7684 IPv4 \u5730\u5740");
|
|
1941
|
+
IsPort = createSimpleValidator("isPort", (value) => {
|
|
1942
|
+
if (typeof value === "string") {
|
|
1943
|
+
const num = parseInt(value, 10);
|
|
1944
|
+
return !Number.isNaN(num) && num >= 0 && num <= 65535;
|
|
1945
|
+
}
|
|
1946
|
+
if (typeof value === "number") {
|
|
1947
|
+
return Number.isInteger(value) && value >= 0 && value <= 65535;
|
|
1948
|
+
}
|
|
1949
|
+
return false;
|
|
1950
|
+
}, "\u5FC5\u987B\u662F\u6709\u6548\u7684\u7AEF\u53E3\u53F7 (0-65535)");
|
|
1951
|
+
IsPostalCode = createSimpleValidator("isPostalCode", (value) => typeof value === "string" && /^[1-9]\d{5}$/.test(value), "\u5FC5\u987B\u662F\u6709\u6548\u7684\u90AE\u653F\u7F16\u7801");
|
|
1952
|
+
IsCreditCard = createSimpleValidator("isCreditCard", (value) => {
|
|
1953
|
+
if (typeof value !== "string")
|
|
1954
|
+
return false;
|
|
1955
|
+
const sanitized = value.replace(/[\s-]/g, "");
|
|
1956
|
+
if (!/^\d{13,19}$/.test(sanitized))
|
|
1957
|
+
return false;
|
|
1958
|
+
let sum = 0;
|
|
1959
|
+
let isEven = false;
|
|
1960
|
+
for (let i = sanitized.length - 1;i >= 0; i--) {
|
|
1961
|
+
let digit = parseInt(sanitized[i], 10);
|
|
1962
|
+
if (isEven) {
|
|
1963
|
+
digit *= 2;
|
|
1964
|
+
if (digit > 9)
|
|
1965
|
+
digit -= 9;
|
|
1966
|
+
}
|
|
1967
|
+
sum += digit;
|
|
1968
|
+
isEven = !isEven;
|
|
1969
|
+
}
|
|
1970
|
+
return sum % 10 === 0;
|
|
1971
|
+
}, "\u5FC5\u987B\u662F\u6709\u6548\u7684\u4FE1\u7528\u5361\u53F7");
|
|
1972
|
+
IsHexColor = createSimpleValidator("isHexColor", (value) => typeof value === "string" && /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(value), "\u5FC5\u987B\u662F\u6709\u6548\u7684\u5341\u516D\u8FDB\u5236\u989C\u8272\u503C");
|
|
1973
|
+
IsMacAddress = createSimpleValidator("isMacAddress", (value) => typeof value === "string" && /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/.test(value), "\u5FC5\u987B\u662F\u6709\u6548\u7684 MAC \u5730\u5740");
|
|
1974
|
+
IsSemVer = createSimpleValidator("isSemVer", (value) => typeof value === "string" && /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/.test(value), "\u5FC5\u987B\u662F\u6709\u6548\u7684\u8BED\u4E49\u5316\u7248\u672C\u53F7");
|
|
1975
|
+
IsDivisibleBy = createCustomValidator("isDivisibleBy", (value, divisor) => typeof value === "number" && !Number.isNaN(value) && value % divisor === 0, (divisor) => `\u5FC5\u987B\u80FD\u88AB ${divisor} \u6574\u9664`);
|
|
1976
|
+
IsBetween = createCustomValidator("isBetween", (value, min, max) => typeof value === "number" && value >= min && value <= max, (min, max) => `\u5FC5\u987B\u5728 ${min} \u548C ${max} \u4E4B\u95F4`);
|
|
1977
|
+
Contains = createCustomValidator("contains", (value, substring) => typeof value === "string" && value.includes(substring), (substring) => `\u5FC5\u987B\u5305\u542B "${substring}"`);
|
|
1978
|
+
NotContains = createCustomValidator("notContains", (value, substring) => typeof value === "string" && !value.includes(substring), (substring) => `\u4E0D\u80FD\u5305\u542B "${substring}"`);
|
|
1979
|
+
});
|
|
1980
|
+
|
|
1981
|
+
// src/validation/class-validator.ts
|
|
1982
|
+
import"reflect-metadata";
|
|
1983
|
+
function ValidateClass() {
|
|
1984
|
+
return (target) => {
|
|
1985
|
+
Reflect.defineMetadata(VALIDATE_CLASS_METADATA_KEY, true, target);
|
|
1986
|
+
};
|
|
1987
|
+
}
|
|
1988
|
+
function Property(...rules) {
|
|
1989
|
+
return (target, propertyKey) => {
|
|
1990
|
+
if (typeof propertyKey === "symbol") {
|
|
1991
|
+
throw new Error("@Property decorator does not support symbol property keys");
|
|
1992
|
+
}
|
|
1993
|
+
const existingMetadata = Reflect.getMetadata(CLASS_VALIDATION_METADATA_KEY, target.constructor) ?? [];
|
|
1994
|
+
let propertyMetadata = existingMetadata.find((m) => m.property === propertyKey);
|
|
1995
|
+
if (!propertyMetadata) {
|
|
1996
|
+
propertyMetadata = { property: propertyKey, rules: [] };
|
|
1997
|
+
existingMetadata.push(propertyMetadata);
|
|
1998
|
+
}
|
|
1999
|
+
propertyMetadata.rules.push(...rules);
|
|
2000
|
+
Reflect.defineMetadata(CLASS_VALIDATION_METADATA_KEY, existingMetadata, target.constructor);
|
|
2001
|
+
};
|
|
2002
|
+
}
|
|
2003
|
+
function getClassValidationMetadata(target) {
|
|
2004
|
+
return Reflect.getMetadata(CLASS_VALIDATION_METADATA_KEY, target) ?? [];
|
|
2005
|
+
}
|
|
2006
|
+
function isValidateClass(target) {
|
|
2007
|
+
return Reflect.getMetadata(VALIDATE_CLASS_METADATA_KEY, target) === true;
|
|
2008
|
+
}
|
|
2009
|
+
function validateValue(value, rules, property, fullObject) {
|
|
2010
|
+
const issues = [];
|
|
2011
|
+
let currentValue = value;
|
|
2012
|
+
let shouldSkip2 = false;
|
|
2013
|
+
for (const rule of rules) {
|
|
2014
|
+
if (rule.condition && !rule.condition(currentValue, fullObject)) {
|
|
2015
|
+
shouldSkip2 = true;
|
|
2016
|
+
break;
|
|
2017
|
+
}
|
|
2018
|
+
if (rule.optional && (currentValue === undefined || currentValue === null)) {
|
|
2019
|
+
shouldSkip2 = true;
|
|
2020
|
+
break;
|
|
2021
|
+
}
|
|
2022
|
+
if (rule.transform) {
|
|
2023
|
+
currentValue = rule.transform(currentValue);
|
|
2024
|
+
}
|
|
2025
|
+
if (rule.nested) {
|
|
2026
|
+
if (rule.each && Array.isArray(currentValue)) {
|
|
2027
|
+
for (let i = 0;i < currentValue.length; i++) {
|
|
2028
|
+
const item = currentValue[i];
|
|
2029
|
+
if (typeof item === "object" && item !== null && rule.nestedType) {
|
|
2030
|
+
const nestedIssues = validateObjectInternal(item, rule.nestedType, `${property}[${i}]`);
|
|
2031
|
+
issues.push(...nestedIssues);
|
|
2032
|
+
}
|
|
2033
|
+
}
|
|
2034
|
+
} else if (typeof currentValue === "object" && currentValue !== null && rule.nestedType) {
|
|
2035
|
+
const nestedIssues = validateObjectInternal(currentValue, rule.nestedType, property);
|
|
2036
|
+
issues.push(...nestedIssues);
|
|
2037
|
+
}
|
|
2038
|
+
continue;
|
|
2039
|
+
}
|
|
2040
|
+
const passed = rule.validate(currentValue, fullObject);
|
|
2041
|
+
if (!passed) {
|
|
2042
|
+
issues.push({
|
|
2043
|
+
property,
|
|
2044
|
+
rule: rule.name,
|
|
2045
|
+
message: rule.message,
|
|
2046
|
+
value: currentValue
|
|
2047
|
+
});
|
|
2048
|
+
}
|
|
2049
|
+
}
|
|
2050
|
+
return shouldSkip2 ? [] : issues;
|
|
2051
|
+
}
|
|
2052
|
+
function validateObjectInternal(obj, targetClass, prefix = "") {
|
|
2053
|
+
const metadata = getClassValidationMetadata(targetClass);
|
|
2054
|
+
const issues = [];
|
|
2055
|
+
if (typeof obj !== "object" || obj === null) {
|
|
2056
|
+
issues.push({
|
|
2057
|
+
property: prefix || "root",
|
|
2058
|
+
rule: "isObject",
|
|
2059
|
+
message: "\u5FC5\u987B\u662F\u5BF9\u8C61",
|
|
2060
|
+
value: obj
|
|
2061
|
+
});
|
|
2062
|
+
return issues;
|
|
2063
|
+
}
|
|
2064
|
+
const objRecord = obj;
|
|
2065
|
+
for (const meta of metadata) {
|
|
2066
|
+
const propertyPath = prefix ? `${prefix}.${meta.property}` : meta.property;
|
|
2067
|
+
const value = objRecord[meta.property];
|
|
2068
|
+
const propertyIssues = validateValue(value, meta.rules, propertyPath, obj);
|
|
2069
|
+
issues.push(...propertyIssues);
|
|
2070
|
+
}
|
|
2071
|
+
return issues;
|
|
2072
|
+
}
|
|
2073
|
+
function validateObject(obj, targetClass, options = {}) {
|
|
2074
|
+
const issues = validateObjectInternal(obj, targetClass);
|
|
2075
|
+
if (options.stopAtFirstError && issues.length > 0) {
|
|
2076
|
+
throw new ValidationError("Validation failed", [issues[0]]);
|
|
2077
|
+
}
|
|
2078
|
+
if (issues.length > 0) {
|
|
2079
|
+
throw new ValidationError("Validation failed", issues);
|
|
2080
|
+
}
|
|
2081
|
+
}
|
|
2082
|
+
function validateObjectSync(obj, targetClass, options = {}) {
|
|
2083
|
+
const issues = validateObjectInternal(obj, targetClass);
|
|
2084
|
+
if (options.stopAtFirstError && issues.length > 0) {
|
|
2085
|
+
return { valid: false, issues: [issues[0]] };
|
|
2086
|
+
}
|
|
2087
|
+
return { valid: issues.length === 0, issues };
|
|
2088
|
+
}
|
|
2089
|
+
function NestedProperty(nestedClass) {
|
|
2090
|
+
return (target, propertyKey) => {
|
|
2091
|
+
if (typeof propertyKey === "symbol") {
|
|
2092
|
+
throw new Error("@NestedProperty decorator does not support symbol property keys");
|
|
2093
|
+
}
|
|
2094
|
+
const existingMetadata = Reflect.getMetadata(CLASS_VALIDATION_METADATA_KEY, target.constructor) ?? [];
|
|
2095
|
+
let propertyMetadata = existingMetadata.find((m) => m.property === propertyKey);
|
|
2096
|
+
if (!propertyMetadata) {
|
|
2097
|
+
propertyMetadata = { property: propertyKey, rules: [] };
|
|
2098
|
+
existingMetadata.push(propertyMetadata);
|
|
2099
|
+
}
|
|
2100
|
+
propertyMetadata.rules.push({
|
|
2101
|
+
name: "validateNested",
|
|
2102
|
+
message: "\u5D4C\u5957\u5BF9\u8C61\u9A8C\u8BC1\u5931\u8D25",
|
|
2103
|
+
nested: true,
|
|
2104
|
+
nestedType: nestedClass,
|
|
2105
|
+
validate: (value) => typeof value === "object" && value !== null && !Array.isArray(value)
|
|
2106
|
+
});
|
|
2107
|
+
Reflect.defineMetadata(CLASS_VALIDATION_METADATA_KEY, existingMetadata, target.constructor);
|
|
2108
|
+
};
|
|
2109
|
+
}
|
|
2110
|
+
function ArrayNestedProperty(nestedClass) {
|
|
2111
|
+
return (target, propertyKey) => {
|
|
2112
|
+
if (typeof propertyKey === "symbol") {
|
|
2113
|
+
throw new Error("@ArrayNestedProperty decorator does not support symbol property keys");
|
|
2114
|
+
}
|
|
2115
|
+
const existingMetadata = Reflect.getMetadata(CLASS_VALIDATION_METADATA_KEY, target.constructor) ?? [];
|
|
2116
|
+
let propertyMetadata = existingMetadata.find((m) => m.property === propertyKey);
|
|
2117
|
+
if (!propertyMetadata) {
|
|
2118
|
+
propertyMetadata = { property: propertyKey, rules: [] };
|
|
2119
|
+
existingMetadata.push(propertyMetadata);
|
|
2120
|
+
}
|
|
2121
|
+
propertyMetadata.rules.push({
|
|
2122
|
+
name: "validateNestedArray",
|
|
2123
|
+
message: "\u6570\u7EC4\u5143\u7D20\u9A8C\u8BC1\u5931\u8D25",
|
|
2124
|
+
nested: true,
|
|
2125
|
+
nestedType: nestedClass,
|
|
2126
|
+
each: true,
|
|
2127
|
+
validate: (value) => Array.isArray(value)
|
|
2128
|
+
});
|
|
2129
|
+
Reflect.defineMetadata(CLASS_VALIDATION_METADATA_KEY, existingMetadata, target.constructor);
|
|
2130
|
+
};
|
|
2131
|
+
}
|
|
2132
|
+
var CLASS_VALIDATION_METADATA_KEY, PROPERTY_VALIDATION_METADATA_KEY, VALIDATE_CLASS_METADATA_KEY;
|
|
2133
|
+
var init_class_validator = __esm(() => {
|
|
2134
|
+
init_errors();
|
|
2135
|
+
CLASS_VALIDATION_METADATA_KEY = Symbol("validation:class");
|
|
2136
|
+
PROPERTY_VALIDATION_METADATA_KEY = Symbol("validation:property");
|
|
2137
|
+
VALIDATE_CLASS_METADATA_KEY = Symbol("validation:validateClass");
|
|
2138
|
+
});
|
|
2139
|
+
|
|
1491
2140
|
// src/validation/index.ts
|
|
1492
2141
|
var init_validation = __esm(() => {
|
|
1493
2142
|
init_decorators5();
|
|
1494
2143
|
init_validator();
|
|
1495
2144
|
init_errors();
|
|
2145
|
+
init_common();
|
|
2146
|
+
init_custom_validator();
|
|
2147
|
+
init_class_validator();
|
|
1496
2148
|
});
|
|
1497
2149
|
|
|
1498
2150
|
// src/error/error-codes.ts
|
|
@@ -2571,6 +3223,12 @@ var init_interceptor = __esm(() => {
|
|
|
2571
3223
|
});
|
|
2572
3224
|
|
|
2573
3225
|
// src/controller/controller.ts
|
|
3226
|
+
var exports_controller = {};
|
|
3227
|
+
__export(exports_controller, {
|
|
3228
|
+
ControllerRegistry: () => ControllerRegistry,
|
|
3229
|
+
Controller: () => Controller,
|
|
3230
|
+
CONTROLLER_METADATA_KEY: () => CONTROLLER_METADATA_KEY
|
|
3231
|
+
});
|
|
2574
3232
|
import"reflect-metadata";
|
|
2575
3233
|
function Controller(path = "") {
|
|
2576
3234
|
return function(target) {
|
|
@@ -3632,12 +4290,14 @@ init_controller();
|
|
|
3632
4290
|
init_container();
|
|
3633
4291
|
init_types();
|
|
3634
4292
|
init_module();
|
|
4293
|
+
init_decorators();
|
|
3635
4294
|
|
|
3636
4295
|
class ModuleRegistry {
|
|
3637
4296
|
static instance;
|
|
3638
4297
|
moduleRefs = new Map;
|
|
3639
4298
|
processing = new Set;
|
|
3640
4299
|
rootContainer;
|
|
4300
|
+
globalModules = new Set;
|
|
3641
4301
|
static getInstance() {
|
|
3642
4302
|
if (!ModuleRegistry.instance) {
|
|
3643
4303
|
ModuleRegistry.instance = new ModuleRegistry;
|
|
@@ -3656,8 +4316,12 @@ class ModuleRegistry {
|
|
|
3656
4316
|
clear() {
|
|
3657
4317
|
this.moduleRefs.clear();
|
|
3658
4318
|
this.processing.clear();
|
|
4319
|
+
this.globalModules.clear();
|
|
3659
4320
|
this.rootContainer = undefined;
|
|
3660
4321
|
}
|
|
4322
|
+
getGlobalModules() {
|
|
4323
|
+
return Array.from(this.globalModules);
|
|
4324
|
+
}
|
|
3661
4325
|
processModule(moduleClass, parentContainer) {
|
|
3662
4326
|
if (this.processing.has(moduleClass)) {
|
|
3663
4327
|
throw new Error(`Circular module dependency detected for ${moduleClass.name}`);
|
|
@@ -3680,6 +4344,7 @@ class ModuleRegistry {
|
|
|
3680
4344
|
throw new Error("ModuleRegistry is not initialized with a root container");
|
|
3681
4345
|
}
|
|
3682
4346
|
const metadata = getModuleMetadata(moduleClass);
|
|
4347
|
+
const isGlobal = isGlobalModule(moduleClass);
|
|
3683
4348
|
const container = new Container({ parent: this.rootContainer });
|
|
3684
4349
|
this.registerProviders(container, metadata.providers);
|
|
3685
4350
|
ref = {
|
|
@@ -3689,12 +4354,25 @@ class ModuleRegistry {
|
|
|
3689
4354
|
controllersRegistered: false,
|
|
3690
4355
|
attachedParents: new Set,
|
|
3691
4356
|
extensions: metadata.extensions ?? [],
|
|
3692
|
-
middlewares: metadata.middlewares ?? []
|
|
4357
|
+
middlewares: metadata.middlewares ?? [],
|
|
4358
|
+
isGlobal
|
|
3693
4359
|
};
|
|
3694
4360
|
this.registerControllers(ref);
|
|
3695
4361
|
this.moduleRefs.set(moduleClass, ref);
|
|
4362
|
+
if (isGlobal) {
|
|
4363
|
+
this.globalModules.add(moduleClass);
|
|
4364
|
+
this.registerGlobalExports(ref);
|
|
4365
|
+
}
|
|
3696
4366
|
return ref;
|
|
3697
4367
|
}
|
|
4368
|
+
registerGlobalExports(moduleRef) {
|
|
4369
|
+
if (!this.rootContainer) {
|
|
4370
|
+
return;
|
|
4371
|
+
}
|
|
4372
|
+
for (const exportedToken of moduleRef.metadata.exports) {
|
|
4373
|
+
this.registerExport(this.rootContainer, moduleRef, exportedToken);
|
|
4374
|
+
}
|
|
4375
|
+
}
|
|
3698
4376
|
registerProviders(container, providers) {
|
|
3699
4377
|
for (const provider of providers) {
|
|
3700
4378
|
if (typeof provider === "function") {
|
|
@@ -5476,6 +6154,232 @@ function checkRoles(target, propertyKey, userRoles = []) {
|
|
|
5476
6154
|
return config.roles.some((role) => userRoles.includes(role));
|
|
5477
6155
|
}
|
|
5478
6156
|
|
|
6157
|
+
// src/security/guards/decorators.ts
|
|
6158
|
+
import"reflect-metadata";
|
|
6159
|
+
|
|
6160
|
+
// src/security/guards/types.ts
|
|
6161
|
+
var GUARDS_METADATA_KEY = Symbol("@dangao/bun-server:guards");
|
|
6162
|
+
var GUARD_REGISTRY_TOKEN = Symbol("@dangao/bun-server:guard-registry");
|
|
6163
|
+
var ROLES_METADATA_KEY = Symbol("@dangao/bun-server:roles");
|
|
6164
|
+
|
|
6165
|
+
// src/security/guards/decorators.ts
|
|
6166
|
+
function UseGuards(...guards) {
|
|
6167
|
+
return (target, propertyKey, descriptor) => {
|
|
6168
|
+
if (propertyKey !== undefined) {
|
|
6169
|
+
const existingGuards = Reflect.getMetadata(GUARDS_METADATA_KEY, target, propertyKey) || [];
|
|
6170
|
+
Reflect.defineMetadata(GUARDS_METADATA_KEY, [...existingGuards, ...guards], target, propertyKey);
|
|
6171
|
+
} else {
|
|
6172
|
+
const existingGuards = Reflect.getMetadata(GUARDS_METADATA_KEY, target) || [];
|
|
6173
|
+
Reflect.defineMetadata(GUARDS_METADATA_KEY, [...existingGuards, ...guards], target);
|
|
6174
|
+
}
|
|
6175
|
+
};
|
|
6176
|
+
}
|
|
6177
|
+
function Roles(...roles) {
|
|
6178
|
+
return (target, propertyKey, descriptor) => {
|
|
6179
|
+
if (propertyKey !== undefined) {
|
|
6180
|
+
Reflect.defineMetadata(ROLES_METADATA_KEY, roles, target, propertyKey);
|
|
6181
|
+
} else {
|
|
6182
|
+
Reflect.defineMetadata(ROLES_METADATA_KEY, roles, target);
|
|
6183
|
+
}
|
|
6184
|
+
};
|
|
6185
|
+
}
|
|
6186
|
+
function getGuardsMetadata(target, propertyKey) {
|
|
6187
|
+
if (target === null || target === undefined) {
|
|
6188
|
+
return [];
|
|
6189
|
+
}
|
|
6190
|
+
if (typeof target !== "object" && typeof target !== "function") {
|
|
6191
|
+
return [];
|
|
6192
|
+
}
|
|
6193
|
+
if (propertyKey !== undefined) {
|
|
6194
|
+
return Reflect.getMetadata(GUARDS_METADATA_KEY, target, propertyKey) || [];
|
|
6195
|
+
}
|
|
6196
|
+
return Reflect.getMetadata(GUARDS_METADATA_KEY, target) || [];
|
|
6197
|
+
}
|
|
6198
|
+
function getRolesMetadata(target, propertyKey) {
|
|
6199
|
+
if (propertyKey !== undefined) {
|
|
6200
|
+
return Reflect.getMetadata(ROLES_METADATA_KEY, target, propertyKey) || [];
|
|
6201
|
+
}
|
|
6202
|
+
return Reflect.getMetadata(ROLES_METADATA_KEY, target) || [];
|
|
6203
|
+
}
|
|
6204
|
+
|
|
6205
|
+
// src/security/guards/guard-registry.ts
|
|
6206
|
+
init_http_exception();
|
|
6207
|
+
init_error_codes();
|
|
6208
|
+
|
|
6209
|
+
class GuardRegistry {
|
|
6210
|
+
globalGuards = [];
|
|
6211
|
+
guardInstances = new Map;
|
|
6212
|
+
addGlobalGuards(...guards) {
|
|
6213
|
+
this.globalGuards.push(...guards);
|
|
6214
|
+
}
|
|
6215
|
+
getGlobalGuards() {
|
|
6216
|
+
return [...this.globalGuards];
|
|
6217
|
+
}
|
|
6218
|
+
clearGlobalGuards() {
|
|
6219
|
+
this.globalGuards = [];
|
|
6220
|
+
this.guardInstances.clear();
|
|
6221
|
+
}
|
|
6222
|
+
resolveGuard(guard, container) {
|
|
6223
|
+
if (typeof guard !== "function") {
|
|
6224
|
+
return guard;
|
|
6225
|
+
}
|
|
6226
|
+
const cached = this.guardInstances.get(guard);
|
|
6227
|
+
if (cached) {
|
|
6228
|
+
return cached;
|
|
6229
|
+
}
|
|
6230
|
+
try {
|
|
6231
|
+
if (container.isRegistered(guard)) {
|
|
6232
|
+
const instance2 = container.resolve(guard);
|
|
6233
|
+
this.guardInstances.set(guard, instance2);
|
|
6234
|
+
return instance2;
|
|
6235
|
+
}
|
|
6236
|
+
} catch {}
|
|
6237
|
+
const GuardClass = guard;
|
|
6238
|
+
const instance = new GuardClass;
|
|
6239
|
+
this.guardInstances.set(guard, instance);
|
|
6240
|
+
return instance;
|
|
6241
|
+
}
|
|
6242
|
+
getControllerGuards(controllerClass) {
|
|
6243
|
+
return getGuardsMetadata(controllerClass);
|
|
6244
|
+
}
|
|
6245
|
+
getMethodGuards(controllerClass, methodName) {
|
|
6246
|
+
return getGuardsMetadata(controllerClass.prototype, methodName);
|
|
6247
|
+
}
|
|
6248
|
+
collectGuards(controllerClass, methodName) {
|
|
6249
|
+
const globalGuards = this.getGlobalGuards();
|
|
6250
|
+
const controllerGuards = this.getControllerGuards(controllerClass);
|
|
6251
|
+
const methodGuards = this.getMethodGuards(controllerClass, methodName);
|
|
6252
|
+
return [...globalGuards, ...controllerGuards, ...methodGuards];
|
|
6253
|
+
}
|
|
6254
|
+
async executeGuards(context, container) {
|
|
6255
|
+
const controllerClass = context.getClass();
|
|
6256
|
+
const methodName = context.getMethodName();
|
|
6257
|
+
const guards = this.collectGuards(controllerClass, methodName);
|
|
6258
|
+
if (guards.length === 0) {
|
|
6259
|
+
return true;
|
|
6260
|
+
}
|
|
6261
|
+
for (const guard of guards) {
|
|
6262
|
+
const guardInstance = this.resolveGuard(guard, container);
|
|
6263
|
+
const result = await guardInstance.canActivate(context);
|
|
6264
|
+
if (!result) {
|
|
6265
|
+
const guardName = typeof guard === "function" ? guard.name : guard.constructor.name;
|
|
6266
|
+
throw new ForbiddenException(`Access denied by guard: ${guardName}`, { guard: guardName }, "AUTH_INSUFFICIENT_PERMISSIONS" /* AUTH_INSUFFICIENT_PERMISSIONS */);
|
|
6267
|
+
}
|
|
6268
|
+
}
|
|
6269
|
+
return true;
|
|
6270
|
+
}
|
|
6271
|
+
}
|
|
6272
|
+
|
|
6273
|
+
// src/security/guards/execution-context.ts
|
|
6274
|
+
import"reflect-metadata";
|
|
6275
|
+
|
|
6276
|
+
class HttpArgumentsHostImpl {
|
|
6277
|
+
ctx;
|
|
6278
|
+
responseBuilder;
|
|
6279
|
+
constructor(ctx, responseBuilder) {
|
|
6280
|
+
this.ctx = ctx;
|
|
6281
|
+
this.responseBuilder = responseBuilder;
|
|
6282
|
+
}
|
|
6283
|
+
getRequest() {
|
|
6284
|
+
return this.ctx;
|
|
6285
|
+
}
|
|
6286
|
+
getResponse() {
|
|
6287
|
+
return this.responseBuilder;
|
|
6288
|
+
}
|
|
6289
|
+
}
|
|
6290
|
+
|
|
6291
|
+
class WsArgumentsHostImpl {
|
|
6292
|
+
client;
|
|
6293
|
+
data;
|
|
6294
|
+
constructor(client, data) {
|
|
6295
|
+
this.client = client;
|
|
6296
|
+
this.data = data;
|
|
6297
|
+
}
|
|
6298
|
+
getClient() {
|
|
6299
|
+
return this.client;
|
|
6300
|
+
}
|
|
6301
|
+
getData() {
|
|
6302
|
+
return this.data;
|
|
6303
|
+
}
|
|
6304
|
+
}
|
|
6305
|
+
|
|
6306
|
+
class ExecutionContextImpl {
|
|
6307
|
+
ctx;
|
|
6308
|
+
controllerClass;
|
|
6309
|
+
methodName;
|
|
6310
|
+
handler;
|
|
6311
|
+
args;
|
|
6312
|
+
httpHost;
|
|
6313
|
+
wsHost;
|
|
6314
|
+
constructor(ctx, controllerClass, methodName, handler, args = [], responseBuilder) {
|
|
6315
|
+
this.ctx = ctx;
|
|
6316
|
+
this.controllerClass = controllerClass;
|
|
6317
|
+
this.methodName = methodName;
|
|
6318
|
+
this.handler = handler;
|
|
6319
|
+
this.args = args;
|
|
6320
|
+
this.httpHost = new HttpArgumentsHostImpl(ctx, responseBuilder);
|
|
6321
|
+
}
|
|
6322
|
+
setWsContext(client, data) {
|
|
6323
|
+
this.wsHost = new WsArgumentsHostImpl(client, data);
|
|
6324
|
+
}
|
|
6325
|
+
switchToHttp() {
|
|
6326
|
+
return this.httpHost;
|
|
6327
|
+
}
|
|
6328
|
+
switchToWs() {
|
|
6329
|
+
if (!this.wsHost) {
|
|
6330
|
+
throw new Error("WebSocket context is not available");
|
|
6331
|
+
}
|
|
6332
|
+
return this.wsHost;
|
|
6333
|
+
}
|
|
6334
|
+
getClass() {
|
|
6335
|
+
return this.controllerClass;
|
|
6336
|
+
}
|
|
6337
|
+
getHandler() {
|
|
6338
|
+
return this.handler;
|
|
6339
|
+
}
|
|
6340
|
+
getMethodName() {
|
|
6341
|
+
return this.methodName;
|
|
6342
|
+
}
|
|
6343
|
+
getMetadata(key) {
|
|
6344
|
+
const methodMetadata = Reflect.getMetadata(key, this.controllerClass.prototype, this.methodName);
|
|
6345
|
+
if (methodMetadata !== undefined) {
|
|
6346
|
+
return methodMetadata;
|
|
6347
|
+
}
|
|
6348
|
+
return Reflect.getMetadata(key, this.controllerClass);
|
|
6349
|
+
}
|
|
6350
|
+
getArgs() {
|
|
6351
|
+
return this.args;
|
|
6352
|
+
}
|
|
6353
|
+
}
|
|
6354
|
+
|
|
6355
|
+
// src/security/guards/reflector.ts
|
|
6356
|
+
import"reflect-metadata";
|
|
6357
|
+
|
|
6358
|
+
class Reflector {
|
|
6359
|
+
get(metadataKey, target) {
|
|
6360
|
+
return Reflect.getMetadata(metadataKey, target);
|
|
6361
|
+
}
|
|
6362
|
+
getFromClass(metadataKey, target) {
|
|
6363
|
+
return Reflect.getMetadata(metadataKey, target);
|
|
6364
|
+
}
|
|
6365
|
+
getFromMethod(metadataKey, target, propertyKey) {
|
|
6366
|
+
return Reflect.getMetadata(metadataKey, target, propertyKey);
|
|
6367
|
+
}
|
|
6368
|
+
getAllAndMerge(metadataKey, target, propertyKey) {
|
|
6369
|
+
const classMetadata = this.getFromClass(metadataKey, target) || [];
|
|
6370
|
+
const methodMetadata = this.getFromMethod(metadataKey, target.prototype, propertyKey) || [];
|
|
6371
|
+
return [...classMetadata, ...methodMetadata];
|
|
6372
|
+
}
|
|
6373
|
+
getAllAndOverride(metadataKey, target, propertyKey) {
|
|
6374
|
+
const methodMetadata = this.getFromMethod(metadataKey, target.prototype, propertyKey);
|
|
6375
|
+
if (methodMetadata !== undefined) {
|
|
6376
|
+
return methodMetadata;
|
|
6377
|
+
}
|
|
6378
|
+
return this.getFromClass(metadataKey, target);
|
|
6379
|
+
}
|
|
6380
|
+
}
|
|
6381
|
+
var REFLECTOR_TOKEN = Symbol("@dangao/bun-server:reflector");
|
|
6382
|
+
|
|
5479
6383
|
// src/security/filter.ts
|
|
5480
6384
|
function createSecurityFilter(config) {
|
|
5481
6385
|
const {
|
|
@@ -5483,8 +6387,24 @@ function createSecurityFilter(config) {
|
|
|
5483
6387
|
accessDecisionManager = new RoleBasedAccessDecisionManager,
|
|
5484
6388
|
excludePaths = [],
|
|
5485
6389
|
defaultAuthRequired = true,
|
|
5486
|
-
extractToken
|
|
6390
|
+
extractToken,
|
|
6391
|
+
container: initialContainer,
|
|
6392
|
+
guardRegistry
|
|
5487
6393
|
} = config;
|
|
6394
|
+
const registry = guardRegistry || new GuardRegistry;
|
|
6395
|
+
let cachedContainer = initialContainer || null;
|
|
6396
|
+
const getContainer = () => {
|
|
6397
|
+
if (cachedContainer) {
|
|
6398
|
+
return cachedContainer;
|
|
6399
|
+
}
|
|
6400
|
+
try {
|
|
6401
|
+
const { ControllerRegistry: ControllerRegistry2 } = (init_controller(), __toCommonJS(exports_controller));
|
|
6402
|
+
cachedContainer = ControllerRegistry2.getInstance().getContainer();
|
|
6403
|
+
return cachedContainer;
|
|
6404
|
+
} catch {
|
|
6405
|
+
return null;
|
|
6406
|
+
}
|
|
6407
|
+
};
|
|
5488
6408
|
return async (ctx, next) => {
|
|
5489
6409
|
return SecurityContextHolder.runWithContext(async () => {
|
|
5490
6410
|
const path = ctx.path || ctx.request.url.split("?")[0].replace(/^https?:\/\/[^/]+/, "");
|
|
@@ -5505,11 +6425,23 @@ function createSecurityFilter(config) {
|
|
|
5505
6425
|
securityContext.setAuthentication(authentication);
|
|
5506
6426
|
}
|
|
5507
6427
|
}
|
|
6428
|
+
ctx.security = securityContext;
|
|
6429
|
+
ctx.auth = {
|
|
6430
|
+
isAuthenticated: securityContext.isAuthenticated(),
|
|
6431
|
+
user: securityContext.getPrincipal(),
|
|
6432
|
+
payload: securityContext.authentication?.details
|
|
6433
|
+
};
|
|
5508
6434
|
const handler = ctx.routeHandler;
|
|
5509
6435
|
if (handler) {
|
|
5510
6436
|
const controllerClass = handler.controller;
|
|
5511
6437
|
const controllerTarget = controllerClass && controllerClass.prototype || controllerClass;
|
|
5512
6438
|
const method = handler.method;
|
|
6439
|
+
const container = getContainer();
|
|
6440
|
+
if (container && typeof controllerClass === "function") {
|
|
6441
|
+
const methodHandler = controllerTarget[method];
|
|
6442
|
+
const executionContext = new ExecutionContextImpl(ctx, controllerClass, method, methodHandler || (() => {}));
|
|
6443
|
+
await registry.executeGuards(executionContext, container);
|
|
6444
|
+
}
|
|
5513
6445
|
if (requiresAuth(controllerTarget, method)) {
|
|
5514
6446
|
const authentication = securityContext.authentication;
|
|
5515
6447
|
if (!authentication || !authentication.authenticated) {
|
|
@@ -5527,12 +6459,6 @@ function createSecurityFilter(config) {
|
|
|
5527
6459
|
} else if (defaultAuthRequired && !securityContext.isAuthenticated()) {
|
|
5528
6460
|
throw new UnauthorizedException("Authentication required", undefined, "AUTH_REQUIRED" /* AUTH_REQUIRED */);
|
|
5529
6461
|
}
|
|
5530
|
-
ctx.security = securityContext;
|
|
5531
|
-
ctx.auth = {
|
|
5532
|
-
isAuthenticated: securityContext.isAuthenticated(),
|
|
5533
|
-
user: securityContext.getPrincipal(),
|
|
5534
|
-
payload: securityContext.authentication?.details
|
|
5535
|
-
};
|
|
5536
6462
|
return await next();
|
|
5537
6463
|
} finally {
|
|
5538
6464
|
SecurityContextHolder.clearContext();
|
|
@@ -5540,6 +6466,22 @@ function createSecurityFilter(config) {
|
|
|
5540
6466
|
});
|
|
5541
6467
|
};
|
|
5542
6468
|
}
|
|
6469
|
+
function getGuardRegistry(container) {
|
|
6470
|
+
if (container.isRegistered(GUARD_REGISTRY_TOKEN)) {
|
|
6471
|
+
return container.resolve(GUARD_REGISTRY_TOKEN);
|
|
6472
|
+
}
|
|
6473
|
+
const registry = new GuardRegistry;
|
|
6474
|
+
container.registerInstance(GUARD_REGISTRY_TOKEN, registry);
|
|
6475
|
+
return registry;
|
|
6476
|
+
}
|
|
6477
|
+
function registerReflector(container) {
|
|
6478
|
+
if (container.isRegistered(REFLECTOR_TOKEN)) {
|
|
6479
|
+
return container.resolve(REFLECTOR_TOKEN);
|
|
6480
|
+
}
|
|
6481
|
+
const reflector = new Reflector;
|
|
6482
|
+
container.registerInstance(REFLECTOR_TOKEN, reflector);
|
|
6483
|
+
return reflector;
|
|
6484
|
+
}
|
|
5543
6485
|
function extractTokenFromHeader(ctx) {
|
|
5544
6486
|
const authHeader = ctx.getHeader("authorization");
|
|
5545
6487
|
if (!authHeader) {
|
|
@@ -6008,6 +6950,8 @@ OAuth2Controller = __legacyDecorateClassTS([
|
|
|
6008
6950
|
], OAuth2Controller);
|
|
6009
6951
|
|
|
6010
6952
|
// src/security/security-module.ts
|
|
6953
|
+
var _guardRegistry = null;
|
|
6954
|
+
|
|
6011
6955
|
class SecurityModule {
|
|
6012
6956
|
static forRoot(config) {
|
|
6013
6957
|
const jwtUtil = new JWTUtil(config.jwt);
|
|
@@ -6016,13 +6960,23 @@ class SecurityModule {
|
|
|
6016
6960
|
const authenticationManager = new AuthenticationManager;
|
|
6017
6961
|
authenticationManager.registerProvider(new JwtAuthenticationProvider(jwtUtil));
|
|
6018
6962
|
authenticationManager.registerProvider(new OAuth2AuthenticationProvider(oauth2Service, jwtUtil));
|
|
6963
|
+
const guardRegistry = new GuardRegistry;
|
|
6964
|
+
if (_guardRegistry) {
|
|
6965
|
+
_guardRegistry.clearGlobalGuards();
|
|
6966
|
+
}
|
|
6967
|
+
_guardRegistry = guardRegistry;
|
|
6968
|
+
if (config.globalGuards && config.globalGuards.length > 0) {
|
|
6969
|
+
guardRegistry.addGlobalGuards(...config.globalGuards);
|
|
6970
|
+
}
|
|
6971
|
+
const reflector = new Reflector;
|
|
6019
6972
|
const securityFilter = createSecurityFilter({
|
|
6020
6973
|
authenticationManager,
|
|
6021
6974
|
excludePaths: [
|
|
6022
6975
|
...config.excludePaths || [],
|
|
6023
6976
|
...config.enableOAuth2Endpoints !== false ? [config.oauth2Prefix || "/oauth2"] : []
|
|
6024
6977
|
],
|
|
6025
|
-
defaultAuthRequired: config.defaultAuthRequired ?? false
|
|
6978
|
+
defaultAuthRequired: config.defaultAuthRequired ?? false,
|
|
6979
|
+
guardRegistry
|
|
6026
6980
|
});
|
|
6027
6981
|
const controllers = [];
|
|
6028
6982
|
const providers = [];
|
|
@@ -6039,6 +6993,12 @@ class SecurityModule {
|
|
|
6039
6993
|
}, {
|
|
6040
6994
|
provide: AuthenticationManager,
|
|
6041
6995
|
useValue: authenticationManager
|
|
6996
|
+
}, {
|
|
6997
|
+
provide: GUARD_REGISTRY_TOKEN,
|
|
6998
|
+
useValue: guardRegistry
|
|
6999
|
+
}, {
|
|
7000
|
+
provide: REFLECTOR_TOKEN,
|
|
7001
|
+
useValue: reflector
|
|
6042
7002
|
});
|
|
6043
7003
|
middlewares.push(securityFilter);
|
|
6044
7004
|
const existingMetadata = Reflect.getMetadata(MODULE_METADATA_KEY, SecurityModule) || {};
|
|
@@ -6051,12 +7011,29 @@ class SecurityModule {
|
|
|
6051
7011
|
...existingMetadata.exports || [],
|
|
6052
7012
|
JWT_UTIL_TOKEN,
|
|
6053
7013
|
OAUTH2_SERVICE_TOKEN,
|
|
6054
|
-
AuthenticationManager
|
|
7014
|
+
AuthenticationManager,
|
|
7015
|
+
GUARD_REGISTRY_TOKEN,
|
|
7016
|
+
REFLECTOR_TOKEN
|
|
6055
7017
|
]
|
|
6056
7018
|
};
|
|
6057
7019
|
Reflect.defineMetadata(MODULE_METADATA_KEY, metadata, SecurityModule);
|
|
6058
7020
|
return SecurityModule;
|
|
6059
7021
|
}
|
|
7022
|
+
static getGuardRegistry() {
|
|
7023
|
+
return _guardRegistry;
|
|
7024
|
+
}
|
|
7025
|
+
static addGlobalGuards(...guards) {
|
|
7026
|
+
if (_guardRegistry) {
|
|
7027
|
+
_guardRegistry.addGlobalGuards(...guards);
|
|
7028
|
+
}
|
|
7029
|
+
}
|
|
7030
|
+
static reset() {
|
|
7031
|
+
if (_guardRegistry) {
|
|
7032
|
+
_guardRegistry.clearGlobalGuards();
|
|
7033
|
+
}
|
|
7034
|
+
_guardRegistry = null;
|
|
7035
|
+
Reflect.deleteMetadata(MODULE_METADATA_KEY, SecurityModule);
|
|
7036
|
+
}
|
|
6060
7037
|
}
|
|
6061
7038
|
SecurityModule = __legacyDecorateClassTS([
|
|
6062
7039
|
Module({
|
|
@@ -6065,6 +7042,94 @@ SecurityModule = __legacyDecorateClassTS([
|
|
|
6065
7042
|
middlewares: []
|
|
6066
7043
|
})
|
|
6067
7044
|
], SecurityModule);
|
|
7045
|
+
// src/security/guards/builtin/auth-guard.ts
|
|
7046
|
+
init_decorators();
|
|
7047
|
+
init_http_exception();
|
|
7048
|
+
init_error_codes();
|
|
7049
|
+
class AuthGuard {
|
|
7050
|
+
canActivate(context) {
|
|
7051
|
+
const securityContext = SecurityContextHolder.getContext();
|
|
7052
|
+
if (!securityContext.isAuthenticated()) {
|
|
7053
|
+
throw new UnauthorizedException("Authentication required", undefined, "AUTH_REQUIRED" /* AUTH_REQUIRED */);
|
|
7054
|
+
}
|
|
7055
|
+
return true;
|
|
7056
|
+
}
|
|
7057
|
+
}
|
|
7058
|
+
AuthGuard = __legacyDecorateClassTS([
|
|
7059
|
+
Injectable()
|
|
7060
|
+
], AuthGuard);
|
|
7061
|
+
|
|
7062
|
+
class OptionalAuthGuard {
|
|
7063
|
+
canActivate(context) {
|
|
7064
|
+
return true;
|
|
7065
|
+
}
|
|
7066
|
+
}
|
|
7067
|
+
OptionalAuthGuard = __legacyDecorateClassTS([
|
|
7068
|
+
Injectable()
|
|
7069
|
+
], OptionalAuthGuard);
|
|
7070
|
+
// src/security/guards/builtin/roles-guard.ts
|
|
7071
|
+
init_decorators();
|
|
7072
|
+
init_http_exception();
|
|
7073
|
+
init_error_codes();
|
|
7074
|
+
class RolesGuard {
|
|
7075
|
+
reflector;
|
|
7076
|
+
constructor(reflector) {
|
|
7077
|
+
this.reflector = reflector || new Reflector;
|
|
7078
|
+
}
|
|
7079
|
+
canActivate(context) {
|
|
7080
|
+
const requiredRoles = this.reflector.getAllAndMerge(ROLES_METADATA_KEY, context.getClass(), context.getMethodName());
|
|
7081
|
+
if (!requiredRoles || requiredRoles.length === 0) {
|
|
7082
|
+
return true;
|
|
7083
|
+
}
|
|
7084
|
+
const securityContext = SecurityContextHolder.getContext();
|
|
7085
|
+
const authentication = securityContext.authentication;
|
|
7086
|
+
if (!authentication || !authentication.authenticated) {
|
|
7087
|
+
throw new ForbiddenException("Access denied: authentication required for role check", { requiredRoles }, "AUTH_INSUFFICIENT_PERMISSIONS" /* AUTH_INSUFFICIENT_PERMISSIONS */);
|
|
7088
|
+
}
|
|
7089
|
+
const userRoles = authentication.authorities || [];
|
|
7090
|
+
const hasRole = requiredRoles.some((role) => userRoles.includes(role));
|
|
7091
|
+
if (!hasRole) {
|
|
7092
|
+
throw new ForbiddenException(`Access denied: required roles [${requiredRoles.join(", ")}], but user has [${userRoles.join(", ")}]`, { requiredRoles, userRoles }, "AUTH_INSUFFICIENT_PERMISSIONS" /* AUTH_INSUFFICIENT_PERMISSIONS */);
|
|
7093
|
+
}
|
|
7094
|
+
return true;
|
|
7095
|
+
}
|
|
7096
|
+
}
|
|
7097
|
+
RolesGuard = __legacyDecorateClassTS([
|
|
7098
|
+
Injectable(),
|
|
7099
|
+
__legacyDecorateParamTS(0, Inject(REFLECTOR_TOKEN)),
|
|
7100
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
7101
|
+
typeof Reflector === "undefined" ? Object : Reflector
|
|
7102
|
+
])
|
|
7103
|
+
], RolesGuard);
|
|
7104
|
+
function createRolesGuard(options = {}) {
|
|
7105
|
+
const { matchAll = false, getRoles } = options;
|
|
7106
|
+
|
|
7107
|
+
class CustomRolesGuard {
|
|
7108
|
+
reflector = new Reflector;
|
|
7109
|
+
canActivate(context) {
|
|
7110
|
+
const requiredRoles = this.reflector.getAllAndMerge(ROLES_METADATA_KEY, context.getClass(), context.getMethodName());
|
|
7111
|
+
if (!requiredRoles || requiredRoles.length === 0) {
|
|
7112
|
+
return true;
|
|
7113
|
+
}
|
|
7114
|
+
let userRoles;
|
|
7115
|
+
if (getRoles) {
|
|
7116
|
+
userRoles = getRoles(context);
|
|
7117
|
+
} else {
|
|
7118
|
+
const securityContext = SecurityContextHolder.getContext();
|
|
7119
|
+
userRoles = securityContext.authentication?.authorities || [];
|
|
7120
|
+
}
|
|
7121
|
+
const hasRole = matchAll ? requiredRoles.every((role) => userRoles.includes(role)) : requiredRoles.some((role) => userRoles.includes(role));
|
|
7122
|
+
if (!hasRole) {
|
|
7123
|
+
throw new ForbiddenException(`Access denied: required roles [${requiredRoles.join(", ")}], user has [${userRoles.join(", ")}]`, { requiredRoles, userRoles, matchAll }, "AUTH_INSUFFICIENT_PERMISSIONS" /* AUTH_INSUFFICIENT_PERMISSIONS */);
|
|
7124
|
+
}
|
|
7125
|
+
return true;
|
|
7126
|
+
}
|
|
7127
|
+
}
|
|
7128
|
+
CustomRolesGuard = __legacyDecorateClassTS([
|
|
7129
|
+
Injectable()
|
|
7130
|
+
], CustomRolesGuard);
|
|
7131
|
+
return CustomRolesGuard;
|
|
7132
|
+
}
|
|
6068
7133
|
// src/health/health-module.ts
|
|
6069
7134
|
init_module();
|
|
6070
7135
|
|
|
@@ -9511,26 +10576,387 @@ class ServiceMetricsCollector {
|
|
|
9511
10576
|
this.metricsIntegration?.stop();
|
|
9512
10577
|
}
|
|
9513
10578
|
}
|
|
10579
|
+
// src/events/types.ts
|
|
10580
|
+
var EVENT_EMITTER_TOKEN = Symbol("@dangao/bun-server:events:emitter");
|
|
10581
|
+
var EVENT_OPTIONS_TOKEN = Symbol("@dangao/bun-server:events:options");
|
|
10582
|
+
var ON_EVENT_METADATA_KEY = Symbol("@dangao/bun-server:events:on-event");
|
|
10583
|
+
var EVENT_LISTENER_CLASS_METADATA_KEY = Symbol("@dangao/bun-server:events:listener-class");
|
|
10584
|
+
// src/events/service.ts
|
|
10585
|
+
class EventEmitterService {
|
|
10586
|
+
listeners = new Map;
|
|
10587
|
+
options;
|
|
10588
|
+
constructor(options = {}) {
|
|
10589
|
+
this.options = {
|
|
10590
|
+
wildcard: false,
|
|
10591
|
+
delimiter: ".",
|
|
10592
|
+
maxListeners: 10,
|
|
10593
|
+
...options
|
|
10594
|
+
};
|
|
10595
|
+
}
|
|
10596
|
+
emit(event, payload) {
|
|
10597
|
+
const eventName = this.resolveEventName(event);
|
|
10598
|
+
const matchedListeners = this.getMatchedListeners(eventName);
|
|
10599
|
+
if (matchedListeners.length === 0) {
|
|
10600
|
+
return;
|
|
10601
|
+
}
|
|
10602
|
+
const sortedListeners = this.sortListenersByPriority(matchedListeners);
|
|
10603
|
+
for (const { listener, once, async: isAsync } of sortedListeners) {
|
|
10604
|
+
try {
|
|
10605
|
+
const result = listener(payload);
|
|
10606
|
+
if (isAsync && result instanceof Promise) {
|
|
10607
|
+
result.catch((error) => {
|
|
10608
|
+
this.handleError(error, eventName, payload);
|
|
10609
|
+
});
|
|
10610
|
+
}
|
|
10611
|
+
} catch (error) {
|
|
10612
|
+
this.handleError(error, eventName, payload);
|
|
10613
|
+
}
|
|
10614
|
+
if (once) {
|
|
10615
|
+
this.off(eventName, listener);
|
|
10616
|
+
}
|
|
10617
|
+
}
|
|
10618
|
+
}
|
|
10619
|
+
async emitAsync(event, payload) {
|
|
10620
|
+
const eventName = this.resolveEventName(event);
|
|
10621
|
+
const matchedListeners = this.getMatchedListeners(eventName);
|
|
10622
|
+
if (matchedListeners.length === 0) {
|
|
10623
|
+
return;
|
|
10624
|
+
}
|
|
10625
|
+
const sortedListeners = this.sortListenersByPriority(matchedListeners);
|
|
10626
|
+
const promises = [];
|
|
10627
|
+
const toRemove = [];
|
|
10628
|
+
for (const { listener, once } of sortedListeners) {
|
|
10629
|
+
try {
|
|
10630
|
+
const result = listener(payload);
|
|
10631
|
+
if (result instanceof Promise) {
|
|
10632
|
+
promises.push(result.catch((error) => {
|
|
10633
|
+
this.handleError(error, eventName, payload);
|
|
10634
|
+
}));
|
|
10635
|
+
}
|
|
10636
|
+
} catch (error) {
|
|
10637
|
+
this.handleError(error, eventName, payload);
|
|
10638
|
+
}
|
|
10639
|
+
if (once) {
|
|
10640
|
+
toRemove.push(listener);
|
|
10641
|
+
}
|
|
10642
|
+
}
|
|
10643
|
+
if (promises.length > 0) {
|
|
10644
|
+
await Promise.all(promises);
|
|
10645
|
+
}
|
|
10646
|
+
for (const listener of toRemove) {
|
|
10647
|
+
this.off(eventName, listener);
|
|
10648
|
+
}
|
|
10649
|
+
}
|
|
10650
|
+
on(event, listener, options = {}) {
|
|
10651
|
+
const eventName = this.resolveEventName(event);
|
|
10652
|
+
return this.addListener(eventName, listener, false, options);
|
|
10653
|
+
}
|
|
10654
|
+
once(event, listener, options = {}) {
|
|
10655
|
+
const eventName = this.resolveEventName(event);
|
|
10656
|
+
return this.addListener(eventName, listener, true, options);
|
|
10657
|
+
}
|
|
10658
|
+
off(event, listener) {
|
|
10659
|
+
const eventName = this.resolveEventName(event);
|
|
10660
|
+
const eventListeners = this.listeners.get(eventName);
|
|
10661
|
+
if (!eventListeners) {
|
|
10662
|
+
return;
|
|
10663
|
+
}
|
|
10664
|
+
const index = eventListeners.findIndex((l) => l.listener === listener);
|
|
10665
|
+
if (index !== -1) {
|
|
10666
|
+
eventListeners.splice(index, 1);
|
|
10667
|
+
}
|
|
10668
|
+
if (eventListeners.length === 0) {
|
|
10669
|
+
this.listeners.delete(eventName);
|
|
10670
|
+
}
|
|
10671
|
+
}
|
|
10672
|
+
removeAllListeners(event) {
|
|
10673
|
+
if (event !== undefined) {
|
|
10674
|
+
const eventName = this.resolveEventName(event);
|
|
10675
|
+
this.listeners.delete(eventName);
|
|
10676
|
+
} else {
|
|
10677
|
+
this.listeners.clear();
|
|
10678
|
+
}
|
|
10679
|
+
}
|
|
10680
|
+
listenerCount(event) {
|
|
10681
|
+
const eventName = this.resolveEventName(event);
|
|
10682
|
+
const matchedListeners = this.getMatchedListeners(eventName);
|
|
10683
|
+
return matchedListeners.length;
|
|
10684
|
+
}
|
|
10685
|
+
eventNames() {
|
|
10686
|
+
return Array.from(this.listeners.keys());
|
|
10687
|
+
}
|
|
10688
|
+
addListener(event, listener, once, options) {
|
|
10689
|
+
let eventListeners = this.listeners.get(event);
|
|
10690
|
+
if (!eventListeners) {
|
|
10691
|
+
eventListeners = [];
|
|
10692
|
+
this.listeners.set(event, eventListeners);
|
|
10693
|
+
}
|
|
10694
|
+
if (this.options.maxListeners && eventListeners.length >= this.options.maxListeners) {
|
|
10695
|
+
console.warn(`[EventEmitter] Max listeners (${this.options.maxListeners}) exceeded for event: ${String(event)}. ` + "This may indicate a memory leak.");
|
|
10696
|
+
}
|
|
10697
|
+
const registeredListener = {
|
|
10698
|
+
listener,
|
|
10699
|
+
once,
|
|
10700
|
+
priority: options.priority ?? 0,
|
|
10701
|
+
async: options.async ?? false
|
|
10702
|
+
};
|
|
10703
|
+
eventListeners.push(registeredListener);
|
|
10704
|
+
return () => {
|
|
10705
|
+
this.off(event, listener);
|
|
10706
|
+
};
|
|
10707
|
+
}
|
|
10708
|
+
resolveEventName(event) {
|
|
10709
|
+
if (typeof event === "symbol") {
|
|
10710
|
+
return event;
|
|
10711
|
+
}
|
|
10712
|
+
if (this.options.globalPrefix) {
|
|
10713
|
+
return `${this.options.globalPrefix}${this.options.delimiter}${event}`;
|
|
10714
|
+
}
|
|
10715
|
+
return event;
|
|
10716
|
+
}
|
|
10717
|
+
getMatchedListeners(event) {
|
|
10718
|
+
const result = [];
|
|
10719
|
+
const exactListeners = this.listeners.get(event);
|
|
10720
|
+
if (exactListeners) {
|
|
10721
|
+
result.push(...exactListeners);
|
|
10722
|
+
}
|
|
10723
|
+
if (this.options.wildcard && typeof event === "string") {
|
|
10724
|
+
const delimiter = this.options.delimiter ?? ".";
|
|
10725
|
+
const eventParts = event.split(delimiter);
|
|
10726
|
+
for (const [key, listeners] of this.listeners.entries()) {
|
|
10727
|
+
if (typeof key !== "string" || key === event) {
|
|
10728
|
+
continue;
|
|
10729
|
+
}
|
|
10730
|
+
if (this.matchWildcard(eventParts, key.split(delimiter))) {
|
|
10731
|
+
result.push(...listeners);
|
|
10732
|
+
}
|
|
10733
|
+
}
|
|
10734
|
+
}
|
|
10735
|
+
return result;
|
|
10736
|
+
}
|
|
10737
|
+
matchWildcard(eventParts, patternParts) {
|
|
10738
|
+
let eventIndex = 0;
|
|
10739
|
+
let patternIndex = 0;
|
|
10740
|
+
while (patternIndex < patternParts.length) {
|
|
10741
|
+
const pattern = patternParts[patternIndex];
|
|
10742
|
+
if (pattern === "**") {
|
|
10743
|
+
if (patternIndex === patternParts.length - 1) {
|
|
10744
|
+
return true;
|
|
10745
|
+
}
|
|
10746
|
+
for (let i = eventIndex;i <= eventParts.length; i++) {
|
|
10747
|
+
if (this.matchWildcard(eventParts.slice(i), patternParts.slice(patternIndex + 1))) {
|
|
10748
|
+
return true;
|
|
10749
|
+
}
|
|
10750
|
+
}
|
|
10751
|
+
return false;
|
|
10752
|
+
} else if (pattern === "*") {
|
|
10753
|
+
if (eventIndex >= eventParts.length) {
|
|
10754
|
+
return false;
|
|
10755
|
+
}
|
|
10756
|
+
eventIndex++;
|
|
10757
|
+
patternIndex++;
|
|
10758
|
+
} else {
|
|
10759
|
+
if (eventIndex >= eventParts.length || eventParts[eventIndex] !== pattern) {
|
|
10760
|
+
return false;
|
|
10761
|
+
}
|
|
10762
|
+
eventIndex++;
|
|
10763
|
+
patternIndex++;
|
|
10764
|
+
}
|
|
10765
|
+
}
|
|
10766
|
+
return eventIndex === eventParts.length;
|
|
10767
|
+
}
|
|
10768
|
+
sortListenersByPriority(listeners) {
|
|
10769
|
+
return [...listeners].sort((a, b) => b.priority - a.priority);
|
|
10770
|
+
}
|
|
10771
|
+
handleError(error, event, payload) {
|
|
10772
|
+
if (this.options.onError) {
|
|
10773
|
+
this.options.onError(error, event, payload);
|
|
10774
|
+
} else {
|
|
10775
|
+
console.error(`[EventEmitter] Error in listener for event "${String(event)}":`, error);
|
|
10776
|
+
}
|
|
10777
|
+
}
|
|
10778
|
+
}
|
|
10779
|
+
// src/events/decorators.ts
|
|
10780
|
+
import"reflect-metadata";
|
|
10781
|
+
function OnEvent(event, options = {}) {
|
|
10782
|
+
return (target, propertyKey, descriptor) => {
|
|
10783
|
+
const methodName = String(propertyKey);
|
|
10784
|
+
const constructor = target.constructor;
|
|
10785
|
+
const existingMetadata = Reflect.getMetadata(ON_EVENT_METADATA_KEY, constructor) || [];
|
|
10786
|
+
const metadata = {
|
|
10787
|
+
methodName,
|
|
10788
|
+
event,
|
|
10789
|
+
async: options.async ?? false,
|
|
10790
|
+
priority: options.priority ?? 0
|
|
10791
|
+
};
|
|
10792
|
+
Reflect.defineMetadata(ON_EVENT_METADATA_KEY, [...existingMetadata, metadata], constructor);
|
|
10793
|
+
Reflect.defineMetadata(EVENT_LISTENER_CLASS_METADATA_KEY, true, constructor);
|
|
10794
|
+
return descriptor;
|
|
10795
|
+
};
|
|
10796
|
+
}
|
|
10797
|
+
function getOnEventMetadata(target) {
|
|
10798
|
+
return Reflect.getMetadata(ON_EVENT_METADATA_KEY, target);
|
|
10799
|
+
}
|
|
10800
|
+
function isEventListenerClass(target) {
|
|
10801
|
+
return Reflect.getMetadata(EVENT_LISTENER_CLASS_METADATA_KEY, target) === true;
|
|
10802
|
+
}
|
|
10803
|
+
// src/events/event-module.ts
|
|
10804
|
+
init_module();
|
|
10805
|
+
import"reflect-metadata";
|
|
10806
|
+
class EventListenerScanner {
|
|
10807
|
+
eventEmitter;
|
|
10808
|
+
container;
|
|
10809
|
+
constructor(eventEmitter, container) {
|
|
10810
|
+
this.eventEmitter = eventEmitter;
|
|
10811
|
+
this.container = container;
|
|
10812
|
+
}
|
|
10813
|
+
scanAndRegister(listenerClasses) {
|
|
10814
|
+
for (const listenerClass of listenerClasses) {
|
|
10815
|
+
this.registerListenerClass(listenerClass);
|
|
10816
|
+
}
|
|
10817
|
+
}
|
|
10818
|
+
registerListenerClass(listenerClass) {
|
|
10819
|
+
if (!isEventListenerClass(listenerClass)) {
|
|
10820
|
+
return;
|
|
10821
|
+
}
|
|
10822
|
+
const metadata = getOnEventMetadata(listenerClass);
|
|
10823
|
+
if (!metadata || metadata.length === 0) {
|
|
10824
|
+
return;
|
|
10825
|
+
}
|
|
10826
|
+
const instance = this.container.resolve(listenerClass);
|
|
10827
|
+
if (!instance) {
|
|
10828
|
+
console.warn(`[EventModule] Failed to resolve listener class: ${listenerClass.name}. ` + "Make sure it is registered as a provider.");
|
|
10829
|
+
return;
|
|
10830
|
+
}
|
|
10831
|
+
for (const listenerMetadata of metadata) {
|
|
10832
|
+
const method = instance[listenerMetadata.methodName];
|
|
10833
|
+
if (typeof method !== "function") {
|
|
10834
|
+
console.warn(`[EventModule] Method "${listenerMetadata.methodName}" not found on ${listenerClass.name}`);
|
|
10835
|
+
continue;
|
|
10836
|
+
}
|
|
10837
|
+
const boundMethod = method.bind(instance);
|
|
10838
|
+
this.eventEmitter.on(listenerMetadata.event, boundMethod, {
|
|
10839
|
+
async: listenerMetadata.async,
|
|
10840
|
+
priority: listenerMetadata.priority
|
|
10841
|
+
});
|
|
10842
|
+
}
|
|
10843
|
+
}
|
|
10844
|
+
}
|
|
10845
|
+
var EVENT_LISTENER_SCANNER_TOKEN = Symbol("@dangao/bun-server:events:scanner");
|
|
10846
|
+
|
|
10847
|
+
class EventModule {
|
|
10848
|
+
static listenerClasses = [];
|
|
10849
|
+
static forRoot(options = {}) {
|
|
10850
|
+
const providers2 = [];
|
|
10851
|
+
const eventEmitter = new EventEmitterService(options);
|
|
10852
|
+
providers2.push({
|
|
10853
|
+
provide: EVENT_OPTIONS_TOKEN,
|
|
10854
|
+
useValue: options
|
|
10855
|
+
});
|
|
10856
|
+
providers2.push({
|
|
10857
|
+
provide: EVENT_EMITTER_TOKEN,
|
|
10858
|
+
useValue: eventEmitter
|
|
10859
|
+
});
|
|
10860
|
+
const existingMetadata = Reflect.getMetadata(MODULE_METADATA_KEY, EventModule) || {};
|
|
10861
|
+
const metadata = {
|
|
10862
|
+
...existingMetadata,
|
|
10863
|
+
providers: [...existingMetadata.providers || [], ...providers2],
|
|
10864
|
+
exports: [
|
|
10865
|
+
...existingMetadata.exports || [],
|
|
10866
|
+
EVENT_EMITTER_TOKEN,
|
|
10867
|
+
EVENT_OPTIONS_TOKEN
|
|
10868
|
+
]
|
|
10869
|
+
};
|
|
10870
|
+
Reflect.defineMetadata(MODULE_METADATA_KEY, metadata, EventModule);
|
|
10871
|
+
EventModule.listenerClasses = [];
|
|
10872
|
+
return EventModule;
|
|
10873
|
+
}
|
|
10874
|
+
static registerListeners(listenerClasses) {
|
|
10875
|
+
EventModule.listenerClasses.push(...listenerClasses);
|
|
10876
|
+
}
|
|
10877
|
+
static initializeListeners(listenerContainer, additionalListeners = []) {
|
|
10878
|
+
const registry = ModuleRegistry.getInstance();
|
|
10879
|
+
const eventModuleRef = registry.getModuleRef(EventModule);
|
|
10880
|
+
let eventEmitter;
|
|
10881
|
+
if (eventModuleRef) {
|
|
10882
|
+
try {
|
|
10883
|
+
eventEmitter = eventModuleRef.container.resolve(EVENT_EMITTER_TOKEN);
|
|
10884
|
+
} catch {}
|
|
10885
|
+
}
|
|
10886
|
+
if (!eventEmitter) {
|
|
10887
|
+
console.warn("[EventModule] EventEmitter not found. Make sure EventModule.forRoot() is called and the module is registered.");
|
|
10888
|
+
return;
|
|
10889
|
+
}
|
|
10890
|
+
const resolveContainer = listenerContainer ?? eventModuleRef?.container;
|
|
10891
|
+
if (!resolveContainer) {
|
|
10892
|
+
console.warn("[EventModule] No container available to resolve listeners.");
|
|
10893
|
+
return;
|
|
10894
|
+
}
|
|
10895
|
+
const scanner = new EventListenerScanner(eventEmitter, resolveContainer);
|
|
10896
|
+
const allListeners = [
|
|
10897
|
+
...EventModule.listenerClasses,
|
|
10898
|
+
...additionalListeners
|
|
10899
|
+
];
|
|
10900
|
+
scanner.scanAndRegister(allListeners);
|
|
10901
|
+
}
|
|
10902
|
+
static getEventEmitter(container) {
|
|
10903
|
+
const registry = ModuleRegistry.getInstance();
|
|
10904
|
+
const moduleRef = registry.getModuleRef(EventModule);
|
|
10905
|
+
if (moduleRef) {
|
|
10906
|
+
try {
|
|
10907
|
+
return moduleRef.container.resolve(EVENT_EMITTER_TOKEN);
|
|
10908
|
+
} catch {}
|
|
10909
|
+
}
|
|
10910
|
+
if (container) {
|
|
10911
|
+
try {
|
|
10912
|
+
return container.resolve(EVENT_EMITTER_TOKEN);
|
|
10913
|
+
} catch {}
|
|
10914
|
+
}
|
|
10915
|
+
return;
|
|
10916
|
+
}
|
|
10917
|
+
}
|
|
10918
|
+
EventModule = __legacyDecorateClassTS([
|
|
10919
|
+
Module({
|
|
10920
|
+
providers: []
|
|
10921
|
+
})
|
|
10922
|
+
], EventModule);
|
|
9514
10923
|
export {
|
|
10924
|
+
validateParameters,
|
|
10925
|
+
validateObjectSync,
|
|
10926
|
+
validateObject,
|
|
9515
10927
|
scanInterceptorMetadata,
|
|
9516
10928
|
requiresAuth,
|
|
10929
|
+
registerReflector,
|
|
10930
|
+
isValidateClass,
|
|
10931
|
+
isGlobalModule,
|
|
10932
|
+
isEventListenerClass,
|
|
10933
|
+
getValidationMetadata,
|
|
9517
10934
|
getTransactionMetadata,
|
|
10935
|
+
getRolesMetadata,
|
|
9518
10936
|
getRepositoryMetadata,
|
|
10937
|
+
getOnEventMetadata,
|
|
10938
|
+
getGuardsMetadata,
|
|
10939
|
+
getGuardRegistry,
|
|
9519
10940
|
getEntityMetadata,
|
|
9520
10941
|
getColumnMetadata,
|
|
10942
|
+
getClassValidationMetadata,
|
|
9521
10943
|
getAuthMetadata,
|
|
9522
10944
|
createUserKeyGenerator,
|
|
9523
10945
|
createTokenKeyGenerator,
|
|
9524
10946
|
createSwaggerUIMiddleware,
|
|
9525
10947
|
createStaticFileMiddleware,
|
|
10948
|
+
createSimpleValidator,
|
|
9526
10949
|
createSessionMiddleware,
|
|
9527
10950
|
createSecurityFilter,
|
|
10951
|
+
createRolesGuard,
|
|
9528
10952
|
createRequestLoggingMiddleware,
|
|
10953
|
+
createRegexValidator,
|
|
9529
10954
|
createRateLimitMiddleware,
|
|
9530
10955
|
createLoggerMiddleware,
|
|
9531
10956
|
createHttpMetricsMiddleware,
|
|
9532
10957
|
createFileUploadMiddleware,
|
|
9533
10958
|
createErrorHandlingMiddleware,
|
|
10959
|
+
createCustomValidator,
|
|
9534
10960
|
createCorsMiddleware,
|
|
9535
10961
|
contextStore,
|
|
9536
10962
|
checkRoles,
|
|
@@ -9538,10 +10964,15 @@ export {
|
|
|
9538
10964
|
WebSocketGatewayRegistry,
|
|
9539
10965
|
WebSocketGateway,
|
|
9540
10966
|
ValidationError,
|
|
10967
|
+
ValidateNested,
|
|
10968
|
+
ValidateIf,
|
|
10969
|
+
ValidateClass,
|
|
9541
10970
|
Validate,
|
|
9542
10971
|
UserInfoRequestInterceptor,
|
|
9543
10972
|
UseMiddleware,
|
|
10973
|
+
UseGuards,
|
|
9544
10974
|
UnauthorizedException,
|
|
10975
|
+
Transform,
|
|
9545
10976
|
Transactional,
|
|
9546
10977
|
TransactionStatus,
|
|
9547
10978
|
TransactionManager,
|
|
@@ -9570,6 +11001,8 @@ export {
|
|
|
9570
11001
|
RouteRegistry,
|
|
9571
11002
|
Route,
|
|
9572
11003
|
RoundRobinLoadBalancer,
|
|
11004
|
+
RolesGuard,
|
|
11005
|
+
Roles,
|
|
9573
11006
|
RoleBasedAccessDecisionManager,
|
|
9574
11007
|
RetryStrategyImpl,
|
|
9575
11008
|
ResponseTransformInterceptor,
|
|
@@ -9578,11 +11011,14 @@ export {
|
|
|
9578
11011
|
RequestWrapper,
|
|
9579
11012
|
RequestLogInterceptor,
|
|
9580
11013
|
Repository,
|
|
11014
|
+
Reflector,
|
|
9581
11015
|
RedisSessionStore,
|
|
9582
11016
|
RedisCacheStore,
|
|
9583
11017
|
RateLimiter,
|
|
9584
11018
|
RateLimit,
|
|
9585
11019
|
RandomLoadBalancer,
|
|
11020
|
+
ROLES_METADATA_KEY,
|
|
11021
|
+
REFLECTOR_TOKEN,
|
|
9586
11022
|
QueueService,
|
|
9587
11023
|
QueueModule,
|
|
9588
11024
|
Queue,
|
|
@@ -9590,6 +11026,7 @@ export {
|
|
|
9590
11026
|
Query,
|
|
9591
11027
|
QUEUE_SERVICE_TOKEN,
|
|
9592
11028
|
QUEUE_OPTIONS_TOKEN,
|
|
11029
|
+
Property,
|
|
9593
11030
|
Propagation,
|
|
9594
11031
|
PrometheusFormatter,
|
|
9595
11032
|
PrimaryKey,
|
|
@@ -9603,20 +11040,27 @@ export {
|
|
|
9603
11040
|
PERMISSION_METADATA_KEY,
|
|
9604
11041
|
PATCH,
|
|
9605
11042
|
OrmService,
|
|
11043
|
+
OptionalAuthGuard,
|
|
9606
11044
|
OnOpen,
|
|
9607
11045
|
OnMessage,
|
|
11046
|
+
OnEvent,
|
|
9608
11047
|
OnClose,
|
|
9609
11048
|
ORM_SERVICE_TOKEN,
|
|
11049
|
+
ON_EVENT_METADATA_KEY,
|
|
9610
11050
|
OAuth2Service,
|
|
9611
11051
|
OAuth2Controller,
|
|
9612
11052
|
OAuth2AuthenticationProvider,
|
|
9613
11053
|
OAUTH2_SERVICE_TOKEN,
|
|
9614
11054
|
NotFoundException,
|
|
11055
|
+
NotEquals,
|
|
11056
|
+
NotContains,
|
|
11057
|
+
NestedProperty,
|
|
9615
11058
|
NacosServiceRegistry,
|
|
9616
11059
|
NacosConfigCenter,
|
|
9617
11060
|
ModuleRegistry,
|
|
9618
11061
|
Module,
|
|
9619
11062
|
MinLength,
|
|
11063
|
+
Min,
|
|
9620
11064
|
MiddlewarePipeline,
|
|
9621
11065
|
MetricsModule,
|
|
9622
11066
|
MetricsCollector,
|
|
@@ -9624,6 +11068,9 @@ export {
|
|
|
9624
11068
|
MemorySessionStore,
|
|
9625
11069
|
MemoryQueueStore,
|
|
9626
11070
|
MemoryCacheStore,
|
|
11071
|
+
MaxLength,
|
|
11072
|
+
Max,
|
|
11073
|
+
Matches,
|
|
9627
11074
|
METRICS_SERVICE_TOKEN,
|
|
9628
11075
|
METRICS_OPTIONS_TOKEN,
|
|
9629
11076
|
LoggerModule,
|
|
@@ -9633,6 +11080,7 @@ export {
|
|
|
9633
11080
|
Log,
|
|
9634
11081
|
LoadBalancerFactory,
|
|
9635
11082
|
Lifecycle,
|
|
11083
|
+
Length,
|
|
9636
11084
|
LeastActiveLoadBalancer,
|
|
9637
11085
|
LOG_METADATA_KEY,
|
|
9638
11086
|
LOGGER_TOKEN,
|
|
@@ -9640,10 +11088,39 @@ export {
|
|
|
9640
11088
|
JWT_UTIL_TOKEN,
|
|
9641
11089
|
JWTUtil,
|
|
9642
11090
|
IsolationLevel,
|
|
11091
|
+
IsUrl,
|
|
11092
|
+
IsUUID,
|
|
9643
11093
|
IsString,
|
|
11094
|
+
IsSemVer,
|
|
11095
|
+
IsPostalCode,
|
|
11096
|
+
IsPositive,
|
|
11097
|
+
IsPort,
|
|
11098
|
+
IsPhoneNumber,
|
|
9644
11099
|
IsOptional,
|
|
11100
|
+
IsObject,
|
|
11101
|
+
IsNumberString,
|
|
9645
11102
|
IsNumber,
|
|
11103
|
+
IsNotIn,
|
|
11104
|
+
IsNotEmptyObject,
|
|
11105
|
+
IsNotEmpty,
|
|
11106
|
+
IsNegative,
|
|
11107
|
+
IsMacAddress,
|
|
11108
|
+
IsJSON,
|
|
11109
|
+
IsInt,
|
|
11110
|
+
IsIn,
|
|
11111
|
+
IsIdCard,
|
|
11112
|
+
IsIPv4,
|
|
11113
|
+
IsHexColor,
|
|
9646
11114
|
IsEmail,
|
|
11115
|
+
IsDivisibleBy,
|
|
11116
|
+
IsDefined,
|
|
11117
|
+
IsDate,
|
|
11118
|
+
IsCreditCard,
|
|
11119
|
+
IsBoolean,
|
|
11120
|
+
IsBetween,
|
|
11121
|
+
IsArray,
|
|
11122
|
+
IsAlphanumeric,
|
|
11123
|
+
IsAlpha,
|
|
9647
11124
|
InternalServerErrorException,
|
|
9648
11125
|
InterceptorRegistry,
|
|
9649
11126
|
InterceptorChain,
|
|
@@ -9656,12 +11133,26 @@ export {
|
|
|
9656
11133
|
Header,
|
|
9657
11134
|
HEALTH_OPTIONS_TOKEN,
|
|
9658
11135
|
HEALTH_INDICATORS_TOKEN,
|
|
11136
|
+
GuardRegistry,
|
|
11137
|
+
Global,
|
|
11138
|
+
GUARD_REGISTRY_TOKEN,
|
|
11139
|
+
GUARDS_METADATA_KEY,
|
|
11140
|
+
GLOBAL_MODULE_METADATA_KEY,
|
|
9659
11141
|
GET,
|
|
9660
11142
|
ForbiddenException,
|
|
11143
|
+
ExecutionContextImpl,
|
|
9661
11144
|
ExceptionFilterRegistry,
|
|
11145
|
+
EventModule,
|
|
11146
|
+
EventListenerScanner,
|
|
11147
|
+
EventEmitterService,
|
|
9662
11148
|
ErrorHandlerInterceptor,
|
|
11149
|
+
Equals,
|
|
9663
11150
|
Entity,
|
|
9664
11151
|
EnableCacheProxy,
|
|
11152
|
+
EVENT_OPTIONS_TOKEN,
|
|
11153
|
+
EVENT_LISTENER_SCANNER_TOKEN,
|
|
11154
|
+
EVENT_LISTENER_CLASS_METADATA_KEY,
|
|
11155
|
+
EVENT_EMITTER_TOKEN,
|
|
9665
11156
|
DrizzleBaseRepository,
|
|
9666
11157
|
DatabaseService2 as DatabaseService,
|
|
9667
11158
|
DatabaseModule,
|
|
@@ -9677,6 +11168,7 @@ export {
|
|
|
9677
11168
|
ContextService,
|
|
9678
11169
|
Context2 as ContextParam,
|
|
9679
11170
|
Context,
|
|
11171
|
+
Contains,
|
|
9680
11172
|
Container,
|
|
9681
11173
|
ConsoleTraceCollector,
|
|
9682
11174
|
ConsistentHashLoadBalancer,
|
|
@@ -9713,7 +11205,15 @@ export {
|
|
|
9713
11205
|
BaseInterceptor,
|
|
9714
11206
|
BadRequestException,
|
|
9715
11207
|
AuthenticationManager,
|
|
11208
|
+
AuthGuard,
|
|
9716
11209
|
Auth,
|
|
11210
|
+
ArrayUnique,
|
|
11211
|
+
ArrayNotEmpty,
|
|
11212
|
+
ArrayNotContains,
|
|
11213
|
+
ArrayNestedProperty,
|
|
11214
|
+
ArrayMinSize,
|
|
11215
|
+
ArrayMaxSize,
|
|
11216
|
+
ArrayContains,
|
|
9717
11217
|
Application,
|
|
9718
11218
|
ApiTags,
|
|
9719
11219
|
ApiResponse,
|