@classytic/arc 2.7.7 → 2.8.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/README.md +11 -2
- package/dist/{BaseController-CpMfCXdn.mjs → BaseController-DAGGc5Xn.mjs} +76 -25
- package/dist/{EventTransport-C4VheKeC.d.mts → EventTransport-CLXJUzyT.d.mts} +37 -1
- package/dist/{ResourceRegistry-DsHiG9cL.mjs → ResourceRegistry-Dtcojmu8.mjs} +14 -2
- package/dist/adapters/index.d.mts +2 -2
- package/dist/adapters/index.mjs +1 -1
- package/dist/{adapters-BxGgSHjj.mjs → adapters-BBqAVvPK.mjs} +11 -0
- package/dist/audit/index.d.mts +1 -1
- package/dist/audit/index.mjs +1 -1
- package/dist/audit/mongodb.d.mts +1 -1
- package/dist/audit/mongodb.mjs +1 -1
- package/dist/auth/index.d.mts +4 -4
- package/dist/auth/index.mjs +3 -3
- package/dist/auth/redis-session.d.mts +1 -1
- package/dist/{betterAuthOpenApi-EkPaMWNM.mjs → betterAuthOpenApi-C5lDyRH2.mjs} +1 -1
- package/dist/cache/index.d.mts +2 -2
- package/dist/cache/index.mjs +1 -1
- package/dist/cli/commands/docs.mjs +2 -2
- package/dist/cli/commands/generate.mjs +1 -1
- package/dist/cli/commands/introspect.mjs +1 -1
- package/dist/core/index.d.mts +2 -2
- package/dist/core/index.mjs +4 -3
- package/dist/core-CrLDuqoT.mjs +34 -0
- package/dist/{core-B_zEeA2b.mjs → createActionRouter-Df1BuawX.mjs} +88 -52
- package/dist/{createApp-D7e77m8C.mjs → createApp-p2OThysU.mjs} +10 -10
- package/dist/{defineResource-BW2dMCu9.mjs → defineResource-CqeUltrW.mjs} +91 -8
- package/dist/docs/index.d.mts +2 -2
- package/dist/docs/index.mjs +1 -1
- package/dist/dynamic/index.d.mts +2 -2
- package/dist/dynamic/index.mjs +1 -1
- package/dist/{elevation-By_p2lnn.mjs → elevation-BBGFjzIP.mjs} +1 -1
- package/dist/{errorHandler-CH8wk1eD.mjs → errorHandler-Cw34h_om.mjs} +1 -1
- package/dist/{errorHandler-pCpEtNd7.d.mts → errorHandler-DJ7OAB2V.d.mts} +1 -1
- package/dist/{eventPlugin-CdvUoUna.d.mts → eventPlugin-Cdjwo0Gv.d.mts} +1 -1
- package/dist/{eventPlugin-B6U_nCFU.mjs → eventPlugin-XijlQmlL.mjs} +19 -1
- package/dist/events/index.d.mts +399 -28
- package/dist/events/index.mjs +345 -29
- package/dist/events/transports/redis-stream-entry.d.mts +1 -1
- package/dist/events/transports/redis.d.mts +1 -1
- package/dist/factory/index.d.mts +1 -1
- package/dist/factory/index.mjs +1 -1
- package/dist/hooks/index.d.mts +1 -1
- package/dist/hooks/index.mjs +1 -1
- package/dist/idempotency/index.d.mts +3 -3
- package/dist/idempotency/mongodb.d.mts +1 -1
- package/dist/idempotency/redis.d.mts +1 -1
- package/dist/{index-C9eYNjGR.d.mts → index-0zj73o2U.d.mts} +1 -1
- package/dist/{index-B0extFr4.d.mts → index-CBru2y5Y.d.mts} +3 -3
- package/dist/{index-BjShrzoj.d.mts → index-DadoLP51.d.mts} +48 -16
- package/dist/index.d.mts +8 -8
- package/dist/index.mjs +8 -8
- package/dist/integrations/event-gateway.d.mts +1 -1
- package/dist/integrations/event-gateway.mjs +1 -1
- 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/{interface-B91alUzq.d.mts → interface-CS6d7HiB.d.mts} +693 -110
- package/dist/{mongodb-Cgu9F1Nd.d.mts → mongodb-B1eVtFhw.d.mts} +1 -1
- package/dist/{mongodb-B7zupyck.d.mts → mongodb-NShVZDMr.d.mts} +1 -1
- package/dist/{openapi-D7Z7VODz.mjs → openapi-q6rNKfZy.mjs} +49 -2
- package/dist/org/index.d.mts +2 -2
- package/dist/permissions/index.d.mts +3 -3
- package/dist/plugins/index.d.mts +4 -4
- package/dist/plugins/index.mjs +9 -9
- package/dist/plugins/tracing-entry.d.mts +1 -1
- package/dist/plugins/tracing-entry.mjs +1 -1
- package/dist/policies/index.d.mts +1 -1
- package/dist/presets/index.d.mts +3 -3
- package/dist/presets/multiTenant.d.mts +1 -1
- package/dist/{queryCachePlugin-Ckl71mkc.d.mts → queryCachePlugin-BCFVXnxK.d.mts} +1 -1
- package/dist/{redis-3TQxm2VZ.d.mts → redis-Bunu3qWg.d.mts} +1 -1
- package/dist/{redis-stream-Dag5LFa9.d.mts → redis-stream-BgrYzpeq.d.mts} +1 -1
- package/dist/registry/index.d.mts +1 -1
- package/dist/registry/index.mjs +2 -2
- package/dist/{resourceToTools-BJkoQoUP.mjs → resourceToTools-DNNWnZtx.mjs} +194 -64
- package/dist/rpc/index.d.mts +1 -1
- package/dist/rpc/index.mjs +1 -1
- package/dist/scope/index.d.mts +2 -2
- package/dist/scope/index.mjs +1 -1
- package/dist/{sse-6W0hjVS_.mjs → sse-CD5Hghpu.mjs} +1 -1
- package/dist/testing/index.d.mts +2 -2
- package/dist/testing/index.mjs +1 -1
- package/dist/types/index.d.mts +5 -5
- package/dist/{types-CKB47kiu.d.mts → types-BlOuKTPw.d.mts} +9 -9
- package/dist/{types-B4BNthET.d.mts → types-BoaZHr-2.d.mts} +1 -1
- package/dist/{types-C5g2oRC7.d.mts → types-D3b7hA00.d.mts} +1 -1
- package/dist/utils/index.d.mts +4 -16
- package/dist/utils/index.mjs +5 -5
- package/dist/{utils-B-l6410F.mjs → utils-7sJ8X83I.mjs} +1 -13
- package/package.json +6 -5
- package/skills/arc/SKILL.md +23 -4
- package/skills/arc/references/integrations.md +1 -1
- package/skills/arc/references/mcp.md +2 -0
- /package/dist/{HookSystem-BNYKnrXF.mjs → HookSystem-BjFu7zf1.mjs} +0 -0
- /package/dist/{caching-5DtLwIqb.mjs → caching-CHH-iHs3.mjs} +0 -0
- /package/dist/{circuitBreaker-BBPDt-J_.d.mts → circuitBreaker-BGVoB1hD.d.mts} +0 -0
- /package/dist/{circuitBreaker-l18oRgL5.mjs → circuitBreaker-cmi5XDv5.mjs} +0 -0
- /package/dist/{elevation-D7WK0RXq.d.mts → elevation-UJO3-NvX.d.mts} +0 -0
- /package/dist/{errors-Cg58SLNi.mjs → errors-BF2bIOIS.mjs} +0 -0
- /package/dist/{errors-BS6lZvWy.d.mts → errors-BI8kEKsO.d.mts} +0 -0
- /package/dist/{externalPaths-iba7jD3d.d.mts → externalPaths-BQ8QijNH.d.mts} +0 -0
- /package/dist/{fields-D4nMDqnK.d.mts → fields-DoeDgh2b.d.mts} +0 -0
- /package/dist/{interface-CSbZdv_3.d.mts → interface-CkkWm5uR.d.mts} +0 -0
- /package/dist/{interface-CG7oRZjX.d.mts → interface-bpoLKKqx.d.mts} +0 -0
- /package/dist/{logger-DLg8-Ueg.mjs → logger-CDjpjySd.mjs} +0 -0
- /package/dist/{metrics-Qnvwc-LQ.mjs → metrics-DuhiSEZI.mjs} +0 -0
- /package/dist/{mongodb-B7X7P1P8.mjs → mongodb-5Ff3w8jy.mjs} +0 -0
- /package/dist/{pluralize-Dckfq6US.mjs → pluralize-BneOJkpi.mjs} +0 -0
- /package/dist/{queryCachePlugin-CwTpR04-.mjs → queryCachePlugin-D0iIVhW_.mjs} +0 -0
- /package/dist/{registry-B3lRFBWo.mjs → registry-B0Wl7uVV.mjs} +0 -0
- /package/dist/{replyHelpers-uDUIYh7u.mjs → replyHelpers-CXtJDAZ0.mjs} +0 -0
- /package/dist/{requestContext-xHIKedG6.mjs → requestContext-DYvHl113.mjs} +0 -0
- /package/dist/{schemaConverter-Y5EejTnJ.mjs → schemaConverter-OxfCshus.mjs} +0 -0
- /package/dist/{sessionManager-CEo9jwPI.d.mts → sessionManager-BkzVU8h2.d.mts} +0 -0
- /package/dist/{tracing-DEqdGkr-.d.mts → tracing-xqXzWeaf.d.mts} +0 -0
- /package/dist/{types--D3vvfdt.d.mts → types-CN6JvmYz.d.mts} +0 -0
- /package/dist/{versioning-CdBbFefk.mjs → versioning-CPU_5Xfs.mjs} +0 -0
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
import { t as __exportAll } from "./chunk-BpYLSNr0.mjs";
|
|
1
2
|
import { n as normalizePermissionResult, t as applyPermissionResult } from "./applyPermissionResult-D6GPMsvh.mjs";
|
|
2
|
-
import {
|
|
3
|
+
import { a as toJsonSchema } from "./schemaConverter-OxfCshus.mjs";
|
|
3
4
|
//#region src/core/createActionRouter.ts
|
|
5
|
+
var createActionRouter_exports = /* @__PURE__ */ __exportAll({
|
|
6
|
+
buildActionBodySchema: () => buildActionBodySchema,
|
|
7
|
+
createActionRouter: () => createActionRouter
|
|
8
|
+
});
|
|
4
9
|
/**
|
|
5
10
|
* Create action-based state transition endpoint
|
|
6
11
|
*
|
|
@@ -17,19 +22,7 @@ function createActionRouter(fastify, config) {
|
|
|
17
22
|
fastify.log.warn("[createActionRouter] No actions defined, skipping route creation");
|
|
18
23
|
return;
|
|
19
24
|
}
|
|
20
|
-
const
|
|
21
|
-
type: "string",
|
|
22
|
-
enum: actionEnum,
|
|
23
|
-
description: `Action to perform: ${actionEnum.join(" | ")}`
|
|
24
|
-
} };
|
|
25
|
-
Object.entries(actionSchemas).forEach(([actionName, schema]) => {
|
|
26
|
-
if (schema && typeof schema === "object") Object.entries(schema).forEach(([propName, propSchema]) => {
|
|
27
|
-
bodyProperties[propName] = {
|
|
28
|
-
...propSchema,
|
|
29
|
-
description: `${propSchema.description || ""} (for ${actionName} action)`.trim()
|
|
30
|
-
};
|
|
31
|
-
});
|
|
32
|
-
});
|
|
25
|
+
const bodySchema = buildActionBodySchema(actionEnum, actionSchemas);
|
|
33
26
|
const routeSchema = {
|
|
34
27
|
tags: tag ? [tag] : void 0,
|
|
35
28
|
summary: `Perform action (${actionEnum.join("/")})`,
|
|
@@ -42,11 +35,7 @@ function createActionRouter(fastify, config) {
|
|
|
42
35
|
} },
|
|
43
36
|
required: ["id"]
|
|
44
37
|
},
|
|
45
|
-
body:
|
|
46
|
-
type: "object",
|
|
47
|
-
properties: bodyProperties,
|
|
48
|
-
required: ["action"]
|
|
49
|
-
}
|
|
38
|
+
body: bodySchema
|
|
50
39
|
};
|
|
51
40
|
const preHandler = [];
|
|
52
41
|
const hasPublicActions = Object.entries(actionPermissions).some(([, p]) => p?._isPublic) || globalAuth && globalAuth?._isPublic;
|
|
@@ -165,6 +154,85 @@ function createActionRouter(fastify, config) {
|
|
|
165
154
|
}, "[createActionRouter] Registered action endpoint: POST /:id/action");
|
|
166
155
|
}
|
|
167
156
|
/**
|
|
157
|
+
* Build a discriminated body schema for the unified action endpoint.
|
|
158
|
+
*
|
|
159
|
+
* Produces a schema of the form:
|
|
160
|
+
* ```json
|
|
161
|
+
* {
|
|
162
|
+
* "type": "object",
|
|
163
|
+
* "required": ["action"],
|
|
164
|
+
* "oneOf": [
|
|
165
|
+
* { "properties": { "action": { "const": "dispatch" }, "carrier": {...} }, "required": ["action", "carrier"] },
|
|
166
|
+
* { "properties": { "action": { "const": "approve" } }, "required": ["action"] }
|
|
167
|
+
* ]
|
|
168
|
+
* }
|
|
169
|
+
* ```
|
|
170
|
+
*
|
|
171
|
+
* AJV validates this natively, so an action call missing required fields is
|
|
172
|
+
* rejected with HTTP 400 before the handler ever runs.
|
|
173
|
+
*
|
|
174
|
+
* Exported so OpenAPI generation and MCP tool generation can reuse the same
|
|
175
|
+
* schema shape (single source of truth).
|
|
176
|
+
*/
|
|
177
|
+
function buildActionBodySchema(actionEnum, actionSchemas = {}) {
|
|
178
|
+
const branches = [];
|
|
179
|
+
for (const actionName of actionEnum) {
|
|
180
|
+
const raw = actionSchemas[actionName];
|
|
181
|
+
const { properties, required } = normalizeActionSchema(raw);
|
|
182
|
+
const branchProperties = {
|
|
183
|
+
action: {
|
|
184
|
+
type: "string",
|
|
185
|
+
const: actionName
|
|
186
|
+
},
|
|
187
|
+
...properties
|
|
188
|
+
};
|
|
189
|
+
const branchRequired = ["action", ...required.filter((r) => r !== "action")];
|
|
190
|
+
branches.push({
|
|
191
|
+
type: "object",
|
|
192
|
+
properties: branchProperties,
|
|
193
|
+
required: branchRequired
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
return {
|
|
197
|
+
type: "object",
|
|
198
|
+
required: ["action"],
|
|
199
|
+
oneOf: branches
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Normalize the accepted schema shapes into `{ properties, required }`.
|
|
204
|
+
*
|
|
205
|
+
* Handles:
|
|
206
|
+
* 1. Full JSON Schema object (has `type: 'object'` + `properties`)
|
|
207
|
+
* 2. Zod v4 schema (has `_zod` marker) — converted via `toJsonSchema`
|
|
208
|
+
* 3. Legacy field map (`{ fieldName: { type: 'string' } }`) — every field required
|
|
209
|
+
* unless its schema has `nullable: true` or sentinel `required: false`
|
|
210
|
+
*/
|
|
211
|
+
function normalizeActionSchema(raw) {
|
|
212
|
+
if (!raw || typeof raw !== "object") return {
|
|
213
|
+
properties: {},
|
|
214
|
+
required: []
|
|
215
|
+
};
|
|
216
|
+
const converted = toJsonSchema(raw);
|
|
217
|
+
if (converted && typeof converted === "object" && (converted.type === "object" || "properties" in converted)) return {
|
|
218
|
+
properties: converted.properties ?? {},
|
|
219
|
+
required: Array.isArray(converted.required) ? converted.required : []
|
|
220
|
+
};
|
|
221
|
+
const properties = {};
|
|
222
|
+
const required = [];
|
|
223
|
+
for (const [fieldName, fieldSchema] of Object.entries(raw)) {
|
|
224
|
+
if (fieldName === "type" || fieldName === "properties" || fieldName === "required") continue;
|
|
225
|
+
if (!fieldSchema || typeof fieldSchema !== "object") continue;
|
|
226
|
+
const fs = fieldSchema;
|
|
227
|
+
properties[fieldName] = fs;
|
|
228
|
+
if (fs.required !== false) required.push(fieldName);
|
|
229
|
+
}
|
|
230
|
+
return {
|
|
231
|
+
properties,
|
|
232
|
+
required
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
168
236
|
* Build description with action details
|
|
169
237
|
* Uses _roles metadata from PermissionCheck functions for OpenAPI docs
|
|
170
238
|
*/
|
|
@@ -178,36 +246,4 @@ function buildActionDescription(actions, actionPermissions) {
|
|
|
178
246
|
return lines.join("\n");
|
|
179
247
|
}
|
|
180
248
|
//#endregion
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* Define multiple resources from a shared base config and per-variant overrides.
|
|
184
|
-
*
|
|
185
|
-
* Each variant is independently passed through `defineResource()` — the
|
|
186
|
-
* returned `ResourceDefinition`s are real, fully-registered resources.
|
|
187
|
-
* Register each one's plugin in your app:
|
|
188
|
-
*
|
|
189
|
-
* ```typescript
|
|
190
|
-
* await app.register(articlePublic.toPlugin());
|
|
191
|
-
* await app.register(articleAdmin.toPlugin());
|
|
192
|
-
* ```
|
|
193
|
-
*
|
|
194
|
-
* @param base Shared config — adapter, queryParser, schemaOptions, hooks, etc.
|
|
195
|
-
* Must NOT include `name` or `prefix` (those are per-variant).
|
|
196
|
-
* @param variants Map of variant key → override. Each variant must declare
|
|
197
|
-
* its own `name` and `prefix`. Other fields override the base.
|
|
198
|
-
* @returns A record where each key from `variants` maps to a real
|
|
199
|
-
* `ResourceDefinition` ready for `.toPlugin()` registration.
|
|
200
|
-
*/
|
|
201
|
-
function defineResourceVariants(base, variants) {
|
|
202
|
-
const out = {};
|
|
203
|
-
for (const key of Object.keys(variants)) {
|
|
204
|
-
const override = variants[key];
|
|
205
|
-
out[key] = defineResource({
|
|
206
|
-
...base,
|
|
207
|
-
...override
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
return out;
|
|
211
|
-
}
|
|
212
|
-
//#endregion
|
|
213
|
-
export { createActionRouter as n, defineResourceVariants as t };
|
|
249
|
+
export { createActionRouter as n, createActionRouter_exports as r, buildActionBodySchema as t };
|
|
@@ -207,7 +207,7 @@ async function registerArcCore(fastify, config, trackPlugin) {
|
|
|
207
207
|
await fastify.register(arcCorePlugin, { emitEvents: config.arcPlugins?.emitEvents !== false });
|
|
208
208
|
trackPlugin("arc-core");
|
|
209
209
|
if (config.arcPlugins?.events !== false) {
|
|
210
|
-
const { default: eventPlugin } = await import("./eventPlugin-
|
|
210
|
+
const { default: eventPlugin } = await import("./eventPlugin-XijlQmlL.mjs").then((n) => n.n);
|
|
211
211
|
const eventOpts = typeof config.arcPlugins?.events === "object" ? config.arcPlugins.events : {};
|
|
212
212
|
await fastify.register(eventPlugin, {
|
|
213
213
|
...eventOpts,
|
|
@@ -243,13 +243,13 @@ async function registerArcPlugins(fastify, config, trackPlugin, modules) {
|
|
|
243
243
|
trackPlugin("arc-graceful-shutdown");
|
|
244
244
|
}
|
|
245
245
|
if (config.arcPlugins?.caching) {
|
|
246
|
-
const { default: cachingPlugin } = await import("./caching-
|
|
246
|
+
const { default: cachingPlugin } = await import("./caching-CHH-iHs3.mjs").then((n) => n.r);
|
|
247
247
|
const opts = config.arcPlugins.caching === true ? {} : config.arcPlugins.caching;
|
|
248
248
|
await fastify.register(cachingPlugin, opts);
|
|
249
249
|
trackPlugin("arc-caching", opts);
|
|
250
250
|
}
|
|
251
251
|
if (config.arcPlugins?.queryCache) {
|
|
252
|
-
const { queryCachePlugin } = await import("./queryCachePlugin-
|
|
252
|
+
const { queryCachePlugin } = await import("./queryCachePlugin-D0iIVhW_.mjs").then((n) => n.n);
|
|
253
253
|
const opts = config.arcPlugins.queryCache === true ? {} : config.arcPlugins.queryCache;
|
|
254
254
|
const store = config.stores?.queryCache ?? new (await (import("./memory-Cp7_cAko.mjs").then((n) => n.n))).MemoryCacheStore();
|
|
255
255
|
await fastify.register(queryCachePlugin, {
|
|
@@ -260,19 +260,19 @@ async function registerArcPlugins(fastify, config, trackPlugin, modules) {
|
|
|
260
260
|
}
|
|
261
261
|
if (config.arcPlugins?.sse) if (config.arcPlugins?.events === false) fastify.log.warn("SSE plugin requires events plugin (arcPlugins.events). SSE disabled.");
|
|
262
262
|
else {
|
|
263
|
-
const { default: ssePlugin } = await import("./sse-
|
|
263
|
+
const { default: ssePlugin } = await import("./sse-CD5Hghpu.mjs").then((n) => n.r);
|
|
264
264
|
const opts = config.arcPlugins.sse === true ? {} : config.arcPlugins.sse;
|
|
265
265
|
await fastify.register(ssePlugin, opts);
|
|
266
266
|
trackPlugin("arc-sse", opts);
|
|
267
267
|
}
|
|
268
268
|
if (config.arcPlugins?.metrics) {
|
|
269
|
-
const { default: metricsPlugin } = await import("./metrics-
|
|
269
|
+
const { default: metricsPlugin } = await import("./metrics-DuhiSEZI.mjs").then((n) => n.r);
|
|
270
270
|
const opts = config.arcPlugins.metrics === true ? {} : config.arcPlugins.metrics;
|
|
271
271
|
await fastify.register(metricsPlugin, opts);
|
|
272
272
|
trackPlugin("arc-metrics", opts);
|
|
273
273
|
}
|
|
274
274
|
if (config.arcPlugins?.versioning) {
|
|
275
|
-
const { default: versioningPlugin } = await import("./versioning-
|
|
275
|
+
const { default: versioningPlugin } = await import("./versioning-CPU_5Xfs.mjs").then((n) => n.r);
|
|
276
276
|
await fastify.register(versioningPlugin, config.arcPlugins.versioning);
|
|
277
277
|
trackPlugin("arc-versioning", config.arcPlugins.versioning);
|
|
278
278
|
}
|
|
@@ -340,7 +340,7 @@ async function registerAuth(fastify, config, trackPlugin) {
|
|
|
340
340
|
*/
|
|
341
341
|
async function registerElevation(fastify, config, trackPlugin) {
|
|
342
342
|
if (!config.elevation) return;
|
|
343
|
-
const { elevationPlugin } = await import("./elevation-
|
|
343
|
+
const { elevationPlugin } = await import("./elevation-BBGFjzIP.mjs").then((n) => n.r);
|
|
344
344
|
await fastify.register(elevationPlugin, config.elevation);
|
|
345
345
|
trackPlugin("arc-elevation", config.elevation);
|
|
346
346
|
fastify.log.debug("Elevation plugin enabled");
|
|
@@ -350,7 +350,7 @@ async function registerElevation(fastify, config, trackPlugin) {
|
|
|
350
350
|
*/
|
|
351
351
|
async function registerErrorHandler(fastify, config, trackPlugin) {
|
|
352
352
|
if (config.errorHandler === false) return;
|
|
353
|
-
const { errorHandlerPlugin } = await import("./errorHandler-
|
|
353
|
+
const { errorHandlerPlugin } = await import("./errorHandler-Cw34h_om.mjs").then((n) => n.n);
|
|
354
354
|
const errorOpts = typeof config.errorHandler === "object" ? config.errorHandler : { includeStack: config.preset !== "production" };
|
|
355
355
|
await fastify.register(errorHandlerPlugin, errorOpts);
|
|
356
356
|
trackPlugin("arc-error-handler", errorOpts);
|
|
@@ -667,7 +667,7 @@ function validateDistributedRuntime(options) {
|
|
|
667
667
|
*/
|
|
668
668
|
async function createApp(options) {
|
|
669
669
|
if (options.debug !== void 0 && options.debug !== false) {
|
|
670
|
-
const { configureArcLogger } = await import("./logger-
|
|
670
|
+
const { configureArcLogger } = await import("./logger-CDjpjySd.mjs").then((n) => n.r);
|
|
671
671
|
configureArcLogger({ debug: options.debug });
|
|
672
672
|
}
|
|
673
673
|
validateAuthOptions(options);
|
|
@@ -720,7 +720,7 @@ async function createApp(options) {
|
|
|
720
720
|
await registerErrorHandler(fastify, config, trackPlugin);
|
|
721
721
|
await registerResources(fastify, config);
|
|
722
722
|
if (config.replyHelpers) {
|
|
723
|
-
const { replyHelpersPlugin } = await import("./replyHelpers-
|
|
723
|
+
const { replyHelpersPlugin } = await import("./replyHelpers-CXtJDAZ0.mjs").then((n) => n.n);
|
|
724
724
|
await fastify.register(replyHelpersPlugin);
|
|
725
725
|
}
|
|
726
726
|
if (config.serializeBigInt) fastify.addHook("preSerialization", async (_request, _reply, payload) => {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { s as DEFAULT_UPDATE_METHOD, t as CRUD_OPERATIONS } from "./constants-Cxde4rpC.mjs";
|
|
2
2
|
import { _ as isElevated, n as PUBLIC_SCOPE, v as isMember } from "./types-AOD8fxIw.mjs";
|
|
3
|
-
import { t as BaseController } from "./BaseController-
|
|
3
|
+
import { t as BaseController } from "./BaseController-DAGGc5Xn.mjs";
|
|
4
4
|
import { i as resolveEffectiveRoles, t as applyFieldReadPermissions } from "./fields-ipsbIRPK.mjs";
|
|
5
5
|
import { t as getUserRoles } from "./types-ZUu_h0jp.mjs";
|
|
6
6
|
import { n as normalizePermissionResult, t as applyPermissionResult } from "./applyPermissionResult-D6GPMsvh.mjs";
|
|
7
|
-
import { t as
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
7
|
+
import { n as convertRouteSchema, t as convertOpenApiSchemas } from "./schemaConverter-OxfCshus.mjs";
|
|
8
|
+
import { t as requestContext } from "./requestContext-DYvHl113.mjs";
|
|
9
|
+
import { i as getDefaultCrudSchemas } from "./utils-7sJ8X83I.mjs";
|
|
10
|
+
import { r as ForbiddenError } from "./errors-BF2bIOIS.mjs";
|
|
11
11
|
import { t as hasEvents } from "./typeGuards-CcFZXgU7.mjs";
|
|
12
12
|
import { r as getAvailablePresets, t as applyPresets } from "./presets-BFrGvvjL.mjs";
|
|
13
13
|
//#region src/pipeline/pipe.ts
|
|
@@ -888,6 +888,25 @@ function defineResource(config) {
|
|
|
888
888
|
if (typeof route.permissions !== "function") throw new Error(`[Arc] Resource '${config.name}' route ${route.method} ${route.path}: permissions is required and must be a PermissionCheck function.\nUse allowPublic() or requireAuth() from @classytic/arc/permissions.`);
|
|
889
889
|
if (typeof route.wrapHandler !== "boolean") throw new Error(`[Arc] Resource '${config.name}' route ${route.method} ${route.path}: wrapHandler is required.\nSet true for ControllerHandler (context object) or false for FastifyHandler (req, reply).`);
|
|
890
890
|
}
|
|
891
|
+
if (config.routes && config.additionalRoutes) throw new Error(`[Arc] Resource '${config.name}': Cannot use both 'routes' and 'additionalRoutes'.\nUse 'routes' (v2.8) — it replaces 'additionalRoutes'.`);
|
|
892
|
+
for (const route of config.routes ?? []) if (typeof route.permissions !== "function") throw new Error(`[Arc] Resource '${config.name}' route ${route.method} ${route.path}: permissions is required and must be a PermissionCheck function.`);
|
|
893
|
+
if (config.actions) {
|
|
894
|
+
const CRUD_OPS = new Set([
|
|
895
|
+
"create",
|
|
896
|
+
"update",
|
|
897
|
+
"delete",
|
|
898
|
+
"list",
|
|
899
|
+
"get"
|
|
900
|
+
]);
|
|
901
|
+
for (const [name, entry] of Object.entries(config.actions)) {
|
|
902
|
+
if (CRUD_OPS.has(name)) throw new Error(`[Arc] Resource '${config.name}': action '${name}' conflicts with CRUD operation.\nUse a different name (e.g., '${name}_item', 'do_${name}').`);
|
|
903
|
+
if (typeof entry !== "function") {
|
|
904
|
+
const def = entry;
|
|
905
|
+
if (typeof def.handler !== "function") throw new Error(`[Arc] Resource '${config.name}': actions.${name}.handler must be a function.`);
|
|
906
|
+
if (def.permissions !== void 0 && typeof def.permissions !== "function") throw new Error(`[Arc] Resource '${config.name}': actions.${name}.permissions must be a PermissionCheck function.`);
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
}
|
|
891
910
|
}
|
|
892
911
|
const repository = config.adapter?.repository;
|
|
893
912
|
if (config.idField === void 0 && repository) {
|
|
@@ -1068,9 +1087,21 @@ var ResourceDefinition = class {
|
|
|
1068
1087
|
customSchemas;
|
|
1069
1088
|
permissions;
|
|
1070
1089
|
additionalRoutes;
|
|
1090
|
+
/**
|
|
1091
|
+
* Original v2.8 `routes` declaration — retained for downstream consumers
|
|
1092
|
+
* (OpenAPI, MCP, registry, CLI introspect). Preserves fields dropped during
|
|
1093
|
+
* normalization to `additionalRoutes` (notably `mcp`, `description`,
|
|
1094
|
+
* `annotations`). Undefined when the resource was defined with the legacy
|
|
1095
|
+
* `additionalRoutes` shape.
|
|
1096
|
+
*
|
|
1097
|
+
* Added in 2.8.1 — the source-of-truth fix for "canonical resource manifest".
|
|
1098
|
+
*/
|
|
1099
|
+
routes;
|
|
1071
1100
|
middlewares;
|
|
1072
1101
|
disableDefaultRoutes;
|
|
1073
1102
|
disabledRoutes;
|
|
1103
|
+
actions;
|
|
1104
|
+
actionPermissions;
|
|
1074
1105
|
events;
|
|
1075
1106
|
rateLimit;
|
|
1076
1107
|
audit;
|
|
@@ -1096,10 +1127,13 @@ var ResourceDefinition = class {
|
|
|
1096
1127
|
this.schemaOptions = config.schemaOptions ?? {};
|
|
1097
1128
|
this.customSchemas = config.customSchemas ?? {};
|
|
1098
1129
|
this.permissions = config.permissions ?? {};
|
|
1099
|
-
this.
|
|
1130
|
+
this.routes = config.routes;
|
|
1131
|
+
this.additionalRoutes = config.routes ? convertRoutesToAdditionalRoutes(config.routes) : config.additionalRoutes ?? [];
|
|
1100
1132
|
this.middlewares = config.middlewares ?? {};
|
|
1101
1133
|
this.disableDefaultRoutes = config.disableDefaultRoutes ?? false;
|
|
1102
1134
|
this.disabledRoutes = config.disabledRoutes ?? [];
|
|
1135
|
+
this.actions = config.actions;
|
|
1136
|
+
this.actionPermissions = config.actionPermissions;
|
|
1103
1137
|
this.events = config.events ?? {};
|
|
1104
1138
|
this.rateLimit = config.rateLimit;
|
|
1105
1139
|
this.audit = config.audit;
|
|
@@ -1167,10 +1201,10 @@ var ResourceDefinition = class {
|
|
|
1167
1201
|
pattern,
|
|
1168
1202
|
tags
|
|
1169
1203
|
});
|
|
1170
|
-
const onRegister = self._onRegister;
|
|
1171
|
-
if (onRegister) await onRegister(fastify);
|
|
1172
1204
|
await fastify.register(async (instance) => {
|
|
1173
1205
|
const typedInstance = instance;
|
|
1206
|
+
const onRegister = self._onRegister;
|
|
1207
|
+
if (onRegister) await onRegister(instance);
|
|
1174
1208
|
let schemas = null;
|
|
1175
1209
|
const openApi = self._registryMeta?.openApiSchemas;
|
|
1176
1210
|
if (openApi && (!self.customSchemas || Object.keys(self.customSchemas).length === 0)) {
|
|
@@ -1259,6 +1293,10 @@ var ResourceDefinition = class {
|
|
|
1259
1293
|
pipe: self.pipe,
|
|
1260
1294
|
fields: self.fields
|
|
1261
1295
|
});
|
|
1296
|
+
if (self.actions && Object.keys(self.actions).length > 0) {
|
|
1297
|
+
const { createActionRouter } = await import("./createActionRouter-Df1BuawX.mjs").then((n) => n.r);
|
|
1298
|
+
createActionRouter(instance, normalizeActionsToRouterConfig(self.actions, self.actionPermissions, self.tag));
|
|
1299
|
+
}
|
|
1262
1300
|
if (self.events && Object.keys(self.events).length > 0) typedInstance.log?.debug?.(`Resource '${self.name}' defined ${Object.keys(self.events).length} events`);
|
|
1263
1301
|
}, { prefix: self.prefix });
|
|
1264
1302
|
if (hasEvents(fastify)) try {
|
|
@@ -1312,5 +1350,50 @@ function capitalize(str) {
|
|
|
1312
1350
|
if (!str) return "";
|
|
1313
1351
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
1314
1352
|
}
|
|
1353
|
+
/**
|
|
1354
|
+
* Convert v2.8 RouteDefinition[] to internal AdditionalRoute[] format.
|
|
1355
|
+
* The internal format is what createCrudRouter understands.
|
|
1356
|
+
*/
|
|
1357
|
+
function convertRoutesToAdditionalRoutes(routes) {
|
|
1358
|
+
return routes.map((route) => ({
|
|
1359
|
+
method: route.method,
|
|
1360
|
+
path: route.path,
|
|
1361
|
+
handler: route.handler,
|
|
1362
|
+
permissions: route.permissions,
|
|
1363
|
+
wrapHandler: !route.raw,
|
|
1364
|
+
operation: route.operation,
|
|
1365
|
+
summary: route.summary,
|
|
1366
|
+
description: route.description,
|
|
1367
|
+
tags: route.tags,
|
|
1368
|
+
preHandler: route.preHandler,
|
|
1369
|
+
preAuth: route.preAuth,
|
|
1370
|
+
streamResponse: route.streamResponse,
|
|
1371
|
+
schema: route.schema,
|
|
1372
|
+
mcpHandler: route.mcpHandler,
|
|
1373
|
+
mcp: route.mcp
|
|
1374
|
+
}));
|
|
1375
|
+
}
|
|
1376
|
+
/**
|
|
1377
|
+
* Normalize ActionsMap into the ActionRouterConfig shape that createActionRouter expects.
|
|
1378
|
+
*/
|
|
1379
|
+
function normalizeActionsToRouterConfig(actions, globalAuth, tag) {
|
|
1380
|
+
const handlers = {};
|
|
1381
|
+
const permissions = {};
|
|
1382
|
+
const schemas = {};
|
|
1383
|
+
for (const [name, entry] of Object.entries(actions)) if (typeof entry === "function") handlers[name] = entry;
|
|
1384
|
+
else {
|
|
1385
|
+
const def = entry;
|
|
1386
|
+
handlers[name] = def.handler;
|
|
1387
|
+
if (def.permissions) permissions[name] = def.permissions;
|
|
1388
|
+
if (def.schema) schemas[name] = def.schema;
|
|
1389
|
+
}
|
|
1390
|
+
return {
|
|
1391
|
+
tag,
|
|
1392
|
+
actions: handlers,
|
|
1393
|
+
actionPermissions: permissions,
|
|
1394
|
+
actionSchemas: schemas,
|
|
1395
|
+
globalAuth
|
|
1396
|
+
};
|
|
1397
|
+
}
|
|
1315
1398
|
//#endregion
|
|
1316
1399
|
export { validateResourceConfig as a, createCrudHandlers as c, getControllerContext as d, getControllerScope as f, formatValidationErrors as i, createFastifyHandler as l, pipe as m, defineResource as n, createCrudRouter as o, sendControllerResponse as p, assertValidConfig as r, createPermissionMiddleware as s, ResourceDefinition as t, createRequestContext as u };
|
package/dist/docs/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as ExternalOpenApiPaths } from "../externalPaths-
|
|
1
|
+
import { it as RegistryEntry } from "../interface-CS6d7HiB.mjs";
|
|
2
|
+
import { t as ExternalOpenApiPaths } from "../externalPaths-BQ8QijNH.mjs";
|
|
3
3
|
import { FastifyPluginAsync } from "fastify";
|
|
4
4
|
|
|
5
5
|
//#region src/docs/openapi.d.ts
|
package/dist/docs/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as getUserRoles } from "../types-ZUu_h0jp.mjs";
|
|
2
|
-
import { n as openApiPlugin, r as openapi_default, t as buildOpenApiSpec } from "../openapi-
|
|
2
|
+
import { n as openApiPlugin, r as openapi_default, t as buildOpenApiSpec } from "../openapi-q6rNKfZy.mjs";
|
|
3
3
|
import fp from "fastify-plugin";
|
|
4
4
|
//#region src/docs/scalar.ts
|
|
5
5
|
const scalarPlugin = async (fastify, opts = {}) => {
|
package/dist/dynamic/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as PermissionCheck } from "../types-
|
|
1
|
+
import { qt as ResourceDefinition, r as DataAdapter } from "../interface-CS6d7HiB.mjs";
|
|
2
|
+
import { t as PermissionCheck } from "../types-BoaZHr-2.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/dynamic/ArcDynamicLoader.d.ts
|
|
5
5
|
interface ArcArchitectureSchema {
|
package/dist/dynamic/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as ArcQueryParser } from "../queryParser-CgCtsjti.mjs";
|
|
2
|
-
import { n as defineResource } from "../defineResource-
|
|
2
|
+
import { n as defineResource } from "../defineResource-CqeUltrW.mjs";
|
|
3
3
|
import { C as publicRead, T as readOnly, b as fullPublic, v as adminOnly, w as publicReadAdminWrite, x as ownerWithAdminBypass, y as authenticated } from "../permissions-CH4cNwJi.mjs";
|
|
4
4
|
//#region src/dynamic/ArcDynamicLoader.ts
|
|
5
5
|
const VALID_FIELD_TYPES = new Set([
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as __exportAll } from "./chunk-BpYLSNr0.mjs";
|
|
2
2
|
import { t as getUserRoles } from "./types-ZUu_h0jp.mjs";
|
|
3
|
-
import { t as arcLog } from "./logger-
|
|
3
|
+
import { t as arcLog } from "./logger-CDjpjySd.mjs";
|
|
4
4
|
import fp from "fastify-plugin";
|
|
5
5
|
//#region src/scope/elevation.ts
|
|
6
6
|
var elevation_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "./chunk-BpYLSNr0.mjs";
|
|
2
|
-
import { p as isArcError } from "./errors-
|
|
2
|
+
import { p as isArcError } from "./errors-BF2bIOIS.mjs";
|
|
3
3
|
import fp from "fastify-plugin";
|
|
4
4
|
//#region src/plugins/errorHandler.ts
|
|
5
5
|
var errorHandler_exports = /* @__PURE__ */ __exportAll({ errorHandlerPlugin: () => errorHandlerPlugin });
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as EventTransport, n as EventHandler, r as EventLogger, t as DomainEvent } from "./EventTransport-
|
|
1
|
+
import { i as EventTransport, n as EventHandler, r as EventLogger, t as DomainEvent } from "./EventTransport-CLXJUzyT.mjs";
|
|
2
2
|
import { FastifyPluginAsync } from "fastify";
|
|
3
3
|
|
|
4
4
|
//#region src/events/defineEvent.d.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "./chunk-BpYLSNr0.mjs";
|
|
2
|
-
import { t as requestContext } from "./requestContext-
|
|
2
|
+
import { t as requestContext } from "./requestContext-DYvHl113.mjs";
|
|
3
3
|
import fp from "fastify-plugin";
|
|
4
4
|
//#region src/events/EventTransport.ts
|
|
5
5
|
/**
|
|
@@ -33,6 +33,24 @@ var MemoryEventTransport = class {
|
|
|
33
33
|
this.logger.error(`[EventTransport] Handler error for ${event.type}:`, err);
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Reference `publishMany` implementation — delegates to `publish()` in order.
|
|
38
|
+
*
|
|
39
|
+
* Production transports (Kafka, Redis pipeline, SQS batch) should override
|
|
40
|
+
* this with a single batched network call. Memory transport has nothing to
|
|
41
|
+
* batch, so we just loop — the loop still returns a proper result map so
|
|
42
|
+
* `EventOutbox.relay` can exercise the batched code path in tests.
|
|
43
|
+
*/
|
|
44
|
+
async publishMany(events) {
|
|
45
|
+
const results = /* @__PURE__ */ new Map();
|
|
46
|
+
for (const event of events) try {
|
|
47
|
+
await this.publish(event);
|
|
48
|
+
results.set(event.meta.id, null);
|
|
49
|
+
} catch (err) {
|
|
50
|
+
results.set(event.meta.id, err instanceof Error ? err : new Error(String(err)));
|
|
51
|
+
}
|
|
52
|
+
return results;
|
|
53
|
+
}
|
|
36
54
|
async subscribe(pattern, handler) {
|
|
37
55
|
if (!this.handlers.has(pattern)) this.handlers.set(pattern, /* @__PURE__ */ new Set());
|
|
38
56
|
this.handlers.get(pattern)?.add(handler);
|