@gravito/core 2.0.6 → 3.0.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 +64 -25
- package/dist/Application.d.ts +2 -9
- package/dist/Container.d.ts +18 -1
- package/dist/GravitoServer.d.ts +8 -8
- package/dist/HookManager.d.ts +36 -34
- package/dist/PlanetCore.d.ts +54 -0
- package/dist/Route.d.ts +5 -0
- package/dist/Router.d.ts +14 -1
- package/dist/adapters/bun/BunContext.d.ts +1 -1
- package/dist/adapters/bun/BunNativeAdapter.d.ts +11 -1
- package/dist/adapters/bun/FastPathRegistry.d.ts +31 -0
- package/dist/adapters/bun/RadixNode.d.ts +4 -3
- package/dist/adapters/bun/RadixRouter.d.ts +2 -2
- package/dist/adapters/bun/types.d.ts +7 -0
- package/dist/adapters/types.d.ts +20 -0
- package/dist/compat/async-local-storage.d.ts +5 -1
- package/dist/compat/async-local-storage.js.map +2 -2
- package/dist/compat/crypto.d.ts +6 -1
- package/dist/compat/crypto.js.map +2 -2
- package/dist/engine/AOTRouter.d.ts +1 -1
- package/dist/engine/FastContext.d.ts +4 -4
- package/dist/engine/MinimalContext.d.ts +3 -3
- package/dist/engine/index.js +29 -8
- package/dist/engine/index.js.map +10 -10
- package/dist/engine/types.d.ts +5 -5
- package/dist/events/CircuitBreaker.d.ts +12 -0
- package/dist/events/MessageQueueBridge.d.ts +2 -1
- package/dist/events/observability/EventMetrics.d.ts +1 -2
- package/dist/events/observability/ObservableHookManager.d.ts +1 -1
- package/dist/exceptions/AuthException.d.ts +19 -0
- package/dist/exceptions/AuthenticationException.d.ts +9 -3
- package/dist/exceptions/AuthorizationException.d.ts +2 -2
- package/dist/exceptions/CacheException.d.ts +9 -0
- package/dist/exceptions/CircularDependencyException.d.ts +2 -1
- package/dist/exceptions/ConfigurationException.d.ts +9 -0
- package/dist/exceptions/ContainerBindingCollisionException.d.ts +10 -0
- package/dist/exceptions/DatabaseException.d.ts +9 -0
- package/dist/exceptions/DomainException.d.ts +9 -0
- package/dist/exceptions/InfrastructureException.d.ts +17 -0
- package/dist/exceptions/MiddlewareDriftException.d.ts +10 -0
- package/dist/exceptions/QueueException.d.ts +9 -0
- package/dist/exceptions/StorageException.d.ts +9 -0
- package/dist/exceptions/StreamException.d.ts +9 -0
- package/dist/exceptions/SystemException.d.ts +9 -0
- package/dist/exceptions/ValidationException.d.ts +2 -2
- package/dist/exceptions/index.d.ts +12 -0
- package/dist/ffi/NativeAccelerator.js.map +3 -3
- package/dist/ffi/NativeHasher.d.ts +14 -0
- package/dist/ffi/NativeHasher.js +24 -1
- package/dist/ffi/NativeHasher.js.map +4 -4
- package/dist/ffi/cbor-fallback.js.map +1 -1
- package/dist/ffi/hash-fallback.d.ts +15 -0
- package/dist/ffi/hash-fallback.js +12 -1
- package/dist/ffi/hash-fallback.js.map +3 -3
- package/dist/ffi/types.d.ts +13 -0
- package/dist/ffi/types.js.map +1 -1
- package/dist/hooks/types.d.ts +7 -3
- package/dist/http/types.d.ts +2 -2
- package/dist/index.browser.d.ts +5 -5
- package/dist/index.browser.js +190 -47
- package/dist/index.browser.js.map +50 -46
- package/dist/index.d.ts +17 -7
- package/dist/index.js +613 -202
- package/dist/index.js.map +82 -68
- package/dist/runtime/NativeOrbitDetector.d.ts +59 -0
- package/dist/runtime/index.browser.d.ts +1 -1
- package/dist/runtime/index.d.ts +7 -0
- package/dist/runtime.d.ts +1 -1
- package/dist/testing/HttpTester.d.ts +4 -4
- package/dist/testing/TestResponse.d.ts +4 -4
- package/dist/types.d.ts +3 -3
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -1552,12 +1552,23 @@ var randomBytes = randomBytesFn;
|
|
|
1552
1552
|
import { createHash, createHmac } from "crypto";
|
|
1553
1553
|
|
|
1554
1554
|
class HashFallback {
|
|
1555
|
+
blake2bWarned = false;
|
|
1555
1556
|
sha256(input) {
|
|
1556
1557
|
return createHash("sha256").update(input).digest("hex");
|
|
1557
1558
|
}
|
|
1558
1559
|
hmacSha256(key, data) {
|
|
1559
1560
|
return createHmac("sha256", key).update(data).digest("hex");
|
|
1560
1561
|
}
|
|
1562
|
+
sha512(input) {
|
|
1563
|
+
return createHash("sha512").update(input).digest("hex");
|
|
1564
|
+
}
|
|
1565
|
+
blake2b(input) {
|
|
1566
|
+
if (!this.blake2bWarned) {
|
|
1567
|
+
console.warn("[gravito] BLAKE2b not available in node:crypto \u2014 using SHA-256 fallback");
|
|
1568
|
+
this.blake2bWarned = true;
|
|
1569
|
+
}
|
|
1570
|
+
return createHash("sha256").update(input).digest("hex");
|
|
1571
|
+
}
|
|
1561
1572
|
}
|
|
1562
1573
|
|
|
1563
1574
|
// src/ffi/NativeHasher.ts
|
|
@@ -1568,6 +1579,12 @@ class BunCryptoHasher {
|
|
|
1568
1579
|
hmacSha256(key, data) {
|
|
1569
1580
|
return new Bun.CryptoHasher("sha256", key).update(data).digest("hex");
|
|
1570
1581
|
}
|
|
1582
|
+
sha512(input) {
|
|
1583
|
+
return new Bun.CryptoHasher("sha512").update(input).digest("hex");
|
|
1584
|
+
}
|
|
1585
|
+
blake2b(input) {
|
|
1586
|
+
return new Bun.CryptoHasher("blake2b256").update(input).digest("hex");
|
|
1587
|
+
}
|
|
1571
1588
|
}
|
|
1572
1589
|
|
|
1573
1590
|
class NativeHasher {
|
|
@@ -1601,6 +1618,12 @@ class NativeHasher {
|
|
|
1601
1618
|
runtime
|
|
1602
1619
|
};
|
|
1603
1620
|
}
|
|
1621
|
+
static sha512(input) {
|
|
1622
|
+
return this.getAccelerator().sha512(input);
|
|
1623
|
+
}
|
|
1624
|
+
static blake2b(input) {
|
|
1625
|
+
return this.getAccelerator().blake2b(input);
|
|
1626
|
+
}
|
|
1604
1627
|
static sha256(input) {
|
|
1605
1628
|
return this.getAccelerator().sha256(input);
|
|
1606
1629
|
}
|
|
@@ -1648,6 +1671,7 @@ class RadixNode {
|
|
|
1648
1671
|
paramChild = null;
|
|
1649
1672
|
wildcardChild = null;
|
|
1650
1673
|
handlers = new Map;
|
|
1674
|
+
options = new Map;
|
|
1651
1675
|
paramName = null;
|
|
1652
1676
|
regex = null;
|
|
1653
1677
|
constructor(segment = "", type = 0 /* STATIC */) {
|
|
@@ -1661,13 +1685,15 @@ class RadixNode {
|
|
|
1661
1685
|
children: Array.from(this.children.entries()).map(([k, v]) => [k, v.toJSON()]),
|
|
1662
1686
|
paramChild: this.paramChild?.toJSON() || null,
|
|
1663
1687
|
wildcardChild: this.wildcardChild?.toJSON() || null,
|
|
1688
|
+
handlers: Array.from(this.handlers.entries()),
|
|
1689
|
+
options: Array.from(this.options.entries()),
|
|
1664
1690
|
paramName: this.paramName,
|
|
1665
1691
|
regex: this.regex ? this.regex.source : null
|
|
1666
1692
|
};
|
|
1667
1693
|
}
|
|
1668
1694
|
static fromJSON(json) {
|
|
1669
1695
|
const node = new RadixNode(json.segment, json.type);
|
|
1670
|
-
node.paramName = json.paramName;
|
|
1696
|
+
node.paramName = json.paramName ?? null;
|
|
1671
1697
|
if (json.regex) {
|
|
1672
1698
|
node.regex = new RegExp(json.regex);
|
|
1673
1699
|
}
|
|
@@ -1682,6 +1708,16 @@ class RadixNode {
|
|
|
1682
1708
|
if (json.wildcardChild) {
|
|
1683
1709
|
node.wildcardChild = RadixNode.fromJSON(json.wildcardChild);
|
|
1684
1710
|
}
|
|
1711
|
+
if (json.handlers) {
|
|
1712
|
+
for (const [method, handlers] of json.handlers) {
|
|
1713
|
+
node.handlers.set(method, handlers);
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
if (json.options) {
|
|
1717
|
+
for (const [method, options2] of json.options) {
|
|
1718
|
+
node.options.set(method, options2);
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1685
1721
|
return node;
|
|
1686
1722
|
}
|
|
1687
1723
|
}
|
|
@@ -1717,7 +1753,7 @@ class RadixRouter {
|
|
|
1717
1753
|
where(param, regex) {
|
|
1718
1754
|
this.globalConstraints.set(param, regex);
|
|
1719
1755
|
}
|
|
1720
|
-
add(method, path2, handlers) {
|
|
1756
|
+
add(method, path2, handlers, options2) {
|
|
1721
1757
|
let node = this.root;
|
|
1722
1758
|
const segments = this.splitPath(path2);
|
|
1723
1759
|
for (let i = 0;i < segments.length; i++) {
|
|
@@ -1747,7 +1783,11 @@ class RadixRouter {
|
|
|
1747
1783
|
node = node.children.get(segment);
|
|
1748
1784
|
}
|
|
1749
1785
|
}
|
|
1750
|
-
|
|
1786
|
+
const normalizedMethod = method.toLowerCase();
|
|
1787
|
+
node.handlers.set(normalizedMethod, handlers);
|
|
1788
|
+
if (options2) {
|
|
1789
|
+
node.options.set(normalizedMethod, options2);
|
|
1790
|
+
}
|
|
1751
1791
|
this.routeCache.clear();
|
|
1752
1792
|
}
|
|
1753
1793
|
match(method, path2) {
|
|
@@ -1755,7 +1795,7 @@ class RadixRouter {
|
|
|
1755
1795
|
if (path2 === "/" || path2 === "") {
|
|
1756
1796
|
const handlers = this.root.handlers.get(normalizedMethod);
|
|
1757
1797
|
if (handlers) {
|
|
1758
|
-
return { handlers, params: {} };
|
|
1798
|
+
return { handlers, params: {}, options: this.root.options.get(normalizedMethod) };
|
|
1759
1799
|
}
|
|
1760
1800
|
return null;
|
|
1761
1801
|
}
|
|
@@ -1772,11 +1812,13 @@ class RadixRouter {
|
|
|
1772
1812
|
matchRecursive(node, segments, depth, params, method) {
|
|
1773
1813
|
if (depth >= segments.length) {
|
|
1774
1814
|
let handlers = node.handlers.get(method);
|
|
1815
|
+
let options2 = node.options.get(method);
|
|
1775
1816
|
if (!handlers) {
|
|
1776
1817
|
handlers = node.handlers.get("all");
|
|
1818
|
+
options2 = node.options.get("all");
|
|
1777
1819
|
}
|
|
1778
1820
|
if (handlers) {
|
|
1779
|
-
return { handlers, params };
|
|
1821
|
+
return { handlers, params, options: options2 };
|
|
1780
1822
|
}
|
|
1781
1823
|
return null;
|
|
1782
1824
|
}
|
|
@@ -1803,11 +1845,13 @@ class RadixRouter {
|
|
|
1803
1845
|
}
|
|
1804
1846
|
if (node.wildcardChild) {
|
|
1805
1847
|
let handlers = node.wildcardChild.handlers.get(method);
|
|
1848
|
+
let options2 = node.wildcardChild.options.get(method);
|
|
1806
1849
|
if (!handlers) {
|
|
1807
1850
|
handlers = node.wildcardChild.handlers.get("all");
|
|
1851
|
+
options2 = node.wildcardChild.options.get("all");
|
|
1808
1852
|
}
|
|
1809
1853
|
if (handlers) {
|
|
1810
|
-
return { handlers, params };
|
|
1854
|
+
return { handlers, params, options: options2 };
|
|
1811
1855
|
}
|
|
1812
1856
|
}
|
|
1813
1857
|
return null;
|
|
@@ -2289,7 +2333,7 @@ class RequestScopeManager {
|
|
|
2289
2333
|
let servicesCleaned = 0;
|
|
2290
2334
|
for (const [, instance] of this.scoped) {
|
|
2291
2335
|
if (instance && typeof instance === "object" && "cleanup" in instance) {
|
|
2292
|
-
const fn = instance
|
|
2336
|
+
const fn = instance["cleanup"];
|
|
2293
2337
|
if (typeof fn === "function") {
|
|
2294
2338
|
try {
|
|
2295
2339
|
await fn.call(instance);
|
|
@@ -3300,7 +3344,7 @@ class Gravito {
|
|
|
3300
3344
|
// package.json
|
|
3301
3345
|
var package_default = {
|
|
3302
3346
|
name: "@gravito/core",
|
|
3303
|
-
version: "
|
|
3347
|
+
version: "3.0.1",
|
|
3304
3348
|
description: "",
|
|
3305
3349
|
module: "./dist/index.js",
|
|
3306
3350
|
main: "./dist/index.js",
|
|
@@ -3309,9 +3353,9 @@ var package_default = {
|
|
|
3309
3353
|
types: "./dist/index.d.ts",
|
|
3310
3354
|
exports: {
|
|
3311
3355
|
".": {
|
|
3356
|
+
types: "./dist/index.d.ts",
|
|
3312
3357
|
browser: "./dist/index.browser.js",
|
|
3313
3358
|
bun: "./dist/index.js",
|
|
3314
|
-
types: "./dist/index.d.ts",
|
|
3315
3359
|
default: "./dist/index.js"
|
|
3316
3360
|
},
|
|
3317
3361
|
"./compat": {
|
|
@@ -3357,7 +3401,8 @@ var package_default = {
|
|
|
3357
3401
|
typecheck: "bun tsc -p tsconfig.json --noEmit --skipLibCheck",
|
|
3358
3402
|
prepublishOnly: "bun run typecheck && bun run test && bun run build",
|
|
3359
3403
|
"test:unit": "bun test $(find tests -name '*.test.ts' ! -name '*.integration.test.ts' 2>/dev/null | tr '\\n' ' ') --timeout=10000",
|
|
3360
|
-
"test:integration": "test $(find tests -name '*.integration.test.ts' 2>/dev/null | wc -l) -gt 0 && find tests -name '*.integration.test.ts' -print0 | xargs -0 bun test --timeout=10000 || echo 'No integration tests found'"
|
|
3404
|
+
"test:integration": "test $(find tests -name '*.integration.test.ts' 2>/dev/null | wc -l) -gt 0 && find tests -name '*.integration.test.ts' -print0 | xargs -0 bun test --timeout=10000 || echo 'No integration tests found'",
|
|
3405
|
+
publint: "publint"
|
|
3361
3406
|
},
|
|
3362
3407
|
keywords: [],
|
|
3363
3408
|
author: "Carl Lee <carllee0520@gmail.com>",
|
|
@@ -3755,6 +3800,250 @@ class BunWebSocketHandler {
|
|
|
3755
3800
|
}
|
|
3756
3801
|
}
|
|
3757
3802
|
|
|
3803
|
+
// src/adapters/bun/FastPathRegistry.ts
|
|
3804
|
+
class FastPathRegistry {
|
|
3805
|
+
routes = new Map;
|
|
3806
|
+
register(method, path2, handler) {
|
|
3807
|
+
const upperMethod = method.toUpperCase();
|
|
3808
|
+
let methodRoutes = this.routes.get(upperMethod);
|
|
3809
|
+
if (!methodRoutes) {
|
|
3810
|
+
methodRoutes = new Map;
|
|
3811
|
+
this.routes.set(upperMethod, methodRoutes);
|
|
3812
|
+
}
|
|
3813
|
+
methodRoutes.set(path2, handler);
|
|
3814
|
+
}
|
|
3815
|
+
match(method, path2) {
|
|
3816
|
+
const methodRoutes = this.routes.get(method.toUpperCase());
|
|
3817
|
+
if (!methodRoutes) {
|
|
3818
|
+
return;
|
|
3819
|
+
}
|
|
3820
|
+
return methodRoutes.get(path2);
|
|
3821
|
+
}
|
|
3822
|
+
getAll() {
|
|
3823
|
+
return this.routes;
|
|
3824
|
+
}
|
|
3825
|
+
}
|
|
3826
|
+
|
|
3827
|
+
// src/exceptions/GravitoException.ts
|
|
3828
|
+
class GravitoException extends Error {
|
|
3829
|
+
status;
|
|
3830
|
+
code;
|
|
3831
|
+
i18nKey;
|
|
3832
|
+
i18nParams;
|
|
3833
|
+
constructor(status, code, options2 = {}) {
|
|
3834
|
+
super(options2.message);
|
|
3835
|
+
this.name = "GravitoException";
|
|
3836
|
+
this.status = status;
|
|
3837
|
+
this.cause = options2.cause;
|
|
3838
|
+
this.code = code;
|
|
3839
|
+
if (options2.i18nKey) {
|
|
3840
|
+
this.i18nKey = options2.i18nKey;
|
|
3841
|
+
}
|
|
3842
|
+
if (options2.i18nParams) {
|
|
3843
|
+
this.i18nParams = options2.i18nParams;
|
|
3844
|
+
}
|
|
3845
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
3846
|
+
}
|
|
3847
|
+
getLocalizedMessage(t) {
|
|
3848
|
+
if (this.i18nKey) {
|
|
3849
|
+
return t(this.i18nKey, this.i18nParams);
|
|
3850
|
+
}
|
|
3851
|
+
return this.message;
|
|
3852
|
+
}
|
|
3853
|
+
}
|
|
3854
|
+
|
|
3855
|
+
// src/exceptions/DomainException.ts
|
|
3856
|
+
class DomainException extends GravitoException {
|
|
3857
|
+
constructor(status, code, options2 = {}) {
|
|
3858
|
+
super(status, code, options2);
|
|
3859
|
+
this.name = "DomainException";
|
|
3860
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
3861
|
+
}
|
|
3862
|
+
}
|
|
3863
|
+
|
|
3864
|
+
// src/exceptions/AuthException.ts
|
|
3865
|
+
class AuthException extends DomainException {
|
|
3866
|
+
constructor(status, code, options2 = {}) {
|
|
3867
|
+
super(status, code, options2);
|
|
3868
|
+
this.name = "AuthException";
|
|
3869
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
3870
|
+
}
|
|
3871
|
+
}
|
|
3872
|
+
|
|
3873
|
+
// src/exceptions/AuthenticationException.ts
|
|
3874
|
+
class AuthenticationException extends DomainException {
|
|
3875
|
+
constructor(message = "Unauthenticated.") {
|
|
3876
|
+
super(401, "UNAUTHENTICATED", {
|
|
3877
|
+
message,
|
|
3878
|
+
i18nKey: "errors.authentication.unauthenticated"
|
|
3879
|
+
});
|
|
3880
|
+
this.name = "AuthenticationException";
|
|
3881
|
+
}
|
|
3882
|
+
}
|
|
3883
|
+
|
|
3884
|
+
// src/exceptions/AuthorizationException.ts
|
|
3885
|
+
class AuthorizationException extends DomainException {
|
|
3886
|
+
constructor(message = "This action is unauthorized.") {
|
|
3887
|
+
super(403, "FORBIDDEN", {
|
|
3888
|
+
message,
|
|
3889
|
+
i18nKey: "errors.authorization.forbidden"
|
|
3890
|
+
});
|
|
3891
|
+
this.name = "AuthorizationException";
|
|
3892
|
+
}
|
|
3893
|
+
}
|
|
3894
|
+
|
|
3895
|
+
// src/exceptions/InfrastructureException.ts
|
|
3896
|
+
class InfrastructureException extends GravitoException {
|
|
3897
|
+
retryable;
|
|
3898
|
+
constructor(status, code, options2 = {}) {
|
|
3899
|
+
super(status, code, options2);
|
|
3900
|
+
this.name = "InfrastructureException";
|
|
3901
|
+
this.retryable = options2.retryable ?? false;
|
|
3902
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
3903
|
+
}
|
|
3904
|
+
}
|
|
3905
|
+
|
|
3906
|
+
// src/exceptions/CacheException.ts
|
|
3907
|
+
class CacheException extends InfrastructureException {
|
|
3908
|
+
constructor(status, code, options2 = {}) {
|
|
3909
|
+
super(status, code, options2);
|
|
3910
|
+
this.name = "CacheException";
|
|
3911
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
3912
|
+
}
|
|
3913
|
+
}
|
|
3914
|
+
|
|
3915
|
+
// src/exceptions/SystemException.ts
|
|
3916
|
+
class SystemException extends GravitoException {
|
|
3917
|
+
constructor(status, code, options2 = {}) {
|
|
3918
|
+
super(status, code, options2);
|
|
3919
|
+
this.name = "SystemException";
|
|
3920
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
3921
|
+
}
|
|
3922
|
+
}
|
|
3923
|
+
|
|
3924
|
+
// src/exceptions/CircularDependencyException.ts
|
|
3925
|
+
class CircularDependencyException extends SystemException {
|
|
3926
|
+
constructor(key, stack) {
|
|
3927
|
+
const path2 = [...stack, key].map(String).join(" -> ");
|
|
3928
|
+
super(500, "system.circular_dependency", {
|
|
3929
|
+
message: `Circular dependency detected: ${path2}`
|
|
3930
|
+
});
|
|
3931
|
+
this.name = "CircularDependencyException";
|
|
3932
|
+
}
|
|
3933
|
+
}
|
|
3934
|
+
|
|
3935
|
+
// src/exceptions/ConfigurationException.ts
|
|
3936
|
+
class ConfigurationException extends SystemException {
|
|
3937
|
+
constructor(message, options2 = {}) {
|
|
3938
|
+
super(500, "system.configuration_error", { ...options2, message });
|
|
3939
|
+
this.name = "ConfigurationException";
|
|
3940
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
3941
|
+
}
|
|
3942
|
+
}
|
|
3943
|
+
|
|
3944
|
+
// src/exceptions/ContainerBindingCollisionException.ts
|
|
3945
|
+
class ContainerBindingCollisionException extends SystemException {
|
|
3946
|
+
constructor(message, options2 = {}) {
|
|
3947
|
+
super(500, "system.container_binding_collision", { ...options2, message });
|
|
3948
|
+
this.name = "ContainerBindingCollisionException";
|
|
3949
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
3950
|
+
}
|
|
3951
|
+
}
|
|
3952
|
+
|
|
3953
|
+
// src/exceptions/DatabaseException.ts
|
|
3954
|
+
class DatabaseException extends InfrastructureException {
|
|
3955
|
+
constructor(status, code, options2 = {}) {
|
|
3956
|
+
super(status, code, options2);
|
|
3957
|
+
this.name = "DatabaseException";
|
|
3958
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
3959
|
+
}
|
|
3960
|
+
}
|
|
3961
|
+
|
|
3962
|
+
// src/exceptions/HttpException.ts
|
|
3963
|
+
class HttpException extends GravitoException {
|
|
3964
|
+
constructor(status, options2 = {}) {
|
|
3965
|
+
super(status, "HTTP_ERROR", options2);
|
|
3966
|
+
this.name = "HttpException";
|
|
3967
|
+
}
|
|
3968
|
+
}
|
|
3969
|
+
|
|
3970
|
+
// src/exceptions/MiddlewareDriftException.ts
|
|
3971
|
+
class MiddlewareDriftException extends SystemException {
|
|
3972
|
+
constructor(message, options2 = {}) {
|
|
3973
|
+
super(500, "system.middleware_drift", { ...options2, message });
|
|
3974
|
+
this.name = "MiddlewareDriftException";
|
|
3975
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
3976
|
+
}
|
|
3977
|
+
}
|
|
3978
|
+
|
|
3979
|
+
// src/exceptions/ModelNotFoundException.ts
|
|
3980
|
+
class ModelNotFoundException extends GravitoException {
|
|
3981
|
+
model;
|
|
3982
|
+
id;
|
|
3983
|
+
constructor(model, id) {
|
|
3984
|
+
super(404, "NOT_FOUND", {
|
|
3985
|
+
message: `${model} not found.`,
|
|
3986
|
+
i18nKey: "errors.model.not_found",
|
|
3987
|
+
i18nParams: { model, id: String(id ?? "") }
|
|
3988
|
+
});
|
|
3989
|
+
this.name = "ModelNotFoundException";
|
|
3990
|
+
this.model = model;
|
|
3991
|
+
if (id !== undefined) {
|
|
3992
|
+
this.id = id;
|
|
3993
|
+
}
|
|
3994
|
+
}
|
|
3995
|
+
}
|
|
3996
|
+
|
|
3997
|
+
// src/exceptions/QueueException.ts
|
|
3998
|
+
class QueueException extends InfrastructureException {
|
|
3999
|
+
constructor(status, code, options2 = {}) {
|
|
4000
|
+
super(status, code, options2);
|
|
4001
|
+
this.name = "QueueException";
|
|
4002
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
4003
|
+
}
|
|
4004
|
+
}
|
|
4005
|
+
|
|
4006
|
+
// src/exceptions/StorageException.ts
|
|
4007
|
+
class StorageException extends InfrastructureException {
|
|
4008
|
+
constructor(status, code, options2 = {}) {
|
|
4009
|
+
super(status, code, options2);
|
|
4010
|
+
this.name = "StorageException";
|
|
4011
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
4012
|
+
}
|
|
4013
|
+
}
|
|
4014
|
+
|
|
4015
|
+
// src/exceptions/StreamException.ts
|
|
4016
|
+
class StreamException extends InfrastructureException {
|
|
4017
|
+
constructor(status, code, options2 = {}) {
|
|
4018
|
+
super(status, code, options2);
|
|
4019
|
+
this.name = "StreamException";
|
|
4020
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
4021
|
+
}
|
|
4022
|
+
}
|
|
4023
|
+
|
|
4024
|
+
// src/exceptions/ValidationException.ts
|
|
4025
|
+
class ValidationException extends DomainException {
|
|
4026
|
+
errors;
|
|
4027
|
+
redirectTo;
|
|
4028
|
+
input;
|
|
4029
|
+
constructor(errors, message = "Validation failed") {
|
|
4030
|
+
super(422, "VALIDATION_ERROR", {
|
|
4031
|
+
message,
|
|
4032
|
+
i18nKey: "errors.validation.failed"
|
|
4033
|
+
});
|
|
4034
|
+
this.name = "ValidationException";
|
|
4035
|
+
this.errors = errors;
|
|
4036
|
+
}
|
|
4037
|
+
withRedirect(url) {
|
|
4038
|
+
this.redirectTo = url;
|
|
4039
|
+
return this;
|
|
4040
|
+
}
|
|
4041
|
+
withInput(input) {
|
|
4042
|
+
this.input = input;
|
|
4043
|
+
return this;
|
|
4044
|
+
}
|
|
4045
|
+
}
|
|
4046
|
+
|
|
3758
4047
|
// src/adapters/bun/BunNativeAdapter.ts
|
|
3759
4048
|
class BunNativeAdapter {
|
|
3760
4049
|
name = "bun-native";
|
|
@@ -3762,7 +4051,9 @@ class BunNativeAdapter {
|
|
|
3762
4051
|
get native() {
|
|
3763
4052
|
return this;
|
|
3764
4053
|
}
|
|
4054
|
+
isSnapshotLocked = false;
|
|
3765
4055
|
router = new RadixRouter;
|
|
4056
|
+
fastPathRegistry = new FastPathRegistry;
|
|
3766
4057
|
middlewares = [];
|
|
3767
4058
|
errorHandler = null;
|
|
3768
4059
|
notFoundHandler = null;
|
|
@@ -3770,22 +4061,41 @@ class BunNativeAdapter {
|
|
|
3770
4061
|
maxPoolSize = 100;
|
|
3771
4062
|
middlewareChainCache = new Map;
|
|
3772
4063
|
wsHandler = new BunWebSocketHandler;
|
|
4064
|
+
checkLock() {
|
|
4065
|
+
if (this.isSnapshotLocked && true) {
|
|
4066
|
+
throw new MiddlewareDriftException("FAST_PATH_MIDDLEWARE_DRIFT: Middleware or routes cannot be added after serveConfig() has been called. " + "This ensures the snapshotted configuration remains consistent with the application state.");
|
|
4067
|
+
}
|
|
4068
|
+
}
|
|
3773
4069
|
route(method, path2, ...handlers) {
|
|
3774
|
-
this.
|
|
4070
|
+
this.checkLock();
|
|
4071
|
+
const last = handlers[handlers.length - 1];
|
|
4072
|
+
let options2;
|
|
4073
|
+
if (last && typeof last === "object" && !Array.isArray(last) && "excludeMiddleware" in last) {
|
|
4074
|
+
options2 = handlers.pop();
|
|
4075
|
+
}
|
|
4076
|
+
this.router.add(method, path2, handlers, options2);
|
|
3775
4077
|
}
|
|
3776
4078
|
routes(routes) {
|
|
4079
|
+
this.checkLock();
|
|
3777
4080
|
for (const route of routes) {
|
|
3778
|
-
|
|
4081
|
+
const options2 = {};
|
|
4082
|
+
if (route.excludeMiddleware) {
|
|
4083
|
+
options2.excludeMiddleware = route.excludeMiddleware;
|
|
4084
|
+
}
|
|
4085
|
+
this.router.add(route.method, route.path, route.handlers, Object.keys(options2).length > 0 ? options2 : undefined);
|
|
3779
4086
|
}
|
|
3780
4087
|
}
|
|
3781
4088
|
use(path2, ...middleware) {
|
|
4089
|
+
this.checkLock();
|
|
3782
4090
|
this.middlewares.push({ path: path2, handlers: middleware });
|
|
3783
4091
|
this.middlewareChainCache.clear();
|
|
3784
4092
|
}
|
|
3785
4093
|
useGlobal(...middleware) {
|
|
4094
|
+
this.checkLock();
|
|
3786
4095
|
this.use("*", ...middleware);
|
|
3787
4096
|
}
|
|
3788
4097
|
useScoped(scope, path2, ...middleware) {
|
|
4098
|
+
this.checkLock();
|
|
3789
4099
|
if (path2 === "*" || path2 === "*/*") {
|
|
3790
4100
|
throw new Error(`useScoped(): Cannot use wildcard path '*' in Orbit-scoped middleware. ` + `Use regular use('*') for global middleware, or specify explicit paths like '${scope}/*'`);
|
|
3791
4101
|
}
|
|
@@ -3800,6 +4110,9 @@ class BunNativeAdapter {
|
|
|
3800
4110
|
if (pattern === "*") {
|
|
3801
4111
|
return true;
|
|
3802
4112
|
}
|
|
4113
|
+
if (pattern === "/") {
|
|
4114
|
+
return true;
|
|
4115
|
+
}
|
|
3803
4116
|
if (pattern.endsWith("/*")) {
|
|
3804
4117
|
const basePattern = pattern.slice(0, -2);
|
|
3805
4118
|
return path2 === basePattern || path2.startsWith(`${basePattern}/`);
|
|
@@ -3810,17 +4123,25 @@ class BunNativeAdapter {
|
|
|
3810
4123
|
}
|
|
3811
4124
|
return path2 === pattern || path2.startsWith(`${pattern}/`);
|
|
3812
4125
|
}
|
|
3813
|
-
getCompiledMiddlewareChain(path2) {
|
|
3814
|
-
|
|
3815
|
-
|
|
4126
|
+
getCompiledMiddlewareChain(path2, options2) {
|
|
4127
|
+
const exclude = options2?.excludeMiddleware || [];
|
|
4128
|
+
const cacheKey = exclude.length > 0 ? `${path2}:exclude:${exclude.sort().join(",")}` : path2;
|
|
4129
|
+
if (this.middlewareChainCache.has(cacheKey)) {
|
|
4130
|
+
return this.middlewareChainCache.get(cacheKey);
|
|
3816
4131
|
}
|
|
3817
4132
|
const chain = [];
|
|
3818
4133
|
for (const mw of this.middlewares) {
|
|
3819
4134
|
if (this.matchesPath(mw.path, path2)) {
|
|
3820
|
-
|
|
4135
|
+
for (const handler of mw.handlers) {
|
|
4136
|
+
const name = handler.name || handler.middlewareName;
|
|
4137
|
+
if (name && exclude.includes(name)) {
|
|
4138
|
+
continue;
|
|
4139
|
+
}
|
|
4140
|
+
chain.push(handler);
|
|
4141
|
+
}
|
|
3821
4142
|
}
|
|
3822
4143
|
}
|
|
3823
|
-
this.middlewareChainCache.set(
|
|
4144
|
+
this.middlewareChainCache.set(cacheKey, chain);
|
|
3824
4145
|
return chain;
|
|
3825
4146
|
}
|
|
3826
4147
|
acquireContext(request) {
|
|
@@ -3862,12 +4183,36 @@ class BunNativeAdapter {
|
|
|
3862
4183
|
return BunContext.create(request);
|
|
3863
4184
|
}
|
|
3864
4185
|
onError(handler) {
|
|
4186
|
+
this.checkLock();
|
|
3865
4187
|
this.errorHandler = handler;
|
|
3866
4188
|
}
|
|
3867
4189
|
onNotFound(handler) {
|
|
4190
|
+
this.checkLock();
|
|
3868
4191
|
this.notFoundHandler = handler;
|
|
3869
4192
|
}
|
|
4193
|
+
registerFastPath(method, path2, handler) {
|
|
4194
|
+
this.checkLock();
|
|
4195
|
+
this.fastPathRegistry.register(method, path2, handler);
|
|
4196
|
+
}
|
|
4197
|
+
serveConfig(baseConfig = {}) {
|
|
4198
|
+
this.isSnapshotLocked = true;
|
|
4199
|
+
const routes = {};
|
|
4200
|
+
for (const [method, pathMap] of this.fastPathRegistry.getAll()) {
|
|
4201
|
+
if (method === "GET") {
|
|
4202
|
+
for (const [path2, handler] of pathMap) {
|
|
4203
|
+
routes[path2] = handler;
|
|
4204
|
+
}
|
|
4205
|
+
}
|
|
4206
|
+
}
|
|
4207
|
+
return {
|
|
4208
|
+
...baseConfig,
|
|
4209
|
+
routes,
|
|
4210
|
+
fetch: this.fetch.bind(this),
|
|
4211
|
+
websocket: this.websocket
|
|
4212
|
+
};
|
|
4213
|
+
}
|
|
3870
4214
|
registerWebSocketRoute(path2, handlers) {
|
|
4215
|
+
this.checkLock();
|
|
3871
4216
|
this.wsHandler.register(path2, handlers);
|
|
3872
4217
|
}
|
|
3873
4218
|
get websocket() {
|
|
@@ -3882,7 +4227,12 @@ class BunNativeAdapter {
|
|
|
3882
4227
|
}
|
|
3883
4228
|
async fetch(request, _server) {
|
|
3884
4229
|
const url = new URL(request.url);
|
|
3885
|
-
|
|
4230
|
+
const path2 = url.pathname;
|
|
4231
|
+
const fastHandler = this.fastPathRegistry.match(request.method, path2);
|
|
4232
|
+
if (fastHandler) {
|
|
4233
|
+
return fastHandler(request);
|
|
4234
|
+
}
|
|
4235
|
+
if (_server != null && typeof _server.upgrade === "function" && request.headers.get("upgrade")?.toLowerCase() === "websocket" && this.wsHandler.hasRoute(path2)) {
|
|
3886
4236
|
const upgraded = _server.upgrade(request, {
|
|
3887
4237
|
data: {
|
|
3888
4238
|
path: url.pathname,
|
|
@@ -3896,11 +4246,10 @@ class BunNativeAdapter {
|
|
|
3896
4246
|
}
|
|
3897
4247
|
const ctx = this.acquireContext(request);
|
|
3898
4248
|
try {
|
|
3899
|
-
const path2 = url.pathname;
|
|
3900
4249
|
const method = request.method;
|
|
3901
4250
|
const match = this.router.match(method, path2);
|
|
3902
4251
|
const handlers = [];
|
|
3903
|
-
const middlewareChain = this.getCompiledMiddlewareChain(path2);
|
|
4252
|
+
const middlewareChain = this.getCompiledMiddlewareChain(path2, match?.options);
|
|
3904
4253
|
handlers.push(...middlewareChain);
|
|
3905
4254
|
if (match) {
|
|
3906
4255
|
if (match.params) {
|
|
@@ -4608,7 +4957,8 @@ function createNodeAdapter() {
|
|
|
4608
4957
|
},
|
|
4609
4958
|
resourceUsage: async () => {
|
|
4610
4959
|
try {
|
|
4611
|
-
const
|
|
4960
|
+
const childWithUsage = child;
|
|
4961
|
+
const usage = childWithUsage.resourceUsage?.();
|
|
4612
4962
|
if (!usage) {
|
|
4613
4963
|
return;
|
|
4614
4964
|
}
|
|
@@ -4817,6 +5167,78 @@ function createUnknownAdapter() {
|
|
|
4817
5167
|
}
|
|
4818
5168
|
};
|
|
4819
5169
|
}
|
|
5170
|
+
// src/runtime/NativeOrbitDetector.ts
|
|
5171
|
+
function probeCryptoHasher(CryptoHasherCtor, algo) {
|
|
5172
|
+
try {
|
|
5173
|
+
const ctor = CryptoHasherCtor;
|
|
5174
|
+
new ctor(algo).update("").digest("hex");
|
|
5175
|
+
return true;
|
|
5176
|
+
} catch {
|
|
5177
|
+
return false;
|
|
5178
|
+
}
|
|
5179
|
+
}
|
|
5180
|
+
|
|
5181
|
+
class NativeOrbitDetector {
|
|
5182
|
+
static cached = null;
|
|
5183
|
+
static detectBunCapabilities() {
|
|
5184
|
+
if (this.cached !== null) {
|
|
5185
|
+
return this.cached;
|
|
5186
|
+
}
|
|
5187
|
+
const kind2 = getRuntimeKind();
|
|
5188
|
+
const B2 = globalThis.Bun;
|
|
5189
|
+
if (kind2 !== "bun" || !B2) {
|
|
5190
|
+
this.cached = Object.freeze({
|
|
5191
|
+
runtime: kind2,
|
|
5192
|
+
bunVersion: null,
|
|
5193
|
+
password: Object.freeze({ available: false, argon2id: false, bcrypt: false }),
|
|
5194
|
+
cryptoHasher: Object.freeze({
|
|
5195
|
+
available: false,
|
|
5196
|
+
sha256: false,
|
|
5197
|
+
sha512: false,
|
|
5198
|
+
blake2b: false
|
|
5199
|
+
}),
|
|
5200
|
+
glob: false
|
|
5201
|
+
});
|
|
5202
|
+
return this.cached;
|
|
5203
|
+
}
|
|
5204
|
+
const hasPassword = typeof B2.password?.hash === "function" && typeof B2.password?.verify === "function";
|
|
5205
|
+
const passwordFeatures = Object.freeze({
|
|
5206
|
+
available: hasPassword,
|
|
5207
|
+
argon2id: hasPassword,
|
|
5208
|
+
bcrypt: hasPassword
|
|
5209
|
+
});
|
|
5210
|
+
const HasherCtor = B2.CryptoHasher;
|
|
5211
|
+
const hasHasher = typeof HasherCtor === "function";
|
|
5212
|
+
const sha256 = hasHasher ? probeCryptoHasher(HasherCtor, "sha256") : false;
|
|
5213
|
+
const sha512 = hasHasher ? probeCryptoHasher(HasherCtor, "sha512") : false;
|
|
5214
|
+
const blake2b = hasHasher ? probeCryptoHasher(HasherCtor, "blake2b256") : false;
|
|
5215
|
+
const cryptoHasherFeatures = Object.freeze({
|
|
5216
|
+
available: hasHasher && sha256,
|
|
5217
|
+
sha256,
|
|
5218
|
+
sha512,
|
|
5219
|
+
blake2b
|
|
5220
|
+
});
|
|
5221
|
+
const hasGlob = typeof B2.Glob === "function";
|
|
5222
|
+
this.cached = Object.freeze({
|
|
5223
|
+
runtime: kind2,
|
|
5224
|
+
bunVersion: B2.version ?? null,
|
|
5225
|
+
password: passwordFeatures,
|
|
5226
|
+
cryptoHasher: cryptoHasherFeatures,
|
|
5227
|
+
glob: hasGlob
|
|
5228
|
+
});
|
|
5229
|
+
return this.cached;
|
|
5230
|
+
}
|
|
5231
|
+
static reset() {
|
|
5232
|
+
this.cached = null;
|
|
5233
|
+
}
|
|
5234
|
+
}
|
|
5235
|
+
function formatCapabilityReport(f) {
|
|
5236
|
+
const passwordPart = f.password.argon2id ? "Bun.password argon2id \u2713" : "Bun.password argon2id \u2717 (fallback: none)";
|
|
5237
|
+
const hasherPart = f.cryptoHasher.available ? "Bun.CryptoHasher \u2713" : "Bun.CryptoHasher \u2717 (fallback: node:crypto)";
|
|
5238
|
+
const globPart = f.glob ? "Bun.Glob \u2713" : "Bun.Glob \u2717 (fallback: node:fs glob)";
|
|
5239
|
+
return `[gravito] native: ${passwordPart}, ${hasherPart}, ${globPart}`;
|
|
5240
|
+
}
|
|
5241
|
+
|
|
4820
5242
|
// src/runtime/archive.ts
|
|
4821
5243
|
function createBunArchiveAdapter() {
|
|
4822
5244
|
return {
|
|
@@ -4956,6 +5378,9 @@ async function archiveFromDirectory(dirPath, archivePath, options = {}) {
|
|
|
4956
5378
|
let entries = {};
|
|
4957
5379
|
if (kind === "bun") {
|
|
4958
5380
|
const B = globalThis.Bun;
|
|
5381
|
+
if (!B?.Glob || !B.file) {
|
|
5382
|
+
throw new Error("[RuntimeArchiveAdapter] Bun global not available for directory scanning");
|
|
5383
|
+
}
|
|
4959
5384
|
const glob = new B.Glob(options.glob ?? "**/*");
|
|
4960
5385
|
for await (const file of glob.scan(dirPath)) {
|
|
4961
5386
|
const pathMod = await eval('import("node:path")');
|
|
@@ -5569,6 +5994,9 @@ function getPasswordAdapter() {
|
|
|
5569
5994
|
};
|
|
5570
5995
|
return passwordAdapter;
|
|
5571
5996
|
}
|
|
5997
|
+
function resetPasswordAdapter() {
|
|
5998
|
+
passwordAdapter = null;
|
|
5999
|
+
}
|
|
5572
6000
|
async function createSqliteDatabase(path2) {
|
|
5573
6001
|
const kind2 = getRuntimeKind();
|
|
5574
6002
|
const B2 = globalThis.Bun;
|
|
@@ -5670,15 +6098,6 @@ class ConfigManager {
|
|
|
5670
6098
|
}
|
|
5671
6099
|
}
|
|
5672
6100
|
|
|
5673
|
-
// src/exceptions/CircularDependencyException.ts
|
|
5674
|
-
class CircularDependencyException extends Error {
|
|
5675
|
-
constructor(key, stack) {
|
|
5676
|
-
const path2 = [...stack, key].map(String).join(" -> ");
|
|
5677
|
-
super(`Circular dependency detected: ${path2}`);
|
|
5678
|
-
this.name = "CircularDependencyException";
|
|
5679
|
-
}
|
|
5680
|
-
}
|
|
5681
|
-
|
|
5682
6101
|
// src/Container.ts
|
|
5683
6102
|
var scopeStorage = new AsyncLocalStorage;
|
|
5684
6103
|
|
|
@@ -5703,6 +6122,17 @@ class Container {
|
|
|
5703
6122
|
scope: "singleton"
|
|
5704
6123
|
});
|
|
5705
6124
|
}
|
|
6125
|
+
singletonInline(namespace, key, factory) {
|
|
6126
|
+
const namespacedKey = `inline:${namespace}:${key}`;
|
|
6127
|
+
if (this.has(namespacedKey)) {
|
|
6128
|
+
if (true) {
|
|
6129
|
+
throw new ContainerBindingCollisionException(`Binding '${namespacedKey}' already registered by plugin '${namespace}'`);
|
|
6130
|
+
}
|
|
6131
|
+
console.warn(`[gravito] Binding '${namespacedKey}' collision detected \u2014 skipping duplicate registration.`);
|
|
6132
|
+
return;
|
|
6133
|
+
}
|
|
6134
|
+
this.singleton(namespacedKey, factory);
|
|
6135
|
+
}
|
|
5706
6136
|
scoped(key, factory) {
|
|
5707
6137
|
this.bindings.set(key, {
|
|
5708
6138
|
factory,
|
|
@@ -5840,63 +6270,6 @@ function detectRequestScopeLeaks(context) {
|
|
|
5840
6270
|
};
|
|
5841
6271
|
}
|
|
5842
6272
|
|
|
5843
|
-
// src/exceptions/GravitoException.ts
|
|
5844
|
-
class GravitoException extends Error {
|
|
5845
|
-
status;
|
|
5846
|
-
code;
|
|
5847
|
-
i18nKey;
|
|
5848
|
-
i18nParams;
|
|
5849
|
-
constructor(status, code, options2 = {}) {
|
|
5850
|
-
super(options2.message);
|
|
5851
|
-
this.name = "GravitoException";
|
|
5852
|
-
this.status = status;
|
|
5853
|
-
this.cause = options2.cause;
|
|
5854
|
-
this.code = code;
|
|
5855
|
-
if (options2.i18nKey) {
|
|
5856
|
-
this.i18nKey = options2.i18nKey;
|
|
5857
|
-
}
|
|
5858
|
-
if (options2.i18nParams) {
|
|
5859
|
-
this.i18nParams = options2.i18nParams;
|
|
5860
|
-
}
|
|
5861
|
-
}
|
|
5862
|
-
getLocalizedMessage(t) {
|
|
5863
|
-
if (this.i18nKey) {
|
|
5864
|
-
return t(this.i18nKey, this.i18nParams);
|
|
5865
|
-
}
|
|
5866
|
-
return this.message;
|
|
5867
|
-
}
|
|
5868
|
-
}
|
|
5869
|
-
|
|
5870
|
-
// src/exceptions/HttpException.ts
|
|
5871
|
-
class HttpException extends GravitoException {
|
|
5872
|
-
constructor(status, options2 = {}) {
|
|
5873
|
-
super(status, "HTTP_ERROR", options2);
|
|
5874
|
-
this.name = "HttpException";
|
|
5875
|
-
}
|
|
5876
|
-
}
|
|
5877
|
-
|
|
5878
|
-
// src/exceptions/ValidationException.ts
|
|
5879
|
-
class ValidationException extends GravitoException {
|
|
5880
|
-
errors;
|
|
5881
|
-
redirectTo;
|
|
5882
|
-
input;
|
|
5883
|
-
constructor(errors, message = "Validation failed") {
|
|
5884
|
-
super(422, "VALIDATION_ERROR", {
|
|
5885
|
-
message,
|
|
5886
|
-
i18nKey: "errors.validation.failed"
|
|
5887
|
-
});
|
|
5888
|
-
this.errors = errors;
|
|
5889
|
-
}
|
|
5890
|
-
withRedirect(url) {
|
|
5891
|
-
this.redirectTo = url;
|
|
5892
|
-
return this;
|
|
5893
|
-
}
|
|
5894
|
-
withInput(input) {
|
|
5895
|
-
this.input = input;
|
|
5896
|
-
return this;
|
|
5897
|
-
}
|
|
5898
|
-
}
|
|
5899
|
-
|
|
5900
6273
|
// src/helpers/response.ts
|
|
5901
6274
|
function ok(data) {
|
|
5902
6275
|
return { success: true, data };
|
|
@@ -9322,59 +9695,60 @@ class EventMetrics {
|
|
|
9322
9695
|
circuitBreakerSuccessesCounter;
|
|
9323
9696
|
circuitBreakerOpenDurationHistogram;
|
|
9324
9697
|
constructor(registry, prefix = "gravito_event_") {
|
|
9325
|
-
|
|
9698
|
+
const reg = registry;
|
|
9699
|
+
this.dispatchLatency = reg.histogram({
|
|
9326
9700
|
name: `${prefix}dispatch_latency_seconds`,
|
|
9327
9701
|
help: "Event dispatch latency in seconds",
|
|
9328
9702
|
labels: ["event_name", "priority"],
|
|
9329
9703
|
buckets: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 2, 5]
|
|
9330
9704
|
});
|
|
9331
|
-
this.listenerExecutionTime =
|
|
9705
|
+
this.listenerExecutionTime = reg.histogram({
|
|
9332
9706
|
name: `${prefix}listener_execution_seconds`,
|
|
9333
9707
|
help: "Listener execution time in seconds",
|
|
9334
9708
|
labels: ["event_name", "listener_index"],
|
|
9335
9709
|
buckets: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 2, 5]
|
|
9336
9710
|
});
|
|
9337
|
-
this.queueDepthGauge =
|
|
9711
|
+
this.queueDepthGauge = reg.gauge({
|
|
9338
9712
|
name: `${prefix}queue_depth`,
|
|
9339
9713
|
help: "Current queue depth by priority",
|
|
9340
9714
|
labels: ["priority"]
|
|
9341
9715
|
});
|
|
9342
|
-
this.failureCounter =
|
|
9716
|
+
this.failureCounter = reg.counter({
|
|
9343
9717
|
name: `${prefix}failures_total`,
|
|
9344
9718
|
help: "Total number of failed event processing",
|
|
9345
9719
|
labels: ["event_name", "error_type"]
|
|
9346
9720
|
});
|
|
9347
|
-
this.timeoutCounter =
|
|
9721
|
+
this.timeoutCounter = reg.counter({
|
|
9348
9722
|
name: `${prefix}timeouts_total`,
|
|
9349
9723
|
help: "Total number of event processing timeouts",
|
|
9350
9724
|
labels: ["event_name"]
|
|
9351
9725
|
});
|
|
9352
|
-
this.processedCounter =
|
|
9726
|
+
this.processedCounter = reg.counter({
|
|
9353
9727
|
name: `${prefix}processed_total`,
|
|
9354
9728
|
help: "Total number of processed events",
|
|
9355
9729
|
labels: ["event_name", "status"]
|
|
9356
9730
|
});
|
|
9357
|
-
this.circuitBreakerStateGauge =
|
|
9731
|
+
this.circuitBreakerStateGauge = reg.gauge({
|
|
9358
9732
|
name: `${prefix}circuit_breaker_state`,
|
|
9359
9733
|
help: "Current circuit breaker state (0=CLOSED, 1=HALF_OPEN, 2=OPEN)",
|
|
9360
9734
|
labels: ["event_name"]
|
|
9361
9735
|
});
|
|
9362
|
-
this.circuitBreakerTransitionsCounter =
|
|
9736
|
+
this.circuitBreakerTransitionsCounter = reg.counter({
|
|
9363
9737
|
name: `${prefix}circuit_breaker_transitions_total`,
|
|
9364
9738
|
help: "Total number of circuit breaker state transitions",
|
|
9365
9739
|
labels: ["event_name", "from_state", "to_state"]
|
|
9366
9740
|
});
|
|
9367
|
-
this.circuitBreakerFailuresCounter =
|
|
9741
|
+
this.circuitBreakerFailuresCounter = reg.counter({
|
|
9368
9742
|
name: `${prefix}circuit_breaker_failures_total`,
|
|
9369
9743
|
help: "Total number of failures tracked by circuit breaker",
|
|
9370
9744
|
labels: ["event_name"]
|
|
9371
9745
|
});
|
|
9372
|
-
this.circuitBreakerSuccessesCounter =
|
|
9746
|
+
this.circuitBreakerSuccessesCounter = reg.counter({
|
|
9373
9747
|
name: `${prefix}circuit_breaker_successes_total`,
|
|
9374
9748
|
help: "Total number of successes tracked by circuit breaker",
|
|
9375
9749
|
labels: ["event_name"]
|
|
9376
9750
|
});
|
|
9377
|
-
this.circuitBreakerOpenDurationHistogram =
|
|
9751
|
+
this.circuitBreakerOpenDurationHistogram = reg.histogram({
|
|
9378
9752
|
name: `${prefix}circuit_breaker_open_duration_seconds`,
|
|
9379
9753
|
help: "Duration of circuit breaker OPEN state in seconds",
|
|
9380
9754
|
labels: ["event_name"],
|
|
@@ -9767,7 +10141,7 @@ class ObservableHookManager extends HookManager {
|
|
|
9767
10141
|
let span;
|
|
9768
10142
|
if (this.eventTracing) {
|
|
9769
10143
|
span = this.eventTracing.startDispatchSpan(hook, callbacks.length, "normal");
|
|
9770
|
-
span
|
|
10144
|
+
span?.setAttributes({ "event.dispatch_mode": "sync" });
|
|
9771
10145
|
} else if (this.eventTracer) {
|
|
9772
10146
|
span = this.eventTracer.startDispatchSpan(hook, callbacks.length, "normal");
|
|
9773
10147
|
}
|
|
@@ -9912,18 +10286,18 @@ class OTelEventMetrics {
|
|
|
9912
10286
|
});
|
|
9913
10287
|
}
|
|
9914
10288
|
});
|
|
9915
|
-
this.cbFailuresCounter = meter2.createCounter
|
|
10289
|
+
this.cbFailuresCounter = meter2.createCounter(`${prefix}circuit_breaker_failures_total`, {
|
|
9916
10290
|
description: "Total number of failures recorded by circuit breakers",
|
|
9917
10291
|
unit: "{failures}"
|
|
9918
|
-
})
|
|
9919
|
-
this.cbSuccessesCounter = meter2.createCounter
|
|
10292
|
+
});
|
|
10293
|
+
this.cbSuccessesCounter = meter2.createCounter(`${prefix}circuit_breaker_successes_total`, {
|
|
9920
10294
|
description: "Total number of successes recorded by circuit breakers",
|
|
9921
10295
|
unit: "{successes}"
|
|
9922
|
-
})
|
|
9923
|
-
this.cbTransitionsCounter = meter2.createCounter
|
|
10296
|
+
});
|
|
10297
|
+
this.cbTransitionsCounter = meter2.createCounter(`${prefix}circuit_breaker_transitions_total`, {
|
|
9924
10298
|
description: "Total number of state transitions in circuit breakers",
|
|
9925
10299
|
unit: "{transitions}"
|
|
9926
|
-
})
|
|
10300
|
+
});
|
|
9927
10301
|
this.cbOpenDurationHistogram = meter2.createHistogram(`${prefix}circuit_breaker_open_duration_seconds`, {
|
|
9928
10302
|
description: "Duration that circuit breakers remain in OPEN state",
|
|
9929
10303
|
unit: "s",
|
|
@@ -9931,10 +10305,10 @@ class OTelEventMetrics {
|
|
|
9931
10305
|
explicitBucketBoundaries: this.cbOpenDurationBuckets
|
|
9932
10306
|
}
|
|
9933
10307
|
});
|
|
9934
|
-
this.backpressureRejectionsCounter = meter2.createCounter
|
|
10308
|
+
this.backpressureRejectionsCounter = meter2.createCounter(`${prefix}backpressure_rejections_total`, {
|
|
9935
10309
|
description: "Total number of events rejected due to backpressure",
|
|
9936
10310
|
unit: "{rejections}"
|
|
9937
|
-
})
|
|
10311
|
+
});
|
|
9938
10312
|
this.backpressureStateGauge = meter2.createObservableGauge(`${prefix}backpressure_state`, {
|
|
9939
10313
|
description: "Current backpressure state (0=NORMAL, 1=WARNING, 2=CRITICAL, 3=OVERFLOW)",
|
|
9940
10314
|
unit: "{state}"
|
|
@@ -9948,14 +10322,14 @@ class OTelEventMetrics {
|
|
|
9948
10322
|
};
|
|
9949
10323
|
observableResult.observe(stateMap[this.backpressureStateValue] ?? 0);
|
|
9950
10324
|
});
|
|
9951
|
-
this.backpressureDegradationsCounter = meter2.createCounter
|
|
10325
|
+
this.backpressureDegradationsCounter = meter2.createCounter(`${prefix}backpressure_degradations_total`, {
|
|
9952
10326
|
description: "Total number of priority degradations due to backpressure",
|
|
9953
10327
|
unit: "{degradations}"
|
|
9954
|
-
})
|
|
9955
|
-
this.dlqEntriesCounter = meter2.createCounter
|
|
10328
|
+
});
|
|
10329
|
+
this.dlqEntriesCounter = meter2.createCounter(`${prefix}dlq_entries_total`, {
|
|
9956
10330
|
description: "Total number of events added to Dead Letter Queue",
|
|
9957
10331
|
unit: "{entries}"
|
|
9958
|
-
})
|
|
10332
|
+
});
|
|
9959
10333
|
this.dlqDepthGauge = meter2.createObservableGauge(`${prefix}dlq_depth`, {
|
|
9960
10334
|
description: "Current Dead Letter Queue depth",
|
|
9961
10335
|
unit: "{events}"
|
|
@@ -9965,18 +10339,18 @@ class OTelEventMetrics {
|
|
|
9965
10339
|
observableResult.observe(this.dlqDepthCallback());
|
|
9966
10340
|
}
|
|
9967
10341
|
});
|
|
9968
|
-
this.dlqRequeueCounter = meter2.createCounter
|
|
10342
|
+
this.dlqRequeueCounter = meter2.createCounter(`${prefix}dlq_requeue_total`, {
|
|
9969
10343
|
description: "Total number of DLQ requeue attempts",
|
|
9970
10344
|
unit: "{attempts}"
|
|
9971
|
-
})
|
|
9972
|
-
this.retryAttemptsCounter = meter2.createCounter
|
|
10345
|
+
});
|
|
10346
|
+
this.retryAttemptsCounter = meter2.createCounter(`${prefix}retry_attempts_total`, {
|
|
9973
10347
|
description: "Total number of event retry attempts",
|
|
9974
10348
|
unit: "{attempts}"
|
|
9975
|
-
})
|
|
9976
|
-
this.priorityEscalationCounter = meter2.createCounter
|
|
10349
|
+
});
|
|
10350
|
+
this.priorityEscalationCounter = meter2.createCounter(`${prefix}priority_escalation_total`, {
|
|
9977
10351
|
description: "Total number of priority escalations",
|
|
9978
10352
|
unit: "{escalations}"
|
|
9979
|
-
})
|
|
10353
|
+
});
|
|
9980
10354
|
}
|
|
9981
10355
|
recordDispatchDuration(eventName, priority, durationSeconds) {
|
|
9982
10356
|
this.dispatchDurationHistogram.record(durationSeconds, {
|
|
@@ -10911,23 +11285,6 @@ class CookieJar {
|
|
|
10911
11285
|
}
|
|
10912
11286
|
}
|
|
10913
11287
|
|
|
10914
|
-
// src/exceptions/ModelNotFoundException.ts
|
|
10915
|
-
class ModelNotFoundException extends GravitoException {
|
|
10916
|
-
model;
|
|
10917
|
-
id;
|
|
10918
|
-
constructor(model, id) {
|
|
10919
|
-
super(404, "NOT_FOUND", {
|
|
10920
|
-
message: `${model} not found.`,
|
|
10921
|
-
i18nKey: "errors.model.not_found",
|
|
10922
|
-
i18nParams: { model, id: String(id ?? "") }
|
|
10923
|
-
});
|
|
10924
|
-
this.model = model;
|
|
10925
|
-
if (id !== undefined) {
|
|
10926
|
-
this.id = id;
|
|
10927
|
-
}
|
|
10928
|
-
}
|
|
10929
|
-
}
|
|
10930
|
-
|
|
10931
11288
|
// src/Route.ts
|
|
10932
11289
|
class Route {
|
|
10933
11290
|
router;
|
|
@@ -10944,6 +11301,13 @@ class Route {
|
|
|
10944
11301
|
this.router.registerName(name, this.method, this.path, this.options);
|
|
10945
11302
|
return this;
|
|
10946
11303
|
}
|
|
11304
|
+
schema(schemas) {
|
|
11305
|
+
this.options.schema = {
|
|
11306
|
+
...this.options.schema || {},
|
|
11307
|
+
...schemas
|
|
11308
|
+
};
|
|
11309
|
+
return this;
|
|
11310
|
+
}
|
|
10947
11311
|
static get(path2, requestOrHandlerOrMiddleware, handler) {
|
|
10948
11312
|
return router().req("get", path2, requestOrHandlerOrMiddleware, handler);
|
|
10949
11313
|
}
|
|
@@ -11139,18 +11503,20 @@ class Router {
|
|
|
11139
11503
|
const compiled = [];
|
|
11140
11504
|
const nameMap = new Map;
|
|
11141
11505
|
for (const [name, info] of this.namedRoutes) {
|
|
11142
|
-
nameMap.set(`${info.method.toUpperCase()}:${info.path}`, name);
|
|
11506
|
+
nameMap.set(`${info.method.toUpperCase()}:${info.path}`, { name, options: info.options });
|
|
11143
11507
|
}
|
|
11144
11508
|
const compiledKeys = new Set;
|
|
11145
11509
|
for (const route of this.routes) {
|
|
11146
11510
|
const method = route.method.toUpperCase();
|
|
11147
11511
|
const key = `${method}:${route.path}`;
|
|
11148
11512
|
compiledKeys.add(key);
|
|
11513
|
+
const namedInfo = nameMap.get(key);
|
|
11149
11514
|
compiled.push({
|
|
11150
11515
|
method,
|
|
11151
11516
|
path: route.path,
|
|
11152
11517
|
domain: route.domain,
|
|
11153
|
-
name:
|
|
11518
|
+
name: namedInfo?.name,
|
|
11519
|
+
schema: route.options?.schema || namedInfo?.options?.schema
|
|
11154
11520
|
});
|
|
11155
11521
|
}
|
|
11156
11522
|
for (const [name, info] of this.namedRoutes) {
|
|
@@ -11160,7 +11526,8 @@ class Router {
|
|
|
11160
11526
|
name,
|
|
11161
11527
|
method: info.method.toUpperCase(),
|
|
11162
11528
|
path: info.path,
|
|
11163
|
-
domain: info.domain
|
|
11529
|
+
domain: info.domain,
|
|
11530
|
+
schema: info.options?.schema
|
|
11164
11531
|
});
|
|
11165
11532
|
}
|
|
11166
11533
|
}
|
|
@@ -11171,7 +11538,8 @@ class Router {
|
|
|
11171
11538
|
this.namedRoutes.set(name, {
|
|
11172
11539
|
method: method.toUpperCase(),
|
|
11173
11540
|
path: fullPath,
|
|
11174
|
-
domain: options2.domain
|
|
11541
|
+
domain: options2.domain,
|
|
11542
|
+
options: options2
|
|
11175
11543
|
});
|
|
11176
11544
|
}
|
|
11177
11545
|
url(name, params = {}, query = {}) {
|
|
@@ -11211,7 +11579,7 @@ class Router {
|
|
|
11211
11579
|
if (modelClass && typeof modelClass === "object" && "find" in modelClass && typeof modelClass.find === "function") {
|
|
11212
11580
|
const instance = await modelClass.find(id);
|
|
11213
11581
|
if (!instance) {
|
|
11214
|
-
throw new
|
|
11582
|
+
throw new ModelNotFoundException(param, String(id));
|
|
11215
11583
|
}
|
|
11216
11584
|
return instance;
|
|
11217
11585
|
}
|
|
@@ -11233,17 +11601,9 @@ class Router {
|
|
|
11233
11601
|
if (!resolver) {
|
|
11234
11602
|
continue;
|
|
11235
11603
|
}
|
|
11236
|
-
|
|
11237
|
-
|
|
11238
|
-
|
|
11239
|
-
hasResolvedModels = true;
|
|
11240
|
-
} catch (err) {
|
|
11241
|
-
const message = err instanceof Error ? err.message : undefined;
|
|
11242
|
-
if (message === "ModelNotFound") {
|
|
11243
|
-
throw new ModelNotFoundException(param, value2);
|
|
11244
|
-
}
|
|
11245
|
-
throw err;
|
|
11246
|
-
}
|
|
11604
|
+
const resolved = await resolver(value2);
|
|
11605
|
+
routeModels[param] = resolved;
|
|
11606
|
+
hasResolvedModels = true;
|
|
11247
11607
|
}
|
|
11248
11608
|
if (hasResolvedModels) {
|
|
11249
11609
|
c.set("routeModels", routeModels);
|
|
@@ -11307,7 +11667,6 @@ class Router {
|
|
|
11307
11667
|
}
|
|
11308
11668
|
req(method, path2, requestOrHandlerOrMiddleware, handler, options2 = {}) {
|
|
11309
11669
|
const fullPath = (options2.prefix || "") + path2;
|
|
11310
|
-
console.log(`[Router] Registering ${method.toUpperCase()} ${fullPath}`);
|
|
11311
11670
|
let formRequestMiddleware = null;
|
|
11312
11671
|
let routeMiddleware = [];
|
|
11313
11672
|
let finalRouteHandler;
|
|
@@ -11349,11 +11708,16 @@ class Router {
|
|
|
11349
11708
|
if (c.req.header("host") !== options2.domain) {
|
|
11350
11709
|
return c.text("Not Found", 404);
|
|
11351
11710
|
}
|
|
11352
|
-
await next();
|
|
11711
|
+
return await next();
|
|
11353
11712
|
};
|
|
11354
11713
|
handlers.unshift(domainCheck);
|
|
11355
11714
|
}
|
|
11356
|
-
this.routes.push({
|
|
11715
|
+
this.routes.push({
|
|
11716
|
+
method: method.toUpperCase(),
|
|
11717
|
+
path: fullPath,
|
|
11718
|
+
domain: options2.domain,
|
|
11719
|
+
options: options2
|
|
11720
|
+
});
|
|
11357
11721
|
this.core.adapter.route(method, fullPath, ...handlers);
|
|
11358
11722
|
return new Route(this, method, fullPath, options2);
|
|
11359
11723
|
}
|
|
@@ -11471,14 +11835,16 @@ class PlanetCore {
|
|
|
11471
11835
|
services = new Map;
|
|
11472
11836
|
encrypter;
|
|
11473
11837
|
hasher;
|
|
11838
|
+
installedOrbits = [];
|
|
11474
11839
|
observabilityProvider;
|
|
11475
11840
|
providers = [];
|
|
11476
11841
|
deferredProviders = new Map;
|
|
11477
11842
|
bootedProviders = new Set;
|
|
11478
11843
|
isShuttingDown = false;
|
|
11844
|
+
static GLOBAL_SHUTDOWN_TIMEOUT = 1e4;
|
|
11479
11845
|
async initializeObservabilityAsync(obsConfig) {
|
|
11480
11846
|
try {
|
|
11481
|
-
if (this.observabilityProvider && this.observabilityProvider !==
|
|
11847
|
+
if (this.observabilityProvider && this.observabilityProvider._isNoOp !== true) {
|
|
11482
11848
|
this.logger.info("[Observability] \u2705 Using observability provider from @gravito/monitor");
|
|
11483
11849
|
if (obsConfig?.prometheus?.enabled !== false) {
|
|
11484
11850
|
await this.initializePrometheusAsync(obsConfig);
|
|
@@ -11520,10 +11886,11 @@ class PlanetCore {
|
|
|
11520
11886
|
this.logger.debug("[Observability] Prometheus setup moved to @gravito/monitor. Use monitor package for metrics initialization.");
|
|
11521
11887
|
}
|
|
11522
11888
|
register(provider) {
|
|
11523
|
-
|
|
11524
|
-
|
|
11889
|
+
const providerRecord = provider;
|
|
11890
|
+
if (typeof providerRecord["setCore"] === "function") {
|
|
11891
|
+
providerRecord["setCore"](this);
|
|
11525
11892
|
} else {
|
|
11526
|
-
|
|
11893
|
+
providerRecord["core"] = this;
|
|
11527
11894
|
}
|
|
11528
11895
|
if (provider.deferred) {
|
|
11529
11896
|
const services = provider.provides();
|
|
@@ -11577,15 +11944,23 @@ class PlanetCore {
|
|
|
11577
11944
|
}
|
|
11578
11945
|
this.isShuttingDown = true;
|
|
11579
11946
|
this.logger.debug("\uD83D\uDED1 Application shutdown started");
|
|
11580
|
-
|
|
11581
|
-
|
|
11582
|
-
|
|
11583
|
-
|
|
11584
|
-
|
|
11585
|
-
|
|
11586
|
-
|
|
11947
|
+
const shutdownSequence = async () => {
|
|
11948
|
+
for (const provider of [...this.providers].reverse()) {
|
|
11949
|
+
if (provider.onShutdown) {
|
|
11950
|
+
try {
|
|
11951
|
+
this.logger.debug(` onShutdown: ${provider.constructor.name}`);
|
|
11952
|
+
await provider.onShutdown(this);
|
|
11953
|
+
} catch (error) {
|
|
11954
|
+
this.logger.error(`Error during shutdown of ${provider.constructor.name}:`, error);
|
|
11955
|
+
}
|
|
11587
11956
|
}
|
|
11588
11957
|
}
|
|
11958
|
+
};
|
|
11959
|
+
const globalDeadline = new Promise((_, reject) => setTimeout(() => reject(new Error("[PlanetCore] Global shutdown timeout exceeded (10s)")), PlanetCore.GLOBAL_SHUTDOWN_TIMEOUT));
|
|
11960
|
+
try {
|
|
11961
|
+
await Promise.race([shutdownSequence(), globalDeadline]);
|
|
11962
|
+
} catch (err) {
|
|
11963
|
+
this.logger.warn("[PlanetCore] Forced shutdown after global timeout:", err);
|
|
11589
11964
|
}
|
|
11590
11965
|
this.hooks.doAction("app:shutdown", this);
|
|
11591
11966
|
this.logger.debug("\u2705 Application shutdown complete");
|
|
@@ -11686,8 +12061,38 @@ class PlanetCore {
|
|
|
11686
12061
|
process.on("SIGTERM", () => handleSignal("SIGTERM"));
|
|
11687
12062
|
process.on("SIGINT", () => handleSignal("SIGINT"));
|
|
11688
12063
|
}
|
|
12064
|
+
async plugin(config3) {
|
|
12065
|
+
if (!config3.name) {
|
|
12066
|
+
throw new Error('plugin(): Lite Satellites require a "name" property to enable safe service namespacing. Consider naming it based on the feature (e.g., "ping", "health-check").');
|
|
12067
|
+
}
|
|
12068
|
+
const alreadyRegistered = this.installedOrbits.some((orbit) => orbit.name === config3.name);
|
|
12069
|
+
if (alreadyRegistered) {
|
|
12070
|
+
if (true) {
|
|
12071
|
+
throw new ContainerBindingCollisionException(`Lite Satellite name '${config3.name}' already registered`);
|
|
12072
|
+
}
|
|
12073
|
+
this.logger.warn(`[gravito] Lite Satellite '${config3.name}' already registered \u2014 skipping duplicate installation.`);
|
|
12074
|
+
return this;
|
|
12075
|
+
}
|
|
12076
|
+
this.logger.debug(`\uD83D\uDD0C Installing Lite Satellite: ${config3.name}`);
|
|
12077
|
+
this.installedOrbits.push({
|
|
12078
|
+
name: config3.name,
|
|
12079
|
+
dependencies: config3.dependencies || []
|
|
12080
|
+
});
|
|
12081
|
+
await config3.install(this);
|
|
12082
|
+
return this;
|
|
12083
|
+
}
|
|
11689
12084
|
async orbit(orbit) {
|
|
11690
12085
|
const instance = typeof orbit === "function" ? new orbit : orbit;
|
|
12086
|
+
const name = instance.name || instance.constructor.name;
|
|
12087
|
+
if (instance.name) {
|
|
12088
|
+
this.logger.debug(`\uD83D\uDEF0\uFE0F Installing Orbit: ${instance.name}`);
|
|
12089
|
+
} else {
|
|
12090
|
+
this.logger.debug(`\uD83D\uDEF0\uFE0F Installing Orbit: ${instance.constructor.name}`);
|
|
12091
|
+
}
|
|
12092
|
+
this.installedOrbits.push({
|
|
12093
|
+
name,
|
|
12094
|
+
dependencies: instance.dependencies || []
|
|
12095
|
+
});
|
|
11691
12096
|
await instance.install(this);
|
|
11692
12097
|
return this;
|
|
11693
12098
|
}
|
|
@@ -11712,17 +12117,24 @@ class PlanetCore {
|
|
|
11712
12117
|
...config3.logger && { logger: config3.logger },
|
|
11713
12118
|
...config3.config && { config: config3.config },
|
|
11714
12119
|
...config3.adapter && { adapter: config3.adapter },
|
|
11715
|
-
...config3.container && { container: config3.container }
|
|
12120
|
+
...config3.container && { container: config3.container },
|
|
12121
|
+
...config3.observabilityProvider && { observabilityProvider: config3.observabilityProvider }
|
|
11716
12122
|
});
|
|
12123
|
+
const features = NativeOrbitDetector.detectBunCapabilities();
|
|
12124
|
+
core.logger.info(formatCapabilityReport(features));
|
|
11717
12125
|
if (config3.orbits) {
|
|
11718
12126
|
for (const OrbitClassOrInstance of config3.orbits) {
|
|
11719
|
-
|
|
11720
|
-
|
|
11721
|
-
orbit = new OrbitClassOrInstance;
|
|
12127
|
+
if (typeof OrbitClassOrInstance !== "function" && OrbitClassOrInstance.name) {
|
|
12128
|
+
await core.plugin(OrbitClassOrInstance);
|
|
11722
12129
|
} else {
|
|
11723
|
-
orbit
|
|
12130
|
+
let orbit;
|
|
12131
|
+
if (typeof OrbitClassOrInstance === "function") {
|
|
12132
|
+
orbit = new OrbitClassOrInstance;
|
|
12133
|
+
} else {
|
|
12134
|
+
orbit = OrbitClassOrInstance;
|
|
12135
|
+
}
|
|
12136
|
+
await orbit.install(core);
|
|
11724
12137
|
}
|
|
11725
|
-
await orbit.install(core);
|
|
11726
12138
|
}
|
|
11727
12139
|
}
|
|
11728
12140
|
return core;
|
|
@@ -12492,7 +12904,8 @@ class MessageQueueBridge {
|
|
|
12492
12904
|
throw new Error(`[MessageQueueBridge] No listeners registered for event: ${eventName}`);
|
|
12493
12905
|
}
|
|
12494
12906
|
if (this.config.enableCircuitBreaker) {
|
|
12495
|
-
const
|
|
12907
|
+
const hm = this.config.hookManager;
|
|
12908
|
+
const breaker = hm.getCircuitBreaker?.(eventName);
|
|
12496
12909
|
if (breaker?.getState?.() === "OPEN") {
|
|
12497
12910
|
throw new Error(`[MessageQueueBridge] Circuit breaker is OPEN for event: ${eventName}`);
|
|
12498
12911
|
}
|
|
@@ -12618,9 +13031,9 @@ class RetryScheduler {
|
|
|
12618
13031
|
try {
|
|
12619
13032
|
const queue = this.getOrCreateQueue(eventName);
|
|
12620
13033
|
const delay = this.calculateDelay(retryCount);
|
|
12621
|
-
const
|
|
12622
|
-
if (typeof
|
|
12623
|
-
await
|
|
13034
|
+
const queueObj = queue;
|
|
13035
|
+
if (typeof queueObj.add === "function") {
|
|
13036
|
+
await queueObj.add.call(queue, "retry", { payload, error: error.message, retryCount }, { delay });
|
|
12624
13037
|
}
|
|
12625
13038
|
} catch (schedulerError) {
|
|
12626
13039
|
const err = schedulerError instanceof Error ? schedulerError : new Error(String(schedulerError));
|
|
@@ -13189,25 +13602,6 @@ class QueueDashboard {
|
|
|
13189
13602
|
return value2.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\n/g, "\\n");
|
|
13190
13603
|
}
|
|
13191
13604
|
}
|
|
13192
|
-
// src/exceptions/AuthenticationException.ts
|
|
13193
|
-
class AuthenticationException extends GravitoException {
|
|
13194
|
-
constructor(message = "Unauthenticated.") {
|
|
13195
|
-
super(401, "UNAUTHENTICATED", {
|
|
13196
|
-
message,
|
|
13197
|
-
i18nKey: "errors.authentication.unauthenticated"
|
|
13198
|
-
});
|
|
13199
|
-
}
|
|
13200
|
-
}
|
|
13201
|
-
|
|
13202
|
-
// src/exceptions/AuthorizationException.ts
|
|
13203
|
-
class AuthorizationException extends GravitoException {
|
|
13204
|
-
constructor(message = "This action is unauthorized.") {
|
|
13205
|
-
super(403, "FORBIDDEN", {
|
|
13206
|
-
message,
|
|
13207
|
-
i18nKey: "errors.authorization.forbidden"
|
|
13208
|
-
});
|
|
13209
|
-
}
|
|
13210
|
-
}
|
|
13211
13605
|
// src/ServiceProvider.ts
|
|
13212
13606
|
class ServiceProvider {
|
|
13213
13607
|
core;
|
|
@@ -13431,15 +13825,19 @@ class TestResponse {
|
|
|
13431
13825
|
async assertJsonStructure(structure) {
|
|
13432
13826
|
const json = await this.getJson();
|
|
13433
13827
|
const checkKeys = (data2, struct) => {
|
|
13434
|
-
|
|
13435
|
-
|
|
13436
|
-
|
|
13437
|
-
|
|
13438
|
-
|
|
13828
|
+
const structObj = struct;
|
|
13829
|
+
const dataObj = data2;
|
|
13830
|
+
for (const key in structObj) {
|
|
13831
|
+
if (Array.isArray(structObj[key])) {
|
|
13832
|
+
expect(Array.isArray(dataObj[key])).toBe(true);
|
|
13833
|
+
const dataArr = dataObj[key];
|
|
13834
|
+
const structArr = structObj[key];
|
|
13835
|
+
if (dataArr.length > 0) {
|
|
13836
|
+
checkKeys(dataArr[0], structArr[0]);
|
|
13439
13837
|
}
|
|
13440
|
-
} else if (typeof
|
|
13441
|
-
expect(typeof
|
|
13442
|
-
checkKeys(
|
|
13838
|
+
} else if (typeof structObj[key] === "object") {
|
|
13839
|
+
expect(typeof dataObj[key]).toBe("object");
|
|
13840
|
+
checkKeys(dataObj[key], structObj[key]);
|
|
13443
13841
|
} else {
|
|
13444
13842
|
expect(data2).toHaveProperty(key);
|
|
13445
13843
|
}
|
|
@@ -13888,6 +14286,7 @@ export {
|
|
|
13888
14286
|
runtimeAppendFile,
|
|
13889
14287
|
router,
|
|
13890
14288
|
resetRuntimeAdapter,
|
|
14289
|
+
resetPasswordAdapter,
|
|
13891
14290
|
registerQueueCommands,
|
|
13892
14291
|
registerGlobalErrorHandlers,
|
|
13893
14292
|
old,
|
|
@@ -13912,6 +14311,7 @@ export {
|
|
|
13912
14311
|
getCookie,
|
|
13913
14312
|
getCompressionAdapter,
|
|
13914
14313
|
getArchiveAdapter,
|
|
14314
|
+
formatCapabilityReport,
|
|
13915
14315
|
filled,
|
|
13916
14316
|
fail,
|
|
13917
14317
|
extractRequestScopeErrorContext,
|
|
@@ -13945,7 +14345,10 @@ export {
|
|
|
13945
14345
|
ValidationException,
|
|
13946
14346
|
VERSION,
|
|
13947
14347
|
TestResponse,
|
|
14348
|
+
SystemException,
|
|
14349
|
+
StreamException,
|
|
13948
14350
|
Str,
|
|
14351
|
+
StorageException,
|
|
13949
14352
|
StarvationProtectionStrategy,
|
|
13950
14353
|
ServiceProvider,
|
|
13951
14354
|
Router,
|
|
@@ -13961,6 +14364,7 @@ export {
|
|
|
13961
14364
|
RateLimitStrategy,
|
|
13962
14365
|
RadixRouter,
|
|
13963
14366
|
RadixNode,
|
|
14367
|
+
QueueException,
|
|
13964
14368
|
QueueDepthStrategy,
|
|
13965
14369
|
QueueDashboard,
|
|
13966
14370
|
PriorityRebalanceStrategy,
|
|
@@ -13969,7 +14373,9 @@ export {
|
|
|
13969
14373
|
ObservableHookManager,
|
|
13970
14374
|
OTelEventMetrics,
|
|
13971
14375
|
NodeType,
|
|
14376
|
+
NativeOrbitDetector,
|
|
13972
14377
|
ModelNotFoundException,
|
|
14378
|
+
InfrastructureException,
|
|
13973
14379
|
IdempotencyCache,
|
|
13974
14380
|
HttpTester,
|
|
13975
14381
|
HttpException,
|
|
@@ -13988,18 +14394,22 @@ export {
|
|
|
13988
14394
|
ErrorHandler,
|
|
13989
14395
|
Encrypter,
|
|
13990
14396
|
DumpDieError,
|
|
14397
|
+
DomainException,
|
|
13991
14398
|
DeadLetterQueueManager,
|
|
13992
14399
|
DeadLetterQueue,
|
|
14400
|
+
DatabaseException,
|
|
13993
14401
|
DEFAULT_EVENT_OPTIONS,
|
|
13994
14402
|
CookieJar,
|
|
13995
14403
|
Container,
|
|
13996
14404
|
ConsoleLogger,
|
|
14405
|
+
ConfigurationException,
|
|
13997
14406
|
ConfigManager,
|
|
13998
14407
|
CompositeStrategy,
|
|
13999
14408
|
CommandKernel,
|
|
14000
14409
|
CircularDependencyException,
|
|
14001
14410
|
CircuitBreakerState,
|
|
14002
14411
|
CircuitBreaker,
|
|
14412
|
+
CacheException,
|
|
14003
14413
|
BunWebSocketHandler,
|
|
14004
14414
|
BunRequest,
|
|
14005
14415
|
BunNativeAdapter,
|
|
@@ -14009,8 +14419,9 @@ export {
|
|
|
14009
14419
|
BackpressureManager,
|
|
14010
14420
|
AuthorizationException,
|
|
14011
14421
|
AuthenticationException,
|
|
14422
|
+
AuthException,
|
|
14012
14423
|
Arr,
|
|
14013
14424
|
Application
|
|
14014
14425
|
};
|
|
14015
14426
|
|
|
14016
|
-
//# debugId=
|
|
14427
|
+
//# debugId=AFB01087B997521264756E2164756E21
|