@classytic/arc 2.19.0 → 2.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/bin/arc.js +37 -0
- package/dist/{BaseController-Dy6EQHjM.mjs → BaseController-D-MHZ27_.mjs} +4 -4
- package/dist/{ResourceRegistry-5fKZwhK_.mjs → ResourceRegistry-7RnrEWNP.mjs} +1 -1
- package/dist/{actionPermissions-D7NGwcAR.mjs → actionPermissions-C9RMiIpc.mjs} +1 -1
- package/dist/audit/index.mjs +1 -1
- package/dist/auth/index.d.mts +1 -1
- package/dist/auth/index.mjs +7 -5
- package/dist/{buildHandler-B0qvAguf.mjs → buildHandler-D_2ULWxZ.mjs} +3 -3
- package/dist/cache/index.mjs +2 -2
- package/dist/cli/commands/describe.d.mts +1 -1
- package/dist/cli/commands/describe.mjs +2 -2
- package/dist/cli/commands/docs.mjs +2 -2
- package/dist/cli/commands/generate.mjs +1 -1
- package/dist/cli/commands/init.mjs +1 -1
- package/dist/cli/commands/introspect.mjs +4 -13
- package/dist/cli/index.mjs +2 -2
- package/dist/{constants-gaEeMlz-.mjs → constants-DNre0wRg.mjs} +1 -1
- package/dist/core/index.d.mts +2 -2
- package/dist/core/index.mjs +4 -4
- package/dist/{core-Ba-6Sue6.mjs → core-CWhyGkiM.mjs} +125 -53
- package/dist/{createActionRouter-B_WzBFyf.mjs → createActionRouter-HlQso0jO.mjs} +4 -4
- package/dist/{createAggregationRouter-B_G_nIjm.mjs → createAggregationRouter-5LzPzgw1.mjs} +5 -4
- package/dist/{createApp--703hQE1.mjs → createApp-D6uwzCKu.mjs} +210 -17
- package/dist/docs/index.d.mts +1 -1
- package/dist/docs/index.mjs +1 -1
- package/dist/events/index.mjs +9 -6
- package/dist/factory/index.d.mts +3 -2
- package/dist/factory/index.mjs +2 -2
- package/dist/{fastify-augmentation-D-5_yQJi.d.mts → fastify-augmentation-CCQJEDgh.d.mts} +12 -1
- package/dist/{generate-Brans3fW.mjs → generate-usRSdQmP.mjs} +4 -3
- package/dist/hooks/index.d.mts +1 -1
- package/dist/idempotency/index.mjs +1 -1
- package/dist/{index-CRKiiP5o.d.mts → index-CdFkIMEd.d.mts} +5 -0
- package/dist/{index-CP6A1Ffj.d.mts → index-DUa8WHz3.d.mts} +1 -1
- package/dist/{index-CUTG2Cuo.d.mts → index-_--GyzcO.d.mts} +28 -1
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +6 -6
- package/dist/{init-Bqpt1Hxf.mjs → init-YH_nslQR.mjs} +87 -5
- package/dist/integrations/index.d.mts +1 -1
- package/dist/integrations/mcp/index.d.mts +2 -2
- package/dist/integrations/mcp/index.mjs +1 -1
- package/dist/integrations/mcp/testing.d.mts +1 -1
- package/dist/integrations/mcp/testing.mjs +1 -1
- package/dist/integrations/streamline.d.mts +17 -5
- package/dist/integrations/streamline.mjs +9 -5
- package/dist/{loadResourcesFromEntry-BTlFEx05.mjs → loadResourcesFromEntry-OMCvIEE7.mjs} +1 -1
- package/dist/{mcpPlugin-C088Nd-G.mjs → mcpPlugin-CuW6L_uD.mjs} +148 -49
- package/dist/middleware/index.d.mts +1 -1
- package/dist/middleware/index.mjs +1 -1
- package/dist/module-JYH9V0I8.d.mts +384 -0
- package/dist/{openapi-DZ-5a5Op.mjs → openapi-Dq6RbEGK.mjs} +3 -3
- package/dist/permissions/index.d.mts +1 -1
- package/dist/permissions/index.mjs +1 -1
- package/dist/{permissions-BPB1xqGf.mjs → permissions-CgbOLJZG.mjs} +10 -2
- package/dist/pipeline/index.d.mts +1 -1
- package/dist/plugins/index.d.mts +10 -5
- package/dist/plugins/index.mjs +3 -3
- package/dist/plugins/tracing-entry.mjs +1 -1
- package/dist/{pluralize-DccFV9R7.mjs → pluralize-BhrgwZb9.mjs} +3 -3
- package/dist/presets/filesUpload.d.mts +1 -1
- package/dist/presets/filesUpload.mjs +1 -1
- package/dist/presets/index.d.mts +16 -2
- package/dist/presets/index.mjs +1 -1
- package/dist/presets/multiTenant.d.mts +1 -1
- package/dist/presets/multiTenant.mjs +1 -1
- package/dist/presets/search.d.mts +1 -1
- package/dist/presets/search.mjs +3 -2
- package/dist/{presets-BtyFwTO4.mjs → presets-DWsYQdbV.mjs} +1 -1
- package/dist/{queryCachePlugin-emHb0CuX.mjs → queryCachePlugin-DzqLN904.mjs} +2 -2
- package/dist/{registerRoute-BdV8DDwU.mjs → registerRoute-DGSREwPw.mjs} +1 -1
- package/dist/registry/index.d.mts +1 -1
- package/dist/registry/index.mjs +2 -2
- package/dist/{registry-Bm9LjWKs.mjs → registry-vcOCtPij.mjs} +1 -1
- package/dist/{schemaIR-D1MJwqmp.mjs → schemaIR-ajetw3Fv.mjs} +1 -42
- package/dist/scim/index.mjs +2 -2
- package/dist/sync/changelog.d.mts +2 -0
- package/dist/sync/changelog.mjs +2 -0
- package/dist/testing/index.d.mts +2 -2
- package/dist/testing/index.mjs +2 -2
- package/dist/types/index.d.mts +1 -1
- package/dist/{types-9_wtNPsI.d.mts → types-BHMKlMBU.d.mts} +53 -195
- package/dist/{types-DpvSF5Hh.d.mts → types-C9b2HR5W.d.mts} +1 -1
- package/dist/utils/index.d.mts +1 -1
- package/dist/utils/index.mjs +1 -1
- package/dist/{utils-C6QQ9-hd.mjs → utils-ChjYQpjn.mjs} +1400 -1400
- package/dist/{validate-CRcaWzp2.mjs → validate-C2mGgSXg.mjs} +3 -3
- package/package.json +13 -8
- package/skills/arc/SKILL.md +10 -0
- package/skills/arc/references/mcp.md +2 -0
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
import { FastifyInstance } from "fastify";
|
|
2
|
+
|
|
3
|
+
//#region src/factory/loadResources.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* loadResources — Auto-discover resource files from a directory.
|
|
6
|
+
*
|
|
7
|
+
* Scans for `*.resource.{ts,js,mts,mjs}` files, imports each,
|
|
8
|
+
* and collects their default exports. No barrel file needed.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { createApp, loadResources } from '@classytic/arc/factory';
|
|
13
|
+
*
|
|
14
|
+
* // Recommended: import.meta.url — works in both src/ (dev) and dist/ (prod)
|
|
15
|
+
* const app = await createApp({
|
|
16
|
+
* resources: await loadResources(import.meta.url),
|
|
17
|
+
* auth: { type: 'jwt', jwt: { secret: process.env.JWT_SECRET } },
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* // Or explicit path (must match runtime layout)
|
|
21
|
+
* const app2 = await createApp({
|
|
22
|
+
* resources: await loadResources('./src/resources'),
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* File convention:
|
|
27
|
+
* ```
|
|
28
|
+
* src/resources/
|
|
29
|
+
* product/product.resource.ts → export default defineResource({ name: 'product', ... })
|
|
30
|
+
* order/order.resource.ts → export default defineResource({ name: 'order', ... })
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
/**
|
|
34
|
+
* Resource interface — the contract between `loadResources`/`createApp` and resource definitions.
|
|
35
|
+
*
|
|
36
|
+
* Matches the shape of `ResourceDefinition` from `defineResource()` without requiring
|
|
37
|
+
* the import. All properties except `toPlugin` are optional so plain objects work too:
|
|
38
|
+
*
|
|
39
|
+
* ```typescript
|
|
40
|
+
* // Full resource (from defineResource)
|
|
41
|
+
* const product = defineResource({ name: 'product', ... }); // satisfies ResourceLike
|
|
42
|
+
*
|
|
43
|
+
* // Minimal resource (plain object)
|
|
44
|
+
* const simple: ResourceLike = { name: 'ping', toPlugin: () => () => {} };
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* **DO NOT add an index signature** (`[key: string]: unknown`) to this interface.
|
|
48
|
+
* Class instances (like `ResourceDefinition`) don't implicitly carry index signatures,
|
|
49
|
+
* so adding one here makes `ResourceDefinition` *unassignable* to `ResourceLike` —
|
|
50
|
+
* the exact opposite of the intent. TypeScript's structural typing already allows
|
|
51
|
+
* classes with extra properties to satisfy this interface without an index signature.
|
|
52
|
+
*/
|
|
53
|
+
interface ResourceLike {
|
|
54
|
+
/** Plugin factory — called by createApp to register routes */
|
|
55
|
+
toPlugin: () => unknown;
|
|
56
|
+
/** Resource name (used for route generation, logging, duplicate detection) */
|
|
57
|
+
name?: string;
|
|
58
|
+
/** Route prefix (default: `/${name}s`) */
|
|
59
|
+
prefix?: string;
|
|
60
|
+
/** Skip the global `resourcePrefix` from createApp — register at root */
|
|
61
|
+
skipGlobalPrefix?: boolean;
|
|
62
|
+
/** Display name for docs/OpenAPI */
|
|
63
|
+
displayName?: string;
|
|
64
|
+
/** Applied preset names */
|
|
65
|
+
_appliedPresets?: string[];
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Resource module — what a `.resource.ts` file's default (or named) export
|
|
69
|
+
* may resolve to.
|
|
70
|
+
*
|
|
71
|
+
* Two shapes accepted:
|
|
72
|
+
* 1. **Plain `ResourceLike`** — the result of `defineResource({...})`.
|
|
73
|
+
* Used as-is; no engine wiring needed.
|
|
74
|
+
* 2. **Factory `(ctx: TContext) => ResourceLike | Promise<ResourceLike>`**
|
|
75
|
+
* — a function arc calls with the `context` from `LoadResourcesOptions`.
|
|
76
|
+
* Eliminates the parallel `createXResource(engine)` factory files +
|
|
77
|
+
* `exclude: [...]` bookkeeping that engine-bound resources used to need.
|
|
78
|
+
*
|
|
79
|
+
* Detection is by `typeof === 'function'`: `ResourceDefinition` instances
|
|
80
|
+
* (returned by `defineResource()`) are class instances (`typeof === 'object'`),
|
|
81
|
+
* so the two shapes are unambiguous in practice.
|
|
82
|
+
*/
|
|
83
|
+
type ResourceModule<TContext = unknown> = ResourceLike | ((ctx: TContext) => ResourceLike | Promise<ResourceLike>);
|
|
84
|
+
interface LoadResourcesOptions<TContext = unknown> {
|
|
85
|
+
/** File pattern suffix (default: '.resource'). Matches `*.resource.{ts,js,mts,mjs}`. */
|
|
86
|
+
suffix?: string;
|
|
87
|
+
/** Recurse into subdirectories (default: true) */
|
|
88
|
+
recursive?: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Context passed to factory-style default exports. Resources whose default
|
|
91
|
+
* export is a function `(ctx) => ResourceLike` are called with this value;
|
|
92
|
+
* plain `ResourceLike` exports are returned unchanged.
|
|
93
|
+
*
|
|
94
|
+
* Use this to thread engine handles into engine-bound resources without
|
|
95
|
+
* creating parallel factory files outside `loadResources`'s sweep:
|
|
96
|
+
*
|
|
97
|
+
* ```ts
|
|
98
|
+
* // category.resource.ts
|
|
99
|
+
* import type { AppContext } from '#core/app/context.js';
|
|
100
|
+
* export default (ctx: AppContext) =>
|
|
101
|
+
* defineResource({
|
|
102
|
+
* name: 'category',
|
|
103
|
+
* adapter: createMongooseAdapter(
|
|
104
|
+
* ctx.catalog.models.Category,
|
|
105
|
+
* ctx.catalog.repositories.category,
|
|
106
|
+
* ),
|
|
107
|
+
* });
|
|
108
|
+
*
|
|
109
|
+
* // create-arc-app-options.ts
|
|
110
|
+
* resources: async () => {
|
|
111
|
+
* const [catalog, flow] = await Promise.all([
|
|
112
|
+
* ensureCatalogEngine(),
|
|
113
|
+
* ensureFlowEngine(),
|
|
114
|
+
* ]);
|
|
115
|
+
* return loadResources(import.meta.url, { context: { catalog, flow } });
|
|
116
|
+
* }
|
|
117
|
+
* ```
|
|
118
|
+
*
|
|
119
|
+
* Backwards compatible — pre-2.11.1 callers omit `context`, plain exports
|
|
120
|
+
* keep working unchanged. Factories that need a context but receive
|
|
121
|
+
* `undefined` should narrow defensively.
|
|
122
|
+
*/
|
|
123
|
+
context?: TContext;
|
|
124
|
+
/**
|
|
125
|
+
* Resource names to exclude. Matched against the resource's `.name` property
|
|
126
|
+
* after import, so you use the resource name (not the filename).
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```ts
|
|
130
|
+
* await loadResources('./src/resources', { exclude: ['debug', 'legacy-report'] })
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
exclude?: string[];
|
|
134
|
+
/**
|
|
135
|
+
* Resource names to include. When set, only matching resources are returned.
|
|
136
|
+
* Takes priority over `exclude`.
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```ts
|
|
140
|
+
* // Only load these two resources (useful for testing or microservice splits)
|
|
141
|
+
* await loadResources('./src/resources', { include: ['product', 'order'] })
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
include?: string[];
|
|
145
|
+
/**
|
|
146
|
+
* Optional logger override for diagnostics. When omitted, warnings flow
|
|
147
|
+
* through arc's standard logger (`arcLog('loadResources')`) — same path
|
|
148
|
+
* as every other arc-internal warning, controlled by `ARC_SUPPRESS_WARNINGS=1`
|
|
149
|
+
* and routable via `configureArcLogger({ writer })`.
|
|
150
|
+
*
|
|
151
|
+
* Pass any object with `warn(msg)` to override (e.g. `fastify.log` —
|
|
152
|
+
* which is what `registerResources` passes automatically when arc's
|
|
153
|
+
* factory triggers auto-discovery via `resourceDir`).
|
|
154
|
+
*
|
|
155
|
+
* Pre-2.11.1 had a `silent: boolean` flag and "silent by default" semantics;
|
|
156
|
+
* both removed. Migration:
|
|
157
|
+
*
|
|
158
|
+
* ```ts
|
|
159
|
+
* // Pre-2.11.1 // 2.11.1+
|
|
160
|
+
* loadResources(url, { silent: true }); // ARC_SUPPRESS_WARNINGS=1 (env)
|
|
161
|
+
* // OR configureArcLogger({ writer })
|
|
162
|
+
* loadResources(url, { silent: !isDev }); // ARC_SUPPRESS_WARNINGS=1 in prod
|
|
163
|
+
* loadResources(url, { logger: pinoAdapter }); // unchanged — still works
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
logger?: {
|
|
167
|
+
warn: (msg: string) => void;
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Scan a directory for resource files and import their default exports.
|
|
172
|
+
*
|
|
173
|
+
* Accepts a directory path OR `import.meta.url` (file:// URL).
|
|
174
|
+
* When given a URL, resolves to the directory containing that file —
|
|
175
|
+
* so `loadResources(import.meta.url)` works in both dev (`src/`) and
|
|
176
|
+
* production (`dist/`) without path gymnastics.
|
|
177
|
+
*
|
|
178
|
+
* @param dir - Directory path, or `import.meta.url` (file:// URL resolved to its dirname)
|
|
179
|
+
* @param options - Pattern and recursion options
|
|
180
|
+
* @returns Array of resource definitions (anything with `.toPlugin()`)
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```ts
|
|
184
|
+
* // Works from both src/ and dist/ — resolves relative to the calling file
|
|
185
|
+
* await loadResources(import.meta.url);
|
|
186
|
+
*
|
|
187
|
+
* // Subdirectory relative to the calling file
|
|
188
|
+
* await loadResources(import.meta.url, { suffix: '.resource' });
|
|
189
|
+
*
|
|
190
|
+
* // Explicit path (must match runtime layout)
|
|
191
|
+
* await loadResources('./src/resources');
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
declare function loadResources<TContext = unknown>(dir: string, options?: LoadResourcesOptions<TContext>): Promise<ResourceLike[]>;
|
|
195
|
+
//#endregion
|
|
196
|
+
//#region src/factory/module.d.ts
|
|
197
|
+
interface ArcModule<TExports = unknown> {
|
|
198
|
+
/** Stable identifier — appears in boot logs and duplicate-module detection. */
|
|
199
|
+
readonly name: string;
|
|
200
|
+
/**
|
|
201
|
+
* Names of modules this one must be composed AFTER. arc topologically orders
|
|
202
|
+
* the `modules` array from these edges before ANY phase runs, so a
|
|
203
|
+
* dependency's `bootstrap` (and thus its `fastify.arc.modules[dep]` export)
|
|
204
|
+
* is always live before this module's bootstrap, resources, or
|
|
205
|
+
* afterResources. Teardown (`onClose`) runs in the reverse of that order.
|
|
206
|
+
*
|
|
207
|
+
* Use this instead of relying on list position when a module reads another's
|
|
208
|
+
* public export — e.g. `@classytic/arc-reservation` wiring off
|
|
209
|
+
* `arc.modules.order`:
|
|
210
|
+
*
|
|
211
|
+
* ```ts
|
|
212
|
+
* defineModule({ name: "reservation", dependsOn: ["order"], bootstrap: (f) => {
|
|
213
|
+
* const order = getModuleExports<OrderEngine>(f, "order"); // guaranteed live
|
|
214
|
+
* …
|
|
215
|
+
* }});
|
|
216
|
+
* ```
|
|
217
|
+
*
|
|
218
|
+
* The order is a STABLE topological sort: modules with no `dependsOn` (and
|
|
219
|
+
* any two modules with no edge between them) keep their original list order,
|
|
220
|
+
* so adding `dependsOn` never silently reorders an unrelated module. All
|
|
221
|
+
* failure modes are fail-fast at boot: a name not in the composed set, a
|
|
222
|
+
* self-reference, and dependency CYCLES each throw with the offending path.
|
|
223
|
+
*
|
|
224
|
+
* **`dependsOn` is COMPOSITION order, not lazy loading.** Every module input
|
|
225
|
+
* (including dynamic-import thunks) is resolved — imported — up front via
|
|
226
|
+
* `Promise.all` BEFORE the sort; `dependsOn` then orders the *composition*
|
|
227
|
+
* (which module's `plugins`/`bootstrap` runs first), it does NOT delay
|
|
228
|
+
* *importing* a dependent until its dependency is ready. Use a thunk to gate
|
|
229
|
+
* whether a module is imported at all (region/tier packs); use `dependsOn`
|
|
230
|
+
* to order modules that are already selected.
|
|
231
|
+
*/
|
|
232
|
+
readonly dependsOn?: readonly string[];
|
|
233
|
+
/**
|
|
234
|
+
* Fastify plugins / decorators this module needs — the module-level analog
|
|
235
|
+
* of the app's `plugins()` slot. Runs in the plugins phase: AFTER the app's
|
|
236
|
+
* own `plugins()` (so module infra can build on app foundations like a DB
|
|
237
|
+
* connection) and in `dependsOn` order, but BEFORE any module `bootstrap` —
|
|
238
|
+
* so engines initialised in `bootstrap` can rely on what's registered here.
|
|
239
|
+
*
|
|
240
|
+
* Separating this from `bootstrap` keeps lifecycle intent explicit for
|
|
241
|
+
* published ecosystem packages: `plugins` = "register infra"; `bootstrap` =
|
|
242
|
+
* "initialise engines (and return the public export)". Registering a plugin
|
|
243
|
+
* inside `bootstrap` still works — this slot just makes the two distinct.
|
|
244
|
+
*/
|
|
245
|
+
plugins?: (fastify: FastifyInstance) => void | Promise<void>;
|
|
246
|
+
/**
|
|
247
|
+
* Domain init — runs in the `bootstrap` phase (after all `plugins`, before
|
|
248
|
+
* resources). Initialize engines / singletons / event subscriptions here so
|
|
249
|
+
* they are live when this module's `resources` factory runs.
|
|
250
|
+
*
|
|
251
|
+
* A returned value becomes the module's PUBLIC EXPORT, recorded at
|
|
252
|
+
* `fastify.arc.modules[name]` (wiki/modules.md — "no container", layer 2).
|
|
253
|
+
* Later modules' bootstraps can read it (list order = init order), which is
|
|
254
|
+
* how cross-module ports are wired without a DI container. Declare the
|
|
255
|
+
* export shape via `defineModule<TExports>` and read it back with the typed
|
|
256
|
+
* accessor — no cast at the consuming end:
|
|
257
|
+
*
|
|
258
|
+
* ```ts
|
|
259
|
+
* // arc-invoice bootstrap, composed AFTER arc-accounting:
|
|
260
|
+
* const acct = getModuleExports<AccountingEngine>(fastify, "accounting");
|
|
261
|
+
* ```
|
|
262
|
+
*/
|
|
263
|
+
bootstrap?: (fastify: FastifyInstance) => TExports | Promise<TExports>;
|
|
264
|
+
/**
|
|
265
|
+
* The module's resources. Array or factory — the factory form runs AFTER all
|
|
266
|
+
* bootstraps, so `defineResource(...)` receives fully-booted engines. Flows
|
|
267
|
+
* through arc's normal registration (prefix, dedup, docs), identical to a
|
|
268
|
+
* top-level `resources` entry.
|
|
269
|
+
*/
|
|
270
|
+
resources?: ReadonlyArray<ResourceLike> | ((fastify: FastifyInstance) => ReadonlyArray<ResourceLike> | Promise<ReadonlyArray<ResourceLike>>);
|
|
271
|
+
/**
|
|
272
|
+
* Post-registration wiring — runs in the `afterResources` phase, once this
|
|
273
|
+
* module's routes are mounted. Use for cross-resource event subscriptions the
|
|
274
|
+
* module owns.
|
|
275
|
+
*/
|
|
276
|
+
afterResources?: (fastify: FastifyInstance) => void | Promise<void>;
|
|
277
|
+
/**
|
|
278
|
+
* Teardown — registered as a Fastify `onClose` hook. Destroy engines, stop
|
|
279
|
+
* timers, flush the module's outbox. Modules close in REVERSE list order
|
|
280
|
+
* (last composed, first closed), mirroring init.
|
|
281
|
+
*/
|
|
282
|
+
onClose?: (fastify: FastifyInstance) => void | Promise<void>;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* A module in any of the forms `createApp({ modules })` accepts:
|
|
286
|
+
*
|
|
287
|
+
* - `ArcModule` — eager (already imported)
|
|
288
|
+
* - `Promise<ArcModule>` — an in-flight import
|
|
289
|
+
* - `() => ArcModule | Promise<…>` — a thunk, resolved at boot
|
|
290
|
+
*
|
|
291
|
+
* The **thunk of a dynamic import** is the point of this union — it lets a host
|
|
292
|
+
* compose modules *logically* and load them *lazily / conditionally*, the
|
|
293
|
+
* `next/dynamic` idea applied to backend domains. The module's code (and its
|
|
294
|
+
* heavy deps) is only pulled in when the thunk runs, so region- or tier-gated
|
|
295
|
+
* packs never enter the bundle path they aren't selected for:
|
|
296
|
+
*
|
|
297
|
+
* ```ts
|
|
298
|
+
* const taxPack =
|
|
299
|
+
* region === "BD"
|
|
300
|
+
* ? () => import("@classytic/bd-tax").then((m) => m.createBdTaxModule(deps))
|
|
301
|
+
* : () => import("@classytic/us-tax").then((m) => m.createUsTaxModule(deps));
|
|
302
|
+
*
|
|
303
|
+
* await createApp({ modules: [coreModule(deps), taxPack] });
|
|
304
|
+
* // only the selected tax package is imported + composed
|
|
305
|
+
* ```
|
|
306
|
+
*/
|
|
307
|
+
type ArcModuleInput<TExports = unknown> = ArcModule<TExports> | Promise<ArcModule<TExports>> | (() => ArcModule<TExports> | Promise<ArcModule<TExports>>);
|
|
308
|
+
/**
|
|
309
|
+
* Resolve any module-input form to a concrete `ArcModule`. A thunk is invoked
|
|
310
|
+
* (this is where a dynamic `import()` fires); a promise (or plain module) is
|
|
311
|
+
* awaited. Called once per module at the start of the bootstrap phase.
|
|
312
|
+
*/
|
|
313
|
+
declare function resolveModule(input: ArcModuleInput): Promise<ArcModule>;
|
|
314
|
+
/**
|
|
315
|
+
* Order modules for composition by their `dependsOn` edges — a STABLE
|
|
316
|
+
* topological sort. Called once at the start of the bootstrap phase; every
|
|
317
|
+
* subsequent phase (bootstrap, resources, afterResources, and reverse-order
|
|
318
|
+
* onClose) iterates the returned list, so a module's declared dependencies are
|
|
319
|
+
* always composed before it.
|
|
320
|
+
*
|
|
321
|
+
* "Stable" = modules with no edge between them keep their original list order,
|
|
322
|
+
* so declaring `dependsOn` on one module never silently reorders an unrelated
|
|
323
|
+
* one. Backward compatible: a `modules` array with NO `dependsOn` anywhere is
|
|
324
|
+
* returned unchanged.
|
|
325
|
+
*
|
|
326
|
+
* Fail-fast — throws (never reorders past a broken contract) on:
|
|
327
|
+
* - duplicate module names (the name is the graph key)
|
|
328
|
+
* - a `dependsOn` name not present in the composed set
|
|
329
|
+
* - a self-reference (`dependsOn` includes the module's own name)
|
|
330
|
+
* - a dependency cycle (reports the concrete `a → b → … → a` path)
|
|
331
|
+
*/
|
|
332
|
+
declare function orderModules(modules: readonly ArcModule[]): ArcModule[];
|
|
333
|
+
/**
|
|
334
|
+
* Typed module registry — hosts augment this via declaration merging so
|
|
335
|
+
* `getModuleExports(f, "order")` infers the export type without a manual type
|
|
336
|
+
* argument (the fastify / awilix pattern):
|
|
337
|
+
*
|
|
338
|
+
* ```ts
|
|
339
|
+
* declare module "@classytic/arc/factory" {
|
|
340
|
+
* interface ArcModuleRegistry {
|
|
341
|
+
* order: OrderEngine;
|
|
342
|
+
* accounting: AccountingEngine;
|
|
343
|
+
* }
|
|
344
|
+
* }
|
|
345
|
+
* ```
|
|
346
|
+
*
|
|
347
|
+
* Left empty here so the fallback `getModuleExports<T>(f, name: string)` stays
|
|
348
|
+
* available for apps that don't augment it.
|
|
349
|
+
*/
|
|
350
|
+
interface ArcModuleRegistry {}
|
|
351
|
+
/**
|
|
352
|
+
* Identity helper for authoring a typed module — mirrors `defineResource`.
|
|
353
|
+
* Gives inference + a single obvious construction site; does no work.
|
|
354
|
+
*
|
|
355
|
+
* `TExports` is inferred from the `bootstrap` return value, so a module
|
|
356
|
+
* author gets a typed public export for free:
|
|
357
|
+
*
|
|
358
|
+
* ```ts
|
|
359
|
+
* export const accountingModule = (deps: Deps) =>
|
|
360
|
+
* defineModule({
|
|
361
|
+
* name: "accounting",
|
|
362
|
+
* bootstrap: async () => createAccountingEngine(deps), // TExports inferred
|
|
363
|
+
* });
|
|
364
|
+
* ```
|
|
365
|
+
*/
|
|
366
|
+
declare function defineModule<TExports = unknown>(module: ArcModule<TExports>): ArcModule<TExports>;
|
|
367
|
+
/**
|
|
368
|
+
* Typed accessor for a module's public export (its `bootstrap` return value),
|
|
369
|
+
* recorded at `fastify.arc.modules[name]`.
|
|
370
|
+
*
|
|
371
|
+
* Throwing, in line with the fail-fast contract (and `requireOrgId`-style
|
|
372
|
+
* accessors): a missing entry means the module either isn't composed, is
|
|
373
|
+
* composed AFTER the caller (list order = init order), or returned nothing —
|
|
374
|
+
* all wiring bugs that must surface at boot, not as `undefined` downstream.
|
|
375
|
+
*
|
|
376
|
+
* The type parameter is an assertion, not a proof. Two ways to type it:
|
|
377
|
+
* - augment `ArcModuleRegistry` once — then the name alone infers the type:
|
|
378
|
+
* `getModuleExports(f, "accounting")` → `AccountingEngine`.
|
|
379
|
+
* - or pass it inline: `getModuleExports<AccountingEngine>(f, "accounting")`.
|
|
380
|
+
*/
|
|
381
|
+
declare function getModuleExports<K extends keyof ArcModuleRegistry>(fastify: FastifyInstance, name: K): ArcModuleRegistry[K];
|
|
382
|
+
declare function getModuleExports<TExports = unknown>(fastify: FastifyInstance, name: string): TExports;
|
|
383
|
+
//#endregion
|
|
384
|
+
export { getModuleExports as a, LoadResourcesOptions as c, loadResources as d, defineModule as i, ResourceLike as l, ArcModuleInput as n, orderModules as o, ArcModuleRegistry as r, resolveModule as s, ArcModule as t, ResourceModule as u };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { t as getUserRoles } from "./types-XTApa8b6.mjs";
|
|
2
2
|
import { n as convertRouteSchema } from "./schemaConverter-U0MnO9vd.mjs";
|
|
3
|
-
import { t as resolveActionPermission } from "./actionPermissions-
|
|
4
|
-
import { t as pluralize } from "./pluralize-
|
|
5
|
-
import { t as buildActionBodySchema } from "./createActionRouter-
|
|
3
|
+
import { t as resolveActionPermission } from "./actionPermissions-C9RMiIpc.mjs";
|
|
4
|
+
import { t as pluralize } from "./pluralize-BhrgwZb9.mjs";
|
|
5
|
+
import { t as buildActionBodySchema } from "./createActionRouter-HlQso0jO.mjs";
|
|
6
6
|
import fp from "fastify-plugin";
|
|
7
7
|
//#region src/docs/openapi/canonical-schemas.ts
|
|
8
8
|
/**
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { a as applyFieldWritePermissions, c as PermissionCheck, d as UserBase, f as getUserRoles, i as applyFieldReadPermissions, l as PermissionContext, n as FieldPermissionMap, o as fields, p as normalizeRoles, r as FieldPermissionType, s as resolveEffectiveRoles, t as FieldPermission, u as PermissionResult } from "../fields-C7ahdGYf.mjs";
|
|
2
|
-
import { A as requireRoles, C as allOf, D as not, E as denyAll, F as RequireAgentScopeOptions, I as RequireMandateOptions, L as requireAgentScope, M as when, N as applyPermissionResult, O as requireAuth, P as normalizePermissionResult, R as requireDPoP, S as createOrgPermissions, T as anyOf, _ as ConnectEventsOptions, a as presets_d_exports, b as PermissionEventBus, c as readOnly, d as requireOrgRole, f as requireScopeContext, g as createRoleHierarchy, h as RoleHierarchy, i as ownerWithAdminBypass, j as roles, k as requireOwnership, l as requireOrgInScope, m as requireTeamMembership, n as authenticated, o as publicRead, p as requireServiceScope, r as fullPublic, s as publicReadAdminWrite, t as adminOnly, u as requireOrgMembership, v as DynamicPermissionMatrix, w as allowPublic, x as createDynamicPermissionMatrix, y as DynamicPermissionMatrixConfig, z as requireMandate } from "../index-
|
|
2
|
+
import { A as requireRoles, C as allOf, D as not, E as denyAll, F as RequireAgentScopeOptions, I as RequireMandateOptions, L as requireAgentScope, M as when, N as applyPermissionResult, O as requireAuth, P as normalizePermissionResult, R as requireDPoP, S as createOrgPermissions, T as anyOf, _ as ConnectEventsOptions, a as presets_d_exports, b as PermissionEventBus, c as readOnly, d as requireOrgRole, f as requireScopeContext, g as createRoleHierarchy, h as RoleHierarchy, i as ownerWithAdminBypass, j as roles, k as requireOwnership, l as requireOrgInScope, m as requireTeamMembership, n as authenticated, o as publicRead, p as requireServiceScope, r as fullPublic, s as publicReadAdminWrite, t as adminOnly, u as requireOrgMembership, v as DynamicPermissionMatrix, w as allowPublic, x as createDynamicPermissionMatrix, y as DynamicPermissionMatrixConfig, z as requireMandate } from "../index-CdFkIMEd.mjs";
|
|
3
3
|
export { type ConnectEventsOptions, type DynamicPermissionMatrix, type DynamicPermissionMatrixConfig, type FieldPermission, type FieldPermissionMap, type FieldPermissionType, type PermissionCheck, type PermissionContext, type PermissionEventBus, type PermissionResult, type RequireAgentScopeOptions, type RequireMandateOptions, type RoleHierarchy, type UserBase, adminOnly, allOf, allowPublic, anyOf, applyFieldReadPermissions, applyFieldWritePermissions, applyPermissionResult, authenticated, createDynamicPermissionMatrix, createOrgPermissions, createRoleHierarchy, denyAll, fields, fullPublic, getUserRoles, normalizePermissionResult, normalizeRoles, not, ownerWithAdminBypass, presets_d_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAgentScope, requireAuth, requireDPoP, requireMandate, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, resolveEffectiveRoles, roles, when };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { A as requireMandate, C as requireAuth, D as when, E as roles, F as applyFieldWritePermissions, I as fields, L as resolveEffectiveRoles, N as normalizePermissionResult, O as requireAgentScope, P as applyFieldReadPermissions, S as not, T as requireRoles, _ as requireTeamMembership, a as presets_exports, b as anyOf, c as readOnly, d as createOrgPermissions, f as requireOrgInScope, g as requireServiceScope, h as requireScopeContext, i as ownerWithAdminBypass, j as applyPermissionResult, k as requireDPoP, l as createRoleHierarchy, m as requireOrgRole, n as authenticated, o as publicRead, p as requireOrgMembership, r as fullPublic, s as publicReadAdminWrite, t as adminOnly, u as createDynamicPermissionMatrix, v as allOf, w as requireOwnership, x as denyAll, y as allowPublic } from "../permissions-
|
|
1
|
+
import { A as requireMandate, C as requireAuth, D as when, E as roles, F as applyFieldWritePermissions, I as fields, L as resolveEffectiveRoles, N as normalizePermissionResult, O as requireAgentScope, P as applyFieldReadPermissions, S as not, T as requireRoles, _ as requireTeamMembership, a as presets_exports, b as anyOf, c as readOnly, d as createOrgPermissions, f as requireOrgInScope, g as requireServiceScope, h as requireScopeContext, i as ownerWithAdminBypass, j as applyPermissionResult, k as requireDPoP, l as createRoleHierarchy, m as requireOrgRole, n as authenticated, o as publicRead, p as requireOrgMembership, r as fullPublic, s as publicReadAdminWrite, t as adminOnly, u as createDynamicPermissionMatrix, v as allOf, w as requireOwnership, x as denyAll, y as allowPublic } from "../permissions-CgbOLJZG.mjs";
|
|
2
2
|
import { n as normalizeRoles, t as getUserRoles } from "../types-XTApa8b6.mjs";
|
|
3
3
|
export { adminOnly, allOf, allowPublic, anyOf, applyFieldReadPermissions, applyFieldWritePermissions, applyPermissionResult, authenticated, createDynamicPermissionMatrix, createOrgPermissions, createRoleHierarchy, denyAll, fields, fullPublic, getUserRoles, normalizePermissionResult, normalizeRoles, not, ownerWithAdminBypass, presets_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAgentScope, requireAuth, requireDPoP, requireMandate, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, resolveEffectiveRoles, roles, when };
|
|
@@ -167,7 +167,7 @@ function applyFieldWritePermissions(body, fieldPermissions, userRoles) {
|
|
|
167
167
|
function resolveEffectiveRoles(userRoles, orgRoles) {
|
|
168
168
|
if (orgRoles.length === 0) return [...userRoles];
|
|
169
169
|
if (userRoles.length === 0) return [...orgRoles];
|
|
170
|
-
return [
|
|
170
|
+
return [.../* @__PURE__ */ new Set([...userRoles, ...orgRoles])];
|
|
171
171
|
}
|
|
172
172
|
//#endregion
|
|
173
173
|
//#region src/permissions/applyPermissionResult.ts
|
|
@@ -1482,11 +1482,19 @@ function fullPublic(overrides) {
|
|
|
1482
1482
|
/**
|
|
1483
1483
|
* Read-only: list + get authenticated, write operations denied.
|
|
1484
1484
|
* Useful for computed/derived resources.
|
|
1485
|
+
*
|
|
1486
|
+
* Writes carry an explicit `denyAll` check — an omitted CRUD permission
|
|
1487
|
+
* mounts the route with NO gate (public-by-omission), so leaving
|
|
1488
|
+
* create/update/delete undefined here would expose unauthenticated writes.
|
|
1489
|
+
* Hosts that disable write routes entirely (`disabledRoutes`) are unaffected.
|
|
1485
1490
|
*/
|
|
1486
1491
|
function readOnly(overrides) {
|
|
1487
1492
|
return withOverrides({
|
|
1488
1493
|
list: requireAuth(),
|
|
1489
|
-
get: requireAuth()
|
|
1494
|
+
get: requireAuth(),
|
|
1495
|
+
create: denyAll("Write operations are disabled on this read-only resource"),
|
|
1496
|
+
update: denyAll("Write operations are disabled on this read-only resource"),
|
|
1497
|
+
delete: denyAll("Write operations are disabled on this read-only resource")
|
|
1490
1498
|
}, overrides);
|
|
1491
1499
|
}
|
|
1492
1500
|
//#endregion
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Bt as Transform, Ft as NextFunction, It as OperationFilter, Lt as PipelineConfig, Nt as Guard, Pt as Interceptor, Rt as PipelineContext, bt as IControllerResponse, zt as PipelineStep } from "../index-
|
|
1
|
+
import { Bt as Transform, Ft as NextFunction, It as OperationFilter, Lt as PipelineConfig, Nt as Guard, Pt as Interceptor, Rt as PipelineContext, bt as IControllerResponse, zt as PipelineStep } from "../index-_--GyzcO.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/pipeline/guard.d.ts
|
|
4
4
|
interface GuardOptions {
|
package/dist/plugins/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Q as MiddlewareConfig, ft as RouteDefinition, ht as RouteSchemaOptions, nt as PresetHook, qt as AnyRecord } from "../index-
|
|
2
|
-
import { a as arcCorePlugin, i as _default, n as ArcCorePluginOptions, r as PluginMeta, t as ArcCore } from "../fastify-augmentation-
|
|
1
|
+
import { Q as MiddlewareConfig, ft as RouteDefinition, ht as RouteSchemaOptions, nt as PresetHook, qt as AnyRecord } from "../index-_--GyzcO.mjs";
|
|
2
|
+
import { a as arcCorePlugin, i as _default, n as ArcCorePluginOptions, r as PluginMeta, t as ArcCore } from "../fastify-augmentation-CCQJEDgh.mjs";
|
|
3
3
|
import { _ as HealthOptions, a as MetricsCollector, c as metricsPlugin, d as ssePlugin, f as CachingOptions, g as HealthCheck, h as cachingPlugin, i as MetricEntry, l as SSEOptions, m as _default$1, n as _default$7, o as MetricsOptions, p as CachingRule, r as versioningPlugin, s as _default$4, t as VersioningOptions, u as _default$6, v as _default$3, y as healthPlugin } from "../versioning-D_eBCfNr.mjs";
|
|
4
4
|
import { i as errorHandlerPlugin, n as ErrorMapper, r as defaultIsDuplicateKeyError, t as ErrorHandlerOptions } from "../errorHandler-BtUUDPEa.mjs";
|
|
5
5
|
import { t as TracingOptions } from "../tracing-D8jlGXP7.mjs";
|
|
@@ -24,10 +24,15 @@ interface CreatePluginDefinition<TRootOpts extends AnyRecord = AnyRecord, TResou
|
|
|
24
24
|
*/
|
|
25
25
|
forRoot?: (fastify: FastifyInstance, opts: TRootOpts) => void | Promise<void>;
|
|
26
26
|
/**
|
|
27
|
-
* Per-resource configuration function. Called
|
|
28
|
-
*
|
|
27
|
+
* Per-resource configuration function. Called (via `plugin.forResource(opts)`)
|
|
28
|
+
* to PRODUCE a partial resource config — hooks, routes, middlewares — that the
|
|
29
|
+
* host spreads into `defineResource(...)`. It receives only the plugin's own
|
|
30
|
+
* `opts`: the resource does not exist yet at this call site, so it cannot be
|
|
31
|
+
* inspected here (that was a false promise pre-2.20; the unused `resourceConfig`
|
|
32
|
+
* parameter is removed). For behavior that must vary by resource, key off the
|
|
33
|
+
* plugin's `opts` the host passes per resource.
|
|
29
34
|
*/
|
|
30
|
-
forResource?: (
|
|
35
|
+
forResource?: (opts: TResourceOpts) => PluginResourceResult;
|
|
31
36
|
}
|
|
32
37
|
interface ArcPlugin<TRootOpts extends AnyRecord = AnyRecord, TResourceOpts extends AnyRecord = AnyRecord> {
|
|
33
38
|
/** Plugin name */
|
package/dist/plugins/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { p as MUTATION_OPERATIONS } from "../constants-
|
|
1
|
+
import { p as MUTATION_OPERATIONS } from "../constants-DNre0wRg.mjs";
|
|
2
2
|
import { c as getOrgId } from "../types-bHblZ9YN.mjs";
|
|
3
3
|
import { n as requestContext } from "../requestContext-BZKOr13H.mjs";
|
|
4
4
|
import { t as hasEvents } from "../typeGuards-C9KXUly6.mjs";
|
|
5
5
|
import { t as HookSystem } from "../HookSystem-C1vB_Gc9.mjs";
|
|
6
|
-
import { t as ResourceRegistry } from "../ResourceRegistry-
|
|
6
|
+
import { t as ResourceRegistry } from "../ResourceRegistry-7RnrEWNP.mjs";
|
|
7
7
|
import { n as caching_default, t as cachingPlugin } from "../caching-_NJeDd1_.mjs";
|
|
8
8
|
import { n as errorHandlerPlugin, t as defaultIsDuplicateKeyError } from "../errorHandler-Dxf6P_kV.mjs";
|
|
9
9
|
import { n as metrics_default, t as metricsPlugin } from "../metrics-fdxI5mn_.mjs";
|
|
@@ -131,7 +131,7 @@ function createPlugin(name, definition) {
|
|
|
131
131
|
},
|
|
132
132
|
forResource(opts) {
|
|
133
133
|
if (!definition.forResource) return {};
|
|
134
|
-
return definition.forResource(
|
|
134
|
+
return definition.forResource(opts ?? {});
|
|
135
135
|
}
|
|
136
136
|
};
|
|
137
137
|
}
|
|
@@ -58,7 +58,7 @@ try {
|
|
|
58
58
|
function createTracerProvider(options) {
|
|
59
59
|
if (!isAvailable || !NodeTracerProvider || !BatchSpanProcessor || !OTLPTraceExporter) return null;
|
|
60
60
|
const { serviceName = "@classytic/arc", serviceVersion, exporterUrl = "http://localhost:4318/v1/traces" } = options;
|
|
61
|
-
const resolvedVersion = serviceVersion ?? "2.
|
|
61
|
+
const resolvedVersion = serviceVersion ?? "2.20.0";
|
|
62
62
|
const exporter = new OTLPTraceExporter({ url: exporterUrl });
|
|
63
63
|
const provider = new NodeTracerProvider({ resource: { attributes: {
|
|
64
64
|
"service.name": serviceName,
|
|
@@ -34,7 +34,7 @@ const IRREGULARS = {
|
|
|
34
34
|
vertex: "vertices",
|
|
35
35
|
criterion: "criteria"
|
|
36
36
|
};
|
|
37
|
-
const UNCOUNTABLES = new Set([
|
|
37
|
+
const UNCOUNTABLES = /* @__PURE__ */ new Set([
|
|
38
38
|
"sheep",
|
|
39
39
|
"fish",
|
|
40
40
|
"deer",
|
|
@@ -65,7 +65,7 @@ function pluralize(word) {
|
|
|
65
65
|
if (lower.endsWith("f") && !lower.endsWith("ff") && !lower.endsWith("roof") && !lower.endsWith("chief") && !lower.endsWith("belief")) return `${word.slice(0, -1)}ves`;
|
|
66
66
|
if (lower.endsWith("y") && !/[aeiou]y$/i.test(lower)) return `${word.slice(0, -1)}ies`;
|
|
67
67
|
if (lower.endsWith("is")) return `${word.slice(0, -2)}es`;
|
|
68
|
-
if (new Set([
|
|
68
|
+
if ((/* @__PURE__ */ new Set([
|
|
69
69
|
"cactus",
|
|
70
70
|
"stimulus",
|
|
71
71
|
"focus",
|
|
@@ -76,7 +76,7 @@ function pluralize(word) {
|
|
|
76
76
|
"alumnus",
|
|
77
77
|
"terminus",
|
|
78
78
|
"bacillus"
|
|
79
|
-
]).has(lower)) return `${word.slice(0, -2)}i`;
|
|
79
|
+
])).has(lower)) return `${word.slice(0, -2)}i`;
|
|
80
80
|
if (lower.endsWith("z") && !lower.endsWith("zz")) return `${word}zes`;
|
|
81
81
|
if (/(?:s|sh|ch|x|zz)$/i.test(lower)) return `${word}es`;
|
|
82
82
|
if (lower.endsWith("o") && !/[aeiou]o$/i.test(lower)) return `${word}es`;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { rt as PresetResult } from "../index-
|
|
1
|
+
import { rt as PresetResult } from "../index-_--GyzcO.mjs";
|
|
2
2
|
import { i as RequestScope } from "../types-LNebCoJx.mjs";
|
|
3
3
|
import { c as PermissionCheck } from "../fields-C7ahdGYf.mjs";
|
|
4
4
|
import { a as StorageReadResult, i as StorageReadRange, n as StorageContext, o as StorageUploadInput, r as StorageFile, t as Storage } from "../storage-Co_PQpeQ.mjs";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { i as NotFoundError, u as ValidationError } from "../errors-DkO8Nk6-.mjs";
|
|
2
2
|
import { c as getOrgId, g as getUserId } from "../types-bHblZ9YN.mjs";
|
|
3
|
-
import { C as requireAuth, y as allowPublic } from "../permissions-
|
|
3
|
+
import { C as requireAuth, y as allowPublic } from "../permissions-CgbOLJZG.mjs";
|
|
4
4
|
import { t as multipartBody } from "../multipartBody-CHEQSZ6G.mjs";
|
|
5
5
|
//#region src/presets/filesUpload.ts
|
|
6
6
|
const DEFAULT_FIELD_NAME = "file";
|
package/dist/presets/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { bt as IControllerResponse, d as PaginationResult, qt as AnyRecord, rt as PresetResult, st as ResourceConfig, xt as IRequestContext } from "../index-
|
|
1
|
+
import { bt as IControllerResponse, d as PaginationResult, qt as AnyRecord, rt as PresetResult, st as ResourceConfig, xt as IRequestContext } from "../index-_--GyzcO.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";
|
|
@@ -237,7 +237,21 @@ type IAuditedPreset = never;
|
|
|
237
237
|
* }
|
|
238
238
|
* ```
|
|
239
239
|
*/
|
|
240
|
-
|
|
240
|
+
/** Preset name → controller contract. Lookup table for {@link IPresetController}. */
|
|
241
|
+
interface PresetControllerContracts<TDoc> {
|
|
242
|
+
softDelete: ISoftDeleteController<TDoc>;
|
|
243
|
+
slugLookup: ISlugLookupController<TDoc>;
|
|
244
|
+
tree: ITreeController<TDoc>;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Collapse a union into an intersection. The pre-2.20 implementation used a
|
|
248
|
+
* distributive conditional, so `IPresetController<T, 'softDelete' | 'tree'>`
|
|
249
|
+
* produced a UNION of contracts — which a class cannot `implements`; the
|
|
250
|
+
* documented multi-preset example didn't compile. An indexed lookup over the
|
|
251
|
+
* union followed by this fold yields the intersection the example promises.
|
|
252
|
+
*/
|
|
253
|
+
type UnionToIntersection<U> = (U extends unknown ? (x: U) => void : never) extends ((x: infer I) => void) ? I : never;
|
|
254
|
+
type IPresetController<TDoc = unknown, TPresets extends keyof PresetControllerContracts<TDoc> = never> = UnionToIntersection<PresetControllerContracts<TDoc>[TPresets]>;
|
|
241
255
|
//#endregion
|
|
242
256
|
//#region src/presets/index.d.ts
|
|
243
257
|
/**
|
package/dist/presets/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { multiTenantPreset } from "./multiTenant.mjs";
|
|
2
|
-
import { a as registerPreset, c as auditedPreset, d as ownedByUserPreset, i as getPreset, l as softDeletePreset, n as flexibleMultiTenantPreset, o as treePreset, r as getAvailablePresets, s as bulkPreset, t as applyPresets, u as slugLookupPreset } from "../presets-
|
|
2
|
+
import { a as registerPreset, c as auditedPreset, d as ownedByUserPreset, i as getPreset, l as softDeletePreset, n as flexibleMultiTenantPreset, o as treePreset, r as getAvailablePresets, s as bulkPreset, t as applyPresets, u as slugLookupPreset } from "../presets-DWsYQdbV.mjs";
|
|
3
3
|
import { filesUploadPreset } from "./filesUpload.mjs";
|
|
4
4
|
import { searchPreset } from "./search.mjs";
|
|
5
5
|
export { applyPresets, auditedPreset, bulkPreset, filesUploadPreset, flexibleMultiTenantPreset, getAvailablePresets, getPreset, multiTenantPreset, ownedByUserPreset, registerPreset, searchPreset, slugLookupPreset, softDeletePreset, treePreset };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ft as RouteDefinition, gt as ControllerHandler, pt as RouteMcpConfig, rt as PresetResult } from "../index-
|
|
1
|
+
import { ft as RouteDefinition, gt as ControllerHandler, pt as RouteMcpConfig, rt as PresetResult } from "../index-_--GyzcO.mjs";
|
|
2
2
|
import { c as PermissionCheck } from "../fields-C7ahdGYf.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/presets/search.d.ts
|
package/dist/presets/search.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as requireAuth, y as allowPublic } from "../permissions-
|
|
1
|
+
import { C as requireAuth, y as allowPublic } from "../permissions-CgbOLJZG.mjs";
|
|
2
2
|
//#region src/presets/search.ts
|
|
3
3
|
const BUILTINS = [
|
|
4
4
|
{
|
|
@@ -84,7 +84,8 @@ function autoHandlerFor(repo, method) {
|
|
|
84
84
|
return fn(body.input ?? body);
|
|
85
85
|
};
|
|
86
86
|
if (method === "searchSimilar") return async (req) => {
|
|
87
|
-
|
|
87
|
+
const body = req.body ?? {};
|
|
88
|
+
return fn(body);
|
|
88
89
|
};
|
|
89
90
|
return async (req) => {
|
|
90
91
|
const body = req.body ?? {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { b as isElevated, n as PUBLIC_SCOPE } from "./types-bHblZ9YN.mjs";
|
|
2
|
-
import { C as requireAuth, T as requireRoles, y as allowPublic } from "./permissions-
|
|
2
|
+
import { C as requireAuth, T as requireRoles, y as allowPublic } from "./permissions-CgbOLJZG.mjs";
|
|
3
3
|
import { multiTenantPreset } from "./presets/multiTenant.mjs";
|
|
4
4
|
//#region src/presets/ownedByUser.ts
|
|
5
5
|
/**
|