@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.
Files changed (72) hide show
  1. package/README.md +64 -25
  2. package/dist/Application.d.ts +2 -9
  3. package/dist/Container.d.ts +18 -1
  4. package/dist/GravitoServer.d.ts +8 -8
  5. package/dist/HookManager.d.ts +36 -34
  6. package/dist/PlanetCore.d.ts +54 -0
  7. package/dist/Route.d.ts +5 -0
  8. package/dist/Router.d.ts +14 -1
  9. package/dist/adapters/bun/BunContext.d.ts +1 -1
  10. package/dist/adapters/bun/BunNativeAdapter.d.ts +11 -1
  11. package/dist/adapters/bun/FastPathRegistry.d.ts +31 -0
  12. package/dist/adapters/bun/RadixNode.d.ts +4 -3
  13. package/dist/adapters/bun/RadixRouter.d.ts +2 -2
  14. package/dist/adapters/bun/types.d.ts +7 -0
  15. package/dist/adapters/types.d.ts +20 -0
  16. package/dist/compat/async-local-storage.d.ts +5 -1
  17. package/dist/compat/async-local-storage.js.map +2 -2
  18. package/dist/compat/crypto.d.ts +6 -1
  19. package/dist/compat/crypto.js.map +2 -2
  20. package/dist/engine/AOTRouter.d.ts +1 -1
  21. package/dist/engine/FastContext.d.ts +4 -4
  22. package/dist/engine/MinimalContext.d.ts +3 -3
  23. package/dist/engine/index.js +29 -8
  24. package/dist/engine/index.js.map +10 -10
  25. package/dist/engine/types.d.ts +5 -5
  26. package/dist/events/CircuitBreaker.d.ts +12 -0
  27. package/dist/events/MessageQueueBridge.d.ts +2 -1
  28. package/dist/events/observability/EventMetrics.d.ts +1 -2
  29. package/dist/events/observability/ObservableHookManager.d.ts +1 -1
  30. package/dist/exceptions/AuthException.d.ts +19 -0
  31. package/dist/exceptions/AuthenticationException.d.ts +9 -3
  32. package/dist/exceptions/AuthorizationException.d.ts +2 -2
  33. package/dist/exceptions/CacheException.d.ts +9 -0
  34. package/dist/exceptions/CircularDependencyException.d.ts +2 -1
  35. package/dist/exceptions/ConfigurationException.d.ts +9 -0
  36. package/dist/exceptions/ContainerBindingCollisionException.d.ts +10 -0
  37. package/dist/exceptions/DatabaseException.d.ts +9 -0
  38. package/dist/exceptions/DomainException.d.ts +9 -0
  39. package/dist/exceptions/InfrastructureException.d.ts +17 -0
  40. package/dist/exceptions/MiddlewareDriftException.d.ts +10 -0
  41. package/dist/exceptions/QueueException.d.ts +9 -0
  42. package/dist/exceptions/StorageException.d.ts +9 -0
  43. package/dist/exceptions/StreamException.d.ts +9 -0
  44. package/dist/exceptions/SystemException.d.ts +9 -0
  45. package/dist/exceptions/ValidationException.d.ts +2 -2
  46. package/dist/exceptions/index.d.ts +12 -0
  47. package/dist/ffi/NativeAccelerator.js.map +3 -3
  48. package/dist/ffi/NativeHasher.d.ts +14 -0
  49. package/dist/ffi/NativeHasher.js +24 -1
  50. package/dist/ffi/NativeHasher.js.map +4 -4
  51. package/dist/ffi/cbor-fallback.js.map +1 -1
  52. package/dist/ffi/hash-fallback.d.ts +15 -0
  53. package/dist/ffi/hash-fallback.js +12 -1
  54. package/dist/ffi/hash-fallback.js.map +3 -3
  55. package/dist/ffi/types.d.ts +13 -0
  56. package/dist/ffi/types.js.map +1 -1
  57. package/dist/hooks/types.d.ts +7 -3
  58. package/dist/http/types.d.ts +2 -2
  59. package/dist/index.browser.d.ts +5 -5
  60. package/dist/index.browser.js +190 -47
  61. package/dist/index.browser.js.map +50 -46
  62. package/dist/index.d.ts +17 -7
  63. package/dist/index.js +613 -202
  64. package/dist/index.js.map +82 -68
  65. package/dist/runtime/NativeOrbitDetector.d.ts +59 -0
  66. package/dist/runtime/index.browser.d.ts +1 -1
  67. package/dist/runtime/index.d.ts +7 -0
  68. package/dist/runtime.d.ts +1 -1
  69. package/dist/testing/HttpTester.d.ts +4 -4
  70. package/dist/testing/TestResponse.d.ts +4 -4
  71. package/dist/types.d.ts +3 -3
  72. package/package.json +4 -3
