stratal 0.0.6 → 0.0.7

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 (96) hide show
  1. package/dist/application.d.ts +10 -42
  2. package/dist/application.d.ts.map +1 -1
  3. package/dist/application.js +36 -77
  4. package/dist/application.js.map +1 -1
  5. package/dist/config/config.module.d.ts.map +1 -1
  6. package/dist/config/config.module.js +2 -1
  7. package/dist/config/config.module.js.map +1 -1
  8. package/dist/config/errors/config-module-not-initialized.error.d.ts +10 -0
  9. package/dist/config/errors/config-module-not-initialized.error.d.ts.map +1 -0
  10. package/dist/config/errors/config-module-not-initialized.error.js +12 -0
  11. package/dist/config/errors/config-module-not-initialized.error.js.map +1 -0
  12. package/dist/config/errors/index.d.ts +1 -0
  13. package/dist/config/errors/index.d.ts.map +1 -1
  14. package/dist/config/errors/index.js +1 -0
  15. package/dist/config/errors/index.js.map +1 -1
  16. package/dist/di/container.d.ts +5 -267
  17. package/dist/di/container.d.ts.map +1 -1
  18. package/dist/di/container.js +13 -288
  19. package/dist/di/container.js.map +1 -1
  20. package/dist/di/errors/request-scope-operation-not-allowed.error.d.ts +0 -1
  21. package/dist/di/errors/request-scope-operation-not-allowed.error.d.ts.map +1 -1
  22. package/dist/di/errors/request-scope-operation-not-allowed.error.js +0 -1
  23. package/dist/di/errors/request-scope-operation-not-allowed.error.js.map +1 -1
  24. package/dist/di/index.d.ts +0 -1
  25. package/dist/di/index.d.ts.map +1 -1
  26. package/dist/di/index.js +0 -1
  27. package/dist/di/index.js.map +1 -1
  28. package/dist/errors/error-codes.d.ts +2 -0
  29. package/dist/errors/error-codes.d.ts.map +1 -1
  30. package/dist/errors/error-codes.js +2 -0
  31. package/dist/errors/error-codes.js.map +1 -1
  32. package/dist/events/types.d.ts +1 -1
  33. package/dist/execution-context.d.ts +4 -0
  34. package/dist/execution-context.d.ts.map +1 -0
  35. package/dist/execution-context.js +2 -0
  36. package/dist/execution-context.js.map +1 -0
  37. package/dist/i18n/messages/en/errors.d.ts +2 -2
  38. package/dist/i18n/messages/en/errors.js +2 -2
  39. package/dist/i18n/messages/en/errors.js.map +1 -1
  40. package/dist/index.d.ts +1 -0
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +1 -0
  43. package/dist/index.js.map +1 -1
  44. package/dist/logger/services/logger.service.d.ts +2 -15
  45. package/dist/logger/services/logger.service.d.ts.map +1 -1
  46. package/dist/logger/services/logger.service.js +11 -16
  47. package/dist/logger/services/logger.service.js.map +1 -1
  48. package/dist/router/errors/hono-app-already-configured.error.d.ts +10 -0
  49. package/dist/router/errors/hono-app-already-configured.error.d.ts.map +1 -0
  50. package/dist/router/errors/hono-app-already-configured.error.js +12 -0
  51. package/dist/router/errors/hono-app-already-configured.error.js.map +1 -0
  52. package/dist/router/errors/index.d.ts +1 -2
  53. package/dist/router/errors/index.d.ts.map +1 -1
  54. package/dist/router/errors/index.js +1 -2
  55. package/dist/router/errors/index.js.map +1 -1
  56. package/dist/router/hono-app.d.ts +38 -0
  57. package/dist/router/hono-app.d.ts.map +1 -0
  58. package/dist/router/hono-app.js +128 -0
  59. package/dist/router/hono-app.js.map +1 -0
  60. package/dist/router/index.d.ts +3 -3
  61. package/dist/router/index.d.ts.map +1 -1
  62. package/dist/router/index.js +6 -4
  63. package/dist/router/index.js.map +1 -1
  64. package/dist/router/router.tokens.d.ts +0 -28
  65. package/dist/router/router.tokens.d.ts.map +1 -1
  66. package/dist/router/router.tokens.js +0 -28
  67. package/dist/router/router.tokens.js.map +1 -1
  68. package/dist/router/services/index.d.ts +0 -1
  69. package/dist/router/services/index.d.ts.map +1 -1
  70. package/dist/router/services/index.js +0 -1
  71. package/dist/router/services/index.js.map +1 -1
  72. package/dist/stratal.d.ts +9 -26
  73. package/dist/stratal.d.ts.map +1 -1
  74. package/dist/stratal.js +22 -50
  75. package/dist/stratal.js.map +1 -1
  76. package/package.json +8 -8
  77. package/dist/di/request-context-store.d.ts +0 -122
  78. package/dist/di/request-context-store.d.ts.map +0 -1
  79. package/dist/di/request-context-store.js +0 -135
  80. package/dist/di/request-context-store.js.map +0 -1
  81. package/dist/router/errors/router-already-configured.error.d.ts +0 -5
  82. package/dist/router/errors/router-already-configured.error.d.ts.map +0 -1
  83. package/dist/router/errors/router-already-configured.error.js +0 -8
  84. package/dist/router/errors/router-already-configured.error.js.map +0 -1
  85. package/dist/router/errors/router-not-configured.error.d.ts +0 -5
  86. package/dist/router/errors/router-not-configured.error.d.ts.map +0 -1
  87. package/dist/router/errors/router-not-configured.error.js +0 -8
  88. package/dist/router/errors/router-not-configured.error.js.map +0 -1
  89. package/dist/router/router.service.d.ts +0 -62
  90. package/dist/router/router.service.d.ts.map +0 -1
  91. package/dist/router/router.service.js +0 -166
  92. package/dist/router/router.service.js.map +0 -1
  93. package/dist/router/services/request-scope.service.d.ts +0 -42
  94. package/dist/router/services/request-scope.service.d.ts.map +0 -1
  95. package/dist/router/services/request-scope.service.js +0 -76
  96. package/dist/router/services/request-scope.service.js.map +0 -1
