@classytic/arc 2.10.3 → 2.11.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/README.md +1 -1
- package/dist/{BaseController-CbKKIflT.mjs → BaseController-JNV08qOT.mjs} +595 -537
- package/dist/{queryCachePlugin-BKbWjgDG.d.mts → QueryCache-DOBNHBE0.d.mts} +2 -32
- package/dist/actionPermissions-C8YYU92K.mjs +22 -0
- package/dist/adapters/index.d.mts +2 -2
- package/dist/adapters/index.mjs +1 -1
- package/dist/{adapters-BXY4i-hw.mjs → adapters-D0tT2Tyo.mjs} +54 -0
- package/dist/audit/index.d.mts +2 -2
- package/dist/audit/index.mjs +15 -17
- package/dist/auth/index.d.mts +4 -4
- package/dist/auth/index.mjs +3 -3
- package/dist/auth/redis-session.d.mts +1 -1
- package/dist/{betterAuthOpenApi-BBRVhjQN.mjs → betterAuthOpenApi-DwxtK3uG.mjs} +1 -1
- package/dist/cache/index.d.mts +3 -2
- package/dist/cache/index.mjs +3 -3
- package/dist/cli/commands/docs.mjs +2 -2
- package/dist/cli/commands/generate.mjs +37 -27
- package/dist/cli/commands/init.mjs +47 -34
- package/dist/cli/commands/introspect.mjs +1 -1
- package/dist/context/index.d.mts +58 -0
- package/dist/context/index.mjs +2 -0
- package/dist/core/index.d.mts +3 -3
- package/dist/core/index.mjs +4 -3
- package/dist/core-DXdSSFW-.mjs +1037 -0
- package/dist/createActionRouter-BwaSM0No.mjs +166 -0
- package/dist/{createApp-BuvPma24.mjs → createApp-DvNYEhpb.mjs} +118 -36
- package/dist/docs/index.d.mts +2 -2
- package/dist/docs/index.mjs +1 -1
- package/dist/{elevation-C7hgL_aI.mjs → elevation-DOFoxoDs.mjs} +1 -1
- package/dist/errorHandler-Co3lnVmJ.d.mts +114 -0
- package/dist/{eventPlugin-DCUjuiQT.mjs → eventPlugin--5HIkdPU.mjs} +1 -1
- package/dist/{eventPlugin-CxWgpd6K.d.mts → eventPlugin-CUNjYYRY.d.mts} +1 -1
- package/dist/events/index.d.mts +4 -4
- package/dist/events/index.mjs +69 -51
- package/dist/events/transports/redis-stream-entry.d.mts +1 -1
- package/dist/events/transports/redis.d.mts +1 -1
- package/dist/factory/index.d.mts +1 -1
- package/dist/factory/index.mjs +2 -2
- package/dist/{fields-Lo1VUDpt.d.mts → fields-C8Y0XLAu.d.mts} +1 -1
- package/dist/hooks/index.d.mts +1 -1
- package/dist/hooks/index.mjs +1 -1
- package/dist/idempotency/index.d.mts +3 -3
- package/dist/idempotency/index.mjs +38 -27
- package/dist/idempotency/redis.d.mts +1 -1
- package/dist/{index-ChIw3776.d.mts → index-BYCqHCVu.d.mts} +4 -4
- package/dist/{index-Cl0uoKd5.d.mts → index-Cm0vUrr_.d.mts} +2100 -1688
- package/dist/{index-DStwgFUK.d.mts → index-DAushRTt.d.mts} +29 -10
- package/dist/index-DsJ1MNfC.d.mts +1179 -0
- package/dist/{index-8qw4y6ff.d.mts → index-t8pLpPFW.d.mts} +13 -10
- package/dist/index.d.mts +7 -251
- package/dist/index.mjs +8 -128
- package/dist/integrations/event-gateway.d.mts +2 -2
- package/dist/integrations/event-gateway.mjs +1 -1
- package/dist/integrations/index.d.mts +2 -2
- package/dist/integrations/mcp/index.d.mts +2 -2
- package/dist/integrations/mcp/index.mjs +1 -1
- package/dist/integrations/mcp/testing.d.mts +1 -1
- package/dist/integrations/mcp/testing.mjs +1 -1
- package/dist/integrations/streamline.d.mts +46 -5
- package/dist/integrations/streamline.mjs +50 -21
- package/dist/integrations/websocket-redis.d.mts +1 -1
- package/dist/integrations/websocket.d.mts +2 -154
- package/dist/integrations/websocket.mjs +292 -224
- package/dist/{keys-qcD-TVJl.mjs → keys-CARyUjiR.mjs} +2 -0
- package/dist/{loadResources-BAzJItAJ.mjs → loadResources-YNwKHvRA.mjs} +3 -1
- package/dist/logger/index.d.mts +81 -0
- package/dist/{logger-DLg8-Ueg.mjs → logger/index.mjs} +1 -6
- package/dist/middleware/index.d.mts +109 -0
- package/dist/middleware/index.mjs +70 -0
- package/dist/multipartBody-CvTR1Un6.mjs +123 -0
- package/dist/{openapi-B5F8AddX.mjs → openapi-C0L9ar7m.mjs} +9 -7
- package/dist/org/index.d.mts +2 -2
- package/dist/permissions/index.d.mts +2 -2
- package/dist/permissions/index.mjs +1 -3
- package/dist/{permissions-Dk6mshja.mjs → permissions-B4vU9L0Q.mjs} +220 -2
- package/dist/pipe-DVoIheVC.mjs +62 -0
- package/dist/pipeline/index.d.mts +62 -0
- package/dist/pipeline/index.mjs +53 -0
- package/dist/plugins/index.d.mts +25 -5
- package/dist/plugins/index.mjs +10 -10
- package/dist/plugins/response-cache.mjs +1 -1
- package/dist/plugins/tracing-entry.d.mts +1 -1
- package/dist/plugins/tracing-entry.mjs +42 -24
- package/dist/presets/filesUpload.d.mts +4 -4
- package/dist/presets/filesUpload.mjs +255 -1
- package/dist/presets/index.d.mts +1 -1
- package/dist/presets/index.mjs +2 -2
- package/dist/presets/multiTenant.d.mts +1 -1
- package/dist/presets/multiTenant.mjs +48 -8
- package/dist/presets/search.d.mts +2 -2
- package/dist/presets/search.mjs +1 -1
- package/dist/{presets-fLJVXdVn.mjs → presets-k604Lj99.mjs} +1 -1
- package/dist/queryCachePlugin-BUXBSm4F.d.mts +34 -0
- package/dist/{queryCachePlugin-DQCEfJis.mjs → queryCachePlugin-Bq6bO6vc.mjs} +3 -3
- package/dist/{redis-DqyeggCa.d.mts → redis-Cm1gnRDf.d.mts} +1 -1
- package/dist/{redis-stream-CakIQmwR.d.mts → redis-stream-CM8TXTix.d.mts} +1 -1
- package/dist/registry/index.d.mts +1 -1
- package/dist/registry/index.mjs +2 -2
- package/dist/{requestContext-xHIKedG6.mjs → requestContext-CfRkaxwf.mjs} +1 -1
- package/dist/{resourceToTools-BElv3xPT.mjs → resourceToTools--okX6QBr.mjs} +534 -415
- package/dist/routerShared-DeESFp4a.mjs +515 -0
- package/dist/schemaIR-BlG9bY7v.mjs +137 -0
- package/dist/scope/index.d.mts +2 -2
- package/dist/scope/index.mjs +1 -1
- package/dist/{sse-yBCgOLGu.mjs → sse-V7aXc3bW.mjs} +1 -1
- package/dist/{store-helpers-ZCSMJJAX.mjs → store-helpers-BhrzxvyQ.mjs} +4 -0
- package/dist/testing/index.d.mts +367 -711
- package/dist/testing/index.mjs +646 -1434
- package/dist/testing/storageContract.d.mts +1 -1
- package/dist/{tracing-65B51Dw3.d.mts → tracing-DokiEsuz.d.mts} +9 -4
- package/dist/types/index.d.mts +5 -5
- package/dist/types/index.mjs +1 -3
- package/dist/types/storage.d.mts +1 -1
- package/dist/{types-Co8k3NyS.d.mts → types-CgikqKAj.d.mts} +133 -21
- package/dist/{types-Btdda02s.d.mts → types-D9NqiYIw.d.mts} +1 -1
- package/dist/utils/index.d.mts +2 -898
- package/dist/utils/index.mjs +4 -5
- package/dist/utils-D3Yxnrwr.mjs +1639 -0
- package/dist/versioning-M9lNLhO8.d.mts +117 -0
- package/dist/websocket-CyJ1VIFI.d.mts +186 -0
- package/package.json +26 -8
- package/skills/arc/SKILL.md +124 -39
- package/skills/arc/references/testing.md +212 -183
- package/dist/applyPermissionResult-QhV1Pa-g.mjs +0 -37
- package/dist/core-CcR01lup.mjs +0 -1411
- package/dist/createActionRouter-Bp_5c_2b.mjs +0 -249
- package/dist/errorHandler-DRQ3EqfL.d.mts +0 -218
- package/dist/errors-CCSsMpXE.d.mts +0 -140
- package/dist/fields-bxkeltzz.mjs +0 -126
- package/dist/filesUpload-t21LS-py.mjs +0 -377
- package/dist/queryParser-DBqBB6AC.mjs +0 -352
- package/dist/types-Csi3FLfq.mjs +0 -27
- package/dist/utils-B2fNOD_i.mjs +0 -929
- /package/dist/{EventTransport-CUw5NNWe.d.mts → EventTransport-CfVEGaEl.d.mts} +0 -0
- /package/dist/{HookSystem-BNYKnrXF.mjs → HookSystem-CGsMd6oK.mjs} +0 -0
- /package/dist/{ResourceRegistry-BPd6NQDm.mjs → ResourceRegistry-DkAeAuTX.mjs} +0 -0
- /package/dist/{caching-CBpK_SCM.mjs → caching-CheW3m-S.mjs} +0 -0
- /package/dist/{elevation-C5SwtkAn.d.mts → elevation-s5ykdNHr.d.mts} +0 -0
- /package/dist/{errorHandler-Bb49BvPD.mjs → errorHandler-BQm8ZxTK.mjs} +0 -0
- /package/dist/{externalPaths-BQ8QijNH.d.mts → externalPaths-Bapitwvd.d.mts} +0 -0
- /package/dist/{interface-CSbZdv_3.d.mts → interface-CkkWm5uR.d.mts} +0 -0
- /package/dist/{interface-D218ikEo.d.mts → interface-Da0r7Lna.d.mts} +0 -0
- /package/dist/{memory-B5Amv9A1.mjs → memory-DikHSvWa.mjs} +0 -0
- /package/dist/{metrics-DuhiSEZI.mjs → metrics-Csh4nsvv.mjs} +0 -0
- /package/dist/{pluralize-A0tWEl1K.mjs → pluralize-BneOJkpi.mjs} +0 -0
- /package/dist/{registry-B3lRFBWo.mjs → registry-D63ee7fl.mjs} +0 -0
- /package/dist/{replyHelpers-CXtJDAZ0.mjs → replyHelpers-ByllIXXV.mjs} +0 -0
- /package/dist/{schemaConverter-BxFDdtXu.mjs → schemaConverter-B0oKLuqI.mjs} +0 -0
- /package/dist/{sessionManager-BkzVU8h2.d.mts → sessionManager-D-oNWHz3.d.mts} +0 -0
- /package/dist/{storage-CVk_SEn2.d.mts → storage-BwGQXUpd.d.mts} +0 -0
- /package/dist/{typeGuards-Cj5Rgvlg.mjs → typeGuards-CcFZXgU7.mjs} +0 -0
- /package/dist/{types-BD85MlEK.d.mts → types-tgR4Pt8F.d.mts} +0 -0
- /package/dist/{versioning-C2U_bLY0.mjs → versioning-CGPjkqAg.mjs} +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { FastifyInstance, FastifyRequest } from "fastify";
|
|
2
|
+
import { Span, Tracer } from "@opentelemetry/api";
|
|
2
3
|
|
|
3
4
|
//#region src/plugins/tracing.d.ts
|
|
4
5
|
interface TracingOptions {
|
|
@@ -28,8 +29,8 @@ interface TracingOptions {
|
|
|
28
29
|
sampleRate?: number;
|
|
29
30
|
}
|
|
30
31
|
interface TracerContext {
|
|
31
|
-
tracer:
|
|
32
|
-
currentSpan:
|
|
32
|
+
tracer: Tracer;
|
|
33
|
+
currentSpan: Span;
|
|
33
34
|
}
|
|
34
35
|
declare module "fastify" {
|
|
35
36
|
interface FastifyRequest {
|
|
@@ -53,7 +54,7 @@ declare function tracingPlugin(fastify: FastifyInstance, options?: TracingOption
|
|
|
53
54
|
* });
|
|
54
55
|
* }
|
|
55
56
|
*/
|
|
56
|
-
declare function createSpan<T>(request: FastifyRequest, name: string, fn: (span:
|
|
57
|
+
declare function createSpan<T>(request: FastifyRequest, name: string, fn: (span: Span | null) => Promise<T>, attributes?: Record<string, string | number | boolean>): Promise<T>;
|
|
57
58
|
/**
|
|
58
59
|
* Decorator to automatically trace repository methods
|
|
59
60
|
*
|
|
@@ -65,7 +66,11 @@ declare function createSpan<T>(request: FastifyRequest, name: string, fn: (span:
|
|
|
65
66
|
* }
|
|
66
67
|
* }
|
|
67
68
|
*/
|
|
68
|
-
declare function traced(spanName?: string): (target:
|
|
69
|
+
declare function traced(spanName?: string): (target: {
|
|
70
|
+
constructor: {
|
|
71
|
+
name: string;
|
|
72
|
+
};
|
|
73
|
+
}, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
|
|
69
74
|
/**
|
|
70
75
|
* Check if OpenTelemetry is available
|
|
71
76
|
*/
|
package/dist/types/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as
|
|
2
|
-
import {
|
|
3
|
-
import { c as PermissionCheck, d as UserBase, l as PermissionContext, u as PermissionResult } from "../fields-
|
|
4
|
-
import {
|
|
5
|
-
export {
|
|
1
|
+
import { $ as OpenApiSchemas, A as RequestIdOptions, At as Authenticator, Bt as UserOrganization, C as RequestContext, D as HealthCheck, E as GracefulShutdownOptions, F as FastifyWithDecorators, Ft as ApiResponse, G as ActionsMap, H as ActionDefinition, I as MiddlewareHandler, It as ArcRequest, J as CrudRouteKey, K as ArcFieldRule, L as RequestWithExtras, Lt as JWTPayload, M as EventsDecorator, Mt as JwtContext, N as FastifyRequestExtras, Nt as TokenPair, O as HealthOptions, Ot as AuthHelpers, P as FastifyWithAuth, Pt as AnyRecord, Q as MiddlewareConfig, Rt as ObjectId, S as QueryParserInterface, T as CrudRouterOptions, U as ActionEntry, W as ActionHandlerFn, X as EventDefinition, Y as CrudSchemas, Z as FieldRule, _ as ControllerQueryOptions, _t as IControllerResponse, a as InferAdapterDoc, at as ResourceConfig, b as ParsedQuery, c as TypedController, ct as ResourcePermissions, d as PaginationResult, dt as RouteMethod, et as PresetFunction, f as IntrospectionData, ft as RouteSchemaOptions, g as ArcInternalMetadata, gt as IController, h as ResourceMetadata, ht as FastifyHandler, i as ValidationResult, it as ResourceCacheConfig, j as ArcDecorator, jt as AuthenticatorContext, k as IntrospectionPluginOptions, kt as AuthPluginOptions, l as TypedRepository, lt as RouteDefinition, m as RegistryStats, mt as ControllerLike, n as ConfigError, nt as PresetResult, o as InferDocType, ot as ResourceHookContext, p as RegistryEntry, pt as ControllerHandler, q as CrudController, r as ValidateOptions, rt as RateLimitConfig, s as InferResourceDoc, st as ResourceHooks, t as RouteHandlerMethod, tn as BaseControllerOptions, tt as PresetHook, u as TypedResourceConfig, ut as RouteMcpConfig, v as LookupOption, vt as IRequestContext, w as ServiceContext, x as PopulateOption, y as OwnershipCheck, yt as RouteHandler, zt as UserLike } from "../index-Cm0vUrr_.mjs";
|
|
2
|
+
import { r as RequestScope } from "../types-tgR4Pt8F.mjs";
|
|
3
|
+
import { c as PermissionCheck, d as UserBase, l as PermissionContext, u as PermissionResult } from "../fields-C8Y0XLAu.mjs";
|
|
4
|
+
import { n as ElevationOptions, t as ElevationEvent } from "../elevation-s5ykdNHr.mjs";
|
|
5
|
+
export { ActionDefinition, ActionEntry, ActionHandlerFn, ActionsMap, AnyRecord, ApiResponse, ArcDecorator, ArcFieldRule, ArcInternalMetadata, ArcRequest, AuthHelpers, AuthPluginOptions, Authenticator, AuthenticatorContext, BaseControllerOptions, ConfigError, ControllerHandler, ControllerLike, ControllerQueryOptions, CrudController, CrudRouteKey, CrudRouterOptions, CrudSchemas, ElevationEvent, ElevationOptions, EventDefinition, EventsDecorator, FastifyHandler, FastifyRequestExtras, FastifyWithAuth, FastifyWithDecorators, FieldRule, GracefulShutdownOptions, HealthCheck, HealthOptions, IController, IControllerResponse, IRequestContext, InferAdapterDoc, InferDocType, InferResourceDoc, IntrospectionData, IntrospectionPluginOptions, JWTPayload, JwtContext, LookupOption, MiddlewareConfig, MiddlewareHandler, ObjectId, OpenApiSchemas, OwnershipCheck, PaginationResult, ParsedQuery, PermissionCheck, PermissionContext, PermissionResult, PopulateOption, PresetFunction, PresetHook, PresetResult, QueryParserInterface, RateLimitConfig, RegistryEntry, RegistryStats, RequestContext, RequestIdOptions, RequestScope, RequestWithExtras, ResourceCacheConfig, ResourceConfig, ResourceHookContext, ResourceHooks, ResourceMetadata, ResourcePermissions, RouteDefinition, RouteHandler, RouteHandlerMethod, RouteMcpConfig, RouteMethod, RouteSchemaOptions, ServiceContext, TokenPair, TypedController, TypedRepository, TypedResourceConfig, UserBase, UserLike, UserOrganization, ValidateOptions, ValidationResult };
|
package/dist/types/index.mjs
CHANGED
|
@@ -1,3 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { n as getUserId, t as envelope } from "../types-Csi3FLfq.mjs";
|
|
3
|
-
export { AUTHENTICATED_SCOPE, PUBLIC_SCOPE, envelope, getOrgId, getOrgRoles, getTeamId, getUserId, hasOrgAccess, isAuthenticated, isElevated, isMember };
|
|
1
|
+
export {};
|
package/dist/types/storage.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as StorageReadResult, i as StorageReadRange, n as StorageContext, o as StorageUploadInput, r as StorageFile, t as Storage } from "../storage-
|
|
1
|
+
import { a as StorageReadResult, i as StorageReadRange, n as StorageContext, o as StorageUploadInput, r as StorageFile, t as Storage } from "../storage-BwGQXUpd.mjs";
|
|
2
2
|
export { Storage, StorageContext, StorageFile, StorageReadRange, StorageReadResult, StorageUploadInput };
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { r as QueryCachePluginOptions } from "./queryCachePlugin-
|
|
7
|
-
import { t as EventPluginOptions } from "./eventPlugin-
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
1
|
+
import { At as Authenticator } from "./index-Cm0vUrr_.mjs";
|
|
2
|
+
import { r as CacheStore } from "./interface-Da0r7Lna.mjs";
|
|
3
|
+
import { n as ElevationOptions } from "./elevation-s5ykdNHr.mjs";
|
|
4
|
+
import { o as EventTransport } from "./EventTransport-CfVEGaEl.mjs";
|
|
5
|
+
import { t as ExternalOpenApiPaths } from "./externalPaths-Bapitwvd.mjs";
|
|
6
|
+
import { r as QueryCachePluginOptions } from "./queryCachePlugin-BUXBSm4F.mjs";
|
|
7
|
+
import { t as EventPluginOptions } from "./eventPlugin-CUNjYYRY.mjs";
|
|
8
|
+
import { f as CachingOptions, l as SSEOptions, o as MetricsOptions, t as VersioningOptions } from "./versioning-M9lNLhO8.mjs";
|
|
9
|
+
import { t as ErrorHandlerOptions } from "./errorHandler-Co3lnVmJ.mjs";
|
|
10
|
+
import { r as IdempotencyStore } from "./interface-CkkWm5uR.mjs";
|
|
10
11
|
import { FastifyInstance, FastifyPluginAsync, FastifyReply, FastifyRequest, FastifyServerOptions } from "fastify";
|
|
11
12
|
|
|
12
13
|
//#region src/factory/loadResources.d.ts
|
|
@@ -149,6 +150,18 @@ type HelmetOptions = Record<string, unknown>;
|
|
|
149
150
|
type RateLimitOpts = Record<string, unknown> & {
|
|
150
151
|
max?: number;
|
|
151
152
|
timeWindow?: string | number;
|
|
153
|
+
/**
|
|
154
|
+
* Path patterns to exempt from rate limiting. Supports exact match
|
|
155
|
+
* (`/health`) or prefix match with trailing `*` (`/api/auth/*`).
|
|
156
|
+
*
|
|
157
|
+
* Implemented by synthesising a `@fastify/rate-limit` `allowList`
|
|
158
|
+
* function. When combined with a user-supplied `allowList`, both
|
|
159
|
+
* are OR-ed together (path OR ip/custom match skips the limit).
|
|
160
|
+
*
|
|
161
|
+
* Use this for endpoints that are hit frequently but independently
|
|
162
|
+
* of user traffic — session heartbeat, webhooks, health probes.
|
|
163
|
+
*/
|
|
164
|
+
skipPaths?: string[];
|
|
152
165
|
};
|
|
153
166
|
/**
|
|
154
167
|
* Arc's built-in JWT auth
|
|
@@ -640,18 +653,70 @@ interface CreateAppOptions {
|
|
|
640
653
|
*/
|
|
641
654
|
serializeBigInt?: boolean;
|
|
642
655
|
/**
|
|
643
|
-
* Resources to register automatically.
|
|
644
|
-
* Each resource's `.toPlugin()` is called and registered for you.
|
|
656
|
+
* Resources to register automatically. Accepts two shapes:
|
|
645
657
|
*
|
|
646
|
-
*
|
|
658
|
+
* 1. **Array** — each resource's `.toPlugin()` is called and registered.
|
|
659
|
+
* Defined at module-import time, so the resource's adapter must be
|
|
660
|
+
* constructible without any async state.
|
|
661
|
+
*
|
|
662
|
+
* 2. **Factory function** (sync or async) — called AFTER `bootstrap[]`
|
|
663
|
+
* but BEFORE routes are wired. Use this when a resource's adapter
|
|
664
|
+
* depends on an engine / singleton that boots asynchronously
|
|
665
|
+
* (e.g. `await ensureCatalogEngine()` / `await createFlowEngine()`).
|
|
666
|
+
* The factory receives the Fastify instance for symmetry with
|
|
667
|
+
* `plugins` and `bootstrap`.
|
|
668
|
+
*
|
|
669
|
+
* Arc's lifecycle contract:
|
|
670
|
+
* ```
|
|
671
|
+
* 1. Arc core (security, auth, events)
|
|
672
|
+
* 2. plugins() ← infra (DB, SSE, docs)
|
|
673
|
+
* 3. bootstrap[] ← domain init (engines, singletons)
|
|
674
|
+
* 4. resources resolution ← (factory form: call it here)
|
|
675
|
+
* 5. resources registered ← plugins mounted on Fastify
|
|
676
|
+
* 6. afterResources() ← post-registration wiring
|
|
677
|
+
* ```
|
|
678
|
+
*
|
|
679
|
+
* The factory form is the canonical answer to "my repository lives in an
|
|
680
|
+
* engine that boots asynchronously." Before this shape existed, hosts had
|
|
681
|
+
* to write per-resource lazy-bridge adapters that awaited the engine on
|
|
682
|
+
* every CRUD call — pure boilerplate. With a factory, `defineResource(...)`
|
|
683
|
+
* runs with the engine already live, so `createMongooseAdapter(engine.models.X, engine.repositories.X)`
|
|
684
|
+
* works directly.
|
|
685
|
+
*
|
|
686
|
+
* @example Static array (most resources)
|
|
647
687
|
* ```ts
|
|
648
688
|
* const app = await createApp({
|
|
649
689
|
* resources: [productResource, orderResource, userResource],
|
|
650
690
|
* auth: { type: 'jwt', jwt: { secret: 'xxx' } },
|
|
651
691
|
* });
|
|
652
692
|
* ```
|
|
693
|
+
*
|
|
694
|
+
* @example Factory with async-booted engine
|
|
695
|
+
* ```ts
|
|
696
|
+
* const app = await createApp({
|
|
697
|
+
* bootstrap: [async () => { await ensureCatalogEngine(); }],
|
|
698
|
+
* resources: async () => {
|
|
699
|
+
* const cat = await ensureCatalogEngine();
|
|
700
|
+
* return [
|
|
701
|
+
* defineResource({
|
|
702
|
+
* name: 'product',
|
|
703
|
+
* adapter: createMongooseAdapter(cat.models.Product, cat.repositories.product),
|
|
704
|
+
* // ...
|
|
705
|
+
* }),
|
|
706
|
+
* ];
|
|
707
|
+
* },
|
|
708
|
+
* });
|
|
709
|
+
* ```
|
|
710
|
+
*
|
|
711
|
+
* @example Factory delegating to auto-discovery
|
|
712
|
+
* ```ts
|
|
713
|
+
* const app = await createApp({
|
|
714
|
+
* bootstrap: [async () => { await ensureCatalogEngine(); }],
|
|
715
|
+
* resources: async () => loadResources(import.meta.url),
|
|
716
|
+
* });
|
|
717
|
+
* ```
|
|
653
718
|
*/
|
|
654
|
-
resources?:
|
|
719
|
+
resources?: ReadonlyArray<ResourceLike> | ((fastify: FastifyInstance) => ReadonlyArray<ResourceLike> | Promise<ReadonlyArray<ResourceLike>>);
|
|
655
720
|
/**
|
|
656
721
|
* URL prefix for all auto-registered resources.
|
|
657
722
|
* Applied only to resources in the `resources` array — not to `plugins()`.
|
|
@@ -668,25 +733,72 @@ interface CreateAppOptions {
|
|
|
668
733
|
resourcePrefix?: string;
|
|
669
734
|
/**
|
|
670
735
|
* Auto-discover resources from a directory instead of passing an explicit
|
|
671
|
-
* `resources` array.
|
|
736
|
+
* `resources` array.
|
|
672
737
|
*
|
|
673
|
-
*
|
|
674
|
-
*
|
|
675
|
-
*
|
|
676
|
-
*
|
|
738
|
+
* Accepts either a filesystem path OR `import.meta.url` (a `file://` URL).
|
|
739
|
+
* **Prefer the URL form in production** — bare strings resolve relative to
|
|
740
|
+
* `process.cwd()`, which diverges from `dist/` at runtime and was the root
|
|
741
|
+
* cause of a reported "deployed app serves 404 on every route" incident.
|
|
677
742
|
*
|
|
678
|
-
* When both `resourceDir` and `resources` are provided, `resources` wins
|
|
679
|
-
*
|
|
743
|
+
* When both `resourceDir` and `resources` are provided, `resources` wins —
|
|
744
|
+
* explicit always beats convention, **including an explicit empty array**.
|
|
745
|
+
* `resources: []` disables resource registration entirely even with
|
|
746
|
+
* `resourceDir` set, which is the common case for shared base configs
|
|
747
|
+
* that turn resource loading off in test / CLI / health-check subprocesses.
|
|
748
|
+
* Auto-discovery from `resourceDir` fires only when `resources` is
|
|
749
|
+
* `undefined` (absent).
|
|
680
750
|
*
|
|
681
751
|
* @example
|
|
682
752
|
* ```ts
|
|
753
|
+
* // Recommended (v2.10.9+): URL form works in both src/ and dist/
|
|
683
754
|
* const app = await createApp({
|
|
684
|
-
* resourceDir:
|
|
755
|
+
* resourceDir: import.meta.url,
|
|
685
756
|
* resourcePrefix: '/api/v1',
|
|
686
757
|
* });
|
|
758
|
+
*
|
|
759
|
+
* // String form — resolves against process.cwd(), mind the dist/ gap
|
|
760
|
+
* const app = await createApp({
|
|
761
|
+
* resourceDir: 'src/resources',
|
|
762
|
+
* });
|
|
687
763
|
* ```
|
|
688
764
|
*/
|
|
689
765
|
resourceDir?: string;
|
|
766
|
+
/**
|
|
767
|
+
* Throw instead of silently booting with zero resources when `resourceDir`
|
|
768
|
+
* yields an empty result. Off by default to preserve back-compat — turning
|
|
769
|
+
* it on in production catches the "typoed path / stale dist/ layout"
|
|
770
|
+
* failure mode before the app accepts traffic.
|
|
771
|
+
*
|
|
772
|
+
* Only takes effect when `resourceDir` is set.
|
|
773
|
+
*
|
|
774
|
+
* @example
|
|
775
|
+
* ```ts
|
|
776
|
+
* await createApp({
|
|
777
|
+
* resourceDir: import.meta.url,
|
|
778
|
+
* strictResourceDir: process.env.NODE_ENV === 'production',
|
|
779
|
+
* });
|
|
780
|
+
* ```
|
|
781
|
+
*
|
|
782
|
+
* @default false
|
|
783
|
+
*/
|
|
784
|
+
strictResourceDir?: boolean;
|
|
785
|
+
/**
|
|
786
|
+
* Throw instead of warn when two resources share the same `name`. Off by
|
|
787
|
+
* default to preserve back-compat; turn on in production to catch stale
|
|
788
|
+
* `dist/` files (a common source of `Mongoose model already exists`
|
|
789
|
+
* collisions downstream of arc's own registry).
|
|
790
|
+
*
|
|
791
|
+
* @example
|
|
792
|
+
* ```ts
|
|
793
|
+
* await createApp({
|
|
794
|
+
* resources: await loadResources(import.meta.url),
|
|
795
|
+
* strictResources: process.env.NODE_ENV === 'production',
|
|
796
|
+
* });
|
|
797
|
+
* ```
|
|
798
|
+
*
|
|
799
|
+
* @default false
|
|
800
|
+
*/
|
|
801
|
+
strictResources?: boolean;
|
|
690
802
|
/**
|
|
691
803
|
* Custom plugin registration — runs after Arc core (security, auth, events)
|
|
692
804
|
* but before `bootstrap` and `resources`.
|