@classytic/arc 2.19.0 → 2.21.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 (139) hide show
  1. package/README.md +1 -1
  2. package/bin/arc.js +37 -0
  3. package/dist/{BaseController-Dy6EQHjM.mjs → BaseController-BnLYgE9A.mjs} +4 -4
  4. package/dist/{EventTransport-IEn7Tn-Q.d.mts → EventTransport-QmY7A258.d.mts} +0 -1
  5. package/dist/{QueryCache-TRfXau3W.d.mts → QueryCache-Z1B38koh.d.mts} +0 -1
  6. package/dist/{ResourceRegistry-5fKZwhK_.mjs → ResourceRegistry-7RnrEWNP.mjs} +1 -1
  7. package/dist/{actionPermissions-D7NGwcAR.mjs → actionPermissions-ze70xXJi.mjs} +1 -1
  8. package/dist/audit/index.d.mts +9 -5
  9. package/dist/audit/index.mjs +1 -1
  10. package/dist/auth/audit.d.mts +7 -4
  11. package/dist/auth/audit.mjs +5 -0
  12. package/dist/auth/index.d.mts +7 -14
  13. package/dist/auth/index.mjs +7 -5
  14. package/dist/auth/redis-session.d.mts +1 -2
  15. package/dist/{buildHandler-B0qvAguf.mjs → buildHandler-D_2ULWxZ.mjs} +3 -3
  16. package/dist/cache/index.d.mts +2 -3
  17. package/dist/cache/index.mjs +2 -2
  18. package/dist/cli/commands/describe.d.mts +1 -2
  19. package/dist/cli/commands/describe.mjs +2 -2
  20. package/dist/cli/commands/docs.mjs +2 -2
  21. package/dist/cli/commands/generate.mjs +1 -1
  22. package/dist/cli/commands/init.mjs +1 -1
  23. package/dist/cli/commands/introspect.mjs +4 -13
  24. package/dist/cli/index.mjs +2 -2
  25. package/dist/{constants-gaEeMlz-.mjs → constants-DNre0wRg.mjs} +1 -1
  26. package/dist/context/index.d.mts +2 -2
  27. package/dist/core/index.d.mts +3 -3
  28. package/dist/core/index.mjs +5 -5
  29. package/dist/{core-Ba-6Sue6.mjs → core-DZ6Xe1jR.mjs} +182 -55
  30. package/dist/{createActionRouter-B_WzBFyf.mjs → createActionRouter-BWMDW-dL.mjs} +4 -4
  31. package/dist/{createAggregationRouter-B_G_nIjm.mjs → createAggregationRouter-l5mNdYrZ.mjs} +5 -4
  32. package/dist/{createApp--703hQE1.mjs → createApp-Bi61XxqU.mjs} +229 -24
  33. package/dist/discovery/index.d.mts +0 -1
  34. package/dist/docs/index.d.mts +1 -2
  35. package/dist/docs/index.mjs +1 -1
  36. package/dist/{elevation-xGUBq6p_.d.mts → elevation-C9s5hFP_.d.mts} +0 -1
  37. package/dist/encryption/index.d.mts +2 -144
  38. package/dist/{errorHandler-BtUUDPEa.d.mts → errorHandler-B0e-bq-O.d.mts} +0 -1
  39. package/dist/{errors-DOHkjQlD.d.mts → errors-DHcHVAgk.d.mts} +0 -1
  40. package/dist/{eventPlugin-DbBFd3x_.d.mts → eventPlugin-A6EbthXR.d.mts} +10 -6
  41. package/dist/events/index.d.mts +9 -6
  42. package/dist/events/index.mjs +9 -6
  43. package/dist/events/transports/redis-stream-entry.d.mts +1 -1
  44. package/dist/events/transports/redis.d.mts +1 -2
  45. package/dist/factory/index.d.mts +5 -4
  46. package/dist/factory/index.mjs +3 -3
  47. package/dist/{fastify-augmentation-D-5_yQJi.d.mts → fastify-augmentation-DafigGQp.d.mts} +12 -2
  48. package/dist/{fields-C7ahdGYf.d.mts → fields-BGqrAa_u.d.mts} +1 -2
  49. package/dist/{generate-Brans3fW.mjs → generate-usRSdQmP.mjs} +4 -3
  50. package/dist/hooks/index.d.mts +1 -1
  51. package/dist/idempotency/index.d.mts +4 -3
  52. package/dist/idempotency/index.mjs +1 -1
  53. package/dist/idempotency/redis.d.mts +1 -1
  54. package/dist/{index-CP6A1Ffj.d.mts → index-B5N-NaHs.d.mts} +88 -7
  55. package/dist/{index-CRKiiP5o.d.mts → index-B5PoNbfu.d.mts} +41 -7
  56. package/dist/{index-CUTG2Cuo.d.mts → index-Dtrj6XZk.d.mts} +90 -29
  57. package/dist/index.d.mts +7 -7
  58. package/dist/index.mjs +7 -7
  59. package/dist/{init-Bqpt1Hxf.mjs → init-0YhHkXGk.mjs} +239 -140
  60. package/dist/integrations/event-gateway.d.mts +2 -3
  61. package/dist/integrations/index.d.mts +2 -2
  62. package/dist/integrations/jobs.d.mts +0 -1
  63. package/dist/integrations/mcp/index.d.mts +6 -7
  64. package/dist/integrations/mcp/index.mjs +1 -1
  65. package/dist/integrations/mcp/testing.d.mts +1 -2
  66. package/dist/integrations/mcp/testing.mjs +1 -1
  67. package/dist/integrations/streamline.d.mts +19 -7
  68. package/dist/integrations/streamline.mjs +9 -5
  69. package/dist/integrations/webhooks.d.mts +0 -1
  70. package/dist/integrations/websocket-pushref-redis.d.mts +1 -2
  71. package/dist/integrations/websocket-redis.d.mts +1 -2
  72. package/dist/integrations/websocket.d.mts +2 -2
  73. package/dist/{loadResources-B8UmpITt.mjs → loadResources-DpU8pfjV.mjs} +4 -3
  74. package/dist/{loadResourcesFromEntry-BTlFEx05.mjs → loadResourcesFromEntry-OMCvIEE7.mjs} +1 -1
  75. package/dist/{mcpPlugin-C088Nd-G.mjs → mcpPlugin-B9XjjNVG.mjs} +148 -49
  76. package/dist/middleware/index.d.mts +1 -2
  77. package/dist/middleware/index.mjs +1 -1
  78. package/dist/module-WeuU5jfd.d.mts +429 -0
  79. package/dist/{openapi-DZ-5a5Op.mjs → openapi-Kyod_di6.mjs} +3 -3
  80. package/dist/permissions/index.d.mts +3 -3
  81. package/dist/permissions/index.mjs +2 -2
  82. package/dist/{permissions-BPB1xqGf.mjs → permissions-BJMuKMl7.mjs} +43 -3
  83. package/dist/pipeline/index.d.mts +1 -2
  84. package/dist/plugins/index.d.mts +87 -10
  85. package/dist/plugins/index.mjs +91 -4
  86. package/dist/plugins/response-cache.d.mts +5 -3
  87. package/dist/plugins/tracing-entry.d.mts +1 -1
  88. package/dist/plugins/tracing-entry.mjs +1 -1
  89. package/dist/{pluralize-DccFV9R7.mjs → pluralize-BhrgwZb9.mjs} +3 -3
  90. package/dist/presets/filesUpload.d.mts +4 -5
  91. package/dist/presets/filesUpload.mjs +1 -1
  92. package/dist/presets/index.d.mts +16 -3
  93. package/dist/presets/index.mjs +1 -1
  94. package/dist/presets/multiTenant.d.mts +1 -2
  95. package/dist/presets/multiTenant.mjs +1 -1
  96. package/dist/presets/search.d.mts +2 -3
  97. package/dist/presets/search.mjs +3 -2
  98. package/dist/{presets-BtyFwTO4.mjs → presets-gw0ciIUD.mjs} +1 -1
  99. package/dist/{pushref-registry-DnCqL3aa.d.mts → pushref-registry-BbcnpNTm.d.mts} +4 -2
  100. package/dist/{queryCachePlugin-xzFyKAjT.d.mts → queryCachePlugin-CfYWq-Ak.d.mts} +1 -2
  101. package/dist/{queryCachePlugin-emHb0CuX.mjs → queryCachePlugin-DzqLN904.mjs} +2 -2
  102. package/dist/{redis-C3W0qbz8.d.mts → redis-UDtLaNj6.d.mts} +0 -1
  103. package/dist/{redis-stream-DsP1vqZB.d.mts → redis-stream-iVR2l7aS.d.mts} +1 -2
  104. package/dist/{registerRoute-BdV8DDwU.mjs → registerRoute-oGAl0oA8.mjs} +1 -1
  105. package/dist/registry/index.d.mts +2 -2
  106. package/dist/registry/index.mjs +2 -2
  107. package/dist/{registry-Bm9LjWKs.mjs → registry-vcOCtPij.mjs} +1 -1
  108. package/dist/{schemaIR-D1MJwqmp.mjs → schemaIR-ajetw3Fv.mjs} +1 -42
  109. package/dist/schemas/index.d.mts +0 -1
  110. package/dist/scim/index.d.mts +0 -1
  111. package/dist/scim/index.mjs +2 -2
  112. package/dist/scope/index.d.mts +2 -3
  113. package/dist/{sessionManager-BXG-HGwG.d.mts → sessionManager-BHOM3N_0.d.mts} +10 -6
  114. package/dist/{storage-Co_PQpeQ.d.mts → storage-DLUZ04kK.d.mts} +8 -4
  115. package/dist/sync/changelog.d.mts +2 -0
  116. package/dist/sync/changelog.mjs +2 -0
  117. package/dist/testing/index.d.mts +2 -3
  118. package/dist/testing/index.mjs +6 -3
  119. package/dist/testing/storageContract.d.mts +1 -2
  120. package/dist/{tracing-D8jlGXP7.d.mts → tracing-CsGKQJGg.d.mts} +0 -1
  121. package/dist/types/index.d.mts +4 -4
  122. package/dist/types/storage.d.mts +1 -1
  123. package/dist/types-Cc91nXuA.d.mts +132 -0
  124. package/dist/{types-LNebCoJx.d.mts → types-DH0GupI7.d.mts} +8 -4
  125. package/dist/{types-DpvSF5Hh.d.mts → types-DRj-Ut4n.d.mts} +1 -2
  126. package/dist/{types-9_wtNPsI.d.mts → types-DpxoNX5v.d.mts} +112 -214
  127. package/dist/utils/index.d.mts +182 -128
  128. package/dist/utils/index.mjs +2 -2
  129. package/dist/{utils-C6QQ9-hd.mjs → utils-CO8a3B_1.mjs} +1435 -1391
  130. package/dist/{validate-CRcaWzp2.mjs → validate-C2mGgSXg.mjs} +3 -3
  131. package/dist/{versioning-D_eBCfNr.d.mts → versioning-DQ4mCvg0.d.mts} +1 -2
  132. package/dist/{websocket-MlYlrYq0.d.mts → websocket-uuWqM6UY.d.mts} +5 -4
  133. package/package.json +18 -13
  134. package/skills/arc/SKILL.md +10 -0
  135. package/skills/arc/references/mcp.md +2 -0
  136. package/skills/arc-module-publishing/SKILL.md +242 -0
  137. package/skills/arc-module-publishing/references/authoring-modules.md +272 -0
  138. package/skills/arc-module-publishing/references/package-manifest.md +155 -0
  139. package/skills/arc-module-publishing/references/publishing-workflow.md +182 -0