@@ -149,7 +149,7 @@ var randomBytes = randomBytesFn;
149
149
  // package.json
150
150
  var package_default = {
151
151
  name: "@gravito/core",
152
- version: "2.0.6",
152
+ version: "3.0.1",
153
153
  description: "",
154
154
  module: "./dist/index.js",
155
155
  main: "./dist/index.js",
@@ -158,9 +158,9 @@ var package_default = {
158
158
  types: "./dist/index.d.ts",
159
159
  exports: {
160
160
  ".": {
161
+ types: "./dist/index.d.ts",
161
162
  browser: "./dist/index.browser.js",
162
163
  bun: "./dist/index.js",
163
- types: "./dist/index.d.ts",
164
164
  default: "./dist/index.js"
165
165
  },
166
166
  "./compat": {
@@ -206,7 +206,8 @@ var package_default = {
206
206
  typecheck: "bun tsc -p tsconfig.json --noEmit --skipLibCheck",
207
207
  prepublishOnly: "bun run typecheck && bun run test && bun run build",
208
208
  "test:unit": "bun test $(find tests -name '*.test.ts' ! -name '*.integration.test.ts' 2>/dev/null | tr '\\n' ' ') --timeout=10000",
209
- "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'"
209
+ "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'",
210
+ publint: "publint"
210
211
  },
211
212
  keywords: [],
212
213
  author: "Carl Lee <carllee0520@gmail.com>",
@@ -253,6 +254,7 @@ class RadixNode {
253
254
  paramChild = null;
254
255
  wildcardChild = null;
255
256
  handlers = new Map;
257
+ options = new Map;
256
258
  paramName = null;
257
259
  regex = null;
258
260
  constructor(segment = "", type = 0 /* STATIC */) {
@@ -266,13 +268,15 @@ class RadixNode {
266
268
  children: Array.from(this.children.entries()).map(([k, v]) => [k, v.toJSON()]),
267
269
  paramChild: this.paramChild?.toJSON() || null,
268
270
  wildcardChild: this.wildcardChild?.toJSON() || null,
271
+ handlers: Array.from(this.handlers.entries()),
272
+ options: Array.from(this.options.entries()),
269
273
  paramName: this.paramName,
270
274
  regex: this.regex ? this.regex.source : null
271
275
  };
272
276
  }
273
277
  static fromJSON(json) {
274
278
  const node = new RadixNode(json.segment, json.type);
275
- node.paramName = json.paramName;
279
+ node.paramName = json.paramName ?? null;
276
280
  if (json.regex) {
277
281
  node.regex = new RegExp(json.regex);
278
282
  }
@@ -287,6 +291,16 @@ class RadixNode {
287
291
  if (json.wildcardChild) {
288
292
  node.wildcardChild = RadixNode.fromJSON(json.wildcardChild);
289
293
  }
294
+ if (json.handlers) {
295
+ for (const [method, handlers] of json.handlers) {
296
+ node.handlers.set(method, handlers);
297
+ }
298
+ }
299
+ if (json.options) {
300
+ for (const [method, options2] of json.options) {
301
+ node.options.set(method, options2);
302
+ }
303
+ }
290
304
  return node;
291
305
  }
292
306
  }
@@ -322,7 +336,7 @@ class RadixRouter {
322
336
  where(param, regex) {
323
337
  this.globalConstraints.set(param, regex);
324
338
  }
325
- add(method, path2, handlers) {
339
+ add(method, path2, handlers, options2) {
326
340
  let node = this.root;
327
341
  const segments = this.splitPath(path2);
328
342
  for (let i = 0;i < segments.length; i++) {
@@ -352,7 +366,11 @@ class RadixRouter {
352
366
  node = node.children.get(segment);
353
367
  }
354
368
  }
355
- node.handlers.set(method.toLowerCase(), handlers);
369
+ const normalizedMethod = method.toLowerCase();
370
+ node.handlers.set(normalizedMethod, handlers);
371
+ if (options2) {
372
+ node.options.set(normalizedMethod, options2);
373
+ }
356
374
  this.routeCache.clear();
357
375
  }
358
376
  match(method, path2) {
@@ -360,7 +378,7 @@ class RadixRouter {
360
378
  if (path2 === "/" || path2 === "") {
361
379
  const handlers = this.root.handlers.get(normalizedMethod);
362
380
  if (handlers) {
363
- return { handlers, params: {} };
381
+ return { handlers, params: {}, options: this.root.options.get(normalizedMethod) };
364
382
  }
365
383
  return null;
366
384
  }
@@ -377,11 +395,13 @@ class RadixRouter {
377
395
  matchRecursive(node, segments, depth, params, method) {
378
396
  if (depth >= segments.length) {
379
397
  let handlers = node.handlers.get(method);
398
+ let options2 = node.options.get(method);
380
399
  if (!handlers) {
381
400
  handlers = node.handlers.get("all");
401
+ options2 = node.options.get("all");
382
402
  }
383
403
  if (handlers) {
384
- return { handlers, params };
404
+ return { handlers, params, options: options2 };
385
405
  }
386
406
  return null;
387
407
  }
@@ -408,11 +428,13 @@ class RadixRouter {
408
428
  }
409
429
  if (node.wildcardChild) {
410
430
  let handlers = node.wildcardChild.handlers.get(method);
431
+ let options2 = node.wildcardChild.options.get(method);
411
432
  if (!handlers) {
412
433
  handlers = node.wildcardChild.handlers.get("all");
434
+ options2 = node.wildcardChild.options.get("all");
413
435
  }
414
436
  if (handlers) {
415
- return { handlers, params };
437
+ return { handlers, params, options: options2 };
416
438
  }
417
439
  }
418
440
  return null;
@@ -894,7 +916,7 @@ class RequestScopeManager {
894
916
  let servicesCleaned = 0;
895
917
  for (const [, instance] of this.scoped) {
896
918
  if (instance && typeof instance === "object" && "cleanup" in instance) {
897
- const fn = instance.cleanup;
919
+ const fn = instance["cleanup"];
898
920
  if (typeof fn === "function") {
899
921
  try {
900
922
  await fn.call(instance);
@@ -2548,7 +2570,8 @@ function createNodeAdapter() {
2548
2570
  },
2549
2571
  resourceUsage: async () => {
2550
2572
  try {
2551
- const usage = child.resourceUsage?.();
2573
+ const childWithUsage = child;
2574
+ const usage = childWithUsage.resourceUsage?.();
2552
2575
  if (!usage) {
2553
2576
  return;
2554
2577
  }
@@ -2757,6 +2780,78 @@ function createUnknownAdapter() {
2757
2780
  }
2758
2781
  };
2759
2782
  }
2783
+ // src/runtime/NativeOrbitDetector.ts
2784
+ function probeCryptoHasher(CryptoHasherCtor, algo) {
2785
+ try {
2786
+ const ctor = CryptoHasherCtor;
2787
+ new ctor(algo).update("").digest("hex");
2788
+ return true;
2789
+ } catch {
2790
+ return false;
2791
+ }
2792
+ }
2793
+
2794
+ class NativeOrbitDetector {
2795
+ static cached = null;
2796
+ static detectBunCapabilities() {
2797
+ if (this.cached !== null) {
2798
+ return this.cached;
2799
+ }
2800
+ const kind2 = getRuntimeKind();
2801
+ const B2 = globalThis.Bun;
2802
+ if (kind2 !== "bun" || !B2) {
2803
+ this.cached = Object.freeze({
2804
+ runtime: kind2,
2805
+ bunVersion: null,
2806
+ password: Object.freeze({ available: false, argon2id: false, bcrypt: false }),
2807
+ cryptoHasher: Object.freeze({
2808
+ available: false,
2809
+ sha256: false,
2810
+ sha512: false,
2811
+ blake2b: false
2812
+ }),
2813
+ glob: false
2814
+ });
2815
+ return this.cached;
2816
+ }
2817
+ const hasPassword = typeof B2.password?.hash === "function" && typeof B2.password?.verify === "function";
2818
+ const passwordFeatures = Object.freeze({
2819
+ available: hasPassword,
2820
+ argon2id: hasPassword,
2821
+ bcrypt: hasPassword
2822
+ });
2823
+ const HasherCtor = B2.CryptoHasher;
2824
+ const hasHasher = typeof HasherCtor === "function";
2825
+ const sha256 = hasHasher ? probeCryptoHasher(HasherCtor, "sha256") : false;
2826
+ const sha512 = hasHasher ? probeCryptoHasher(HasherCtor, "sha512") : false;
2827
+ const blake2b = hasHasher ? probeCryptoHasher(HasherCtor, "blake2b256") : false;
2828
+ const cryptoHasherFeatures = Object.freeze({
2829
+ available: hasHasher && sha256,
2830
+ sha256,
2831
+ sha512,
2832
+ blake2b
2833
+ });
2834
+ const hasGlob = typeof B2.Glob === "function";
2835
+ this.cached = Object.freeze({
2836
+ runtime: kind2,
2837
+ bunVersion: B2.version ?? null,
2838
+ password: passwordFeatures,
2839
+ cryptoHasher: cryptoHasherFeatures,
2840
+ glob: hasGlob
2841
+ });
2842
+ return this.cached;
2843
+ }
2844
+ static reset() {
2845
+ this.cached = null;
2846
+ }
2847
+ }
2848
+ function formatCapabilityReport(f) {
2849
+ const passwordPart = f.password.argon2id ? "Bun.password argon2id \u2713" : "Bun.password argon2id \u2717 (fallback: none)";
2850
+ const hasherPart = f.cryptoHasher.available ? "Bun.CryptoHasher \u2713" : "Bun.CryptoHasher \u2717 (fallback: node:crypto)";
2851
+ const globPart = f.glob ? "Bun.Glob \u2713" : "Bun.Glob \u2717 (fallback: node:fs glob)";
2852
+ return `[gravito] native: ${passwordPart}, ${hasherPart}, ${globPart}`;
2853
+ }
2854
+
2760
2855
  // src/runtime/archive.ts
2761
2856
  function createBunArchiveAdapter() {
2762
2857
  return {
@@ -2896,6 +2991,9 @@ async function archiveFromDirectory(dirPath, archivePath, options = {}) {
2896
2991
  let entries = {};
2897
2992
  if (kind === "bun") {
2898
2993
  const B = globalThis.Bun;
2994
+ if (!B?.Glob || !B.file) {
2995
+ throw new Error("[RuntimeArchiveAdapter] Bun global not available for directory scanning");
2996
+ }
2899
2997
  const glob = new B.Glob(options.glob ?? "**/*");
2900
2998
  for await (const file of glob.scan(dirPath)) {
2901
2999
  const pathMod = await eval('import("node:path")');
@@ -3509,6 +3607,9 @@ function getPasswordAdapter() {
3509
3607
  };
3510
3608
  return passwordAdapter;
3511
3609
  }
3610
+ function resetPasswordAdapter() {
3611
+ passwordAdapter = null;
3612
+ }
3512
3613
  async function createSqliteDatabase(path2) {
3513
3614
  const kind2 = getRuntimeKind();
3514
3615
  const B2 = globalThis.Bun;
@@ -3609,15 +3710,63 @@ class ConfigManager {
3609
3710
  }
3610
3711
  }
3611
3712
  }
3713
+ // src/exceptions/GravitoException.ts
3714
+ class GravitoException extends Error {
3715
+ status;
3716
+ code;
3717
+ i18nKey;
3718
+ i18nParams;
3719
+ constructor(status, code, options2 = {}) {
3720
+ super(options2.message);
3721
+ this.name = "GravitoException";
3722
+ this.status = status;
3723
+ this.cause = options2.cause;
3724
+ this.code = code;
3725
+ if (options2.i18nKey) {
3726
+ this.i18nKey = options2.i18nKey;
3727
+ }
3728
+ if (options2.i18nParams) {
3729
+ this.i18nParams = options2.i18nParams;
3730
+ }
3731
+ Object.setPrototypeOf(this, new.target.prototype);
3732
+ }
3733
+ getLocalizedMessage(t) {
3734
+ if (this.i18nKey) {
3735
+ return t(this.i18nKey, this.i18nParams);
3736
+ }
3737
+ return this.message;
3738
+ }
3739
+ }
3740
+
3741
+ // src/exceptions/SystemException.ts
3742
+ class SystemException extends GravitoException {
3743
+ constructor(status, code, options2 = {}) {
3744
+ super(status, code, options2);
3745
+ this.name = "SystemException";
3746
+ Object.setPrototypeOf(this, new.target.prototype);
3747
+ }
3748
+ }
3749
+
3612
3750
  // src/exceptions/CircularDependencyException.ts
3613
- class CircularDependencyException extends Error {
3751
+ class CircularDependencyException extends SystemException {
3614
3752
  constructor(key, stack) {
3615
3753
  const path2 = [...stack, key].map(String).join(" -> ");
3616
- super(`Circular dependency detected: ${path2}`);
3754
+ super(500, "system.circular_dependency", {
3755
+ message: `Circular dependency detected: ${path2}`
3756
+ });
3617
3757
  this.name = "CircularDependencyException";
3618
3758
  }
3619
3759
  }
3620
3760
 
3761
+ // src/exceptions/ContainerBindingCollisionException.ts
3762
+ class ContainerBindingCollisionException extends SystemException {
3763
+ constructor(message, options2 = {}) {
3764
+ super(500, "system.container_binding_collision", { ...options2, message });
3765
+ this.name = "ContainerBindingCollisionException";
3766
+ Object.setPrototypeOf(this, new.target.prototype);
3767
+ }
3768
+ }
3769
+
3621
3770
  // src/Container.ts
3622
3771
  var scopeStorage = new AsyncLocalStorage;
3623
3772
 
@@ -3642,6 +3791,17 @@ class Container {
3642
3791
  scope: "singleton"
3643
3792
  });
3644
3793
  }
3794
+ singletonInline(namespace, key, factory) {
3795
+ const namespacedKey = `inline:${namespace}:${key}`;
3796
+ if (this.has(namespacedKey)) {
3797
+ if (true) {
3798
+ throw new ContainerBindingCollisionException(`Binding '${namespacedKey}' already registered by plugin '${namespace}'`);
3799
+ }
3800
+ console.warn(`[gravito] Binding '${namespacedKey}' collision detected \u2014 skipping duplicate registration.`);
3801
+ return;
3802
+ }
3803
+ this.singleton(namespacedKey, factory);
3804
+ }
3645
3805
  scoped(key, factory) {
3646
3806
  this.bindings.set(key, {
3647
3807
  factory,
@@ -4107,33 +4267,6 @@ function detectRequestScopeLeaks(context) {
4107
4267
  };
4108
4268
  }
4109
4269
 
4110
- // src/exceptions/GravitoException.ts
4111
- class GravitoException extends Error {
4112
- status;
4113
- code;
4114
- i18nKey;
4115
- i18nParams;
4116
- constructor(status, code, options2 = {}) {
4117
- super(options2.message);
4118
- this.name = "GravitoException";
4119
- this.status = status;
4120
- this.cause = options2.cause;
4121
- this.code = code;
4122
- if (options2.i18nKey) {
4123
- this.i18nKey = options2.i18nKey;
4124
- }
4125
- if (options2.i18nParams) {
4126
- this.i18nParams = options2.i18nParams;
4127
- }
4128
- }
4129
- getLocalizedMessage(t) {
4130
- if (this.i18nKey) {
4131
- return t(this.i18nKey, this.i18nParams);
4132
- }
4133
- return this.message;
4134
- }
4135
- }
4136
-
4137
4270
  // src/exceptions/HttpException.ts
4138
4271
  class HttpException extends GravitoException {
4139
4272
  constructor(status, options2 = {}) {
@@ -4142,8 +4275,17 @@ class HttpException extends GravitoException {
4142
4275
  }
4143
4276
  }
4144
4277
 
4278
+ // src/exceptions/DomainException.ts
4279
+ class DomainException extends GravitoException {
4280
+ constructor(status, code, options2 = {}) {
4281
+ super(status, code, options2);
4282
+ this.name = "DomainException";
4283
+ Object.setPrototypeOf(this, new.target.prototype);
4284
+ }
4285
+ }
4286
+
4145
4287
  // src/exceptions/ValidationException.ts
4146
- class ValidationException extends GravitoException {
4288
+ class ValidationException extends DomainException {
4147
4289
  errors;
4148
4290
  redirectTo;
4149
4291
  input;
@@ -4152,6 +4294,7 @@ class ValidationException extends GravitoException {
4152
4294
  message,
4153
4295
  i18nKey: "errors.validation.failed"
4154
4296
  });
4297
+ this.name = "ValidationException";
4155
4298
  this.errors = errors;
4156
4299
  }
4157
4300
  withRedirect(url) {
@@ -6244,7 +6387,8 @@ class MessageQueueBridge {
6244
6387
  throw new Error(`[MessageQueueBridge] No listeners registered for event: ${eventName}`);
6245
6388
  }
6246
6389
  if (this.config.enableCircuitBreaker) {
6247
- const breaker = this.config.hookManager.getCircuitBreaker?.(eventName);
6390
+ const hm = this.config.hookManager;
6391
+ const breaker = hm.getCircuitBreaker?.(eventName);
6248
6392
  if (breaker?.getState?.() === "OPEN") {
6249
6393
  throw new Error(`[MessageQueueBridge] Circuit breaker is OPEN for event: ${eventName}`);
6250
6394
  }
@@ -6370,9 +6514,9 @@ class RetryScheduler {
6370
6514
  try {
6371
6515
  const queue = this.getOrCreateQueue(eventName);
6372
6516
  const delay = this.calculateDelay(retryCount);
6373
- const addMethod = queue.add;
6374
- if (typeof addMethod === "function") {
6375
- await addMethod.call(queue, "retry", { payload, error: error.message, retryCount }, { delay });
6517
+ const queueObj = queue;
6518
+ if (typeof queueObj.add === "function") {
6519
+ await queueObj.add.call(queue, "retry", { payload, error: error.message, retryCount }, { delay });
6376
6520
  }
6377
6521
  } catch (schedulerError) {
6378
6522
  const err = schedulerError instanceof Error ? schedulerError : new Error(String(schedulerError));
@@ -8953,7 +9097,6 @@ export {
8953
9097
  throwIf,
8954
9098
  tap,
8955
9099
  setCookie,
8956
- setApp,
8957
9100
  router,
8958
9101
  registerQueueCommands,
8959
9102
  old,
@@ -9030,4 +9173,4 @@ export {
9030
9173
  Arr
9031
9174
  };
9032
9175
 
9033
- //# debugId=1C1545AE2FF7EA4564756E2164756E21
9176
+ //# debugId=245BF91366B5C49E64756E2164756E21