@classytic/arc 2.22.0 → 2.25.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.
- package/dist/{BaseController-C6FlRWxF.mjs → BaseController--M8EMzt0.mjs} +92 -22
- package/dist/QueryCache-DOMT_iq7.d.mts +72 -0
- package/dist/{ResourceRegistry-7RnrEWNP.mjs → ResourceRegistry-y9Hnypus.mjs} +1 -0
- package/dist/actionPermissions-CAphcmUG.mjs +24 -0
- package/dist/applyPermissionResult-Tw4iXtlf.mjs +264 -0
- package/dist/audit/index.d.mts +32 -3
- package/dist/audit/index.mjs +7 -4
- package/dist/auth/index.d.mts +2 -2
- package/dist/auth/index.mjs +264 -260
- package/dist/{buildHandler-D_2ULWxZ.mjs → buildHandler-Dtwd8fdz.mjs} +1 -1
- package/dist/cache/index.d.mts +41 -3
- package/dist/cache/index.mjs +33 -4
- package/dist/cli/commands/describe.d.mts +1 -1
- package/dist/cli/commands/describe.mjs +1 -1
- package/dist/cli/commands/docs.mjs +2 -2
- package/dist/cli/commands/generate.mjs +1 -1
- package/dist/cli/commands/init.mjs +1 -1
- package/dist/cli/commands/introspect.mjs +1 -1
- package/dist/cli/index.mjs +2 -2
- package/dist/context/index.mjs +2 -64
- package/dist/core/index.d.mts +3 -3
- package/dist/core/index.mjs +4 -4
- package/dist/{core-b6fgFgnd.mjs → core-EUNu0u07.mjs} +298 -12
- package/dist/{createActionRouter-h1cEEaEX.mjs → createActionRouter-B6GvAuAX.mjs} +4 -3
- package/dist/{createAggregationRouter-B1C0kvTL.mjs → createAggregationRouter-wzwFa_dW.mjs} +3 -3
- package/dist/docs/index.d.mts +1 -1
- package/dist/docs/index.mjs +2 -2
- package/dist/{elevation-COpYKt2h.mjs → elevation-CIz1GjGm.mjs} +4 -3
- package/dist/{errorHandler-BTzXSwIg.mjs → errorHandler-Bq2OeEQL.mjs} +10 -7
- package/dist/{eventPlugin-A6EbthXR.d.mts → eventPlugin-Bg3cP2_u.d.mts} +38 -3
- package/dist/{eventPlugin-DJG2D7sy.mjs → eventPlugin-DrQ_FesK.mjs} +22 -4
- package/dist/events/index.d.mts +57 -314
- package/dist/events/index.mjs +168 -93
- package/dist/events/transports/redis-stream-entry.d.mts +1 -1
- package/dist/events/transports/redis-stream-entry.mjs +24 -2
- package/dist/factory/index.d.mts +21 -6
- package/dist/factory/index.mjs +58 -18
- package/dist/{fastify-augmentation-9_fuetB4.d.mts → fastify-augmentation-dPNBVeIj.d.mts} +25 -2
- package/dist/{generate-usRSdQmP.mjs → generate-D0wZupBg.mjs} +1 -1
- package/dist/headers-BvlQSDMB.mjs +45 -0
- package/dist/health-CB_m4S32.mjs +377 -0
- package/dist/hooks/index.d.mts +1 -1
- package/dist/idempotency/index.d.mts +7 -0
- package/dist/idempotency/index.mjs +32 -20
- package/dist/{index-ogIHvOjo.d.mts → index-BMnbzvtO.d.mts} +70 -4
- package/dist/{integrations/jobs.d.mts → index-CG4yqMDB.d.mts} +82 -2
- package/dist/{index-DbtgCOCj.d.mts → index-DPRH0Cme.d.mts} +46 -94
- package/dist/{module-B4u10iOJ.d.mts → index-KUoxjIq1.d.mts} +263 -23
- package/dist/{index-D8MKYGDa.d.mts → index-f4PTrk3B.d.mts} +37 -5
- package/dist/index.d.mts +6 -6
- package/dist/index.mjs +6 -5
- package/dist/{init-DleK3p9f.mjs → init-tlRSt667.mjs} +206 -205
- package/dist/integrations/event-gateway.d.mts +1 -1
- package/dist/integrations/event-gateway.mjs +1 -1
- package/dist/integrations/index.d.mts +3 -3
- package/dist/integrations/jobs/index.d.mts +2 -0
- package/dist/integrations/{jobs.mjs → jobs/index.mjs} +110 -67
- package/dist/integrations/mcp/index.d.mts +68 -5
- package/dist/integrations/mcp/index.mjs +2 -2
- package/dist/integrations/mcp/testing.d.mts +1 -1
- package/dist/integrations/mcp/testing.mjs +1 -1
- package/dist/integrations/webhooks.d.mts +149 -22
- package/dist/integrations/webhooks.mjs +186 -42
- package/dist/integrations/websocket-redis.d.mts +1 -1
- package/dist/integrations/websocket.d.mts +1 -1
- package/dist/integrations/websocket.mjs +41 -14
- package/dist/{interface-C1_WLTMK.d.mts → interface-BGZCzOGL.d.mts} +24 -31
- package/dist/interface-n5hpKg1d.mjs +16 -0
- package/dist/{loadResourcesFromEntry-OMCvIEE7.mjs → loadResourcesFromEntry-kvGT6EcO.mjs} +1 -1
- package/dist/{mcpPlugin-ByA2tf6D.mjs → mcpPlugin-Cb7olw0j.mjs} +316 -45
- package/dist/{memory-CLXA2VeJ.mjs → memory-CmnzXE5Z.mjs} +29 -0
- package/dist/middleware/index.d.mts +17 -1
- package/dist/middleware/index.mjs +1 -1
- package/dist/migrations/index.d.mts +94 -44
- package/dist/migrations/index.mjs +196 -44
- package/dist/{multipartBody-CHEQSZ6G.mjs → multipartBody-D0eBvkeq.mjs} +17 -0
- package/dist/{openapi-BRpMZD7C.mjs → openapi-DrLtog_B.mjs} +4 -4
- package/dist/permissions/index.d.mts +3 -3
- package/dist/permissions/index.mjs +4 -3
- package/dist/{permissions-BJMuKMl7.mjs → permissions-BrtiBKGs.mjs} +305 -492
- package/dist/pipeline/index.d.mts +1 -1
- package/dist/{actionPermissions-ze70xXJi.mjs → pipeline-BN5G05rd.mjs} +4 -27
- package/dist/plugins/index.d.mts +7 -78
- package/dist/plugins/index.mjs +14 -97
- package/dist/plugins/response-cache.mjs +1 -0
- package/dist/plugins/tracing-entry.mjs +1 -1
- package/dist/{index-BEu4wjbL.d.mts → preloadResources-0oe-JSSS.d.mts} +59 -50
- package/dist/{createApp-Ci7yG5gv.mjs → preloadResources-DfyngIN9.mjs} +240 -68
- package/dist/presets/filesUpload.d.mts +3 -3
- package/dist/presets/filesUpload.mjs +3 -3
- package/dist/presets/index.d.mts +2 -1
- package/dist/presets/index.mjs +1 -1
- package/dist/presets/multiTenant.d.mts +1 -1
- package/dist/presets/multiTenant.mjs +1 -1
- package/dist/presets/search.d.mts +2 -2
- package/dist/presets/search.mjs +1 -1
- package/dist/{presets-gw0ciIUD.mjs → presets-DwFDVKP0.mjs} +2 -2
- package/dist/{queryCachePlugin-DzqLN904.mjs → queryCachePlugin-DSGuSVLW.mjs} +39 -8
- package/dist/{queryCachePlugin-CfYWq-Ak.d.mts → queryCachePlugin-br4otiqF.d.mts} +2 -2
- package/dist/{registerRoute-xHc42fwB.mjs → rateLimit-DrED-C4v.mjs} +2 -109
- package/dist/realtime-Cuw_deA-.mjs +375 -0
- package/dist/{redis-stream-iVR2l7aS.d.mts → redis-stream-uIaauNpZ.d.mts} +22 -0
- package/dist/registerRoute-v0Wb6Plt.mjs +108 -0
- package/dist/registry/index.d.mts +2 -2
- package/dist/registry/index.mjs +1 -1
- package/dist/renewingLease-3cuQH7h8.mjs +44 -0
- package/dist/{requestContext-BZKOr13H.mjs → requestContext-MrlJwECf.mjs} +2 -2
- package/dist/schedules-CjOd2MG9.mjs +113 -0
- package/dist/{schemaConverter-Ds5reSGs.mjs → schemaConverter-DJvodiHj.mjs} +4 -1
- package/dist/{schemaIR-B-6SPe7g.mjs → schemaIR-Ca7ySNPx.mjs} +1 -1
- package/dist/schemas/index.d.mts +67 -67
- package/dist/schemas/index.mjs +2 -3
- package/dist/scim/index.mjs +1 -2
- package/dist/scope/index.d.mts +2 -2
- package/dist/scope/index.mjs +4 -4
- package/dist/scope-DfaPntpo.mjs +36 -0
- package/dist/simpleEqualityMatcher-Cg05HPsn.mjs +68 -0
- package/dist/{sse-CfUjwjDk.mjs → sse-BQ1w0dfl.mjs} +8 -31
- package/dist/sseStream-BQ7Qaynp.mjs +57 -0
- package/dist/testing/index.d.mts +4 -3
- package/dist/testing/index.mjs +2 -2
- package/dist/transactionContext-PNdoyLLm.mjs +64 -0
- package/dist/types/index.d.mts +4 -4
- package/dist/{types-bHblZ9YN.mjs → types-CSyCxl2V.mjs} +38 -7
- package/dist/{types-DH0GupI7.d.mts → types-DjC-KUCz.d.mts} +118 -20
- package/dist/{types-Csxga7d3.d.mts → types-Dmw-6Qeo.d.mts} +96 -4
- package/dist/{types-Bc42CUyk.d.mts → types-QFGc3Cjv.d.mts} +37 -2
- package/dist/usage/index.d.mts +3 -52
- package/dist/usage/index.mjs +0 -0
- package/dist/userHelpers-Cg_y3fBz.mjs +29 -0
- package/dist/utils/index.d.mts +90 -57
- package/dist/utils/index.mjs +7 -3
- package/dist/{utils-FhJ88TJE.mjs → utils-taUVD4p3.mjs} +47 -385
- package/dist/{validate-C2mGgSXg.mjs → validate-Bk44F2yT.mjs} +1 -1
- package/dist/{versioning-DLwklPlG.d.mts → versioning-DXgY5BUm.d.mts} +52 -31
- package/dist/{versioning-Dk-71iIz.mjs → versioning-gKWyryT3.mjs} +8 -1
- package/dist/{websocket-uuWqM6UY.d.mts → websocket-_Pd0CgR0.d.mts} +15 -1
- package/package.json +526 -453
- package/skills/arc/references/api-reference.md +3 -1
- package/skills/arc/references/integrations.md +20 -11
- package/skills/arc/references/production.md +734 -696
- package/dist/QueryCache-Z1B38koh.d.mts +0 -40
- package/dist/betterAuthOpenApi-CV1lxpRX.mjs +0 -2
- package/dist/health-ScyjIVo5.mjs +0 -202
- package/dist/requestId-5BhTVzBv.mjs +0 -113
- package/dist/scope-k15RXfcq.mjs +0 -64
- package/dist/types-XTApa8b6.mjs +0 -24
|
@@ -1,5 +1,59 @@
|
|
|
1
1
|
import { FastifyPluginAsync } from "fastify";
|
|
2
|
-
//#region src/integrations/jobs.d.ts
|
|
2
|
+
//#region src/integrations/jobs/execution.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Timed handler execution — the concurrency core of the jobs worker,
|
|
5
|
+
* extracted from the BullMQ registration so the algorithm is testable
|
|
6
|
+
* without queue mocks.
|
|
7
|
+
*
|
|
8
|
+
* Contract:
|
|
9
|
+
* - The handler receives an `AbortSignal`, aborted when `timeoutMs`
|
|
10
|
+
* elapses. The timeout rejects THIS call; the handler itself is only
|
|
11
|
+
* signalled — cooperative cancellation.
|
|
12
|
+
* - `releaseSlot` (the bulkhead semaphore) fires when the handler
|
|
13
|
+
* promise SETTLES, not when the timeout rejects — a timed-out handler
|
|
14
|
+
* that keeps running still occupies its concurrency slot, so retries
|
|
15
|
+
* can't stack live executions past the limit.
|
|
16
|
+
* - `cancelGraceMs` bounds that hold: a handler ignoring its signal past
|
|
17
|
+
* timeout + grace has its slot force-released (logged loudly — beyond
|
|
18
|
+
* this point the bulkhead can be exceeded by the abandoned execution).
|
|
19
|
+
* - A timed-out handler's eventual settle is logged for observability;
|
|
20
|
+
* its result is discarded.
|
|
21
|
+
* - `releaseSlot` is invoked exactly once, on every path (success,
|
|
22
|
+
* failure, timeout-then-settle, grace expiry). Synchronous throws from
|
|
23
|
+
* the handler are converted to rejections so release always fires.
|
|
24
|
+
*/
|
|
25
|
+
interface TimedHandlerLogger {
|
|
26
|
+
warn(obj: Record<string, unknown>, msg: string): void;
|
|
27
|
+
}
|
|
28
|
+
interface ExecuteTimedHandlerOptions<T> {
|
|
29
|
+
/** The work. Must treat the signal as its cancellation channel. */
|
|
30
|
+
run: (signal: AbortSignal) => Promise<T>;
|
|
31
|
+
/** Job/queue label for timeout errors and logs. */
|
|
32
|
+
label: string;
|
|
33
|
+
/** Correlation id for logs (e.g. the BullMQ job id). */
|
|
34
|
+
jobId?: string;
|
|
35
|
+
/** Reject after this many ms and abort the signal. Omit = no timeout. */
|
|
36
|
+
timeoutMs?: number;
|
|
37
|
+
/** Slot hold-bound after timeout (default: 30_000). */
|
|
38
|
+
cancelGraceMs?: number;
|
|
39
|
+
/** Bulkhead slot release — called exactly once. Omit when unguarded. */
|
|
40
|
+
releaseSlot?: () => void;
|
|
41
|
+
logger?: TimedHandlerLogger;
|
|
42
|
+
}
|
|
43
|
+
declare function executeTimedHandler<T>(options: ExecuteTimedHandlerOptions<T>): Promise<T>;
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/integrations/jobs/types.d.ts
|
|
46
|
+
/**
|
|
47
|
+
* Job queue integration — public contract (definitions, meta, dispatcher).
|
|
48
|
+
*
|
|
49
|
+
* Directory map (mechanical split of the former single file):
|
|
50
|
+
* types.ts — this contract + `defineJob`
|
|
51
|
+
* execution.ts — `executeTimedHandler` (timeout / cancellation / bulkhead)
|
|
52
|
+
* repeat.ts — repeatable-schedule reconciliation (boot hygiene)
|
|
53
|
+
* plugin.ts — BullMQ wiring (queues, workers, DLQ, routes, shutdown)
|
|
54
|
+
* index.ts — public barrel; `src/integrations/jobs.ts` re-exports it
|
|
55
|
+
* so the package subpath is unchanged
|
|
56
|
+
*/
|
|
3
57
|
/** Repeat schedule — cron pattern or fixed interval. Explicit timezone is required. */
|
|
4
58
|
interface JobRepeatOptions {
|
|
5
59
|
/** Cron pattern (e.g. '0 9 * * *' = every day 09:00). Mutually exclusive with `every`. */
|
|
@@ -44,13 +98,37 @@ interface JobDefinition<TData = unknown, TResult = unknown> {
|
|
|
44
98
|
* and appear as `throttled: true` in `GET /jobs/:id/status`.
|
|
45
99
|
* Distinct from BullMQ `concurrency` — use this when the constraint is a
|
|
46
100
|
* downstream resource (AI model rate limit, DB connection pool, external API).
|
|
101
|
+
*
|
|
102
|
+
* The slot is held until the handler actually SETTLES — a timed-out
|
|
103
|
+
* handler that keeps running (ignoring `meta.signal`) still counts
|
|
104
|
+
* against `maxConcurrent`, so retries can't stack live executions past
|
|
105
|
+
* the limit. `cancelGraceMs` bounds how long a stuck handler may hold
|
|
106
|
+
* its slot after timeout.
|
|
47
107
|
*/
|
|
48
108
|
maxConcurrent?: number;
|
|
109
|
+
/**
|
|
110
|
+
* How long after a TIMEOUT a still-running handler may keep its
|
|
111
|
+
* `maxConcurrent` slot before the slot is force-released (default:
|
|
112
|
+
* 30_000). The bulkhead limits LIVE handlers, not worker awaits — but a
|
|
113
|
+
* handler that ignores `meta.signal` forever must not wedge the queue.
|
|
114
|
+
* A force-release is logged loudly: past that point the bulkhead can be
|
|
115
|
+
* exceeded by the abandoned execution.
|
|
116
|
+
*/
|
|
117
|
+
cancelGraceMs?: number;
|
|
49
118
|
}
|
|
50
119
|
interface JobMeta {
|
|
51
120
|
jobId: string;
|
|
52
121
|
attemptsMade: number;
|
|
53
122
|
timestamp: number;
|
|
123
|
+
/**
|
|
124
|
+
* Aborted when the job's `timeout` elapses. Pass it to fetch/DB calls so
|
|
125
|
+
* timed-out work actually STOPS — the timeout alone only rejects the
|
|
126
|
+
* worker's await (releasing the concurrency slot) while the handler keeps
|
|
127
|
+
* running; a BullMQ retry can then overlap the original execution.
|
|
128
|
+
* Handlers that ignore the signal must be idempotent / compare-and-set
|
|
129
|
+
* safe under that overlap.
|
|
130
|
+
*/
|
|
131
|
+
signal: AbortSignal;
|
|
54
132
|
}
|
|
55
133
|
interface JobDispatchOptions {
|
|
56
134
|
/** Delay job execution by ms */
|
|
@@ -148,6 +226,8 @@ interface QueueStats {
|
|
|
148
226
|
* });
|
|
149
227
|
*/
|
|
150
228
|
declare function defineJob<TData = unknown, TResult = unknown>(definition: JobDefinition<TData, TResult>): JobDefinition<TData, TResult>;
|
|
229
|
+
//#endregion
|
|
230
|
+
//#region src/integrations/jobs/plugin.d.ts
|
|
151
231
|
/**
|
|
152
232
|
* Pluggable BullMQ job queue integration for Arc.
|
|
153
233
|
*
|
|
@@ -156,4 +236,4 @@ declare function defineJob<TData = unknown, TResult = unknown>(definition: JobDe
|
|
|
156
236
|
*/
|
|
157
237
|
declare const jobsPlugin: FastifyPluginAsync<JobsPluginOptions>;
|
|
158
238
|
//#endregion
|
|
159
|
-
export {
|
|
239
|
+
export { JobMeta as a, JobsPluginOptions as c, ExecuteTimedHandlerOptions as d, TimedHandlerLogger as f, JobDispatcher as i, QueueStats as l, JobDefinition as n, JobRepeatOptions as o, executeTimedHandler as p, JobDispatchOptions as r, JobStatus as s, jobsPlugin as t, defineJob as u };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as QueryCacheConfig } from "./QueryCache-
|
|
2
|
-
import { i as RequestScope } from "./types-
|
|
3
|
-
import { i as UserBase, t as PermissionCheck } from "./types-
|
|
1
|
+
import { a as QueryCacheConfig } from "./QueryCache-DOMT_iq7.mjs";
|
|
2
|
+
import { P as ArcHeaders, i as RequestScope } from "./types-DjC-KUCz.mjs";
|
|
3
|
+
import { c as AnyRecord, i as UserBase, t as PermissionCheck } from "./types-Dmw-6Qeo.mjs";
|
|
4
4
|
import "./elevation-C9s5hFP_.mjs";
|
|
5
5
|
import { n as FieldPermissionMap } from "./fields-D3lhgzhD.mjs";
|
|
6
6
|
import { n as EncryptionDirective } from "./types-Cc91nXuA.mjs";
|
|
@@ -620,9 +620,9 @@ declare class QueryResolver {
|
|
|
620
620
|
/** Sanitize advanced populate options against allowedPopulate */
|
|
621
621
|
private sanitizePopulateOptions;
|
|
622
622
|
/**
|
|
623
|
-
* Sanitize lookup/join options.
|
|
624
|
-
*
|
|
625
|
-
*
|
|
623
|
+
* Sanitize lookup/join options. Deny-by-default: `allowedLookups` must be
|
|
624
|
+
* configured for any client-driven lookup to pass; listed collections are
|
|
625
|
+
* then structurally validated to prevent injection.
|
|
626
626
|
*/
|
|
627
627
|
private sanitizeLookups;
|
|
628
628
|
/**
|
|
@@ -833,6 +833,26 @@ declare class BaseCrudController<TDoc = AnyRecord, TRepository extends Repositor
|
|
|
833
833
|
* create/update, the original input (`existing`) for delete.
|
|
834
834
|
*/
|
|
835
835
|
protected runAfterHook(req: IRequestContext, op: "create" | "update" | "delete", data: AnyRecord, meta?: Record<string, unknown>): Promise<void>;
|
|
836
|
+
/**
|
|
837
|
+
* Per-instance single-flight for cache fills — concurrent requests for
|
|
838
|
+
* the SAME cache key coalesce onto one repository query instead of each
|
|
839
|
+
* issuing its own (a popular entry expiring under 1,000 concurrent
|
|
840
|
+
* readers must produce 1 DB query, not 1,000). Keys already encode the
|
|
841
|
+
* resolved query + user/org scope + resource version, so coalescing can
|
|
842
|
+
* never cross tenants, scopes, or invalidation generations. Per-process
|
|
843
|
+
* by design; distributed refresh leases are a store-level concern
|
|
844
|
+
* (planned with the repo-core CacheEngine façade, which ships
|
|
845
|
+
* single-flight natively).
|
|
846
|
+
*/
|
|
847
|
+
private readonly inFlightCacheFills;
|
|
848
|
+
private cacheSingleFlight;
|
|
849
|
+
/**
|
|
850
|
+
* Register a background SWR refresh for `key` unless one is already in
|
|
851
|
+
* flight. Registration is SYNCHRONOUS (before the deferred tick) so a
|
|
852
|
+
* burst of stale readers arriving in the same tick schedules exactly one
|
|
853
|
+
* revalidation.
|
|
854
|
+
*/
|
|
855
|
+
private scheduleCacheRefresh;
|
|
836
856
|
/** Cached `list()` flow with SWR semantics. Returns null when cache is disabled. */
|
|
837
857
|
protected withListCache(req: IRequestContext, options: ParsedQuery): Promise<IControllerResponse<ListResult<TDoc>> | null>;
|
|
838
858
|
/** Cached `get()` flow with SWR semantics. Returns null when cache is disabled. */
|
|
@@ -1044,90 +1064,6 @@ declare class BaseController<TDoc extends AnyRecord = AnyRecord, _TRepository ex
|
|
|
1044
1064
|
readonly _phantom?: [TDoc, _TRepository];
|
|
1045
1065
|
}
|
|
1046
1066
|
//#endregion
|
|
1047
|
-
//#region src/types/base.d.ts
|
|
1048
|
-
declare module "fastify" {
|
|
1049
|
-
interface FastifyRequest {
|
|
1050
|
-
/** Request scope — set by auth adapter, read by permissions/presets/guards */
|
|
1051
|
-
scope: RequestScope;
|
|
1052
|
-
/**
|
|
1053
|
-
* Current user — set by auth adapter (Better Auth, JWT, custom).
|
|
1054
|
-
* `undefined` on public routes (`auth: false`) or unauthenticated requests.
|
|
1055
|
-
* Guard with `if (request.user)` on routes that allow anonymous access.
|
|
1056
|
-
*
|
|
1057
|
-
* Kept as required (not `user?`) because `@fastify/jwt` declares it
|
|
1058
|
-
* as required — declaration merges must have identical modifiers.
|
|
1059
|
-
* The `| undefined` in the type achieves the same DX.
|
|
1060
|
-
*/
|
|
1061
|
-
user: Record<string, unknown> | undefined;
|
|
1062
|
-
/** Policy-injected query filters (e.g. ownership, org-scoping) */
|
|
1063
|
-
_policyFilters?: Record<string, unknown>;
|
|
1064
|
-
/** Field mask — fields to include/exclude in responses */
|
|
1065
|
-
fieldMask?: {
|
|
1066
|
-
include?: string[];
|
|
1067
|
-
exclude?: string[];
|
|
1068
|
-
};
|
|
1069
|
-
/** Arbitrary policy metadata for downstream consumers */
|
|
1070
|
-
policyMetadata?: Record<string, unknown>;
|
|
1071
|
-
/** Document loaded by policy middleware for ownership checks */
|
|
1072
|
-
document?: unknown;
|
|
1073
|
-
/** Ownership check context (field name + user field) */
|
|
1074
|
-
_ownershipCheck?: Record<string, unknown>;
|
|
1075
|
-
}
|
|
1076
|
-
}
|
|
1077
|
-
type AnyRecord = Record<string, unknown>;
|
|
1078
|
-
/** MongoDB ObjectId — accepts string or any object with a `toString()` (e.g. mongoose ObjectId). */
|
|
1079
|
-
type ObjectId = string | {
|
|
1080
|
-
toString(): string;
|
|
1081
|
-
};
|
|
1082
|
-
/**
|
|
1083
|
-
* Flexible user type that accepts any object with id/_id properties.
|
|
1084
|
-
* The actual user structure is defined by your app's auth system.
|
|
1085
|
-
*/
|
|
1086
|
-
type UserLike = UserBase & {
|
|
1087
|
-
/** User email (optional) */
|
|
1088
|
-
email?: string;
|
|
1089
|
-
};
|
|
1090
|
-
interface UserOrganization {
|
|
1091
|
-
userId: string;
|
|
1092
|
-
organizationId: string;
|
|
1093
|
-
[key: string]: unknown;
|
|
1094
|
-
}
|
|
1095
|
-
interface JWTPayload {
|
|
1096
|
-
sub: string;
|
|
1097
|
-
[key: string]: unknown;
|
|
1098
|
-
}
|
|
1099
|
-
/**
|
|
1100
|
-
* Standard API response envelope — `{ success, data?, error?, message?, meta? }`.
|
|
1101
|
-
* Used by Arc's default response shape.
|
|
1102
|
-
*/
|
|
1103
|
-
interface ApiResponse<T = unknown> {
|
|
1104
|
-
success: boolean;
|
|
1105
|
-
data?: T;
|
|
1106
|
-
error?: string;
|
|
1107
|
-
message?: string;
|
|
1108
|
-
meta?: Record<string, unknown>;
|
|
1109
|
-
}
|
|
1110
|
-
/**
|
|
1111
|
-
* Typed Fastify request with Arc decorations. Use in `raw: true` handlers
|
|
1112
|
-
* instead of `(req as any).user`.
|
|
1113
|
-
*
|
|
1114
|
-
* @example
|
|
1115
|
-
* ```typescript
|
|
1116
|
-
* import type { ArcRequest } from '@classytic/arc';
|
|
1117
|
-
*
|
|
1118
|
-
* handler: async (req: ArcRequest, reply) => {
|
|
1119
|
-
* req.user?.id; // typed
|
|
1120
|
-
* req.scope.organizationId; // typed (when member)
|
|
1121
|
-
* req.signal; // AbortSignal (Fastify 5)
|
|
1122
|
-
* }
|
|
1123
|
-
* ```
|
|
1124
|
-
*/
|
|
1125
|
-
type ArcRequest = FastifyRequest & {
|
|
1126
|
-
scope: RequestScope;
|
|
1127
|
-
user: Record<string, unknown> | undefined;
|
|
1128
|
-
signal: AbortSignal;
|
|
1129
|
-
};
|
|
1130
|
-
//#endregion
|
|
1131
1067
|
//#region src/types/auth.d.ts
|
|
1132
1068
|
/**
|
|
1133
1069
|
* JWT utilities provided to authenticator. Arc provides the helpers;
|
|
@@ -1423,8 +1359,16 @@ interface IRequestContext<TBody = unknown, TParams extends Record<string, string
|
|
|
1423
1359
|
body: TBody;
|
|
1424
1360
|
/** Authenticated user or null */
|
|
1425
1361
|
user: TUser | null;
|
|
1426
|
-
/**
|
|
1427
|
-
|
|
1362
|
+
/**
|
|
1363
|
+
* Request headers — `ArcHeaders` (`string | string[] | undefined` per
|
|
1364
|
+
* name), the HONEST type: on the HTTP path this is Fastify's headers
|
|
1365
|
+
* object passed through, and repeated headers arrive as `string[]` at
|
|
1366
|
+
* runtime (2.24 widening — the previous `Record<string, string |
|
|
1367
|
+
* undefined>` lied about that). Read via `getHeader(ctx.headers, name)`
|
|
1368
|
+
* from `@classytic/arc/utils` for array-safe, duplicate-deterministic
|
|
1369
|
+
* access, or `requireSingleHeaderValue` for security-sensitive headers.
|
|
1370
|
+
*/
|
|
1371
|
+
headers: ArcHeaders;
|
|
1428
1372
|
/** Organization ID (for multi-tenant apps) */
|
|
1429
1373
|
organizationId?: string;
|
|
1430
1374
|
/** Team ID (for team-scoped resources) */
|
|
@@ -1652,7 +1596,7 @@ interface RouteDefinition {
|
|
|
1652
1596
|
* compiler to catch typos. `handler` stays optional when `controllerMethod`
|
|
1653
1597
|
* is set — exactly one of the two must be declared.
|
|
1654
1598
|
*/
|
|
1655
|
-
readonly handler?: string | ControllerHandler | RouteHandlerMethod | ((request:
|
|
1599
|
+
readonly handler?: string | ControllerHandler | RouteHandlerMethod | ((request: never, reply: never) => unknown);
|
|
1656
1600
|
/**
|
|
1657
1601
|
* Typed function-reference handler (2.16). Receives the live controller
|
|
1658
1602
|
* instance and returns the method to invoke — TypeScript catches typos
|
|
@@ -4055,6 +3999,14 @@ interface RegistryEntry extends ResourceMetadata {
|
|
|
4055
3999
|
roles?: readonly string[];
|
|
4056
4000
|
redactValue?: unknown;
|
|
4057
4001
|
}>;
|
|
4002
|
+
/**
|
|
4003
|
+
* The LIVE field-permission map (2.22) — the same object `defineResource`
|
|
4004
|
+
* consumes, surfaced so request-time consumers (the realtime change feed)
|
|
4005
|
+
* can apply `applyFieldReadPermissions` masking to event payloads without
|
|
4006
|
+
* re-reading the resource definition. `fieldPermissions` above stays the
|
|
4007
|
+
* introspection-safe metadata twin.
|
|
4008
|
+
*/
|
|
4009
|
+
fields?: FieldPermissionMap;
|
|
4058
4010
|
/** Pipeline step names (for OpenAPI data) */
|
|
4059
4011
|
pipelineSteps?: Array<{
|
|
4060
4012
|
type: string;
|
|
@@ -4237,4 +4189,4 @@ interface ValidateOptions {
|
|
|
4237
4189
|
strict?: boolean;
|
|
4238
4190
|
}
|
|
4239
4191
|
//#endregion
|
|
4240
|
-
export { OpenApiSchemas as $,
|
|
4192
|
+
export { OpenApiSchemas as $, SlugExt as $t, RequestIdOptions as A, ControllerConfigurableOptions as An, RouteDefinition as At, defineResource as B, RouteHandler as Bt, RequestContext as C, defineHook as Cn, PipelineStep as Ct, HealthCheck as D, ArcListResult as Dn, ActionEntry as Dt, GracefulShutdownOptions as E, ArcGetResult as En, ActionDefinition as Et, FastifyWithDecorators as F, ControllerLike as Ft, OnTenantDeleteConfig as G, AuthenticatorContext as Gt, CrudController as H, AuthHelpers as Ht, MiddlewareHandler as I, FastifyHandler as It, PresetHook as J, BaseController as Jt, ResolvedTenantPurge as K, JwtContext as Kt, RequestWithExtras as L, IController as Lt, EventsDecorator as M, ListResult as Mn, RouteMethod as Mt, FastifyRequestExtras as N, BodySanitizer as Nn, RateLimitConfig as Nt, HealthOptions as O, ArcUpdateResult as On, ActionHandlerFn as Ot, FastifyWithAuth as P, BodySanitizerConfig as Pn, ControllerHandler as Pt, MiddlewareConfig as Q, TreeMixin as Qt, RegisterOptions as R, IControllerResponse as Rt, QueryParserInterface as S, createHookSystem as Sn, PipelineContext as St, CrudRouterOptions as T, ArcDeleteResult as Tn, ResourceCacheConfig as Tt, ResourceConfig as U, AuthPluginOptions as Ut, ResourceDefinition as V, ServerAccessor as Vt, ResourcePermissions as W, Authenticator as Wt, CrudRouteKey as X, SoftDeleteMixin as Xt, PresetResult as Y, SoftDeleteExt as Yt, CrudSchemas as Z, TreeExt as Zt, ControllerQueryOptions as _, afterDelete as _n, Guard as _t, InferAdapterDoc as a, QueryResolverConfig as an, ResourceExtensions as at, ParsedQuery as b, beforeDelete as bn, OperationFilter as bt, TypedController as c, DefineHookOptions as cn, AggMeasureShorthand as ct, PaginationResult as d, HookOperation as dn, AggregationDateRangeRequirement as dt, SlugMixin as en, RouteSchemaOptions as et, IntrospectionData as f, HookPhase as fn, AggregationIndexHint as ft, ArcInternalMetadata as g, afterCreate as gn, AggregationsMap as gt, ResourceMetadata as h, HookSystemOptions as hn, AggregationRateLimit as ht, ValidationResult as i, QueryResolver as in, ResourceHooks as it, ArcDecorator as j, ControllerConstructionOptions as jn, RouteMcpConfig as jt, IntrospectionPluginOptions as k, BaseControllerOptions as kn, ActionsMap as kt, TypedRepository as l, HookContext as ln, AggregationCacheConfig as lt, RegistryStats as m, HookSystem as mn, AggregationMaterializedResult as mt, ConfigError as n, BulkMixin as nn, FieldRule$1 as nt, InferDocType as o, AccessControl as on, EventDefinition as ot, RegistryEntry as p, HookRegistration as pn, AggregationMaterializedContext as pt, PresetFunction as q, TokenPair as qt, ValidateOptions as r, BaseCrudController as rn, ResourceHookContext as rt, InferResourceDoc as s, AccessControlConfig as sn, AggMeasureInput as st, RouteHandlerMethod$1 as t, BulkExt as tn, ArcFieldRule as tt, TypedResourceConfig as u, HookHandler as un, AggregationConfig as ut, LookupOption as v, afterUpdate as vn, Interceptor as vt, ServiceContext as w, ArcCreateResult as wn, Transform as wt, PopulateOption as x, beforeUpdate as xn, PipelineConfig as xt, OwnershipCheck as y, beforeCreate as yn, NextFunction as yt, ResourceRegistry as z, IRequestContext as zt };
|
|
@@ -1,5 +1,106 @@
|
|
|
1
|
+
import { r as EventHandler } from "./EventTransport-QmY7A258.mjs";
|
|
1
2
|
import { n as ErrorMapper } from "./errorHandler-C6yv4ZTW.mjs";
|
|
2
|
-
import { FastifyInstance } from "fastify";
|
|
3
|
+
import { FastifyInstance, FastifyPluginAsync } from "fastify";
|
|
4
|
+
import { LockAdapter } from "@classytic/repo-core/lock";
|
|
5
|
+
//#region src/plugins/health.d.ts
|
|
6
|
+
interface HealthCheck {
|
|
7
|
+
/** Name of the dependency */
|
|
8
|
+
name: string;
|
|
9
|
+
/**
|
|
10
|
+
* Function that returns true if healthy, false otherwise.
|
|
11
|
+
*
|
|
12
|
+
* Receives an `AbortSignal` aborted when the check's timeout elapses —
|
|
13
|
+
* pass it to fetch/driver calls so a stalled dependency probe actually
|
|
14
|
+
* STOPS instead of accumulating an abandoned operation per readiness
|
|
15
|
+
* poll. Ignoring the parameter is fine (back-compat): the timeout still
|
|
16
|
+
* bounds how long the PROBE waits, just not the underlying work.
|
|
17
|
+
*/
|
|
18
|
+
check: (signal?: AbortSignal) => Promise<boolean> | boolean;
|
|
19
|
+
/** Optional timeout in ms (default: 5000) */
|
|
20
|
+
timeout?: number;
|
|
21
|
+
/** Whether this check is critical for readiness (default: true) */
|
|
22
|
+
critical?: boolean;
|
|
23
|
+
}
|
|
24
|
+
interface HealthOptions {
|
|
25
|
+
/** Route prefix (default: '/_health') */
|
|
26
|
+
prefix?: string;
|
|
27
|
+
/** Health check dependencies */
|
|
28
|
+
checks?: readonly HealthCheck[];
|
|
29
|
+
/** Enable metrics endpoint (default: false) */
|
|
30
|
+
metrics?: boolean;
|
|
31
|
+
/** Custom metrics collector function */
|
|
32
|
+
metricsCollector?: () => Promise<string> | string;
|
|
33
|
+
/** Version info to include in responses */
|
|
34
|
+
version?: string;
|
|
35
|
+
/** Collect HTTP request metrics (default: true if metrics enabled) */
|
|
36
|
+
collectHttpMetrics?: boolean;
|
|
37
|
+
}
|
|
38
|
+
declare const healthPlugin: FastifyPluginAsync<HealthOptions>;
|
|
39
|
+
declare const _default$1: FastifyPluginAsync<HealthOptions>;
|
|
40
|
+
//#endregion
|
|
41
|
+
//#region src/plugins/schedules.d.ts
|
|
42
|
+
interface ScheduleDefinition {
|
|
43
|
+
/** Unique name — also the lock key (`arc:schedule:<name>`). */
|
|
44
|
+
name: string;
|
|
45
|
+
/** Interval in milliseconds between the END of one run and the next tick. */
|
|
46
|
+
every: number;
|
|
47
|
+
/** The work. Receives the Fastify instance; errors are logged, never fatal. */
|
|
48
|
+
handler: (fastify: FastifyInstance) => void | Promise<void>;
|
|
49
|
+
/** Fire once immediately when the app becomes ready (default: false). */
|
|
50
|
+
runOnStart?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Random extra delay in `[0, jitterMs)` added to the FIRST tick only.
|
|
53
|
+
* Spreads boot-aligned jobs so multiple same-cadence schedules don't all
|
|
54
|
+
* fire at exactly `boot + every` after every restart (and, with a lock,
|
|
55
|
+
* de-synchronizes replicas competing for the same lease). Ignored when
|
|
56
|
+
* `runOnStart` is true.
|
|
57
|
+
*/
|
|
58
|
+
jitterMs?: number;
|
|
59
|
+
/**
|
|
60
|
+
* Lease duration when a `lock` is configured. Default: `every * 0.9`
|
|
61
|
+
* (capped at 5 minutes) — long enough that other replicas skip the same
|
|
62
|
+
* tick, short enough that a crashed leader fails over within one cycle.
|
|
63
|
+
*/
|
|
64
|
+
leaseMs?: number;
|
|
65
|
+
/** Per-schedule kill switch (default: true). */
|
|
66
|
+
enabled?: boolean;
|
|
67
|
+
}
|
|
68
|
+
interface SchedulesPluginOptions {
|
|
69
|
+
schedules: readonly ScheduleDefinition[];
|
|
70
|
+
/**
|
|
71
|
+
* Ecosystem lock adapter (`LockAdapter` from `@classytic/repo-core/lock`)
|
|
72
|
+
* for multi-replica deployments. Omit for single-instance apps — every
|
|
73
|
+
* tick runs locally.
|
|
74
|
+
*/
|
|
75
|
+
lock?: LockAdapter;
|
|
76
|
+
/**
|
|
77
|
+
* Identity of this replica for lease ownership. Default: a random id per
|
|
78
|
+
* process (repo-core's `getInstanceId()` is a good explicit value).
|
|
79
|
+
*/
|
|
80
|
+
holderId?: string;
|
|
81
|
+
/**
|
|
82
|
+
* Master switch — `false` registers a typed no-op (config-gated
|
|
83
|
+
* environments), same pattern as `idempotencyPlugin`.
|
|
84
|
+
*/
|
|
85
|
+
enabled?: boolean;
|
|
86
|
+
}
|
|
87
|
+
/** Per-schedule runtime counters, readable via `fastify.getScheduleStats()`. */
|
|
88
|
+
interface ScheduleStats {
|
|
89
|
+
name: string;
|
|
90
|
+
runs: number;
|
|
91
|
+
failures: number;
|
|
92
|
+
skippedByLock: number;
|
|
93
|
+
lastRunAt: string | null;
|
|
94
|
+
lastError: string | null;
|
|
95
|
+
}
|
|
96
|
+
declare module "fastify" {
|
|
97
|
+
interface FastifyInstance {
|
|
98
|
+
getScheduleStats?: () => ScheduleStats[];
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
declare const schedulesPlugin: FastifyPluginAsync<SchedulesPluginOptions>;
|
|
102
|
+
declare const _default: FastifyPluginAsync<SchedulesPluginOptions>;
|
|
103
|
+
//#endregion
|
|
3
104
|
//#region src/factory/loadResources.d.ts
|
|
4
105
|
/**
|
|
5
106
|
* loadResources — Auto-discover resource files from a directory.
|
|
@@ -218,7 +319,31 @@ interface LoadResourcesOptions<TContext = unknown> {
|
|
|
218
319
|
*/
|
|
219
320
|
declare function loadResources<TContext = unknown>(dir: string, options?: LoadResourcesOptions<TContext>): Promise<ResourceLike[]>;
|
|
220
321
|
//#endregion
|
|
221
|
-
//#region src/factory/module.d.ts
|
|
322
|
+
//#region src/factory/module/types.d.ts
|
|
323
|
+
/**
|
|
324
|
+
* A module's contribution of some arm (event handlers, scheduled jobs, …).
|
|
325
|
+
* Either a static array or a factory resolved AFTER all module bootstraps, so a
|
|
326
|
+
* contribution can close over booted engines / the Fastify instance instead of
|
|
327
|
+
* reaching for a global getter (the coupling the module contract removes).
|
|
328
|
+
*/
|
|
329
|
+
type ModuleContribution<T> = readonly T[] | ((fastify: FastifyInstance) => readonly T[] | Promise<readonly T[]>);
|
|
330
|
+
/**
|
|
331
|
+
* A domain-event subscription a module owns. Subscribed in dependency order
|
|
332
|
+
* during the `afterResources` phase (routes mounted, engines booted) and
|
|
333
|
+
* auto-unsubscribed at shutdown BEFORE module `onClose` (deps still alive).
|
|
334
|
+
*/
|
|
335
|
+
interface EventHandlerDefinition {
|
|
336
|
+
/** Event pattern(s) to subscribe — same matcher as `fastify.events.subscribe`. */
|
|
337
|
+
event: string | readonly string[];
|
|
338
|
+
/** The subscriber. */
|
|
339
|
+
handler: EventHandler;
|
|
340
|
+
/**
|
|
341
|
+
* Optional stable name — enables duplicate detection + teardown diagnostics.
|
|
342
|
+
* Third-party modules should prefix it with their module name, for example
|
|
343
|
+
* `inventory.order-created`; Arc does not silently rewrite public names.
|
|
344
|
+
*/
|
|
345
|
+
name?: string;
|
|
346
|
+
}
|
|
222
347
|
interface ArcModule<TExports = unknown> {
|
|
223
348
|
/** Stable identifier — appears in boot logs and duplicate-module detection. */
|
|
224
349
|
readonly name: string;
|
|
@@ -344,6 +469,74 @@ interface ArcModule<TExports = unknown> {
|
|
|
344
469
|
* module owns.
|
|
345
470
|
*/
|
|
346
471
|
afterResources?: (fastify: FastifyInstance) => void | Promise<void>;
|
|
472
|
+
/**
|
|
473
|
+
* Readiness checks this module contributes to the app's
|
|
474
|
+
* `healthPlugin` (`/_health/ready`). Collected across ALL modules in
|
|
475
|
+
* dependency order and merged BEFORE the host's app-level `arcPlugins.health`
|
|
476
|
+
* checks (modules-first, host-last) — the same additive convention arc uses
|
|
477
|
+
* for resources and error mappers. Check `name`s must be unique across the
|
|
478
|
+
* module graph (arc fails at boot on a collision, attributing both owners).
|
|
479
|
+
*
|
|
480
|
+
* STATIC by design (not a factory): declare the check up front and let its
|
|
481
|
+
* `check()` closure resolve dependencies LAZILY at probe time, so collection
|
|
482
|
+
* can happen before the health plugin registers and the worker probe
|
|
483
|
+
* (`createWorker`) receives the identical union without a second registration.
|
|
484
|
+
*
|
|
485
|
+
* ```ts
|
|
486
|
+
* defineModule({ name: "inventory", healthChecks: [
|
|
487
|
+
* { name: "flow-engine", check: () => flow.isReady() },
|
|
488
|
+
* ] })
|
|
489
|
+
* ```
|
|
490
|
+
*/
|
|
491
|
+
readonly healthChecks?: readonly HealthCheck[];
|
|
492
|
+
/**
|
|
493
|
+
* Domain-event subscriptions this module owns — the declarative replacement
|
|
494
|
+
* for imperative `fastify.events.subscribe(...)` calls inside
|
|
495
|
+
* `afterResources`. Subscribed in dependency order during the
|
|
496
|
+
* `afterResources` phase (routes mounted, engines booted), and arc RETAINS
|
|
497
|
+
* every unsubscribe and invokes it at shutdown BEFORE module `onClose` (while
|
|
498
|
+
* module deps are still alive). Named handlers must be unique across the
|
|
499
|
+
* module graph; a module that declares handlers while the event subsystem is
|
|
500
|
+
* disabled (`arcPlugins.events: false`) fails at boot. Array or factory (the
|
|
501
|
+
* factory runs after bootstraps, so it can close over booted engines).
|
|
502
|
+
*
|
|
503
|
+
* ```ts
|
|
504
|
+
* defineModule({ name: "party", eventHandlers: [
|
|
505
|
+
* { name: "party.link-customer", event: ["customer:created"], handler: onCustomer },
|
|
506
|
+
* ] })
|
|
507
|
+
* ```
|
|
508
|
+
*/
|
|
509
|
+
readonly eventHandlers?: ModuleContribution<EventHandlerDefinition>;
|
|
510
|
+
/**
|
|
511
|
+
* Durable workflows this module owns. OPAQUE to arc core — arc never imports
|
|
512
|
+
* `@classytic/streamline`; the value flows through untouched and the
|
|
513
|
+
* streamline integration (`@classytic/arc/integrations/streamline`, a peer)
|
|
514
|
+
* gives it meaning (name/shape validation, registration). Collected via
|
|
515
|
+
* `collectModuleWorkflows` at integration-init time (after module bootstraps),
|
|
516
|
+
* so a factory can close over the shared workflow container the integration
|
|
517
|
+
* decorates on the instance.
|
|
518
|
+
*
|
|
519
|
+
* ```ts
|
|
520
|
+
* defineModule({ name: "invoice",
|
|
521
|
+
* workflows: (f) => createInvoiceWorkflows(f.streamlineContainer) })
|
|
522
|
+
* ```
|
|
523
|
+
*/
|
|
524
|
+
readonly workflows?: ModuleContribution<unknown>;
|
|
525
|
+
/**
|
|
526
|
+
* Recurring interval schedules this module owns. Arc composes them into its
|
|
527
|
+
* existing `schedulesPlugin` after bootstraps, in dependency order. Names
|
|
528
|
+
* must be unique across the module graph. Configure multi-replica locking via
|
|
529
|
+
* `arcPlugins.schedules`; explicitly disabling that runner while a module
|
|
530
|
+
* declares schedules fails boot instead of silently dropping work. Array or
|
|
531
|
+
* factory (the factory runs once after bootstraps and may close over engines).
|
|
532
|
+
*
|
|
533
|
+
* ```ts
|
|
534
|
+
* defineModule({ name: "loyalty", scheduledJobs: [
|
|
535
|
+
* { name: "loyalty.point.expiration", every: 3_600_000, handler: () => sweep() },
|
|
536
|
+
* ] })
|
|
537
|
+
* ```
|
|
538
|
+
*/
|
|
539
|
+
readonly scheduledJobs?: ModuleContribution<ScheduleDefinition>;
|
|
347
540
|
/**
|
|
348
541
|
* Teardown — registered as a Fastify `onClose` hook. Destroy engines, stop
|
|
349
542
|
* timers, flush the module's outbox. Modules close in REVERSE list order
|
|
@@ -376,11 +569,64 @@ interface ArcModule<TExports = unknown> {
|
|
|
376
569
|
*/
|
|
377
570
|
type ArcModuleInput<TExports = unknown> = ArcModule<TExports> | Promise<ArcModule<TExports>> | (() => ArcModule<TExports> | Promise<ArcModule<TExports>>);
|
|
378
571
|
/**
|
|
379
|
-
*
|
|
380
|
-
* (
|
|
381
|
-
*
|
|
572
|
+
* Typed module registry — hosts augment this via declaration merging so
|
|
573
|
+
* `getModuleExports(f, "order")` infers the export type without a manual type
|
|
574
|
+
* argument (the fastify / awilix pattern):
|
|
575
|
+
*
|
|
576
|
+
* ```ts
|
|
577
|
+
* declare module "@classytic/arc/factory" {
|
|
578
|
+
* interface ArcModuleRegistry {
|
|
579
|
+
* order: OrderEngine;
|
|
580
|
+
* accounting: AccountingEngine;
|
|
581
|
+
* }
|
|
582
|
+
* }
|
|
583
|
+
* ```
|
|
584
|
+
*
|
|
585
|
+
* Left empty here so the fallback `getModuleExports<T>(f, name: string)` stays
|
|
586
|
+
* available for apps that don't augment it.
|
|
382
587
|
*/
|
|
383
|
-
|
|
588
|
+
interface ArcModuleRegistry {}
|
|
589
|
+
//#endregion
|
|
590
|
+
//#region src/factory/module/contributions.d.ts
|
|
591
|
+
/**
|
|
592
|
+
* Collect every module's `healthChecks` in the caller's order. Fails at boot
|
|
593
|
+
* on a duplicate check `name` across modules, naming BOTH owning modules.
|
|
594
|
+
* The host's app-level checks are appended AFTER this (modules-first,
|
|
595
|
+
* host-last) by the caller.
|
|
596
|
+
*/
|
|
597
|
+
declare function collectModuleHealthChecks(modules: readonly ArcModule[]): HealthCheck[];
|
|
598
|
+
/**
|
|
599
|
+
* Collect every module's `workflows`. Resolves factory contributions (so a
|
|
600
|
+
* factory can close over a container the caller has already decorated on
|
|
601
|
+
* `fastify`) and flattens to a single opaque array. Arc core deliberately
|
|
602
|
+
* does NOT validate or interpret the values — the streamline integration
|
|
603
|
+
* owns name/shape checks and registration. Called by the integration at init
|
|
604
|
+
* time, not by arc's boot pipeline (workflows depend on the integration's
|
|
605
|
+
* container).
|
|
606
|
+
*/
|
|
607
|
+
declare function collectModuleWorkflows(fastify: FastifyInstance, modules: readonly ArcModule[]): Promise<unknown[]>;
|
|
608
|
+
/**
|
|
609
|
+
* Collect every module's `scheduledJobs`. Resolves factory contributions
|
|
610
|
+
* (after bootstraps) and fails at boot on a duplicate job `name` across
|
|
611
|
+
* modules. The caller passes the returned definitions to the canonical
|
|
612
|
+
* schedules plugin; factories must therefore be resolved only once.
|
|
613
|
+
*/
|
|
614
|
+
declare function collectModuleScheduledJobs(fastify: FastifyInstance, modules: readonly ArcModule[]): Promise<ScheduleDefinition[]>;
|
|
615
|
+
//#endregion
|
|
616
|
+
//#region src/factory/module/lifecycle.d.ts
|
|
617
|
+
/**
|
|
618
|
+
* Subscribe every module's `eventHandlers` in dependency order (pass the
|
|
619
|
+
* `orderModules`-sorted list). Returns the ordered list of unsubscribe
|
|
620
|
+
* functions so the caller can tear them down at shutdown BEFORE module
|
|
621
|
+
* `onClose` (while module deps are still alive). Fails at boot on:
|
|
622
|
+
* - a duplicate NAMED handler across modules (attributing both owners);
|
|
623
|
+
* - a module declaring handlers while the event subsystem is unavailable.
|
|
624
|
+
* Resolves factory contributions (after bootstraps) so a handler can close over
|
|
625
|
+
* booted engines rather than a global getter.
|
|
626
|
+
*/
|
|
627
|
+
declare function subscribeModuleEventHandlers(fastify: FastifyInstance, modules: readonly ArcModule[]): Promise<Array<() => void | Promise<void>>>;
|
|
628
|
+
//#endregion
|
|
629
|
+
//#region src/factory/module/order.d.ts
|
|
384
630
|
/**
|
|
385
631
|
* Order modules for composition by their `dependsOn` edges — a STABLE
|
|
386
632
|
* topological sort. Called once at the start of the bootstrap phase; every
|
|
@@ -400,24 +646,18 @@ declare function resolveModule(input: ArcModuleInput): Promise<ArcModule>;
|
|
|
400
646
|
* - a dependency cycle (reports the concrete `a → b → … → a` path)
|
|
401
647
|
*/
|
|
402
648
|
declare function orderModules(modules: readonly ArcModule[]): ArcModule[];
|
|
649
|
+
//#endregion
|
|
650
|
+
//#region src/factory/module/resolve.d.ts
|
|
403
651
|
/**
|
|
404
|
-
*
|
|
405
|
-
* `
|
|
406
|
-
*
|
|
407
|
-
*
|
|
408
|
-
* ```ts
|
|
409
|
-
* declare module "@classytic/arc/factory" {
|
|
410
|
-
* interface ArcModuleRegistry {
|
|
411
|
-
* order: OrderEngine;
|
|
412
|
-
* accounting: AccountingEngine;
|
|
413
|
-
* }
|
|
414
|
-
* }
|
|
415
|
-
* ```
|
|
416
|
-
*
|
|
417
|
-
* Left empty here so the fallback `getModuleExports<T>(f, name: string)` stays
|
|
418
|
-
* available for apps that don't augment it.
|
|
652
|
+
* Resolve any module-input form to a concrete `ArcModule`. A thunk is invoked
|
|
653
|
+
* (this is where a dynamic `import()` fires); a promise (or plain module) is
|
|
654
|
+
* awaited. Called once per module at the start of the bootstrap phase.
|
|
419
655
|
*/
|
|
420
|
-
|
|
656
|
+
declare function resolveModule(input: ArcModuleInput): Promise<ArcModule>;
|
|
657
|
+
/** Resolve a `ModuleContribution` to a concrete array (array passthrough or factory call). */
|
|
658
|
+
declare function resolveContribution<T>(contribution: ModuleContribution<T> | undefined, fastify: FastifyInstance): Promise<readonly T[]>;
|
|
659
|
+
//#endregion
|
|
660
|
+
//#region src/factory/module/index.d.ts
|
|
421
661
|
/**
|
|
422
662
|
* Identity helper for authoring a typed module — mirrors `defineResource`.
|
|
423
663
|
* Gives inference + a single obvious construction site; does no work.
|
|
@@ -451,4 +691,4 @@ declare function defineModule<TExports = unknown>(module: ArcModule<TExports>):
|
|
|
451
691
|
declare function getModuleExports<K extends keyof ArcModuleRegistry>(fastify: FastifyInstance, name: K): ArcModuleRegistry[K];
|
|
452
692
|
declare function getModuleExports<TExports = unknown>(fastify: FastifyInstance, name: string): TExports;
|
|
453
693
|
//#endregion
|
|
454
|
-
export {
|
|
694
|
+
export { schedulesPlugin as C, healthPlugin as D, _default$1 as E, _default as S, HealthOptions as T, ResourceModule as _, orderModules as a, ScheduleStats as b, collectModuleScheduledJobs as c, ArcModuleInput as d, ArcModuleRegistry as f, ResourceLike as g, LoadResourcesOptions as h, resolveModule as i, collectModuleWorkflows as l, ModuleContribution as m, getModuleExports as n, subscribeModuleEventHandlers as o, EventHandlerDefinition as p, resolveContribution as r, collectModuleHealthChecks as s, defineModule as t, ArcModule as u, loadResources as v, HealthCheck as w, SchedulesPluginOptions as x, ScheduleDefinition as y };
|