@@ -1,208 +1,15 @@
1
- import { Ut as Authenticator } from "./index-CUTG2Cuo.mjs";
1
+ import { Ut as Authenticator } from "./index-Dtrj6XZk.mjs";
2
2
  import { r as CacheStore } from "./interface-C1_WLTMK.mjs";
3
- import { n as ElevationOptions } from "./elevation-xGUBq6p_.mjs";
4
- import { a as EventTransport } from "./EventTransport-IEn7Tn-Q.mjs";
3
+ import { n as ElevationOptions } from "./elevation-C9s5hFP_.mjs";
4
+ import { a as EventTransport } from "./EventTransport-QmY7A258.mjs";
5
5
  import { t as ExternalOpenApiPaths } from "./externalPaths-BE6wFpYv.mjs";
6
- import { r as QueryCachePluginOptions } from "./queryCachePlugin-xzFyKAjT.mjs";
7
- import { t as EventPluginOptions } from "./eventPlugin-DbBFd3x_.mjs";
8
- import { _ as HealthOptions, f as CachingOptions, l as SSEOptions, o as MetricsOptions, t as VersioningOptions } from "./versioning-D_eBCfNr.mjs";
9
- import { t as ErrorHandlerOptions } from "./errorHandler-BtUUDPEa.mjs";
6
+ import { r as QueryCachePluginOptions } from "./queryCachePlugin-CfYWq-Ak.mjs";
7
+ import { t as ErrorHandlerOptions } from "./errorHandler-B0e-bq-O.mjs";
8
+ import { l as ResourceLike, n as ArcModuleInput } from "./module-WeuU5jfd.mjs";
9
+ import { t as EventPluginOptions } from "./eventPlugin-A6EbthXR.mjs";
10
+ import { _ as HealthOptions, f as CachingOptions, l as SSEOptions, o as MetricsOptions, t as VersioningOptions } from "./versioning-DQ4mCvg0.mjs";
10
11
  import { r as IdempotencyStore } from "./interface-Uk8ONJv7.mjs";
