@classytic/arc 2.8.3 → 2.8.5

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.
Files changed (125) hide show
  1. package/README.md +50 -1
  2. package/dist/adapters/index.d.mts +2 -2
  3. package/dist/audit/index.d.mts +1 -1
  4. package/dist/audit/index.mjs +1 -1
  5. package/dist/audit/mongodb.d.mts +1 -1
  6. package/dist/audit/mongodb.mjs +1 -1
  7. package/dist/auth/index.d.mts +4 -4
  8. package/dist/auth/index.mjs +2 -2
  9. package/dist/auth/redis-session.d.mts +1 -1
  10. package/dist/{betterAuthOpenApi-C5lDyRH2.mjs → betterAuthOpenApi-BuUcUEJq.mjs} +1 -1
  11. package/dist/cache/index.d.mts +73 -3
  12. package/dist/cache/index.mjs +95 -2
  13. package/dist/cli/commands/docs.mjs +2 -2
  14. package/dist/cli/commands/generate.mjs +1 -1
  15. package/dist/cli/commands/introspect.mjs +1 -1
  16. package/dist/core/index.d.mts +2 -2
  17. package/dist/core/index.mjs +3 -3
  18. package/dist/{core-DKSwNSXf.mjs → core-F0QoWBt2.mjs} +1 -1
  19. package/dist/{createActionRouter-Df1BuawX.mjs → createActionRouter-BORM8f17.mjs} +1 -1
  20. package/dist/{createApp-BOYjBgdI.mjs → createApp-B1EY8zxa.mjs} +11 -11
  21. package/dist/{defineResource-Bb_Bdhtw.mjs → defineResource-tcgySDo1.mjs} +2 -2
  22. package/dist/docs/index.d.mts +2 -2
  23. package/dist/docs/index.mjs +1 -1
  24. package/dist/dynamic/index.d.mts +2 -2
  25. package/dist/dynamic/index.mjs +1 -1
  26. package/dist/{elevation-BBGFjzIP.mjs → elevation-DtFxrG0s.mjs} +1 -1
  27. package/dist/{errorHandler-CdZDavNH.d.mts → errorHandler-Bah5JhBd.d.mts} +1 -1
  28. package/dist/{eventPlugin-CVxlE6De.d.mts → eventPlugin-D9DKB2zM.d.mts} +1 -1
  29. package/dist/events/index.d.mts +3 -3
  30. package/dist/events/index.mjs +1 -1
  31. package/dist/events/transports/redis-stream-entry.d.mts +1 -1
  32. package/dist/events/transports/redis.d.mts +1 -1
  33. package/dist/factory/index.d.mts +1 -1
  34. package/dist/factory/index.mjs +2 -2
  35. package/dist/filesUpload-C7r7HIeA.mjs +319 -0
  36. package/dist/hooks/index.d.mts +1 -1
  37. package/dist/hooks/index.mjs +1 -1
  38. package/dist/idempotency/index.d.mts +3 -3
  39. package/dist/idempotency/mongodb.d.mts +1 -1
  40. package/dist/idempotency/redis.d.mts +2 -2
  41. package/dist/idempotency/redis.mjs +134 -13
  42. package/dist/{index-CSkeivBx.d.mts → index-BLXBmWud.d.mts} +3 -3
  43. package/dist/{index-BgmMdpm8.d.mts → index-C1meYuDn.d.mts} +1 -1
  44. package/dist/{index-CpTSDqmD.d.mts → index-DtDzOBn8.d.mts} +3 -3
  45. package/dist/index.d.mts +7 -7
  46. package/dist/index.mjs +4 -4
  47. package/dist/integrations/event-gateway.d.mts +1 -1
  48. package/dist/integrations/event-gateway.mjs +1 -1
  49. package/dist/integrations/index.d.mts +1 -1
  50. package/dist/integrations/jobs.d.mts +25 -3
  51. package/dist/integrations/jobs.mjs +63 -4
  52. package/dist/integrations/mcp/index.d.mts +51 -3
  53. package/dist/integrations/mcp/index.mjs +78 -19
  54. package/dist/integrations/mcp/testing.d.mts +1 -1
  55. package/dist/integrations/mcp/testing.mjs +1 -1
  56. package/dist/{interface-BVuMfeVv.d.mts → interface-CMRutPfe.d.mts} +38 -16
  57. package/dist/{mongodb-B8U2xaLj.d.mts → mongodb-BsP-WbhN.d.mts} +1 -1
  58. package/dist/{mongodb-X7LbEjTN.d.mts → mongodb-CTcp0hQZ.d.mts} +1 -1
  59. package/dist/{openapi-CYCuekCn.mjs → openapi-CbKUJY_m.mjs} +3 -3
  60. package/dist/org/index.d.mts +2 -2
  61. package/dist/permissions/index.d.mts +3 -3
  62. package/dist/plugins/index.d.mts +4 -4
  63. package/dist/plugins/index.mjs +8 -8
  64. package/dist/plugins/tracing-entry.d.mts +1 -1
  65. package/dist/plugins/tracing-entry.mjs +1 -1
  66. package/dist/policies/index.d.mts +1 -1
  67. package/dist/presets/filesUpload.d.mts +49 -0
  68. package/dist/presets/filesUpload.mjs +2 -0
  69. package/dist/presets/index.d.mts +3 -2
  70. package/dist/presets/index.mjs +2 -1
  71. package/dist/presets/multiTenant.d.mts +1 -1
  72. package/dist/{queryCachePlugin-CnTZZTC5.d.mts → queryCachePlugin-BJJGBTlu.d.mts} +1 -1
  73. package/dist/redis-BM00zaPB.d.mts +115 -0
  74. package/dist/{redis-stream-D54N5oXs.d.mts → redis-stream-CrsfUmPt.d.mts} +1 -1
  75. package/dist/registry/index.d.mts +1 -1
  76. package/dist/registry/index.mjs +2 -2
  77. package/dist/{resourceToTools-O_HwWXFa.mjs → resourceToTools-8s-EsCCe.mjs} +1 -1
  78. package/dist/rpc/index.d.mts +1 -1
  79. package/dist/{schemaConverter-OxfCshus.mjs → schemaConverter-Y7nCYaLJ.mjs} +24 -8
  80. package/dist/scope/index.d.mts +2 -2
  81. package/dist/scope/index.mjs +1 -1
  82. package/dist/{sse-CJpt7LGI.mjs → sse-Ad7ypl9e.mjs} +1 -1
  83. package/dist/storage-Dfzt4VTl.d.mts +146 -0
  84. package/dist/testing/index.d.mts +4 -3
  85. package/dist/testing/index.mjs +3 -2
  86. package/dist/testing/storageContract.d.mts +26 -0
  87. package/dist/testing/storageContract.mjs +216 -0
  88. package/dist/types/index.d.mts +4 -4
  89. package/dist/types/storage.d.mts +2 -0
  90. package/dist/types/storage.mjs +1 -0
  91. package/dist/{types-CcG4avic.d.mts → types-BsbNMEDR.d.mts} +1 -1
  92. package/dist/{types-Bg2X42_m.d.mts → types-Ch9pTQbf.d.mts} +9 -9
  93. package/dist/{types-CVC4HOKi.d.mts → types-DZi1aYhm.d.mts} +1 -1
  94. package/dist/utils/index.d.mts +26 -8
  95. package/dist/utils/index.mjs +1 -1
  96. package/package.json +16 -1
  97. package/skills/arc/SKILL.md +22 -0
  98. package/skills/arc/references/events.md +29 -0
  99. package/skills/arc/references/mcp.md +37 -0
  100. package/dist/redis-z3sFr1UP.d.mts +0 -49
  101. /package/dist/{EventTransport-CinyO7zQ.d.mts → EventTransport-BXja8NOc.d.mts} +0 -0
  102. /package/dist/{HookSystem-BjFu7zf1.mjs → HookSystem-HprTmvVY.mjs} +0 -0
  103. /package/dist/{ResourceRegistry-Dq3_zBQP.mjs → ResourceRegistry-C6uXlWe3.mjs} +0 -0
  104. /package/dist/{caching-CjybdRwx.mjs → caching-IMuYVjTL.mjs} +0 -0
  105. /package/dist/{circuitBreaker-CvXkjfrW.d.mts → circuitBreaker-dTtG-UyS.d.mts} +0 -0
  106. /package/dist/{elevation-s5ykdNHr.d.mts → elevation-B6S5csVA.d.mts} +0 -0
  107. /package/dist/{errorHandler-mzqk4cGl.mjs → errorHandler-f869_8PQ.mjs} +0 -0
  108. /package/dist/{errors-Bmn3eZT6.d.mts → errors-Ck2h67pm.d.mts} +0 -0
  109. /package/dist/{eventPlugin-D91S2YF4.mjs → eventPlugin-CDjVTM82.mjs} +0 -0
  110. /package/dist/{externalPaths-Bapitwvd.d.mts → externalPaths-BnkYrNzp.d.mts} +0 -0
  111. /package/dist/{fields-DC4So2M2.d.mts → fields-DpZQa_Q3.d.mts} +0 -0
  112. /package/dist/{interface-DplgQO2e.d.mts → interface-4y979v99.d.mts} +0 -0
  113. /package/dist/{interface-B-pe8fhj.d.mts → interface-DfLGcus7.d.mts} +0 -0
  114. /package/dist/{loadResources-Bksk8ydA.mjs → loadResources-PWd0OCpV.mjs} +0 -0
  115. /package/dist/{logger-CDjpjySd.mjs → logger-D1YrIImS.mjs} +0 -0
  116. /package/dist/{metrics-TuOmguhi.mjs → metrics-B-PU4-Yu.mjs} +0 -0
  117. /package/dist/{mongodb-B5O6xaW1.mjs → mongodb-Utc5k_-0.mjs} +0 -0
  118. /package/dist/{pluralize-A0tWEl1K.mjs → pluralize-CWP6MB39.mjs} +0 -0
  119. /package/dist/{queryCachePlugin-D0iIVhW_.mjs → queryCachePlugin-BH-fidlv.mjs} +0 -0
  120. /package/dist/{registry-B0Wl7uVV.mjs → registry-BiTKT1Dg.mjs} +0 -0
  121. /package/dist/{replyHelpers-BLojtuvR.mjs → replyHelpers-CxkYGT81.mjs} +0 -0
  122. /package/dist/{sessionManager-D-oNWHz3.d.mts → sessionManager-DDCmiNIo.d.mts} +0 -0
  123. /package/dist/{tracing-DxjKk7eW.d.mts → tracing-DdN2-wHJ.d.mts} +0 -0
  124. /package/dist/{types-C72d3NDn.d.mts → types-BD85MlEK.d.mts} +0 -0
  125. /package/dist/{versioning-Cm8qoFDg.mjs → versioning-CDugduqI.mjs} +0 -0
