@rpcbase/server 0.601.0 → 0.602.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/dist/fileReferences-Ca0tivFd.js +101 -0
- package/dist/fileReferences-Ca0tivFd.js.map +1 -0
- package/dist/{handler-Fk-5fOSm.js → handler-BUTqP40B.js} +2 -2
- package/dist/{handler-Fk-5fOSm.js.map → handler-BUTqP40B.js.map} +1 -1
- package/dist/{handler-C92_gJkX.js → handler-BgcIWWMc.js} +2 -2
- package/dist/{handler-C92_gJkX.js.map → handler-BgcIWWMc.js.map} +1 -1
- package/dist/{handler-CapJTGzc.js → handler-CqSlSCdd.js} +215 -57
- package/dist/handler-CqSlSCdd.js.map +1 -0
- package/dist/{handler-BqlcQ9sE.js → handler-LRLmxrsg.js} +69 -24
- package/dist/handler-LRLmxrsg.js.map +1 -0
- package/dist/notifications.js +1 -1
- package/dist/postProcessors-iffHvje4.js.map +1 -1
- package/dist/rts/index.js +1 -1
- package/dist/{schemas-B2fUvgYo.js → schemas-POKnVn0c.js} +58 -2
- package/dist/schemas-POKnVn0c.js.map +1 -0
- package/dist/{shared-DfrVDSp0.js → shared-Zt17vuAT.js} +54 -2
- package/dist/shared-Zt17vuAT.js.map +1 -0
- package/dist/uploads/api/file-uploads/fileReferences.d.ts +42 -0
- package/dist/uploads/api/file-uploads/fileReferences.d.ts.map +1 -0
- package/dist/uploads/api/file-uploads/handlers/completeUpload.d.ts.map +1 -1
- package/dist/uploads/api/file-uploads/handlers/initUpload.d.ts.map +1 -1
- package/dist/uploads/api/file-uploads/imageVariantsPostProcessor.d.ts.map +1 -1
- package/dist/uploads/api/file-uploads/index.d.ts +23 -0
- package/dist/uploads/api/file-uploads/index.d.ts.map +1 -1
- package/dist/uploads/api/file-uploads/postProcessors.d.ts +2 -0
- package/dist/uploads/api/file-uploads/postProcessors.d.ts.map +1 -1
- package/dist/uploads/api/file-uploads/shared.d.ts +21 -0
- package/dist/uploads/api/file-uploads/shared.d.ts.map +1 -1
- package/dist/uploads/api/files/handlers/deleteFile.d.ts.map +1 -1
- package/dist/uploads/api/files/handlers/getFile.d.ts.map +1 -1
- package/dist/uploads/worker.js +3 -2
- package/dist/uploads/worker.js.map +1 -1
- package/dist/uploads.js +2 -2
- package/package.json +1 -1
- package/dist/handler-BqlcQ9sE.js.map +0 -1
- package/dist/handler-CapJTGzc.js.map +0 -1
- package/dist/schemas-B2fUvgYo.js.map +0 -1
- package/dist/shared-DfrVDSp0.js.map +0 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _ as getUserId, h as getUploadKeyHash, m as getTenantId, s as getBucketName, y as resolveStoredUploadAccessScope } from "./shared-Zt17vuAT.js";
|
|
2
|
+
import { i as findUploadFileReference, r as deleteUploadFileReference } from "./fileReferences-Ca0tivFd.js";
|
|
2
3
|
import { GridFSBucket, ObjectId } from "mongodb";
|
|
3
4
|
import { getTenantFilesystemDb } from "@rpcbase/db";
|
|
4
5
|
//#region src/uploads/api/files/handlers/deleteFile.ts
|
|
@@ -45,7 +46,8 @@ var deleteFile = async (_payload, ctx) => {
|
|
|
45
46
|
error: "filesystem_db_unavailable"
|
|
46
47
|
};
|
|
47
48
|
}
|
|
48
|
-
const
|
|
49
|
+
const bucketName = getBucketName();
|
|
50
|
+
const bucket = new GridFSBucket(nativeDb, { bucketName });
|
|
49
51
|
const userId = getUserId(ctx);
|
|
50
52
|
const uploadKeyHash = getUploadKeyHash(ctx);
|
|
51
53
|
if (!userId && !uploadKeyHash) {
|
|
@@ -55,6 +57,35 @@ var deleteFile = async (_payload, ctx) => {
|
|
|
55
57
|
error: "unauthorized"
|
|
56
58
|
};
|
|
57
59
|
}
|
|
60
|
+
const reference = await findUploadFileReference(nativeDb, bucketName, fileObjectId);
|
|
61
|
+
if (reference) {
|
|
62
|
+
const referenceMetadata = reference;
|
|
63
|
+
const metadataUserId = resolveHeaderString$1(reference.userId);
|
|
64
|
+
const ownerKeyHash = resolveHeaderString$1(reference.ownerKeyHash);
|
|
65
|
+
const accessScope = resolveStoredUploadAccessScope(referenceMetadata);
|
|
66
|
+
if (!Boolean(userId && metadataUserId && userId === metadataUserId) && !Boolean(uploadKeyHash && ownerKeyHash && uploadKeyHash === ownerKeyHash) && !(accessScope === "tenant" && Boolean(userId))) {
|
|
67
|
+
ctx.res.status(401);
|
|
68
|
+
return {
|
|
69
|
+
ok: false,
|
|
70
|
+
error: "unauthorized"
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
await deleteUploadFileReference({
|
|
75
|
+
tenantId,
|
|
76
|
+
bucketName,
|
|
77
|
+
referenceId: fileObjectId
|
|
78
|
+
});
|
|
79
|
+
} catch {
|
|
80
|
+
ctx.res.status(500);
|
|
81
|
+
return {
|
|
82
|
+
ok: false,
|
|
83
|
+
error: "delete_failed"
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
ctx.res.status(204);
|
|
87
|
+
return { ok: true };
|
|
88
|
+
}
|
|
58
89
|
const [file] = await bucket.find({ _id: fileObjectId }).limit(1).toArray();
|
|
59
90
|
if (!file) {
|
|
60
91
|
ctx.res.status(204);
|
|
@@ -62,13 +93,23 @@ var deleteFile = async (_payload, ctx) => {
|
|
|
62
93
|
}
|
|
63
94
|
const metadataUserId = resolveHeaderString$1(file?.metadata?.userId);
|
|
64
95
|
const ownerKeyHash = resolveHeaderString$1(file?.metadata?.ownerKeyHash);
|
|
65
|
-
|
|
96
|
+
const rawMetadata = file?.metadata;
|
|
97
|
+
const fileMetadata = rawMetadata && typeof rawMetadata === "object" ? rawMetadata : {};
|
|
98
|
+
const accessScope = resolveStoredUploadAccessScope(fileMetadata);
|
|
99
|
+
if (!Boolean(userId && metadataUserId && userId === metadataUserId) && !Boolean(uploadKeyHash && ownerKeyHash && uploadKeyHash === ownerKeyHash) && !(accessScope === "tenant" && Boolean(userId))) {
|
|
66
100
|
ctx.res.status(401);
|
|
67
101
|
return {
|
|
68
102
|
ok: false,
|
|
69
103
|
error: "unauthorized"
|
|
70
104
|
};
|
|
71
105
|
}
|
|
106
|
+
if (fileMetadata.deduplication && typeof fileMetadata.deduplication === "object") {
|
|
107
|
+
ctx.res.status(409);
|
|
108
|
+
return {
|
|
109
|
+
ok: false,
|
|
110
|
+
error: "file_reference_required"
|
|
111
|
+
};
|
|
112
|
+
}
|
|
72
113
|
try {
|
|
73
114
|
const variantIds = (await bucket.find({ "metadata.variantOf": fileObjectId.toHexString() }).toArray()).map((variant) => variant?._id).filter((id) => id instanceof ObjectId);
|
|
74
115
|
await deleteGridFsFile(bucket, fileObjectId);
|
|
@@ -90,15 +131,6 @@ var resolveHeaderString = (value) => {
|
|
|
90
131
|
const normalized = value.trim();
|
|
91
132
|
return normalized ? normalized : null;
|
|
92
133
|
};
|
|
93
|
-
var resolveHeaderBoolean = (value) => {
|
|
94
|
-
if (typeof value === "boolean") return value;
|
|
95
|
-
if (typeof value !== "string") return null;
|
|
96
|
-
const normalized = value.trim().toLowerCase();
|
|
97
|
-
if (!normalized) return null;
|
|
98
|
-
if (normalized === "true") return true;
|
|
99
|
-
if (normalized === "false") return false;
|
|
100
|
-
return null;
|
|
101
|
-
};
|
|
102
134
|
var escapeHeaderFilename = (filename) => filename.replace(/[\\"]/g, "_");
|
|
103
135
|
var parseRequestedWidth = (value) => {
|
|
104
136
|
if (typeof value !== "string") return null;
|
|
@@ -168,28 +200,41 @@ var getFile = async (_payload, ctx) => {
|
|
|
168
200
|
ctx.res.status(500).end();
|
|
169
201
|
return {};
|
|
170
202
|
}
|
|
171
|
-
const
|
|
172
|
-
const
|
|
203
|
+
const bucketName = getBucketName();
|
|
204
|
+
const bucket = new GridFSBucket(nativeDb, { bucketName });
|
|
205
|
+
const reference = await findUploadFileReference(nativeDb, bucketName, fileObjectId);
|
|
206
|
+
const blobObjectId = reference?.blobId ?? fileObjectId;
|
|
207
|
+
const [file] = await bucket.find({ _id: blobObjectId }).limit(1).toArray();
|
|
173
208
|
if (!file) {
|
|
174
209
|
ctx.res.status(404).end();
|
|
175
210
|
return {};
|
|
176
211
|
}
|
|
177
|
-
|
|
212
|
+
const rawMetadata = reference ?? file?.metadata;
|
|
213
|
+
const fileMetadata = rawMetadata && typeof rawMetadata === "object" ? rawMetadata : {};
|
|
214
|
+
const accessScope = resolveStoredUploadAccessScope(fileMetadata);
|
|
215
|
+
if (accessScope !== "public") {
|
|
178
216
|
const userId = getUserId(ctx);
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
217
|
+
if (accessScope === "tenant") {
|
|
218
|
+
if (!userId) {
|
|
219
|
+
ctx.res.status(401).end();
|
|
220
|
+
return {};
|
|
221
|
+
}
|
|
222
|
+
} else {
|
|
223
|
+
const uploadKeyHash = getUploadKeyHash(ctx);
|
|
224
|
+
const metadataUserId = resolveHeaderString(fileMetadata.userId);
|
|
225
|
+
const ownerKeyHash = resolveHeaderString(fileMetadata.ownerKeyHash);
|
|
226
|
+
if (!Boolean(userId && metadataUserId && userId === metadataUserId) && !Boolean(uploadKeyHash && ownerKeyHash && uploadKeyHash === ownerKeyHash)) {
|
|
227
|
+
ctx.res.status(401).end();
|
|
228
|
+
return {};
|
|
229
|
+
}
|
|
185
230
|
}
|
|
186
231
|
}
|
|
187
232
|
const variantFileObjectId = selectVariantFileId(file, parseRequestedWidth(ctx.req.query?.w), ctx.req.query?.variant);
|
|
188
233
|
const [variantFile] = variantFileObjectId ? await bucket.find({ _id: variantFileObjectId }).limit(1).toArray() : [];
|
|
189
|
-
const selectedFileObjectId = variantFile ? variantFileObjectId :
|
|
234
|
+
const selectedFileObjectId = variantFile ? variantFileObjectId : blobObjectId;
|
|
190
235
|
const selectedFile = variantFile ?? file;
|
|
191
236
|
const mimeType = resolveHeaderString(selectedFile?.metadata?.mimeType) ?? "application/octet-stream";
|
|
192
|
-
const filenameSafe = escapeHeaderFilename(resolveHeaderString(selectedFile?.filename) ?? fileIdRaw);
|
|
237
|
+
const filenameSafe = escapeHeaderFilename(resolveHeaderString(reference?.filename ?? selectedFile?.filename) ?? fileIdRaw);
|
|
193
238
|
const cacheControl = "private, max-age=0, must-revalidate";
|
|
194
239
|
const md5 = resolveHeaderString(selectedFile?.md5);
|
|
195
240
|
const uploadDate = selectedFile?.uploadDate instanceof Date ? selectedFile.uploadDate : null;
|
|
@@ -242,4 +287,4 @@ var handler_default = (api) => {
|
|
|
242
287
|
//#endregion
|
|
243
288
|
export { handler_default as default };
|
|
244
289
|
|
|
245
|
-
//# sourceMappingURL=handler-
|
|
290
|
+
//# sourceMappingURL=handler-LRLmxrsg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler-LRLmxrsg.js","names":["ApiHandler","getTenantFilesystemDb","GridFSBucket","ObjectId","deleteUploadFileReference","findUploadFileReference","getBucketName","getTenantId","getUploadKeyHash","getUserId","resolveStoredUploadAccessScope","SessionUser","DeleteResponsePayload","ok","error","resolveHeaderString","value","normalized","trim","isFileNotFoundError","message","Error","String","includes","deleteGridFsFile","bucket","fileId","Promise","delete","deleteFile","Record","_payload","ctx","tenantId","res","status","fileIdRaw","req","params","fileObjectId","fsDb","nativeDb","db","bucketName","userId","uploadKeyHash","reference","referenceMetadata","metadataUserId","ownerKeyHash","accessScope","authorizedByUser","Boolean","authorizedByKey","authorizedByTenant","referenceId","file","find","_id","limit","toArray","metadata","rawMetadata","fileMetadata","deduplication","variants","toHexString","variantIds","map","variant","filter","id","variantId","ApiHandler","getTenantFilesystemDb","GridFSBucket","ObjectId","findUploadFileReference","getBucketName","getTenantId","getUploadKeyHash","getUserId","resolveStoredUploadAccessScope","SessionUser","resolveHeaderString","value","normalized","trim","escapeHeaderFilename","filename","replace","parseRequestedWidth","parsed","Number","isFinite","Math","floor","resolveImageVariants","file","Record","metadata","image","variants","resolveVariantFileId","variant","fileId","selectVariantFileId","requestedWidth","requestedVariant","aliasWidth","toLowerCase","variantFileId","String","targetWidth","widths","Object","keys","map","width","filter","isInteger","sort","a","b","selectedWidth","reduce","selected","selectedDistance","abs","distance","getFile","_payload","ctx","Promise","tenantId","res","status","end","fileIdRaw","req","params","fileObjectId","fsDb","nativeDb","db","bucketName","bucket","reference","blobObjectId","blobId","find","_id","limit","toArray","rawMetadata","fileMetadata","accessScope","userId","uploadKeyHash","metadataUserId","ownerKeyHash","authorizedByUser","Boolean","authorizedByKey","query","w","variantFileObjectId","variantFile","selectedFileObjectId","selectedFile","mimeTypeFromMetadata","mimeType","filenameFromDb","filenameSafe","cacheControl","md5","uploadDate","Date","etagValue","toHexString","length","getTime","etag","ifNoneMatch","headers","candidates","split","includes","setHeader","flushHeaders","method","stream","openDownloadStream","on","destroy","pipe","Route","GetRoute","DeleteRoute"],"sources":["../src/uploads/api/files/handlers/deleteFile.ts","../src/uploads/api/files/handlers/getFile.ts","../src/uploads/api/files/index.ts","../src/uploads/api/files/handler.ts"],"sourcesContent":["import { ApiHandler } from \"@rpcbase/api\"\nimport { getTenantFilesystemDb } from \"@rpcbase/db\"\nimport { GridFSBucket, ObjectId } from \"mongodb\"\n\nimport {\n deleteUploadFileReference,\n findUploadFileReference,\n} from \"../../file-uploads/fileReferences\"\nimport {\n getBucketName,\n getTenantId,\n getUploadKeyHash,\n getUserId,\n resolveStoredUploadAccessScope,\n type SessionUser,\n} from \"../../file-uploads/shared\"\n\n\ntype DeleteResponsePayload = {\n ok: boolean\n error?: string\n}\n\nconst resolveHeaderString = (value: unknown): string | null => {\n if (typeof value !== \"string\") return null\n const normalized = value.trim()\n return normalized ? normalized : null\n}\n\nconst isFileNotFoundError = (error: unknown): boolean => {\n const message = error instanceof Error ? error.message : String(error)\n return message.includes(\"FileNotFound\")\n}\n\nconst deleteGridFsFile = async (bucket: GridFSBucket, fileId: ObjectId): Promise<void> => {\n try {\n await bucket.delete(fileId)\n } catch (error) {\n if (!isFileNotFoundError(error)) throw error\n }\n}\n\nexport const deleteFile: ApiHandler<Record<string, never>, DeleteResponsePayload, SessionUser> = async (\n _payload,\n ctx,\n): Promise<DeleteResponsePayload> => {\n const tenantId = getTenantId(ctx)\n if (!tenantId) {\n ctx.res.status(400)\n return { ok: false, error: \"tenant_missing\" }\n }\n\n const fileIdRaw = String(ctx.req.params?.fileId ?? \"\").trim()\n let fileObjectId: ObjectId\n try {\n fileObjectId = new ObjectId(fileIdRaw)\n } catch {\n ctx.res.status(400)\n return { ok: false, error: \"invalid_file_id\" }\n }\n\n const fsDb = await getTenantFilesystemDb(tenantId)\n const nativeDb = fsDb.db\n if (!nativeDb) {\n ctx.res.status(500)\n return { ok: false, error: \"filesystem_db_unavailable\" }\n }\n\n const bucketName = getBucketName()\n const bucket = new GridFSBucket(nativeDb, { bucketName })\n\n const userId = getUserId(ctx)\n const uploadKeyHash = getUploadKeyHash(ctx)\n if (!userId && !uploadKeyHash) {\n ctx.res.status(401)\n return { ok: false, error: \"unauthorized\" }\n }\n\n const reference = await findUploadFileReference(nativeDb, bucketName, fileObjectId)\n if (reference) {\n const referenceMetadata = reference as unknown as Record<string, unknown>\n const metadataUserId = resolveHeaderString(reference.userId)\n const ownerKeyHash = resolveHeaderString(reference.ownerKeyHash)\n const accessScope = resolveStoredUploadAccessScope(referenceMetadata)\n\n const authorizedByUser = Boolean(userId && metadataUserId && userId === metadataUserId)\n const authorizedByKey = Boolean(uploadKeyHash && ownerKeyHash && uploadKeyHash === ownerKeyHash)\n const authorizedByTenant = accessScope === \"tenant\" && Boolean(userId)\n\n if (!authorizedByUser && !authorizedByKey && !authorizedByTenant) {\n ctx.res.status(401)\n return { ok: false, error: \"unauthorized\" }\n }\n\n try {\n await deleteUploadFileReference({\n tenantId,\n bucketName,\n referenceId: fileObjectId,\n })\n } catch {\n ctx.res.status(500)\n return { ok: false, error: \"delete_failed\" }\n }\n\n ctx.res.status(204)\n return { ok: true }\n }\n\n const [file] = await bucket.find({ _id: fileObjectId }).limit(1).toArray()\n if (!file) {\n ctx.res.status(204)\n return { ok: true }\n }\n\n const metadataUserId = resolveHeaderString((file as any)?.metadata?.userId)\n const ownerKeyHash = resolveHeaderString((file as any)?.metadata?.ownerKeyHash)\n const rawMetadata = (file as any)?.metadata\n const fileMetadata = rawMetadata && typeof rawMetadata === \"object\"\n ? rawMetadata as Record<string, unknown>\n : {}\n const accessScope = resolveStoredUploadAccessScope(fileMetadata)\n\n const authorizedByUser = Boolean(userId && metadataUserId && userId === metadataUserId)\n const authorizedByKey = Boolean(uploadKeyHash && ownerKeyHash && uploadKeyHash === ownerKeyHash)\n const authorizedByTenant = accessScope === \"tenant\" && Boolean(userId)\n\n if (!authorizedByUser && !authorizedByKey && !authorizedByTenant) {\n ctx.res.status(401)\n return { ok: false, error: \"unauthorized\" }\n }\n\n if (fileMetadata.deduplication && typeof fileMetadata.deduplication === \"object\") {\n ctx.res.status(409)\n return { ok: false, error: \"file_reference_required\" }\n }\n\n try {\n const variants = await bucket.find({ \"metadata.variantOf\": fileObjectId.toHexString() }).toArray()\n const variantIds = variants\n .map((variant) => (variant as any)?._id)\n .filter((id): id is ObjectId => id instanceof ObjectId)\n\n await deleteGridFsFile(bucket, fileObjectId)\n for (const variantId of variantIds) {\n await deleteGridFsFile(bucket, variantId)\n }\n } catch {\n ctx.res.status(500)\n return { ok: false, error: \"delete_failed\" }\n }\n\n ctx.res.status(204)\n return { ok: true }\n}\n","import { ApiHandler } from \"@rpcbase/api\"\nimport { getTenantFilesystemDb } from \"@rpcbase/db\"\nimport { GridFSBucket, ObjectId } from \"mongodb\"\n\nimport { findUploadFileReference } from \"../../file-uploads/fileReferences\"\nimport {\n getBucketName,\n getTenantId,\n getUploadKeyHash,\n getUserId,\n resolveStoredUploadAccessScope,\n type SessionUser,\n} from \"../../file-uploads/shared\"\n\n\nconst resolveHeaderString = (value: unknown): string | null => {\n if (typeof value !== \"string\") return null\n const normalized = value.trim()\n return normalized ? normalized : null\n}\n\nconst escapeHeaderFilename = (filename: string): string => filename.replace(/[\\\\\"]/g, \"_\")\n\nconst parseRequestedWidth = (value: unknown): number | null => {\n if (typeof value !== \"string\") return null\n const parsed = Number(value.trim())\n if (!Number.isFinite(parsed) || parsed <= 0) return null\n return Math.floor(parsed)\n}\n\nconst resolveImageVariants = (file: unknown): Record<string, unknown> | null => {\n const metadata = (file as any)?.metadata\n if (!metadata || typeof metadata !== \"object\") return null\n const image = (metadata as Record<string, unknown>).image\n if (!image || typeof image !== \"object\") return null\n const variants = (image as Record<string, unknown>).variants\n if (!variants || typeof variants !== \"object\") return null\n return variants as Record<string, unknown>\n}\n\nconst resolveVariantFileId = (variant: unknown): ObjectId | null => {\n if (!variant || typeof variant !== \"object\") return null\n const fileId = (variant as Record<string, unknown>).fileId\n if (typeof fileId !== \"string\") return null\n try {\n return new ObjectId(fileId)\n } catch {\n return null\n }\n}\n\nconst selectVariantFileId = (file: unknown, requestedWidth: number | null, requestedVariant: unknown): ObjectId | null => {\n const variants = resolveImageVariants(file)\n if (!variants) return null\n\n let aliasWidth: number | null = null\n if (typeof requestedVariant === \"string\") {\n const normalized = requestedVariant.trim().toLowerCase()\n aliasWidth = normalized === \"thumb\" ? 320 : normalized === \"small\" ? 640 : normalized === \"medium\" ? 960 : normalized === \"large\" ? 1600 : null\n if (aliasWidth) {\n const variantFileId = resolveVariantFileId(variants[String(aliasWidth)])\n if (variantFileId) return variantFileId\n }\n }\n\n const targetWidth = aliasWidth ?? requestedWidth\n if (!targetWidth) return null\n\n const widths = Object.keys(variants)\n .map((width) => Number(width))\n .filter((width) => Number.isInteger(width) && width > 0)\n .sort((a, b) => a - b)\n\n const selectedWidth = widths.reduce<number | null>((selected, width) => {\n if (selected === null) return width\n\n const selectedDistance = Math.abs(selected - targetWidth)\n const distance = Math.abs(width - targetWidth)\n if (distance < selectedDistance) return width\n if (distance === selectedDistance && width > selected) return width\n return selected\n }, null)\n return selectedWidth ? resolveVariantFileId(variants[String(selectedWidth)]) : null\n}\n\nexport const getFile: ApiHandler<Record<string, never>, Record<string, never>, SessionUser> = async (\n _payload,\n ctx,\n): Promise<Record<string, never>> => {\n const tenantId = getTenantId(ctx)\n if (!tenantId) {\n ctx.res.status(400).end()\n return {}\n }\n\n const fileIdRaw = String(ctx.req.params?.fileId ?? \"\").trim()\n let fileObjectId: ObjectId\n try {\n fileObjectId = new ObjectId(fileIdRaw)\n } catch {\n ctx.res.status(400).end()\n return {}\n }\n\n const fsDb = await getTenantFilesystemDb(tenantId)\n const nativeDb = fsDb.db\n if (!nativeDb) {\n ctx.res.status(500).end()\n return {}\n }\n\n const bucketName = getBucketName()\n const bucket = new GridFSBucket(nativeDb, { bucketName })\n const reference = await findUploadFileReference(nativeDb, bucketName, fileObjectId)\n const blobObjectId = reference?.blobId ?? fileObjectId\n\n const [file] = await bucket.find({ _id: blobObjectId }).limit(1).toArray()\n if (!file) {\n ctx.res.status(404).end()\n return {}\n }\n\n const rawMetadata = reference ?? (file as any)?.metadata\n const fileMetadata = rawMetadata && typeof rawMetadata === \"object\"\n ? rawMetadata as Record<string, unknown>\n : {}\n const accessScope = resolveStoredUploadAccessScope(fileMetadata)\n if (accessScope !== \"public\") {\n const userId = getUserId(ctx)\n if (accessScope === \"tenant\") {\n if (!userId) {\n ctx.res.status(401).end()\n return {}\n }\n } else {\n const uploadKeyHash = getUploadKeyHash(ctx)\n const metadataUserId = resolveHeaderString(fileMetadata.userId)\n const ownerKeyHash = resolveHeaderString(fileMetadata.ownerKeyHash)\n\n const authorizedByUser = Boolean(userId && metadataUserId && userId === metadataUserId)\n const authorizedByKey = Boolean(uploadKeyHash && ownerKeyHash && uploadKeyHash === ownerKeyHash)\n\n if (!authorizedByUser && !authorizedByKey) {\n ctx.res.status(401).end()\n return {}\n }\n }\n }\n\n const requestedWidth = parseRequestedWidth((ctx.req.query as any)?.w)\n const variantFileObjectId = selectVariantFileId(file, requestedWidth, (ctx.req.query as any)?.variant)\n const [variantFile] = variantFileObjectId\n ? await bucket.find({ _id: variantFileObjectId }).limit(1).toArray()\n : []\n const selectedFileObjectId = variantFile ? variantFileObjectId as ObjectId : blobObjectId\n const selectedFile = variantFile ?? file\n\n const mimeTypeFromMetadata = resolveHeaderString((selectedFile as any)?.metadata?.mimeType)\n const mimeType = mimeTypeFromMetadata ?? \"application/octet-stream\"\n const filenameFromDb = resolveHeaderString(reference?.filename ?? (selectedFile as any)?.filename)\n const filename = filenameFromDb ?? fileIdRaw\n const filenameSafe = escapeHeaderFilename(filename)\n\n const cacheControl = \"private, max-age=0, must-revalidate\"\n const md5 = resolveHeaderString((selectedFile as any)?.md5)\n const uploadDate = (selectedFile as any)?.uploadDate instanceof Date ? (selectedFile as any).uploadDate : null\n const etagValue = md5 ?? `${selectedFileObjectId.toHexString()}-${String((selectedFile as any)?.length ?? 0)}-${String(uploadDate?.getTime() ?? 0)}`\n const etag = md5 ? `\"${etagValue}\"` : `W/\"${etagValue}\"`\n const ifNoneMatch = resolveHeaderString((ctx.req.headers as any)?.[\"if-none-match\"])\n if (ifNoneMatch) {\n const candidates = ifNoneMatch.split(\",\").map((value) => value.trim()).filter(Boolean)\n if (candidates.includes(\"*\") || candidates.includes(etag)) {\n ctx.res.status(304)\n ctx.res.setHeader(\"Cache-Control\", cacheControl)\n ctx.res.setHeader(\"ETag\", etag)\n ctx.res.end()\n return {}\n }\n }\n\n ctx.res.status(200)\n ctx.res.setHeader(\"Content-Type\", mimeType)\n ctx.res.setHeader(\"Content-Length\", String((selectedFile as any)?.length ?? 0))\n ctx.res.setHeader(\"Content-Disposition\", `inline; filename=\"${filenameSafe}\"`)\n ctx.res.setHeader(\"Cache-Control\", cacheControl)\n ctx.res.setHeader(\"ETag\", etag)\n ctx.res.setHeader(\"X-Content-Type-Options\", \"nosniff\")\n if (mimeType === \"image/svg+xml\") {\n ctx.res.setHeader(\n \"Content-Security-Policy\",\n \"default-src 'none'; style-src 'unsafe-inline'; sandbox; base-uri 'none'; form-action 'none'\",\n )\n }\n ctx.res.flushHeaders()\n\n if (ctx.req.method === \"HEAD\") {\n ctx.res.end()\n return {}\n }\n\n const stream = bucket.openDownloadStream(selectedFileObjectId)\n\n stream.on(\"error\", () => {\n try {\n ctx.res.destroy()\n } catch {\n //\n }\n })\n\n stream.pipe(ctx.res)\n return {}\n}\n","export const Route = \"/api/rb/files/:fileId\"\n\nexport const GetRoute = Route\nexport const DeleteRoute = Route\n","import { Api } from \"@rpcbase/api\"\n\nimport { deleteFile } from \"./handlers/deleteFile\"\nimport { getFile } from \"./handlers/getFile\"\n\nimport * as Files from \"./index\"\n\n\nexport default (api: Api) => {\n api.get(Files.GetRoute, getFile)\n api.delete(Files.DeleteRoute, deleteFile)\n}\n"],"mappings":"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"}
|
package/dist/notifications.js
CHANGED
|
@@ -2,7 +2,7 @@ import { i as sendEmail } from "./email-CK8NNDQY.js";
|
|
|
2
2
|
import { models } from "@rpcbase/db";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
4
|
//#region src/notifications/routes.ts
|
|
5
|
-
var routes = Object.entries({ .../* #__PURE__ */ Object.assign({ "./api/notifications/handler.ts": () => import("./handler-
|
|
5
|
+
var routes = Object.entries({ .../* #__PURE__ */ Object.assign({ "./api/notifications/handler.ts": () => import("./handler-BgcIWWMc.js") }) }).reduce((acc, [path, mod]) => {
|
|
6
6
|
acc[path.replace("./api/", "@rpcbase/server/notifications/api/")] = mod;
|
|
7
7
|
return acc;
|
|
8
8
|
}, {});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postProcessors-iffHvje4.js","names":["queue","UploadPostProcessorContext","tenantId","uploadId","fileId","filename","mimeType","clientMimeType","totalSize","isPublic","userId","ownerKeyHash","inlineProcessors","metadata","Record","UploadPostProcessor","id","version","match","ctx","process","Promise","processorsById","Object","create","uploadPostProcessorTaskName","normalizeProcessorId","value","trim","normalizeProcessorVersion","undefined","Number","isInteger","registerUploadPostProcessor","processor","normalizedId","Error","normalizedVersion","registerUploadProcessor","unregisterUploadPostProcessor","unregisterUploadProcessor","clearUploadPostProcessors","keys","clearUploadProcessors","getUploadPostProcessors","values","getUploadProcessors","runUploadPostProcessors","processors","length","error","console","processorId","processorVersion","stage","isUploadPostProcessorTaskRegistered","registerUploadPostProcessorTask","registerTask","payload","enqueueUploadPostProcessors","add","attempts","backoff","type","delay","removeOnComplete","removeOnFail"],"sources":["../src/uploads/api/file-uploads/postProcessors.ts"],"sourcesContent":["import { queue } from \"@rpcbase/worker\"\n\n\nexport type UploadPostProcessorContext = {\n tenantId: string\n uploadId: string\n fileId: string\n filename: string\n mimeType: string\n clientMimeType: string\n totalSize: number\n isPublic?: boolean\n userId?: string\n ownerKeyHash?: string\n inlineProcessors: string[]\n metadata: Record<string, unknown>\n}\n\nexport type UploadPostProcessor = {\n id: string\n version?: number\n match?: (ctx: UploadPostProcessorContext) => boolean\n process: (ctx: UploadPostProcessorContext) => Promise<unknown> | unknown\n}\n\nconst processorsById: Record<string, UploadPostProcessor> = Object.create(null)\nexport const uploadPostProcessorTaskName = \"rb-upload-post-processors\"\n\nconst normalizeProcessorId = (value: unknown): string => (typeof value === \"string\" ? value.trim() : \"\")\n\nconst normalizeProcessorVersion = (value: unknown): number | undefined => {\n if (typeof value !== \"number\") return undefined\n if (!Number.isInteger(value) || value < 1) return undefined\n return value\n}\n\nexport const registerUploadPostProcessor = (processor: UploadPostProcessor): void => {\n const normalizedId = normalizeProcessorId(processor.id)\n if (!normalizedId) {\n throw new Error(\"Upload post processor id is required.\")\n }\n\n const normalizedVersion = normalizeProcessorVersion(processor.version)\n\n processorsById[normalizedId] = {\n ...processor,\n id: normalizedId,\n ...(normalizedVersion ? { version: normalizedVersion } : {}),\n }\n}\n\nexport const registerUploadProcessor = registerUploadPostProcessor\n\nexport const unregisterUploadPostProcessor = (id: string): void => {\n const normalizedId = normalizeProcessorId(id)\n if (!normalizedId) return\n delete processorsById[normalizedId]\n}\n\nexport const unregisterUploadProcessor = unregisterUploadPostProcessor\n\nexport const clearUploadPostProcessors = (): void => {\n for (const id of Object.keys(processorsById)) {\n delete processorsById[id]\n }\n}\n\nexport const clearUploadProcessors = clearUploadPostProcessors\n\nexport const getUploadPostProcessors = (): UploadPostProcessor[] => Object.values(processorsById)\n\nexport const getUploadProcessors = getUploadPostProcessors\n\nexport const runUploadPostProcessors = async (ctx: UploadPostProcessorContext): Promise<void> => {\n const processors = getUploadPostProcessors()\n if (!processors.length) return\n\n for (const processor of processors) {\n if (processor.match) {\n try {\n if (!processor.match(ctx)) continue\n } catch (error) {\n console.error(\"Upload post processor failed\", {\n processorId: processor.id,\n processorVersion: processor.version,\n tenantId: ctx.tenantId,\n uploadId: ctx.uploadId,\n fileId: ctx.fileId,\n stage: \"match\",\n error,\n })\n continue\n }\n }\n\n try {\n await processor.process(ctx)\n } catch (error) {\n console.error(\"Upload post processor failed\", {\n processorId: processor.id,\n processorVersion: processor.version,\n tenantId: ctx.tenantId,\n uploadId: ctx.uploadId,\n fileId: ctx.fileId,\n stage: \"process\",\n error,\n })\n }\n }\n}\n\nlet isUploadPostProcessorTaskRegistered = false\n\nexport const registerUploadPostProcessorTask = (): void => {\n if (isUploadPostProcessorTaskRegistered) return\n\n queue.registerTask(uploadPostProcessorTaskName, async (payload) => {\n await runUploadPostProcessors(payload as UploadPostProcessorContext)\n })\n isUploadPostProcessorTaskRegistered = true\n}\n\nexport const enqueueUploadPostProcessors = async (ctx: UploadPostProcessorContext): Promise<void> => {\n await queue.add(uploadPostProcessorTaskName, ctx, {\n attempts: 3,\n backoff: { type: \"exponential\", delay: 5_000 },\n removeOnComplete: true,\n removeOnFail: false,\n })\n}\n"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"postProcessors-iffHvje4.js","names":["queue","UploadAccessScope","UploadPostProcessorContext","tenantId","uploadId","fileId","filename","mimeType","clientMimeType","totalSize","isPublic","accessScope","userId","ownerKeyHash","inlineProcessors","metadata","Record","UploadPostProcessor","id","version","match","ctx","process","Promise","processorsById","Object","create","uploadPostProcessorTaskName","normalizeProcessorId","value","trim","normalizeProcessorVersion","undefined","Number","isInteger","registerUploadPostProcessor","processor","normalizedId","Error","normalizedVersion","registerUploadProcessor","unregisterUploadPostProcessor","unregisterUploadProcessor","clearUploadPostProcessors","keys","clearUploadProcessors","getUploadPostProcessors","values","getUploadProcessors","runUploadPostProcessors","processors","length","error","console","processorId","processorVersion","stage","isUploadPostProcessorTaskRegistered","registerUploadPostProcessorTask","registerTask","payload","enqueueUploadPostProcessors","add","attempts","backoff","type","delay","removeOnComplete","removeOnFail"],"sources":["../src/uploads/api/file-uploads/postProcessors.ts"],"sourcesContent":["import { queue } from \"@rpcbase/worker\"\n\nimport type { UploadAccessScope } from \"./shared\"\n\n\nexport type UploadPostProcessorContext = {\n tenantId: string\n uploadId: string\n fileId: string\n filename: string\n mimeType: string\n clientMimeType: string\n totalSize: number\n isPublic?: boolean\n accessScope?: UploadAccessScope\n userId?: string\n ownerKeyHash?: string\n inlineProcessors: string[]\n metadata: Record<string, unknown>\n}\n\nexport type UploadPostProcessor = {\n id: string\n version?: number\n match?: (ctx: UploadPostProcessorContext) => boolean\n process: (ctx: UploadPostProcessorContext) => Promise<unknown> | unknown\n}\n\nconst processorsById: Record<string, UploadPostProcessor> = Object.create(null)\nexport const uploadPostProcessorTaskName = \"rb-upload-post-processors\"\n\nconst normalizeProcessorId = (value: unknown): string => (typeof value === \"string\" ? value.trim() : \"\")\n\nconst normalizeProcessorVersion = (value: unknown): number | undefined => {\n if (typeof value !== \"number\") return undefined\n if (!Number.isInteger(value) || value < 1) return undefined\n return value\n}\n\nexport const registerUploadPostProcessor = (processor: UploadPostProcessor): void => {\n const normalizedId = normalizeProcessorId(processor.id)\n if (!normalizedId) {\n throw new Error(\"Upload post processor id is required.\")\n }\n\n const normalizedVersion = normalizeProcessorVersion(processor.version)\n\n processorsById[normalizedId] = {\n ...processor,\n id: normalizedId,\n ...(normalizedVersion ? { version: normalizedVersion } : {}),\n }\n}\n\nexport const registerUploadProcessor = registerUploadPostProcessor\n\nexport const unregisterUploadPostProcessor = (id: string): void => {\n const normalizedId = normalizeProcessorId(id)\n if (!normalizedId) return\n delete processorsById[normalizedId]\n}\n\nexport const unregisterUploadProcessor = unregisterUploadPostProcessor\n\nexport const clearUploadPostProcessors = (): void => {\n for (const id of Object.keys(processorsById)) {\n delete processorsById[id]\n }\n}\n\nexport const clearUploadProcessors = clearUploadPostProcessors\n\nexport const getUploadPostProcessors = (): UploadPostProcessor[] => Object.values(processorsById)\n\nexport const getUploadProcessors = getUploadPostProcessors\n\nexport const runUploadPostProcessors = async (ctx: UploadPostProcessorContext): Promise<void> => {\n const processors = getUploadPostProcessors()\n if (!processors.length) return\n\n for (const processor of processors) {\n if (processor.match) {\n try {\n if (!processor.match(ctx)) continue\n } catch (error) {\n console.error(\"Upload post processor failed\", {\n processorId: processor.id,\n processorVersion: processor.version,\n tenantId: ctx.tenantId,\n uploadId: ctx.uploadId,\n fileId: ctx.fileId,\n stage: \"match\",\n error,\n })\n continue\n }\n }\n\n try {\n await processor.process(ctx)\n } catch (error) {\n console.error(\"Upload post processor failed\", {\n processorId: processor.id,\n processorVersion: processor.version,\n tenantId: ctx.tenantId,\n uploadId: ctx.uploadId,\n fileId: ctx.fileId,\n stage: \"process\",\n error,\n })\n }\n }\n}\n\nlet isUploadPostProcessorTaskRegistered = false\n\nexport const registerUploadPostProcessorTask = (): void => {\n if (isUploadPostProcessorTaskRegistered) return\n\n queue.registerTask(uploadPostProcessorTaskName, async (payload) => {\n await runUploadPostProcessors(payload as UploadPostProcessorContext)\n })\n isUploadPostProcessorTaskRegistered = true\n}\n\nexport const enqueueUploadPostProcessors = async (ctx: UploadPostProcessorContext): Promise<void> => {\n await queue.add(uploadPostProcessorTaskName, ctx, {\n attempts: 3,\n backoff: { type: \"exponential\", delay: 5_000 },\n removeOnComplete: true,\n removeOnFail: false,\n })\n}\n"],"mappings":";;AA4BA,IAAMwB,iBAAsDC,OAAOC,OAAO,IAAI;AAC9E,IAAaC,8BAA8B;AAE3C,IAAMC,wBAAwBC,UAA4B,OAAOA,UAAU,WAAWA,MAAMC,KAAK,IAAI;AAErG,IAAMC,6BAA6BF,UAAuC;CACxE,IAAI,OAAOA,UAAU,UAAU,OAAOG,KAAAA;CACtC,IAAI,CAACC,OAAOC,UAAUL,KAAK,KAAKA,QAAQ,GAAG,OAAOG,KAAAA;CAClD,OAAOH;AACT;AAEA,IAAaM,+BAA+BC,cAAyC;CACnF,MAAMC,eAAeT,qBAAqBQ,UAAUlB,EAAE;CACtD,IAAI,CAACmB,cACH,MAAM,IAAIC,MAAM,uCAAuC;CAGzD,MAAMC,oBAAoBR,0BAA0BK,UAAUjB,OAAO;CAErEK,eAAea,gBAAgB;EAC7B,GAAGD;EACHlB,IAAImB;EACJ,GAAIE,oBAAoB,EAAEpB,SAASoB,kBAAkB,IAAI,CAAC;CAC5D;AACF;AAEA,IAAaC,0BAA0BL;AAEvC,IAAaM,iCAAiCvB,OAAqB;CACjE,MAAMmB,eAAeT,qBAAqBV,EAAE;CAC5C,IAAI,CAACmB,cAAc;CACnB,OAAOb,eAAea;AACxB;AAEA,IAAaK,4BAA4BD;AAEzC,IAAaE,kCAAwC;CACnD,KAAK,MAAMzB,MAAMO,OAAOmB,KAAKpB,cAAc,GACzC,OAAOA,eAAeN;AAE1B;AAEA,IAAa2B,wBAAwBF;AAErC,IAAaG,gCAAuDrB,OAAOsB,OAAOvB,cAAc;AAEhG,IAAawB,sBAAsBF;AAEnC,IAAaG,0BAA0B,OAAO5B,QAAmD;CAC/F,MAAM6B,aAAaJ,wBAAwB;CAC3C,IAAI,CAACI,WAAWC,QAAQ;CAExB,KAAK,MAAMf,aAAac,YAAY;EAClC,IAAId,UAAUhB,OACZ,IAAI;GACF,IAAI,CAACgB,UAAUhB,MAAMC,GAAG,GAAG;EAC7B,SAAS+B,OAAO;GACdC,QAAQD,MAAM,gCAAgC;IAC5CE,aAAalB,UAAUlB;IACvBqC,kBAAkBnB,UAAUjB;IAC5BhB,UAAUkB,IAAIlB;IACdC,UAAUiB,IAAIjB;IACdC,QAAQgB,IAAIhB;IACZmD,OAAO;IACPJ;GACF,CAAC;GACD;EACF;EAGF,IAAI;GACF,MAAMhB,UAAUd,QAAQD,GAAG;EAC7B,SAAS+B,OAAO;GACdC,QAAQD,MAAM,gCAAgC;IAC5CE,aAAalB,UAAUlB;IACvBqC,kBAAkBnB,UAAUjB;IAC5BhB,UAAUkB,IAAIlB;IACdC,UAAUiB,IAAIjB;IACdC,QAAQgB,IAAIhB;IACZmD,OAAO;IACPJ;GACF,CAAC;EACH;CACF;AACF;AAEA,IAAIK,sCAAsC;AAE1C,IAAaC,wCAA8C;CACzD,IAAID,qCAAqC;CAEzCzD,MAAM2D,aAAahC,6BAA6B,OAAOiC,YAAY;EACjE,MAAMX,wBAAwBW,OAAqC;CACrE,CAAC;CACDH,sCAAsC;AACxC;AAEA,IAAaI,8BAA8B,OAAOxC,QAAmD;CACnG,MAAMrB,MAAM8D,IAAInC,6BAA6BN,KAAK;EAChD0C,UAAU;EACVC,SAAS;GAAEC,MAAM;GAAeC,OAAO;EAAM;EAC7CC,kBAAkB;EAClBC,cAAc;CAChB,CAAC;AACH"}
|
package/dist/rts/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { randomUUID } from "node:crypto";
|
|
|
4
4
|
import { buildAbilityFromSession } from "@rpcbase/db/acl";
|
|
5
5
|
import { WebSocketServer } from "ws";
|
|
6
6
|
//#region src/rts/routes.ts
|
|
7
|
-
var routes = Object.entries({ .../* #__PURE__ */ Object.assign({ "./api/changes/handler.ts": () => import("../handler-
|
|
7
|
+
var routes = Object.entries({ .../* #__PURE__ */ Object.assign({ "./api/changes/handler.ts": () => import("../handler-BUTqP40B.js") }) }).reduce((acc, [path, mod]) => {
|
|
8
8
|
acc[path.replace("./api/", "@rpcbase/server/rts/api/")] = mod;
|
|
9
9
|
return acc;
|
|
10
10
|
}, {});
|
|
@@ -1989,6 +1989,24 @@ var $ZodEnum = /*@__PURE__*/ $constructor("$ZodEnum", (inst, def) => {
|
|
|
1989
1989
|
return payload;
|
|
1990
1990
|
};
|
|
1991
1991
|
});
|
|
1992
|
+
var $ZodLiteral = /*@__PURE__*/ $constructor("$ZodLiteral", (inst, def) => {
|
|
1993
|
+
$ZodType.init(inst, def);
|
|
1994
|
+
if (def.values.length === 0) throw new Error("Cannot create literal schema with no valid values");
|
|
1995
|
+
const values = new Set(def.values);
|
|
1996
|
+
inst._zod.values = values;
|
|
1997
|
+
inst._zod.pattern = new RegExp(`^(${def.values.map((o) => typeof o === "string" ? escapeRegex(o) : o ? escapeRegex(o.toString()) : String(o)).join("|")})$`);
|
|
1998
|
+
inst._zod.parse = (payload, _ctx) => {
|
|
1999
|
+
const input = payload.value;
|
|
2000
|
+
if (values.has(input)) return payload;
|
|
2001
|
+
payload.issues.push({
|
|
2002
|
+
code: "invalid_value",
|
|
2003
|
+
values: def.values,
|
|
2004
|
+
input,
|
|
2005
|
+
inst
|
|
2006
|
+
});
|
|
2007
|
+
return payload;
|
|
2008
|
+
};
|
|
2009
|
+
});
|
|
1992
2010
|
var $ZodTransform = /*@__PURE__*/ $constructor("$ZodTransform", (inst, def) => {
|
|
1993
2011
|
$ZodType.init(inst, def);
|
|
1994
2012
|
inst._zod.optin = "optional";
|
|
@@ -3125,6 +3143,27 @@ var enumProcessor = (schema, _ctx, json, _params) => {
|
|
|
3125
3143
|
if (values.every((v) => typeof v === "string")) json.type = "string";
|
|
3126
3144
|
json.enum = values;
|
|
3127
3145
|
};
|
|
3146
|
+
var literalProcessor = (schema, ctx, json, _params) => {
|
|
3147
|
+
const def = schema._zod.def;
|
|
3148
|
+
const vals = [];
|
|
3149
|
+
for (const val of def.values) if (val === void 0) {
|
|
3150
|
+
if (ctx.unrepresentable === "throw") throw new Error("Literal `undefined` cannot be represented in JSON Schema");
|
|
3151
|
+
} else if (typeof val === "bigint") if (ctx.unrepresentable === "throw") throw new Error("BigInt literals cannot be represented in JSON Schema");
|
|
3152
|
+
else vals.push(Number(val));
|
|
3153
|
+
else vals.push(val);
|
|
3154
|
+
if (vals.length === 0) {} else if (vals.length === 1) {
|
|
3155
|
+
const val = vals[0];
|
|
3156
|
+
json.type = val === null ? "null" : typeof val;
|
|
3157
|
+
if (ctx.target === "draft-04" || ctx.target === "openapi-3.0") json.enum = [val];
|
|
3158
|
+
else json.const = val;
|
|
3159
|
+
} else {
|
|
3160
|
+
if (vals.every((v) => typeof v === "number")) json.type = "number";
|
|
3161
|
+
if (vals.every((v) => typeof v === "string")) json.type = "string";
|
|
3162
|
+
if (vals.every((v) => typeof v === "boolean")) json.type = "boolean";
|
|
3163
|
+
if (vals.every((v) => v === null)) json.type = "null";
|
|
3164
|
+
json.enum = vals;
|
|
3165
|
+
}
|
|
3166
|
+
};
|
|
3128
3167
|
var customProcessor = (_schema, ctx, _json, _params) => {
|
|
3129
3168
|
if (ctx.unrepresentable === "throw") throw new Error("Custom types cannot be represented in JSON Schema");
|
|
3130
3169
|
};
|
|
@@ -3980,6 +4019,23 @@ function _enum(values, params) {
|
|
|
3980
4019
|
...normalizeParams(params)
|
|
3981
4020
|
});
|
|
3982
4021
|
}
|
|
4022
|
+
var ZodLiteral = /*@__PURE__*/ $constructor("ZodLiteral", (inst, def) => {
|
|
4023
|
+
$ZodLiteral.init(inst, def);
|
|
4024
|
+
ZodType.init(inst, def);
|
|
4025
|
+
inst._zod.processJSONSchema = (ctx, json, params) => literalProcessor(inst, ctx, json, params);
|
|
4026
|
+
inst.values = new Set(def.values);
|
|
4027
|
+
Object.defineProperty(inst, "value", { get() {
|
|
4028
|
+
if (def.values.length > 1) throw new Error("This schema contains multiple valid literal values. Use `.values` instead.");
|
|
4029
|
+
return def.values[0];
|
|
4030
|
+
} });
|
|
4031
|
+
});
|
|
4032
|
+
function literal(value, params) {
|
|
4033
|
+
return new ZodLiteral({
|
|
4034
|
+
type: "literal",
|
|
4035
|
+
values: Array.isArray(value) ? value : [value],
|
|
4036
|
+
...normalizeParams(params)
|
|
4037
|
+
});
|
|
4038
|
+
}
|
|
3983
4039
|
var ZodTransform = /*@__PURE__*/ $constructor("ZodTransform", (inst, def) => {
|
|
3984
4040
|
$ZodTransform.init(inst, def);
|
|
3985
4041
|
ZodType.init(inst, def);
|
|
@@ -4146,6 +4202,6 @@ function superRefine(fn, params) {
|
|
|
4146
4202
|
return /* @__PURE__ */ _superRefine(fn, params);
|
|
4147
4203
|
}
|
|
4148
4204
|
//#endregion
|
|
4149
|
-
export {
|
|
4205
|
+
export { number as a, string as c, literal as i, unknown as l, array as n, object as o, boolean as r, record as s, _enum as t };
|
|
4150
4206
|
|
|
4151
|
-
//# sourceMappingURL=schemas-
|
|
4207
|
+
//# sourceMappingURL=schemas-POKnVn0c.js.map
|