glasswork 1.4.1 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. package/CHANGELOG.md +75 -1
  2. package/README.md +6 -2
  3. package/dist/audit/audit-logger.d.ts +6 -1
  4. package/dist/audit/audit-logger.d.ts.map +1 -1
  5. package/dist/audit/audit-logger.js +6 -1
  6. package/dist/audit/audit-logger.js.map +1 -1
  7. package/dist/auth/assert.d.ts +4 -0
  8. package/dist/auth/assert.d.ts.map +1 -1
  9. package/dist/auth/assert.js +7 -3
  10. package/dist/auth/assert.js.map +1 -1
  11. package/dist/auth/better-auth-provider.js +13 -4
  12. package/dist/auth/better-auth-provider.js.map +1 -1
  13. package/dist/auth/errors.d.ts +17 -0
  14. package/dist/auth/errors.d.ts.map +1 -0
  15. package/dist/auth/errors.js +23 -0
  16. package/dist/auth/errors.js.map +1 -0
  17. package/dist/auth/index.d.ts +2 -1
  18. package/dist/auth/index.d.ts.map +1 -1
  19. package/dist/auth/index.js +1 -0
  20. package/dist/auth/index.js.map +1 -1
  21. package/dist/auth/middleware.d.ts +13 -0
  22. package/dist/auth/middleware.d.ts.map +1 -1
  23. package/dist/auth/middleware.js +19 -8
  24. package/dist/auth/middleware.js.map +1 -1
  25. package/dist/auth/types.d.ts +4 -0
  26. package/dist/auth/types.d.ts.map +1 -1
  27. package/dist/config/providers.d.ts.map +1 -1
  28. package/dist/config/providers.js +5 -4
  29. package/dist/config/providers.js.map +1 -1
  30. package/dist/core/bootstrap.d.ts +2 -2
  31. package/dist/core/bootstrap.d.ts.map +1 -1
  32. package/dist/core/bootstrap.js +162 -83
  33. package/dist/core/bootstrap.js.map +1 -1
  34. package/dist/core/contract.d.ts +9 -2
  35. package/dist/core/contract.d.ts.map +1 -1
  36. package/dist/core/contract.js +2 -1
  37. package/dist/core/contract.js.map +1 -1
  38. package/dist/core/errors.d.ts +16 -0
  39. package/dist/core/errors.d.ts.map +1 -0
  40. package/dist/core/errors.js +31 -0
  41. package/dist/core/errors.js.map +1 -0
  42. package/dist/core/glasswork-config.d.ts +42 -0
  43. package/dist/core/glasswork-config.d.ts.map +1 -0
  44. package/dist/core/glasswork-config.js +2 -0
  45. package/dist/core/glasswork-config.js.map +1 -0
  46. package/dist/core/index.d.ts +7 -4
  47. package/dist/core/index.d.ts.map +1 -1
  48. package/dist/core/index.js +5 -3
  49. package/dist/core/index.js.map +1 -1
  50. package/dist/core/job-services.d.ts +16 -0
  51. package/dist/core/job-services.d.ts.map +1 -0
  52. package/dist/core/job-services.js +19 -0
  53. package/dist/core/job-services.js.map +1 -0
  54. package/dist/core/lifecycle.d.ts +30 -2
  55. package/dist/core/lifecycle.d.ts.map +1 -1
  56. package/dist/core/lifecycle.js +100 -13
  57. package/dist/core/lifecycle.js.map +1 -1
  58. package/dist/core/module-graph.d.ts +7 -1
  59. package/dist/core/module-graph.d.ts.map +1 -1
  60. package/dist/core/module-graph.js +90 -21
  61. package/dist/core/module-graph.js.map +1 -1
  62. package/dist/core/module-inspection.d.ts +44 -0
  63. package/dist/core/module-inspection.d.ts.map +1 -0
  64. package/dist/core/module-inspection.js +114 -0
  65. package/dist/core/module-inspection.js.map +1 -0
  66. package/dist/core/module-runtime.d.ts +22 -0
  67. package/dist/core/module-runtime.d.ts.map +1 -0
  68. package/dist/core/module-runtime.js +252 -0
  69. package/dist/core/module-runtime.js.map +1 -0
  70. package/dist/core/module.d.ts +5 -1
  71. package/dist/core/module.d.ts.map +1 -1
  72. package/dist/core/module.js +15 -3
  73. package/dist/core/module.js.map +1 -1
  74. package/dist/core/request-scope.d.ts +1 -1
  75. package/dist/core/request-scope.d.ts.map +1 -1
  76. package/dist/core/request-scope.js +10 -8
  77. package/dist/core/request-scope.js.map +1 -1
  78. package/dist/core/types.d.ts +106 -10
  79. package/dist/core/types.d.ts.map +1 -1
  80. package/dist/email/compiler/compiler.d.ts.map +1 -1
  81. package/dist/email/compiler/compiler.js +24 -13
  82. package/dist/email/compiler/compiler.js.map +1 -1
  83. package/dist/email/email-service.d.ts +0 -4
  84. package/dist/email/email-service.d.ts.map +1 -1
  85. package/dist/email/email-service.js +2 -29
  86. package/dist/email/email-service.js.map +1 -1
  87. package/dist/email/html-to-text.d.ts +14 -0
  88. package/dist/email/html-to-text.d.ts.map +1 -0
  89. package/dist/email/html-to-text.js +47 -0
  90. package/dist/email/html-to-text.js.map +1 -0
  91. package/dist/email/index.d.ts +1 -0
  92. package/dist/email/index.d.ts.map +1 -1
  93. package/dist/email/index.js +1 -0
  94. package/dist/email/index.js.map +1 -1
  95. package/dist/email/ses.d.ts +7 -0
  96. package/dist/email/ses.d.ts.map +1 -0
  97. package/dist/email/ses.js +6 -0
  98. package/dist/email/ses.js.map +1 -0
  99. package/dist/email/smtp.d.ts +7 -0
  100. package/dist/email/smtp.d.ts.map +1 -0
  101. package/dist/email/smtp.js +6 -0
  102. package/dist/email/smtp.js.map +1 -0
  103. package/dist/email/transports/ses-transport.d.ts.map +1 -1
  104. package/dist/email/transports/ses-transport.js +6 -4
  105. package/dist/email/transports/ses-transport.js.map +1 -1
  106. package/dist/email/transports/smtp-transport.d.ts +40 -0
  107. package/dist/email/transports/smtp-transport.d.ts.map +1 -0
  108. package/dist/email/transports/smtp-transport.js +67 -0
  109. package/dist/email/transports/smtp-transport.js.map +1 -0
  110. package/dist/http/error-handler.d.ts +7 -1
  111. package/dist/http/error-handler.d.ts.map +1 -1
  112. package/dist/http/error-handler.js +18 -6
  113. package/dist/http/error-handler.js.map +1 -1
  114. package/dist/http/error-response.dto.d.ts +6 -0
  115. package/dist/http/error-response.dto.d.ts.map +1 -1
  116. package/dist/http/error-response.dto.js +6 -0
  117. package/dist/http/error-response.dto.js.map +1 -1
  118. package/dist/http/errors.d.ts +12 -0
  119. package/dist/http/errors.d.ts.map +1 -1
  120. package/dist/http/errors.js +35 -23
  121. package/dist/http/errors.js.map +1 -1
  122. package/dist/http/index.d.ts +1 -1
  123. package/dist/http/index.d.ts.map +1 -1
  124. package/dist/http/index.js +1 -1
  125. package/dist/http/index.js.map +1 -1
  126. package/dist/http/route-authorization.d.ts.map +1 -1
  127. package/dist/http/route-authorization.js +3 -3
  128. package/dist/http/route-authorization.js.map +1 -1
  129. package/dist/http/route-helpers.d.ts +2 -1
  130. package/dist/http/route-helpers.d.ts.map +1 -1
  131. package/dist/http/route-helpers.js +29 -2
  132. package/dist/http/route-helpers.js.map +1 -1
  133. package/dist/http/route-openapi-context.d.ts +15 -1
  134. package/dist/http/route-openapi-context.d.ts.map +1 -1
  135. package/dist/http/route-openapi-context.js.map +1 -1
  136. package/dist/http/route-response.d.ts +6 -2
  137. package/dist/http/route-response.d.ts.map +1 -1
  138. package/dist/http/route-response.js +36 -16
  139. package/dist/http/route-response.js.map +1 -1
  140. package/dist/http/route-types.d.ts +12 -4
  141. package/dist/http/route-types.d.ts.map +1 -1
  142. package/dist/http/route-types.js.map +1 -1
  143. package/dist/http/route-validation.d.ts.map +1 -1
  144. package/dist/http/route-validation.js +21 -1
  145. package/dist/http/route-validation.js.map +1 -1
  146. package/dist/jobs/drivers/eventbridge-scheduler-driver.d.ts +1 -0
  147. package/dist/jobs/drivers/eventbridge-scheduler-driver.d.ts.map +1 -1
  148. package/dist/jobs/drivers/eventbridge-scheduler-driver.js +12 -2
  149. package/dist/jobs/drivers/eventbridge-scheduler-driver.js.map +1 -1
  150. package/dist/jobs/drivers/mock-driver.d.ts +4 -0
  151. package/dist/jobs/drivers/mock-driver.d.ts.map +1 -1
  152. package/dist/jobs/drivers/mock-driver.js +10 -3
  153. package/dist/jobs/drivers/mock-driver.js.map +1 -1
  154. package/dist/jobs/drivers/sqs-driver.d.ts +1 -1
  155. package/dist/jobs/drivers/sqs-driver.d.ts.map +1 -1
  156. package/dist/jobs/drivers/sqs-driver.js +8 -2
  157. package/dist/jobs/drivers/sqs-driver.js.map +1 -1
  158. package/dist/jobs/errors.d.ts +14 -1
  159. package/dist/jobs/errors.d.ts.map +1 -1
  160. package/dist/jobs/errors.js +19 -2
  161. package/dist/jobs/errors.js.map +1 -1
  162. package/dist/jobs/index.d.ts +3 -3
  163. package/dist/jobs/index.d.ts.map +1 -1
  164. package/dist/jobs/index.js +1 -1
  165. package/dist/jobs/index.js.map +1 -1
  166. package/dist/jobs/job-service.d.ts +46 -7
  167. package/dist/jobs/job-service.d.ts.map +1 -1
  168. package/dist/jobs/job-service.js +63 -9
  169. package/dist/jobs/job-service.js.map +1 -1
  170. package/dist/jobs/scheduler.d.ts +6 -0
  171. package/dist/jobs/scheduler.d.ts.map +1 -0
  172. package/dist/jobs/scheduler.js +6 -0
  173. package/dist/jobs/scheduler.js.map +1 -0
  174. package/dist/jobs/sqs.d.ts +7 -0
  175. package/dist/jobs/sqs.d.ts.map +1 -0
  176. package/dist/jobs/sqs.js +7 -0
  177. package/dist/jobs/sqs.js.map +1 -0
  178. package/dist/jobs/types.d.ts +6 -1
  179. package/dist/jobs/types.d.ts.map +1 -1
  180. package/dist/jobs/utils.d.ts +6 -0
  181. package/dist/jobs/utils.d.ts.map +1 -1
  182. package/dist/jobs/utils.js +8 -0
  183. package/dist/jobs/utils.js.map +1 -1
  184. package/dist/jobs/worker.d.ts.map +1 -1
  185. package/dist/jobs/worker.js +28 -23
  186. package/dist/jobs/worker.js.map +1 -1
  187. package/dist/middleware/rate-limit.d.ts.map +1 -1
  188. package/dist/middleware/rate-limit.js +5 -4
  189. package/dist/middleware/rate-limit.js.map +1 -1
  190. package/dist/observability/exception-tracking.d.ts +23 -0
  191. package/dist/observability/exception-tracking.d.ts.map +1 -1
  192. package/dist/observability/exception-tracking.js +101 -6
  193. package/dist/observability/exception-tracking.js.map +1 -1
  194. package/dist/observability/index.d.ts +1 -1
  195. package/dist/observability/index.d.ts.map +1 -1
  196. package/dist/observability/index.js +1 -1
  197. package/dist/observability/index.js.map +1 -1
  198. package/dist/observability/sanitizers.d.ts.map +1 -1
  199. package/dist/observability/sanitizers.js +2 -0
  200. package/dist/observability/sanitizers.js.map +1 -1
  201. package/dist/openapi/drift.d.ts +17 -2
  202. package/dist/openapi/drift.d.ts.map +1 -1
  203. package/dist/openapi/drift.js +79 -5
  204. package/dist/openapi/drift.js.map +1 -1
  205. package/dist/openapi/openapi.d.ts.map +1 -1
  206. package/dist/openapi/openapi.js +2 -1
  207. package/dist/openapi/openapi.js.map +1 -1
  208. package/dist/utils/environment.d.ts +10 -2
  209. package/dist/utils/environment.d.ts.map +1 -1
  210. package/dist/utils/environment.js +20 -3
  211. package/dist/utils/environment.js.map +1 -1
  212. package/dist/utils/module-interop.d.ts +9 -0
  213. package/dist/utils/module-interop.d.ts.map +1 -0
  214. package/dist/utils/module-interop.js +16 -0
  215. package/dist/utils/module-interop.js.map +1 -0
  216. package/dist/utils/optional-dependency.d.ts +6 -0
  217. package/dist/utils/optional-dependency.d.ts.map +1 -0
  218. package/dist/utils/optional-dependency.js +16 -0
  219. package/dist/utils/optional-dependency.js.map +1 -0
  220. package/dist/utils/serialize-prisma-types.d.ts +51 -15
  221. package/dist/utils/serialize-prisma-types.d.ts.map +1 -1
  222. package/dist/utils/serialize-prisma-types.js +47 -16
  223. package/dist/utils/serialize-prisma-types.js.map +1 -1
  224. package/package.json +56 -12