@@ -1,6 +1,19 @@
1
1
  import { FastifyPluginAsync } from "fastify";
2
2
 
3
3
  //#region src/integrations/jobs.d.ts
4
+ /** Repeat schedule — cron pattern or fixed interval. Explicit timezone is required. */
5
+ interface JobRepeatOptions {
6
+ /** Cron pattern (e.g. '0 9 * * *' = every day 09:00). Mutually exclusive with `every`. */
7
+ pattern?: string;
8
+ /** Fixed interval in ms. Mutually exclusive with `pattern`. */
9
+ every?: number;
10
+ /** IANA timezone (e.g. 'UTC', 'America/New_York'). Required for `pattern` — prevents DST drift. */
11
+ tz?: string;
12
+ /** Stop repeating after this date. */
13
+ endDate?: Date | string | number;
14
+ /** Max total runs. */
15
+ limit?: number;
16
+ }
4
17
  interface JobDefinition<TData = unknown, TResult = unknown> {
5
18
  /** Unique job name */
6
19
  name: string;
@@ -22,8 +35,10 @@ interface JobDefinition<TData = unknown, TResult = unknown> {
22
35
  max: number;
23
36
  duration: number;
24
37
  };
25
- /** Dead letter queue name (default: '{name}:dead') */
38
+ /** Dead letter queue name (default: '{name}-dead') */
26
39
  deadLetterQueue?: string;
40
+ /** Repeat schedule — cron or interval. Requires explicit timezone for cron. */
41
+ repeat?: JobRepeatOptions;
27
42
  }
