@classytic/arc 2.16.0 → 2.16.1
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-DlCCTIxJ.mjs → BaseController-Vk8I7C0x.mjs} +1 -1
- package/dist/{QueryCache-SvmT_9ti.d.mts → QueryCache-8YmAQ-zW.d.mts} +1 -1
- package/dist/{ResourceRegistry-f48hFk3m.mjs → ResourceRegistry-CzSzVK1m.mjs} +3 -0
- package/dist/audit/index.d.mts +1 -1
- package/dist/auth/index.d.mts +4 -4
- package/dist/auth/redis-session.d.mts +1 -1
- package/dist/{buildHandler-BZX6zzDM.mjs → buildHandler-C_SkBNF3.mjs} +6 -4
- package/dist/cache/index.d.mts +3 -3
- 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.d.mts +1 -1
- package/dist/cli/commands/generate.mjs +1 -1
- package/dist/cli/commands/init.d.mts +1 -1
- package/dist/cli/commands/init.mjs +1 -1
- package/dist/cli/commands/introspect.mjs +1 -1
- package/dist/cli/index.d.mts +2 -2
- package/dist/cli/index.mjs +2 -2
- package/dist/core/index.d.mts +2 -2
- package/dist/core/index.mjs +3 -3
- package/dist/{core-DBJ_j6rX.mjs → core-wKeGXn38.mjs} +5 -5
- package/dist/{createActionRouter-DUpN3Dd1.mjs → createActionRouter-eiOFtnC3.mjs} +2 -2
- package/dist/{createAggregationRouter-Dq-TUCuY.mjs → createAggregationRouter-C4unhBnV.mjs} +3 -3
- package/dist/{createApp-DNccuhyI.mjs → createApp-DdPBtmzp.mjs} +8 -8
- package/dist/{defineEvent-DRwY0fYm.mjs → defineEvent-NPKUJRt8.mjs} +1 -1
- package/dist/docs/index.d.mts +2 -2
- package/dist/docs/index.mjs +1 -1
- package/dist/{eventPlugin-C2cGqtRO.mjs → eventPlugin-CnJCUyM0.mjs} +1 -1
- package/dist/{eventPlugin-CtHC_av1.d.mts → eventPlugin-DjEx_J3j.d.mts} +1 -1
- package/dist/events/index.d.mts +3 -3
- package/dist/events/index.mjs +5 -5
- 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 +2 -2
- package/dist/factory/index.mjs +4 -3
- package/dist/fastify-augmentation-CJm0vh-l.d.mts +42 -0
- package/dist/{fields-Anj0xdih.d.mts → fields-DqZLp5d6.d.mts} +1 -1
- package/dist/hooks/index.d.mts +1 -1
- package/dist/idempotency/index.d.mts +2 -2
- package/dist/idempotency/index.mjs +1 -1
- package/dist/idempotency/redis.d.mts +1 -1
- package/dist/{index-3oIimXQn.d.mts → index-3L-adFJO.d.mts} +3 -3
- package/dist/{index-B-ulKx5P.d.mts → index-CC_pgZjY.d.mts} +36 -16
- package/dist/{index-CkW0flkU.d.mts → index-DBDgy6Hw.d.mts} +79 -7
- package/dist/index.d.mts +5 -5
- package/dist/index.mjs +4 -4
- 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 +4 -4
- 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/websocket-redis.d.mts +1 -1
- package/dist/integrations/websocket.d.mts +1 -1
- package/dist/{loadResourcesFromEntry-BLMEI2Xa.mjs → loadResourcesFromEntry-DCjYMgfC.mjs} +1 -1
- package/dist/{mcpPlugin-7vGV51ED.mjs → mcpPlugin-Dbgz9_Rj.mjs} +5 -5
- package/dist/middleware/index.d.mts +1 -1
- package/dist/{openapi-34T9yNwd.mjs → openapi-BRnd3pT7.mjs} +36 -9
- package/dist/permissions/index.d.mts +2 -2
- package/dist/pipeline/index.d.mts +1 -1
- package/dist/plugins/index.d.mts +5 -59
- package/dist/plugins/index.mjs +7 -7
- package/dist/plugins/tracing-entry.d.mts +1 -1
- package/dist/plugins/tracing-entry.mjs +1 -1
- package/dist/preloadResources-BOXzPhKU.mjs +45 -0
- package/dist/presets/filesUpload.d.mts +4 -4
- package/dist/presets/index.d.mts +1 -1
- package/dist/presets/multiTenant.d.mts +1 -1
- package/dist/presets/search.d.mts +2 -2
- package/dist/{queryCachePlugin-Biqzfbi5.d.mts → queryCachePlugin-Do4P_WBC.d.mts} +2 -2
- package/dist/{redis-Cyzrz6SX.d.mts → redis-cpqVb85w.d.mts} +1 -1
- package/dist/{redis-stream-DT-YjzrB.d.mts → redis-stream-BuiAS3aE.d.mts} +1 -1
- package/dist/registry/index.d.mts +30 -8
- package/dist/registry/index.mjs +2 -2
- package/dist/{registry-BBE23CDj.mjs → registry-BrlHkrRS.mjs} +14 -8
- package/dist/{routerShared-CZV5aabX.mjs → routerShared-ClV4cCaa.mjs} +37 -13
- package/dist/scope/index.d.mts +2 -2
- package/dist/testing/index.d.mts +2 -25
- package/dist/testing/index.mjs +2 -45
- package/dist/testing/storageContract.d.mts +1 -1
- package/dist/types/index.d.mts +4 -4
- package/dist/types/storage.d.mts +1 -1
- package/dist/{types-BsJMEQ4D.d.mts → types-BD0BCdf6.d.mts} +1 -1
- package/dist/{types-D-fYtKjb.d.mts → types-Dw--SyTq.d.mts} +34 -11
- package/dist/utils/index.d.mts +5 -4
- package/dist/utils/index.mjs +1 -1
- package/dist/{utils-DC5ycPfr.mjs → utils-DPXZnZUx.mjs} +69 -1
- package/dist/{validate-By96rH0r.mjs → validate-DFIP2VrM.mjs} +65 -3
- package/dist/{versioning-ZwX9tmbS.d.mts → versioning-5H4930tj.d.mts} +1 -1
- package/package.json +3 -3
- /package/dist/{EventTransport-C-2oAHtw.d.mts → EventTransport-B1GFiYUy.d.mts} +0 -0
- /package/dist/{EventTransport-Hxvv5QQz.mjs → EventTransport-ClEDfiMS.mjs} +0 -0
- /package/dist/{caching-TeHE8G-v.mjs → caching-8MfrrUYU.mjs} +0 -0
- /package/dist/{elevation-0YBpa663.d.mts → elevation-DvwtjDwu.d.mts} +0 -0
- /package/dist/{errorHandler-DpoXQHZ9.mjs → errorHandler-DNPzqaTT.mjs} +0 -0
- /package/dist/{errorHandler-mHuyWzZE.d.mts → errorHandler-DuqTqeqn.d.mts} +0 -0
- /package/dist/{errors-C1lX_jlm.d.mts → errors-4ZloYFvm.d.mts} +0 -0
- /package/dist/{externalPaths-DFg-2KTp.d.mts → externalPaths-ClykOQqa.d.mts} +0 -0
- /package/dist/{generate-CYac-OLv.mjs → generate-CcM24hoq.mjs} +0 -0
- /package/dist/{generate-BWFwgcCM.d.mts → generate-cRnsafMS.d.mts} +0 -0
- /package/dist/{init-Dv71MsJr.d.mts → init-D-vrTZ1G.d.mts} +0 -0
- /package/dist/{init-HDvoO9L5.mjs → init-DYzfniuX.mjs} +0 -0
- /package/dist/{interface-CH0OQudo.d.mts → interface-BVkZsvEe.d.mts} +0 -0
- /package/dist/{interface-NwJ_qPlY.d.mts → interface-DoE6UoC2.d.mts} +0 -0
- /package/dist/{loadResources-ChQEj8ih.mjs → loadResources-fol6JuvW.mjs} +0 -0
- /package/dist/{metrics-TuOmguhi.mjs → metrics-B-PU4-Yu.mjs} +0 -0
- /package/dist/{replyHelpers-C-gD32oF.mjs → replyHelpers-boS5Rx26.mjs} +0 -0
- /package/dist/{schemaIR-Ctc89DSn.mjs → schemaIR-DAOvBWgT.mjs} +0 -0
- /package/dist/{sessionManager-BqFegc0W.d.mts → sessionManager-DlmaHUAl.d.mts} +0 -0
- /package/dist/{sse-BY6sTy4P.mjs → sse-jh5OqFjR.mjs} +0 -0
- /package/dist/{storage-D2KZJAmn.d.mts → storage-HcAgP5Ni.d.mts} +0 -0
- /package/dist/{store-helpers-B0sunfZZ.mjs → store-helpers-5JgaxieH.mjs} +0 -0
- /package/dist/{tracing-Dm8n7Cnn.d.mts → tracing-bRqqUxFO.d.mts} +0 -0
- /package/dist/{types-DVfpSfx2.d.mts → types-CfapW2t8.d.mts} +0 -0
- /package/dist/{versioning-B6mimogM.mjs → versioning-CuIwUQZ2.mjs} +0 -0
- /package/dist/{websocket-BkjeGZRn.d.mts → websocket-BJ0w-3Dt.d.mts} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { rt as PresetResult } from "../index-
|
|
2
|
-
import { i as RequestScope } from "../types-
|
|
3
|
-
import { c as PermissionCheck } from "../fields-
|
|
4
|
-
import { a as StorageReadResult, i as StorageReadRange, n as StorageContext, o as StorageUploadInput, r as StorageFile, t as Storage } from "../storage-
|
|
1
|
+
import { rt as PresetResult } from "../index-DBDgy6Hw.mjs";
|
|
2
|
+
import { i as RequestScope } from "../types-CfapW2t8.mjs";
|
|
3
|
+
import { c as PermissionCheck } from "../fields-DqZLp5d6.mjs";
|
|
4
|
+
import { a as StorageReadResult, i as StorageReadRange, n as StorageContext, o as StorageUploadInput, r as StorageFile, t as Storage } from "../storage-HcAgP5Ni.mjs";
|
|
5
5
|
|
|
6
6
|
//#region src/presets/filesUpload.d.ts
|
|
7
7
|
interface FilesUploadPresetRoutes {
|
package/dist/presets/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Kt as AnyRecord, bt as IRequestContext, d as PaginationResult, rt as PresetResult, st as ResourceConfig, yt as IControllerResponse } from "../index-
|
|
1
|
+
import { Kt as AnyRecord, bt as IRequestContext, d as PaginationResult, rt as PresetResult, st as ResourceConfig, yt as IControllerResponse } from "../index-DBDgy6Hw.mjs";
|
|
2
2
|
import { FilesUploadPresetOptions, FilesUploadPresetPermissions, FilesUploadPresetRoutes, filesUploadPreset } from "./filesUpload.mjs";
|
|
3
3
|
import { MultiTenantOptions, TenantFieldSpec, multiTenantPreset } from "./multiTenant.mjs";
|
|
4
4
|
import { SearchHandler, SearchPresetOptions, SearchRouteConfig, searchPreset } from "./search.mjs";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { dt as RouteDefinition, ft as RouteMcpConfig, ht as ControllerHandler, rt as PresetResult } from "../index-
|
|
2
|
-
import { c as PermissionCheck } from "../fields-
|
|
1
|
+
import { dt as RouteDefinition, ft as RouteMcpConfig, ht as ControllerHandler, rt as PresetResult } from "../index-DBDgy6Hw.mjs";
|
|
2
|
+
import { c as PermissionCheck } from "../fields-DqZLp5d6.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/presets/search.d.ts
|
|
5
5
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { r as CacheStore } from "./interface-
|
|
2
|
-
import { i as QueryCache } from "./QueryCache-
|
|
1
|
+
import { r as CacheStore } from "./interface-BVkZsvEe.mjs";
|
|
2
|
+
import { i as QueryCache } from "./QueryCache-8YmAQ-zW.mjs";
|
|
3
3
|
import { FastifyPluginAsync } from "fastify";
|
|
4
4
|
|
|
5
5
|
//#region src/cache/queryCachePlugin.d.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as EventTransport, i as EventLogger, n as DomainEvent, r as EventHandler } from "./EventTransport-
|
|
1
|
+
import { a as EventTransport, i as EventLogger, n as DomainEvent, r as EventHandler } from "./EventTransport-B1GFiYUy.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/events/transports/redis-stream.d.ts
|
|
4
4
|
interface RedisStreamLike {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { J as CrudRouteKey, R as RegisterOptions, V as ResourceDefinition, at as ResolvedTenantPurge, k as IntrospectionPluginOptions, p as RegistryEntry, z as ResourceRegistry } from "../index-
|
|
1
|
+
import { J as CrudRouteKey, R as RegisterOptions, V as ResourceDefinition, at as ResolvedTenantPurge, k as IntrospectionPluginOptions, p as RegistryEntry, z as ResourceRegistry } from "../index-DBDgy6Hw.mjs";
|
|
2
2
|
import { FastifyPluginAsync } from "fastify";
|
|
3
3
|
import { TenantPurgeProgress, TenantPurgeStrategy } from "@classytic/repo-core/repository";
|
|
4
4
|
|
|
@@ -20,7 +20,14 @@ interface AssertNoTenantDataOptions {
|
|
|
20
20
|
interface TenantDataLeak {
|
|
21
21
|
readonly resource: string;
|
|
22
22
|
readonly tenantField: string;
|
|
23
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Full `TenantPurgeStrategy` discriminated union — not just `.type`.
|
|
25
|
+
* `anonymize` carries the field map; `custom` carries the handler
|
|
26
|
+
* descriptor; auditors get the actionable signal without re-resolving
|
|
27
|
+
* the resource definition. Narrow on `.strategy.type` for typed
|
|
28
|
+
* access.
|
|
29
|
+
*/
|
|
30
|
+
readonly strategy: TenantPurgeStrategy;
|
|
24
31
|
readonly expected: number;
|
|
25
32
|
readonly actual: number;
|
|
26
33
|
readonly reason?: string;
|
|
@@ -64,7 +71,14 @@ declare function assertNoTenantData(registry: ResourceRegistry, options: AssertN
|
|
|
64
71
|
interface PurgeResourceOutcome {
|
|
65
72
|
readonly resource: string;
|
|
66
73
|
readonly tenantField: string;
|
|
67
|
-
|
|
74
|
+
/**
|
|
75
|
+
* Full `TenantPurgeStrategy` discriminated union. Audit consumers
|
|
76
|
+
* narrow on `.strategy.type` for typed access — `skip` carries the
|
|
77
|
+
* mandatory `reason`, `anonymize` carries the field map, `custom`
|
|
78
|
+
* carries the handler descriptor. Pre-2.17 this was the `.type` tag
|
|
79
|
+
* only, which dropped the audit-critical `reason` field.
|
|
80
|
+
*/
|
|
81
|
+
readonly strategy: TenantPurgeStrategy;
|
|
68
82
|
readonly processed: number;
|
|
69
83
|
readonly ok: boolean;
|
|
70
84
|
readonly path: "purgeByField" | "legacy-deleteMany" | "skipped" | "unsupported";
|
|
@@ -92,11 +106,13 @@ interface CascadeResourceReport {
|
|
|
92
106
|
*/
|
|
93
107
|
readonly deletedCount: number;
|
|
94
108
|
/**
|
|
95
|
-
*
|
|
96
|
-
* `'
|
|
97
|
-
* "did data physically leave the system?".
|
|
109
|
+
* Full `TenantPurgeStrategy` that ran for this resource. Branch on
|
|
110
|
+
* `.strategy.type` (`'hard'` / `'soft'` / `'anonymize'` / `'skip'` /
|
|
111
|
+
* `'custom'`) to answer "did data physically leave the system?". The
|
|
112
|
+
* `skip` variant carries the mandatory `reason`; `anonymize` carries
|
|
113
|
+
* the field map; `custom` carries the handler descriptor.
|
|
98
114
|
*/
|
|
99
|
-
readonly strategy?: TenantPurgeStrategy
|
|
115
|
+
readonly strategy?: TenantPurgeStrategy;
|
|
100
116
|
/**
|
|
101
117
|
* Where the strategy came from — `'declared'` (host wrote
|
|
102
118
|
* `onTenantDelete`) or `'disabled'` (filtered out before reaching
|
|
@@ -221,11 +237,17 @@ declare function getCascadingResources(registry: ResourceRegistry): readonly str
|
|
|
221
237
|
* cascading resource. Use for audit dashboards that answer "what
|
|
222
238
|
* happens to this resource on org-delete?" without grepping the
|
|
223
239
|
* source.
|
|
240
|
+
*
|
|
241
|
+
* **Returns the full `TenantPurgeStrategy` discriminated union**, not
|
|
242
|
+
* just its `type` tag. The `skip` variant carries a required `reason`
|
|
243
|
+
* field — auditors need it to sign off on every "we deliberately don't
|
|
244
|
+
* purge this" entry. Anonymize carries the field map. Custom carries
|
|
245
|
+
* the handler reference. Narrow on `.strategy.type` for typed access.
|
|
224
246
|
*/
|
|
225
247
|
declare function getCascadingResourcesWithMetadata(registry: ResourceRegistry): readonly {
|
|
226
248
|
name: string;
|
|
227
249
|
tenantField: string;
|
|
228
|
-
strategy: TenantPurgeStrategy
|
|
250
|
+
strategy: TenantPurgeStrategy;
|
|
229
251
|
source: ResolvedTenantPurge["source"];
|
|
230
252
|
priority: number;
|
|
231
253
|
}[];
|
package/dist/registry/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as cascadeDeleteForOrganization, c as assertNoTenantData, i as introspectionPlugin_default, n as buildResourceManifestFromRegistry, o as getCascadingResources, r as introspectionPlugin, s as getCascadingResourcesWithMetadata, t as buildResourceManifest } from "../registry-
|
|
2
|
-
import { t as ResourceRegistry } from "../ResourceRegistry-
|
|
1
|
+
import { a as cascadeDeleteForOrganization, c as assertNoTenantData, i as introspectionPlugin_default, n as buildResourceManifestFromRegistry, o as getCascadingResources, r as introspectionPlugin, s as getCascadingResourcesWithMetadata, t as buildResourceManifest } from "../registry-BrlHkrRS.mjs";
|
|
2
|
+
import { t as ResourceRegistry } from "../ResourceRegistry-CzSzVK1m.mjs";
|
|
3
3
|
export { ResourceRegistry, assertNoTenantData, buildResourceManifest, buildResourceManifestFromRegistry, cascadeDeleteForOrganization, getCascadingResources, getCascadingResourcesWithMetadata, introspectionPlugin_default as introspectionPlugin, introspectionPlugin as introspectionPluginFn };
|
|
@@ -59,7 +59,7 @@ async function assertNoTenantData(registry, options) {
|
|
|
59
59
|
if (actual !== expected) leaks.push({
|
|
60
60
|
resource: r.name,
|
|
61
61
|
tenantField,
|
|
62
|
-
strategy
|
|
62
|
+
strategy,
|
|
63
63
|
expected,
|
|
64
64
|
actual
|
|
65
65
|
});
|
|
@@ -88,7 +88,7 @@ async function purgeResource(resourceName, tenantField, organizationId, resolved
|
|
|
88
88
|
if (strategy.type === "skip") return {
|
|
89
89
|
resource: resourceName,
|
|
90
90
|
tenantField,
|
|
91
|
-
strategy
|
|
91
|
+
strategy,
|
|
92
92
|
processed: 0,
|
|
93
93
|
ok: true,
|
|
94
94
|
path: "skipped",
|
|
@@ -103,7 +103,7 @@ async function purgeResource(resourceName, tenantField, organizationId, resolved
|
|
|
103
103
|
return {
|
|
104
104
|
resource: resourceName,
|
|
105
105
|
tenantField,
|
|
106
|
-
strategy
|
|
106
|
+
strategy,
|
|
107
107
|
processed: result.processed,
|
|
108
108
|
ok: result.ok,
|
|
109
109
|
path: "purgeByField",
|
|
@@ -114,7 +114,7 @@ async function purgeResource(resourceName, tenantField, organizationId, resolved
|
|
|
114
114
|
if (strategy.type !== "hard") return {
|
|
115
115
|
resource: resourceName,
|
|
116
116
|
tenantField,
|
|
117
|
-
strategy
|
|
117
|
+
strategy,
|
|
118
118
|
processed: 0,
|
|
119
119
|
ok: false,
|
|
120
120
|
path: "unsupported",
|
|
@@ -127,7 +127,7 @@ async function purgeResource(resourceName, tenantField, organizationId, resolved
|
|
|
127
127
|
if (!op) return {
|
|
128
128
|
resource: resourceName,
|
|
129
129
|
tenantField,
|
|
130
|
-
strategy
|
|
130
|
+
strategy,
|
|
131
131
|
processed: 0,
|
|
132
132
|
ok: false,
|
|
133
133
|
path: "unsupported",
|
|
@@ -142,7 +142,7 @@ async function purgeResource(resourceName, tenantField, organizationId, resolved
|
|
|
142
142
|
return {
|
|
143
143
|
resource: resourceName,
|
|
144
144
|
tenantField,
|
|
145
|
-
strategy
|
|
145
|
+
strategy,
|
|
146
146
|
processed: typeof result === "number" ? result : typeof result?.deletedCount === "number" ? result.deletedCount : typeof result?.count === "number" ? result.count : -1,
|
|
147
147
|
ok: true,
|
|
148
148
|
path: "legacy-deleteMany",
|
|
@@ -152,7 +152,7 @@ async function purgeResource(resourceName, tenantField, organizationId, resolved
|
|
|
152
152
|
return {
|
|
153
153
|
resource: resourceName,
|
|
154
154
|
tenantField,
|
|
155
|
-
strategy
|
|
155
|
+
strategy,
|
|
156
156
|
processed: 0,
|
|
157
157
|
ok: false,
|
|
158
158
|
path: "legacy-deleteMany",
|
|
@@ -178,6 +178,12 @@ function getCascadingResources(registry) {
|
|
|
178
178
|
* cascading resource. Use for audit dashboards that answer "what
|
|
179
179
|
* happens to this resource on org-delete?" without grepping the
|
|
180
180
|
* source.
|
|
181
|
+
*
|
|
182
|
+
* **Returns the full `TenantPurgeStrategy` discriminated union**, not
|
|
183
|
+
* just its `type` tag. The `skip` variant carries a required `reason`
|
|
184
|
+
* field — auditors need it to sign off on every "we deliberately don't
|
|
185
|
+
* purge this" entry. Anonymize carries the field map. Custom carries
|
|
186
|
+
* the handler reference. Narrow on `.strategy.type` for typed access.
|
|
181
187
|
*/
|
|
182
188
|
function getCascadingResourcesWithMetadata(registry) {
|
|
183
189
|
return registry.getAll().filter((r) => isResourceCascading(r)).map((r) => {
|
|
@@ -191,7 +197,7 @@ function getCascadingResourcesWithMetadata(registry) {
|
|
|
191
197
|
return {
|
|
192
198
|
name: r.name,
|
|
193
199
|
tenantField,
|
|
194
|
-
strategy: r0.strategy
|
|
200
|
+
strategy: r0.strategy,
|
|
195
201
|
source: r0.source,
|
|
196
202
|
priority: r0.priority
|
|
197
203
|
};
|
|
@@ -55,9 +55,13 @@ function applyFieldMask(data, fieldMask) {
|
|
|
55
55
|
return data;
|
|
56
56
|
}
|
|
57
57
|
/**
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
58
|
+
* Project `FastifyRequest` into the curated `IRequestContext` shape that
|
|
59
|
+
* arc's controllers receive. This is a developer-facing facade, not a
|
|
60
|
+
* portability boundary — arc is Fastify-only. The projection lifts the
|
|
61
|
+
* fields tenant-scoped controllers reach for (`organizationId`,
|
|
62
|
+
* `teamId`, `scope`, `context`, server accessor) onto a flat, typed
|
|
63
|
+
* surface so handler code doesn't have to dig through Fastify's
|
|
64
|
+
* decorator surface or `req.metadata._scope` internals.
|
|
61
65
|
*/
|
|
62
66
|
function createRequestContext(req) {
|
|
63
67
|
const reqWithExtras = req;
|
|
@@ -145,12 +149,33 @@ function computeFieldCapabilities(fieldPerms, effectiveRoles) {
|
|
|
145
149
|
return caps;
|
|
146
150
|
}
|
|
147
151
|
/**
|
|
148
|
-
* Send IControllerResponse
|
|
152
|
+
* Send a controller's `IControllerResponse` through Fastify's reply.
|
|
153
|
+
*
|
|
154
|
+
* The `IControllerResponse<T>` envelope is arc's internal pipeline
|
|
155
|
+
* contract — it's how custom `status`, `meta`, `headers`, and field
|
|
156
|
+
* permissions thread from a handler through interceptors to the wire
|
|
157
|
+
* without each step having to touch `reply` directly. Not a portability
|
|
158
|
+
* abstraction (arc is Fastify-only); a pipeline-internal one.
|
|
149
159
|
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
160
|
+
* **Auto-envelope of bare returns.** Custom route handlers are
|
|
161
|
+
* expected to return the envelope shape so this function can apply
|
|
162
|
+
* field permissions, attach `fieldCaps`, and flatten paginated lists.
|
|
163
|
+
* A handler that returns raw `T` (array, plain object, primitive) used
|
|
164
|
+
* to silently produce a broken response — `response.data` was
|
|
165
|
+
* `undefined`, the body sent was `undefined`, and any declared
|
|
166
|
+
* `fields:` permission map was bypassed (the leak shape mentora
|
|
167
|
+
* flagged). 2.17 detects bare returns and wraps them into
|
|
168
|
+
* `{ data: response, status: 200 }` before the field-permission
|
|
169
|
+
* pipeline runs, so `fields:` applies to ALL custom routes whether the
|
|
170
|
+
* handler envelopes its return value or not. The envelope shape is
|
|
171
|
+
* still the canonical contract — auto-wrapping is a safety net, not
|
|
172
|
+
* an invitation to drop the envelope.
|
|
152
173
|
*/
|
|
153
174
|
function sendControllerResponse(reply, response, request) {
|
|
175
|
+
if (response === null || typeof response !== "object" || !Object.hasOwn(response, "data")) response = {
|
|
176
|
+
data: response,
|
|
177
|
+
status: 200
|
|
178
|
+
};
|
|
154
179
|
const reqWithExtras = request;
|
|
155
180
|
const fieldMaskConfig = reqWithExtras?.fieldMask;
|
|
156
181
|
const arcMeta = reqWithExtras?.arc;
|
|
@@ -207,18 +232,17 @@ function sendControllerResponse(reply, response, request) {
|
|
|
207
232
|
reply.code(status).send(filteredData);
|
|
208
233
|
}
|
|
209
234
|
/**
|
|
210
|
-
*
|
|
211
|
-
*
|
|
212
|
-
*
|
|
235
|
+
* Bridge an `IController` method (`(ctx: IRequestContext) => Promise<IControllerResponse<T>>`)
|
|
236
|
+
* into a Fastify route handler. Translates between arc's curated request
|
|
237
|
+
* context surface and Fastify's request/reply, and routes the envelope
|
|
238
|
+
* through `sendControllerResponse` so the pipeline applies field
|
|
239
|
+
* permissions, status, and meta uniformly. Internal plumbing, not a
|
|
240
|
+
* portability layer — arc is Fastify-only.
|
|
213
241
|
*
|
|
214
242
|
* @example
|
|
215
243
|
* ```typescript
|
|
216
244
|
* const controller = new BaseController(repository);
|
|
217
|
-
*
|
|
218
|
-
* // Create Fastify handler
|
|
219
245
|
* const listHandler = createFastifyHandler(controller.list.bind(controller));
|
|
220
|
-
*
|
|
221
|
-
* // Register route
|
|
222
246
|
* fastify.get('/products', listHandler);
|
|
223
247
|
* ```
|
|
224
248
|
*/
|
package/dist/scope/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as isMember, D as requireOrgId, E as requireClientId, O as requireTeamId, S as isElevated, T as isService, _ as getTenantFromRequest, a as getAncestorOrgIds, b as hasOrgAccess, c as getMandate, d as getOrgRoles, f as getRequestScope, g as getTeamId, h as getServiceScopes, i as RequestScope, k as requireUserId, l as getOrgContext, m as getScopeContextMap, n as Mandate, o as getClientId, p as getScopeContext, r as PUBLIC_SCOPE, s as getDPoPJkt, t as AUTHENTICATED_SCOPE, u as getOrgId, v as getUserId, w as isOrgInScope, x as isAuthenticated, y as getUserRoles } from "../types-
|
|
2
|
-
import { i as elevationPlugin, n as ElevationOptions, r as _default, t as ElevationEvent } from "../elevation-
|
|
1
|
+
import { C as isMember, D as requireOrgId, E as requireClientId, O as requireTeamId, S as isElevated, T as isService, _ as getTenantFromRequest, a as getAncestorOrgIds, b as hasOrgAccess, c as getMandate, d as getOrgRoles, f as getRequestScope, g as getTeamId, h as getServiceScopes, i as RequestScope, k as requireUserId, l as getOrgContext, m as getScopeContextMap, n as Mandate, o as getClientId, p as getScopeContext, r as PUBLIC_SCOPE, s as getDPoPJkt, t as AUTHENTICATED_SCOPE, u as getOrgId, v as getUserId, w as isOrgInScope, x as isAuthenticated, y as getUserRoles } from "../types-CfapW2t8.mjs";
|
|
2
|
+
import { i as elevationPlugin, n as ElevationOptions, r as _default, t as ElevationEvent } from "../elevation-DvwtjDwu.mjs";
|
|
3
3
|
import { FastifyReply, FastifyRequest } from "fastify";
|
|
4
4
|
|
|
5
5
|
//#region src/scope/rateLimitKey.d.ts
|
package/dist/testing/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Kt as AnyRecord, V as ResourceDefinition } from "../index-
|
|
2
|
-
import { d as
|
|
1
|
+
import { Kt as AnyRecord, V as ResourceDefinition } from "../index-DBDgy6Hw.mjs";
|
|
2
|
+
import { d as preloadResourcesAsync, r as CreateAppOptions, u as preloadResources } from "../types-Dw--SyTq.mjs";
|
|
3
3
|
import { StorageContractSetup, StorageContractSetupResult, runStorageContract } from "./storageContract.mjs";
|
|
4
4
|
import { FastifyInstance, FastifyServerOptions } from "fastify";
|
|
5
5
|
import { Mock } from "vitest";
|
|
@@ -464,29 +464,6 @@ declare function createTestTimer(): {
|
|
|
464
464
|
reset: () => void;
|
|
465
465
|
};
|
|
466
466
|
//#endregion
|
|
467
|
-
//#region src/testing/preloadResources.d.ts
|
|
468
|
-
/** Eager glob result: `{ '/path/to/file.ts': resourceModule }` */
|
|
469
|
-
type EagerGlobResult = Record<string, unknown>;
|
|
470
|
-
/** Lazy glob result: `{ '/path/to/file.ts': () => Promise<unknown> }` */
|
|
471
|
-
type LazyGlobResult = Record<string, () => Promise<unknown>>;
|
|
472
|
-
/**
|
|
473
|
-
* Normalize an eager `import.meta.glob` result into a `ResourceLike[]`.
|
|
474
|
-
*
|
|
475
|
-
* Accepts either:
|
|
476
|
-
* - `{ import: 'default' }` form: values are the resource directly
|
|
477
|
-
* - default form: values are the full module — picks first export with `toPlugin()`
|
|
478
|
-
*
|
|
479
|
-
* Throws if any module doesn't yield a valid `ResourceLike`.
|
|
480
|
-
*/
|
|
481
|
-
declare function preloadResources(globResult: EagerGlobResult): ResourceLike[];
|
|
482
|
-
/**
|
|
483
|
-
* Normalize a lazy `import.meta.glob` result into a `Promise<ResourceLike[]>`.
|
|
484
|
-
*
|
|
485
|
-
* Use this when resources depend on prior bootstrap (e.g., engine init) and
|
|
486
|
-
* cannot be evaluated at import time of the preload file.
|
|
487
|
-
*/
|
|
488
|
-
declare function preloadResourcesAsync(globResult: LazyGlobResult): Promise<ResourceLike[]>;
|
|
489
|
-
//#endregion
|
|
490
467
|
//#region src/testing/testApp.d.ts
|
|
491
468
|
type DbMode = "in-memory" | {
|
|
492
469
|
uri: string;
|
package/dist/testing/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { t as CRUD_OPERATIONS } from "../constants-TrJVIJl0.mjs";
|
|
2
|
+
import { n as preloadResourcesAsync, t as preloadResources } from "../preloadResources-BOXzPhKU.mjs";
|
|
2
3
|
import { runStorageContract } from "./storageContract.mjs";
|
|
3
4
|
import Fastify from "fastify";
|
|
4
5
|
import { afterAll, describe, expect, it, vi } from "vitest";
|
|
@@ -970,50 +971,6 @@ function createTestTimer() {
|
|
|
970
971
|
};
|
|
971
972
|
}
|
|
972
973
|
//#endregion
|
|
973
|
-
//#region src/testing/preloadResources.ts
|
|
974
|
-
/**
|
|
975
|
-
* Normalize an eager `import.meta.glob` result into a `ResourceLike[]`.
|
|
976
|
-
*
|
|
977
|
-
* Accepts either:
|
|
978
|
-
* - `{ import: 'default' }` form: values are the resource directly
|
|
979
|
-
* - default form: values are the full module — picks first export with `toPlugin()`
|
|
980
|
-
*
|
|
981
|
-
* Throws if any module doesn't yield a valid `ResourceLike`.
|
|
982
|
-
*/
|
|
983
|
-
function preloadResources(globResult) {
|
|
984
|
-
const resources = [];
|
|
985
|
-
for (const [path, value] of Object.entries(globResult)) {
|
|
986
|
-
const resource = pickResource(value);
|
|
987
|
-
if (!resource) throw new Error(`preloadResources: ${path} does not export a valid resource.\n Expected: a default export OR a named export with toPlugin().`);
|
|
988
|
-
resources.push(resource);
|
|
989
|
-
}
|
|
990
|
-
return resources.sort((a, b) => (a.name ?? "").localeCompare(b.name ?? ""));
|
|
991
|
-
}
|
|
992
|
-
/**
|
|
993
|
-
* Normalize a lazy `import.meta.glob` result into a `Promise<ResourceLike[]>`.
|
|
994
|
-
*
|
|
995
|
-
* Use this when resources depend on prior bootstrap (e.g., engine init) and
|
|
996
|
-
* cannot be evaluated at import time of the preload file.
|
|
997
|
-
*/
|
|
998
|
-
async function preloadResourcesAsync(globResult) {
|
|
999
|
-
return (await Promise.all(Object.entries(globResult).map(async ([path, loader]) => {
|
|
1000
|
-
const resource = pickResource(await loader());
|
|
1001
|
-
if (!resource) throw new Error(`preloadResourcesAsync: ${path} does not export a valid resource.\n Expected: a default export OR a named export with toPlugin().`);
|
|
1002
|
-
return resource;
|
|
1003
|
-
}))).sort((a, b) => (a.name ?? "").localeCompare(b.name ?? ""));
|
|
1004
|
-
}
|
|
1005
|
-
function pickResource(value) {
|
|
1006
|
-
if (!value || typeof value !== "object") return void 0;
|
|
1007
|
-
if (typeof value.toPlugin === "function") return value;
|
|
1008
|
-
const mod = value;
|
|
1009
|
-
const candidates = [
|
|
1010
|
-
mod.default,
|
|
1011
|
-
mod.resource,
|
|
1012
|
-
...Object.values(mod)
|
|
1013
|
-
];
|
|
1014
|
-
for (const c of candidates) if (c && typeof c === "object" && typeof c.toPlugin === "function") return c;
|
|
1015
|
-
}
|
|
1016
|
-
//#endregion
|
|
1017
974
|
//#region src/testing/testApp.ts
|
|
1018
975
|
/**
|
|
1019
976
|
* createTestApp — test app factory for arc
|
|
@@ -1079,7 +1036,7 @@ function pickDefaultAuth(authMode, callerAuth) {
|
|
|
1079
1036
|
};
|
|
1080
1037
|
}
|
|
1081
1038
|
async function createTestApp(options = {}) {
|
|
1082
|
-
const { createApp } = await import("../createApp-
|
|
1039
|
+
const { createApp } = await import("../createApp-DdPBtmzp.mjs").then((n) => n.r);
|
|
1083
1040
|
const { resources = [], db = "in-memory", connectMongoose = false, authMode = "jwt", defaultOrgId, plugins, auth: callerAuth, ...appOptions } = options;
|
|
1084
1041
|
let dbHandle;
|
|
1085
1042
|
let dbUri;
|
package/dist/types/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { $ as OnTenantDeleteConfig, A as RequestIdOptions, Bt as AuthHelpers, C as RequestContext, D as HealthCheck, E as GracefulShutdownOptions, F as FastifyWithDecorators, G as ActionsMap, Gt as TokenPair, H as ActionDefinition, Ht as Authenticator, I as MiddlewareHandler, J as CrudRouteKey, Jt as ArcRequest, K as ArcFieldRule, Kt as AnyRecord, L as RequestWithExtras, M as EventsDecorator, N as FastifyRequestExtras, O as HealthOptions, P as FastifyWithAuth, Q as MiddlewareConfig, Qt as UserOrganization, S as QueryParserInterface, T as CrudRouterOptions, U as ActionEntry, Ut as AuthenticatorContext, Vt as AuthPluginOptions, W as ActionHandlerFn, Wt as JwtContext, X as EventDefinition, Xt as ObjectId, Y as CrudSchemas, Yt as JWTPayload, Z as FieldRule, Zt as UserLike, _ as ControllerQueryOptions, _t as FastifyHandler, a as InferAdapterDoc, at as ResolvedTenantPurge, b as ParsedQuery, bt as IRequestContext, c as TypedController, cn as BaseControllerOptions, ct as ResourceHookContext, d as PaginationResult, dt as RouteDefinition, et as OpenApiSchemas, f as IntrospectionData, ft as RouteMcpConfig, g as ArcInternalMetadata, gt as ControllerLike, h as ResourceMetadata, ht as ControllerHandler, i as ValidationResult, it as RateLimitConfig, j as ArcDecorator, k as IntrospectionPluginOptions, l as TypedRepository, lt as ResourceHooks, m as RegistryStats, mt as RouteSchemaOptions, n as ConfigError, nt as PresetHook, o as InferDocType, ot as ResourceCacheConfig, p as RegistryEntry, pt as RouteMethod, q as CrudController, qt as ApiResponse, r as ValidateOptions, rt as PresetResult, s as InferResourceDoc, st as ResourceConfig, t as RouteHandlerMethod, tt as PresetFunction, u as TypedResourceConfig, ut as ResourcePermissions, v as LookupOption, vt as IController, w as ServiceContext, x as PopulateOption, xt as RouteHandler, y as OwnershipCheck, yt as IControllerResponse } from "../index-
|
|
2
|
-
import { i as RequestScope } from "../types-
|
|
3
|
-
import { c as PermissionCheck, d as UserBase, l as PermissionContext, u as PermissionResult } from "../fields-
|
|
4
|
-
import { n as ElevationOptions, t as ElevationEvent } from "../elevation-
|
|
1
|
+
import { $ as OnTenantDeleteConfig, A as RequestIdOptions, Bt as AuthHelpers, C as RequestContext, D as HealthCheck, E as GracefulShutdownOptions, F as FastifyWithDecorators, G as ActionsMap, Gt as TokenPair, H as ActionDefinition, Ht as Authenticator, I as MiddlewareHandler, J as CrudRouteKey, Jt as ArcRequest, K as ArcFieldRule, Kt as AnyRecord, L as RequestWithExtras, M as EventsDecorator, N as FastifyRequestExtras, O as HealthOptions, P as FastifyWithAuth, Q as MiddlewareConfig, Qt as UserOrganization, S as QueryParserInterface, T as CrudRouterOptions, U as ActionEntry, Ut as AuthenticatorContext, Vt as AuthPluginOptions, W as ActionHandlerFn, Wt as JwtContext, X as EventDefinition, Xt as ObjectId, Y as CrudSchemas, Yt as JWTPayload, Z as FieldRule, Zt as UserLike, _ as ControllerQueryOptions, _t as FastifyHandler, a as InferAdapterDoc, at as ResolvedTenantPurge, b as ParsedQuery, bt as IRequestContext, c as TypedController, cn as BaseControllerOptions, ct as ResourceHookContext, d as PaginationResult, dt as RouteDefinition, et as OpenApiSchemas, f as IntrospectionData, ft as RouteMcpConfig, g as ArcInternalMetadata, gt as ControllerLike, h as ResourceMetadata, ht as ControllerHandler, i as ValidationResult, it as RateLimitConfig, j as ArcDecorator, k as IntrospectionPluginOptions, l as TypedRepository, lt as ResourceHooks, m as RegistryStats, mt as RouteSchemaOptions, n as ConfigError, nt as PresetHook, o as InferDocType, ot as ResourceCacheConfig, p as RegistryEntry, pt as RouteMethod, q as CrudController, qt as ApiResponse, r as ValidateOptions, rt as PresetResult, s as InferResourceDoc, st as ResourceConfig, t as RouteHandlerMethod, tt as PresetFunction, u as TypedResourceConfig, ut as ResourcePermissions, v as LookupOption, vt as IController, w as ServiceContext, x as PopulateOption, xt as RouteHandler, y as OwnershipCheck, yt as IControllerResponse } from "../index-DBDgy6Hw.mjs";
|
|
2
|
+
import { i as RequestScope } from "../types-CfapW2t8.mjs";
|
|
3
|
+
import { c as PermissionCheck, d as UserBase, l as PermissionContext, u as PermissionResult } from "../fields-DqZLp5d6.mjs";
|
|
4
|
+
import { n as ElevationOptions, t as ElevationEvent } from "../elevation-DvwtjDwu.mjs";
|
|
5
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, OnTenantDeleteConfig, OpenApiSchemas, OwnershipCheck, PaginationResult, ParsedQuery, PermissionCheck, PermissionContext, PermissionResult, PopulateOption, PresetFunction, PresetHook, PresetResult, QueryParserInterface, RateLimitConfig, RegistryEntry, RegistryStats, RequestContext, RequestIdOptions, RequestScope, RequestWithExtras, ResolvedTenantPurge, 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/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-HcAgP5Ni.mjs";
|
|
2
2
|
export { Storage, StorageContext, StorageFile, StorageReadRange, StorageReadResult, StorageUploadInput };
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { r as CacheStore } from "./interface-
|
|
2
|
-
import { Ht as Authenticator } from "./index-
|
|
3
|
-
import { n as ElevationOptions } from "./elevation-
|
|
4
|
-
import { a as EventTransport } from "./EventTransport-
|
|
5
|
-
import { t as ExternalOpenApiPaths } from "./externalPaths-
|
|
6
|
-
import { r as QueryCachePluginOptions } from "./queryCachePlugin-
|
|
7
|
-
import { t as EventPluginOptions } from "./eventPlugin-
|
|
8
|
-
import { _ as HealthOptions, f as CachingOptions, l as SSEOptions, o as MetricsOptions, t as VersioningOptions } from "./versioning-
|
|
9
|
-
import { t as ErrorHandlerOptions } from "./errorHandler-
|
|
10
|
-
import { r as IdempotencyStore } from "./interface-
|
|
1
|
+
import { r as CacheStore } from "./interface-BVkZsvEe.mjs";
|
|
2
|
+
import { Ht as Authenticator } from "./index-DBDgy6Hw.mjs";
|
|
3
|
+
import { n as ElevationOptions } from "./elevation-DvwtjDwu.mjs";
|
|
4
|
+
import { a as EventTransport } from "./EventTransport-B1GFiYUy.mjs";
|
|
5
|
+
import { t as ExternalOpenApiPaths } from "./externalPaths-ClykOQqa.mjs";
|
|
6
|
+
import { r as QueryCachePluginOptions } from "./queryCachePlugin-Do4P_WBC.mjs";
|
|
7
|
+
import { t as EventPluginOptions } from "./eventPlugin-DjEx_J3j.mjs";
|
|
8
|
+
import { _ as HealthOptions, f as CachingOptions, l as SSEOptions, o as MetricsOptions, t as VersioningOptions } from "./versioning-5H4930tj.mjs";
|
|
9
|
+
import { t as ErrorHandlerOptions } from "./errorHandler-DuqTqeqn.mjs";
|
|
10
|
+
import { r as IdempotencyStore } from "./interface-DoE6UoC2.mjs";
|
|
11
11
|
import { FastifyInstance, FastifyPluginAsync, FastifyReply, FastifyRequest, FastifyServerOptions } from "fastify";
|
|
12
12
|
|
|
13
13
|
//#region src/factory/loadResources.d.ts
|
|
@@ -203,6 +203,29 @@ interface LoadResourcesOptions<TContext = unknown> {
|
|
|
203
203
|
*/
|
|
204
204
|
declare function loadResources<TContext = unknown>(dir: string, options?: LoadResourcesOptions<TContext>): Promise<ResourceLike[]>;
|
|
205
205
|
//#endregion
|
|
206
|
+
//#region src/testing/preloadResources.d.ts
|
|
207
|
+
/** Eager glob result: `{ '/path/to/file.ts': resourceModule }` */
|
|
208
|
+
type EagerGlobResult = Record<string, unknown>;
|
|
209
|
+
/** Lazy glob result: `{ '/path/to/file.ts': () => Promise<unknown> }` */
|
|
210
|
+
type LazyGlobResult = Record<string, () => Promise<unknown>>;
|
|
211
|
+
/**
|
|
212
|
+
* Normalize an eager `import.meta.glob` result into a `ResourceLike[]`.
|
|
213
|
+
*
|
|
214
|
+
* Accepts either:
|
|
215
|
+
* - `{ import: 'default' }` form: values are the resource directly
|
|
216
|
+
* - default form: values are the full module — picks first export with `toPlugin()`
|
|
217
|
+
*
|
|
218
|
+
* Throws if any module doesn't yield a valid `ResourceLike`.
|
|
219
|
+
*/
|
|
220
|
+
declare function preloadResources(globResult: EagerGlobResult): ResourceLike[];
|
|
221
|
+
/**
|
|
222
|
+
* Normalize a lazy `import.meta.glob` result into a `Promise<ResourceLike[]>`.
|
|
223
|
+
*
|
|
224
|
+
* Use this when resources depend on prior bootstrap (e.g., engine init) and
|
|
225
|
+
* cannot be evaluated at import time of the preload file.
|
|
226
|
+
*/
|
|
227
|
+
declare function preloadResourcesAsync(globResult: LazyGlobResult): Promise<ResourceLike[]>;
|
|
228
|
+
//#endregion
|
|
206
229
|
//#region src/factory/types.d.ts
|
|
207
230
|
type CorsOptions = Record<string, unknown> & {
|
|
208
231
|
origin?: unknown;
|
|
@@ -1041,4 +1064,4 @@ interface RawBodyOptions {
|
|
|
1041
1064
|
runFirst?: boolean;
|
|
1042
1065
|
}
|
|
1043
1066
|
//#endregion
|
|
1044
|
-
export { CustomPluginAuthOption as a, RawBodyOptions as c,
|
|
1067
|
+
export { CustomPluginAuthOption as a, RawBodyOptions as c, preloadResourcesAsync as d, LoadResourcesOptions as f, loadResources as h, CustomAuthenticatorOption as i, UnderPressureOptions as l, ResourceModule as m, BetterAuthOption as n, JwtAuthOption as o, ResourceLike as p, CreateAppOptions as r, MultipartOptions as s, AuthOption as t, preloadResources as u };
|
package/dist/utils/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Kt as AnyRecord, S as QueryParserInterface, Zt as UserLike, b as ParsedQuery, et as OpenApiSchemas, st as ResourceConfig } from "../index-
|
|
2
|
-
import { n as ErrorMapper } from "../errorHandler-
|
|
3
|
-
import { a as NotFoundError, c as RateLimitError, d as ValidationError, f as createDomainError, i as ForbiddenError, l as ServiceUnavailableError, m as isArcError, n as ConflictError, o as OrgAccessDeniedError, p as createError, r as ErrorOptions, s as OrgRequiredError, t as ArcError, u as UnauthorizedError } from "../errors-
|
|
1
|
+
import { Kt as AnyRecord, S as QueryParserInterface, Zt as UserLike, b as ParsedQuery, et as OpenApiSchemas, st as ResourceConfig } from "../index-DBDgy6Hw.mjs";
|
|
2
|
+
import { n as ErrorMapper } from "../errorHandler-DuqTqeqn.mjs";
|
|
3
|
+
import { a as NotFoundError, c as RateLimitError, d as ValidationError, f as createDomainError, i as ForbiddenError, l as ServiceUnavailableError, m as isArcError, n as ConflictError, o as OrgAccessDeniedError, p as createError, r as ErrorOptions, s as OrgRequiredError, t as ArcError, u as UnauthorizedError } from "../errors-4ZloYFvm.mjs";
|
|
4
4
|
import { errorContractSchema, errorDetailSchema } from "@classytic/repo-core/errors";
|
|
5
5
|
import { FastifyInstance, FastifyReply, FastifyRequest, RouteHandlerMethod } from "fastify";
|
|
6
6
|
|
|
@@ -1144,7 +1144,8 @@ declare function simpleEqualityMatcher(item: unknown, filters: Record<string, un
|
|
|
1144
1144
|
* State Machine Utility
|
|
1145
1145
|
*
|
|
1146
1146
|
* Pure utility for validating state transitions in workflow systems.
|
|
1147
|
-
* Zero dependencies,
|
|
1147
|
+
* Zero runtime dependencies — usable from any layer of arc (controllers,
|
|
1148
|
+
* hooks, pipeline steps, tests).
|
|
1148
1149
|
*
|
|
1149
1150
|
* @example
|
|
1150
1151
|
* const orderState = createStateMachine('Order', {
|
package/dist/utils/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as OrgAccessDeniedError, c as ServiceUnavailableError, d as createDomainError, f as createError, i as NotFoundError, l as UnauthorizedError, n as ConflictError, o as OrgRequiredError, p as isArcError, r as ForbiddenError, s as RateLimitError, t as ArcError, u as ValidationError } from "../errors-j4aJm1Wg.mjs";
|
|
2
|
-
import { A as assertValidConfig, C as withCompensation, D as CircuitState, E as CircuitBreakerRegistry, M as validateResourceConfig, N as simpleEqualityMatcher, O as createCircuitBreaker, S as defineCompensation, T as CircuitBreakerError, _ as ArcQueryParser, a as bareListResponse, b as defineGuard, c as errorDetailSchema, d as keysetListResponse, f as listResponse, g as responses, h as queryParams, i as aggregateListResponse, j as formatValidationErrors, k as createCircuitBreakerRegistry, l as getDefaultCrudSchemas, m as paginationSchema, n as createStateMachine, o as deleteResponse, p as offsetListResponse, r as scheduleBackground, s as errorContractSchema, t as getUserId, u as getListQueryParams, v as createQueryParser, w as CircuitBreaker, x as defineErrorMapper, y as handleRaw } from "../utils-
|
|
2
|
+
import { A as assertValidConfig, C as withCompensation, D as CircuitState, E as CircuitBreakerRegistry, M as validateResourceConfig, N as simpleEqualityMatcher, O as createCircuitBreaker, S as defineCompensation, T as CircuitBreakerError, _ as ArcQueryParser, a as bareListResponse, b as defineGuard, c as errorDetailSchema, d as keysetListResponse, f as listResponse, g as responses, h as queryParams, i as aggregateListResponse, j as formatValidationErrors, k as createCircuitBreakerRegistry, l as getDefaultCrudSchemas, m as paginationSchema, n as createStateMachine, o as deleteResponse, p as offsetListResponse, r as scheduleBackground, s as errorContractSchema, t as getUserId, u as getListQueryParams, v as createQueryParser, w as CircuitBreaker, x as defineErrorMapper, y as handleRaw } from "../utils-DPXZnZUx.mjs";
|
|
3
3
|
import { a as toJsonSchema, i as isZodSchema, n as convertRouteSchema, r as isJsonSchema, t as convertOpenApiSchemas } from "../schemaConverter-De34B1ZG.mjs";
|
|
4
4
|
import { t as hasEvents } from "../typeGuards-BzkXkvVv.mjs";
|
|
5
5
|
export { ArcError, ArcQueryParser, CircuitBreaker, CircuitBreakerError, CircuitBreakerRegistry, CircuitState, ConflictError, ForbiddenError, NotFoundError, OrgAccessDeniedError, OrgRequiredError, RateLimitError, ServiceUnavailableError, UnauthorizedError, ValidationError, aggregateListResponse, assertValidConfig, bareListResponse, convertOpenApiSchemas, convertRouteSchema, createCircuitBreaker, createCircuitBreakerRegistry, createDomainError, createError, createQueryParser, createStateMachine, defineCompensation, defineErrorMapper, defineGuard, deleteResponse, errorContractSchema, errorDetailSchema, formatValidationErrors, getDefaultCrudSchemas, getListQueryParams, getUserId, handleRaw, hasEvents, isArcError, isJsonSchema, isZodSchema, keysetListResponse, listResponse, offsetListResponse, paginationSchema, queryParams, responses, scheduleBackground, simpleEqualityMatcher, toJsonSchema, validateResourceConfig, withCompensation };
|
|
@@ -142,7 +142,10 @@ function validateResourceConfig(config, options = {}) {
|
|
|
142
142
|
suggestion: `Change to "${config.prefix.slice(0, -1)}"`
|
|
143
143
|
});
|
|
144
144
|
}
|
|
145
|
-
if (config.routes)
|
|
145
|
+
if (config.routes) {
|
|
146
|
+
validateRoutes(config.routes, errors);
|
|
147
|
+
validateRouteCrudCollisions(config, errors);
|
|
148
|
+
}
|
|
146
149
|
return {
|
|
147
150
|
valid: errors.length === 0,
|
|
148
151
|
errors,
|
|
@@ -210,6 +213,71 @@ function validatePresetOptions(preset, warnings) {
|
|
|
210
213
|
suggestion: validOptions.length > 0 ? `Valid options: ${validOptions.join(", ")}` : `Preset "${preset.name}" has no configurable options`
|
|
211
214
|
});
|
|
212
215
|
}
|
|
216
|
+
/**
|
|
217
|
+
* Detect collisions between user-declared `routes:` entries and the
|
|
218
|
+
* auto-CRUD route table that `createCrudRouter` will register.
|
|
219
|
+
*
|
|
220
|
+
* Without this check, a custom `POST /` on the same prefix as auto-CRUD's
|
|
221
|
+
* `create` boots fine through `defineResource()` and only blows up at
|
|
222
|
+
* `app.register()` time with Fastify's opaque `FST_ERR_DUPLICATED_ROUTE`.
|
|
223
|
+
* That error doesn't mention `disabledRoutes` and doesn't distinguish
|
|
224
|
+
* "you collided with auto-CRUD" from "you collided with yourself" — so
|
|
225
|
+
* the consumer has to grep arc's source to discover the fix.
|
|
226
|
+
*
|
|
227
|
+
* We surface the fix in the error message, naming the conflicting op
|
|
228
|
+
* and the literal line to add.
|
|
229
|
+
*
|
|
230
|
+
* Honored config:
|
|
231
|
+
* - `disableDefaultRoutes: true` → no auto-CRUD, no collisions possible
|
|
232
|
+
* - `disabledRoutes: ['create']` → that op's path is free for custom use
|
|
233
|
+
* - `updateMethod: 'PUT' | 'both'` → update slot covers PUT/PATCH accordingly
|
|
234
|
+
*/
|
|
235
|
+
function validateRouteCrudCollisions(config, errors) {
|
|
236
|
+
if (config.disableDefaultRoutes) return;
|
|
237
|
+
if (!config.routes || config.routes.length === 0) return;
|
|
238
|
+
const updateMethod = config.updateMethod ?? "PATCH";
|
|
239
|
+
const updateMethods = updateMethod === "both" ? ["PUT", "PATCH"] : [updateMethod];
|
|
240
|
+
const disabled = new Set(config.disabledRoutes ?? []);
|
|
241
|
+
const crudTable = [
|
|
242
|
+
{
|
|
243
|
+
op: "list",
|
|
244
|
+
method: "GET",
|
|
245
|
+
path: "/"
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
op: "get",
|
|
249
|
+
method: "GET",
|
|
250
|
+
path: "/:id"
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
op: "create",
|
|
254
|
+
method: "POST",
|
|
255
|
+
path: "/"
|
|
256
|
+
},
|
|
257
|
+
...updateMethods.map((m) => ({
|
|
258
|
+
op: "update",
|
|
259
|
+
method: m,
|
|
260
|
+
path: "/:id"
|
|
261
|
+
})),
|
|
262
|
+
{
|
|
263
|
+
op: "delete",
|
|
264
|
+
method: "DELETE",
|
|
265
|
+
path: "/:id"
|
|
266
|
+
}
|
|
267
|
+
];
|
|
268
|
+
for (const [i, route] of config.routes.entries()) {
|
|
269
|
+
if (!route.method || !route.path) continue;
|
|
270
|
+
for (const crud of crudTable) {
|
|
271
|
+
if (disabled.has(crud.op)) continue;
|
|
272
|
+
if (route.method !== crud.method || route.path !== crud.path) continue;
|
|
273
|
+
errors.push({
|
|
274
|
+
field: `routes[${i}]`,
|
|
275
|
+
message: `Route ${route.method} ${route.path} collides with auto-CRUD "${crud.op}"`,
|
|
276
|
+
suggestion: `Add \`disabledRoutes: ['${crud.op}']\` to suppress the auto-CRUD route, or move your custom handler to a different path. Set \`disableDefaultRoutes: true\` to disable all auto-CRUD on this resource.`
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
213
281
|
function validateRoutes(routes, errors) {
|
|
214
282
|
const validMethods = [
|
|
215
283
|
"GET",
|