@classytic/arc 2.41.1 → 2.44.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/{EventTransport-CbUKDzZZ.d.mts → EventTransport-CiicKz2Z.d.mts} +1 -1
- package/dist/{EventTransport-DSqD_Xsg.mjs → EventTransport-DZWDsaPa.mjs} +22 -17
- package/dist/{HookSystem-CMF94SEA.mjs → HookSystem-yjEgn7Cm.mjs} +2 -2
- package/dist/{QueryCache-DFA-QrU9.d.mts → QueryCache--5uAuYPW.d.mts} +7 -3
- package/dist/{ResourceRegistry-MGpXoxHZ.mjs → ResourceRegistry-DJxHUpE4.mjs} +44 -13
- package/dist/acquire-BozJ-9yt.mjs +35 -0
- package/dist/actionPermissions-5N04zBL4.mjs +772 -0
- package/dist/audit/index.d.mts +46 -8
- package/dist/audit/index.mjs +48 -26
- package/dist/auth/audit.d.mts +8 -8
- package/dist/auth/audit.mjs +1 -1
- package/dist/auth/index.d.mts +46 -16
- package/dist/auth/index.mjs +134 -156
- package/dist/auth/redis-session.d.mts +4 -5
- package/dist/auth/redis-session.mjs +1 -1
- package/dist/{authorizationDecision-DawKGoXb.mjs → authorizationDecision-wX3SA9w_.mjs} +7 -102
- package/dist/{base-CxrV1LmG.d.mts → base-CZyixEQR.d.mts} +27 -5
- package/dist/boundedMap-DWiKW7lP.mjs +57 -0
- package/dist/{buildHandler-CvxKOc0m.mjs → buildHandler-Bswu_vNb.mjs} +4 -4
- package/dist/cache/index.d.mts +31 -43
- package/dist/cache/index.mjs +4 -4
- package/dist/{caching-DbCBxlgw.mjs → caching-Drp68DIS.mjs} +3 -3
- package/dist/claimed-DYvQoZLv.mjs +8 -0
- package/dist/cleanup/index.d.mts +18 -22
- package/dist/cleanup/index.mjs +27 -73
- package/dist/cli/commands/describe.d.mts +7 -5
- package/dist/cli/commands/describe.mjs +7 -4
- package/dist/cli/commands/docs.d.mts +2 -3
- package/dist/cli/commands/docs.mjs +3 -3
- package/dist/cli/commands/doctor.d.mts +2 -3
- package/dist/cli/commands/doctor.mjs +1 -1
- package/dist/cli/commands/generate.mjs +2 -3
- package/dist/cli/commands/init.mjs +2 -3
- package/dist/cli/commands/introspect.d.mts +2 -3
- package/dist/cli/commands/introspect.mjs +2 -2
- package/dist/cli/index.mjs +3 -3
- package/dist/{constants-D5Ubn1fe.mjs → constants-B2QHb6u6.mjs} +4 -2
- package/dist/context/index.d.mts +11 -14
- package/dist/context/index.mjs +18 -38
- package/dist/core/index.d.mts +3 -3
- package/dist/core/index.mjs +8 -8
- package/dist/{core-5lazhva9.mjs → core-COcqo0Cp.mjs} +15 -5
- package/dist/{createActionRouter-DNqoaK81.mjs → createActionRouter-zG13rpPJ.mjs} +97 -39
- package/dist/{createAggregationRouter-BcbQJf10.mjs → createAggregationRouter-CWRz96Vr.mjs} +11 -8
- package/dist/{preloadResources-f3boenVZ.mjs → createApp-BGLYtErt.mjs} +305 -394
- package/dist/{createMcpServer-CbDWkZ1T.d.mts → createMcpServer-DSztofa9.d.mts} +1 -1
- package/dist/{defineAggregation-D_eJjm5A.mjs → defineAggregation--3xguLkk.mjs} +1 -1
- package/dist/{defineResource-DxkMTjRn.mjs → defineResource-gUp9ug66.mjs} +118 -1024
- package/dist/discovery/index.d.mts +6 -7
- package/dist/discovery/index.mjs +1 -1
- package/dist/docs/index.d.mts +11 -5
- package/dist/docs/index.mjs +4 -4
- package/dist/{elevation-CkvG0LG2.mjs → elevation-BG4gnMsJ.mjs} +41 -12
- package/dist/{elevation-BXCfVcNG.d.mts → elevation-BW2J3tNj.d.mts} +1 -2
- package/dist/encryption/index.d.mts +5 -5
- package/dist/encryption/index.mjs +3 -3
- package/dist/{errorHandler-D1GHKGlV.mjs → errorHandler-COHw3N1b.mjs} +26 -5
- package/dist/{errors-BH7YU_9O.mjs → errors-CW4anJBy.mjs} +58 -23
- package/dist/{errors-BGdVwP25.d.mts → errors-JYc9vwqE.d.mts} +9 -0
- package/dist/{eventPlugin-B52abJ8W.d.mts → eventPlugin-BtmA4-3P.d.mts} +65 -9
- package/dist/{eventPlugin-zZY-unhr.mjs → eventPlugin-BweHAVws.mjs} +82 -21
- package/dist/{subscribe-helpers-DatDkcuG.mjs → eventTypes-N4-omQFR.mjs} +151 -17
- package/dist/events/index.d.mts +43 -18
- package/dist/events/index.mjs +49 -53
- package/dist/events/transports/redis-stream-entry.d.mts +1 -1
- package/dist/events/transports/redis-stream-entry.mjs +139 -157
- package/dist/events/transports/redis.d.mts +5 -6
- package/dist/events/transports/redis.mjs +2 -2
- package/dist/factory/index.d.mts +42 -27
- package/dist/factory/index.mjs +213 -32
- package/dist/{fastify-augmentation-Cq2nHVaW.d.mts → fastify-augmentation-DRlCIWE9.d.mts} +11 -25
- package/dist/{fields-BHrkoF5y.mjs → fields-A5crhsJb.mjs} +1 -1
- package/dist/{fields-I_EeRWND.d.mts → fields-BBSpf8pS.d.mts} +1 -1
- package/dist/filter-merge-DGM-GQ1J.mjs +99 -0
- package/dist/{generate-BLRf2m3y.mjs → generate-BXKo2Gc8.mjs} +2 -2
- package/dist/{headers-BIXWKrzQ.mjs → headers-DKZQKL-Z.mjs} +2 -2
- package/dist/health-BYAwA6YS.mjs +22 -0
- package/dist/{health-ZRHeDHXH.mjs → health-CrqUp3sz.mjs} +115 -55
- package/dist/hooks/index.d.mts +2 -2
- package/dist/hooks/index.mjs +2 -3
- package/dist/idempotency/index.d.mts +36 -10
- package/dist/idempotency/index.mjs +230 -111
- package/dist/idempotency/redis.d.mts +1 -1
- package/dist/idempotency/redis.mjs +77 -12
- package/dist/{index-D4u76eQW.d.mts → index-Beg3aNnK.d.mts} +23 -101
- package/dist/{preloadResources-CjS2OfpU.d.mts → index-BkV55WlV.d.mts} +37 -38
- package/dist/{index-BHdZD8zK.d.mts → index-Bxriq3so.d.mts} +84 -21
- package/dist/index-CUJvoyw3.d.mts +510 -0
- package/dist/{index-CbJiYrfv.d.mts → index-Chgz3d0i.d.mts} +1 -1
- package/dist/{index-DHbyPo5j.d.mts → index-WH7xgvxS.d.mts} +304 -254
- package/dist/index.d.mts +9 -9
- package/dist/index.mjs +11 -11
- package/dist/{init-CpLkjU18.mjs → init-BPzK5Lnr.mjs} +1 -1
- package/dist/integrations/event-gateway.d.mts +11 -7
- package/dist/integrations/event-gateway.mjs +4 -4
- package/dist/integrations/index.d.mts +3 -3
- package/dist/integrations/index.mjs +1 -1
- package/dist/integrations/jobs/index.d.mts +1 -1
- package/dist/integrations/jobs/index.mjs +18 -5
- package/dist/integrations/mcp/index.d.mts +102 -89
- package/dist/integrations/mcp/index.mjs +19 -4
- package/dist/integrations/mcp/testing.d.mts +8 -9
- package/dist/integrations/mcp/testing.mjs +2 -2
- package/dist/integrations/streamline.d.mts +85 -144
- package/dist/integrations/streamline.mjs +131 -55
- package/dist/integrations/webhooks.d.mts +83 -143
- package/dist/integrations/webhooks.mjs +36 -80
- package/dist/integrations/websocket-pushref-redis.d.mts +5 -6
- package/dist/integrations/websocket-pushref-redis.mjs +1 -1
- package/dist/integrations/websocket-redis.d.mts +5 -6
- package/dist/integrations/websocket-redis.mjs +1 -1
- package/dist/integrations/websocket.d.mts +3 -3
- package/dist/integrations/websocket.mjs +2 -2
- package/dist/{interface-DEWNOMza.d.mts → interface-JJzwH4Ro.d.mts} +34 -2
- package/dist/{jsonBody-ELR9lfeU.mjs → jsonBody-YIq-vGLv.mjs} +2 -2
- package/dist/{keys-cpZCtcIE.mjs → keys-CpoiZ8hU.mjs} +7 -18
- package/dist/{loadResources-BPfWiI5s.mjs → loadResources-6jO52-RR.mjs} +3 -3
- package/dist/{loadResourcesFromEntry-ixtfL3J2.mjs → loadResourcesFromEntry-MP8xEppu.mjs} +2 -2
- package/dist/logger/index.d.mts +9 -17
- package/dist/logger/index.mjs +2 -153
- package/dist/logger-D4V1zGLI.mjs +160 -0
- package/dist/{mcpPlugin-BX5PujI0.mjs → mcpPlugin-srPc7ItN.mjs} +446 -170
- package/dist/{memory-Iotz0cCx.mjs → memory-CTa5pOCW.mjs} +36 -34
- package/dist/{metrics-NMsmpRmY.mjs → metrics-DsZrvnpB.mjs} +39 -72
- package/dist/middleware/index.d.mts +5 -5
- package/dist/middleware/index.mjs +3 -3
- package/dist/migrations/index.d.mts +13 -13
- package/dist/migrations/index.mjs +2 -2
- package/dist/{module-DpLJG2_N.mjs → module--L0iBIZz.mjs} +8 -8
- package/dist/mongodb-memory-server-CHhYSq5y.mjs +35539 -0
- package/dist/mongoose-CYJCLyi-.mjs +67451 -0
- package/dist/multiTenant-CAtYlW6H.d.mts +104 -0
- package/dist/{multipartBody-DtRWM6_U.mjs → multipartBody-Cc7eZ9cq.mjs} +46 -7
- package/dist/node-D8UZv_8c.mjs +41236 -0
- package/dist/{openapi-CmFf3yq_.mjs → openapi-CMegfsm8.mjs} +48 -10
- package/dist/outbox-admin/index.d.mts +5 -5
- package/dist/outbox-admin/index.mjs +6 -18
- package/dist/{outbox-module-D2z5WkDY.mjs → outbox-module-Ryk270jd.mjs} +203 -33
- package/dist/{outbox-module-BHdUnuuK.d.mts → outbox-module-gZCHoE4H.d.mts} +79 -6
- package/dist/permissions/index.d.mts +5 -4
- package/dist/permissions/index.mjs +8 -6
- package/dist/{permissions-D8TBH44E.mjs → permissions-C5ijIz5Q.mjs} +149 -33
- package/dist/{pipe-FMWNheSO.mjs → pipe-D81zMtWs.mjs} +2 -2
- package/dist/pipeline/index.d.mts +7 -7
- package/dist/pipeline/index.mjs +2 -2
- package/dist/plan-CJGMKoui.mjs +565 -0
- package/dist/{BaseController-CYEwjyjN.mjs → plugin-DALd9dcF.mjs} +1269 -346
- package/dist/plugins/index.d.mts +17 -14
- package/dist/plugins/index.mjs +44 -22
- package/dist/plugins/response-cache.d.mts +5 -6
- package/dist/plugins/response-cache.mjs +8 -14
- package/dist/plugins/tracing-entry.mjs +2 -2
- package/dist/{pluralize-CXWZIzTv.mjs → pluralize-COUNYo3d.mjs} +1 -1
- package/dist/presets/filesUpload.d.mts +8 -8
- package/dist/presets/filesUpload.mjs +5 -5
- package/dist/presets/index.d.mts +35 -40
- package/dist/presets/index.mjs +4 -4
- package/dist/presets/multiTenant.d.mts +2 -107
- package/dist/presets/multiTenant.mjs +22 -162
- package/dist/presets/search.d.mts +9 -10
- package/dist/presets/search.mjs +2 -2
- package/dist/{presets-ZJSPgmT2.mjs → presets-CONf2Qem.mjs} +99 -107
- package/dist/{projection-BzIgzoKZ.mjs → projection-wFoLqdss.mjs} +2 -2
- package/dist/{pushref-registry-Dov9l4qE.d.mts → pushref-registry-UxCkoA4C.d.mts} +1 -1
- package/dist/{queryCachePlugin-DZHPOm9p.mjs → queryCachePlugin-BATECpyh.mjs} +12 -14
- package/dist/{queryCachePlugin-BzqxconG.d.mts → queryCachePlugin-C2lZjTxk.d.mts} +1 -1
- package/dist/{rateLimitKey-BvOvcBDi.mjs → rateLimitKey-DVEZ_UpV.mjs} +1 -1
- package/dist/{realtime-8tIQWZz4.mjs → realtime-xyubMKSB.mjs} +25 -21
- package/dist/{redis-Bzi1y3F9.d.mts → redis-BDgv9Glw.d.mts} +17 -24
- package/dist/redis-stream-BMk-bpQS.d.mts +219 -0
- package/dist/redisShapes-CQksY67q.d.mts +55 -0
- package/dist/registry/index.d.mts +15 -10
- package/dist/registry/index.mjs +4 -4
- package/dist/{registry-DNkgGQcK.mjs → registry-Bdzg-hdm.mjs} +13 -10
- package/dist/{renewingLease-yF8BdW4b.mjs → renewingLease-BFJxGPuh.mjs} +1 -1
- package/dist/{replyHelpers-CNdvMfM4.mjs → replyHelpers-Bnc6lJyy.mjs} +2 -2
- package/dist/{requestContext-cDkAUr-P.mjs → requestContext-C10UeFe5.mjs} +1 -1
- package/dist/requirement-Bu50QALH.mjs +35 -0
- package/dist/requirement-CbiLdQ1n.d.mts +22 -0
- package/dist/resourceRateLimit-Wf6d6FL9.d.mts +30 -0
- package/dist/resourceRateLimit-urWPJxrt.mjs +180 -0
- package/dist/rolldown-runtime-MYrLNGnq.mjs +45 -0
- package/dist/routeValidator-DHtpzrzk.mjs +70 -0
- package/dist/{runtimeCapabilities-CkhS6jn6.mjs → runtimeCapabilities-DIMKMV2G.mjs} +1 -1
- package/dist/{schedules-j6uXXAeJ.mjs → schedules-CKTs5ys8.mjs} +46 -37
- package/dist/{schemaConverter-BVA7cFRG.mjs → schemaConverter-BVjkQ5DD.mjs} +2 -2
- package/dist/{schemaIR-CTvPDoPB.mjs → schemaIR-BA0Hb21Y.mjs} +2 -2
- package/dist/schemas/index.d.mts +20 -10
- package/dist/schemas/index.mjs +8 -3
- package/dist/scim/index.d.mts +13 -13
- package/dist/scim/index.mjs +2 -2
- package/dist/scope/index.d.mts +4 -4
- package/dist/scope/index.mjs +6 -6
- package/dist/{scope-BUi1xV1I.mjs → scope-DINaj7Ax.mjs} +4 -4
- package/dist/shutdown-LpLMH8T1.mjs +59 -0
- package/dist/{simpleEqualityMatcher-C9bzq2gO.mjs → simpleEqualityMatcher-DbwIM1f1.mjs} +1 -1
- package/dist/{sse-BeqVKQKu.mjs → sse-BzJFPX_1.mjs} +11 -15
- package/dist/{sseStream-Ppzo-WUH.mjs → sseStream-DQChzGTs.mjs} +2 -2
- package/dist/{store-helpers-dW71XVWL.mjs → store-helpers-Coj9RhOZ.mjs} +1 -1
- package/dist/{streaming-IcRFjWQU.mjs → streaming-JzB5CAga.mjs} +1 -1
- package/dist/subscriberIdentity-DeyppIif.mjs +28 -0
- package/dist/tenancy-DxV8OuX2.mjs +43 -0
- package/dist/tenantPreparation-CBvvAcAj.mjs +67 -0
- package/dist/testing/cleanupStoreContract.d.mts +4 -5
- package/dist/testing/cleanupStoreContract.mjs +1 -1
- package/dist/testing/index.d.mts +215 -197
- package/dist/testing/index.mjs +289 -214
- package/dist/testing/outboxStoreContract.d.mts +4 -5
- package/dist/testing/outboxStoreContract.mjs +137 -2
- package/dist/testing/requiredPorts.d.mts +16 -0
- package/dist/testing/requiredPorts.mjs +65 -0
- package/dist/testing/storageContract.d.mts +4 -5
- package/dist/testing/storageContract.mjs +1 -1
- package/dist/timing-CntavTlR.mjs +46 -0
- package/dist/{transactionContext-CPbdlnVw.mjs → transactionContext-orvnGu4F.mjs} +1 -1
- package/dist/{typeGuards-BLjPgVBm.mjs → typeGuards-kEaP_WmO.mjs} +1 -1
- package/dist/types/index.d.mts +4 -4
- package/dist/types/index.mjs +1 -1
- package/dist/types/storage.mjs +1 -1
- package/dist/{types-DfVDvkdP.d.mts → types-BJ-2XqVF.d.mts} +189 -204
- package/dist/{types-CWQn9-IC.d.mts → types-D3Ixsh00.d.mts} +22 -9
- package/dist/{types-CgenB1gv.mjs → types-fvO6Ovzx.mjs} +4 -4
- package/dist/usage/index.d.mts +5 -6
- package/dist/usage/index.mjs +5 -5
- package/dist/{userHelpers-ChRvkuSZ.mjs → userHelpers-C76zD5pa.mjs} +1 -1
- package/dist/utils/index.d.mts +125 -264
- package/dist/utils/index.mjs +13 -12
- package/dist/{utils-CxcctrAh.mjs → utils-BpkVZ8rB.mjs} +315 -404
- package/dist/{validate-DrYWnOzI.mjs → validate-CWp-lsrm.mjs} +6 -14
- package/dist/{versioning-D6JIK8Tk.d.mts → versioning-Bsb51gGT.d.mts} +28 -13
- package/dist/{versioning-DKkT4hNJ.mjs → versioning-CHhL9P3o.mjs} +4 -4
- package/dist/{websocket-BOXVggMf.d.mts → websocket-Cs4awVyD.d.mts} +1 -1
- package/dist/{workScope-CxKqoIFn.mjs → workScope-n9a7d_lZ.mjs} +2 -2
- package/package.json +57 -59
- package/skills/arc/SKILL.md +13 -4
- package/skills/arc/references/auth.md +8 -5
- package/skills/arc/references/integrations.md +1 -1
- package/skills/arc/references/mcp.md +8 -6
- package/skills/arc/references/multi-tenancy.md +19 -14
- package/skills/arc/references/production.md +27 -10
- package/dist/actionPermissions-BoPGQ5-4.mjs +0 -350
- package/dist/index-CFfLKMH4.d.mts +0 -290
- package/dist/interface-YzIbF7Ii.mjs +0 -17
- package/dist/redis-stream-BPKscsTB.d.mts +0 -260
- package/dist/registerRoute-Bsnk6NiZ.mjs +0 -364
- package/dist/rolldown-runtime-eysyzFAF.mjs +0 -15
- package/dist/sync/changelog.d.mts +0 -3
- package/dist/sync/changelog.mjs +0 -3
package/dist/testing/index.d.mts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
|
|
2
2
|
import { i as RequestScope } from "../types-Ddl9OjmE.mjs";
|
|
3
|
-
import { l as PermissionCheck, t as AnyRecord } from "../base-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import "../index-
|
|
7
|
-
import { n as
|
|
3
|
+
import { l as PermissionCheck, t as AnyRecord } from "../base-CZyixEQR.mjs";
|
|
4
|
+
import { F as ResourceDefinition } from "../index-WH7xgvxS.mjs";
|
|
5
|
+
import { h as ModuleSetupContext, m as ModuleDisposer, o as ArcPorts, p as PortName, r as ArcModuleInput, u as ModuleName } from "../types-BJ-2XqVF.mjs";
|
|
6
|
+
import "../index-CUJvoyw3.mjs";
|
|
7
|
+
import { n as CreateAppOptions } from "../index-BkV55WlV.mjs";
|
|
8
8
|
import { StorageContractSetup, StorageContractSetupResult, runStorageContract } from "./storageContract.mjs";
|
|
9
9
|
import { StandardRepo } from "@classytic/repo-core/repository";
|
|
10
10
|
import { FastifyInstance, FastifyServerOptions } from "fastify";
|
|
@@ -72,7 +72,181 @@ interface ArcAssertion {
|
|
|
72
72
|
/** Assert a specific key on `body.meta` or flattened top-level (matches sendControllerResponse flattening). */
|
|
73
73
|
hasMeta(key: string, value?: unknown): ArcAssertion;
|
|
74
74
|
}
|
|
75
|
-
declare function expectArc(response: ArcResponseLike): ArcAssertion;
|
|
75
|
+
export declare function expectArc(response: ArcResponseLike): ArcAssertion;
|
|
76
|
+
//#endregion
|
|
77
|
+
//#region src/testing/testActor.d.ts
|
|
78
|
+
/** The header the testing harness uses to carry a request's actor. */
|
|
79
|
+
export declare const TEST_ACTOR_HEADER = "x-test-actor";
|
|
80
|
+
/**
|
|
81
|
+
* What a test wants to be. An `organizationId` produces a `member` scope (the
|
|
82
|
+
* org-scoped case); without one the actor is `authenticated`.
|
|
83
|
+
*/
|
|
84
|
+
interface TestActor {
|
|
85
|
+
/**
|
|
86
|
+
* Defaults to a synthetic id derived from the roles. Pass one explicitly when
|
|
87
|
+
* a test distinguishes two actors — ownership and audit assertions do, and
|
|
88
|
+
* two actors sharing roles would otherwise share an id.
|
|
89
|
+
*/
|
|
90
|
+
userId?: string;
|
|
91
|
+
/** Global roles — what `requireRoles` reads. */
|
|
92
|
+
roles?: string[];
|
|
93
|
+
/** Tenant. Present ⇒ a `member` scope. */
|
|
94
|
+
organizationId?: string;
|
|
95
|
+
/** Org-level roles from membership records. Defaults to `roles`. */
|
|
96
|
+
orgRoles?: string[];
|
|
97
|
+
teamId?: string;
|
|
98
|
+
/** App-defined dimensions (branch, project, region) read via `getScopeContext`. */
|
|
99
|
+
context?: Record<string, string>;
|
|
100
|
+
/**
|
|
101
|
+
* Elevated (platform-admin) scope. The value is the `elevatedBy` audit string
|
|
102
|
+
* arc requires — an elevated scope must record who granted it. `true` is
|
|
103
|
+
* shorthand for `'test'`.
|
|
104
|
+
*
|
|
105
|
+
* An elevated scope carries no roles: elevation is a different kind of actor,
|
|
106
|
+
* not a role. A test needing a role gate AND elevation wants `member`.
|
|
107
|
+
*/
|
|
108
|
+
elevated?: string | boolean;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Build the headers that make an injected request act as `actor`.
|
|
112
|
+
*
|
|
113
|
+
* A string is shorthand for a single role. `null` means "stay public", so a test
|
|
114
|
+
* can prove an endpoint is reachable anonymously.
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```ts
|
|
118
|
+
* t.app.inject({ method: 'GET', url: '/pos/shifts/current',
|
|
119
|
+
* headers: testActorHeaders('manager', ORG) });
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
export declare function testActorHeaders(actor: TestActor | string | null, organizationId?: string): Record<string, string>;
|
|
123
|
+
/**
|
|
124
|
+
* Turn a spec into a `RequestScope`.
|
|
125
|
+
*
|
|
126
|
+
* `orgRoles` defaults to `roles`: a test that says "manager" means it at both
|
|
127
|
+
* levels, and making the caller repeat itself only produces tests that pass a
|
|
128
|
+
* global gate and mysteriously fail an org one.
|
|
129
|
+
*/
|
|
130
|
+
export declare function scopeFromTestActor(spec: TestActor): RequestScope;
|
|
131
|
+
/**
|
|
132
|
+
* Build the `auth` option that makes the test actor arc's authenticator.
|
|
133
|
+
*
|
|
134
|
+
* It must be an authenticator, not a hook. Fastify encapsulates plugins and
|
|
135
|
+
* modules register DURING `createApp`, so a hook added to the root instance
|
|
136
|
+
* afterwards never runs for their routes — every request still resolves as
|
|
137
|
+
* public and every role gate still answers 401, which reads exactly like a
|
|
138
|
+
* broken authorization rule in the code under test. Registering as
|
|
139
|
+
* `auth: { type: 'authenticator' }` puts the scope where arc's own auth would,
|
|
140
|
+
* at the phase arc expects, so tenant filtering and permission checks behave
|
|
141
|
+
* identically to production.
|
|
142
|
+
*
|
|
143
|
+
* `defaultActor` applies to requests carrying no header. A malformed header
|
|
144
|
+
* REJECTS rather than falling back to public — a test that meant to be an admin
|
|
145
|
+
* and got quietly demoted is the most expensive way to fail.
|
|
146
|
+
*/
|
|
147
|
+
export declare function testActorAuth(defaultActor?: TestActor): {
|
|
148
|
+
type: "authenticator";
|
|
149
|
+
authenticate: (request: unknown) => Promise<void>;
|
|
150
|
+
};
|
|
151
|
+
//#endregion
|
|
152
|
+
//#region src/testing/bootModuleApp.d.ts
|
|
153
|
+
/** Handed to a modules factory — the in-memory DB is live at call time. */
|
|
154
|
+
/**
|
|
155
|
+
* A provisioned test database — what the `database` seam yields. Arc
|
|
156
|
+
* core never names a driver: kits ship factories (`mongoMemoryDatabase`
|
|
157
|
+
* is the built-in default; a sqlitekit/pgkit testkit ships its own) and
|
|
158
|
+
* the connection flows through as an opaque generic.
|
|
159
|
+
*/
|
|
160
|
+
interface TestDatabase<TConn = unknown> {
|
|
161
|
+
/** Connection string, when the backend has one (informational). */
|
|
162
|
+
uri: string;
|
|
163
|
+
/** Driver connection handle passed to the modules factory. */
|
|
164
|
+
connection: TConn;
|
|
165
|
+
/** Stop/disconnect everything this factory started. MUST be idempotent-safe to call once. */
|
|
166
|
+
teardown(): Promise<void>;
|
|
167
|
+
}
|
|
168
|
+
/** The DB-provisioning seam — `bootModuleApp({ database })`. */
|
|
169
|
+
type TestDatabaseFactory<TConn = unknown> = (opts: {
|
|
170
|
+
replset?: boolean;
|
|
171
|
+
}) => Promise<TestDatabase<TConn>>;
|
|
172
|
+
interface TestkitContext<TConn = unknown> {
|
|
173
|
+
/** The provisioned database's connection string. */
|
|
174
|
+
uri: string;
|
|
175
|
+
/**
|
|
176
|
+
* Driver connection handle (the default factory yields mongoose's
|
|
177
|
+
* DEFAULT connection). Generic so DB-typed wrappers assert the driver
|
|
178
|
+
* type ONCE: `bootModuleApp<Connection>(...)`. Arc core stays DB-agnostic.
|
|
179
|
+
*/
|
|
180
|
+
connection: TConn;
|
|
181
|
+
}
|
|
182
|
+
type BootModulesInput<TConn = unknown> = ArcModuleInput | readonly ArcModuleInput[] | ((ctx: TestkitContext<TConn>) => ArcModuleInput | readonly ArcModuleInput[] | Promise<ArcModuleInput | readonly ArcModuleInput[]>);
|
|
183
|
+
interface BootModuleAppOptions<TConn = unknown> {
|
|
184
|
+
/**
|
|
185
|
+
* DB provisioner. Default: `mongoMemoryDatabase` (in-memory MongoDB —
|
|
186
|
+
* lazy devDep imports, nothing Mongo touches arc's runtime). Kits for
|
|
187
|
+
* other stores inject their own factory here; the rest of the harness
|
|
188
|
+
* (module resolution, app boot, teardown ordering) is DB-agnostic.
|
|
189
|
+
*/
|
|
190
|
+
database?: TestDatabaseFactory<TConn>;
|
|
191
|
+
/** Single-node replica set (transactions). Default: standalone. Passed to the database factory. */
|
|
192
|
+
replset?: boolean;
|
|
193
|
+
/**
|
|
194
|
+
* Extra `createApp` options merged over the testing defaults
|
|
195
|
+
* (`preset: 'testing'`, `auth: false`, `sensible: false` — utility
|
|
196
|
+
* plugins stay off so the testkit is dependency-light; re-enable per
|
|
197
|
+
* boot when a module genuinely exercises one).
|
|
198
|
+
*/
|
|
199
|
+
app?: Partial<CreateAppOptions>;
|
|
200
|
+
/**
|
|
201
|
+
* Default actor for every injected request that carries no `x-test-actor` header.
|
|
202
|
+
*
|
|
203
|
+
* The harness boots with `auth: false`, so without this every request is
|
|
204
|
+
* `PUBLIC_SCOPE` and role-gated routes answer 401 — correct, but it left tests with
|
|
205
|
+
* no supported way to be somebody. See `testActor.ts` for why the seam lives in the
|
|
206
|
+
* testing entrypoint and can never be reached from production.
|
|
207
|
+
*/
|
|
208
|
+
actor?: TestActor;
|
|
209
|
+
/** Host ports for the booted modules — typed and checked exactly as `createApp({ ports })`. */
|
|
210
|
+
ports?: ArcPorts;
|
|
211
|
+
}
|
|
212
|
+
interface ModuleTestApp<TConn = unknown> {
|
|
213
|
+
app: FastifyInstance;
|
|
214
|
+
/** The provisioned database's connection string. */
|
|
215
|
+
uri: string;
|
|
216
|
+
/** The mongoose `Connection` handed to the modules factory. */
|
|
217
|
+
connection: TConn;
|
|
218
|
+
/**
|
|
219
|
+
* Typed module-export accessor — `t.exports<CatalogEngine>('catalog')`
|
|
220
|
+
* instead of reaching through `(t.app as ...).arc.modules.catalog`.
|
|
221
|
+
* Delegates to `getModuleExports` (throws with the registered-module
|
|
222
|
+
* list when the name is unknown — same contract hosts get).
|
|
223
|
+
*/
|
|
224
|
+
exports<TExports = unknown>(name: string): TExports;
|
|
225
|
+
/** Close app → disconnect mongoose → stop the in-memory server. Idempotent. */
|
|
226
|
+
close(): Promise<void>;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* The built-in DB factory: in-memory MongoDB via lazy devDep imports.
|
|
230
|
+
* Everything Mongo-specific about the harness lives HERE — the harness
|
|
231
|
+
* itself is driver-blind and any kit can replace this via `database`.
|
|
232
|
+
*/
|
|
233
|
+
export declare function mongoMemoryDatabase(opts: {
|
|
234
|
+
replset?: boolean;
|
|
235
|
+
}): Promise<TestDatabase<unknown>>;
|
|
236
|
+
export declare function bootModuleApp<TConn = unknown>(modules: BootModulesInput<TConn>, options?: BootModuleAppOptions<TConn>): Promise<ModuleTestApp<TConn>>;
|
|
237
|
+
//#endregion
|
|
238
|
+
//#region src/testing/assertModuleBootsAlone.d.ts
|
|
239
|
+
interface ModuleBootsAloneOptions<TConn = unknown> extends BootModuleAppOptions<TConn> {
|
|
240
|
+
/** Runs against the booted closure before it closes — drive the module's cross-module ports. */
|
|
241
|
+
probe?: (t: ModuleTestApp<TConn>) => void | Promise<void>;
|
|
242
|
+
}
|
|
243
|
+
interface ModuleBootsAloneResult {
|
|
244
|
+
/** The closure's modules (bridges excluded), in input order. */
|
|
245
|
+
readonly closure: readonly string[];
|
|
246
|
+
}
|
|
247
|
+
export declare function assertModuleBootsAlone<TConn = unknown>(modules: BootModulesInput<TConn>,
|
|
248
|
+
/** The module — or several roots booted together, when a deployment rule pairs them. */
|
|
249
|
+
name: ModuleName | readonly ModuleName[], options?: ModuleBootsAloneOptions<TConn>): Promise<ModuleBootsAloneResult>;
|
|
76
250
|
//#endregion
|
|
77
251
|
//#region src/testing/authorizationConformance.d.ts
|
|
78
252
|
/** One surface's observed enforcement: the HTTP status + the filter arc passed the repo. */
|
|
@@ -107,7 +281,7 @@ interface AuthorizationConformance {
|
|
|
107
281
|
* Boot a one-resource app gated by `permission` on both list + an aggregation,
|
|
108
282
|
* hit both surfaces anonymously, and report what arc enforced on each.
|
|
109
283
|
*/
|
|
110
|
-
declare function runAuthorizationConformance(opts: {
|
|
284
|
+
export declare function runAuthorizationConformance(opts: {
|
|
111
285
|
/** The permission under test — applied to `list` and the aggregation alike. */
|
|
112
286
|
permission: PermissionCheck;
|
|
113
287
|
/** Rows the mock repo returns for list (aggregation returns a count). */
|
|
@@ -166,21 +340,21 @@ interface TestAuthProvider {
|
|
|
166
340
|
* Accepts both `user` (payload to sign) and `token` (pre-signed) role configs,
|
|
167
341
|
* so the same provider handles mixed flows in a single test.
|
|
168
342
|
*/
|
|
169
|
-
declare function createJwtAuthProvider(app: FastifyInstance, opts?: {
|
|
343
|
+
export declare function createJwtAuthProvider(app: FastifyInstance, opts?: {
|
|
170
344
|
defaultOrgId?: string;
|
|
171
345
|
}): TestAuthProvider;
|
|
172
346
|
/**
|
|
173
347
|
* Better Auth provider — uses pre-signed tokens (from signUp/signIn flows).
|
|
174
348
|
* No signing: role configs MUST carry `token`. A `user` alone will throw.
|
|
175
349
|
*/
|
|
176
|
-
declare function createBetterAuthProvider(opts?: {
|
|
350
|
+
export declare function createBetterAuthProvider(opts?: {
|
|
177
351
|
defaultOrgId?: string;
|
|
178
352
|
}): TestAuthProvider;
|
|
179
353
|
/**
|
|
180
354
|
* Custom provider — plug in your own token minting logic. Useful for
|
|
181
355
|
* mocked external issuers, session-cookie flows, or fixtures that pre-mint.
|
|
182
356
|
*/
|
|
183
|
-
declare function createCustomAuthProvider(mintToken: (role: string, config: RoleConfig) => string, opts?: {
|
|
357
|
+
export declare function createCustomAuthProvider(mintToken: (role: string, config: RoleConfig) => string, opts?: {
|
|
184
358
|
defaultOrgId?: string;
|
|
185
359
|
}): TestAuthProvider;
|
|
186
360
|
//#endregion
|
|
@@ -313,13 +487,13 @@ interface SetupBetterAuthTestAppResult {
|
|
|
313
487
|
* Auth endpoints occasionally emit empty 204 bodies (e.g. set-active) and
|
|
314
488
|
* tests shouldn't crash on the parse.
|
|
315
489
|
*/
|
|
316
|
-
declare function safeParseBody<T = unknown>(body: string | undefined): T | null;
|
|
490
|
+
export declare function safeParseBody<T = unknown>(body: string | undefined): T | null;
|
|
317
491
|
/**
|
|
318
492
|
* Stateless Better Auth helpers. Each function takes the app as a positional
|
|
319
493
|
* argument, so a single helper instance works across multiple test apps in
|
|
320
494
|
* the same suite.
|
|
321
495
|
*/
|
|
322
|
-
declare function createBetterAuthTestHelpers(options?: BetterAuthTestHelpersOptions): BetterAuthTestHelpers;
|
|
496
|
+
export declare function createBetterAuthTestHelpers(options?: BetterAuthTestHelpersOptions): BetterAuthTestHelpers;
|
|
323
497
|
/**
|
|
324
498
|
* Composite setup for Better Auth apps. Replaces the pre-v2.11
|
|
325
499
|
* `setupBetterAuthOrg` with a tighter contract:
|
|
@@ -339,183 +513,24 @@ declare function createBetterAuthTestHelpers(options?: BetterAuthTestHelpersOpti
|
|
|
339
513
|
* creators are supplied (ambiguous ownership is a boot-time bug, not a
|
|
340
514
|
* runtime one).
|
|
341
515
|
*/
|
|
342
|
-
declare function setupBetterAuthTestApp(input: SetupBetterAuthTestAppInput): Promise<SetupBetterAuthTestAppResult>;
|
|
343
|
-
//#endregion
|
|
344
|
-
//#region src/testing/testActor.d.ts
|
|
345
|
-
/** The header the testing harness uses to carry a request's actor. */
|
|
346
|
-
declare const TEST_ACTOR_HEADER = "x-test-actor";
|
|
347
|
-
/**
|
|
348
|
-
* What a test wants to be. An `organizationId` produces a `member` scope (the
|
|
349
|
-
* org-scoped case); without one the actor is `authenticated`.
|
|
350
|
-
*/
|
|
351
|
-
interface TestActor {
|
|
352
|
-
/**
|
|
353
|
-
* Defaults to a synthetic id derived from the roles. Pass one explicitly when
|
|
354
|
-
* a test distinguishes two actors — ownership and audit assertions do, and
|
|
355
|
-
* two actors sharing roles would otherwise share an id.
|
|
356
|
-
*/
|
|
357
|
-
userId?: string;
|
|
358
|
-
/** Global roles — what `requireRoles` reads. */
|
|
359
|
-
roles?: string[];
|
|
360
|
-
/** Tenant. Present ⇒ a `member` scope. */
|
|
361
|
-
organizationId?: string;
|
|
362
|
-
/** Org-level roles from membership records. Defaults to `roles`. */
|
|
363
|
-
orgRoles?: string[];
|
|
364
|
-
teamId?: string;
|
|
365
|
-
/** App-defined dimensions (branch, project, region) read via `getScopeContext`. */
|
|
366
|
-
context?: Record<string, string>;
|
|
367
|
-
/**
|
|
368
|
-
* Elevated (platform-admin) scope. The value is the `elevatedBy` audit string
|
|
369
|
-
* arc requires — an elevated scope must record who granted it. `true` is
|
|
370
|
-
* shorthand for `'test'`.
|
|
371
|
-
*
|
|
372
|
-
* An elevated scope carries no roles: elevation is a different kind of actor,
|
|
373
|
-
* not a role. A test needing a role gate AND elevation wants `member`.
|
|
374
|
-
*/
|
|
375
|
-
elevated?: string | boolean;
|
|
376
|
-
}
|
|
377
|
-
/**
|
|
378
|
-
* Build the headers that make an injected request act as `actor`.
|
|
379
|
-
*
|
|
380
|
-
* A string is shorthand for a single role. `null` means "stay public", so a test
|
|
381
|
-
* can prove an endpoint is reachable anonymously.
|
|
382
|
-
*
|
|
383
|
-
* @example
|
|
384
|
-
* ```ts
|
|
385
|
-
* t.app.inject({ method: 'GET', url: '/pos/shifts/current',
|
|
386
|
-
* headers: testActorHeaders('manager', ORG) });
|
|
387
|
-
* ```
|
|
388
|
-
*/
|
|
389
|
-
declare function testActorHeaders(actor: TestActor | string | null, organizationId?: string): Record<string, string>;
|
|
390
|
-
/**
|
|
391
|
-
* Turn a spec into a `RequestScope`.
|
|
392
|
-
*
|
|
393
|
-
* `orgRoles` defaults to `roles`: a test that says "manager" means it at both
|
|
394
|
-
* levels, and making the caller repeat itself only produces tests that pass a
|
|
395
|
-
* global gate and mysteriously fail an org one.
|
|
396
|
-
*/
|
|
397
|
-
declare function scopeFromTestActor(spec: TestActor): RequestScope;
|
|
398
|
-
/**
|
|
399
|
-
* Build the `auth` option that makes the test actor arc's authenticator.
|
|
400
|
-
*
|
|
401
|
-
* It must be an authenticator, not a hook. Fastify encapsulates plugins and
|
|
402
|
-
* modules register DURING `createApp`, so a hook added to the root instance
|
|
403
|
-
* afterwards never runs for their routes — every request still resolves as
|
|
404
|
-
* public and every role gate still answers 401, which reads exactly like a
|
|
405
|
-
* broken authorization rule in the code under test. Registering as
|
|
406
|
-
* `auth: { type: 'authenticator' }` puts the scope where arc's own auth would,
|
|
407
|
-
* at the phase arc expects, so tenant filtering and permission checks behave
|
|
408
|
-
* identically to production.
|
|
409
|
-
*
|
|
410
|
-
* `defaultActor` applies to requests carrying no header. A malformed header
|
|
411
|
-
* REJECTS rather than falling back to public — a test that meant to be an admin
|
|
412
|
-
* and got quietly demoted is the most expensive way to fail.
|
|
413
|
-
*/
|
|
414
|
-
declare function testActorAuth(defaultActor?: TestActor): {
|
|
415
|
-
type: "authenticator";
|
|
416
|
-
authenticate: (request: unknown) => Promise<void>;
|
|
417
|
-
};
|
|
418
|
-
//#endregion
|
|
419
|
-
//#region src/testing/bootModuleApp.d.ts
|
|
420
|
-
/** Handed to a modules factory — the in-memory DB is live at call time. */
|
|
421
|
-
/**
|
|
422
|
-
* A provisioned test database — what the `database` seam yields. Arc
|
|
423
|
-
* core never names a driver: kits ship factories (`mongoMemoryDatabase`
|
|
424
|
-
* is the built-in default; a sqlitekit/pgkit testkit ships its own) and
|
|
425
|
-
* the connection flows through as an opaque generic.
|
|
426
|
-
*/
|
|
427
|
-
interface TestDatabase<TConn = unknown> {
|
|
428
|
-
/** Connection string, when the backend has one (informational). */
|
|
429
|
-
uri: string;
|
|
430
|
-
/** Driver connection handle passed to the modules factory. */
|
|
431
|
-
connection: TConn;
|
|
432
|
-
/** Stop/disconnect everything this factory started. MUST be idempotent-safe to call once. */
|
|
433
|
-
teardown(): Promise<void>;
|
|
434
|
-
}
|
|
435
|
-
/** The DB-provisioning seam — `bootModuleApp({ database })`. */
|
|
436
|
-
type TestDatabaseFactory<TConn = unknown> = (opts: {
|
|
437
|
-
replset?: boolean;
|
|
438
|
-
}) => Promise<TestDatabase<TConn>>;
|
|
439
|
-
interface TestkitContext<TConn = unknown> {
|
|
440
|
-
/** The provisioned database's connection string. */
|
|
441
|
-
uri: string;
|
|
442
|
-
/**
|
|
443
|
-
* Driver connection handle (the default factory yields mongoose's
|
|
444
|
-
* DEFAULT connection). Generic so DB-typed wrappers assert the driver
|
|
445
|
-
* type ONCE: `bootModuleApp<Connection>(...)`. Arc core stays DB-agnostic.
|
|
446
|
-
*/
|
|
447
|
-
connection: TConn;
|
|
448
|
-
}
|
|
449
|
-
type BootModulesInput<TConn = unknown> = ArcModuleInput | readonly ArcModuleInput[] | ((ctx: TestkitContext<TConn>) => ArcModuleInput | readonly ArcModuleInput[] | Promise<ArcModuleInput | readonly ArcModuleInput[]>);
|
|
450
|
-
interface BootModuleAppOptions<TConn = unknown> {
|
|
451
|
-
/**
|
|
452
|
-
* DB provisioner. Default: `mongoMemoryDatabase` (in-memory MongoDB —
|
|
453
|
-
* lazy devDep imports, nothing Mongo touches arc's runtime). Kits for
|
|
454
|
-
* other stores inject their own factory here; the rest of the harness
|
|
455
|
-
* (module resolution, app boot, teardown ordering) is DB-agnostic.
|
|
456
|
-
*/
|
|
457
|
-
database?: TestDatabaseFactory<TConn>;
|
|
458
|
-
/** Single-node replica set (transactions). Default: standalone. Passed to the database factory. */
|
|
459
|
-
replset?: boolean;
|
|
460
|
-
/**
|
|
461
|
-
* Extra `createApp` options merged over the testing defaults
|
|
462
|
-
* (`preset: 'testing'`, `auth: false`, `sensible: false` — utility
|
|
463
|
-
* plugins stay off so the testkit is dependency-light; re-enable per
|
|
464
|
-
* boot when a module genuinely exercises one).
|
|
465
|
-
*/
|
|
466
|
-
app?: Partial<CreateAppOptions>;
|
|
467
|
-
/**
|
|
468
|
-
* Default actor for every injected request that carries no `x-test-actor` header.
|
|
469
|
-
*
|
|
470
|
-
* The harness boots with `auth: false`, so without this every request is
|
|
471
|
-
* `PUBLIC_SCOPE` and role-gated routes answer 401 — correct, but it left tests with
|
|
472
|
-
* no supported way to be somebody. See `testActor.ts` for why the seam lives in the
|
|
473
|
-
* testing entrypoint and can never be reached from production.
|
|
474
|
-
*/
|
|
475
|
-
actor?: TestActor;
|
|
476
|
-
}
|
|
477
|
-
interface ModuleTestApp<TConn = unknown> {
|
|
478
|
-
app: FastifyInstance;
|
|
479
|
-
/** The provisioned database's connection string. */
|
|
480
|
-
uri: string;
|
|
481
|
-
/** The mongoose `Connection` handed to the modules factory. */
|
|
482
|
-
connection: TConn;
|
|
483
|
-
/**
|
|
484
|
-
* Typed module-export accessor — `t.exports<CatalogEngine>('catalog')`
|
|
485
|
-
* instead of reaching through `(t.app as ...).arc.modules.catalog`.
|
|
486
|
-
* Delegates to `getModuleExports` (throws with the registered-module
|
|
487
|
-
* list when the name is unknown — same contract hosts get).
|
|
488
|
-
*/
|
|
489
|
-
exports<TExports = unknown>(name: string): TExports;
|
|
490
|
-
/** Close app → disconnect mongoose → stop the in-memory server. Idempotent. */
|
|
491
|
-
close(): Promise<void>;
|
|
492
|
-
}
|
|
493
|
-
/**
|
|
494
|
-
* The built-in DB factory: in-memory MongoDB via lazy devDep imports.
|
|
495
|
-
* Everything Mongo-specific about the harness lives HERE — the harness
|
|
496
|
-
* itself is driver-blind and any kit can replace this via `database`.
|
|
497
|
-
*/
|
|
498
|
-
declare function mongoMemoryDatabase(opts: {
|
|
499
|
-
replset?: boolean;
|
|
500
|
-
}): Promise<TestDatabase<unknown>>;
|
|
501
|
-
declare function bootModuleApp<TConn = unknown>(modules: BootModulesInput<TConn>, options?: BootModuleAppOptions<TConn>): Promise<ModuleTestApp<TConn>>;
|
|
516
|
+
export declare function setupBetterAuthTestApp(input: SetupBetterAuthTestAppInput): Promise<SetupBetterAuthTestAppResult>;
|
|
502
517
|
//#endregion
|
|
503
518
|
//#region src/testing/fixtures.d.ts
|
|
504
|
-
type FixtureFactory<T extends
|
|
519
|
+
type FixtureFactory<T extends object = AnyRecord> = (data: Partial<T>) => Promise<T>;
|
|
505
520
|
/** Delete hook invoked by `clear()` for records that were created through a factory. */
|
|
506
|
-
type FixtureDestroyer<T extends
|
|
507
|
-
interface FixtureRegistration<T extends
|
|
521
|
+
type FixtureDestroyer<T extends object = AnyRecord> = (record: T) => Promise<void>;
|
|
522
|
+
interface FixtureRegistration<T extends object = AnyRecord> {
|
|
508
523
|
create: FixtureFactory<T>;
|
|
509
524
|
/** Optional cleanup. Defaults to a no-op; adapters that support deletion should provide one. */
|
|
510
525
|
destroy?: FixtureDestroyer<T>;
|
|
511
526
|
}
|
|
512
527
|
interface TestFixtures {
|
|
513
528
|
/** Register a named factory. Later calls replace the earlier registration. */
|
|
514
|
-
register<T extends
|
|
529
|
+
register<T extends object = AnyRecord>(name: string, factoryOrRegistration: FixtureFactory<T> | FixtureRegistration<T>): void;
|
|
515
530
|
/** Create one record through the named factory. Tracked for cleanup. */
|
|
516
|
-
create<T extends
|
|
531
|
+
create<T extends object = AnyRecord>(name: string, data?: Partial<T>): Promise<T>;
|
|
517
532
|
/** Create many records with a shared template. Tracked for cleanup. */
|
|
518
|
-
createMany<T extends
|
|
533
|
+
createMany<T extends object = AnyRecord>(name: string, count: number, template?: Partial<T>): Promise<T[]>;
|
|
519
534
|
/**
|
|
520
535
|
* Run every registered `destroy` hook over the records this instance
|
|
521
536
|
* created, then forget them. Safe to call multiple times (idempotent).
|
|
@@ -524,11 +539,11 @@ interface TestFixtures {
|
|
|
524
539
|
*/
|
|
525
540
|
clear(): Promise<void>;
|
|
526
541
|
/** All records ever created by a given factory name (read-only snapshot). */
|
|
527
|
-
all<T extends
|
|
542
|
+
all<T extends object = AnyRecord>(name: string): readonly T[];
|
|
528
543
|
/** Registered factory names. */
|
|
529
544
|
readonly names: readonly string[];
|
|
530
545
|
}
|
|
531
|
-
declare function createTestFixtures(): TestFixtures;
|
|
546
|
+
export declare function createTestFixtures(): TestFixtures;
|
|
532
547
|
//#endregion
|
|
533
548
|
//#region src/testing/HttpTestHarness.d.ts
|
|
534
549
|
interface HttpTestHarnessOptions<T = unknown> {
|
|
@@ -548,7 +563,7 @@ interface HttpTestHarnessOptions<T = unknown> {
|
|
|
548
563
|
apiPrefix?: string;
|
|
549
564
|
}
|
|
550
565
|
type OptionsOrGetter<T> = HttpTestHarnessOptions<T> | (() => HttpTestHarnessOptions<T>);
|
|
551
|
-
declare class HttpTestHarness<T = unknown> {
|
|
566
|
+
export declare class HttpTestHarness<T = unknown> {
|
|
552
567
|
private resource;
|
|
553
568
|
private optionsOrGetter;
|
|
554
569
|
private enabledRoutes;
|
|
@@ -566,7 +581,7 @@ declare class HttpTestHarness<T = unknown> {
|
|
|
566
581
|
* Create an HTTP test harness. `optionsOrGetter` may be a plain object
|
|
567
582
|
* (for eager app setup) or a getter function (for async `beforeAll` apps).
|
|
568
583
|
*/
|
|
569
|
-
declare function createHttpTestHarness<T = unknown>(resource: ResourceDefinition<unknown>, optionsOrGetter: HttpTestHarnessOptions<T> | (() => HttpTestHarnessOptions<T>)): HttpTestHarness<T>;
|
|
584
|
+
export declare function createHttpTestHarness<T = unknown>(resource: ResourceDefinition<unknown>, optionsOrGetter: HttpTestHarnessOptions<T> | (() => HttpTestHarnessOptions<T>)): HttpTestHarness<T>;
|
|
570
585
|
//#endregion
|
|
571
586
|
//#region src/testing/mocks.d.ts
|
|
572
587
|
/**
|
|
@@ -591,11 +606,11 @@ interface MockRepository<T> extends StandardRepo<T> {
|
|
|
591
606
|
*
|
|
592
607
|
* await mockRepo.getById('1'); // Returns mocked product
|
|
593
608
|
*/
|
|
594
|
-
declare function createMockRepository<T extends
|
|
609
|
+
export declare function createMockRepository<T extends object = AnyRecord>(overrides?: Partial<MockRepository<T>>): MockRepository<T>;
|
|
595
610
|
/**
|
|
596
611
|
* Create a mock user for authentication testing
|
|
597
612
|
*/
|
|
598
|
-
declare function createMockUser(overrides?: Partial<AnyRecord>): {
|
|
613
|
+
export declare function createMockUser(overrides?: Partial<AnyRecord>): {
|
|
599
614
|
_id: string;
|
|
600
615
|
id: string;
|
|
601
616
|
email: string;
|
|
@@ -605,11 +620,11 @@ declare function createMockUser(overrides?: Partial<AnyRecord>): {
|
|
|
605
620
|
/**
|
|
606
621
|
* Create a mock Fastify request
|
|
607
622
|
*/
|
|
608
|
-
declare function createMockRequest(overrides?: Partial<AnyRecord>): unknown;
|
|
623
|
+
export declare function createMockRequest(overrides?: Partial<AnyRecord>): unknown;
|
|
609
624
|
/**
|
|
610
625
|
* Create a mock Fastify reply
|
|
611
626
|
*/
|
|
612
|
-
declare function createMockReply(): unknown;
|
|
627
|
+
export declare function createMockReply(): unknown;
|
|
613
628
|
/**
|
|
614
629
|
* Create a mock controller for testing.
|
|
615
630
|
*
|
|
@@ -625,7 +640,7 @@ declare function createMockReply(): unknown;
|
|
|
625
640
|
* arguments) while naming only `vitest`, which arc does declare. Same shape
|
|
626
641
|
* `MockRepository` above uses.
|
|
627
642
|
*/
|
|
628
|
-
declare function createMockController(repository: StandardRepo<AnyRecord>): {
|
|
643
|
+
export declare function createMockController(repository: StandardRepo<AnyRecord>): {
|
|
629
644
|
repository: StandardRepo<AnyRecord>;
|
|
630
645
|
list: Mock;
|
|
631
646
|
get: Mock;
|
|
@@ -646,7 +661,7 @@ declare function createMockController(repository: StandardRepo<AnyRecord>): {
|
|
|
646
661
|
* const product = productFactory.build();
|
|
647
662
|
* const products = productFactory.buildMany(10);
|
|
648
663
|
*/
|
|
649
|
-
declare function createDataFactory<T extends AnyRecord>(template: Record<keyof T, (index: number) => unknown>): {
|
|
664
|
+
export declare function createDataFactory<T extends AnyRecord>(template: Record<keyof T, (index: number) => unknown>): {
|
|
650
665
|
build(overrides?: Partial<T>): T;
|
|
651
666
|
buildMany(count: number, overrides?: Partial<T>): T[];
|
|
652
667
|
reset(): void;
|
|
@@ -656,7 +671,7 @@ declare function createDataFactory<T extends AnyRecord>(template: Record<keyof T
|
|
|
656
671
|
*
|
|
657
672
|
* Useful for testing side effects without full mocking
|
|
658
673
|
*/
|
|
659
|
-
declare function createSpy<T extends (...args: unknown[]) => unknown>(_name?: string): Mock<T> & {
|
|
674
|
+
export declare function createSpy<T extends (...args: unknown[]) => unknown>(_name?: string): Mock<T> & {
|
|
660
675
|
getCalls(): unknown[][];
|
|
661
676
|
getLastCall(): unknown[];
|
|
662
677
|
};
|
|
@@ -677,7 +692,7 @@ declare function createSpy<T extends (...args: unknown[]) => unknown>(_name?: st
|
|
|
677
692
|
* @example
|
|
678
693
|
* await waitFor(() => runs >= 3, { label: "3 scheduler ticks" });
|
|
679
694
|
*/
|
|
680
|
-
declare function waitFor(condition: () => boolean | Promise<boolean>, options?: {
|
|
695
|
+
export declare function waitFor(condition: () => boolean | Promise<boolean>, options?: {
|
|
681
696
|
timeout?: number;
|
|
682
697
|
interval?: number;
|
|
683
698
|
label?: string;
|
|
@@ -685,7 +700,7 @@ declare function waitFor(condition: () => boolean | Promise<boolean>, options?:
|
|
|
685
700
|
/**
|
|
686
701
|
* Create a test timer that can be controlled
|
|
687
702
|
*/
|
|
688
|
-
declare function createTestTimer(): {
|
|
703
|
+
export declare function createTestTimer(): {
|
|
689
704
|
now: () => number;
|
|
690
705
|
advance: (ms: number) => void;
|
|
691
706
|
set: (timestamp: number) => void;
|
|
@@ -695,7 +710,7 @@ declare function createTestTimer(): {
|
|
|
695
710
|
//#region src/testing/moduleSetup.d.ts
|
|
696
711
|
interface TestModuleSetup {
|
|
697
712
|
/** Pass this as the second argument to `bootstrap` / `plugins` / `afterResources`. */
|
|
698
|
-
readonly context: ModuleSetupContext
|
|
713
|
+
readonly context: ModuleSetupContext<PortName, PortName>;
|
|
699
714
|
/**
|
|
700
715
|
* Disposers the module registered, in REGISTRATION order (`dispose()` runs
|
|
701
716
|
* them backwards). Assert on `.length` to prove a phase registered teardown
|
|
@@ -712,7 +727,10 @@ interface TestModuleSetup {
|
|
|
712
727
|
*/
|
|
713
728
|
dispose(): Promise<void>;
|
|
714
729
|
}
|
|
715
|
-
declare function createTestModuleSetup(
|
|
730
|
+
export declare function createTestModuleSetup(options?: {
|
|
731
|
+
/** The `context.ports` the phases see — supply what the module declares. */
|
|
732
|
+
readonly ports?: ArcPorts;
|
|
733
|
+
}): TestModuleSetup;
|
|
716
734
|
//#endregion
|
|
717
735
|
//#region src/testing/scopeRoleGate.d.ts
|
|
718
736
|
/**
|
|
@@ -737,7 +755,7 @@ declare function createTestModuleSetup(): TestModuleSetup;
|
|
|
737
755
|
* filters by tenant, so a gate that waves a tenant-less request through is how a
|
|
738
756
|
* green test reads another org's rows.
|
|
739
757
|
*/
|
|
740
|
-
declare function scopeRoleGate(...allowed: string[]): PermissionCheck;
|
|
758
|
+
export declare function scopeRoleGate(...allowed: string[]): PermissionCheck;
|
|
741
759
|
//#endregion
|
|
742
760
|
//#region src/testing/testApp.d.ts
|
|
743
761
|
type DbMode = "in-memory" | {
|
|
@@ -808,12 +826,12 @@ interface TestAppContext {
|
|
|
808
826
|
*/
|
|
809
827
|
close(): Promise<void>;
|
|
810
828
|
}
|
|
811
|
-
declare function createTestApp(options?: CreateTestAppOptions): Promise<TestAppContext>;
|
|
829
|
+
export declare function createTestApp(options?: CreateTestAppOptions): Promise<TestAppContext>;
|
|
812
830
|
/**
|
|
813
831
|
* Minimal Fastify instance — no arc plugins, no auth, no db. Use when a test
|
|
814
832
|
* needs bare Fastify (e.g. plugin unit tests that manually register their
|
|
815
833
|
* dependencies).
|
|
816
834
|
*/
|
|
817
|
-
declare function createMinimalTestApp(options?: FastifyServerOptions): FastifyInstance;
|
|
835
|
+
export declare function createMinimalTestApp(options?: FastifyServerOptions): FastifyInstance;
|
|
818
836
|
//#endregion
|
|
819
|
-
export { type ArcAssertion, type ArcResponseLike, type AuthMode, type AuthResponse, type AuthorizationConformance, type BetterAuthTestHelpers, type BetterAuthTestHelpersOptions, type BetterAuthTestUser, type BootModuleAppOptions, type BootModulesInput, type CreateOrgInput, type CreateTestAppOptions, type DbMode, type FixtureDestroyer, type FixtureFactory, type FixtureRegistration,
|
|
837
|
+
export { type ArcAssertion, type ArcResponseLike, type AuthMode, type AuthResponse, type AuthorizationConformance, type BetterAuthTestHelpers, type BetterAuthTestHelpersOptions, type BetterAuthTestUser, type BootModuleAppOptions, type BootModulesInput, type CreateOrgInput, type CreateTestAppOptions, type DbMode, type FixtureDestroyer, type FixtureFactory, type FixtureRegistration, type HttpTestHarnessOptions, type MockRepository, type ModuleBootsAloneOptions, type ModuleBootsAloneResult, type ModuleTestApp, type OrgResponse, type RoleConfig, type SetupBetterAuthTestAppInput, type SetupBetterAuthTestAppResult, type SignInInput, type SignUpInput, type StorageContractSetup, type StorageContractSetupResult, type SurfaceObservation, type TestActor, type TestAppContext, type TestAuthProvider, type TestAuthSession, type TestDatabase, type TestDatabaseFactory, type TestFixtures, type TestModuleSetup, type TestkitContext, runStorageContract };
|