11
12
  import { FastifyInstance, FastifyPluginAsync, FastifyReply, FastifyRequest, FastifyServerOptions } from "fastify";
12
-
13
- //#region src/factory/loadResources.d.ts
14
- /**
15
- * loadResources — Auto-discover resource files from a directory.
16
- *
17
- * Scans for `*.resource.{ts,js,mts,mjs}` files, imports each,
18
- * and collects their default exports. No barrel file needed.
19
- *
20
- * @example
21
- * ```ts
22
- * import { createApp, loadResources } from '@classytic/arc/factory';
23
- *
24
- * // Recommended: import.meta.url — works in both src/ (dev) and dist/ (prod)
25
- * const app = await createApp({
26
- * resources: await loadResources(import.meta.url),
27
- * auth: { type: 'jwt', jwt: { secret: process.env.JWT_SECRET } },
28
- * });
29
- *
30
- * // Or explicit path (must match runtime layout)
31
- * const app2 = await createApp({
32
- * resources: await loadResources('./src/resources'),
33
- * });
34
- * ```
35
- *
36
- * File convention:
37
- * ```
38
- * src/resources/
39
- * product/product.resource.ts → export default defineResource({ name: 'product', ... })
40
- * order/order.resource.ts → export default defineResource({ name: 'order', ... })
41
- * ```
42
- */
43
- /**
44
- * Resource interface — the contract between `loadResources`/`createApp` and resource definitions.
45
- *
46
- * Matches the shape of `ResourceDefinition` from `defineResource()` without requiring
47
- * the import. All properties except `toPlugin` are optional so plain objects work too:
48
- *
49
- * ```typescript
50
- * // Full resource (from defineResource)
51
- * const product = defineResource({ name: 'product', ... }); // satisfies ResourceLike
52
- *
53
- * // Minimal resource (plain object)
54
- * const simple: ResourceLike = { name: 'ping', toPlugin: () => () => {} };
55
- * ```
56
- *
57
- * **DO NOT add an index signature** (`[key: string]: unknown`) to this interface.
58
- * Class instances (like `ResourceDefinition`) don't implicitly carry index signatures,
59
- * so adding one here makes `ResourceDefinition` *unassignable* to `ResourceLike` —
60
- * the exact opposite of the intent. TypeScript's structural typing already allows
61
- * classes with extra properties to satisfy this interface without an index signature.
62
- */
63
- interface ResourceLike {
64
- /** Plugin factory — called by createApp to register routes */
65
- toPlugin: () => unknown;
66
- /** Resource name (used for route generation, logging, duplicate detection) */
67
- name?: string;
68
- /** Route prefix (default: `/${name}s`) */
69
- prefix?: string;
70
- /** Skip the global `resourcePrefix` from createApp — register at root */
71
- skipGlobalPrefix?: boolean;
72
- /** Display name for docs/OpenAPI */
73
- displayName?: string;
74
- /** Applied preset names */
75
- _appliedPresets?: string[];
76
- }
77
- /**
78
- * Resource module — what a `.resource.ts` file's default (or named) export
79
- * may resolve to.
80
- *
81
- * Two shapes accepted:
82
- * 1. **Plain `ResourceLike`** — the result of `defineResource({...})`.
83
- * Used as-is; no engine wiring needed.
84
- * 2. **Factory `(ctx: TContext) => ResourceLike | Promise<ResourceLike>`**
85
- * — a function arc calls with the `context` from `LoadResourcesOptions`.
86
- * Eliminates the parallel `createXResource(engine)` factory files +
87
- * `exclude: [...]` bookkeeping that engine-bound resources used to need.
88
- *
89
- * Detection is by `typeof === 'function'`: `ResourceDefinition` instances
90
- * (returned by `defineResource()`) are class instances (`typeof === 'object'`),
91
- * so the two shapes are unambiguous in practice.
92
- */
93
- type ResourceModule<TContext = unknown> = ResourceLike | ((ctx: TContext) => ResourceLike | Promise<ResourceLike>);
94
- interface LoadResourcesOptions<TContext = unknown> {
95
- /** File pattern suffix (default: '.resource'). Matches `*.resource.{ts,js,mts,mjs}`. */
96
- suffix?: string;
97
- /** Recurse into subdirectories (default: true) */
98
- recursive?: boolean;
99
- /**
100
- * Context passed to factory-style default exports. Resources whose default
101
- * export is a function `(ctx) => ResourceLike` are called with this value;
102
- * plain `ResourceLike` exports are returned unchanged.
103
- *
104
- * Use this to thread engine handles into engine-bound resources without
105
- * creating parallel factory files outside `loadResources`'s sweep:
106
- *
107
- * ```ts
108
- * // category.resource.ts
109
- * import type { AppContext } from '#core/app/context.js';
110
- * export default (ctx: AppContext) =>
111
- * defineResource({
112
- * name: 'category',
113
- * adapter: createMongooseAdapter(
114
- * ctx.catalog.models.Category,
115
- * ctx.catalog.repositories.category,
116
- * ),
117
- * });
118
- *
119
- * // create-arc-app-options.ts
120
- * resources: async () => {
121
- * const [catalog, flow] = await Promise.all([
122
- * ensureCatalogEngine(),
123
- * ensureFlowEngine(),
124
- * ]);
125
- * return loadResources(import.meta.url, { context: { catalog, flow } });
126
- * }
127
- * ```
128
- *
129
- * Backwards compatible — pre-2.11.1 callers omit `context`, plain exports
130
- * keep working unchanged. Factories that need a context but receive
131
- * `undefined` should narrow defensively.
132
- */
133
- context?: TContext;
134
- /**
135
- * Resource names to exclude. Matched against the resource's `.name` property
136
- * after import, so you use the resource name (not the filename).
137
- *
138
- * @example
139
- * ```ts
140
- * await loadResources('./src/resources', { exclude: ['debug', 'legacy-report'] })
141
- * ```
142
- */
143
- exclude?: string[];
144
- /**
145
- * Resource names to include. When set, only matching resources are returned.
146
- * Takes priority over `exclude`.
147
- *
148
- * @example
149
- * ```ts
150
- * // Only load these two resources (useful for testing or microservice splits)
151
- * await loadResources('./src/resources', { include: ['product', 'order'] })
152
- * ```
153
- */
154
- include?: string[];
155
- /**
156
- * Optional logger override for diagnostics. When omitted, warnings flow
157
- * through arc's standard logger (`arcLog('loadResources')`) — same path
158
- * as every other arc-internal warning, controlled by `ARC_SUPPRESS_WARNINGS=1`
159
- * and routable via `configureArcLogger({ writer })`.
160
- *
161
- * Pass any object with `warn(msg)` to override (e.g. `fastify.log` —
162
- * which is what `registerResources` passes automatically when arc's
163
- * factory triggers auto-discovery via `resourceDir`).
164
- *
165
- * Pre-2.11.1 had a `silent: boolean` flag and "silent by default" semantics;
166
- * both removed. Migration:
167
- *
168
- * ```ts
169
- * // Pre-2.11.1 // 2.11.1+
170
- * loadResources(url, { silent: true }); // ARC_SUPPRESS_WARNINGS=1 (env)
171
- * // OR configureArcLogger({ writer })
172
- * loadResources(url, { silent: !isDev }); // ARC_SUPPRESS_WARNINGS=1 in prod
173
- * loadResources(url, { logger: pinoAdapter }); // unchanged — still works
174
- * ```
175
- */
176
- logger?: {
177
- warn: (msg: string) => void;
178
- };
179
- }
180
- /**
181
- * Scan a directory for resource files and import their default exports.
182
- *
183
- * Accepts a directory path OR `import.meta.url` (file:// URL).
184
- * When given a URL, resolves to the directory containing that file —
185
- * so `loadResources(import.meta.url)` works in both dev (`src/`) and
186
- * production (`dist/`) without path gymnastics.
187
- *
188
- * @param dir - Directory path, or `import.meta.url` (file:// URL resolved to its dirname)
189
- * @param options - Pattern and recursion options
190
- * @returns Array of resource definitions (anything with `.toPlugin()`)
191
- *
192
- * @example
193
- * ```ts
194
- * // Works from both src/ and dist/ — resolves relative to the calling file
195
- * await loadResources(import.meta.url);
196
- *
197
- * // Subdirectory relative to the calling file
198
- * await loadResources(import.meta.url, { suffix: '.resource' });
199
- *
200
- * // Explicit path (must match runtime layout)
201
- * await loadResources('./src/resources');
202
- * ```
203
- */
204
- declare function loadResources<TContext = unknown>(dir: string, options?: LoadResourcesOptions<TContext>): Promise<ResourceLike[]>;
205
- //#endregion
206
13
  //#region src/testing/preloadResources.d.ts