28
43
  interface JobMeta {
29
44
  jobId: string;
@@ -41,6 +56,8 @@ interface JobDispatchOptions {
41
56
  removeOnComplete?: boolean | number;
42
57
  /** Remove job after failure */
43
58
  removeOnFail?: boolean | number;
59
+ /** One-shot repeat override at dispatch time. Usually prefer `JobDefinition.repeat`. */
60
+ repeat?: JobRepeatOptions;
44
61
  }
45
62
  interface JobsPluginOptions {
46
63
  /** Redis connection options (passed to BullMQ) */
@@ -97,7 +114,12 @@ interface QueueStats {
97
114
  * });
98
115
  */
99
116
  declare function defineJob<TData = unknown, TResult = unknown>(definition: JobDefinition<TData, TResult>): JobDefinition<TData, TResult>;
100
- /** Pluggable BullMQ job queue integration for Arc */
117
+ /**
118
+ * Pluggable BullMQ job queue integration for Arc.
119
+ *
120
+ * Wrapped with fastify-plugin so the `fastify.jobs` decorator is available
121
+ * in the outer scope (the documented `fastify.jobs.dispatch(...)` usage).
122
+ */
101
123
  declare const jobsPlugin: FastifyPluginAsync<JobsPluginOptions>;
102
124
  //#endregion
103
- export { JobDefinition, JobDispatchOptions, JobDispatcher, JobMeta, JobsPluginOptions, QueueStats, defineJob, jobsPlugin };
125
+ export { JobDefinition, JobDispatchOptions, JobDispatcher, JobMeta, JobRepeatOptions, JobsPluginOptions, QueueStats, defineJob, jobsPlugin };
@@ -1,3 +1,4 @@
1
+ import fp from "fastify-plugin";
1
2
  //#region src/integrations/jobs.ts
2
3
  /**
3
4
  * Define a background job with typed data and configuration.
@@ -26,16 +27,41 @@ const jobsPluginImpl = async (fastify, options) => {
26
27
  } catch {
27
28
  throw new Error("@classytic/arc/integrations/jobs requires \"bullmq\" package.\nInstall it: npm install bullmq");
28
29
  }
30
+ if (connection && typeof connection === "object" && "options" in connection) {
31
+ if (connection.options?.maxRetriesPerRequest !== null) fastify.log.warn("[arc/jobs] BullMQ requires ioredis `maxRetriesPerRequest: null`. Pass `new Redis(url, { maxRetriesPerRequest: null, enableReadyCheck: false })` or workers will stall on transient Redis errors.");
32
+ }
29
33
  const queues = /* @__PURE__ */ new Map();
30
34
  const dlqQueues = /* @__PURE__ */ new Map();
31
35
  const workers = /* @__PURE__ */ new Map();
36
+ for (const job of jobs) {
37
+ if (!job.repeat) continue;
38
+ const { pattern, every, tz } = job.repeat;
39
+ if (pattern && every) throw new Error(`[arc/jobs] Job '${job.name}' sets both repeat.pattern and repeat.every — use one.`);
40
+ if (!pattern && every == null) throw new Error(`[arc/jobs] Job '${job.name}' has repeat config but no pattern or every.`);
41
+ if (pattern && !tz) throw new Error(`[arc/jobs] Job '${job.name}' uses a cron pattern but no timezone. Set repeat.tz (e.g. 'UTC' or 'America/New_York') to avoid DST drift.`);
42
+ }
32
43
  for (const job of jobs) {
33
44
  const queueName = job.name;
34
45
  const queue = new Queue(queueName, { connection });
35
46
  queues.set(queueName, queue);
47
+ if (job.repeat) {
48
+ const repeatOpts = {
49
+ ...job.repeat.pattern ? {
50
+ pattern: job.repeat.pattern,
51
+ tz: job.repeat.tz
52
+ } : { every: job.repeat.every },
53
+ ...job.repeat.endDate ? { endDate: job.repeat.endDate } : {},
54
+ ...job.repeat.limit != null ? { limit: job.repeat.limit } : {}
55
+ };
56
+ await queue.add(queueName, {}, {
57
+ repeat: repeatOpts,
58
+ removeOnComplete: defaults.removeOnComplete ?? 100,
59
+ removeOnFail: defaults.removeOnFail ?? 500
60
+ });
61
+ }
36
62
  let dlqQueue = null;
37
63
  if (job.deadLetterQueue != null) {
38
- const dlqName = job.deadLetterQueue || `${queueName}:dead`;
64
+ const dlqName = job.deadLetterQueue || `${queueName}-dead`;
39
65
  dlqQueue = new Queue(dlqName, { connection });
40
66
  dlqQueues.set(dlqName, dlqQueue);
41
67
  }
@@ -110,12 +136,35 @@ const jobsPluginImpl = async (fastify, options) => {
110
136
  }, `Failed to publish job.${queueName}.failed event`);
111
137
  }
112
138
  });
139
+ worker.on("stalled", async (jobId) => {
140
+ fastify.log.warn({
141
+ jobId,
142
+ queue: queueName
143
+ }, "Job stalled — worker may have crashed");
144
+ if (bridgeEvents && fastify.events?.publish) try {
145
+ await fastify.events.publish(`job.${queueName}.stalled`, { jobId });
146
+ } catch (err) {
147
+ fastify.log.warn({
148
+ err,
149
+ jobId
150
+ }, `Failed to publish job.${queueName}.stalled event`);
151
+ }
152
+ });
113
153
  workers.set(queueName, worker);
114
154
  }