@@ -4,13 +4,15 @@
4
4
  */
5
5
  export { ConfigValidationException, createConfig, dotenvProvider, envProvider, objectProvider, parseArray, parseBoolean, parseJson, ssmProvider, toCamelCase, toSnakeCase, validateConfig, } from '../config/index.js';
6
6
  export { deepMerge } from '../utils/deep-merge.js';
7
- export { isDevelopment, isLambda, isProduction, isTest } from '../utils/environment.js';
7
+ export { detectEnvironment, isDevelopment, isLambda, isProduction, isTest, } from '../utils/environment.js';
8
8
  export { getClientIp } from '../utils/get-client-ip.js';
9
9
  export { createLogger, createPlainLogger, defaultLogger } from '../utils/logger.js';
10
10
  export { omit } from '../utils/omit.js';
11
11
  export { pick } from '../utils/pick.js';
12
- export { defaultConfig, serializePrismaTypes } from '../utils/serialize-prisma-types.js';
12
+ export { createSerializationConfig, defaultConfig, serializePrismaTypes, } from '../utils/serialize-prisma-types.js';
13
13
  export { bootstrap } from './bootstrap.js';
14
14
  export { generateOpenAPI } from './contract.js';
15
- export { defineModule } from './module.js';
15
+ export { ProviderNotAvailableError } from './errors.js';
16
+ export { defineModule, forwardRef } from './module.js';
17
+ export { inspectModuleGraph, moduleGraphToMermaid, } from './module-inspection.js';
16
18
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAIL,yBAAyB,EACzB,YAAY,EAEZ,cAAc,EAEd,WAAW,EACX,cAAc,EACd,UAAU,EACV,YAAY,EACZ,SAAS,EAET,WAAW,EACX,WAAW,EACX,WAAW,EACX,cAAc,GACf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACxF,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAExD,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACpF,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAQxC,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AACzF,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAIL,yBAAyB,EACzB,YAAY,EAEZ,cAAc,EAEd,WAAW,EACX,cAAc,EACd,UAAU,EACV,YAAY,EACZ,SAAS,EAET,WAAW,EACX,WAAW,EACX,WAAW,EACX,cAAc,GACf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,QAAQ,EACR,YAAY,EACZ,MAAM,GACP,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAExD,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACpF,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAQxC,OAAO,EACL,yBAAyB,EACzB,aAAa,EACb,oBAAoB,GACrB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAExD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EACL,kBAAkB,EAIlB,oBAAoB,GACrB,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Module cradles answer this key with a function that opens a scope in the module that
3
+ * declares a job. Queue drivers that run jobs in-process use it so a job resolves the same
4
+ * providers as it does in the worker, without exporting private services.
5
+ * @internal
6
+ */
7
+ export declare const JOB_SERVICES: unique symbol;
8
+ /** Services for one job execution and the disposal of their scope. */
9
+ export interface JobServicesScope {
10
+ services: Record<string, unknown>;
11
+ dispose(): Promise<void>;
12
+ }
13
+ export type JobServicesResolver = (jobName: string) => JobServicesScope | undefined;
14
+ /** Returns the owning module's services for a job when `services` is a module cradle. */
15
+ export declare function resolveJobServices(services: Record<string, unknown>, jobName: string): JobServicesScope | undefined;
16
+ //# sourceMappingURL=job-services.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-services.d.ts","sourceRoot":"","sources":["../../src/core/job-services.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,YAAY,eAAsC,CAAC;AAEhE,sEAAsE;AACtE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,gBAAgB,GAAG,SAAS,CAAC;AAEpF,yFAAyF;AACzF,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,OAAO,EAAE,MAAM,GACd,gBAAgB,GAAG,SAAS,CAQ9B"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Module cradles answer this key with a function that opens a scope in the module that
3
+ * declares a job. Queue drivers that run jobs in-process use it so a job resolves the same
4
+ * providers as it does in the worker, without exporting private services.
5
+ * @internal
6
+ */
7
+ export const JOB_SERVICES = Symbol.for('glasswork.jobServices');
8
+ /** Returns the owning module's services for a job when `services` is a module cradle. */
9
+ export function resolveJobServices(services, jobName) {
10
+ let resolver;
11
+ try {
12
+ resolver = services[JOB_SERVICES];
13
+ }
14
+ catch {
15
+ return undefined;
16
+ }
17
+ return typeof resolver === 'function' ? resolver(jobName) : undefined;
18
+ }
19
+ //# sourceMappingURL=job-services.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-services.js","sourceRoot":"","sources":["../../src/core/job-services.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;AAUhE,yFAAyF;AACzF,MAAM,UAAU,kBAAkB,CAChC,QAAiC,EACjC,OAAe;IAEf,IAAI,QAAiB,CAAC;IACtB,IAAI,CAAC;QACH,QAAQ,GAAI,QAAoC,CAAC,YAAY,CAAC,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,OAAO,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAE,QAAgC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACjG,CAAC"}
@@ -1,7 +1,35 @@
1
- import type { AwilixContainer } from 'awilix';
1
+ import { type AwilixContainer } from 'awilix';
2
2
  import type { Logger } from '../utils/logger.js';
