@classytic/arc 2.8.4 → 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.
- package/README.md +28 -0
- package/dist/adapters/index.d.mts +2 -2
- 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 +2 -2
- package/dist/auth/redis-session.d.mts +1 -1
- package/dist/{betterAuthOpenApi-C5lDyRH2.mjs → betterAuthOpenApi-BuUcUEJq.mjs} +1 -1
- package/dist/cache/index.d.mts +73 -3
- package/dist/cache/index.mjs +95 -2
- 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 +3 -3
- package/dist/{core-DKSwNSXf.mjs → core-F0QoWBt2.mjs} +1 -1
- package/dist/{createActionRouter-Df1BuawX.mjs → createActionRouter-BORM8f17.mjs} +1 -1
- package/dist/{createApp-BOYjBgdI.mjs → createApp-B1EY8zxa.mjs} +11 -11
- package/dist/{defineResource-Bb_Bdhtw.mjs → defineResource-tcgySDo1.mjs} +2 -2
- 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-BBGFjzIP.mjs → elevation-DtFxrG0s.mjs} +1 -1
- package/dist/{errorHandler-CdZDavNH.d.mts → errorHandler-Bah5JhBd.d.mts} +1 -1
- package/dist/{eventPlugin-CVxlE6De.d.mts → eventPlugin-D9DKB2zM.d.mts} +1 -1
- package/dist/events/index.d.mts +3 -3
- package/dist/events/index.mjs +1 -1
- 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/filesUpload-C7r7HIeA.mjs +319 -0
- 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 +2 -2
- package/dist/idempotency/redis.mjs +134 -13
- package/dist/{index-CSkeivBx.d.mts → index-BLXBmWud.d.mts} +3 -3
- package/dist/{index-BgmMdpm8.d.mts → index-C1meYuDn.d.mts} +1 -1
- package/dist/{index-CpTSDqmD.d.mts → index-DtDzOBn8.d.mts} +3 -3
- package/dist/index.d.mts +7 -7
- package/dist/index.mjs +4 -4
- 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/jobs.d.mts +25 -3
- package/dist/integrations/jobs.mjs +63 -4
- 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-BVuMfeVv.d.mts → interface-CMRutPfe.d.mts} +38 -16
- package/dist/{mongodb-B8U2xaLj.d.mts → mongodb-BsP-WbhN.d.mts} +1 -1
- package/dist/{mongodb-X7LbEjTN.d.mts → mongodb-CTcp0hQZ.d.mts} +1 -1
- package/dist/{openapi-CYCuekCn.mjs → openapi-CbKUJY_m.mjs} +3 -3
- 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 +8 -8
- 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/filesUpload.d.mts +49 -0
- package/dist/presets/filesUpload.mjs +2 -0
- package/dist/presets/index.d.mts +3 -2
- package/dist/presets/index.mjs +2 -1
- package/dist/presets/multiTenant.d.mts +1 -1
- package/dist/{queryCachePlugin-CnTZZTC5.d.mts → queryCachePlugin-BJJGBTlu.d.mts} +1 -1
- package/dist/redis-BM00zaPB.d.mts +115 -0
- package/dist/{redis-stream-D54N5oXs.d.mts → redis-stream-CrsfUmPt.d.mts} +1 -1
- package/dist/registry/index.d.mts +1 -1
- package/dist/registry/index.mjs +2 -2
- package/dist/{resourceToTools-O_HwWXFa.mjs → resourceToTools-8s-EsCCe.mjs} +1 -1
- package/dist/rpc/index.d.mts +1 -1
- package/dist/{schemaConverter-OxfCshus.mjs → schemaConverter-Y7nCYaLJ.mjs} +24 -8
- package/dist/scope/index.d.mts +2 -2
- package/dist/scope/index.mjs +1 -1
- package/dist/{sse-CJpt7LGI.mjs → sse-Ad7ypl9e.mjs} +1 -1
- package/dist/storage-Dfzt4VTl.d.mts +146 -0
- package/dist/testing/index.d.mts +4 -3
- package/dist/testing/index.mjs +3 -2
- package/dist/testing/storageContract.d.mts +26 -0
- package/dist/testing/storageContract.mjs +216 -0
- package/dist/types/index.d.mts +4 -4
- package/dist/types/storage.d.mts +2 -0
- package/dist/types/storage.mjs +1 -0
- package/dist/{types-CcG4avic.d.mts → types-BsbNMEDR.d.mts} +1 -1
- package/dist/{types-Bg2X42_m.d.mts → types-Ch9pTQbf.d.mts} +9 -9
- package/dist/{types-CVC4HOKi.d.mts → types-DZi1aYhm.d.mts} +1 -1
- package/dist/utils/index.d.mts +26 -8
- package/dist/utils/index.mjs +1 -1
- package/package.json +16 -1
- package/skills/arc/references/events.md +29 -0
- package/dist/redis-z3sFr1UP.d.mts +0 -49
- /package/dist/{EventTransport-CinyO7zQ.d.mts → EventTransport-BXja8NOc.d.mts} +0 -0
- /package/dist/{HookSystem-BjFu7zf1.mjs → HookSystem-HprTmvVY.mjs} +0 -0
- /package/dist/{ResourceRegistry-Dq3_zBQP.mjs → ResourceRegistry-C6uXlWe3.mjs} +0 -0
- /package/dist/{caching-CjybdRwx.mjs → caching-IMuYVjTL.mjs} +0 -0
- /package/dist/{circuitBreaker-CvXkjfrW.d.mts → circuitBreaker-dTtG-UyS.d.mts} +0 -0
- /package/dist/{elevation-s5ykdNHr.d.mts → elevation-B6S5csVA.d.mts} +0 -0
- /package/dist/{errorHandler-mzqk4cGl.mjs → errorHandler-f869_8PQ.mjs} +0 -0
- /package/dist/{errors-Bmn3eZT6.d.mts → errors-Ck2h67pm.d.mts} +0 -0
- /package/dist/{eventPlugin-D91S2YF4.mjs → eventPlugin-CDjVTM82.mjs} +0 -0
- /package/dist/{externalPaths-Bapitwvd.d.mts → externalPaths-BnkYrNzp.d.mts} +0 -0
- /package/dist/{fields-DC4So2M2.d.mts → fields-DpZQa_Q3.d.mts} +0 -0
- /package/dist/{interface-DplgQO2e.d.mts → interface-4y979v99.d.mts} +0 -0
- /package/dist/{interface-B-pe8fhj.d.mts → interface-DfLGcus7.d.mts} +0 -0
- /package/dist/{loadResources-Bksk8ydA.mjs → loadResources-PWd0OCpV.mjs} +0 -0
- /package/dist/{logger-CDjpjySd.mjs → logger-D1YrIImS.mjs} +0 -0
- /package/dist/{metrics-TuOmguhi.mjs → metrics-B-PU4-Yu.mjs} +0 -0
- /package/dist/{mongodb-B5O6xaW1.mjs → mongodb-Utc5k_-0.mjs} +0 -0
- /package/dist/{pluralize-A0tWEl1K.mjs → pluralize-CWP6MB39.mjs} +0 -0
- /package/dist/{queryCachePlugin-D0iIVhW_.mjs → queryCachePlugin-BH-fidlv.mjs} +0 -0
- /package/dist/{registry-B0Wl7uVV.mjs → registry-BiTKT1Dg.mjs} +0 -0
- /package/dist/{replyHelpers-BLojtuvR.mjs → replyHelpers-CxkYGT81.mjs} +0 -0
- /package/dist/{sessionManager-D-oNWHz3.d.mts → sessionManager-DDCmiNIo.d.mts} +0 -0
- /package/dist/{tracing-DxjKk7eW.d.mts → tracing-DdN2-wHJ.d.mts} +0 -0
- /package/dist/{types-C72d3NDn.d.mts → types-BD85MlEK.d.mts} +0 -0
- /package/dist/{versioning-Cm8qoFDg.mjs → versioning-CDugduqI.mjs} +0 -0
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import { o as getOrgId, p as getUserId } from "./types-AOD8fxIw.mjs";
|
|
2
|
+
import { i as NotFoundError, u as ValidationError } from "./errors-BF2bIOIS.mjs";
|
|
3
|
+
import { n as allowPublic, s as requireAuth } from "./permissions-CH4cNwJi.mjs";
|
|
4
|
+
//#region src/middleware/multipartBody.ts
|
|
5
|
+
const DEFAULT_MAX_FILE_SIZE$1 = 10 * 1024 * 1024;
|
|
6
|
+
const DEFAULT_MAX_FILES = 5;
|
|
7
|
+
const DEFAULT_FILES_KEY = "_files";
|
|
8
|
+
/**
|
|
9
|
+
* Create a multipart body parsing middleware.
|
|
10
|
+
*
|
|
11
|
+
* When a request has `content-type: multipart/form-data`, this middleware:
|
|
12
|
+
* 1. Reads all parts (fields + files)
|
|
13
|
+
* 2. Sets text fields on `req.body` as a plain object
|
|
14
|
+
* 3. Attaches file buffers to `req.body[filesKey]` (default: `req.body._files`)
|
|
15
|
+
*
|
|
16
|
+
* For non-multipart requests (regular JSON), this is a no-op — the request
|
|
17
|
+
* passes through unchanged. This makes it safe to add to create/update
|
|
18
|
+
* middlewares without breaking JSON clients.
|
|
19
|
+
*/
|
|
20
|
+
function multipartBody(options = {}) {
|
|
21
|
+
const maxFileSize = options.maxFileSize ?? DEFAULT_MAX_FILE_SIZE$1;
|
|
22
|
+
const maxFiles = options.maxFiles ?? DEFAULT_MAX_FILES;
|
|
23
|
+
const allowedMimeTypes = options.allowedMimeTypes ? new Set(options.allowedMimeTypes) : void 0;
|
|
24
|
+
const filesKey = options.filesKey ?? DEFAULT_FILES_KEY;
|
|
25
|
+
const requiredFields = options.requiredFields && options.requiredFields.length > 0 ? options.requiredFields : void 0;
|
|
26
|
+
return async function parseMultipartBody(request, reply) {
|
|
27
|
+
if (!(request.headers["content-type"] ?? "").includes("multipart/form-data")) return;
|
|
28
|
+
if (typeof request.parts !== "function") {
|
|
29
|
+
request.log.warn("multipartBody middleware: @fastify/multipart not registered. Ensure createApp() has multipart enabled (default) or install @fastify/multipart.");
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const body = {};
|
|
33
|
+
const files = {};
|
|
34
|
+
let fileCount = 0;
|
|
35
|
+
try {
|
|
36
|
+
const parts = request.parts();
|
|
37
|
+
for await (const part of parts) if (part.type === "file") {
|
|
38
|
+
if (fileCount >= maxFiles) continue;
|
|
39
|
+
if (allowedMimeTypes && !allowedMimeTypes.has(part.mimetype)) return reply.code(415).send({
|
|
40
|
+
success: false,
|
|
41
|
+
error: `File type '${part.mimetype}' not allowed. Accepted: ${[...allowedMimeTypes].join(", ")}`
|
|
42
|
+
});
|
|
43
|
+
const buffer = await part.toBuffer();
|
|
44
|
+
if (buffer.length > maxFileSize) return reply.code(413).send({
|
|
45
|
+
success: false,
|
|
46
|
+
error: `File '${part.filename}' exceeds maximum size of ${Math.round(maxFileSize / 1024 / 1024)}MB`
|
|
47
|
+
});
|
|
48
|
+
files[part.fieldname] = {
|
|
49
|
+
filename: part.filename,
|
|
50
|
+
mimetype: part.mimetype,
|
|
51
|
+
buffer,
|
|
52
|
+
size: buffer.length,
|
|
53
|
+
fieldname: part.fieldname
|
|
54
|
+
};
|
|
55
|
+
fileCount++;
|
|
56
|
+
} else body[part.fieldname] = tryParseValue(part.value);
|
|
57
|
+
} catch (err) {
|
|
58
|
+
request.log.error({ err }, "multipartBody: failed to parse multipart form");
|
|
59
|
+
return reply.code(400).send({
|
|
60
|
+
success: false,
|
|
61
|
+
error: "Failed to parse multipart form data"
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
if (requiredFields) {
|
|
65
|
+
const missing = requiredFields.filter((name) => !(name in files));
|
|
66
|
+
if (missing.length > 0) return reply.code(400).send({
|
|
67
|
+
success: false,
|
|
68
|
+
error: `Missing required file field${missing.length > 1 ? "s" : ""}: ${missing.join(", ")}`,
|
|
69
|
+
code: "MISSING_FILE_FIELDS",
|
|
70
|
+
details: { missing }
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
if (fileCount > 0) body[filesKey] = files;
|
|
74
|
+
request.body = body;
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Try to parse a form field value as JSON, number, or boolean.
|
|
79
|
+
* Falls back to the raw string if parsing fails.
|
|
80
|
+
*/
|
|
81
|
+
function tryParseValue(value) {
|
|
82
|
+
if (value === "true") return true;
|
|
83
|
+
if (value === "false") return false;
|
|
84
|
+
if (value === "null") return null;
|
|
85
|
+
if (/^-?\d+(\.\d+)?$/.test(value) && value.length < 16) {
|
|
86
|
+
const num = Number(value);
|
|
87
|
+
if (Number.isFinite(num)) return num;
|
|
88
|
+
}
|
|
89
|
+
if (value.startsWith("{") && value.endsWith("}") || value.startsWith("[") && value.endsWith("]")) try {
|
|
90
|
+
return JSON.parse(value);
|
|
91
|
+
} catch {}
|
|
92
|
+
return value;
|
|
93
|
+
}
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region src/presets/filesUpload.ts
|
|
96
|
+
const DEFAULT_FIELD_NAME = "file";
|
|
97
|
+
const DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
98
|
+
function defaultContextFrom(scope) {
|
|
99
|
+
if (!scope) return {};
|
|
100
|
+
const userId = getUserId(scope);
|
|
101
|
+
const organizationId = getOrgId(scope);
|
|
102
|
+
const ctx = {};
|
|
103
|
+
if (userId !== void 0) ctx.userId = userId;
|
|
104
|
+
if (organizationId !== void 0) ctx.organizationId = organizationId;
|
|
105
|
+
return ctx;
|
|
106
|
+
}
|
|
107
|
+
function buildStorageContext(request, contextFrom) {
|
|
108
|
+
const scope = request.scope;
|
|
109
|
+
return {
|
|
110
|
+
scope: contextFrom(scope),
|
|
111
|
+
requestId: request.id
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Parse a single-range `Range: bytes=start-end` header.
|
|
116
|
+
*
|
|
117
|
+
* Returns `undefined` when the header is missing or unparseable. Only
|
|
118
|
+
* satisfiable single ranges are supported — multi-range requests fall through
|
|
119
|
+
* to the full-object response (per RFC 7233 §4.1 a server MAY ignore ranges).
|
|
120
|
+
*/
|
|
121
|
+
function parseRangeHeader(header, totalSize) {
|
|
122
|
+
if (!header || !header.startsWith("bytes=")) return void 0;
|
|
123
|
+
const spec = header.slice(6).split(",")[0]?.trim();
|
|
124
|
+
if (!spec) return void 0;
|
|
125
|
+
const dashIndex = spec.indexOf("-");
|
|
126
|
+
if (dashIndex === -1) return void 0;
|
|
127
|
+
const startRaw = spec.slice(0, dashIndex);
|
|
128
|
+
const endRaw = spec.slice(dashIndex + 1);
|
|
129
|
+
if (startRaw === "") {
|
|
130
|
+
if (totalSize === void 0) return void 0;
|
|
131
|
+
const suffix = Number(endRaw);
|
|
132
|
+
if (!Number.isFinite(suffix) || suffix <= 0) return void 0;
|
|
133
|
+
return {
|
|
134
|
+
start: Math.max(0, totalSize - suffix),
|
|
135
|
+
end: totalSize - 1
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
const start = Number(startRaw);
|
|
139
|
+
if (!Number.isFinite(start) || start < 0) return void 0;
|
|
140
|
+
if (endRaw === "") {
|
|
141
|
+
if (totalSize === void 0) return void 0;
|
|
142
|
+
return {
|
|
143
|
+
start,
|
|
144
|
+
end: totalSize - 1
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
const end = Number(endRaw);
|
|
148
|
+
if (!Number.isFinite(end) || end < start) return void 0;
|
|
149
|
+
if (totalSize !== void 0 && end >= totalSize) return {
|
|
150
|
+
start,
|
|
151
|
+
end: totalSize - 1
|
|
152
|
+
};
|
|
153
|
+
return {
|
|
154
|
+
start,
|
|
155
|
+
end
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function makeUploadHandler(deps) {
|
|
159
|
+
return async function uploadHandler(request, reply) {
|
|
160
|
+
const file = (request.body?._files)?.[deps.fieldName];
|
|
161
|
+
if (!file) throw new ValidationError(`Missing file field '${deps.fieldName}' in multipart body`);
|
|
162
|
+
const ctx = buildStorageContext(request, deps.contextFrom);
|
|
163
|
+
const result = await deps.storage.upload({
|
|
164
|
+
buffer: file.buffer,
|
|
165
|
+
filename: file.filename,
|
|
166
|
+
mimeType: file.mimetype,
|
|
167
|
+
size: file.size
|
|
168
|
+
}, ctx);
|
|
169
|
+
return reply.code(201).send({
|
|
170
|
+
success: true,
|
|
171
|
+
data: toResponseFile(result)
|
|
172
|
+
});
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
function toResponseFile(file) {
|
|
176
|
+
const payload = {
|
|
177
|
+
id: file.id,
|
|
178
|
+
url: file.url,
|
|
179
|
+
pathname: file.pathname,
|
|
180
|
+
contentType: file.contentType,
|
|
181
|
+
bytes: file.bytes
|
|
182
|
+
};
|
|
183
|
+
if (file.metadata !== void 0) payload.metadata = file.metadata;
|
|
184
|
+
return payload;
|
|
185
|
+
}
|
|
186
|
+
function makeReadHandler(deps) {
|
|
187
|
+
return async function readHandler(request, reply) {
|
|
188
|
+
const { id } = request.params;
|
|
189
|
+
const ctx = buildStorageContext(request, deps.contextFrom);
|
|
190
|
+
reply.header("Accept-Ranges", "bytes");
|
|
191
|
+
const rangeHeader = request.headers.range;
|
|
192
|
+
let result;
|
|
193
|
+
try {
|
|
194
|
+
const parsed = rangeHeader ? parseRangeHeader(rangeHeader, void 0) : void 0;
|
|
195
|
+
result = await deps.storage.read(id, ctx, parsed);
|
|
196
|
+
} catch (err) {
|
|
197
|
+
throw toNotFound(err, "File", id);
|
|
198
|
+
}
|
|
199
|
+
if (result.kind === "buffer") return sendBuffer(reply, result, rangeHeader);
|
|
200
|
+
return sendStream(reply, result, rangeHeader);
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
function sendBuffer(reply, result, rangeHeader) {
|
|
204
|
+
reply.type(result.contentType);
|
|
205
|
+
const total = result.totalBytes ?? result.buffer.length;
|
|
206
|
+
if (result.range) {
|
|
207
|
+
const { start, end } = result.range;
|
|
208
|
+
reply.code(206);
|
|
209
|
+
reply.header("Content-Range", `bytes ${start}-${end}/${total}`);
|
|
210
|
+
reply.header("Content-Length", String(result.buffer.length));
|
|
211
|
+
return reply.send(result.buffer);
|
|
212
|
+
}
|
|
213
|
+
if (rangeHeader) {
|
|
214
|
+
const parsed = parseRangeHeader(rangeHeader, total);
|
|
215
|
+
if (parsed) {
|
|
216
|
+
const slice = result.buffer.subarray(parsed.start, parsed.end + 1);
|
|
217
|
+
reply.code(206);
|
|
218
|
+
reply.header("Content-Range", `bytes ${parsed.start}-${parsed.end}/${total}`);
|
|
219
|
+
reply.header("Content-Length", String(slice.length));
|
|
220
|
+
return reply.send(slice);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
reply.header("Content-Length", String(result.buffer.length));
|
|
224
|
+
return reply.send(result.buffer);
|
|
225
|
+
}
|
|
226
|
+
function sendStream(reply, result, rangeHeader) {
|
|
227
|
+
reply.type(result.contentType);
|
|
228
|
+
if (result.range && result.bytes !== void 0) {
|
|
229
|
+
const { start, end } = result.range;
|
|
230
|
+
reply.code(206);
|
|
231
|
+
reply.header("Content-Range", `bytes ${start}-${end}/${result.bytes}`);
|
|
232
|
+
reply.header("Content-Length", String(end - start + 1));
|
|
233
|
+
} else if (result.bytes !== void 0) {
|
|
234
|
+
reply.header("Content-Length", String(result.bytes));
|
|
235
|
+
if (rangeHeader) reply.request.log.debug({ url: reply.request.url }, "filesUploadPreset: adapter returned unsliced stream for a range request — sending full object");
|
|
236
|
+
}
|
|
237
|
+
return reply.send(result.stream);
|
|
238
|
+
}
|
|
239
|
+
function makeDeleteHandler(deps) {
|
|
240
|
+
return async function deleteHandler(request, reply) {
|
|
241
|
+
const { id } = request.params;
|
|
242
|
+
const ctx = buildStorageContext(request, deps.contextFrom);
|
|
243
|
+
if (!await deps.storage.delete(id, ctx)) throw new NotFoundError("File", id);
|
|
244
|
+
return reply.code(204).send();
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
function toNotFound(err, resource, id) {
|
|
248
|
+
if (err instanceof NotFoundError) return err;
|
|
249
|
+
const maybe = err;
|
|
250
|
+
if (maybe?.statusCode === 404 || maybe?.code === "NOT_FOUND") return new NotFoundError(resource, id);
|
|
251
|
+
if (typeof maybe?.message === "string" && /not\s*found/i.test(maybe.message)) return new NotFoundError(resource, id);
|
|
252
|
+
return err;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Create a files-upload preset bound to a `Storage` adapter.
|
|
256
|
+
*
|
|
257
|
+
* The preset uses `raw: true` routes so binary responses bypass arc's JSON
|
|
258
|
+
* envelope. Upload still returns the standard `{ success: true, data }`
|
|
259
|
+
* envelope manually because the response is structured metadata, not bytes.
|
|
260
|
+
*/
|
|
261
|
+
function filesUploadPreset(options) {
|
|
262
|
+
if (!options?.storage) throw new Error("filesUploadPreset: `storage` is required");
|
|
263
|
+
const deps = {
|
|
264
|
+
storage: options.storage,
|
|
265
|
+
fieldName: options.fieldName ?? DEFAULT_FIELD_NAME,
|
|
266
|
+
contextFrom: options.contextFrom ?? defaultContextFrom
|
|
267
|
+
};
|
|
268
|
+
const maxFileSize = options.maxFileSize ?? DEFAULT_MAX_FILE_SIZE;
|
|
269
|
+
const allowedMimeTypes = options.allowedMimeTypes;
|
|
270
|
+
const includeRoutes = {
|
|
271
|
+
upload: options.includeRoutes?.upload ?? true,
|
|
272
|
+
read: options.includeRoutes?.read ?? true,
|
|
273
|
+
delete: options.includeRoutes?.delete ?? true
|
|
274
|
+
};
|
|
275
|
+
return {
|
|
276
|
+
name: "filesUpload",
|
|
277
|
+
routes: (permissions) => {
|
|
278
|
+
const routes = [];
|
|
279
|
+
if (includeRoutes.upload) routes.push({
|
|
280
|
+
method: "POST",
|
|
281
|
+
path: "/upload",
|
|
282
|
+
operation: "filesUpload.upload",
|
|
283
|
+
summary: "Upload a file",
|
|
284
|
+
description: "Accepts a multipart/form-data request and persists the bytes via the configured Storage adapter.",
|
|
285
|
+
permissions: options.permissions?.upload ?? permissions.create ?? requireAuth(),
|
|
286
|
+
preHandler: [multipartBody({
|
|
287
|
+
maxFileSize,
|
|
288
|
+
allowedMimeTypes,
|
|
289
|
+
requiredFields: [deps.fieldName]
|
|
290
|
+
})],
|
|
291
|
+
raw: true,
|
|
292
|
+
handler: makeUploadHandler(deps)
|
|
293
|
+
});
|
|
294
|
+
if (includeRoutes.read) routes.push({
|
|
295
|
+
method: "GET",
|
|
296
|
+
path: "/:id",
|
|
297
|
+
operation: "filesUpload.read",
|
|
298
|
+
summary: "Download a file",
|
|
299
|
+
description: "Streams the stored bytes. Supports single-range `Range: bytes=start-end`.",
|
|
300
|
+
permissions: options.permissions?.read ?? permissions.get ?? allowPublic(),
|
|
301
|
+
raw: true,
|
|
302
|
+
handler: makeReadHandler(deps),
|
|
303
|
+
mcp: false
|
|
304
|
+
});
|
|
305
|
+
if (includeRoutes.delete) routes.push({
|
|
306
|
+
method: "DELETE",
|
|
307
|
+
path: "/:id",
|
|
308
|
+
operation: "filesUpload.delete",
|
|
309
|
+
summary: "Delete a file",
|
|
310
|
+
permissions: options.permissions?.delete ?? permissions.delete ?? requireAuth(),
|
|
311
|
+
raw: true,
|
|
312
|
+
handler: makeDeleteHandler(deps)
|
|
313
|
+
});
|
|
314
|
+
return routes;
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
//#endregion
|
|
319
|
+
export { filesUploadPreset as t };
|
package/dist/hooks/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { An as beforeCreate, Cn as HookPhase, Dn as afterCreate, En as HookSystemOptions, Mn as beforeUpdate, Nn as createHookSystem, On as afterDelete, Pn as defineHook, Sn as HookOperation, Tn as HookSystem, bn as HookContext, jn as beforeDelete, kn as afterUpdate, wn as HookRegistration, xn as HookHandler, yn as DefineHookOptions } from "../interface-
|
|
1
|
+
import { An as beforeCreate, Cn as HookPhase, Dn as afterCreate, En as HookSystemOptions, Mn as beforeUpdate, Nn as createHookSystem, On as afterDelete, Pn as defineHook, Sn as HookOperation, Tn as HookSystem, bn as HookContext, jn as beforeDelete, kn as afterUpdate, wn as HookRegistration, xn as HookHandler, yn as DefineHookOptions } from "../interface-CMRutPfe.mjs";
|
|
2
2
|
export { type DefineHookOptions, type HookContext, type HookHandler, type HookOperation, type HookPhase, type HookRegistration, HookSystem, type HookSystemOptions, afterCreate, afterDelete, afterUpdate, beforeCreate, beforeDelete, beforeUpdate, createHookSystem, defineHook };
|
package/dist/hooks/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as beforeCreate, c as createHookSystem, i as afterUpdate, l as defineHook, n as afterCreate, o as beforeDelete, r as afterDelete, s as beforeUpdate, t as HookSystem } from "../HookSystem-
|
|
1
|
+
import { a as beforeCreate, c as createHookSystem, i as afterUpdate, l as defineHook, n as afterCreate, o as beforeDelete, r as afterDelete, s as beforeUpdate, t as HookSystem } from "../HookSystem-HprTmvVY.mjs";
|
|
2
2
|
export { HookSystem, afterCreate, afterDelete, afterUpdate, beforeCreate, beforeDelete, beforeUpdate, createHookSystem, defineHook };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { i as createIdempotencyResult, n as IdempotencyResult, r as IdempotencyStore, t as IdempotencyLock } from "../interface-
|
|
2
|
-
import { n as MongoIdempotencyStoreOptions } from "../mongodb-
|
|
3
|
-
import {
|
|
1
|
+
import { i as createIdempotencyResult, n as IdempotencyResult, r as IdempotencyStore, t as IdempotencyLock } from "../interface-DfLGcus7.mjs";
|
|
2
|
+
import { n as MongoIdempotencyStoreOptions } from "../mongodb-CTcp0hQZ.mjs";
|
|
3
|
+
import { i as RedisIdempotencyStoreOptions, n as RedisClient } from "../redis-BM00zaPB.mjs";
|
|
4
4
|
import { FastifyPluginAsync } from "fastify";
|
|
5
5
|
|
|
6
6
|
//#region src/idempotency/idempotencyPlugin.d.ts
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as MongoIdempotencyStoreOptions, t as MongoIdempotencyStore } from "../mongodb-
|
|
1
|
+
import { n as MongoIdempotencyStoreOptions, t as MongoIdempotencyStore } from "../mongodb-CTcp0hQZ.mjs";
|
|
2
2
|
export { MongoIdempotencyStore, type MongoIdempotencyStoreOptions };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as
|
|
2
|
-
export { type RedisClient, RedisIdempotencyStore, type RedisIdempotencyStoreOptions };
|
|
1
|
+
import { a as UpstashRedisLike, i as RedisIdempotencyStoreOptions, n as RedisClient, o as ioredisAsIdempotencyClient, r as RedisIdempotencyStore, s as upstashAsIdempotencyClient, t as IoredisLike } from "../redis-BM00zaPB.mjs";
|
|
2
|
+
export { type IoredisLike, type RedisClient, RedisIdempotencyStore, type RedisIdempotencyStoreOptions, type UpstashRedisLike, ioredisAsIdempotencyClient, upstashAsIdempotencyClient };
|
|
@@ -77,18 +77,24 @@ var RedisIdempotencyStore = class {
|
|
|
77
77
|
}
|
|
78
78
|
async findByPrefix(prefix) {
|
|
79
79
|
const keys = await this.scanByPrefix(this.resultKey(prefix));
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
80
|
+
if (keys.length === 0) return void 0;
|
|
81
|
+
const BATCH_SIZE = 10;
|
|
82
|
+
const now = /* @__PURE__ */ new Date();
|
|
83
|
+
for (let i = 0; i < keys.length; i += BATCH_SIZE) {
|
|
84
|
+
const batch = keys.slice(i, i + BATCH_SIZE);
|
|
85
|
+
const values = await Promise.all(batch.map((k) => this.client.get(k)));
|
|
86
|
+
for (const data of values) {
|
|
87
|
+
if (!data) continue;
|
|
88
|
+
try {
|
|
89
|
+
const result = JSON.parse(data);
|
|
90
|
+
if (new Date(result.expiresAt) < now) continue;
|
|
91
|
+
return {
|
|
92
|
+
...result,
|
|
93
|
+
createdAt: new Date(result.createdAt),
|
|
94
|
+
expiresAt: new Date(result.expiresAt)
|
|
95
|
+
};
|
|
96
|
+
} catch {}
|
|
97
|
+
}
|
|
92
98
|
}
|
|
93
99
|
}
|
|
94
100
|
/** Scan Redis keys matching a prefix pattern. Falls back to empty if SCAN unavailable. */
|
|
@@ -105,5 +111,120 @@ var RedisIdempotencyStore = class {
|
|
|
105
111
|
}
|
|
106
112
|
async close() {}
|
|
107
113
|
};
|
|
114
|
+
/**
|
|
115
|
+
* Wrap an ioredis instance as the arc idempotency `RedisClient`.
|
|
116
|
+
*
|
|
117
|
+
* Arc's idempotency store expects node-redis-v4 style option objects
|
|
118
|
+
* (`{ EX, NX }`). ioredis uses positional flags. This adapter lets users
|
|
119
|
+
* plug an ioredis instance in without writing the bridge themselves.
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```typescript
|
|
123
|
+
* import Redis from 'ioredis';
|
|
124
|
+
* import { RedisIdempotencyStore, ioredisAsIdempotencyClient }
|
|
125
|
+
* from '@classytic/arc/idempotency/redis';
|
|
126
|
+
*
|
|
127
|
+
* const redis = new Redis(process.env.REDIS_URL);
|
|
128
|
+
* const store = new RedisIdempotencyStore({
|
|
129
|
+
* client: ioredisAsIdempotencyClient(redis),
|
|
130
|
+
* });
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
function ioredisAsIdempotencyClient(client) {
|
|
134
|
+
return {
|
|
135
|
+
async get(key) {
|
|
136
|
+
return client.get(key);
|
|
137
|
+
},
|
|
138
|
+
async set(key, value, options) {
|
|
139
|
+
const args = [key, value];
|
|
140
|
+
if (options?.EX != null) args.push("EX", options.EX);
|
|
141
|
+
if (options?.NX) args.push("NX");
|
|
142
|
+
return client.set(...args);
|
|
143
|
+
},
|
|
144
|
+
async del(key) {
|
|
145
|
+
if (Array.isArray(key)) return client.del(...key);
|
|
146
|
+
return client.del(key);
|
|
147
|
+
},
|
|
148
|
+
async exists(key) {
|
|
149
|
+
if (Array.isArray(key)) return client.exists(...key);
|
|
150
|
+
return client.exists(key);
|
|
151
|
+
},
|
|
152
|
+
async scan(cursor, ...args) {
|
|
153
|
+
const [next, keys] = await client.scan(cursor, ...args);
|
|
154
|
+
return [next, keys];
|
|
155
|
+
},
|
|
156
|
+
eval: client.eval ? (script, numKeys, ...args) => client.eval(script, numKeys, ...args) : void 0,
|
|
157
|
+
async quit() {
|
|
158
|
+
if (client.quit) return client.quit();
|
|
159
|
+
return "OK";
|
|
160
|
+
},
|
|
161
|
+
async disconnect() {
|
|
162
|
+
if (client.disconnect) client.disconnect();
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Wrap an `@upstash/redis` REST client as an idempotency `RedisClient`.
|
|
168
|
+
*
|
|
169
|
+
* Enables running arc's idempotency store on Cloudflare Workers, Vercel Edge
|
|
170
|
+
* and Deno Deploy — runtimes that don't support raw TCP (ioredis).
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```typescript
|
|
174
|
+
* import { Redis } from '@upstash/redis';
|
|
175
|
+
* import { RedisIdempotencyStore, upstashAsIdempotencyClient }
|
|
176
|
+
* from '@classytic/arc/idempotency/redis';
|
|
177
|
+
*
|
|
178
|
+
* const redis = Redis.fromEnv();
|
|
179
|
+
* const store = new RedisIdempotencyStore({
|
|
180
|
+
* client: upstashAsIdempotencyClient(redis),
|
|
181
|
+
* });
|
|
182
|
+
* ```
|
|
183
|
+
*/
|
|
184
|
+
function upstashAsIdempotencyClient(client) {
|
|
185
|
+
return {
|
|
186
|
+
async get(key) {
|
|
187
|
+
const raw = await client.get(key);
|
|
188
|
+
if (raw == null) return null;
|
|
189
|
+
return typeof raw === "string" ? raw : JSON.stringify(raw);
|
|
190
|
+
},
|
|
191
|
+
async set(key, value, options) {
|
|
192
|
+
const opts = {};
|
|
193
|
+
if (options?.EX != null) opts.ex = options.EX;
|
|
194
|
+
if (options?.NX) opts.nx = true;
|
|
195
|
+
const res = await client.set(key, value, opts);
|
|
196
|
+
return res == null ? null : String(res);
|
|
197
|
+
},
|
|
198
|
+
async del(key) {
|
|
199
|
+
if (Array.isArray(key)) return client.del(...key);
|
|
200
|
+
return client.del(key);
|
|
201
|
+
},
|
|
202
|
+
async exists(key) {
|
|
203
|
+
if (Array.isArray(key)) return client.exists(...key);
|
|
204
|
+
return client.exists(key);
|
|
205
|
+
},
|
|
206
|
+
async scan(cursor, ...args) {
|
|
207
|
+
const opts = {};
|
|
208
|
+
for (let i = 0; i < args.length; i += 2) {
|
|
209
|
+
const flag = String(args[i]).toLowerCase();
|
|
210
|
+
const val = args[i + 1];
|
|
211
|
+
if (flag === "match" && typeof val === "string") opts.match = val;
|
|
212
|
+
if (flag === "count") opts.count = Number(val);
|
|
213
|
+
}
|
|
214
|
+
const [next, keys] = await client.scan(cursor, opts);
|
|
215
|
+
return [next, keys];
|
|
216
|
+
},
|
|
217
|
+
eval: client.eval ? async (script, _numKeys, ...args) => {
|
|
218
|
+
const keyCount = _numKeys;
|
|
219
|
+
const keys = args.slice(0, keyCount).map(String);
|
|
220
|
+
const rest = args.slice(keyCount);
|
|
221
|
+
return client.eval(script, keys, rest);
|
|
222
|
+
} : void 0,
|
|
223
|
+
async quit() {
|
|
224
|
+
return "OK";
|
|
225
|
+
},
|
|
226
|
+
async disconnect() {}
|
|
227
|
+
};
|
|
228
|
+
}
|
|
108
229
|
//#endregion
|
|
109
|
-
export { RedisIdempotencyStore };
|
|
230
|
+
export { RedisIdempotencyStore, ioredisAsIdempotencyClient, upstashAsIdempotencyClient };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { r as RequestScope } from "./types-
|
|
2
|
-
import { n as PermissionContext, r as PermissionResult, t as PermissionCheck } from "./types-
|
|
3
|
-
import { i as CacheStore, t as CacheLogger } from "./interface-
|
|
1
|
+
import { r as RequestScope } from "./types-BD85MlEK.mjs";
|
|
2
|
+
import { n as PermissionContext, r as PermissionResult, t as PermissionCheck } from "./types-DZi1aYhm.mjs";
|
|
3
|
+
import { i as CacheStore, t as CacheLogger } from "./interface-4y979v99.mjs";
|
|
4
4
|
import { FastifyRequest } from "fastify";
|
|
5
5
|
|
|
6
6
|
//#region src/permissions/applyPermissionResult.d.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Y as OpenApiSchemas, Z as ParsedQuery, Zt as CrudRepository, c as ValidationResult, n as AdapterSchemaContext, nt as QueryParserInterface, o as RepositoryLike, r as DataAdapter, s as SchemaMetadata, vt as RouteSchemaOptions } from "./interface-
|
|
1
|
+
import { Y as OpenApiSchemas, Z as ParsedQuery, Zt as CrudRepository, c as ValidationResult, n as AdapterSchemaContext, nt as QueryParserInterface, o as RepositoryLike, r as DataAdapter, s as SchemaMetadata, vt as RouteSchemaOptions } from "./interface-CMRutPfe.mjs";
|
|
2
2
|
import { Model } from "mongoose";
|
|
3
3
|
|
|
4
4
|
//#region src/adapters/mongoose.d.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { r as RequestScope } from "./types-
|
|
2
|
-
import { D as CrudRouterOptions, Ht as IControllerResponse, N as FastifyWithDecorators, T as CrudController, Ut as IRequestContext, Vt as IController, ct as RequestWithExtras, m as AnyRecord, ot as RequestContext, qt as ResourceDefinition, ut as ResourceConfig } from "./interface-
|
|
3
|
-
import { t as PermissionCheck } from "./types-
|
|
1
|
+
import { r as RequestScope } from "./types-BD85MlEK.mjs";
|
|
2
|
+
import { D as CrudRouterOptions, Ht as IControllerResponse, N as FastifyWithDecorators, T as CrudController, Ut as IRequestContext, Vt as IController, ct as RequestWithExtras, m as AnyRecord, ot as RequestContext, qt as ResourceDefinition, ut as ResourceConfig } from "./interface-CMRutPfe.mjs";
|
|
3
|
+
import { t as PermissionCheck } from "./types-DZi1aYhm.mjs";
|
|
4
4
|
import { FastifyInstance, FastifyReply, FastifyRequest, RouteHandlerMethod } from "fastify";
|
|
5
5
|
|
|
6
6
|
//#region src/constants.d.ts
|
package/dist/index.d.mts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { $ as PresetFunction, $t as DeleteOptions, At as BaseController, B as InferResourceDoc, C as ConfigError, Ct as TypedResourceConfig, D as CrudRouterOptions, Dt as ValidationResult$1, E as CrudRouteKey, Et as ValidateOptions, F as GracefulShutdownOptions, H as IntrospectionPluginOptions, Ht as IControllerResponse, I as HealthCheck, Jt as defineResource, K as MiddlewareConfig, L as HealthOptions, M as FastifyWithAuth, N as FastifyWithDecorators, O as CrudSchemas, Ot as envelope, P as FieldRule, Qt as DeleteManyResult, R as InferAdapterDoc, St as TypedRepository, T as CrudController, Tt as UserOrganization, U as JWTPayload, Ut as IRequestContext, V as IntrospectionData, Vt as IController, Wt as RouteHandler, X as OwnershipCheck, Xt as BulkWriteResult, Yt as BulkWriteOperation, Zt as CrudRepository, _ as ArcInternalMetadata, _n as PipelineStep, a as RelationMetadata, an as PaginationParams, at as RegistryStats, b as AuthPluginOptions, c as ValidationResult, cn as RepositorySession, ct as RequestWithExtras, dn as Guard, en as DeleteResult, fn as Interceptor, gn as PipelineContext, gt as RouteHandlerMethod, h as ApiResponse, hn as PipelineConfig, i as FieldMetadata, in as PaginatedResult, it as RegistryEntry, j as FastifyRequestExtras, jt as BaseControllerOptions, k as EventDefinition, ln as UpdateManyResult, m as AnyRecord, mn as OperationFilter, nn as KeysetPaginatedResult, o as RepositoryLike, on as PaginationResult, ot as RequestContext, p as AdditionalRoute, pn as NextFunction, pt as ResourceMetadata, q as MiddlewareHandler, qt as ResourceDefinition, r as DataAdapter, rn as OffsetPaginatedResult, rt as RateLimitConfig, s as SchemaMetadata, sn as QueryOptions, st as RequestIdOptions, tt as PresetResult, un as WriteOptions, ut as ResourceConfig, v as ArcRequest, vn as Transform, vt as RouteSchemaOptions, xt as TypedController, yt as ServiceContext, z as InferDocType, zt as ControllerLike } from "./interface-
|
|
2
|
-
import { a as applyFieldWritePermissions, i as applyFieldReadPermissions, n as FieldPermissionMap, o as fields, t as FieldPermission } from "./fields-
|
|
3
|
-
import { i as UserBase, n as PermissionContext, r as PermissionResult, t as PermissionCheck } from "./types-
|
|
4
|
-
import { l as createMongooseAdapter, o as createPrismaAdapter, s as MongooseAdapter, t as PrismaAdapter } from "./index-
|
|
5
|
-
import { A as MUTATION_OPERATIONS, C as HOOK_OPERATIONS, D as MAX_FILTER_DEPTH, E as HookPhase, M as RESERVED_QUERY_PARAMS, N as SYSTEM_FIELDS, O as MAX_REGEX_LENGTH, S as DEFAULT_UPDATE_METHOD, T as HookOperation, _ as DEFAULT_ID_FIELD, a as getControllerScope, b as DEFAULT_SORT, g as CrudOperation, h as CRUD_OPERATIONS, j as MutationOperation, k as MAX_SEARCH_LENGTH, s as defineResourceVariants, v as DEFAULT_LIMIT, w as HOOK_PHASES, x as DEFAULT_TENANT_FIELD, y as DEFAULT_MAX_LIMIT } from "./index-
|
|
6
|
-
import { C as authenticated, D as publicRead, E as presets_d_exports, O as publicReadAdminWrite, S as adminOnly, T as ownerWithAdminBypass, _ as requireScopeContext, a as allOf, c as createDynamicPermissionMatrix, d as requireAuth, f as requireOrgInScope, g as requireRoles, h as requireOwnership, k as readOnly, l as createOrgPermissions, m as requireOrgRole, n as DynamicPermissionMatrix, o as allowPublic, p as requireOrgMembership, r as DynamicPermissionMatrixConfig, s as anyOf, u as denyAll, v as requireServiceScope, w as fullPublic, x as when, y as requireTeamMembership } from "./index-
|
|
7
|
-
import { a as NotFoundError, d as ValidationError, f as createDomainError, i as ForbiddenError, t as ArcError, u as UnauthorizedError } from "./errors-
|
|
1
|
+
import { $ as PresetFunction, $t as DeleteOptions, At as BaseController, B as InferResourceDoc, C as ConfigError, Ct as TypedResourceConfig, D as CrudRouterOptions, Dt as ValidationResult$1, E as CrudRouteKey, Et as ValidateOptions, F as GracefulShutdownOptions, H as IntrospectionPluginOptions, Ht as IControllerResponse, I as HealthCheck, Jt as defineResource, K as MiddlewareConfig, L as HealthOptions, M as FastifyWithAuth, N as FastifyWithDecorators, O as CrudSchemas, Ot as envelope, P as FieldRule, Qt as DeleteManyResult, R as InferAdapterDoc, St as TypedRepository, T as CrudController, Tt as UserOrganization, U as JWTPayload, Ut as IRequestContext, V as IntrospectionData, Vt as IController, Wt as RouteHandler, X as OwnershipCheck, Xt as BulkWriteResult, Yt as BulkWriteOperation, Zt as CrudRepository, _ as ArcInternalMetadata, _n as PipelineStep, a as RelationMetadata, an as PaginationParams, at as RegistryStats, b as AuthPluginOptions, c as ValidationResult, cn as RepositorySession, ct as RequestWithExtras, dn as Guard, en as DeleteResult, fn as Interceptor, gn as PipelineContext, gt as RouteHandlerMethod, h as ApiResponse, hn as PipelineConfig, i as FieldMetadata, in as PaginatedResult, it as RegistryEntry, j as FastifyRequestExtras, jt as BaseControllerOptions, k as EventDefinition, ln as UpdateManyResult, m as AnyRecord, mn as OperationFilter, nn as KeysetPaginatedResult, o as RepositoryLike, on as PaginationResult, ot as RequestContext, p as AdditionalRoute, pn as NextFunction, pt as ResourceMetadata, q as MiddlewareHandler, qt as ResourceDefinition, r as DataAdapter, rn as OffsetPaginatedResult, rt as RateLimitConfig, s as SchemaMetadata, sn as QueryOptions, st as RequestIdOptions, tt as PresetResult, un as WriteOptions, ut as ResourceConfig, v as ArcRequest, vn as Transform, vt as RouteSchemaOptions, xt as TypedController, yt as ServiceContext, z as InferDocType, zt as ControllerLike } from "./interface-CMRutPfe.mjs";
|
|
2
|
+
import { a as applyFieldWritePermissions, i as applyFieldReadPermissions, n as FieldPermissionMap, o as fields, t as FieldPermission } from "./fields-DpZQa_Q3.mjs";
|
|
3
|
+
import { i as UserBase, n as PermissionContext, r as PermissionResult, t as PermissionCheck } from "./types-DZi1aYhm.mjs";
|
|
4
|
+
import { l as createMongooseAdapter, o as createPrismaAdapter, s as MongooseAdapter, t as PrismaAdapter } from "./index-C1meYuDn.mjs";
|
|
5
|
+
import { A as MUTATION_OPERATIONS, C as HOOK_OPERATIONS, D as MAX_FILTER_DEPTH, E as HookPhase, M as RESERVED_QUERY_PARAMS, N as SYSTEM_FIELDS, O as MAX_REGEX_LENGTH, S as DEFAULT_UPDATE_METHOD, T as HookOperation, _ as DEFAULT_ID_FIELD, a as getControllerScope, b as DEFAULT_SORT, g as CrudOperation, h as CRUD_OPERATIONS, j as MutationOperation, k as MAX_SEARCH_LENGTH, s as defineResourceVariants, v as DEFAULT_LIMIT, w as HOOK_PHASES, x as DEFAULT_TENANT_FIELD, y as DEFAULT_MAX_LIMIT } from "./index-DtDzOBn8.mjs";
|
|
6
|
+
import { C as authenticated, D as publicRead, E as presets_d_exports, O as publicReadAdminWrite, S as adminOnly, T as ownerWithAdminBypass, _ as requireScopeContext, a as allOf, c as createDynamicPermissionMatrix, d as requireAuth, f as requireOrgInScope, g as requireRoles, h as requireOwnership, k as readOnly, l as createOrgPermissions, m as requireOrgRole, n as DynamicPermissionMatrix, o as allowPublic, p as requireOrgMembership, r as DynamicPermissionMatrixConfig, s as anyOf, u as denyAll, v as requireServiceScope, w as fullPublic, x as when, y as requireTeamMembership } from "./index-BLXBmWud.mjs";
|
|
7
|
+
import { a as NotFoundError, d as ValidationError, f as createDomainError, i as ForbiddenError, t as ArcError, u as UnauthorizedError } from "./errors-Ck2h67pm.mjs";
|
|
8
8
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
9
9
|
import { RouteHandlerMethod as RouteHandlerMethod$1 } from "fastify";
|
|
10
10
|
|
package/dist/index.mjs
CHANGED
|
@@ -5,10 +5,10 @@ import { envelope } from "./types/index.mjs";
|
|
|
5
5
|
import { n as applyFieldWritePermissions, r as fields, t as applyFieldReadPermissions } from "./fields-ipsbIRPK.mjs";
|
|
6
6
|
import { t as requestContext } from "./requestContext-DYvHl113.mjs";
|
|
7
7
|
import { d as createDomainError, i as NotFoundError, l as UnauthorizedError, r as ForbiddenError, t as ArcError, u as ValidationError } from "./errors-BF2bIOIS.mjs";
|
|
8
|
-
import { a as validateResourceConfig, f as getControllerScope, i as formatValidationErrors, m as pipe, n as defineResource, r as assertValidConfig, t as ResourceDefinition } from "./defineResource-
|
|
8
|
+
import { a as validateResourceConfig, f as getControllerScope, i as formatValidationErrors, m as pipe, n as defineResource, r as assertValidConfig, t as ResourceDefinition } from "./defineResource-tcgySDo1.mjs";
|
|
9
9
|
import { C as publicRead, S as presets_exports, T as readOnly, _ as when, a as createOrgPermissions, b as fullPublic, c as requireOrgInScope, d as requireOwnership, f as requireRoles, h as requireTeamMembership, i as createDynamicPermissionMatrix, l as requireOrgMembership, m as requireServiceScope, n as allowPublic, o as denyAll, p as requireScopeContext, r as anyOf, s as requireAuth, t as allOf, u as requireOrgRole, v as adminOnly, w as publicReadAdminWrite, x as ownerWithAdminBypass, y as authenticated } from "./permissions-CH4cNwJi.mjs";
|
|
10
|
-
import { t as defineResourceVariants } from "./core-
|
|
11
|
-
import { n as configureArcLogger, t as arcLog } from "./logger-
|
|
10
|
+
import { t as defineResourceVariants } from "./core-F0QoWBt2.mjs";
|
|
11
|
+
import { n as configureArcLogger, t as arcLog } from "./logger-D1YrIImS.mjs";
|
|
12
12
|
//#region src/middleware/middleware.ts
|
|
13
13
|
/**
|
|
14
14
|
* Named Middleware — Priority-based, conditional middleware execution.
|
|
@@ -128,6 +128,6 @@ function transform(name, handlerOrOptions) {
|
|
|
128
128
|
}
|
|
129
129
|
//#endregion
|
|
130
130
|
//#region src/index.ts
|
|
131
|
-
const version = "2.8.
|
|
131
|
+
const version = "2.8.5";
|
|
132
132
|
//#endregion
|
|
133
133
|
export { ArcError, BaseController, CRUD_OPERATIONS, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, ForbiddenError, HOOK_OPERATIONS, HOOK_PHASES, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, MongooseAdapter, NotFoundError, PrismaAdapter, RESERVED_QUERY_PARAMS, ResourceDefinition, SYSTEM_FIELDS, UnauthorizedError, ValidationError, adminOnly, allOf, allowPublic, anyOf, applyFieldReadPermissions, applyFieldWritePermissions, arcLog, assertValidConfig, authenticated, configureArcLogger, createDomainError, createDynamicPermissionMatrix, createMongooseAdapter, createOrgPermissions, createPrismaAdapter, defineResource, defineResourceVariants, denyAll, envelope, fields, formatValidationErrors, fullPublic, getControllerScope, guard, intercept, middleware, ownerWithAdminBypass, presets_exports as permissions, pipe, publicRead, publicReadAdminWrite, readOnly, requestContext, requireAuth, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, sortMiddlewares, transform, validateResourceConfig, version, when };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as DomainEvent } from "../EventTransport-
|
|
1
|
+
import { t as DomainEvent } from "../EventTransport-BXja8NOc.mjs";
|
|
2
2
|
import { WebSocketClient, WebSocketMessage } from "./websocket.mjs";
|
|
3
3
|
import { FastifyPluginAsync, FastifyRequest } from "fastify";
|
|
4
4
|
|
|
@@ -4,7 +4,7 @@ const eventGatewayPluginImpl = async (fastify, opts = {}) => {
|
|
|
4
4
|
const { auth = true, orgScoped = false, roomPolicy, maxMessageBytes, maxSubscriptionsPerClient, authenticate } = opts;
|
|
5
5
|
if (auth && !authenticate && !fastify.hasDecorator("authenticate")) throw new Error("[arc-event-gateway] auth is true but fastify.authenticate is not registered. Register an auth plugin first, provide a custom authenticate function, or set auth: false.");
|
|
6
6
|
if (opts.sse !== false) {
|
|
7
|
-
const { default: ssePlugin } = await import("../sse-
|
|
7
|
+
const { default: ssePlugin } = await import("../sse-Ad7ypl9e.mjs").then((n) => n.r);
|
|
8
8
|
await fastify.register(ssePlugin, {
|
|
9
9
|
path: opts.sse?.path ?? "/events/stream",
|
|
10
10
|
requireAuth: auth,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { WebSocketClient, WebSocketMessage, WebSocketPluginOptions } from "./websocket.mjs";
|
|
2
2
|
import { EventGatewayOptions } from "./event-gateway.mjs";
|
|
3
3
|
import { JobDefinition, JobDispatchOptions, JobDispatcher, JobMeta, JobsPluginOptions, QueueStats } from "./jobs.mjs";
|
|
4
|
-
import { c as McpResourceConfig, 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 } from "../types-
|
|
4
|
+
import { c as McpResourceConfig, 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 } from "../types-BsbNMEDR.mjs";
|
|
5
5
|
import { StreamlinePluginOptions, WorkflowLike, WorkflowRunLike } from "./streamline.mjs";
|
|
6
6
|
import { WebhookDeliveryRecord, WebhookManager, WebhookPluginOptions, WebhookStore, WebhookSubscription } from "./webhooks.mjs";
|
|
7
7
|
export { type BetterAuthHandler, type CallToolResult, type CreateMcpServerConfig, type CrudOperation, type EventGatewayOptions, type JobDefinition, type JobDispatchOptions, type JobDispatcher, type JobMeta, type JobsPluginOptions, type McpAuthResult, type McpPluginOptions, type McpResourceConfig, type PromptDefinition, type QueueStats, type StreamlinePluginOptions, type ToolAnnotations, type ToolContext, type ToolDefinition, type WebSocketClient, type WebSocketMessage, type WebSocketPluginOptions, type WebhookDeliveryRecord, type WebhookManager, type WebhookPluginOptions, type WebhookStore, type WebhookSubscription, type WorkflowLike, type WorkflowRunLike };
|