155
+ const JOB_PAYLOAD_WARN_BYTES = 100 * 1024;
115
156
  const dispatcher = {
116
157
  async dispatch(name, data, opts = {}) {
117
158
  const queue = queues.get(name);
118
159
  if (!queue) throw new Error(`Job queue '${name}' not registered. Available: ${Array.from(queues.keys()).join(", ")}`);
160
+ try {
161
+ const serializedBytes = Buffer.byteLength(JSON.stringify(data) ?? "", "utf8");
162
+ if (serializedBytes > JOB_PAYLOAD_WARN_BYTES) fastify.log.warn({
163
+ queue: name,
164
+ bytes: serializedBytes,
165
+ limit: JOB_PAYLOAD_WARN_BYTES
166
+ }, `[arc/jobs] Large job payload — prefer passing IDs and reloading in the handler`);
167
+ } catch {}
119
168
  const jobDef = jobs.find((j) => j.name === name);
120
169
  return { jobId: (await queue.add(name, data, {
121
170
  delay: opts.delay,
@@ -127,7 +176,8 @@ const jobsPluginImpl = async (fastify, options) => {
127
176
  backoff: jobDef?.backoff ?? defaults.backoff ?? {
128
177
  type: "exponential",
129
178
  delay: 1e3
130
- }
179
+ },
180
+ repeat: jobDef?.repeat ?? opts.repeat
131
181
  })).id };
132
182
  },
133
183
  getQueue(name) {
@@ -148,6 +198,7 @@ const jobsPluginImpl = async (fastify, options) => {
148
198
  return stats;
149
199
  },
150
200
  async close() {
201
+ await Promise.all(Array.from(workers.values()).map((w) => w.pause().catch(() => {})));
151
202
  const closePromises = [];
152
203
  for (const worker of workers.values()) closePromises.push(worker.close());
153
204
  for (const queue of queues.values()) closePromises.push(queue.close());
@@ -166,7 +217,15 @@ const jobsPluginImpl = async (fastify, options) => {
166
217
  await dispatcher.close();
167
218
  });
168
219
  };
169
- /** Pluggable BullMQ job queue integration for Arc */
170
- const jobsPlugin = jobsPluginImpl;
220
+ /**
221
+ * Pluggable BullMQ job queue integration for Arc.
222
+ *
223
+ * Wrapped with fastify-plugin so the `fastify.jobs` decorator is available
224
+ * in the outer scope (the documented `fastify.jobs.dispatch(...)` usage).
225
+ */
226
+ const jobsPlugin = fp(jobsPluginImpl, {
227
+ name: "arc-jobs",
228
+ fastify: "5.x"
229
+ });
171
230
  //#endregion
172
231
  export { defineJob, jobsPlugin };
@@ -1,8 +1,56 @@
1
- import { qt as ResourceDefinition } from "../../interface-BVuMfeVv.mjs";
2
- import { a as McpAuthResolver, c as McpResourceConfig, d as SessionEntry, f as ToolAnnotations, i as CrudOperation, l as PromptDefinition, m as ToolDefinition, n as CallToolResult, o as McpAuthResult, p as ToolContext, r as CreateMcpServerConfig, s as McpPluginOptions, t as BetterAuthHandler, u as PromptResult } from "../../types-CcG4avic.mjs";
1
+ import { qt as ResourceDefinition } from "../../interface-CMRutPfe.mjs";
2
+ import { a as McpAuthResolver, c as McpResourceConfig, d as SessionEntry, f as ToolAnnotations, i as CrudOperation, l as PromptDefinition, m as ToolDefinition, n as CallToolResult, o as McpAuthResult, p as ToolContext, r as CreateMcpServerConfig, s as McpPluginOptions, t as BetterAuthHandler, u as PromptResult } from "../../types-BsbNMEDR.mjs";
3
3
  import { FastifyPluginAsync } from "fastify";
4
4
  import { z } from "zod";
5
5
 
6
+ //#region src/integrations/mcp/aiSdkBridge.d.ts
7
+ /** Minimal AI SDK tool shape we need to invoke. */
8
+ interface AiSdkExecutable {
9
+ execute: (input: unknown, options?: unknown) => Promise<unknown>;
10
+ }
11
+ interface McpBridge {
12
+ /** MCP tool name. */
13
+ name: string;
14
+ /** LLM-facing description. */
15
+ description: string;
16
+ /** Zod input schema — matches the AI SDK tool's inputSchema. */
17
+ inputSchema: Record<string, z.ZodType>;
18
+ /** MCP annotations — same shape as `defineTool`. */
19
+ annotations?: ToolAnnotations;
20
+ /**
21
+ * Build the AI SDK tool from MCP session context. Called per-request.
22
+ * The caller injects deps (companyId, projectId, etc.) from `ctx`.
23
+ */
24
+ buildTool: (ctx: ToolContext) => AiSdkExecutable;
25
+ /**
26
+ * Optional pre-execution guard. Return an error message to reject, or
27
+ * `null` to proceed. Runs after `isAuthenticated`.
28
+ */
29
+ guard?: (ctx: ToolContext) => string | null;
30
+ }
31
+ /** Convert a McpBridge into a registered MCP tool. */
32
+ declare function bridgeToMcp(bridge: McpBridge): ToolDefinition;
33
+ interface BuildMcpToolsFromBridgesOptions {
34
+ /** If set, only bridges whose `name` is in this array are registered. */
35
+ include?: string[];
36
+ /** If set, bridges whose `name` is in this array are skipped. */
37
+ exclude?: string[];
38
+ }
39
+ /**
40
+ * Take a list of McpBridge objects and produce a ready-to-register MCP tool
41
+ * array, with optional include/exclude filtering for per-environment config.
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * // All bridges
46
+ * extraTools: [...buildMcpToolsFromBridges(allBridges)]
47
+ *
48
+ * // Read-only deployment — hide destructive tools
49
+ * extraTools: [...buildMcpToolsFromBridges(allBridges, { exclude: ['trigger_job'] })]
50
+ * ```
51
+ */
52
+ declare function buildMcpToolsFromBridges(bridges: readonly McpBridge[], options?: BuildMcpToolsFromBridgesOptions): ToolDefinition[];
53
+ //#endregion
6
54
  //#region src/integrations/mcp/createMcpServer.d.ts
7
55
  /**
8
56
  * Mutable auth ref — updated per-request by mcpPlugin.
@@ -218,4 +266,4 @@ interface ResourceToToolsConfig extends McpResourceConfig {
218
266
  */
219
267
  declare function resourceToTools(resource: ResourceDefinition, config?: ResourceToToolsConfig): ToolDefinition[];
220
268
  //#endregion
221
- export { type AuthRef, type BetterAuthHandler, type CallToolResult, type CreateMcpServerConfig, type CrudOperation, type DefinePromptConfig, type DefineToolConfig, type FieldRuleEntry, type FieldRulesToZodOptions, type McpAuthResolver, type McpAuthResult, type McpGuard, type McpPluginOptions, type McpResourceConfig, type McpServerInstance, type PromptDefinition, type PromptResult, type ResourceToToolsConfig, type ToolAnnotations, type ToolContext, type ToolDefinition, createMcpServer, customGuard, definePrompt, defineTool, denied, fieldRulesToZod, getOrgId, getUserId, guard, hasOrg, isAuthenticated, isOrg, mcpPlugin, requireAuth, requireOrg, requireOrgId, requireRole, resourceToTools };
269
+ export { type AuthRef, type BetterAuthHandler, type BuildMcpToolsFromBridgesOptions, type CallToolResult, type CreateMcpServerConfig, type CrudOperation, type DefinePromptConfig, type DefineToolConfig, type FieldRuleEntry, type FieldRulesToZodOptions, type McpAuthResolver, type McpAuthResult, type McpBridge, type McpGuard, type McpPluginOptions, type McpResourceConfig, type McpServerInstance, type PromptDefinition, type PromptResult, type ResourceToToolsConfig, type ToolAnnotations, type ToolContext, type ToolDefinition, bridgeToMcp, buildMcpToolsFromBridges, createMcpServer, customGuard, definePrompt, defineTool, denied, fieldRulesToZod, getOrgId, getUserId, guard, hasOrg, isAuthenticated, isOrg, mcpPlugin, requireAuth, requireOrg, requireOrgId, requireRole, resourceToTools };
@@ -1,23 +1,6 @@
1
- import { n as fieldRulesToZod, r as createMcpServer, t as resourceToTools } from "../../resourceToTools-O_HwWXFa.mjs";
1
+ import { n as fieldRulesToZod, r as createMcpServer, t as resourceToTools } from "../../resourceToTools-8s-EsCCe.mjs";
2
2
  import { createHash } from "node:crypto";
3
3
  import fp from "fastify-plugin";
4
- //#region src/integrations/mcp/definePrompt.ts
5
- /**
6
- * Define a type-safe MCP prompt.
7
- *
8
- * @param name - Prompt name (snake_case recommended)
9
- * @param config - Description, args schema, handler
10
- */
11
- function definePrompt(name, config) {
12
- return {
13
- name,
14
- description: config.description,
15
- title: config.title,
16
- argsSchema: config.args,
17
- handler: config.handler
18
- };
19
- }
20
- //#endregion
21
4
  //#region src/integrations/mcp/defineTool.ts
22
5
  /**
23
6
  * Define a type-safe MCP tool.
@@ -127,6 +110,82 @@ function customGuard(check, errorMessage) {
127
110
  };
128
111
  }
129
112
  //#endregion
113
+ //#region src/integrations/mcp/aiSdkBridge.ts
114
+ /** Serialize an AI SDK tool result into MCP's text-content envelope. */
115
+ function toMcpEnvelope(result) {
116
+ if (result && typeof result === "object" && "error" in result) {
117
+ const msg = result.error;
118
+ return {
119
+ content: [{
120
+ type: "text",
121
+ text: typeof msg === "string" ? msg : JSON.stringify(msg)
122
+ }],
123
+ isError: true
124
+ };
125
+ }
126
+ return { content: [{
127
+ type: "text",
128
+ text: typeof result === "string" ? result : JSON.stringify(result, null, 2)
129
+ }] };
130
+ }
131
+ /** Convert a McpBridge into a registered MCP tool. */
132
+ function bridgeToMcp(bridge) {
133
+ return defineTool(bridge.name, {
134
+ description: bridge.description,
135
+ input: bridge.inputSchema,
136
+ annotations: bridge.annotations,
137
+ handler: async (input, ctx) => {
138
+ if (!isAuthenticated(ctx)) return denied("Authentication required");
139
+ if (bridge.guard) {
140
+ const reason = bridge.guard(ctx);
141
+ if (reason) return denied(reason);
142
+ }
143
+ try {
144
+ return toMcpEnvelope(await bridge.buildTool(ctx).execute(input));
145
+ } catch (err) {
146
+ return denied(err instanceof Error ? err.message : String(err));
147
+ }
148
+ }
149
+ });
150
+ }
151
+ /**
152
+ * Take a list of McpBridge objects and produce a ready-to-register MCP tool
153
+ * array, with optional include/exclude filtering for per-environment config.
154
+ *
155
+ * @example
156
+ * ```typescript
157
+ * // All bridges
158
+ * extraTools: [...buildMcpToolsFromBridges(allBridges)]
159
+ *
160
+ * // Read-only deployment — hide destructive tools
161
+ * extraTools: [...buildMcpToolsFromBridges(allBridges, { exclude: ['trigger_job'] })]
162
+ * ```
163
+ */
164
+ function buildMcpToolsFromBridges(bridges, options = {}) {
165
+ return bridges.filter((bridge) => {
166
+ if (options.include) return options.include.includes(bridge.name);
167
+ if (options.exclude) return !options.exclude.includes(bridge.name);
168
+ return true;
169
+ }).map(bridgeToMcp);
170
+ }
171
+ //#endregion
172
+ //#region src/integrations/mcp/definePrompt.ts
173
+ /**
174
+ * Define a type-safe MCP prompt.
175
+ *
176
+ * @param name - Prompt name (snake_case recommended)
177
+ * @param config - Description, args schema, handler
178
+ */
179
+ function definePrompt(name, config) {
180
+ return {
181
+ name,
182
+ description: config.description,
183
+ title: config.title,
184
+ argsSchema: config.args,
185
+ handler: config.handler
186
+ };
187
+ }
188
+ //#endregion
130
189
  //#region src/integrations/mcp/authBridge.ts
131
190
  /**
132
191
  * @classytic/arc — MCP Auth Bridge
@@ -572,4 +631,4 @@ const mcpPlugin = fp(mcpPluginImpl, {
572
631
  fastify: "5.x"
573
632
  });
574
633
  //#endregion
575
- export { createMcpServer, customGuard, definePrompt, defineTool, denied, fieldRulesToZod, getOrgId, getUserId, guard, hasOrg, isAuthenticated, isOrg, mcpPlugin, requireAuth, requireOrg, requireOrgId, requireRole, resourceToTools };
634
+ export { bridgeToMcp, buildMcpToolsFromBridges, createMcpServer, customGuard, definePrompt, defineTool, denied, fieldRulesToZod, getOrgId, getUserId, guard, hasOrg, isAuthenticated, isOrg, mcpPlugin, requireAuth, requireOrg, requireOrgId, requireRole, resourceToTools };
@@ -1,4 +1,4 @@
1
- import { o as McpAuthResult, s as McpPluginOptions } from "../../types-CcG4avic.mjs";
1
+ import { o as McpAuthResult, s as McpPluginOptions } from "../../types-BsbNMEDR.mjs";
2
2
 
3
3
  //#region src/integrations/mcp/testing.d.ts
4
4
  interface TestMcpClientOptions {
@@ -1,4 +1,4 @@
1
- import { r as createMcpServer, t as resourceToTools } from "../../resourceToTools-O_HwWXFa.mjs";
1
+ import { r as createMcpServer, t as resourceToTools } from "../../resourceToTools-8s-EsCCe.mjs";
2
2
  //#region src/integrations/mcp/testing.ts
3
3
  /**
4
4
  * @classytic/arc/mcp/testing — MCP Test Utilities
@@ -1,6 +1,6 @@
1
- import { r as RequestScope } from "./types-C72d3NDn.mjs";
2
- import { n as FieldPermissionMap } from "./fields-DC4So2M2.mjs";
3
- import { i as UserBase, t as PermissionCheck } from "./types-CVC4HOKi.mjs";
1
+ import { r as RequestScope } from "./types-BD85MlEK.mjs";
2
+ import { n as FieldPermissionMap } from "./fields-DpZQa_Q3.mjs";
3
+ import { i as UserBase, t as PermissionCheck } from "./types-DZi1aYhm.mjs";
4
4
  import { FastifyInstance, FastifyPluginAsync, FastifyReply, FastifyRequest, RouteHandlerMethod, RouteHandlerMethod as RouteHandlerMethod$1 } from "fastify";
5
5
 
6
6
  //#region src/hooks/HookSystem.d.ts
@@ -2419,8 +2419,20 @@ interface RouteDefinition {
2419
2419
  readonly preAuth?: RouteHandlerMethod[];
2420
2420
  /** SSE streaming mode */
2421
2421
  readonly streamResponse?: boolean;
2422
- /** Fastify route schema */
2423
- readonly schema?: Record<string, unknown>;
2422
+ /**
2423
+ * Fastify route schema. Each slot (`body`, `querystring`, `params`, `headers`,
2424
+ * `response[status]`) accepts a plain JSON Schema object **or** a Zod v4 schema —
2425
+ * arc auto-converts via `convertRouteSchema` at registration time. Slot values
2426
+ * are typed `unknown` so class-based Zod schemas assign without casts.
2427
+ */
2428
+ readonly schema?: {
2429
+ body?: unknown;
2430
+ querystring?: unknown;
2431
+ params?: unknown;
2432
+ headers?: unknown;
2433
+ response?: Record<number | string, unknown>;
2434
+ [key: string]: unknown;
2435
+ };
2424
2436
  /**
2425
2437
  * MCP tool generation:
2426
2438
  * - omitted/true: auto-generate (non-raw routes only)
@@ -2452,8 +2464,11 @@ interface ActionDefinition {
2452
2464
  readonly handler: ActionHandlerFn;
2453
2465
  /** Per-action permission check (overrides resource-level actionPermissions) */
2454
2466
  readonly permissions?: PermissionCheck;
2455
- /** JSON Schema for action-specific body fields */
2456
- readonly schema?: Record<string, Record<string, unknown>>;
2467
+ /**
2468
+ * JSON Schema or Zod v4 schema for action-specific body fields.
2469
+ * Per-field values are typed `unknown` so Zod class instances assign without casts.
2470
+ */
2471
+ readonly schema?: Record<string, unknown>;
2457
2472
  /** Description for OpenAPI docs and MCP tool */
2458
2473
  readonly description?: string;
2459
2474
  /**
@@ -2506,47 +2521,54 @@ interface FieldRule {
2506
2521
  /**
2507
2522
  * CRUD Route Schemas (Fastify Native Format)
2508
2523
  *
2524
+ * Each slot accepts either a plain JSON Schema object **or** a Zod v4 schema —
2525
+ * arc's `convertRouteSchema` feature-detects at runtime. The slot values are
2526
+ * typed `unknown` (not `Record<string, unknown>`) so class-based Zod schemas
2527
+ * assign cleanly without `as unknown as Record<string, unknown>` casts.
2528
+ *
2509
2529
  * @example
2530
+ * ```ts
2510
2531
  * {
2511
2532
  * list: {
2512
2533
  * querystring: { type: 'object', properties: { page: { type: 'number' } } },
2513
- * response: { 200: { type: 'object', properties: { docs: { type: 'array' } } } }
2534
+ * response: { 200: z.object({ docs: z.array(EntitySchema) }) }
2514
2535
  * },
2515
2536
  * create: {
2516
- * body: { type: 'object', properties: { name: { type: 'string' } } },
2517
- * response: { 201: { type: 'object' } }
2537
+ * body: z.object({ name: z.string(), size: z.number().int().positive() }),
2538
+ * response: { 201: EntitySchema }
2518
2539
  * }
2519
2540
  * }
2541
+ * ```
2520
2542
  */
2521
2543
  interface CrudSchemas {
2522
2544
  /** GET / - List all resources */
2523
2545
  list?: {
2524
- querystring?: Record<string, unknown>;
2546
+ /** Plain JSON Schema or Zod schema (auto-converted). */querystring?: unknown; /** Map of HTTP status code → JSON Schema or Zod schema. */
2525
2547
  response?: Record<number, unknown>;
2526
2548
  [key: string]: unknown;
2527
2549
  };
2528
2550
  /** GET /:id - Get single resource */
2529
2551
  get?: {
2530
- params?: Record<string, unknown>;
2552
+ params?: unknown;
2531
2553
  response?: Record<number, unknown>;
2532
2554
  [key: string]: unknown;
2533
2555
  };
2534
2556
  /** POST / - Create resource */
2535
2557
  create?: {
2536
- body?: Record<string, unknown>;
2558
+ body?: unknown;
2537
2559
  response?: Record<number, unknown>;
2538
2560
  [key: string]: unknown;
2539
2561
  };
2540
2562
  /** PATCH /:id - Update resource */
2541
2563
  update?: {
2542
- params?: Record<string, unknown>;
2543
- body?: Record<string, unknown>;
2564
+ params?: unknown;
2565
+ body?: unknown;
2544
2566
  response?: Record<number, unknown>;
2545
2567
  [key: string]: unknown;
2546
2568
  };
2547
2569
  /** DELETE /:id - Delete resource */
2548
2570
  delete?: {
2549
- params?: Record<string, unknown>;
2571
+ params?: unknown;
2550
2572
  response?: Record<number, unknown>;
2551
2573
  [key: string]: unknown;
2552
2574
  };
@@ -1,4 +1,4 @@
1
- import { i as UserBase } from "./types-CVC4HOKi.mjs";
1
+ import { i as UserBase } from "./types-DZi1aYhm.mjs";
2
2
 
3
3
  //#region src/audit/stores/interface.d.ts
4
4
  type AuditAction = "create" | "update" | "delete" | "restore" | "custom";
@@ -1,4 +1,4 @@
1
- import { n as IdempotencyResult, r as IdempotencyStore } from "./interface-B-pe8fhj.mjs";
1
+ import { n as IdempotencyResult, r as IdempotencyStore } from "./interface-DfLGcus7.mjs";
2
2
 
3
3
  //#region src/idempotency/stores/mongodb.d.ts
4
4
  interface MongoConnection {
@@ -1,6 +1,6 @@
1
1
  import { t as getUserRoles } from "./types-ZUu_h0jp.mjs";
2
- import { n as convertRouteSchema } from "./schemaConverter-OxfCshus.mjs";
3
- import { t as buildActionBodySchema } from "./createActionRouter-Df1BuawX.mjs";
2
+ import { n as convertRouteSchema } from "./schemaConverter-Y7nCYaLJ.mjs";
3
+ import { t as buildActionBodySchema } from "./createActionRouter-BORM8f17.mjs";
4
4
  import fp from "fastify-plugin";
5
5
  //#region src/docs/openapi.ts
6
6
  const openApiPlugin = async (fastify, opts = {}) => {
@@ -288,7 +288,7 @@ function generateResourcePaths(resource, apiPrefix = "", additionalSecurity = []
288
288
  responses: { "200": { description: route.description || "Success" } }
289
289
  };
290
290
  const rawSchema = route.schema;
291
- const routeSchema = rawSchema ? convertRouteSchema(rawSchema) : void 0;
291
+ const routeSchema = rawSchema ? convertRouteSchema(rawSchema, "openapi-3.0") : void 0;
292
292
  if (routeSchema?.body && [
293
293
  "post",
294
294
  "put",
@@ -1,5 +1,5 @@
1
- import { Wt as RouteHandler } from "../interface-BVuMfeVv.mjs";
2
- import { i as UserBase } from "../types-CVC4HOKi.mjs";
1
+ import { Wt as RouteHandler } from "../interface-CMRutPfe.mjs";
2
+ import { i as UserBase } from "../types-DZi1aYhm.mjs";
3
3
  import { InvitationAdapter, InvitationDoc, MemberDoc, OrgAdapter, OrgDoc, OrgPermissionStatement, OrgRole, OrganizationPluginOptions } from "./types.mjs";
4
4
  import { FastifyPluginAsync, RouteHandlerMethod } from "fastify";
5
5
 
@@ -1,4 +1,4 @@
1
- import { a as applyFieldWritePermissions, i as applyFieldReadPermissions, n as FieldPermissionMap, o as fields, r as FieldPermissionType, s as resolveEffectiveRoles, t as FieldPermission } from "../fields-DC4So2M2.mjs";
2
- import { a as getUserRoles, i as UserBase, n as PermissionContext, o as normalizeRoles, r as PermissionResult, t as PermissionCheck } from "../types-CVC4HOKi.mjs";
3
- import { A as RoleHierarchy, C as authenticated, D as publicRead, E as presets_d_exports, M as applyPermissionResult, N as normalizePermissionResult, O as publicReadAdminWrite, S as adminOnly, T as ownerWithAdminBypass, _ as requireScopeContext, a as allOf, b as roles, c as createDynamicPermissionMatrix, d as requireAuth, f as requireOrgInScope, g as requireRoles, h as requireOwnership, i as PermissionEventBus, j as createRoleHierarchy, k as readOnly, l as createOrgPermissions, m as requireOrgRole, n as DynamicPermissionMatrix, o as allowPublic, p as requireOrgMembership, r as DynamicPermissionMatrixConfig, s as anyOf, t as ConnectEventsOptions, u as denyAll, v as requireServiceScope, w as fullPublic, x as when, y as requireTeamMembership } from "../index-CSkeivBx.mjs";
1
+ import { a as applyFieldWritePermissions, i as applyFieldReadPermissions, n as FieldPermissionMap, o as fields, r as FieldPermissionType, s as resolveEffectiveRoles, t as FieldPermission } from "../fields-DpZQa_Q3.mjs";
2
+ import { a as getUserRoles, i as UserBase, n as PermissionContext, o as normalizeRoles, r as PermissionResult, t as PermissionCheck } from "../types-DZi1aYhm.mjs";
3
+ import { A as RoleHierarchy, C as authenticated, D as publicRead, E as presets_d_exports, M as applyPermissionResult, N as normalizePermissionResult, O as publicReadAdminWrite, S as adminOnly, T as ownerWithAdminBypass, _ as requireScopeContext, a as allOf, b as roles, c as createDynamicPermissionMatrix, d as requireAuth, f as requireOrgInScope, g as requireRoles, h as requireOwnership, i as PermissionEventBus, j as createRoleHierarchy, k as readOnly, l as createOrgPermissions, m as requireOrgRole, n as DynamicPermissionMatrix, o as allowPublic, p as requireOrgMembership, r as DynamicPermissionMatrixConfig, s as anyOf, t as ConnectEventsOptions, u as denyAll, v as requireServiceScope, w as fullPublic, x as when, y as requireTeamMembership } from "../index-BLXBmWud.mjs";
4
4
  export { ConnectEventsOptions, DynamicPermissionMatrix, DynamicPermissionMatrixConfig, FieldPermission, FieldPermissionMap, FieldPermissionType, PermissionCheck, PermissionContext, PermissionEventBus, PermissionResult, RoleHierarchy, UserBase, adminOnly, allOf, allowPublic, anyOf, applyFieldReadPermissions, applyFieldWritePermissions, applyPermissionResult, authenticated, createDynamicPermissionMatrix, createOrgPermissions, createRoleHierarchy, denyAll, fields, fullPublic, getUserRoles, normalizePermissionResult, normalizeRoles, ownerWithAdminBypass, presets_d_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAuth, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, resolveEffectiveRoles, roles, when };
@@ -1,7 +1,7 @@
1
- import { K as MiddlewareConfig, Kt as ResourceRegistry, Tn as HookSystem, et as PresetHook, m as AnyRecord, p as AdditionalRoute, vt as RouteSchemaOptions } from "../interface-BVuMfeVv.mjs";
2
- import { t as ExternalOpenApiPaths } from "../externalPaths-Bapitwvd.mjs";
3
- import { _ as _default$1, a as _default$7, c as MetricsCollector, d as metricsPlugin, f as SSEOptions, g as CachingRule, h as CachingOptions, i as VersioningOptions, l as MetricsOptions, m as ssePlugin, n as ErrorMapper, o as versioningPlugin, p as _default$6, r as errorHandlerPlugin, s as MetricEntry, t as ErrorHandlerOptions, u as _default$4, v as cachingPlugin } from "../errorHandler-CdZDavNH.mjs";
4
- import { t as TracingOptions } from "../tracing-DxjKk7eW.mjs";
1
+ import { K as MiddlewareConfig, Kt as ResourceRegistry, Tn as HookSystem, et as PresetHook, m as AnyRecord, p as AdditionalRoute, vt as RouteSchemaOptions } from "../interface-CMRutPfe.mjs";
2
+ import { t as ExternalOpenApiPaths } from "../externalPaths-BnkYrNzp.mjs";
3
+ import { _ as _default$1, a as _default$7, c as MetricsCollector, d as metricsPlugin, f as SSEOptions, g as CachingRule, h as CachingOptions, i as VersioningOptions, l as MetricsOptions, m as ssePlugin, n as ErrorMapper, o as versioningPlugin, p as _default$6, r as errorHandlerPlugin, s as MetricEntry, t as ErrorHandlerOptions, u as _default$4, v as cachingPlugin } from "../errorHandler-Bah5JhBd.mjs";
4
+ import { t as TracingOptions } from "../tracing-DdN2-wHJ.mjs";
5
5
  import { FastifyInstance, FastifyPluginAsync } from "fastify";
6
6
  import * as _$node_stream0 from "node:stream";
7
7
 
@@ -2,14 +2,14 @@ import { p as MUTATION_OPERATIONS } from "../constants-Cxde4rpC.mjs";
2
2
  import { o as getOrgId } from "../types-AOD8fxIw.mjs";
3
3
  import { t as requestContext } from "../requestContext-DYvHl113.mjs";
4
4
  import { t as hasEvents } from "../typeGuards-CcFZXgU7.mjs";
5
- import { t as HookSystem } from "../HookSystem-BjFu7zf1.mjs";
6
- import { t as ResourceRegistry } from "../ResourceRegistry-Dq3_zBQP.mjs";
7
- import { n as caching_default, t as cachingPlugin } from "../caching-CjybdRwx.mjs";
8
- import { t as errorHandlerPlugin } from "../errorHandler-mzqk4cGl.mjs";
9
- import { n as metrics_default, t as metricsPlugin } from "../metrics-TuOmguhi.mjs";
10
- import { t as replyHelpersPlugin } from "../replyHelpers-BLojtuvR.mjs";
11
- import { n as sse_default, t as ssePlugin } from "../sse-CJpt7LGI.mjs";
12
- import { n as versioning_default, t as versioningPlugin } from "../versioning-Cm8qoFDg.mjs";
5
+ import { t as HookSystem } from "../HookSystem-HprTmvVY.mjs";
6
+ import { t as ResourceRegistry } from "../ResourceRegistry-C6uXlWe3.mjs";
7
+ import { n as caching_default, t as cachingPlugin } from "../caching-IMuYVjTL.mjs";
8
+ import { t as errorHandlerPlugin } from "../errorHandler-f869_8PQ.mjs";
9
+ import { n as metrics_default, t as metricsPlugin } from "../metrics-B-PU4-Yu.mjs";
10
+ import { t as replyHelpersPlugin } from "../replyHelpers-CxkYGT81.mjs";
11
+ import { n as sse_default, t as ssePlugin } from "../sse-Ad7ypl9e.mjs";
12
+ import { n as versioning_default, t as versioningPlugin } from "../versioning-CDugduqI.mjs";
13
13
  import { randomUUID } from "node:crypto";
14
14
  import fp from "fastify-plugin";
15
15
  //#region src/core/arcCorePlugin.ts
@@ -1,2 +1,2 @@
1
- import { a as traced, i as isTracingAvailable, n as _default, r as createSpan, t as TracingOptions } from "../tracing-DxjKk7eW.mjs";
1
+ import { a as traced, i as isTracingAvailable, n as _default, r as createSpan, t as TracingOptions } from "../tracing-DdN2-wHJ.mjs";
2
2
  export { type TracingOptions, createSpan, isTracingAvailable, traced, _default as tracingPlugin };
@@ -44,7 +44,7 @@ try {
44
44
  function createTracerProvider(options) {
45
45
  if (!isAvailable) return null;
46
46
  const { serviceName = "@classytic/arc", serviceVersion, exporterUrl = "http://localhost:4318/v1/traces" } = options;
47
- const resolvedVersion = serviceVersion ?? "2.8.3";
47
+ const resolvedVersion = serviceVersion ?? "2.8.5";
48
48
  const exporter = new OTLPTraceExporter({ url: exporterUrl });
49
49
  const provider = new NodeTracerProvider({ resource: { attributes: {
50
50
  "service.name": serviceName,
@@ -1,4 +1,4 @@
1
- import { t as PermissionCheck } from "../types-CVC4HOKi.mjs";
1
+ import { t as PermissionCheck } from "../types-DZi1aYhm.mjs";
2
2
  import { FastifyReply, FastifyRequest } from "fastify";
3
3
 
4
4
  //#region src/policies/PolicyInterface.d.ts
@@ -0,0 +1,49 @@
1
+ import { r as RequestScope } from "../types-BD85MlEK.mjs";
2
+ import { tt as PresetResult } from "../interface-CMRutPfe.mjs";
3
+ import { t as PermissionCheck } from "../types-DZi1aYhm.mjs";
4
+ import { a as StorageReadResult, i as StorageReadRange, n as StorageContext, o as StorageUploadInput, r as StorageFile, t as Storage } from "../storage-Dfzt4VTl.mjs";
5
+
6
+ //#region src/presets/filesUpload.d.ts
7
+ interface FilesUploadPresetRoutes {
8
+ upload?: boolean;
9
+ read?: boolean;
10
+ delete?: boolean;
11
+ }
12
+ interface FilesUploadPresetPermissions {
13
+ upload?: PermissionCheck;
14
+ read?: PermissionCheck;
15
+ delete?: PermissionCheck;
16
+ }
17
+ interface FilesUploadPresetOptions {
18
+ /** Any implementation of the `Storage` interface. App owns it. */
19
+ storage: Storage;
20
+ /** Multipart form field name. Default: `'file'`. */
21
+ fieldName?: string;
22
+ /** Max bytes per file. Forwarded to `multipartBody`. Default: 10 MB. */
23
+ maxFileSize?: number;
24
+ /** IANA MIME allow-list. Forwarded to `multipartBody`. Default: no filter. */
25
+ allowedMimeTypes?: string[];
26
+ /**
27
+ * Per-route permissions.
28
+ * Defaults: upload → `requireAuth()`, read → `allowPublic()`, delete → `requireAuth()`.
29
+ */
30
+ permissions?: FilesUploadPresetPermissions;
31
+ /** Opt out of individual routes. Default: all three enabled. */
32
+ includeRoutes?: FilesUploadPresetRoutes;
33
+ /**
34
+ * Map arc's `RequestScope` to `StorageContext.scope`.
35
+ * Default: `{ userId, organizationId }` extracted via `getUserId` / `getOrgId`.
36
+ * Adapters ignore keys they don't care about.
37
+ */
38
+ contextFrom?: (scope: RequestScope | undefined) => Record<string, unknown>;
39
+ }
40
+ /**
41
+ * Create a files-upload preset bound to a `Storage` adapter.
42
+ *
43
+ * The preset uses `raw: true` routes so binary responses bypass arc's JSON
44
+ * envelope. Upload still returns the standard `{ success: true, data }`
45
+ * envelope manually because the response is structured metadata, not bytes.
46
+ */
47
+ declare function filesUploadPreset(options: FilesUploadPresetOptions): PresetResult;
48
+ //#endregion
49
+ export { FilesUploadPresetOptions, FilesUploadPresetPermissions, FilesUploadPresetRoutes, type Storage, type StorageContext, type StorageFile, type StorageReadRange, type StorageReadResult, type StorageUploadInput, filesUploadPreset };
@@ -0,0 +1,2 @@
1
+ import { t as filesUploadPreset } from "../filesUpload-C7r7HIeA.mjs";
2
+ export { filesUploadPreset };