3
3
  /**
4
- * Execute lifecycle hooks on all registered services in parallel.
4
+ * Execute lifecycle hooks on singleton and value providers in parallel.
5
+ *
6
+ * `onModuleInit` creates every singleton to initialize it. `onModuleDestroy` only reaches
7
+ * singletons that were already created, so shutdown never constructs a provider just to
8
+ * destroy it. Every hook runs to completion before failures are reported: one failure is
9
+ * rethrown as-is, several are combined in an `AggregateError`.
5
10
  */
6
11
  export declare function executeLifecycleHooks(container: AwilixContainer, hook: 'onModuleInit' | 'onModuleDestroy', logger: Logger): Promise<void>;
12
+ /**
13
+ * Stops the providers a container owns: destroy hooks first, then the Awilix disposers of
14
+ * resolved registrations. Value providers are borrowed and have no disposer. Disposers run
15
+ * even when a destroy hook failed.
16
+ */
17
+ export declare function shutdownContainer(container: AwilixContainer, logger: Logger): Promise<void>;
18
+ /** Rethrows a single failure unchanged and combines several in an AggregateError. */
19
+ export declare function throwFailures(failures: unknown[], message: string): void;
20
+ export interface ApplicationLifecycle {
21
+ start(): Promise<void>;
22
+ stop(): Promise<void>;
23
+ }
24
+ /**
25
+ * Runs an application's start and stop steps at most once.
26
+ *
27
+ * Concurrent calls share one promise, so `start()` only resolves after the start step has
28
+ * finished. A failed start keeps rejecting with its original error. `stop()` waits for a
29
+ * pending start to settle before it runs, and `start()` rejects once `stop()` was called.
30
+ */
31
+ export declare function createApplicationLifecycle(steps: {
32
+ start: () => Promise<void>;
33
+ stop: () => Promise<void>;
34
+ }): ApplicationLifecycle;
7
35
  //# sourceMappingURL=lifecycle.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../src/core/lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAEjD;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,eAAe,EAC1B,IAAI,EAAE,cAAc,GAAG,iBAAiB,EACxC,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAuBf"}