207
14
  /** Eager glob result: `{ '/path/to/file.ts': resourceModule }` */
208
15
  type EagerGlobResult = Record<string, unknown>;
@@ -287,11 +94,17 @@ interface JwtAuthOption {
287
94
  * If provided, jwt utilities are available in authenticator context
288
95
  */
289
96
  jwt?: {
290
- /** JWT secret (required for JWT features) */secret: string; /** Access token expiry (default: '15m') */
291
- expiresIn?: string; /** Refresh token secret (defaults to main secret) */
292
- refreshSecret?: string; /** Refresh token expiry (default: '7d') */
293
- refreshExpiresIn?: string; /** Additional @fastify/jwt sign options */
294
- sign?: Record<string, unknown>; /** Additional @fastify/jwt verify options */
97
+ /** JWT secret (required for JWT features) */
98
+ secret: string;
99
+ /** Access token expiry (default: '15m') */
100
+ expiresIn?: string;
101
+ /** Refresh token secret (defaults to main secret) */
102
+ refreshSecret?: string;
103
+ /** Refresh token expiry (default: '7d') */
104
+ refreshExpiresIn?: string;
105
+ /** Additional @fastify/jwt sign options */
106
+ sign?: Record<string, unknown>;
107
+ /** Additional @fastify/jwt verify options */
295
108
  verify?: Record<string, unknown>;
296
109
  };
297
110
  /**
@@ -481,9 +294,13 @@ interface CreateAppOptions {
481
294
  * not memory-backed. Provide Redis or other durable adapters.
482
295
  */
483
296
  stores?: {
484
- /** Event transport (e.g., RedisEventTransport) */events?: EventTransport; /** Cache store (e.g., RedisCacheStore) */
485
- cache?: CacheStore; /** Idempotency store (e.g., RedisIdempotencyStore) */
486
- idempotency?: IdempotencyStore; /** QueryCache store (e.g., RedisCacheStore). Default: MemoryCacheStore. */
297
+ /** Event transport (e.g., RedisEventTransport) */
298
+ events?: EventTransport;
299
+ /** Cache store (e.g., RedisCacheStore) */
300
+ cache?: CacheStore;
301
+ /** Idempotency store (e.g., RedisIdempotencyStore) */
302
+ idempotency?: IdempotencyStore;
303
+ /** QueryCache store (e.g., RedisCacheStore). Default: MemoryCacheStore. */
487
304
  queryCache?: CacheStore;
488
305
  };
489
306
  /** Fastify logger configuration */
@@ -634,7 +451,8 @@ interface CreateAppOptions {
634
451
  rawBody?: RawBodyOptions | false;
635
452
  /** Enable Arc plugins (requestId, health, gracefulShutdown, events, caching, sse) */
636
453
  arcPlugins?: {
637
- /** Request ID tracking (default: true) */requestId?: boolean;
454
+ /** Request ID tracking (default: true) */
455
+ requestId?: boolean;
638
456
  /**
639
457
  * Health endpoints (default: true).
640
458
  *
@@ -661,8 +479,10 @@ interface CreateAppOptions {
661
479
  * }
662
480
  * ```
663
481
  */
664
- health?: boolean | HealthOptions; /** Graceful shutdown handling (default: true) */
665
- gracefulShutdown?: boolean; /** Emit events for CRUD operations (default: true) */
482
+ health?: boolean | HealthOptions;
483
+ /** Graceful shutdown handling (default: true) */
484
+ gracefulShutdown?: boolean;
485
+ /** Emit events for CRUD operations (default: true) */
666
486
  emitEvents?: boolean;
667
487
  /**
668
488
  * Event plugin configuration. Default: true (enabled with MemoryEventTransport).
@@ -843,6 +663,56 @@ interface CreateAppOptions {
843
663
  * ```
844
664
  */
845
665
  serializeBigInt?: boolean | "number" | "string";
666
+ /**
667
+ * Domain modules — compose whole domains into the app, one entry each.
668
+ *
669
+ * Where a `resources` entry is a single route group, a module is a self-
670
+ * contained domain package's full contribution (engine init + resources +
671
+ * post-wiring) bundled as one `ArcModule`. A package exports
672
+ * `createXModule(deps): ArcModule`; the host lists it here instead of hand-
673
+ * threading the package's pieces across `bootstrap` / `resources` /
674
+ * `afterResources`.
675
+ *
676
+ * Modules are pure sugar over the existing lifecycle — each expands into the
677
+ * SAME phases, in `dependsOn` order, running BEFORE the app-level entry in
678
+ * every phase:
679
+ * ```
680
+ * app plugins() → modules[].plugins (infra registration)
681
+ * modules[].bootstrap → options.bootstrap
682
+ * modules[].resources → options.resources / resourceDir (see note ↓)
683
+ * modules[].afterResources → options.afterResources
684
+ * modules[].onClose (REVERSE order) → options.onClose (one hook; see below)
685
+ * ```
686
+ * RESOURCES — two orderings, both intentional: app `resources`/`resourceDir`
687
+ * RESOLVE first (semantics untouched), but module resources REGISTER first
688
+ * (prepended, so their routes mount ahead of app resources). Teardown runs
689
+ * module `onClose` (reverse composition order) then app `onClose` in a single
690
+ * close hook, so module teardown (flush outboxes, drain queues, close a
691
+ * module-owned connection) sees live shared infra — the app/plugin
692
+ * connections close last. Module resources flow through arc's normal
693
+ * registration (prefix, dedup, docs, audit) — they are not special-cased.
694
+ *
695
+ * Entries may be eager modules, promises, or **thunks of dynamic imports**
696
+ * (the `next/dynamic` idea, backend-shaped) — thunks resolve once at boot,
697
+ * so region/tier-gated packs are only imported when selected:
698
+ *
699
+ * @example
700
+ * ```ts
701
+ * const taxPack = region === 'BD'
702
+ * ? () => import('@classytic/bd-tax/module').then((m) => m.createBdTaxModule(deps))
703
+ * : () => import('@classytic/us-tax/module').then((m) => m.createUsTaxModule(deps));
704
+ *
705
+ * const app = await createApp({
706
+ * resourcePrefix: '/api/v1',
707
+ * modules: [accountingModule({ permissions }), taxPack],
708
+ * resources: [healthResource], // app-local resources still compose alongside
709
+ * });
710
+ * ```
711
+ *
712
+ * See `wiki/modules.md` for the full design (authoring convention, events/
713
+ * outbox integration, microservices path).
714
+ */
715
+ modules?: ReadonlyArray<ArcModuleInput>;
846
716
  /**
847
717
  * Resources to register automatically. Accepts two shapes:
848
718
  *
@@ -993,6 +863,32 @@ interface CreateAppOptions {
993
863
  * @default false
994
864
  */
995
865
  strictResources?: boolean;
866
+ /**
867
+ * Pre-boot hook — awaited BEFORE arc does anything else: before the
868
+ * Fastify instance exists, before module thunks resolve, before resource
869
+ * discovery imports a single host file.
870
+ *
871
+ * The canonical slot for the DB connection and anything that
872
+ * module-EVAL-time code depends on. Engines that register Mongoose models
873
+ * at import time (top-level `createXEngine(...)`) trigger eager
874
+ * `createIndex()` calls from schema plugins — if the connection isn't
875
+ * open yet those buffer and die with `buffering timed out`. Hosts used to
876
+ * hand-orchestrate this with `await connectDatabase()` + dynamic
877
+ * `await import(...)` tricks before calling `createApp`; with `beforeBoot`
878
+ * the ordering is arc's contract instead:
879
+ *
880
+ * ```ts
881
+ * const app = await createApp({
882
+ * beforeBoot: async () => { await connectDatabase(); },
883
+ * modules: [() => import('#modules/accounting.js')], // thunks resolve AFTER beforeBoot
884
+ * resources: async () => [...],
885
+ * });
886
+ * ```
887
+ *
888
+ * Runs after option validation (config bugs fail fast without touching
889
+ * the DB). Cleanup stays host-owned — pair with `onClose`.
890
+ */
891
+ beforeBoot?: () => void | Promise<void>;
996
892
  /**
997
893
  * Custom plugin registration — runs after Arc core (security, auth, events)
998
894
  * but before `bootstrap` and `resources`.
@@ -1049,7 +945,9 @@ interface UnderPressureOptions {
1049
945
  }
1050
946
  interface MultipartOptions {
1051
947
  limits?: {
1052
- /** Max file size in bytes (default: Fastify default ~1MB) */fileSize?: number; /** Max number of files per request */
948
+ /** Max file size in bytes (default: Fastify default ~1MB) */
949
+ fileSize?: number;
950
+ /** Max number of files per request */
1053
951
  files?: number;
1054
952
  };
1055
953
  }
@@ -1064,4 +962,4 @@ interface RawBodyOptions {
1064
962
  runFirst?: boolean;
1065
963
  }
1066
964
  //#endregion
1067
- export { CustomPluginAuthOption as a, RawBodyOptions as c, preloadResourcesAsync as d, LoadResourcesOptions as f, loadResources as h, CustomAuthenticatorOption as i, UnderPressureOptions as l, ResourceModule as m, BetterAuthOption as n, JwtAuthOption as o, ResourceLike as p, CreateAppOptions as r, MultipartOptions as s, AuthOption as t, preloadResources as u };
965
+ export { CustomPluginAuthOption as a, RawBodyOptions as c, preloadResourcesAsync as d, CustomAuthenticatorOption as i, UnderPressureOptions as l, BetterAuthOption as n, JwtAuthOption as o, CreateAppOptions as r, MultipartOptions as s, AuthOption as t, preloadResources as u };