@classytic/arc 2.15.3 → 2.16.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 -0
- package/bin/arc.js +12 -0
- package/dist/{BaseController-dx3m2J8V.mjs → BaseController-DlCCTIxJ.mjs} +61 -19
- package/dist/{HookSystem-Iiebom92.mjs → HookSystem-Cmf7-Etp.mjs} +8 -4
- package/dist/{QueryCache-D41bfdBB.d.mts → QueryCache-SvmT_9ti.d.mts} +1 -1
- package/dist/{ResourceRegistry-CTERg_2x.mjs → ResourceRegistry-f48hFk3m.mjs} +52 -9
- package/dist/audit/index.d.mts +1 -1
- package/dist/audit/index.mjs +4 -2
- package/dist/auth/index.d.mts +4 -4
- package/dist/auth/index.mjs +4 -4
- package/dist/auth/redis-session.d.mts +1 -1
- package/dist/{betterAuthOpenApi--M_i87dQ.mjs → betterAuthOpenApi-ClWxaceA.mjs} +10 -6
- package/dist/buildHandler-BZX6zzDM.mjs +300 -0
- package/dist/cache/index.d.mts +3 -3
- package/dist/cache/index.mjs +3 -3
- package/dist/{caching-SM8gghN6.mjs → caching-TeHE8G-v.mjs} +1 -1
- package/dist/cli/commands/describe.d.mts +35 -1
- package/dist/cli/commands/describe.mjs +52 -12
- package/dist/cli/commands/docs.d.mts +1 -4
- package/dist/cli/commands/docs.mjs +4 -16
- package/dist/cli/commands/generate.d.mts +2 -20
- package/dist/cli/commands/generate.mjs +1 -546
- package/dist/cli/commands/init.d.mts +2 -40
- package/dist/cli/commands/init.mjs +1 -3036
- package/dist/cli/commands/introspect.mjs +53 -64
- package/dist/cli/index.d.mts +2 -2
- package/dist/cli/index.mjs +2 -2
- package/dist/{constants-Cxde4rpC.mjs → constants-TrJVIJl0.mjs} +7 -0
- package/dist/core/index.d.mts +3 -3
- package/dist/core/index.mjs +5 -5
- package/dist/{core-CvmOqEms.mjs → core-DBJ_j6rX.mjs} +222 -44
- package/dist/createActionRouter-DUpN3Dd1.mjs +288 -0
- package/dist/{createAggregationRouter-B0bPDf5b.mjs → createAggregationRouter-Dq-TUCuY.mjs} +3 -2
- package/dist/{createApp-PFegs47-.mjs → createApp-DNccuhyI.mjs} +16 -14
- package/dist/{defineEvent-D5h7EvAx.mjs → defineEvent-DRwY0fYm.mjs} +1 -1
- package/dist/docs/index.d.mts +2 -2
- package/dist/docs/index.mjs +1 -1
- package/dist/{errorHandler-Bk-AGhkU.mjs → errorHandler-DpoXQHZ9.mjs} +17 -14
- package/dist/errors-C1lX_jlm.d.mts +91 -0
- package/dist/{eventPlugin-CaKTYkYM.mjs → eventPlugin-C2cGqtRO.mjs} +1 -1
- package/dist/{eventPlugin-qXpqTebY.d.mts → eventPlugin-CtHC_av1.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 +1 -1
- package/dist/factory/index.mjs +2 -2
- package/dist/{fields-COhcH3fk.d.mts → fields-Anj0xdih.d.mts} +1 -1
- package/dist/generate-BWFwgcCM.d.mts +38 -0
- package/dist/generate-CYac-OLv.mjs +654 -0
- package/dist/hooks/index.d.mts +1 -1
- package/dist/hooks/index.mjs +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-BTqLEvhu.d.mts → index-3oIimXQn.d.mts} +12 -12
- package/dist/{index-BstGxcc3.d.mts → index-B-ulKx5P.d.mts} +55 -4
- package/dist/{index-BswOSJCE.d.mts → index-CkW0flkU.d.mts} +355 -16
- package/dist/index.d.mts +6 -6
- package/dist/index.mjs +7 -8
- package/dist/init-Dv71MsJr.d.mts +71 -0
- package/dist/init-HDvoO9L5.mjs +3098 -0
- 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/jobs.mjs +3 -3
- package/dist/integrations/mcp/index.d.mts +239 -7
- package/dist/integrations/mcp/index.mjs +2 -528
- package/dist/integrations/mcp/testing.d.mts +2 -2
- package/dist/integrations/mcp/testing.mjs +6 -10
- package/dist/integrations/streamline.d.mts +71 -2
- package/dist/integrations/streamline.mjs +81 -8
- package/dist/integrations/websocket-redis.d.mts +1 -1
- package/dist/integrations/websocket.d.mts +1 -1
- package/dist/integrations/websocket.mjs +1 -0
- package/dist/loadResourcesFromEntry-BLMEI2Xa.mjs +51 -0
- package/dist/{resourceToTools-tFYUNmM0.mjs → mcpPlugin-7vGV51ED.mjs} +1021 -318
- package/dist/{memory-UBydS5ku.mjs → memory-QOLe11D5.mjs} +2 -0
- package/dist/middleware/index.d.mts +1 -1
- package/dist/middleware/index.mjs +1 -1
- package/dist/{openapi-BHXhoX8O.mjs → openapi-34T9yNwd.mjs} +47 -36
- package/dist/permissions/index.d.mts +2 -2
- package/dist/permissions/index.mjs +1 -1
- package/dist/{permissions-ohQyv50e.mjs → permissions-CTxMrreC.mjs} +2 -2
- package/dist/{pipe-Zr0KXjQe.mjs → pipe-DiCyvyPN.mjs} +1 -0
- package/dist/pipeline/index.d.mts +1 -1
- package/dist/pipeline/index.mjs +1 -1
- package/dist/plugins/index.d.mts +5 -5
- package/dist/plugins/index.mjs +10 -10
- package/dist/plugins/response-cache.mjs +5 -5
- package/dist/plugins/tracing-entry.d.mts +1 -1
- package/dist/plugins/tracing-entry.mjs +1 -1
- package/dist/{pluralize-DQgqgifU.mjs → pluralize-B9M8xvy-.mjs} +2 -1
- package/dist/presets/filesUpload.d.mts +4 -4
- package/dist/presets/filesUpload.mjs +2 -2
- package/dist/presets/index.d.mts +1 -1
- package/dist/presets/index.mjs +1 -1
- package/dist/presets/multiTenant.d.mts +1 -1
- package/dist/presets/multiTenant.mjs +4 -3
- package/dist/presets/search.d.mts +2 -2
- package/dist/presets/search.mjs +1 -1
- package/dist/{presets-BbkjdPeH.mjs → presets-C9BE6WaZ.mjs} +2 -2
- package/dist/{queryCachePlugin-m1XsgAIJ.mjs → queryCachePlugin-B4XMSSe7.mjs} +2 -2
- package/dist/{queryCachePlugin-CqMdLI2-.d.mts → queryCachePlugin-Biqzfbi5.d.mts} +2 -2
- package/dist/{redis-DiMkdHEl.d.mts → redis-Cyzrz6SX.d.mts} +1 -1
- package/dist/{redis-stream-D6HzR1Z_.d.mts → redis-stream-DT-YjzrB.d.mts} +1 -1
- package/dist/registry/index.d.mts +319 -2
- package/dist/registry/index.mjs +3 -3
- package/dist/registry-BBE23CDj.mjs +576 -0
- package/dist/{routerShared-DrOa-26E.mjs → routerShared-CZV5aabX.mjs} +3 -3
- package/dist/scope/index.d.mts +3 -3
- package/dist/scope/index.mjs +3 -3
- package/dist/{sse-Bz-5ZeTt.mjs → sse-BY6sTy4P.mjs} +1 -1
- package/dist/testing/index.d.mts +2 -2
- package/dist/testing/index.mjs +16 -7
- package/dist/testing/storageContract.d.mts +1 -1
- package/dist/types/index.d.mts +5 -5
- package/dist/types/storage.d.mts +1 -1
- package/dist/{types-C_s5moIu.mjs → types-Bi0r0vjG.mjs} +53 -1
- package/dist/{types-BQsjgQzS.d.mts → types-BsJMEQ4D.d.mts} +106 -12
- package/dist/{types-DrBaUwyV.d.mts → types-D-fYtKjb.d.mts} +33 -10
- package/dist/{types-CTYvcwHe.d.mts → types-DVfpSfx2.d.mts} +42 -1
- package/dist/utils/index.d.mts +1286 -2
- package/dist/utils/index.mjs +1 -1
- package/dist/{utils-_h9B3c57.mjs → utils-DC5ycPfr.mjs} +89 -40
- package/dist/{buildHandler-CcFOpJLh.mjs → validate-By96rH0r.mjs} +8 -299
- package/dist/{versioning-hmkPcDlX.d.mts → versioning-ZwX9tmbS.d.mts} +1 -1
- package/package.json +22 -29
- package/skills/arc/SKILL.md +299 -689
- package/skills/arc/references/auth.md +19 -7
- package/skills/arc-code-review/SKILL.md +1 -1
- package/skills/arc-code-review/references/arc-cheatsheet.md +100 -322
- package/dist/createActionRouter-S3MLVYot.mjs +0 -220
- package/dist/index-bRjYu21O.d.mts +0 -1320
- package/dist/org/index.d.mts +0 -66
- package/dist/org/index.mjs +0 -486
- package/dist/org/types.d.mts +0 -82
- package/dist/org/types.mjs +0 -1
- package/dist/registry-I-ogLgL9.mjs +0 -46
- /package/dist/{EventTransport-CT_52aWU.d.mts → EventTransport-C-2oAHtw.d.mts} +0 -0
- /package/dist/{EventTransport-DLWoUMHy.mjs → EventTransport-Hxvv5QQz.mjs} +0 -0
- /package/dist/{actionPermissions-CyUkQu6O.mjs → actionPermissions-Bjmvn7Eb.mjs} +0 -0
- /package/dist/{elevation-BXOWoGCF.d.mts → elevation-0YBpa663.d.mts} +0 -0
- /package/dist/{elevation-DgoeTyfX.mjs → elevation-Dci0AYLT.mjs} +0 -0
- /package/dist/{errorHandler-DFr45ZG4.d.mts → errorHandler-mHuyWzZE.d.mts} +0 -0
- /package/dist/{externalPaths-BD5nw6St.d.mts → externalPaths-DFg-2KTp.d.mts} +0 -0
- /package/dist/{interface-beEtJyWM.d.mts → interface-CH0OQudo.d.mts} +0 -0
- /package/dist/{interface-DfLGcus7.d.mts → interface-NwJ_qPlY.d.mts} +0 -0
- /package/dist/{keys-CGcCbNyu.mjs → keys-DopsCuyQ.mjs} +0 -0
- /package/dist/{loadResources-DBMQg_Aj.mjs → loadResources-ChQEj8ih.mjs} +0 -0
- /package/dist/{metrics-Qnvwc-LQ.mjs → metrics-TuOmguhi.mjs} +0 -0
- /package/dist/{replyHelpers-CK-FNO8E.mjs → replyHelpers-C-gD32oF.mjs} +0 -0
- /package/dist/{schemaIR-lYhC2gE5.mjs → schemaIR-Ctc89DSn.mjs} +0 -0
- /package/dist/{sessionManager-C4Le_UB3.d.mts → sessionManager-BqFegc0W.d.mts} +0 -0
- /package/dist/{storage-Dfzt4VTl.d.mts → storage-D2KZJAmn.d.mts} +0 -0
- /package/dist/{store-helpers-BkIN9-vu.mjs → store-helpers-B0sunfZZ.mjs} +0 -0
- /package/dist/{tracing-QJVprktp.d.mts → tracing-Dm8n7Cnn.d.mts} +0 -0
- /package/dist/{versioning-BUrT5aP4.mjs → versioning-B6mimogM.mjs} +0 -0
- /package/dist/{websocket-ChC2rqe1.d.mts → websocket-BkjeGZRn.d.mts} +0 -0
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
import { t as __exportAll } from "./chunk-BpYLSNr0.mjs";
|
|
2
|
-
import "./constants-Cxde4rpC.mjs";
|
|
3
|
-
import { f as createError } from "./errors-j4aJm1Wg.mjs";
|
|
4
|
-
import { a as buildAuthMiddlewareForPermissions, c as buildPreHandlerChain, f as resolveRouterPluginMw, l as buildRateLimitConfig, n as buildActionPipelineHandler, p as selectPluginMw, r as buildArcDecorator, t as buildActionPermissionMw, u as resolvePipelineSteps, y as sendControllerResponse } from "./routerShared-DrOa-26E.mjs";
|
|
5
|
-
import { n as schemaIRToJsonSchemaBranch, t as normalizeSchemaIR } from "./schemaIR-lYhC2gE5.mjs";
|
|
6
|
-
//#region src/core/createActionRouter.ts
|
|
7
|
-
var createActionRouter_exports = /* @__PURE__ */ __exportAll({
|
|
8
|
-
buildActionBodySchema: () => buildActionBodySchema,
|
|
9
|
-
createActionRouter: () => createActionRouter
|
|
10
|
-
});
|
|
11
|
-
/**
|
|
12
|
-
* Register the unified action endpoint: `POST /:id/action`.
|
|
13
|
-
*
|
|
14
|
-
* Shares every lifecycle primitive with the CRUD router — the preHandler
|
|
15
|
-
* chain, the arc decorator, idempotency, rate-limit, and the response
|
|
16
|
-
* shaper. The only thing that stays local is the dynamic permission check
|
|
17
|
-
* (keyed by `body.action` at request time).
|
|
18
|
-
*/
|
|
19
|
-
function createActionRouter(fastify, config) {
|
|
20
|
-
const { tag, resourceName = tag ?? "action", actions, actionPermissions = {}, actionSchemas = {}, globalAuth, onError, fields: fieldPermissions, schemaOptions, idField = "_id", permissions: resourcePermissions, routeGuards = [], pipeline, rateLimit } = config;
|
|
21
|
-
const actionEnum = Object.keys(actions);
|
|
22
|
-
if (actionEnum.length === 0) {
|
|
23
|
-
fastify.log.warn("[createActionRouter] No actions defined, skipping route creation");
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
const bodySchema = buildActionBodySchema(actionEnum, actionSchemas);
|
|
27
|
-
const routeSchema = {
|
|
28
|
-
tags: tag ? [tag] : void 0,
|
|
29
|
-
summary: `Perform action (${actionEnum.join("/")})`,
|
|
30
|
-
description: buildActionDescription(actions, actionPermissions),
|
|
31
|
-
params: {
|
|
32
|
-
type: "object",
|
|
33
|
-
properties: { id: {
|
|
34
|
-
type: "string",
|
|
35
|
-
description: "Resource ID"
|
|
36
|
-
} },
|
|
37
|
-
required: ["id"]
|
|
38
|
-
},
|
|
39
|
-
body: bodySchema
|
|
40
|
-
};
|
|
41
|
-
const arcDecorator = buildArcDecorator({
|
|
42
|
-
resourceName,
|
|
43
|
-
schemaOptions,
|
|
44
|
-
permissions: resourcePermissions,
|
|
45
|
-
hooks: fastify.arc?.hooks,
|
|
46
|
-
events: fastify.events,
|
|
47
|
-
fields: fieldPermissions,
|
|
48
|
-
idField
|
|
49
|
-
});
|
|
50
|
-
const authMw = buildAuthMiddlewareForPermissions(fastify, actionEnum.map((name) => actionPermissions[name] ?? globalAuth));
|
|
51
|
-
const pluginMw = resolveRouterPluginMw(fastify, false);
|
|
52
|
-
const wrappedHandlers = /* @__PURE__ */ new Map();
|
|
53
|
-
for (const [name, handler] of Object.entries(actions)) {
|
|
54
|
-
const steps = resolvePipelineSteps(pipeline, name);
|
|
55
|
-
wrappedHandlers.set(name, buildActionPipelineHandler(handler, steps, name, resourceName));
|
|
56
|
-
}
|
|
57
|
-
const preHandler = buildPreHandlerChain({
|
|
58
|
-
arcDecorator,
|
|
59
|
-
authMw,
|
|
60
|
-
permissionMw: buildActionPermissionMw(actionEnum, actionPermissions, globalAuth, resourceName),
|
|
61
|
-
pluginMw: selectPluginMw("POST", pluginMw),
|
|
62
|
-
routeGuards
|
|
63
|
-
});
|
|
64
|
-
const rateLimitConfig = buildRateLimitConfig(rateLimit);
|
|
65
|
-
fastify.route({
|
|
66
|
-
method: "POST",
|
|
67
|
-
url: "/:id/action",
|
|
68
|
-
schema: routeSchema,
|
|
69
|
-
preHandler: preHandler.length > 0 ? preHandler : void 0,
|
|
70
|
-
...rateLimitConfig ? { config: rateLimitConfig } : {},
|
|
71
|
-
handler: async (req, reply) => {
|
|
72
|
-
const { action, ...data } = req.body;
|
|
73
|
-
const { id } = req.params;
|
|
74
|
-
const reqWithExtras = req;
|
|
75
|
-
reqWithExtras.arc = {
|
|
76
|
-
...reqWithExtras.arc ?? {},
|
|
77
|
-
entityId: id
|
|
78
|
-
};
|
|
79
|
-
const handler = wrappedHandlers.get(action);
|
|
80
|
-
if (!handler) throw createError(400, `Invalid action '${action}'. Valid actions: ${actionEnum.join(", ")}`, { validActions: actionEnum });
|
|
81
|
-
try {
|
|
82
|
-
return sendControllerResponse(reply, await handler(id, data, req), req);
|
|
83
|
-
} catch (error) {
|
|
84
|
-
if (onError) {
|
|
85
|
-
const { statusCode, error: errorMsg, code } = onError(error, action, id);
|
|
86
|
-
throw createError(statusCode, errorMsg, code ? { code } : void 0);
|
|
87
|
-
}
|
|
88
|
-
const err = error;
|
|
89
|
-
const statusCode = err.statusCode || err.status || 500;
|
|
90
|
-
const errorCode = err.code || "ACTION_FAILED";
|
|
91
|
-
if (statusCode >= 500) req.log.error({
|
|
92
|
-
err: error,
|
|
93
|
-
action,
|
|
94
|
-
id
|
|
95
|
-
}, "Action handler error");
|
|
96
|
-
if (error?.name === "ArcError" || error instanceof Error === false) throw error;
|
|
97
|
-
throw createError(statusCode, err.message || `Failed to execute '${action}' action`, { code: errorCode });
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
fastify.log.debug({
|
|
102
|
-
actions: actionEnum,
|
|
103
|
-
tag,
|
|
104
|
-
resourceName
|
|
105
|
-
}, "[createActionRouter] Registered action endpoint: POST /:id/action");
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Build a discriminated body schema for the unified action endpoint.
|
|
109
|
-
*
|
|
110
|
-
* Produces a schema of the form:
|
|
111
|
-
* ```json
|
|
112
|
-
* {
|
|
113
|
-
* "type": "object",
|
|
114
|
-
* "required": ["action"],
|
|
115
|
-
* "properties": {
|
|
116
|
-
* "action": { "type": "string", "enum": ["dispatch", "approve"] },
|
|
117
|
-
* "carrier": { "type": "string" }
|
|
118
|
-
* },
|
|
119
|
-
* "oneOf": [
|
|
120
|
-
* {
|
|
121
|
-
* "properties": {
|
|
122
|
-
* "action": { "const": "dispatch" },
|
|
123
|
-
* "carrier": { "type": "string" } // ← every branch lists the union
|
|
124
|
-
* },
|
|
125
|
-
* "required": ["action", "carrier"]
|
|
126
|
-
* },
|
|
127
|
-
* {
|
|
128
|
-
* "properties": {
|
|
129
|
-
* "action": { "const": "approve" },
|
|
130
|
-
* "carrier": { "type": "string" } // ← even though approve doesn't use it
|
|
131
|
-
* },
|
|
132
|
-
* "required": ["action"]
|
|
133
|
-
* }
|
|
134
|
-
* ]
|
|
135
|
-
* }
|
|
136
|
-
* ```
|
|
137
|
-
*
|
|
138
|
-
* **Why every branch carries the full property union.** AJV's
|
|
139
|
-
* `removeAdditional: 'all'` (Fastify's framework default) interacts badly
|
|
140
|
-
* with `oneOf`: when a branch's `properties` lacks a field, AJV strips it
|
|
141
|
-
* from the body during that branch's evaluation — *even if a different
|
|
142
|
-
* branch would have allowed it*. The strip mutates the body before
|
|
143
|
-
* `oneOf` finishes discriminating, so by the time the matching branch
|
|
144
|
-
* wins, the body has already lost fields. Concretely: `actions: { verify:
|
|
145
|
-
* {}, hold: { schema: z.object({ amount, reason }.optional()) } }` +
|
|
146
|
-
* `POST { action: 'hold', amount: 1, reason }` lands at the handler as
|
|
147
|
-
* `{ action: 'hold' }`. Empirically reproduced and locked at
|
|
148
|
-
* [tests/core/action-discriminator-strip.test.ts](../../tests/core/action-discriminator-strip.test.ts).
|
|
149
|
-
*
|
|
150
|
-
* Listing every action's properties on every branch makes per-branch
|
|
151
|
-
* removeAdditional walks see every caller field as "in this branch's
|
|
152
|
-
* properties," so nothing gets stripped during oneOf evaluation. The
|
|
153
|
-
* `required` array stays per-action, so the handler still gets called
|
|
154
|
-
* only when the matching branch's required-field contract is satisfied.
|
|
155
|
-
* Per-branch `additionalProperties: false` (Zod v4 default) carries
|
|
156
|
-
* through but, under host removeAdditional: 'all', it can no longer
|
|
157
|
-
* reject sibling-action fields — those become silently stripped at top
|
|
158
|
-
* level instead. That's the host's opt-in to stripping; arc's job is to
|
|
159
|
-
* stop accidentally losing the action's *own* declared fields.
|
|
160
|
-
*
|
|
161
|
-
* Under arc's own `createApp` (`removeAdditional: false`), strict-mode
|
|
162
|
-
* rejection still functions normally — see
|
|
163
|
-
* [tests/core/action-strict-schema-parity.test.ts](../../tests/core/action-strict-schema-parity.test.ts).
|
|
164
|
-
*
|
|
165
|
-
* Exported so OpenAPI generation and MCP tool generation can reuse the same
|
|
166
|
-
* schema shape (single source of truth).
|
|
167
|
-
*/
|
|
168
|
-
function buildActionBodySchema(actionEnum, actionSchemas = {}) {
|
|
169
|
-
const unionProperties = {};
|
|
170
|
-
const irs = [];
|
|
171
|
-
for (const actionName of actionEnum) {
|
|
172
|
-
const ir = normalizeSchemaIR(actionSchemas[actionName]);
|
|
173
|
-
irs.push({
|
|
174
|
-
name: actionName,
|
|
175
|
-
ir
|
|
176
|
-
});
|
|
177
|
-
for (const [key, val] of Object.entries(ir.properties)) unionProperties[key] = val;
|
|
178
|
-
}
|
|
179
|
-
const branches = [];
|
|
180
|
-
for (const { name, ir } of irs) branches.push(schemaIRToJsonSchemaBranch({
|
|
181
|
-
...ir,
|
|
182
|
-
properties: {
|
|
183
|
-
...unionProperties,
|
|
184
|
-
...ir.properties
|
|
185
|
-
}
|
|
186
|
-
}, {
|
|
187
|
-
properties: { action: {
|
|
188
|
-
type: "string",
|
|
189
|
-
const: name
|
|
190
|
-
} },
|
|
191
|
-
required: ["action"]
|
|
192
|
-
}));
|
|
193
|
-
return {
|
|
194
|
-
type: "object",
|
|
195
|
-
required: ["action"],
|
|
196
|
-
properties: {
|
|
197
|
-
action: {
|
|
198
|
-
type: "string",
|
|
199
|
-
enum: [...actionEnum]
|
|
200
|
-
},
|
|
201
|
-
...unionProperties
|
|
202
|
-
},
|
|
203
|
-
oneOf: branches
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
/**
|
|
207
|
-
* Build OpenAPI description with action list + role hints.
|
|
208
|
-
* Reads `_roles` metadata from permission checks for docs.
|
|
209
|
-
*/
|
|
210
|
-
function buildActionDescription(actions, actionPermissions) {
|
|
211
|
-
const lines = ["Unified action endpoint for state transitions.\n\n**Available actions:**"];
|
|
212
|
-
Object.keys(actions).forEach((action) => {
|
|
213
|
-
const roles = actionPermissions[action]?._roles;
|
|
214
|
-
const roleStr = roles?.length ? ` (requires: ${roles.join(" or ")})` : "";
|
|
215
|
-
lines.push(`- \`${action}\`${roleStr}`);
|
|
216
|
-
});
|
|
217
|
-
return lines.join("\n");
|
|
218
|
-
}
|
|
219
|
-
//#endregion
|
|
220
|
-
export { createActionRouter_exports as n, buildActionBodySchema as t };
|