1
+ {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../src/core/lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,eAAe,EAAqC,MAAM,QAAQ,CAAC;AACjF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAEjD;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,eAAe,EAC1B,IAAI,EAAE,cAAc,GAAG,iBAAiB,EACxC,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CA4Bf;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA+BjG;AAED,qFAAqF;AACrF,wBAAgB,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAKxE;AAcD,MAAM,WAAW,oBAAoB;IACnC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE;IAChD,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B,GAAG,oBAAoB,CAoBvB"}
@@ -1,23 +1,83 @@
1
+ import { Lifetime } from 'awilix';
1
2
  /**
2
- * Execute lifecycle hooks on all registered services in parallel.
3
+ * Execute lifecycle hooks on singleton and value providers in parallel.
4
+ *
5
+ * `onModuleInit` creates every singleton to initialize it. `onModuleDestroy` only reaches
6
+ * singletons that were already created, so shutdown never constructs a provider just to
7
+ * destroy it. Every hook runs to completion before failures are reported: one failure is
8
+ * rethrown as-is, several are combined in an `AggregateError`.
3
9
  */
4
10
  export async function executeLifecycleHooks(container, hook, logger) {
5
11
  const cradle = container.cradle;
6
- const serviceNames = Object.keys(cradle);
7
- const promises = [];
8
- for (const name of serviceNames) {
9
- const service = cradle[name];
10
- if (hasHook(service, hook)) {
12
+ // Awilix rebuilds `registrations` on every access; read it once.
13
+ const registrations = container.registrations;
14
+ const names = Object.keys(registrations).filter((name) => {
15
+ const lifetime = registrations[name]?.lifetime;
16
+ if (lifetime && lifetime !== Lifetime.SINGLETON)
17
+ return false;
18
+ return hook === 'onModuleInit' || !lifetime || container.cache.has(name);
19
+ });
20
+ const results = await Promise.allSettled(names.map(async (name) => {
21
+ try {
22
+ const service = cradle[name];
23
+ if (!hasHook(service, hook))
24
+ return;
11
25
  logger.debug(`Executing ${hook} for ${name}`);
12
- promises.push(Promise.resolve()
13
- .then(() => service[hook]())
14
- .catch((err) => {
15
- logger.error(`Error in ${hook} for ${name}`, err);
16
- throw err;
17
- }));
26
+ await service[hook]();
18
27
  }
28
+ catch (error) {
29
+ logger.error(`Error in ${hook} for ${name}`, error);
30
+ throw error;
31
+ }
32
+ }));
33
+ throwFailures(results.flatMap((result) => (result.status === 'rejected' ? [result.reason] : [])), `${hook} failed`);
34
+ }
35
+ /**
36
+ * Stops the providers a container owns: destroy hooks first, then the Awilix disposers of
37
+ * resolved registrations. Value providers are borrowed and have no disposer. Disposers run
38
+ * even when a destroy hook failed.
39
+ */
40
+ export async function shutdownContainer(container, logger) {
41
+ const failures = [];
42
+ await executeLifecycleHooks(container, 'onModuleDestroy', logger).catch((error) => {
43
+ failures.push(error);
44
+ });
45
+ // Awilix uses Promise.all for disposal. Preserve its cache ownership, but collect each
46
+ // disposer failure so its promise waits for every close before shutdown rejects.
47
+ for (const [name, entry] of container.cache) {
48
+ const resolver = entry.resolver;
49
+ const dispose = resolver.dispose;
50
+ if (!dispose)
51
+ continue;
52
+ container.cache.set(name, {
53
+ ...entry,
54
+ resolver: {
55
+ ...resolver,
56
+ dispose: async (value) => {
57
+ try {
58
+ await dispose.call(resolver, value);
59
+ }
60
+ catch (error) {
61
+ logger.error(`Error while disposing provider ${String(name)}`, error);
62
+ failures.push(error);
63
+ }
64
+ },
65
+ },
66
+ });
67
+ }
68
+ await container.dispose().catch((error) => {
69
+ logger.error('Error while disposing providers', error);
70
+ failures.push(error);
71
+ });
72
+ throwFailures(failures, 'Shutdown failed');
73
+ }
74
+ /** Rethrows a single failure unchanged and combines several in an AggregateError. */
75
+ export function throwFailures(failures, message) {
76
+ if (failures.length === 1)
77
+ throw failures[0];
78
+ if (failures.length > 1) {
79
+ throw new AggregateError(failures, `${message} (${failures.length} errors)`);
19
80
  }
20
- await Promise.all(promises);
21
81
  }
22
82
  function hasHook(service, hook) {
23
83
  return (service !== null &&
@@ -25,4 +85,31 @@ function hasHook(service, hook) {
25
85
  hook in service &&
26
86
  typeof service[hook] === 'function');
27
87
  }
88
+ /**
89
+ * Runs an application's start and stop steps at most once.
90
+ *
91
+ * Concurrent calls share one promise, so `start()` only resolves after the start step has
92
+ * finished. A failed start keeps rejecting with its original error. `stop()` waits for a
93
+ * pending start to settle before it runs, and `start()` rejects once `stop()` was called.
94
+ */
95
+ export function createApplicationLifecycle(steps) {
96
+ let starting;
97
+ let stopping;
98
+ return {
99
+ start() {
100
+ if (stopping) {
101
+ return Promise.reject(new Error('Application has been stopped and cannot start again'));
102
+ }
103
+ starting ??= steps.start();
104
+ return starting;
105
+ },
106
+ stop() {
107
+ stopping ??= (async () => {
108
+ await starting?.catch(() => undefined);
109
+ await steps.stop();
110
+ })();
111
+ return stopping;
112
+ },
113
+ };
114
+ }
28
115
  //# sourceMappingURL=lifecycle.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../src/core/lifecycle.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,SAA0B,EAC1B,IAAwC,EACxC,MAAc;IAEd,MAAM,MAAM,GAAG,SAAS,CAAC,MAAiC,CAAC;IAC3D,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEzC,MAAM,QAAQ,GAAoB,EAAE,CAAC;IAErC,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QAE7B,IAAI,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;YAC3B,MAAM,CAAC,KAAK,CAAC,aAAa,IAAI,QAAQ,IAAI,EAAE,CAAC,CAAC;YAC9C,QAAQ,CAAC,IAAI,CACX,OAAO,CAAC,OAAO,EAAE;iBACd,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;iBAC3B,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;gBACb,MAAM,CAAC,KAAK,CAAC,YAAY,IAAI,QAAQ,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC;gBAClD,MAAM,GAAG,CAAC;YACZ,CAAC,CAAC,CACL,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,OAAO,CACd,OAAgB,EAChB,IAAwC;IAExC,OAAO,CACL,OAAO,KAAK,IAAI;QAChB,OAAO,OAAO,KAAK,QAAQ;QAC3B,IAAI,IAAI,OAAO;QACf,OAAQ,OAAmC,CAAC,IAAI,CAAC,KAAK,UAAU,CACjE,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../src/core/lifecycle.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { AwilixContainer } from 'awilix';
1
+ import type { AwilixContainer, Resolver } from 'awilix';
2
2
  import type { Logger } from '../utils/logger.js';
3
3
  import type { ModuleConfig } from './types.js';
4
4
  /**
@@ -18,4 +18,10 @@ export declare function registerModuleProviders(module: ModuleConfig, container:
18
18
  * Resolve async factory providers and re-register them as values.
19
19
  */
20
20
  export declare function resolveAsyncFactoryProviders(container: AwilixContainer, names: string[], logger?: Logger): Promise<void>;
21
+ /** Factory dependency metadata used to order asynchronous initialization. */
22
+ export interface DependencyResolver extends Resolver<unknown> {
23
+ dependencies?: string[];
24
+ /** Awilix disposer, set by `.disposer()`. */
25
+ dispose?: (value: unknown) => unknown;
26
+ }
21
27
  //# sourceMappingURL=module-graph.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"module-graph.d.ts","sourceRoot":"","sources":["../../src/core/module-graph.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EAAe,YAAY,EAAgC,MAAM,YAAY,CAAC;AAE1F;;GAEG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,YAAY,GAAG,YAAY,EAAE,CAsBvE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,IAAI,CAyC9D;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,YAAY,EACpB,SAAS,EAAE,eAAe,EAC1B,MAAM,EAAE,MAAM,GACb,MAAM,EAAE,CAeV;AAED;;GAEG;AACH,wBAAsB,4BAA4B,CAChD,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,MAAM,EAAE,EACf,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAoBf"}
1
+ {"version":3,"file":"module-graph.d.ts","sourceRoot":"","sources":["../../src/core/module-graph.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAExD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAEjD,OAAO,KAAK,EAAe,YAAY,EAAgC,MAAM,YAAY,CAAC;AAE1F;;GAEG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,YAAY,GAAG,YAAY,EAAE,CAyBvE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,IAAI,CA4C9D;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,YAAY,EACpB,SAAS,EAAE,eAAe,EAC1B,MAAM,EAAE,MAAM,GACb,MAAM,EAAE,CAeV;AAED;;GAEG;AACH,wBAAsB,4BAA4B,CAChD,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,MAAM,EAAE,EACf,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAoCf;AAyBD,6EAA6E;AAC7E,MAAM,WAAW,kBAAmB,SAAQ,QAAQ,CAAC,OAAO,CAAC;IAC3D,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;CACvC"}
@@ -1,4 +1,5 @@
1
1
  import { asClass, asFunction, asValue } from 'awilix';
2
+ import { resolveModule } from './module.js';
2
3
  /**
3
4
  * Collect all modules (flatten imports recursively).
4
5
  */
@@ -7,13 +8,16 @@ export function collectModules(rootModule) {
7
8
  const visited = new Set();
8
9
  function collect(module) {
9
10
  if (visited.has(module.name)) {
11
+ if (modules.get(module.name) !== module) {
12
+ throw new Error(`Duplicate module name "${module.name}"`);
13
+ }
10
14
  return;
11
15
  }
12
16
  visited.add(module.name);
13
17
  modules.set(module.name, module);
14
18
  if (module.imports) {
15
19
  for (const importedModule of module.imports) {
16
- collect(importedModule);
20
+ collect(resolveModule(importedModule));
17
21
  }
18
22
  }
19
23
  }
@@ -31,7 +35,10 @@ export function validateNoCycles(modules) {
31
35
  }
32
36
  if (module.imports) {
33
37
  for (const importedModule of module.imports) {
34
- graph.get(module.name)?.add(importedModule.name);
38
+ // Deferred edges explicitly break module initialization cycles.
39
+ if (!('forwardRef' in importedModule)) {
40
+ graph.get(module.name)?.add(importedModule.name);
41
+ }
35
42
  }
36
43
  }
37
44
  }
@@ -80,23 +87,60 @@ export async function resolveAsyncFactoryProviders(container, names, logger) {
80
87
  if (names.length === 0) {
81
88
  return;
82
89
  }
83
- try {
84
- // Resolve in registration order so async factories can depend on earlier ones.
85
- for (const name of names) {
90
+ const pending = new Set(names);
91
+ const completed = new Set();
92
+ const visiting = new Set();
93
+ async function initialize(name) {
94
+ if (completed.has(name))
95
+ return;
96
+ if (visiting.has(name))
97
+ throw new Error(`Circular async factory dependency: ${[...visiting, name].join(' -> ')}`);
98
+ visiting.add(name);
99
+ const registration = container.getRegistration(name);
100
+ for (const dependency of registration?.dependencies ?? [])
101
+ await initialize(dependency);
102
+ if (pending.has(name)) {
86
103
  logger?.debug(` - Resolving async factory: ${name}`);
87
- const resolved = container.resolve(name);
88
- const value = resolved instanceof Promise ? await resolved : resolved;
89
- container.register({
90
- [name]: asValue(value),
91
- });
92
- logger?.debug(` - Resolved ${name} (async factory → value)`);
104
+ let value;
105
+ try {
106
+ value = await container.resolve(name);
107
+ }
108
+ catch (error) {
109
+ // Disposal must not receive the rejected promise cached for this singleton.
110
+ container.cache.delete(name);
111
+ throw error;
112
+ }
113
+ registerResolvedValue(container, name, value, registration?.dispose);
93
114
  }
115
+ visiting.delete(name);
116
+ completed.add(name);
117
+ }
118
+ try {
119
+ for (const name of names)
120
+ await initialize(name);
94
121
  }
95
122
  catch (error) {
96
123
  logger?.error('Failed to resolve async providers', { error });
97
124
  throw error;
98
125
  }
99
126
  }
127
+ /**
128
+ * Replaces an async factory with its resolved value. The cached promise is dropped, and a
129
+ * disposer moves to a singleton holding the value so that disposal receives the value.
130
+ */
131
+ function registerResolvedValue(container, name, value, dispose) {
132
+ container.cache.delete(name);
133
+ if (!dispose) {
134
+ container.register({ [name]: asValue(value) });
135
+ return;
136
+ }
137
+ container.register({
138
+ [name]: asFunction(() => value)
139
+ .singleton()
140
+ .disposer(dispose),
141
+ });
142
+ container.resolve(name);
143
+ }
100
144
  function registerProvider(provider, container, moduleName, logger) {
101
145
  if (typeof provider === 'function') {
102
146
  registerClassProvider(provider, container, logger);
@@ -111,7 +155,7 @@ function registerProvider(provider, container, moduleName, logger) {
111
155
  return undefined;
112
156
  }
113
157
  if ('useFactory' in provider) {
114
- return registerFactoryProvider(provider, container, logger);
158
+ return registerFactoryProvider(provider, container, moduleName, logger);
115
159
  }
116
160
  throw new Error(`Invalid provider configuration in module "${moduleName}"`);
117
161
  }
@@ -125,10 +169,13 @@ function registerClassProvider(provider, container, logger) {
125
169
  function registerExplicitClassProvider(provider, container, logger) {
126
170
  const name = typeof provider.provide === 'string' ? provider.provide : camelCase(provider.provide.name);
127
171
  const scope = provider.scope || 'SINGLETON';
172
+ if (provider.dispose && scope === 'TRANSIENT') {
173
+ throw new Error(`Provider "${name}": dispose requires SINGLETON or SCOPED scope`);
174
+ }
128
175
  logger.debug(` - Registering ${name} (scope: ${scope})`);
129
- const registration = asClass(provider.useClass);
176
+ const registration = applyScopeToRegistration(asClass(provider.useClass), scope);
130
177
  container.register({
131
- [name]: applyScopeToRegistration(registration, scope),
178
+ [name]: provider.dispose ? registration.disposer(provider.dispose) : registration,
132
179
  });
133
180
  }
134
181
  function registerValueProvider(provider, container, logger) {
@@ -137,26 +184,48 @@ function registerValueProvider(provider, container, logger) {
137
184
  [provider.provide]: asValue(provider.useValue),
138
185
  });
139
186
  }
140
- function registerFactoryProvider(provider, container, logger) {
187
+ function registerFactoryProvider(provider, container, moduleName, logger) {
141
188
  const scope = provider.scope || 'SINGLETON';
189
+ if (provider.dispose && scope === 'TRANSIENT') {
190
+ throw new Error(`Provider "${provider.provide}": dispose requires SINGLETON or SCOPED scope`);
191
+ }
142
192
  const factory = provider.useFactory;
143
- const isAsync = isAsyncFunction(factory);
193
+ const isAsync = provider.async ?? isAsyncFunction(factory);
144
194
  if (isAsync && scope !== 'SINGLETON') {
145
195
  throw new Error(`Async factory "${provider.provide}" must use SINGLETON scope`);
146
196
  }
147
197
  logger.debug(` - Registering ${provider.provide} (factory${isAsync ? ' async' : ''}, scope: ${scope})`);
148
- const registration = asFunction(factory);
149
- if (provider.inject && provider.inject.length > 0) {
150
- registration.inject(() => provider.inject);
151
- }
198
+ const create = isAsync || scope !== 'SINGLETON'
199
+ ? factory
200
+ : rejectPromiseResult(factory, provider.provide, moduleName);
201
+ const registration = applyScopeToRegistration(Object.assign(asFunction(create), { dependencies: provider.inject ?? [] }), scope);
152
202
  container.register({
153
- [provider.provide]: applyScopeToRegistration(registration, scope),
203
+ [provider.provide]: provider.dispose ? registration.disposer(provider.dispose) : registration,
154
204
  });
155
205
  return isAsync ? provider.provide : undefined;
156
206
  }
157
207
  function isAsyncFunction(fn) {
158
208
  return fn.constructor.name === 'AsyncFunction';
159
209
  }
210
+ /**
211
+ * A singleton factory that is not known to be async would hand its pending promise to every
212
+ * consumer. Fail with the fix instead of awaiting it implicitly.
213
+ */
214
+ function rejectPromiseResult(factory, name, moduleName) {
215
+ return (...args) => {
216
+ const value = factory(...args);
217
+ if (isThenable(value)) {
218
+ void Promise.resolve(value).catch(() => undefined);
219
+ throw new Error(`Factory "${name}" in module "${moduleName}" returned a Promise. Use an async function or set async: true so bootstrap awaits it.`);
220
+ }
221
+ return value;
222
+ };
223
+ }
224
+ function isThenable(value) {
225
+ return ((typeof value === 'object' || typeof value === 'function') &&
226
+ value !== null &&
227
+ typeof value.then === 'function');
228
+ }
160
229
  function applyScopeToRegistration(registration, scope) {
161
230
  if (scope === 'SCOPED') {
162
231
  return registration.scoped();
@@ -1 +1 @@
1
- {"version":3,"file":"module-graph.js","sourceRoot":"","sources":["../../src/core/module-graph.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"module-graph.js","sourceRoot":"","sources":["../../src/core/module-graph.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ import type { ModuleConfig } from './types.js';
2
+ export interface ModuleGraphProvider {
3
+ name: string;
4
+ kind: 'class' | 'factory' | 'value';
5
+ /** Value providers have no Awilix lifetime. */
6
+ scope: 'SINGLETON' | 'SCOPED' | 'TRANSIENT' | 'VALUE';
7
+ /** Async factories are awaited during bootstrap. */
8
+ async: boolean;
9
+ exported: boolean;
10
+ /** Dependencies declared with `inject`. Constructor dependencies are not analyzed. */
11
+ inject: string[];
12
+ }
13
+ export interface ModuleGraphNode {
14
+ name: string;
15
+ basePath?: string;
16
+ /** `deferred` marks a `forwardRef()` import. */
17
+ imports: Array<{
18
+ module: string;
19
+ deferred: boolean;
20
+ }>;
21
+ /** Provider names the module exports, including re-exports of imported modules. */
22
+ exports: string[];
23
+ providers: ModuleGraphProvider[];
24
+ jobs: string[];
25
+ hasRoutes: boolean;
26
+ }
27
+ export interface ModuleGraph {
28
+ root: string;
29
+ modules: ModuleGraphNode[];
30
+ /** Module cycles closed by `forwardRef()` imports, as module names from first to last. */
31
+ cycles: string[][];
32
+ }
33
+ /**
34
+ * Describe the module graph of an application without creating any provider.
35
+ *
36
+ * Runs the same checks as bootstrap: duplicate module and provider names, undeferred import
37
+ * cycles, ambiguous imports, unknown exports and `inject` dependencies that a module cannot
38
+ * see. It does not run factories, route factories or lifecycle hooks, so it needs no
39
+ * database, network or credentials.
40
+ */
41
+ export declare function inspectModuleGraph(root: ModuleConfig): ModuleGraph;
42
+ /** Render a module graph as a Mermaid flowchart. Deferred imports use dotted arrows. */
43
+ export declare function moduleGraphToMermaid(graph: ModuleGraph): string;
44
+ //# sourceMappingURL=module-inspection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-inspection.d.ts","sourceRoot":"","sources":["../../src/core/module-inspection.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAkB,MAAM,YAAY,CAAC;AAE/D,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;IACpC,+CAA+C;IAC/C,KAAK,EAAE,WAAW,GAAG,QAAQ,GAAG,WAAW,GAAG,OAAO,CAAC;IACtD,oDAAoD;IACpD,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,sFAAsF;IACtF,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,OAAO,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACtD,mFAAmF;IACnF,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,mBAAmB,EAAE,CAAC;IACjC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,0FAA0F;IAC1F,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,YAAY,GAAG,WAAW,CAwBlE;AAqED,wFAAwF;AACxF,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAoB/D"}