package/dist/stratal.js CHANGED
@@ -1,12 +1,10 @@
1
1
  import 'reflect-metadata';
2
2
  import { Application } from './application';
3
- import { ROUTER_TOKENS } from './router';
4
3
  /**
5
4
  * Stratal — Hono-style entry point for Cloudflare Workers.
6
5
  *
7
- * Lazily initializes the Application on the first handler call and caches it
8
- * for all subsequent invocations. A concurrent-init guard prevents double
9
- * initialization from simultaneous requests.
6
+ * Eagerly bootstraps the Application at construction time, dynamically
7
+ * importing `cloudflare:workers` for env and waitUntil.
10
8
  *
11
9
  * @example
12
10
  * ```typescript
@@ -17,72 +15,46 @@ import { ROUTER_TOKENS } from './router';
17
15
  * ```
18
16
  */
19
17
  export class Stratal {
20
- config;
21
18
  app = null;
22
- initPromise = null;
19
+ initPromise;
23
20
  constructor(config) {
24
- this.config = config;
25
21
  this.fetch = this.fetch.bind(this);
26
22
  this.queue = this.queue.bind(this);
27
23
  this.scheduled = this.scheduled.bind(this);
24
+ this.initPromise = this.prepareApp(config);
28
25
  }
29
- /**
30
- * Handle HTTP requests via RouterService.
31
- */
32
26
  async fetch(request, env, ctx) {
33
- const app = await this.getApplication(env, ctx);
34
- const router = app.resolve(ROUTER_TOKENS.RouterService);
35
- return router.fetch(request, env, ctx);
27
+ const app = await this.ensureReady();
28
+ return app.hono.fetch(request, env, ctx);
36
29
  }
37
- /**
38
- * Handle queue batches.
39
- */
40
- async queue(batch, env, ctx) {
41
- const app = await this.getApplication(env, ctx);
30
+ async queue(batch) {
31
+ const app = await this.ensureReady();
42
32
  return app.handleQueue(batch, batch.queue);
43
33
  }
44
- /**
45
- * Handle scheduled cron triggers.
46
- */
47
- async scheduled(controller, env, ctx) {
48
- const app = await this.getApplication(env, ctx);
34
+ async scheduled(controller) {
35
+ const app = await this.ensureReady();
49
36
  return app.handleScheduled(controller);
50
37
  }
51
- /**
52
- * Get or lazily initialize the Application singleton.
53
- * The first call's `env`/`ctx` are used for initialization;
54
- * subsequent calls return the cached instance.
55
- */
56
- async getApplication(env, ctx) {
57
- // Fast path: already initialized
58
- if (this.app) {
59
- return this.app;
60
- }
61
- // Concurrent initialization guard
62
- if (this.initPromise) {
63
- return this.initPromise;
64
- }
65
- // Start initialization
66
- this.initPromise = this.initializeApp(env, ctx);
38
+ get hono() {
39
+ return this.initPromise.then(app => app.hono);
40
+ }
41
+ async shutdown() {
67
42
  try {
68
43
  this.app = await this.initPromise;
69
- return this.app;
70
44
  }
71
- finally {
72
- this.initPromise = null;
73
- }
74
- }
75
- /**
76
- * Shut down the application and release all resources.
77
- */
78
- async shutdown() {
45
+ catch { /* ignore */ }
79
46
  if (this.app) {
80
47
  await this.app.shutdown();
81
48
  this.app = null;
82
49
  }
83
50
  }
84
- async initializeApp(env, ctx) {
85
- const app = new Application({ ...this.config, env, ctx });
51
+ async ensureReady() {
52
+ this.app ??= await this.initPromise;
53
+ return this.app;
54
+ }
55
+ async prepareApp(config) {
56
+ const { env, waitUntil } = await import('cloudflare:workers');
57
+ const app = new Application({ ...config, env: env, ctx: { waitUntil } });
86
58
  await app.initialize();
87
59
  return app;
88
60
  }
@@ -1 +1 @@
1
- {"version":3,"file":"stratal.js","sourceRoot":"","sources":["../src/stratal.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stratal.js","sourceRoot":"","sources":["../src/stratal.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAA;AAEzB,OAAO,EAAE,WAAW,EAA0B,MAAM,eAAe,CAAA;AAInE;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,OAAO;IACV,GAAG,GAAuB,IAAI,CAAA;IAC9B,WAAW,CAAsB;IAEzC,YAAY,MAAyB;QACnC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAClC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAClC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAE1C,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;IAC5C,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,OAAgB,EAAE,GAAQ,EAAE,GAAqB;QAC3D,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAA;QACpC,OAAO,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;IAC1C,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,KAAmB;QAC7B,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAA;QACpC,OAAO,GAAG,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAA;IAC5C,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,UAA+B;QAC7C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAA;QACpC,OAAO,GAAG,CAAC,eAAe,CAAC,UAAU,CAAC,CAAA;IACxC,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAC/C,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,IAAI,CAAC;YAAC,IAAI,CAAC,GAAG,GAAG,MAAM,IAAI,CAAC,WAAW,CAAA;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QAChE,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAA;YACzB,IAAI,CAAC,GAAG,GAAG,IAAI,CAAA;QACjB,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,WAAW;QACvB,IAAI,CAAC,GAAG,KAAK,MAAM,IAAI,CAAC,WAAW,CAAC;QACpC,OAAO,IAAI,CAAC,GAAG,CAAA;IACjB,CAAC;IAEO,KAAK,CAAC,UAAU,CAAC,MAAyB;QAChD,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAA;QAC7D,MAAM,GAAG,GAAG,IAAI,WAAW,CAAC,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,GAAU,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,EAAE,CAAC,CAAA;QAC/E,MAAM,GAAG,CAAC,UAAU,EAAE,CAAA;QACtB,OAAO,GAAG,CAAA;IACZ,CAAC;CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stratal",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "description": "A modular Cloudflare Workers framework with dependency injection, queue-based events, and type-safe configuration",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -85,7 +85,7 @@
85
85
  "@intlify/message-compiler": "^11.2.8",
86
86
  "@scalar/hono-api-reference": "^0.10.0",
87
87
  "@xmldom/xmldom": "^0.8.11",
88
- "hono": "^4.12.3",
88
+ "hono": "^4.12.5",
89
89
  "reflect-metadata": "^0.2.2",
90
90
  "tsyringe": "^4.10.0",
91
91
  "zod": "^4.3.6"
@@ -131,15 +131,15 @@
131
131
  }
132
132
  },
133
133
  "devDependencies": {
134
- "@aws-sdk/client-s3": "3.1003.0",
135
- "@aws-sdk/lib-storage": "^3.1000.0",
136
- "@aws-sdk/s3-request-presigner": "3.1003.0",
137
- "@cloudflare/vitest-pool-workers": "^0.12.18",
138
- "@cloudflare/workers-types": "4.20260306.1",
134
+ "@aws-sdk/client-s3": "3.1004.0",
135
+ "@aws-sdk/lib-storage": "^3.1004.0",
136
+ "@aws-sdk/s3-request-presigner": "3.1004.0",
137
+ "@cloudflare/vitest-pool-workers": "^0.12.20",
138
+ "@cloudflare/workers-types": "4.20260307.1",
139
139
  "@react-email/components": "^1.0.8",
140
140
  "@stratal/testing": "workspace:*",
141
141
  "@tus/server": "^2.3.0",
142
- "@types/node": "^25.3.2",
142
+ "@types/node": "^25.3.5",
143
143
  "@types/nodemailer": "^7.0.11",
144
144
  "@types/react": "^19.2.14",
145
145
  "@types/react-dom": "^19.2.3",
@@ -1,122 +0,0 @@
1
- import type { DependencyContainer } from 'tsyringe';
2
- /**
3
- * Request context store using AsyncLocalStorage
4
- *
5
- * Stores and propagates request container across async operations without manual context passing.
6
- * This enables transparent access to request-scoped services from any part of the application
7
- * during request handling.
8
- *
9
- * **Cloudflare Workers Compatibility**:
10
- * - Requires `nodejs_als` compatibility flag in wrangler.jsonc
11
- * - Uses V8's SetContinuationPreservedEmbedderData API (efficient)
12
- * - Performance overhead: ~3-4% in typical scenarios
13
- *
14
- * **Thread Safety**:
15
- * - Singleton instance shared across application
16
- * - Each request gets isolated storage context
17
- * - No context leakage between concurrent requests
18
- *
19
- * @example
20
- * ```typescript
21
- * // In router middleware
22
- * const store = RequestContextStore.getInstance()
23
- * await store.run(requestContainer, async () => {
24
- * // All async operations within this callback have access to requestContainer
25
- * await handleRequest()
26
- * })
27
- *
28
- * // In service (anywhere in the call stack)
29
- * const container = RequestContextStore.getInstance().getRequestContainer()
30
- * if (container) {
31
- * // We're in request context
32
- * const service = container.resolve(TOKEN)
33
- * }
34
- * ```
35
- */
36
- export declare class RequestContextStore {
37
- private static instance;
38
- private readonly storage;
39
- /**
40
- * Private constructor - use getInstance() instead
41
- */
42
- private constructor();
43
- /**
44
- * Get singleton instance
45
- *
46
- * **Note**: Creates instance on first call. Subsequent calls return same instance.
47
- */
48
- static getInstance(): RequestContextStore;
49
- /**
50
- * Run callback within request context
51
- *
52
- * Container is automatically available to all async operations within the callback,
53
- * including nested function calls, promises, timers, and queue handlers.
54
- *
55
- * @param container - Request-scoped dependency container
56
- * @param callback - Async operation to run with context
57
- * @returns Result of callback execution
58
- *
59
- * @example
60
- * ```typescript
61
- * const result = await store.run(requestContainer, async () => {
62
- * // Context automatically propagates to nested calls
63
- * await processRequest()
64
- * return { success: true }
65
- * })
66
- * ```
67
- */
68
- run<T>(container: DependencyContainer, callback: () => T): T;
69
- /**
70
- * Get current request container
71
- *
72
- * Returns the container for the current async context, or undefined if not in request context.
73
- *
74
- * **Use Cases**:
75
- * - Request-scoped services resolving from request container
76
- * - Services needing conditional logic based on context availability
77
- * - Debugging/logging request-specific information
78
- * @deprecated Use container instead
79
- * @returns Request container if in request context, undefined otherwise
80
- *
81
- * @example
82
- * ```typescript
83
- * const container = store.getRequestContainer()
84
- * if (container) {
85
- * // Safe to resolve request-scoped services
86
- * const i18n = container.resolve(I18N_TOKENS.I18nService)
87
- * } else {
88
- * // Not in request context - use fallback
89
- * console.log('No request context available')
90
- * }
91
- * ```
92
- */
93
- getRequestContainer(): DependencyContainer | undefined;
94
- /**
95
- * Check if currently in request context
96
- *
97
- * Convenience method for conditional logic based on context availability.
98
- *
99
- * @returns true if in request context, false otherwise
100
- *
101
- * @example
102
- * ```typescript
103
- * if (store.hasRequestContext()) {
104
- * // Use request-specific data
105
- * const locale = getLocaleFromContext()
106
- * } else {
107
- * // Use default
108
- * const locale = 'en'
109
- * }
110
- * ```
111
- */
112
- hasRequestContext(): boolean;
113
- /**
114
- * Reset singleton instance (for testing only)
115
- *
116
- * **Warning**: Only use in test cleanup. Never call in production code.
117
- *
118
- * @internal
119
- */
120
- static resetInstance(): void;
121
- }
122
- //# sourceMappingURL=request-context-store.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"request-context-store.d.ts","sourceRoot":"","sources":["../../src/di/request-context-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAEnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAmC;IAC1D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwC;IAEhE;;OAEG;IACH,OAAO;IAIP;;;;OAIG;IACH,MAAM,CAAC,WAAW,IAAI,mBAAmB;IAKzC;;;;;;;;;;;;;;;;;;OAkBG;IACH,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC;IAI5D;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,mBAAmB,IAAI,mBAAmB,GAAG,SAAS;IAItD;;;;;;;;;;;;;;;;;OAiBG;IACH,iBAAiB,IAAI,OAAO;IAI5B;;;;;;OAMG;IACH,MAAM,CAAC,aAAa,IAAI,IAAI;CAG7B"}
@@ -1,135 +0,0 @@
1
- import { AsyncLocalStorage } from 'node:async_hooks';
2
- /**
3
- * Request context store using AsyncLocalStorage
4
- *
5
- * Stores and propagates request container across async operations without manual context passing.
6
- * This enables transparent access to request-scoped services from any part of the application
7
- * during request handling.
8
- *
9
- * **Cloudflare Workers Compatibility**:
10
- * - Requires `nodejs_als` compatibility flag in wrangler.jsonc
11
- * - Uses V8's SetContinuationPreservedEmbedderData API (efficient)
12
- * - Performance overhead: ~3-4% in typical scenarios
13
- *
14
- * **Thread Safety**:
15
- * - Singleton instance shared across application
16
- * - Each request gets isolated storage context
17
- * - No context leakage between concurrent requests
18
- *
19
- * @example
20
- * ```typescript
21
- * // In router middleware
22
- * const store = RequestContextStore.getInstance()
23
- * await store.run(requestContainer, async () => {
24
- * // All async operations within this callback have access to requestContainer
25
- * await handleRequest()
26
- * })
27
- *
28
- * // In service (anywhere in the call stack)
29
- * const container = RequestContextStore.getInstance().getRequestContainer()
30
- * if (container) {
31
- * // We're in request context
32
- * const service = container.resolve(TOKEN)
33
- * }
34
- * ```
35
- */
36
- export class RequestContextStore {
37
- static instance = null;
38
- storage;
39
- /**
40
- * Private constructor - use getInstance() instead
41
- */
42
- constructor() {
43
- this.storage = new AsyncLocalStorage();
44
- }
45
- /**
46
- * Get singleton instance
47
- *
48
- * **Note**: Creates instance on first call. Subsequent calls return same instance.
49
- */
50
- static getInstance() {
51
- RequestContextStore.instance ??= new RequestContextStore();
52
- return RequestContextStore.instance;
53
- }
54
- /**
55
- * Run callback within request context
56
- *
57
- * Container is automatically available to all async operations within the callback,
58
- * including nested function calls, promises, timers, and queue handlers.
59
- *
60
- * @param container - Request-scoped dependency container
61
- * @param callback - Async operation to run with context
62
- * @returns Result of callback execution
63
- *
64
- * @example
65
- * ```typescript
66
- * const result = await store.run(requestContainer, async () => {
67
- * // Context automatically propagates to nested calls
68
- * await processRequest()
69
- * return { success: true }
70
- * })
71
- * ```
72
- */
73
- run(container, callback) {
74
- return this.storage.run(container, callback);
75
- }
76
- /**
77
- * Get current request container
78
- *
79
- * Returns the container for the current async context, or undefined if not in request context.
80
- *
81
- * **Use Cases**:
82
- * - Request-scoped services resolving from request container
83
- * - Services needing conditional logic based on context availability
84
- * - Debugging/logging request-specific information
85
- * @deprecated Use container instead
86
- * @returns Request container if in request context, undefined otherwise
87
- *
88
- * @example
89
- * ```typescript
90
- * const container = store.getRequestContainer()
91
- * if (container) {
92
- * // Safe to resolve request-scoped services
93
- * const i18n = container.resolve(I18N_TOKENS.I18nService)
94
- * } else {
95
- * // Not in request context - use fallback
96
- * console.log('No request context available')
97
- * }
98
- * ```
99
- */
100
- getRequestContainer() {
101
- return this.storage.getStore();
102
- }
103
- /**
104
- * Check if currently in request context
105
- *
106
- * Convenience method for conditional logic based on context availability.
107
- *
108
- * @returns true if in request context, false otherwise
109
- *
110
- * @example
111
- * ```typescript
112
- * if (store.hasRequestContext()) {
113
- * // Use request-specific data
114
- * const locale = getLocaleFromContext()
115
- * } else {
116
- * // Use default
117
- * const locale = 'en'
118
- * }
119
- * ```
120
- */
121
- hasRequestContext() {
122
- return this.storage.getStore() !== undefined;
123
- }
124
- /**
125
- * Reset singleton instance (for testing only)
126
- *
127
- * **Warning**: Only use in test cleanup. Never call in production code.
128
- *
129
- * @internal
130
- */
131
- static resetInstance() {
132
- RequestContextStore.instance = null;
133
- }
134
- }
135
- //# sourceMappingURL=request-context-store.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"request-context-store.js","sourceRoot":"","sources":["../../src/di/request-context-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAGpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,OAAO,mBAAmB;IACtB,MAAM,CAAC,QAAQ,GAA+B,IAAI,CAAA;IACzC,OAAO,CAAwC;IAEhE;;OAEG;IACH;QACE,IAAI,CAAC,OAAO,GAAG,IAAI,iBAAiB,EAAuB,CAAA;IAC7D,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,WAAW;QAChB,mBAAmB,CAAC,QAAQ,KAAK,IAAI,mBAAmB,EAAE,CAAA;QAC1D,OAAO,mBAAmB,CAAC,QAAQ,CAAA;IACrC,CAAC;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH,GAAG,CAAI,SAA8B,EAAE,QAAiB;QACtD,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;IAC9C,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,mBAAmB;QACjB,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAA;IAChC,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,iBAAiB;QACf,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,SAAS,CAAA;IAC9C,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,aAAa;QAClB,mBAAmB,CAAC,QAAQ,GAAG,IAAI,CAAA;IACrC,CAAC"}
@@ -1,5 +0,0 @@
1
- import { ApplicationError } from '../../errors';
2
- export declare class RouterAlreadyConfiguredError extends ApplicationError {
3
- constructor();
4
- }
5
- //# sourceMappingURL=router-already-configured.error.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"router-already-configured.error.d.ts","sourceRoot":"","sources":["../../../src/router/errors/router-already-configured.error.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAE/C,qBAAa,4BAA6B,SAAQ,gBAAgB;;CAQjE"}
@@ -1,8 +0,0 @@
1
- import { ERROR_CODES } from '../../errors';
2
- import { ApplicationError } from '../../errors';
3
- export class RouterAlreadyConfiguredError extends ApplicationError {
4
- constructor() {
5
- super('errors.routerAlreadyConfigured', ERROR_CODES.SYSTEM.CONFIGURATION_ERROR, {});
6
- }
7
- }
8
- //# sourceMappingURL=router-already-configured.error.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"router-already-configured.error.js","sourceRoot":"","sources":["../../../src/router/errors/router-already-configured.error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAE/C,MAAM,OAAO,4BAA6B,SAAQ,gBAAgB;IAChE;QACE,KAAK,CACH,gCAAgC,EAChC,WAAW,CAAC,MAAM,CAAC,mBAAmB,EACtC,EAAE,CACH,CAAA;IACH,CAAC;CACF"}
@@ -1,5 +0,0 @@
1
- import { ApplicationError } from '../../errors';
2
- export declare class RouterNotConfiguredError extends ApplicationError {
3
- constructor();
4
- }
5
- //# sourceMappingURL=router-not-configured.error.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"router-not-configured.error.d.ts","sourceRoot":"","sources":["../../../src/router/errors/router-not-configured.error.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAE/C,qBAAa,wBAAyB,SAAQ,gBAAgB;;CAQ7D"}
@@ -1,8 +0,0 @@
1
- import { ERROR_CODES } from '../../errors';
2
- import { ApplicationError } from '../../errors';
3
- export class RouterNotConfiguredError extends ApplicationError {
4
- constructor() {
5
- super('errors.routerNotConfigured', ERROR_CODES.SYSTEM.CONFIGURATION_ERROR, {});
6
- }
7
- }
8
- //# sourceMappingURL=router-not-configured.error.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"router-not-configured.error.js","sourceRoot":"","sources":["../../../src/router/errors/router-not-configured.error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAE/C,MAAM,OAAO,wBAAyB,SAAQ,gBAAgB;IAC5D;QACE,KAAK,CACH,4BAA4B,EAC5B,WAAW,CAAC,MAAM,CAAC,mBAAmB,EACtC,EAAE,CACH,CAAA;IACH,CAAC;CACF"}
@@ -1,62 +0,0 @@
1
- import { type Container } from '../di';
2
- import { type StratalEnv } from '../env';
3
- import { type LoggerService } from '../logger';
4
- import { type MiddlewareConfigEntry } from '../middleware';
5
- import type { Constructor } from '../types';
6
- import type { IController } from './controller';
7
- /**
8
- * RouterService manages HTTP routing and request handling with OpenAPI support
9
- *
10
- * Responsibilities:
11
- * - Creates and configures OpenAPIHono application
12
- * - Delegates to specialized services:
13
- * - RequestScopeService: Request-scoped container setup
14
- * - OpenAPIService: OpenAPI spec and documentation endpoints
15
- * - RouteRegistrationService: Controller and route registration
16
- * - Registers global middleware (CORS, logging, error handling)
17
- * - Handles fetch requests via Hono
18
- *
19
- * Note: Route access control (domain-based enforcement) is handled by
20
- * RouteAccessMiddleware in the tenancy module, applied via TenancyModule.configure().
21
- *
22
- * The service is registered as a singleton in the DI container
23
- * and accessed by the Backend worker's fetch() method.
24
- */
25
- export declare class RouterService {
26
- private logger;
27
- private container;
28
- private app;
29
- private configured;
30
- constructor(logger: LoggerService, container: Container);
31
- /**
32
- * Setup all middleware in correct order
33
- * Note: OpenAPI setup is deferred to configure() because it needs controllers
34
- */
35
- private setupMiddleware;
36
- /**
37
- * Setup global middleware that runs for all requests
38
- */
39
- private setupGlobalMiddleware;
40
- /**
41
- * Configure router with middlewares and controllers atomically
42
- * This MUST be called immediately after RouterService construction
43
- * and can only be called once.
44
- *
45
- * @param middlewareConfigs - Array of middleware configuration entries from modules
46
- * @param controllers - Array of controller classes from modules
47
- */
48
- configure(middlewareConfigs: MiddlewareConfigEntry[], controllers: Constructor<IController>[]): void;
49
- /**
50
- * Handle incoming fetch request via Hono
51
- *
52
- * This method is called by the Backend worker's fetch() method.
53
- * The request-scoped container is created in RequestScopeService.
54
- *
55
- * @param request - Incoming Request object
56
- * @param env - Cloudflare environment bindings
57
- * @param ctx - Cloudflare execution context
58
- * @returns Response object
59
- */
60
- fetch(request: Request, env: StratalEnv, ctx: ExecutionContext): Response | Promise<Response>;
61
- }
62
- //# sourceMappingURL=router.service.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"router.service.d.ts","sourceRoot":"","sources":["../../src/router/router.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAGvD,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,QAAQ,CAAA;AAGxC,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,WAAW,CAAA;AAC7D,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,eAAe,CAAA;AAEtB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAE3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAS/C;;;;;;;;;;;;;;;;;GAiBG;AACH,qBACa,aAAa;IAMtB,OAAO,CAAC,MAAM;IAEd,OAAO,CAAC,SAAS;IAPnB,OAAO,CAAC,GAAG,CAAwB;IACnC,OAAO,CAAC,UAAU,CAAQ;gBAIhB,MAAM,EAAE,aAAa,EAErB,SAAS,EAAE,SAAS;IA8B9B;;;OAGG;IACH,OAAO,CAAC,eAAe;IAWvB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAoB7B;;;;;;;OAOG;IACH,SAAS,CAAC,iBAAiB,EAAE,qBAAqB,EAAE,EAAE,WAAW,EAAE,WAAW,CAAC,WAAW,CAAC,EAAE,GAAG,IAAI;IAgCpG;;;;;;;;;;OAUG;IACH,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,gBAAgB,GAAG,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;CAM9F"}