@kanjijs/common 0.3.0-beta.1 → 1.0.0-alpha.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 (47) hide show
  1. package/LICENSE +21 -0
  2. package/dist/__tests__/cacheable.spec.d.ts +2 -0
  3. package/dist/__tests__/cacheable.spec.d.ts.map +1 -0
  4. package/dist/__tests__/cacheable.spec.js +150 -0
  5. package/dist/__tests__/cacheable.spec.js.map +1 -0
  6. package/dist/__tests__/logger.spec.d.ts +2 -0
  7. package/dist/__tests__/logger.spec.d.ts.map +1 -0
  8. package/dist/__tests__/logger.spec.js +29 -0
  9. package/dist/__tests__/logger.spec.js.map +1 -0
  10. package/dist/env.d.ts +5 -0
  11. package/dist/env.d.ts.map +1 -0
  12. package/dist/env.js +27 -0
  13. package/dist/env.js.map +1 -0
  14. package/dist/index.d.ts +9 -3
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +9 -20
  17. package/dist/index.js.map +1 -0
  18. package/dist/logger.d.ts +15 -0
  19. package/dist/logger.d.ts.map +1 -0
  20. package/dist/logger.js +45 -0
  21. package/dist/logger.js.map +1 -0
  22. package/dist/types.d.ts +13 -0
  23. package/dist/types.d.ts.map +1 -0
  24. package/dist/types.js +2 -0
  25. package/dist/types.js.map +1 -0
  26. package/dist/utils/cacheable.d.ts +17 -0
  27. package/dist/utils/cacheable.d.ts.map +1 -0
  28. package/dist/utils/cacheable.js +62 -0
  29. package/dist/utils/cacheable.js.map +1 -0
  30. package/dist/utils/decorators.d.ts +5 -0
  31. package/dist/utils/decorators.d.ts.map +1 -0
  32. package/dist/utils/decorators.js +28 -0
  33. package/dist/utils/decorators.js.map +1 -0
  34. package/dist/utils/errors.d.ts +36 -0
  35. package/dist/utils/errors.d.ts.map +1 -0
  36. package/dist/utils/errors.js +56 -0
  37. package/dist/utils/errors.js.map +1 -0
  38. package/dist/utils/exception-filter.d.ts +7 -0
  39. package/dist/utils/exception-filter.d.ts.map +1 -0
  40. package/dist/utils/exception-filter.js +11 -0
  41. package/dist/utils/exception-filter.js.map +1 -0
  42. package/dist/utils/helpers.d.ts +9 -0
  43. package/dist/utils/helpers.d.ts.map +1 -0
  44. package/dist/utils/helpers.js +49 -0
  45. package/dist/utils/helpers.js.map +1 -0
  46. package/package.json +12 -13
  47. package/dist/constants.d.ts +0 -71
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 David Sebastian Aguiar
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cacheable.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cacheable.spec.d.ts","sourceRoot":"","sources":["../../src/__tests__/cacheable.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,150 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { describe, it, expect, beforeEach } from 'bun:test';
11
+ import { Cacheable, _cacheStore } from '../utils/cacheable.js';
12
+ describe('@Cacheable', () => {
13
+ beforeEach(() => {
14
+ _cacheStore.clear();
15
+ });
16
+ it('should cache synchronous method results', () => {
17
+ let callCount = 0;
18
+ class TestService {
19
+ getData(id) {
20
+ callCount++;
21
+ return `data-${id}`;
22
+ }
23
+ }
24
+ __decorate([
25
+ Cacheable({ ttl: 1 }),
26
+ __metadata("design:type", Function),
27
+ __metadata("design:paramtypes", [Number]),
28
+ __metadata("design:returntype", String)
29
+ ], TestService.prototype, "getData", null);
30
+ const service = new TestService();
31
+ // Primera llamada - ejecuta original
32
+ expect(service.getData(1)).toBe('data-1');
33
+ expect(callCount).toBe(1);
34
+ // Segunda llamada - obtiene del cache
35
+ expect(service.getData(1)).toBe('data-1');
36
+ expect(callCount).toBe(1);
37
+ // Llamada con diferente argumento - ejecuta original
38
+ expect(service.getData(2)).toBe('data-2');
39
+ expect(callCount).toBe(2);
40
+ });
41
+ it('should preserve "this" context', () => {
42
+ class TestService {
43
+ prefix = 'prefix';
44
+ getData(id) {
45
+ return `${this.prefix}-${id}`;
46
+ }
47
+ }
48
+ __decorate([
49
+ Cacheable({ ttl: 1 }),
50
+ __metadata("design:type", Function),
51
+ __metadata("design:paramtypes", [Number]),
52
+ __metadata("design:returntype", String)
53
+ ], TestService.prototype, "getData", null);
54
+ const service = new TestService();
55
+ expect(service.getData(1)).toBe('prefix-1');
56
+ });
57
+ it('should handle async methods and cache resolved values', async () => {
58
+ let callCount = 0;
59
+ class TestService {
60
+ async getData(id) {
61
+ callCount++;
62
+ return `async-data-${id}`;
63
+ }
64
+ }
65
+ __decorate([
66
+ Cacheable({ ttl: 1 }),
67
+ __metadata("design:type", Function),
68
+ __metadata("design:paramtypes", [Number]),
69
+ __metadata("design:returntype", Promise)
70
+ ], TestService.prototype, "getData", null);
71
+ const service = new TestService();
72
+ // Primera llamada - asíncrona
73
+ const result1 = await service.getData(1);
74
+ expect(result1).toBe('async-data-1');
75
+ expect(callCount).toBe(1);
76
+ // Segunda llamada - asíncrona, desde cache
77
+ const result2 = await service.getData(1);
78
+ expect(result2).toBe('async-data-1');
79
+ expect(callCount).toBe(1);
80
+ });
81
+ it('should respect custom cache key generator', () => {
82
+ let callCount = 0;
83
+ class TestService {
84
+ getData(id, _ignored) {
85
+ callCount++;
86
+ return `val-${id}`;
87
+ }
88
+ }
89
+ __decorate([
90
+ Cacheable({
91
+ ttl: 1,
92
+ // Generar clave custom omitiendo el segundo argumento
93
+ key: (id) => `custom-key:${id}`,
94
+ }),
95
+ __metadata("design:type", Function),
96
+ __metadata("design:paramtypes", [Number, String]),
97
+ __metadata("design:returntype", String)
98
+ ], TestService.prototype, "getData", null);
99
+ const service = new TestService();
100
+ expect(service.getData(1, 'foo')).toBe('val-1');
101
+ expect(callCount).toBe(1);
102
+ // Segunda llamada con diferente segundo argumento, pero misma key generada
103
+ expect(service.getData(1, 'bar')).toBe('val-1');
104
+ expect(callCount).toBe(1);
105
+ });
106
+ it('should bypass cache if ttl is 0 or less', () => {
107
+ let callCount = 0;
108
+ class TestService {
109
+ getData(id) {
110
+ callCount++;
111
+ return `data-${id}`;
112
+ }
113
+ }
114
+ __decorate([
115
+ Cacheable({ ttl: 0 }),
116
+ __metadata("design:type", Function),
117
+ __metadata("design:paramtypes", [Number]),
118
+ __metadata("design:returntype", String)
119
+ ], TestService.prototype, "getData", null);
120
+ const service = new TestService();
121
+ expect(service.getData(1)).toBe('data-1');
122
+ expect(callCount).toBe(1);
123
+ expect(service.getData(1)).toBe('data-1');
124
+ expect(callCount).toBe(2); // no cacheado
125
+ });
126
+ it('should expire cache entries after ttl', async () => {
127
+ let callCount = 0;
128
+ class TestService {
129
+ // 50ms TTL para el test
130
+ getData(id) {
131
+ callCount++;
132
+ return `data-${id}`;
133
+ }
134
+ }
135
+ __decorate([
136
+ Cacheable({ ttl: 0.05 }),
137
+ __metadata("design:type", Function),
138
+ __metadata("design:paramtypes", [Number]),
139
+ __metadata("design:returntype", String)
140
+ ], TestService.prototype, "getData", null);
141
+ const service = new TestService();
142
+ expect(service.getData(1)).toBe('data-1');
143
+ expect(callCount).toBe(1);
144
+ // Esperar 100ms
145
+ await new Promise((resolve) => setTimeout(resolve, 100));
146
+ expect(service.getData(1)).toBe('data-1');
147
+ expect(callCount).toBe(2); // expirado y re-ejecutado
148
+ });
149
+ });
150
+ //# sourceMappingURL=cacheable.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cacheable.spec.js","sourceRoot":"","sources":["../../src/__tests__/cacheable.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=logger.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.spec.d.ts","sourceRoot":"","sources":["../../src/__tests__/logger.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,29 @@
1
+ import { describe, it, expect, spyOn, afterEach } from 'bun:test';
2
+ import { DefaultConsoleLogger } from '../logger.js';
3
+ describe('DefaultConsoleLogger', () => {
4
+ let logSpy = spyOn(console, 'log').mockImplementation(() => { });
5
+ let warnSpy = spyOn(console, 'warn').mockImplementation(() => { });
6
+ let errorSpy = spyOn(console, 'error').mockImplementation(() => { });
7
+ afterEach(() => {
8
+ logSpy.mockClear();
9
+ warnSpy.mockClear();
10
+ errorSpy.mockClear();
11
+ });
12
+ it('should print log messages without throwing', () => {
13
+ const logger = new DefaultConsoleLogger();
14
+ logger.log('Normal info message');
15
+ logger.log('Hono router method GET /users - 200 - +5ms', 'Router');
16
+ expect(logSpy).toHaveBeenCalled();
17
+ });
18
+ it('should print warnings without throwing', () => {
19
+ const logger = new DefaultConsoleLogger();
20
+ logger.warn('Some warning message', 'Contracts');
21
+ expect(warnSpy).toHaveBeenCalled();
22
+ });
23
+ it('should print errors without throwing', () => {
24
+ const logger = new DefaultConsoleLogger();
25
+ logger.error('Critical failure message', 'stacktrace-mock-data', 'InstanceLoader');
26
+ expect(errorSpy).toHaveBeenCalled();
27
+ });
28
+ });
29
+ //# sourceMappingURL=logger.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.spec.js","sourceRoot":"","sources":["../../src/__tests__/logger.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEpD,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,IAAI,MAAM,GAAG,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAChE,IAAI,OAAO,GAAG,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAClE,IAAI,QAAQ,GAAG,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAEpE,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,CAAC,SAAS,EAAE,CAAC;QACnB,OAAO,CAAC,SAAS,EAAE,CAAC;QACpB,QAAQ,CAAC,SAAS,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,MAAM,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC1C,MAAM,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QAClC,MAAM,CAAC,GAAG,CAAC,4CAA4C,EAAE,QAAQ,CAAC,CAAC;QAEnE,MAAM,CAAC,MAAM,CAAC,CAAC,gBAAgB,EAAE,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,MAAM,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC1C,MAAM,CAAC,IAAI,CAAC,sBAAsB,EAAE,WAAW,CAAC,CAAC;QAEjD,MAAM,CAAC,OAAO,CAAC,CAAC,gBAAgB,EAAE,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,MAAM,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAC,0BAA0B,EAAE,sBAAsB,EAAE,gBAAgB,CAAC,CAAC;QAEnF,MAAM,CAAC,QAAQ,CAAC,CAAC,gBAAgB,EAAE,CAAC;IACtC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
package/dist/env.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ import { z } from 'zod';
2
+ export declare function env<T extends z.ZodTypeAny>(key: string, schema: T): z.infer<T>;
3
+ export declare function assertEnvValid(): void;
4
+ export declare function getRegisteredEnvs(): Map<string, z.ZodTypeAny>;
5
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAexB,wBAAgB,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAgB9E;AAED,wBAAgB,cAAc,IAAI,IAAI,CAIrC;AAGD,wBAAgB,iBAAiB,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,CAAC,CAE7D"}
package/dist/env.js ADDED
@@ -0,0 +1,27 @@
1
+ const cache = new Map();
2
+ const schemas = new Map();
3
+ const errors = [];
4
+ export function env(key, schema) {
5
+ // Register schema for .env.example autogeneration
6
+ schemas.set(key, schema);
7
+ if (cache.has(key)) {
8
+ return cache.get(key);
9
+ }
10
+ const result = schema.safeParse(process.env[key]);
11
+ if (!result.success) {
12
+ errors.push(`${key}: ${result.error.issues.map((i) => i.message).join(', ')}`);
13
+ return undefined;
14
+ }
15
+ cache.set(key, result.data);
16
+ return result.data;
17
+ }
18
+ export function assertEnvValid() {
19
+ if (errors.length > 0) {
20
+ throw new Error(`❌ Invalid environment:\n${errors.map((e) => ` - ${e}`).join('\n')}`);
21
+ }
22
+ }
23
+ // Expose schemas map for CLI or developer tools
24
+ export function getRegisteredEnvs() {
25
+ return schemas;
26
+ }
27
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAUA,MAAM,KAAK,GAAG,IAAI,GAAG,EAAoB,CAAC;AAE1C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAwB,CAAC;AAChD,MAAM,MAAM,GAAa,EAAE,CAAC;AAE5B,MAAM,UAAU,GAAG,CAAyB,GAAW,EAAE,MAAS;IAChE,kDAAkD;IAClD,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAEzB,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,CAAe,CAAC;IACtC,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAClD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,KAAK,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC/E,OAAO,SAAuB,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,IAAgB,CAAC,CAAC;IACxC,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,2BAA2B,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzF,CAAC;AACH,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,iBAAiB;IAC/B,OAAO,OAAO,CAAC;AACjB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,9 @@
1
- export declare const COMMON_VERSION = "0.2.0-beta.1";
2
- export type { ContextKey } from "./constants";
3
- export { CONTEXT_KEYS } from "./constants";
1
+ export * from './types';
2
+ export * from './env';
3
+ export * from './logger';
4
+ export * from './utils/errors';
5
+ export * from './utils/helpers';
6
+ export * from './utils/decorators';
7
+ export * from './utils/exception-filter';
8
+ export * from './utils/cacheable';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC"}
package/dist/index.js CHANGED
@@ -1,20 +1,9 @@
1
- // @bun
2
- // src/constants.ts
3
- var CONTEXT_KEYS = {
4
- AUTH_USER: "kanji.auth.user",
5
- AUTH_SESSION: "kanji.auth.session",
6
- AUTH_ROLES: "kanji.auth.roles",
7
- AUTH_SCOPES: "kanji.auth.scopes",
8
- AUTH_PRINCIPAL: "kanji.auth.principal",
9
- AUTHZ_CACHE: "kanji.authz.cache",
10
- AUTHZ_DECISION: "kanji.authz.decision",
11
- REQUEST_ID: "kanji.requestId",
12
- VALIDATED: "kanji.validated"
13
- };
14
-
15
- // src/index.ts
16
- var COMMON_VERSION = "0.2.0-beta.1";
17
- export {
18
- CONTEXT_KEYS,
19
- COMMON_VERSION
20
- };
1
+ export * from './types';
2
+ export * from './env';
3
+ export * from './logger';
4
+ export * from './utils/errors';
5
+ export * from './utils/helpers';
6
+ export * from './utils/decorators';
7
+ export * from './utils/exception-filter';
8
+ export * from './utils/cacheable';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,OAAO,CAAC;AACtB,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC"}
@@ -0,0 +1,15 @@
1
+ export interface KanjiLogger {
2
+ log(message: string, context?: string): void;
3
+ error(message: string, trace?: string, context?: string): void;
4
+ warn(message: string, context?: string): void;
5
+ }
6
+ export declare const LOGGER: unique symbol;
7
+ export declare class DefaultConsoleLogger implements KanjiLogger {
8
+ private useColor;
9
+ constructor();
10
+ private formatRouterMessage;
11
+ log(message: string, context?: string): void;
12
+ warn(message: string, context?: string): void;
13
+ error(message: string, trace?: string, context?: string): void;
14
+ }
15
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/C;AAED,eAAO,MAAM,MAAM,eAAmB,CAAC;AAEvC,qBAAa,oBAAqB,YAAW,WAAW;IACtD,OAAO,CAAC,QAAQ,CAAU;;IAQ1B,OAAO,CAAC,mBAAmB;IAa3B,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAQ5C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAS7C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;CAS/D"}
package/dist/logger.js ADDED
@@ -0,0 +1,45 @@
1
+ export const LOGGER = Symbol('LOGGER');
2
+ export class DefaultConsoleLogger {
3
+ useColor;
4
+ constructor() {
5
+ const isTTY = typeof process !== 'undefined' && process.stdout?.isTTY;
6
+ const noColor = typeof process !== 'undefined' && process.env?.NO_COLOR !== undefined;
7
+ this.useColor = !!isTTY && !noColor;
8
+ }
9
+ formatRouterMessage(message) {
10
+ if (!this.useColor) {
11
+ return message;
12
+ }
13
+ // Formats Router latency message "METHOD /path - STATUS - +DURATIONms" with color codes
14
+ return message.replace(/ - (\d+) - \+(.+ms)/, (_match, status, duration) => {
15
+ const statusCode = parseInt(status, 10);
16
+ const statusColor = statusCode >= 500 ? '\x1b[31m' : statusCode >= 400 ? '\x1b[33m' : '\x1b[32m';
17
+ return ` - ${statusColor}${status}\x1b[0m - \x1b[36m+${duration}\x1b[0m`;
18
+ });
19
+ }
20
+ log(message, context) {
21
+ const ts = new Date().toLocaleTimeString();
22
+ const formattedMsg = context === 'Router' ? this.formatRouterMessage(message) : message;
23
+ const ctx = context ? (this.useColor ? `\x1b[36m[${context}]\x1b[0m` : `[${context}]`) : '';
24
+ const prefix = this.useColor ? `\x1b[35m[Kanji]\x1b[0m` : '[Kanji]';
25
+ console.log(`${prefix} ${ts} ${ctx} ${formattedMsg}`);
26
+ }
27
+ warn(message, context) {
28
+ const ts = new Date().toLocaleTimeString();
29
+ const formattedMsg = context === 'Router' ? this.formatRouterMessage(message) : message;
30
+ const ctx = context ? (this.useColor ? `\x1b[33m[${context}]\x1b[0m` : `[${context}]`) : '';
31
+ const prefix = this.useColor ? `\x1b[33m[Kanji-Warn]\x1b[0m` : '[Kanji-Warn]';
32
+ const msgColor = this.useColor ? `\x1b[33m${formattedMsg}\x1b[0m` : formattedMsg;
33
+ console.warn(`${prefix} ${ts} ${ctx} ${msgColor}`);
34
+ }
35
+ error(message, trace, context) {
36
+ const ts = new Date().toLocaleTimeString();
37
+ const formattedMsg = context === 'Router' ? this.formatRouterMessage(message) : message;
38
+ const ctx = context ? (this.useColor ? `\x1b[31m[${context}]\x1b[0m` : `[${context}]`) : '';
39
+ const prefix = this.useColor ? '\x1b[31m[Kanji-Error]\x1b[0m' : '[Kanji-Error]';
40
+ const msgColor = this.useColor ? `\x1b[31m${formattedMsg}\x1b[0m` : formattedMsg;
41
+ const traceStr = trace ? `\n${trace}` : '';
42
+ console.error(`${prefix} ${ts} ${ctx} ${msgColor}${traceStr}`);
43
+ }
44
+ }
45
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export interface Constructor<T = object> {
2
+ new (...args: never[]): T;
3
+ }
4
+ export type Token<T = object> = Constructor<T> | symbol | string;
5
+ export type DeepPartial<T> = T extends Builtin ? T : T extends Map<infer K, infer V> ? Map<DeepPartial<K>, DeepPartial<V>> : T extends ReadonlyMap<infer K, infer V> ? ReadonlyMap<DeepPartial<K>, DeepPartial<V>> : T extends WeakMap<infer K, infer V> ? WeakMap<DeepPartial<K>, DeepPartial<V>> : T extends Set<infer U> ? Set<DeepPartial<U>> : T extends ReadonlySet<infer U> ? ReadonlySet<DeepPartial<U>> : T extends WeakSet<infer U> ? WeakSet<DeepPartial<U>> : T extends Array<infer U> ? T extends IsTuple<T> ? {
6
+ [K in keyof T]: DeepPartial<T[K]>;
7
+ } : Array<DeepPartial<U>> : T extends Promise<infer U> ? Promise<DeepPartial<U>> : T extends {} ? {
8
+ [K in keyof T]?: DeepPartial<T[K]>;
9
+ } : Partial<T>;
10
+ type Builtin = Function | Date | Error | RegExp;
11
+ type IsTuple<T> = T extends readonly any[] ? (number extends T['length'] ? never : T) : never;
12
+ export {};
13
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,MAAM;IACrC,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;CAC3B;AAED,MAAM,MAAM,KAAK,CAAC,CAAC,GAAG,MAAM,IAAI,WAAW,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,MAAM,CAAC;AAEjE,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,OAAO,GAC1C,CAAC,GACD,CAAC,SAAS,GAAG,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,GAC7B,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,GACnC,CAAC,SAAS,WAAW,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,GACrC,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,GAC3C,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,GACjC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,GACvC,CAAC,SAAS,GAAG,CAAC,MAAM,CAAC,CAAC,GACpB,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,GACnB,CAAC,SAAS,WAAW,CAAC,MAAM,CAAC,CAAC,GAC5B,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,GAC3B,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,CAAC,GACxB,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,GACvB,CAAC,SAAS,KAAK,CAAC,MAAM,CAAC,CAAC,GACtB,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,GAClB;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,GACrC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,GACvB,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,CAAC,GACxB,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,GACvB,CAAC,SAAS,EAAE,GACV;KAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,GACtC,OAAO,CAAC,CAAC,CAAC,CAAC;AAEjC,KAAK,OAAO,GAAG,QAAQ,GAAG,IAAI,GAAG,KAAK,GAAG,MAAM,CAAC;AAEhD,KAAK,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,SAAS,GAAG,EAAE,GAAG,CAAC,MAAM,SAAS,CAAC,CAAC,QAAQ,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,17 @@
1
+ import 'reflect-metadata';
2
+ export interface CacheableOptions {
3
+ ttl: number;
4
+ key?: (...args: readonly never[]) => string;
5
+ }
6
+ interface CacheEntry<T = unknown> {
7
+ value: T;
8
+ expiresAt: number;
9
+ }
10
+ /**
11
+ * Decorador para cachear el retorno de un método.
12
+ * Evita ejecuciones duplicadas de computaciones pesadas o consultas repetidas a la base de datos.
13
+ */
14
+ export declare function Cacheable(options: CacheableOptions): MethodDecorator;
15
+ export declare const _cacheStore: Map<string, CacheEntry<unknown>>;
16
+ export {};
17
+ //# sourceMappingURL=cacheable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cacheable.d.ts","sourceRoot":"","sources":["../../src/utils/cacheable.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,SAAS,KAAK,EAAE,KAAK,MAAM,CAAC;CAC7C;AAED,UAAU,UAAU,CAAC,CAAC,GAAG,OAAO;IAC9B,KAAK,EAAE,CAAC,CAAC;IACT,SAAS,EAAE,MAAM,CAAC;CACnB;AAqBD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,eAAe,CAiDpE;AAGD,eAAO,MAAM,WAAW,kCAAa,CAAC"}
@@ -0,0 +1,62 @@
1
+ import 'reflect-metadata';
2
+ // Almacenamiento en caché en memoria
3
+ const cacheStore = new Map();
4
+ // Cleanup periódico para evitar memory leaks
5
+ const CLEANUP_INTERVAL_MS = 60000; // 1 minuto
6
+ const cleanupTimer = setInterval(() => {
7
+ const now = Date.now();
8
+ for (const [key, entry] of cacheStore.entries()) {
9
+ if (entry.expiresAt <= now) {
10
+ cacheStore.delete(key);
11
+ }
12
+ }
13
+ }, CLEANUP_INTERVAL_MS);
14
+ // Permitir que el proceso de Bun termine de manera limpia sin esperar a que finalice el timer
15
+ if (typeof cleanupTimer.unref === 'function') {
16
+ cleanupTimer.unref();
17
+ }
18
+ /**
19
+ * Decorador para cachear el retorno de un método.
20
+ * Evita ejecuciones duplicadas de computaciones pesadas o consultas repetidas a la base de datos.
21
+ */
22
+ export function Cacheable(options) {
23
+ return (target, propertyKey, descriptor) => {
24
+ const originalMethod = descriptor.value;
25
+ if (typeof originalMethod !== 'function') {
26
+ throw new Error('@Cacheable solo se puede aplicar a métodos de clase.');
27
+ }
28
+ descriptor.value = function (...args) {
29
+ // Si el TTL es menor o igual a 0, ejecutar el método original sin pasar por la caché
30
+ if (options.ttl <= 0) {
31
+ return originalMethod.apply(this, args);
32
+ }
33
+ // Generar clave única para el método
34
+ const cacheKey = options.key
35
+ ? options.key.apply(this, args)
36
+ : `${target.constructor.name}:${String(propertyKey)}:${JSON.stringify(args)}`;
37
+ const now = Date.now();
38
+ const cached = cacheStore.get(cacheKey);
39
+ if (cached && cached.expiresAt > now) {
40
+ return cached.value;
41
+ }
42
+ const result = originalMethod.apply(this, args);
43
+ if (result instanceof Promise) {
44
+ return result.then((resolvedValue) => {
45
+ cacheStore.set(cacheKey, {
46
+ value: resolvedValue,
47
+ expiresAt: Date.now() + options.ttl * 1000,
48
+ });
49
+ return resolvedValue;
50
+ });
51
+ }
52
+ cacheStore.set(cacheKey, {
53
+ value: result,
54
+ expiresAt: Date.now() + options.ttl * 1000,
55
+ });
56
+ return result;
57
+ };
58
+ };
59
+ }
60
+ // Exportar store para propósitos de testing si es necesario
61
+ export const _cacheStore = cacheStore;
62
+ //# sourceMappingURL=cacheable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cacheable.js","sourceRoot":"","sources":["../../src/utils/cacheable.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAY1B,qCAAqC;AACrC,MAAM,UAAU,GAAG,IAAI,GAAG,EAAsB,CAAC;AAEjD,6CAA6C;AAC7C,MAAM,mBAAmB,GAAG,KAAK,CAAC,CAAC,WAAW;AAC9C,MAAM,YAAY,GAAG,WAAW,CAAC,GAAG,EAAE;IACpC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC;QAChD,IAAI,KAAK,CAAC,SAAS,IAAI,GAAG,EAAE,CAAC;YAC3B,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;AACH,CAAC,EAAE,mBAAmB,CAAC,CAAC;AAExB,8FAA8F;AAC9F,IAAI,OAAO,YAAY,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;IAC7C,YAAY,CAAC,KAAK,EAAE,CAAC;AACvB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,OAAyB;IACjD,OAAO,CACL,MAAc,EACd,WAA4B,EAC5B,UAAsC,EACH,EAAE;QACrC,MAAM,cAAc,GAAG,UAAU,CAAC,KAAK,CAAC;QACxC,IAAI,OAAO,cAAc,KAAK,UAAU,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;QAC1E,CAAC;QAED,UAAU,CAAC,KAAK,GAAG,UAAyB,GAAG,IAAa;YAC1D,qFAAqF;YACrF,IAAI,OAAO,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC;gBACrB,OAAO,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAC1C,CAAC;YAED,qCAAqC;YACrC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG;gBAC1B,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC;gBAC/B,CAAC,CAAC,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,IAAI,MAAM,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;YAEhF,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAExC,IAAI,MAAM,IAAI,MAAM,CAAC,SAAS,GAAG,GAAG,EAAE,CAAC;gBACrC,OAAO,MAAM,CAAC,KAAK,CAAC;YACtB,CAAC;YAED,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAEhD,IAAI,MAAM,YAAY,OAAO,EAAE,CAAC;gBAC9B,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,EAAE;oBACnC,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE;wBACvB,KAAK,EAAE,aAAa;wBACpB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI;qBAC3C,CAAC,CAAC;oBACH,OAAO,aAAa,CAAC;gBACvB,CAAC,CAAC,CAAC;YACL,CAAC;YAED,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE;gBACvB,KAAK,EAAE,MAAM;gBACb,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI;aAC3C,CAAC,CAAC;YAEH,OAAO,MAAM,CAAC;QAChB,CAAiB,CAAC;IACpB,CAAC,CAAC;AACJ,CAAC;AAED,4DAA4D;AAC5D,MAAM,CAAC,MAAM,WAAW,GAAG,UAAU,CAAC"}
@@ -0,0 +1,5 @@
1
+ import 'reflect-metadata';
2
+ export declare function createParamDecorator(factory: (ctx: unknown) => unknown): ParameterDecorator;
3
+ export declare function createPropertyDecorator(metakey: string, value: unknown): PropertyDecorator;
4
+ export declare function createMethodDecorator(factory: (...args: Array<unknown>) => PropertyDecorator): (...args: Array<unknown>) => MethodDecorator;
5
+ //# sourceMappingURL=decorators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../src/utils/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,GAAG,kBAAkB,CAc3F;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,iBAAiB,CAK1F;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,iBAAiB,GACtD,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,eAAe,CAS9C"}
@@ -0,0 +1,28 @@
1
+ import 'reflect-metadata';
2
+ export function createParamDecorator(factory) {
3
+ return (target, propertyKey, parameterIndex) => {
4
+ if (propertyKey === undefined)
5
+ return;
6
+ const existingMetadata = Reflect.getMetadata('kanji:params', target, propertyKey) ?? [];
7
+ existingMetadata.push({ index: parameterIndex, factory });
8
+ Reflect.defineMetadata('kanji:params', existingMetadata, target, propertyKey);
9
+ };
10
+ }
11
+ export function createPropertyDecorator(metakey, value) {
12
+ return (target, propertyKey) => {
13
+ if (propertyKey === undefined)
14
+ return;
15
+ Reflect.defineMetadata(metakey, value, target, propertyKey);
16
+ };
17
+ }
18
+ export function createMethodDecorator(factory) {
19
+ return (...args) => {
20
+ const propertyDecorator = factory(...args);
21
+ return (target, propertyKey) => {
22
+ if (propertyKey !== undefined) {
23
+ propertyDecorator(target, propertyKey);
24
+ }
25
+ };
26
+ };
27
+ }
28
+ //# sourceMappingURL=decorators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../src/utils/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B,MAAM,UAAU,oBAAoB,CAAC,OAAkC;IACrE,OAAO,CAAC,MAAc,EAAE,WAAwC,EAAE,cAAsB,EAAE,EAAE;QAC1F,IAAI,WAAW,KAAK,SAAS;YAAE,OAAO;QAEtC,MAAM,gBAAgB,GACpB,OAAO,CAAC,WAAW,CAAC,cAAc,EAAE,MAAM,EAAE,WAA8B,CAAC,IAAI,EAAE,CAAC;QACpF,gBAAgB,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC,CAAC;QAC1D,OAAO,CAAC,cAAc,CACpB,cAAc,EACd,gBAAgB,EAChB,MAAM,EACN,WAA8B,CAC/B,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAAe,EAAE,KAAc;IACrE,OAAO,CAAC,MAAc,EAAE,WAA6B,EAAE,EAAE;QACvD,IAAI,WAAW,KAAK,SAAS;YAAE,OAAO;QACtC,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;IAC9D,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,OAAuD;IAEvD,OAAO,CAAC,GAAG,IAAoB,EAAE,EAAE;QACjC,MAAM,iBAAiB,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;QAC3C,OAAO,CAAC,MAAc,EAAE,WAAwC,EAAE,EAAE;YAClE,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;gBAC9B,iBAAiB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;YACzC,CAAC;QACH,CAAC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,36 @@
1
+ export declare class KanjiError extends Error {
2
+ readonly statusCode: number;
3
+ readonly code: string;
4
+ constructor(message: string, statusCode?: number, code?: string);
5
+ }
6
+ export declare class BadRequestError extends KanjiError {
7
+ constructor(message?: string, code?: string);
8
+ }
9
+ export declare class UnauthorizedError extends KanjiError {
10
+ constructor(message?: string, code?: string);
11
+ }
12
+ export declare class ForbiddenError extends KanjiError {
13
+ constructor(message?: string, code?: string);
14
+ }
15
+ export declare class NotFoundError extends KanjiError {
16
+ constructor(message?: string, code?: string);
17
+ }
18
+ export declare class ConflictError extends KanjiError {
19
+ constructor(message?: string, code?: string);
20
+ }
21
+ export declare class ValidationError extends KanjiError {
22
+ readonly issues: Array<{
23
+ path: string;
24
+ code: string;
25
+ message: string;
26
+ }>;
27
+ constructor(issues: Array<{
28
+ path: string;
29
+ code: string;
30
+ message: string;
31
+ }>, message?: string);
32
+ }
33
+ export declare class TooManyRequestsError extends KanjiError {
34
+ constructor(message?: string, code?: string);
35
+ }
36
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,UAAW,SAAQ,KAAK;IACnC,SAAgB,UAAU,EAAE,MAAM,CAAC;IACnC,SAAgB,IAAI,EAAE,MAAM,CAAC;gBAEjB,OAAO,EAAE,MAAM,EAAE,UAAU,GAAE,MAAY,EAAE,IAAI,GAAE,MAAyB;CAOvF;AAED,qBAAa,eAAgB,SAAQ,UAAU;gBACjC,OAAO,GAAE,MAAsB,EAAE,IAAI,GAAE,MAAsB;CAI1E;AAED,qBAAa,iBAAkB,SAAQ,UAAU;gBACnC,OAAO,GAAE,MAAuB,EAAE,IAAI,GAAE,MAAuB;CAI5E;AAED,qBAAa,cAAe,SAAQ,UAAU;gBAChC,OAAO,GAAE,MAAoB,EAAE,IAAI,GAAE,MAAoB;CAItE;AAED,qBAAa,aAAc,SAAQ,UAAU;gBAC/B,OAAO,GAAE,MAA6B,EAAE,IAAI,GAAE,MAAoB;CAI/E;AAED,qBAAa,aAAc,SAAQ,UAAU;gBAC/B,OAAO,GAAE,MAA4B,EAAE,IAAI,GAAE,MAAmB;CAI7E;AAED,qBAAa,eAAgB,SAAQ,UAAU;IAC7C,SAAgB,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;gBAG7E,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,EAC9D,OAAO,GAAE,MAA4B;CAMxC;AAED,qBAAa,oBAAqB,SAAQ,UAAU;gBACtC,OAAO,GAAE,MAA4B,EAAE,IAAI,GAAE,MAA4B;CAItF"}
@@ -0,0 +1,56 @@
1
+ export class KanjiError extends Error {
2
+ statusCode;
3
+ code;
4
+ constructor(message, statusCode = 500, code = 'INTERNAL_ERROR') {
5
+ super(message);
6
+ this.name = 'KanjiError';
7
+ this.statusCode = statusCode;
8
+ this.code = code;
9
+ Error.captureStackTrace(this, this.constructor);
10
+ }
11
+ }
12
+ export class BadRequestError extends KanjiError {
13
+ constructor(message = 'Bad request', code = 'BAD_REQUEST') {
14
+ super(message, 400, code);
15
+ this.name = 'BadRequestError';
16
+ }
17
+ }
18
+ export class UnauthorizedError extends KanjiError {
19
+ constructor(message = 'Unauthorized', code = 'UNAUTHORIZED') {
20
+ super(message, 401, code);
21
+ this.name = 'UnauthorizedError';
22
+ }
23
+ }
24
+ export class ForbiddenError extends KanjiError {
25
+ constructor(message = 'Forbidden', code = 'FORBIDDEN') {
26
+ super(message, 403, code);
27
+ this.name = 'ForbiddenError';
28
+ }
29
+ }
30
+ export class NotFoundError extends KanjiError {
31
+ constructor(message = 'Resource not found', code = 'NOT_FOUND') {
32
+ super(message, 404, code);
33
+ this.name = 'NotFoundError';
34
+ }
35
+ }
36
+ export class ConflictError extends KanjiError {
37
+ constructor(message = 'Resource conflict', code = 'CONFLICT') {
38
+ super(message, 409, code);
39
+ this.name = 'ConflictError';
40
+ }
41
+ }
42
+ export class ValidationError extends KanjiError {
43
+ issues;
44
+ constructor(issues, message = 'Validation failed') {
45
+ super(message, 422, 'VALIDATION_ERROR');
46
+ this.name = 'ValidationError';
47
+ this.issues = issues;
48
+ }
49
+ }
50
+ export class TooManyRequestsError extends KanjiError {
51
+ constructor(message = 'Too many requests', code = 'TOO_MANY_REQUESTS') {
52
+ super(message, 429, code);
53
+ this.name = 'TooManyRequestsError';
54
+ }
55
+ }
56
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,UAAW,SAAQ,KAAK;IACnB,UAAU,CAAS;IACnB,IAAI,CAAS;IAE7B,YAAY,OAAe,EAAE,aAAqB,GAAG,EAAE,OAAe,gBAAgB;QACpF,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAClD,CAAC;CACF;AAED,MAAM,OAAO,eAAgB,SAAQ,UAAU;IAC7C,YAAY,UAAkB,aAAa,EAAE,OAAe,aAAa;QACvE,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,MAAM,OAAO,iBAAkB,SAAQ,UAAU;IAC/C,YAAY,UAAkB,cAAc,EAAE,OAAe,cAAc;QACzE,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AAED,MAAM,OAAO,cAAe,SAAQ,UAAU;IAC5C,YAAY,UAAkB,WAAW,EAAE,OAAe,WAAW;QACnE,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AAED,MAAM,OAAO,aAAc,SAAQ,UAAU;IAC3C,YAAY,UAAkB,oBAAoB,EAAE,OAAe,WAAW;QAC5E,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,OAAO,aAAc,SAAQ,UAAU;IAC3C,YAAY,UAAkB,mBAAmB,EAAE,OAAe,UAAU;QAC1E,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,OAAO,eAAgB,SAAQ,UAAU;IAC7B,MAAM,CAAyD;IAE/E,YACE,MAA8D,EAC9D,UAAkB,mBAAmB;QAErC,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,kBAAkB,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAED,MAAM,OAAO,oBAAqB,SAAQ,UAAU;IAClD,YAAY,UAAkB,mBAAmB,EAAE,OAAe,mBAAmB;QACnF,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF"}
@@ -0,0 +1,7 @@
1
+ import 'reflect-metadata';
2
+ export interface ExceptionFilter<T = Error> {
3
+ catch(exception: T, context: any): any;
4
+ }
5
+ export declare function Catch(...exceptions: Array<new (...args: any[]) => Error>): ClassDecorator;
6
+ export declare function getExceptionFilterTargets(target: object): Array<new (...args: any[]) => Error> | undefined;
7
+ //# sourceMappingURL=exception-filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exception-filter.d.ts","sourceRoot":"","sources":["../../src/utils/exception-filter.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,KAAK;IACxC,KAAK,CAAC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,GAAG,GAAG,CAAC;CACxC;AAID,wBAAgB,KAAK,CAAC,GAAG,UAAU,EAAE,KAAK,CAAC,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,KAAK,CAAC,GAAG,cAAc,CAIzF;AAED,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,GACb,KAAK,CAAC,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,KAAK,CAAC,GAAG,SAAS,CAElD"}
@@ -0,0 +1,11 @@
1
+ import 'reflect-metadata';
2
+ const CATCH_DECORATOR_KEY = 'kanji:exception:filters';
3
+ export function Catch(...exceptions) {
4
+ return (target) => {
5
+ Reflect.defineMetadata(CATCH_DECORATOR_KEY, exceptions, target);
6
+ };
7
+ }
8
+ export function getExceptionFilterTargets(target) {
9
+ return Reflect.getMetadata(CATCH_DECORATOR_KEY, target);
10
+ }
11
+ //# sourceMappingURL=exception-filter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exception-filter.js","sourceRoot":"","sources":["../../src/utils/exception-filter.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAM1B,MAAM,mBAAmB,GAAG,yBAAyB,CAAC;AAEtD,MAAM,UAAU,KAAK,CAAC,GAAG,UAAgD;IACvE,OAAO,CAAC,MAAM,EAAE,EAAE;QAChB,OAAO,CAAC,cAAc,CAAC,mBAAmB,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;IAClE,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,MAAc;IAEd,OAAO,OAAO,CAAC,WAAW,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;AAC1D,CAAC"}
@@ -0,0 +1,9 @@
1
+ export declare function capitalize(str: string): string;
2
+ export declare function toSingular(str: string): string;
3
+ export declare function toPlural(str: string): string;
4
+ export declare function toCamelCase(str: string): string;
5
+ export declare function toKebabCase(str: string): string;
6
+ export declare function fileExists(path: string): Promise<boolean>;
7
+ export declare function ensureArray<T>(value: T | T[]): T[];
8
+ export declare function slugify(str: string): string;
9
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/utils/helpers.ts"],"names":[],"mappings":"AAEA,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAG9C;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAI9C;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAK5C;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAK/C;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO/D;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,CAElD;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAO3C"}
@@ -0,0 +1,49 @@
1
+ import { stat } from 'fs/promises';
2
+ export function capitalize(str) {
3
+ if (!str)
4
+ return '';
5
+ return str.charAt(0).toUpperCase() + str.slice(1);
6
+ }
7
+ export function toSingular(str) {
8
+ if (str.endsWith('ies'))
9
+ return str.slice(0, -3) + 'y';
10
+ if (str.endsWith('s') && !str.endsWith('ss'))
11
+ return str.slice(0, -1);
12
+ return str;
13
+ }
14
+ export function toPlural(str) {
15
+ if (str.endsWith('y') && !/[aeiou]y$/.test(str)) {
16
+ return str.slice(0, -1) + 'ies';
17
+ }
18
+ return str + 's';
19
+ }
20
+ export function toCamelCase(str) {
21
+ return str.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
22
+ }
23
+ export function toKebabCase(str) {
24
+ return str
25
+ .replace(/([a-z])([A-Z])/g, '$1-$2')
26
+ .replace(/[\s_]+/g, '-')
27
+ .toLowerCase();
28
+ }
29
+ export async function fileExists(path) {
30
+ try {
31
+ await stat(path);
32
+ return true;
33
+ }
34
+ catch {
35
+ return false;
36
+ }
37
+ }
38
+ export function ensureArray(value) {
39
+ return Array.isArray(value) ? value : [value];
40
+ }
41
+ export function slugify(str) {
42
+ return str
43
+ .toLowerCase()
44
+ .trim()
45
+ .replace(/[^\w\s-]/g, '')
46
+ .replace(/[\s_]+/g, '-')
47
+ .replace(/-+/g, '-');
48
+ }
49
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/utils/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAEnC,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IACpB,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;IACvD,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACtE,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAChD,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;IAClC,CAAC;IACD,OAAO,GAAG,GAAG,GAAG,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,OAAO,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,OAAO,GAAG;SACP,OAAO,CAAC,iBAAiB,EAAE,OAAO,CAAC;SACnC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,WAAW,EAAE,CAAC;AACnB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY;IAC3C,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;QACjB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAI,KAAc;IAC3C,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,GAAW;IACjC,OAAO,GAAG;SACP,WAAW,EAAE;SACb,IAAI,EAAE;SACN,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;SACxB,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AACzB,CAAC"}
package/package.json CHANGED
@@ -1,22 +1,21 @@
1
1
  {
2
2
  "name": "@kanjijs/common",
3
- "version": "0.3.0-beta.1",
4
- "type": "module",
3
+ "version": "1.0.0-alpha.1",
5
4
  "main": "./dist/index.js",
6
- "types": "./dist/index.d.ts",
7
5
  "files": [
8
- "dist",
9
- "README.md",
10
- "LICENSE"
6
+ "dist"
11
7
  ],
12
- "scripts": {
13
- "build": "bun build src/index.ts --outdir dist --target bun && bunx tsc --emitDeclarationOnly --declaration --outDir dist -p tsconfig.build.json"
8
+ "types": "./dist/index.d.ts",
9
+ "type": "module",
10
+ "dependencies": {
11
+ "zod": "^3.24.1"
14
12
  },
15
13
  "peerDependencies": {
16
- "@kanjijs/core": "^0.2.0-beta.56"
14
+ "typescript": "6.0.3"
17
15
  },
18
- "devDependencies": {
19
- "bun-types": "latest",
20
- "@kanjijs/core": "^0.2.0-beta.56"
16
+ "scripts": {
17
+ "build": "tsc",
18
+ "dev": "tsc --watch",
19
+ "test": "bun test"
21
20
  }
22
- }
21
+ }
@@ -1,71 +0,0 @@
1
- /**
2
- * Standard Context Keys for Kanjijs Framework
3
- *
4
- * These keys are used to store and retrieve values from the Hono context
5
- * in a standardized way across all Kanjijs packages.
6
- *
7
- * @example
8
- * ```ts
9
- * import { CONTEXT_KEYS } from "@kanjijs/common";
10
- *
11
- * // Set principal in auth middleware
12
- * c.set(CONTEXT_KEYS.AUTH_PRINCIPAL, principal);
13
- *
14
- * // Read principal in authz middleware
15
- * const principal = c.get(CONTEXT_KEYS.AUTH_PRINCIPAL);
16
- * ```
17
- */
18
- export declare const CONTEXT_KEYS: {
19
- /**
20
- * Authenticated user ID
21
- * @example "user_123"
22
- */
23
- readonly AUTH_USER: "kanji.auth.user";
24
- /**
25
- * Session ID
26
- * @example "session_abc"
27
- */
28
- readonly AUTH_SESSION: "kanji.auth.session";
29
- /**
30
- * User roles (array of strings)
31
- * @example ["admin", "editor"]
32
- */
33
- readonly AUTH_ROLES: "kanji.auth.roles";
34
- /**
35
- * User scopes/permissions (array of strings)
36
- * @example ["posts:read", "posts:write"]
37
- */
38
- readonly AUTH_SCOPES: "kanji.auth.scopes";
39
- /**
40
- * Normalized Principal object
41
- * Contains userId, sessionId, roles, scopes, claims
42
- * @see Principal from @kanjijs/security
43
- */
44
- readonly AUTH_PRINCIPAL: "kanji.auth.principal";
45
- /**
46
- * Authorization decision cache (Map)
47
- * Stores decisions per request to avoid re-evaluation
48
- * @example Map<string, Decision>
49
- */
50
- readonly AUTHZ_CACHE: "kanji.authz.cache";
51
- /**
52
- * Last authorization decision
53
- * Useful for debugging and logging
54
- * @see Decision from @kanjijs/security
55
- */
56
- readonly AUTHZ_DECISION: "kanji.authz.decision";
57
- /**
58
- * Request ID for tracing
59
- * @example "req_abc123"
60
- */
61
- readonly REQUEST_ID: "kanji.requestId";
62
- /**
63
- * Validated request data (from contract validation)
64
- * @example { body: {...}, query: {...} }
65
- */
66
- readonly VALIDATED: "kanji.validated";
67
- };
68
- /**
69
- * Type-safe context key type
70
- */
71
- export type ContextKey = (typeof CONTEXT_KEYS)[keyof typeof CONTEXT_KEYS];