@plumix/plugin-media 0.1.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/LICENSE +21 -0
- package/README.md +211 -0
- package/dist/admin/FocalPointField.d.ts +22 -0
- package/dist/admin/FocalPointField.d.ts.map +1 -0
- package/dist/admin/FocalPointField.js +71 -0
- package/dist/admin/FocalPointField.js.map +1 -0
- package/dist/admin/MediaLibrary.d.ts +43 -0
- package/dist/admin/MediaLibrary.d.ts.map +1 -0
- package/dist/admin/MediaLibrary.js +698 -0
- package/dist/admin/MediaLibrary.js.map +1 -0
- package/dist/admin/MediaListPickerField.d.ts +14 -0
- package/dist/admin/MediaListPickerField.d.ts.map +1 -0
- package/dist/admin/MediaListPickerField.js +161 -0
- package/dist/admin/MediaListPickerField.js.map +1 -0
- package/dist/admin/MediaPickerField.d.ts +25 -0
- package/dist/admin/MediaPickerField.d.ts.map +1 -0
- package/dist/admin/MediaPickerField.js +82 -0
- package/dist/admin/MediaPickerField.js.map +1 -0
- package/dist/admin/MediaUrlField.d.ts +14 -0
- package/dist/admin/MediaUrlField.d.ts.map +1 -0
- package/dist/admin/MediaUrlField.js +29 -0
- package/dist/admin/MediaUrlField.js.map +1 -0
- package/dist/admin/index.d.ts +11 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +49 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/messages.d.ts +24 -0
- package/dist/admin/messages.d.ts.map +1 -0
- package/dist/admin/messages.js +28 -0
- package/dist/admin/messages.js.map +1 -0
- package/dist/blocks/file/index.d.ts +2 -0
- package/dist/blocks/file/index.d.ts.map +1 -0
- package/dist/blocks/file/index.js +109 -0
- package/dist/blocks/file/index.js.map +1 -0
- package/dist/blocks/file/normalize.d.ts +10 -0
- package/dist/blocks/file/normalize.d.ts.map +1 -0
- package/dist/blocks/file/normalize.js +45 -0
- package/dist/blocks/file/normalize.js.map +1 -0
- package/dist/blocks/image/index.d.ts +2 -0
- package/dist/blocks/image/index.d.ts.map +1 -0
- package/dist/blocks/image/index.js +141 -0
- package/dist/blocks/image/index.js.map +1 -0
- package/dist/blocks/image/normalize.d.ts +7 -0
- package/dist/blocks/image/normalize.d.ts.map +1 -0
- package/dist/blocks/image/normalize.js +20 -0
- package/dist/blocks/image/normalize.js.map +1 -0
- package/dist/blocks.d.ts +2 -0
- package/dist/blocks.d.ts.map +1 -0
- package/dist/blocks.js +6 -0
- package/dist/blocks.js.map +1 -0
- package/dist/builder.d.ts +80 -0
- package/dist/builder.d.ts.map +1 -0
- package/dist/builder.js +61 -0
- package/dist/builder.js.map +1 -0
- package/dist/fields.d.ts +3 -0
- package/dist/fields.d.ts.map +1 -0
- package/dist/fields.js +7 -0
- package/dist/fields.js.map +1 -0
- package/dist/image-dimensions.d.ts +7 -0
- package/dist/image-dimensions.d.ts.map +1 -0
- package/dist/image-dimensions.js +142 -0
- package/dist/image-dimensions.js.map +1 -0
- package/dist/index.d.ts +62 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +216 -0
- package/dist/index.js.map +1 -0
- package/dist/lookup.d.ts +43 -0
- package/dist/lookup.d.ts.map +1 -0
- package/dist/lookup.js +154 -0
- package/dist/lookup.js.map +1 -0
- package/dist/magic-bytes.d.ts +4 -0
- package/dist/magic-bytes.d.ts.map +1 -0
- package/dist/magic-bytes.js +107 -0
- package/dist/magic-bytes.js.map +1 -0
- package/dist/mcp-tools.d.ts +10 -0
- package/dist/mcp-tools.d.ts.map +1 -0
- package/dist/mcp-tools.js +43 -0
- package/dist/mcp-tools.js.map +1 -0
- package/dist/media-blocks.d.ts +3 -0
- package/dist/media-blocks.d.ts.map +1 -0
- package/dist/media-blocks.js +10 -0
- package/dist/media-blocks.js.map +1 -0
- package/dist/meta.d.ts +12 -0
- package/dist/meta.d.ts.map +1 -0
- package/dist/meta.js +20 -0
- package/dist/meta.js.map +1 -0
- package/dist/mime.d.ts +3 -0
- package/dist/mime.d.ts.map +1 -0
- package/dist/mime.js +58 -0
- package/dist/mime.js.map +1 -0
- package/dist/read-service.d.ts +66 -0
- package/dist/read-service.d.ts.map +1 -0
- package/dist/read-service.js +156 -0
- package/dist/read-service.js.map +1 -0
- package/dist/rpc.d.ts +7 -0
- package/dist/rpc.d.ts.map +1 -0
- package/dist/rpc.js +352 -0
- package/dist/rpc.js.map +1 -0
- package/dist/serve-route.d.ts +19 -0
- package/dist/serve-route.d.ts.map +1 -0
- package/dist/serve-route.js +122 -0
- package/dist/serve-route.js.map +1 -0
- package/dist/upload-route.d.ts +17 -0
- package/dist/upload-route.d.ts.map +1 -0
- package/dist/upload-route.js +106 -0
- package/dist/upload-route.js.map +1 -0
- package/package.json +97 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// Lightweight magic-byte detector for the MIME types the media plugin
|
|
2
|
+
// accepts. The presigned PUT pins a `Content-Type` the bucket stores
|
|
3
|
+
// verbatim — but R2 doesn't sniff bytes, so a malicious user can claim
|
|
4
|
+
// `image/png` and upload arbitrary content (HTML, executables, polyglot
|
|
5
|
+
// payloads). We re-fetch the first ~64 bytes after upload and verify
|
|
6
|
+
// the header matches the claimed type. On mismatch the caller deletes
|
|
7
|
+
// the object and rejects the confirm.
|
|
8
|
+
//
|
|
9
|
+
// Returns `true` when the buffer's prefix matches the claimed MIME, OR
|
|
10
|
+
// when we have no matcher for that MIME (e.g. `text/plain` — no reliable
|
|
11
|
+
// magic bytes). Returns `false` only when a known signature mismatches.
|
|
12
|
+
const sigAt = (offset, ...sig) => (b) => {
|
|
13
|
+
if (b.length < offset + sig.length)
|
|
14
|
+
return false;
|
|
15
|
+
for (let i = 0; i < sig.length; i++) {
|
|
16
|
+
if (b[offset + i] !== sig[i])
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
return true;
|
|
20
|
+
};
|
|
21
|
+
const startsWith = (...sig) => sigAt(0, ...sig);
|
|
22
|
+
const anyOf = (...m) => (b) => m.some((f) => f(b));
|
|
23
|
+
// `RIFF...<tag>` containers — `tag` lives at offset 8 after `RIFF` + size.
|
|
24
|
+
// Used by image/webp + audio/wav.
|
|
25
|
+
const riffWith = (...tag) => {
|
|
26
|
+
const head = startsWith(0x52, 0x49, 0x46, 0x46); // RIFF
|
|
27
|
+
const tail = sigAt(8, ...tag);
|
|
28
|
+
return (b) => head(b) && tail(b);
|
|
29
|
+
};
|
|
30
|
+
const isXmlOrSvg = (b) => {
|
|
31
|
+
// SVG/XML: tolerate UTF-8 BOM + leading whitespace, then `<?xml` or `<svg`.
|
|
32
|
+
const text = new TextDecoder("utf-8", { fatal: false }).decode(b.subarray(0, Math.min(b.length, 256)));
|
|
33
|
+
// Strip a leading UTF-8 BOM (U+FEFF) before checking the prefix.
|
|
34
|
+
const trimmed = text.replace(/^\uFEFF/, "").trimStart();
|
|
35
|
+
return trimmed.startsWith("<?xml") || trimmed.startsWith("<svg");
|
|
36
|
+
};
|
|
37
|
+
// `text/*` payloads must not look like HTML. Authors stash HTML in
|
|
38
|
+
// `.txt` to bypass the image allowlist and have CDNs serve it as
|
|
39
|
+
// content. Magic bytes can't fully prove "this is plain text", but we
|
|
40
|
+
// can reject obvious HTML markers and require UTF-8 decodability.
|
|
41
|
+
const isPlainText = (b) => {
|
|
42
|
+
let text;
|
|
43
|
+
try {
|
|
44
|
+
text = new TextDecoder("utf-8", { fatal: true }).decode(b.subarray(0, Math.min(b.length, 256)));
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
const trimmed = text
|
|
50
|
+
.replace(/^\uFEFF/, "")
|
|
51
|
+
.trimStart()
|
|
52
|
+
.toLowerCase();
|
|
53
|
+
return !(trimmed.startsWith("<!doctype") ||
|
|
54
|
+
trimmed.startsWith("<html") ||
|
|
55
|
+
trimmed.startsWith("<?xml") ||
|
|
56
|
+
trimmed.startsWith("<svg") ||
|
|
57
|
+
trimmed.startsWith("<script") ||
|
|
58
|
+
trimmed.startsWith("<iframe"));
|
|
59
|
+
};
|
|
60
|
+
// `ftyp` at offset 4 covers MP4, MOV, AVIF, HEIC, etc. We only need to
|
|
61
|
+
// detect "is this an isobmff container", not which brand exactly.
|
|
62
|
+
const isISOBMFF = sigAt(4, 0x66, 0x74, 0x79, 0x70);
|
|
63
|
+
// PKZIP local-file header — also matches DOCX/XLSX/PPTX (they're zip
|
|
64
|
+
// archives) and odt/ods/odp. We sniff "is this a zip container", NOT
|
|
65
|
+
// "is this the right Office subtype". A `.docx` claimed as xlsx still
|
|
66
|
+
// passes — verifying via the OOXML `[Content_Types].xml` is out of
|
|
67
|
+
// scope; the inline-safe allowlist excludes all of these so the
|
|
68
|
+
// serve route force-downloads regardless of subtype.
|
|
69
|
+
const isZipContainer = startsWith(0x50, 0x4b, 0x03, 0x04);
|
|
70
|
+
// OLE2 compound document — legacy Office (.doc/.xls/.ppt).
|
|
71
|
+
const isOle2 = startsWith(0xd0, 0xcf, 0x11, 0xe0);
|
|
72
|
+
const MATCHERS = {
|
|
73
|
+
"image/jpeg": startsWith(0xff, 0xd8, 0xff),
|
|
74
|
+
"image/png": startsWith(0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a),
|
|
75
|
+
"image/gif": anyOf(startsWith(0x47, 0x49, 0x46, 0x38, 0x37, 0x61), // GIF87a
|
|
76
|
+
startsWith(0x47, 0x49, 0x46, 0x38, 0x39, 0x61)),
|
|
77
|
+
"image/webp": riffWith(0x57, 0x45, 0x42, 0x50), // RIFF…WEBP
|
|
78
|
+
"image/avif": isISOBMFF,
|
|
79
|
+
"image/svg+xml": isXmlOrSvg,
|
|
80
|
+
"application/pdf": startsWith(0x25, 0x50, 0x44, 0x46), // %PDF
|
|
81
|
+
"application/zip": isZipContainer,
|
|
82
|
+
"application/msword": isOle2,
|
|
83
|
+
"application/vnd.ms-excel": isOle2,
|
|
84
|
+
"application/vnd.ms-powerpoint": isOle2,
|
|
85
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": isZipContainer,
|
|
86
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": isZipContainer,
|
|
87
|
+
"application/vnd.openxmlformats-officedocument.presentationml.presentation": isZipContainer,
|
|
88
|
+
"audio/mpeg": anyOf(startsWith(0x49, 0x44, 0x33), // ID3v2 tag
|
|
89
|
+
startsWith(0xff, 0xfb), startsWith(0xff, 0xf3), startsWith(0xff, 0xf2)),
|
|
90
|
+
"audio/wav": riffWith(0x57, 0x41, 0x56, 0x45), // RIFF…WAVE
|
|
91
|
+
"audio/ogg": startsWith(0x4f, 0x67, 0x67, 0x53), // OggS
|
|
92
|
+
"video/mp4": isISOBMFF,
|
|
93
|
+
"video/webm": startsWith(0x1a, 0x45, 0xdf, 0xa3), // EBML
|
|
94
|
+
"video/quicktime": isISOBMFF,
|
|
95
|
+
"text/plain": isPlainText,
|
|
96
|
+
"text/markdown": isPlainText,
|
|
97
|
+
"text/csv": isPlainText,
|
|
98
|
+
};
|
|
99
|
+
/** Buffer size we ask storage to read for the magic-byte sniff. */
|
|
100
|
+
export const MAGIC_BYTE_SAMPLE_SIZE = 64;
|
|
101
|
+
export function looksLikeMime(bytes, claimedMime) {
|
|
102
|
+
const matcher = MATCHERS[claimedMime];
|
|
103
|
+
if (!matcher)
|
|
104
|
+
return true; // unknown / text — can't verify; accept.
|
|
105
|
+
return matcher(bytes);
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=magic-bytes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"magic-bytes.js","sourceRoot":"","sources":["../src/magic-bytes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { McpTool } from "plumix/plugin";
|
|
2
|
+
import * as v from "valibot";
|
|
3
|
+
import { mediaListInputSchema } from "./read-service.js";
|
|
4
|
+
declare const mediaGetInputSchema: v.ObjectSchema<{
|
|
5
|
+
readonly id: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>]>;
|
|
6
|
+
}, undefined>;
|
|
7
|
+
export declare const mediaListTool: McpTool<typeof mediaListInputSchema>;
|
|
8
|
+
export declare const mediaGetTool: McpTool<typeof mediaGetInputSchema>;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=mcp-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-tools.d.ts","sourceRoot":"","sources":["../src/mcp-tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAE7B,OAAO,EAGL,oBAAoB,EAErB,MAAM,mBAAmB,CAAC;AAE3B,QAAA,MAAM,mBAAmB;;aAEvB,CAAC;AAYH,eAAO,MAAM,aAAa,EAAE,OAAO,CAAC,OAAO,oBAAoB,CAY9D,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,OAAO,CAAC,OAAO,mBAAmB,CAW5D,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { McpToolError } from "plumix/plugin";
|
|
2
|
+
import * as v from "valibot";
|
|
3
|
+
import { getMedia, listMedia, mediaListInputSchema, MediaReadError, } from "./read-service.js";
|
|
4
|
+
const mediaGetInputSchema = v.object({
|
|
5
|
+
id: v.pipe(v.number(), v.integer(), v.minValue(1)),
|
|
6
|
+
});
|
|
7
|
+
function asMcpToolError(error) {
|
|
8
|
+
if (!(error instanceof MediaReadError))
|
|
9
|
+
throw error;
|
|
10
|
+
switch (error.data.code) {
|
|
11
|
+
case "not_found":
|
|
12
|
+
return McpToolError.notFound(error.message);
|
|
13
|
+
case "forbidden":
|
|
14
|
+
return McpToolError.forbidden(error.message);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export const mediaListTool = {
|
|
18
|
+
name: "media_list",
|
|
19
|
+
description: "List published media (images, files) with optional MIME and filename filters, paginated. Clamped to what your token may read.",
|
|
20
|
+
inputSchema: mediaListInputSchema,
|
|
21
|
+
async run(ctx, input) {
|
|
22
|
+
try {
|
|
23
|
+
return await listMedia(ctx, input);
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
throw asMcpToolError(error);
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
export const mediaGetTool = {
|
|
31
|
+
name: "media_get",
|
|
32
|
+
description: "Read a single published media item in full by its id.",
|
|
33
|
+
inputSchema: mediaGetInputSchema,
|
|
34
|
+
async run(ctx, input) {
|
|
35
|
+
try {
|
|
36
|
+
return await getMedia(ctx, input);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
throw asMcpToolError(error);
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=mcp-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-tools.js","sourceRoot":"","sources":["../src/mcp-tools.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAE7B,OAAO,EACL,QAAQ,EACR,SAAS,EACT,oBAAoB,EACpB,cAAc,GACf,MAAM,mBAAmB,CAAC;AAE3B,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;CACnD,CAAC,CAAC;AAEH,SAAS,cAAc,CAAC,KAAc;IACpC,IAAI,CAAC,CAAC,KAAK,YAAY,cAAc,CAAC;QAAE,MAAM,KAAK,CAAC;IACpD,QAAQ,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACxB,KAAK,WAAW;YACd,OAAO,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC9C,KAAK,WAAW;YACd,OAAO,YAAY,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACjD,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAyC;IACjE,IAAI,EAAE,YAAY;IAClB,WAAW,EACT,+HAA+H;IACjI,WAAW,EAAE,oBAAoB;IACjC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK;QAClB,IAAI,CAAC;YACH,OAAO,MAAM,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACrC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,cAAc,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAwC;IAC/D,IAAI,EAAE,WAAW;IACjB,WAAW,EAAE,uDAAuD;IACpE,WAAW,EAAE,mBAAmB;IAChC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK;QAClB,IAAI,CAAC;YACH,OAAO,MAAM,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACpC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,cAAc,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-blocks.d.ts","sourceRoot":"","sources":["../src/media-blocks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAQ/C,eAAO,MAAM,WAAW,EAAE,SAAS,SAAS,EAG1C,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { fileBlock } from "./blocks/file/index.js";
|
|
2
|
+
import { imageBlock } from "./blocks/image/index.js";
|
|
3
|
+
// Browser-clean canonical list — no server-side imports — so the
|
|
4
|
+
// admin chunk can pull it without transitively dragging in the
|
|
5
|
+
// plugin's RPC routes, upload handler, or `definePlugin`.
|
|
6
|
+
export const mediaBlocks = Object.freeze([
|
|
7
|
+
imageBlock,
|
|
8
|
+
fileBlock,
|
|
9
|
+
]);
|
|
10
|
+
//# sourceMappingURL=media-blocks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-blocks.js","sourceRoot":"","sources":["../src/media-blocks.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,iEAAiE;AACjE,+DAA+D;AAC/D,0DAA0D;AAC1D,MAAM,CAAC,MAAM,WAAW,GAAyB,MAAM,CAAC,MAAM,CAAC;IAC7D,UAAU;IACV,SAAS;CACV,CAAC,CAAC"}
|
package/dist/meta.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface MediaMeta {
|
|
2
|
+
readonly mime: string;
|
|
3
|
+
readonly size: number;
|
|
4
|
+
readonly storageKey: string;
|
|
5
|
+
readonly originalName: string | null;
|
|
6
|
+
readonly alt: string | null;
|
|
7
|
+
readonly width: number | null;
|
|
8
|
+
readonly height: number | null;
|
|
9
|
+
}
|
|
10
|
+
export declare function parseMediaMeta(raw: unknown): MediaMeta | null;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=meta.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"meta.d.ts","sourceRoot":"","sources":["../src/meta.ts"],"names":[],"mappings":"AAAA,UAAU,SAAS;IACjB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAG5B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CAmB7D"}
|
package/dist/meta.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export function parseMediaMeta(raw) {
|
|
2
|
+
if (!raw || typeof raw !== "object")
|
|
3
|
+
return null;
|
|
4
|
+
const r = raw;
|
|
5
|
+
if (typeof r.storageKey !== "string" ||
|
|
6
|
+
typeof r.mime !== "string" ||
|
|
7
|
+
typeof r.size !== "number") {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
return {
|
|
11
|
+
storageKey: r.storageKey,
|
|
12
|
+
mime: r.mime,
|
|
13
|
+
size: r.size,
|
|
14
|
+
originalName: typeof r.originalName === "string" ? r.originalName : null,
|
|
15
|
+
alt: typeof r.alt === "string" ? r.alt : null,
|
|
16
|
+
width: typeof r.width === "number" ? r.width : null,
|
|
17
|
+
height: typeof r.height === "number" ? r.height : null,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=meta.js.map
|
package/dist/meta.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"meta.js","sourceRoot":"","sources":["../src/meta.ts"],"names":[],"mappings":"AAYA,MAAM,UAAU,cAAc,CAAC,GAAY;IACzC,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACjD,MAAM,CAAC,GAAG,GAA8B,CAAC;IACzC,IACE,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ;QAChC,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ;QAC1B,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,EAC1B,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO;QACL,UAAU,EAAE,CAAC,CAAC,UAAU;QACxB,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,YAAY,EAAE,OAAO,CAAC,CAAC,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI;QACxE,GAAG,EAAE,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI;QAC7C,KAAK,EAAE,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;QACnD,MAAM,EAAE,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI;KACvD,CAAC;AACJ,CAAC"}
|
package/dist/mime.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mime.d.ts","sourceRoot":"","sources":["../src/mime.ts"],"names":[],"mappings":"AA0DA,eAAO,MAAM,sBAAsB,EAAE,SAAS,MAAM,EAEnD,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEjE"}
|
package/dist/mime.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// Single source of truth for the MIME types this plugin accepts and the
|
|
2
|
+
// extension we'll use for each in storage keys. Both `DEFAULT_ACCEPTED_TYPES`
|
|
3
|
+
// (the upload allowlist) and the rpc layer's extension picker derive from
|
|
4
|
+
// here, so the two stay in lockstep.
|
|
5
|
+
//
|
|
6
|
+
// SECURITY:
|
|
7
|
+
// - The bucket stores whatever bytes the client uploads; the worker
|
|
8
|
+
// verifies them against the claimed mime via magic-byte sniff in
|
|
9
|
+
// `media.confirm` (defense-in-depth — we don't trust the signed
|
|
10
|
+
// Content-Type header at upload time).
|
|
11
|
+
// - `image/svg+xml` is intentionally NOT in the default allowlist:
|
|
12
|
+
// SVG is XML and can carry executable `<script>`/`onload=` payloads.
|
|
13
|
+
// A magic-byte sniff can confirm the bytes start with `<svg`/`<?xml`
|
|
14
|
+
// but cannot prove they're safe to render. Operators who need SVG
|
|
15
|
+
// uploads must opt in explicitly via `media({ acceptedTypes: [...] })`
|
|
16
|
+
// AND serve from a separate cookie domain (so any embedded script
|
|
17
|
+
// can't reach admin cookies).
|
|
18
|
+
// - Same precaution applies to `text/*` mimes: bytes are stored verbatim,
|
|
19
|
+
// and a malicious actor could disguise HTML/JS as `text/plain`. Always
|
|
20
|
+
// serve uploads from a domain distinct from the admin.
|
|
21
|
+
const MEDIA_MIME_REGISTRY = {
|
|
22
|
+
// images
|
|
23
|
+
"image/jpeg": "jpg",
|
|
24
|
+
"image/png": "png",
|
|
25
|
+
"image/gif": "gif",
|
|
26
|
+
"image/webp": "webp",
|
|
27
|
+
"image/avif": "avif",
|
|
28
|
+
// SVG kept in the registry so opt-in consumers get the right extension,
|
|
29
|
+
// but excluded from DEFAULT_ACCEPTED_TYPES below.
|
|
30
|
+
"image/svg+xml": "svg",
|
|
31
|
+
// documents
|
|
32
|
+
"application/pdf": "pdf",
|
|
33
|
+
"application/msword": "doc",
|
|
34
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
|
|
35
|
+
"application/vnd.ms-excel": "xls",
|
|
36
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "xlsx",
|
|
37
|
+
"application/vnd.ms-powerpoint": "ppt",
|
|
38
|
+
"application/vnd.openxmlformats-officedocument.presentationml.presentation": "pptx",
|
|
39
|
+
"text/plain": "txt",
|
|
40
|
+
"text/markdown": "md",
|
|
41
|
+
"text/csv": "csv",
|
|
42
|
+
// audio
|
|
43
|
+
"audio/mpeg": "mp3",
|
|
44
|
+
"audio/wav": "wav",
|
|
45
|
+
"audio/ogg": "ogg",
|
|
46
|
+
// video
|
|
47
|
+
"video/mp4": "mp4",
|
|
48
|
+
"video/webm": "webm",
|
|
49
|
+
"video/quicktime": "mov",
|
|
50
|
+
// archives
|
|
51
|
+
"application/zip": "zip",
|
|
52
|
+
};
|
|
53
|
+
const SVG_MIME = "image/svg+xml";
|
|
54
|
+
export const DEFAULT_ACCEPTED_TYPES = Object.freeze(Object.keys(MEDIA_MIME_REGISTRY).filter((m) => m !== SVG_MIME));
|
|
55
|
+
export function extensionForMime(mime) {
|
|
56
|
+
return MEDIA_MIME_REGISTRY[mime];
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=mime.js.map
|
package/dist/mime.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mime.js","sourceRoot":"","sources":["../src/mime.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,8EAA8E;AAC9E,0EAA0E;AAC1E,qCAAqC;AACrC,EAAE;AACF,YAAY;AACZ,oEAAoE;AACpE,mEAAmE;AACnE,kEAAkE;AAClE,yCAAyC;AACzC,mEAAmE;AACnE,uEAAuE;AACvE,uEAAuE;AACvE,oEAAoE;AACpE,yEAAyE;AACzE,oEAAoE;AACpE,gCAAgC;AAChC,0EAA0E;AAC1E,yEAAyE;AACzE,yDAAyD;AAEzD,MAAM,mBAAmB,GAAqC;IAC5D,SAAS;IACT,YAAY,EAAE,KAAK;IACnB,WAAW,EAAE,KAAK;IAClB,WAAW,EAAE,KAAK;IAClB,YAAY,EAAE,MAAM;IACpB,YAAY,EAAE,MAAM;IACpB,wEAAwE;IACxE,kDAAkD;IAClD,eAAe,EAAE,KAAK;IACtB,YAAY;IACZ,iBAAiB,EAAE,KAAK;IACxB,oBAAoB,EAAE,KAAK;IAC3B,yEAAyE,EACvE,MAAM;IACR,0BAA0B,EAAE,KAAK;IACjC,mEAAmE,EAAE,MAAM;IAC3E,+BAA+B,EAAE,KAAK;IACtC,2EAA2E,EACzE,MAAM;IACR,YAAY,EAAE,KAAK;IACnB,eAAe,EAAE,IAAI;IACrB,UAAU,EAAE,KAAK;IACjB,QAAQ;IACR,YAAY,EAAE,KAAK;IACnB,WAAW,EAAE,KAAK;IAClB,WAAW,EAAE,KAAK;IAClB,QAAQ;IACR,WAAW,EAAE,KAAK;IAClB,YAAY,EAAE,MAAM;IACpB,iBAAiB,EAAE,KAAK;IACxB,WAAW;IACX,iBAAiB,EAAE,KAAK;CACzB,CAAC;AAEF,MAAM,QAAQ,GAAG,eAAe,CAAC;AAEjC,MAAM,CAAC,MAAM,sBAAsB,GAAsB,MAAM,CAAC,MAAM,CACpE,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,CAC/D,CAAC;AAEF,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,mBAAmB,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { AppContext } from "plumix/plugin";
|
|
2
|
+
import * as v from "valibot";
|
|
3
|
+
export declare const MEDIA_ENTRY_TYPE = "media";
|
|
4
|
+
export declare const mediaListInputSchema: v.ObjectSchema<{
|
|
5
|
+
readonly limit: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>, v.MaxValueAction<number, 100, undefined>]>, 24>;
|
|
6
|
+
readonly offset: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>, 0>;
|
|
7
|
+
readonly accept: v.OptionalSchema<v.UnionSchema<[v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 64, undefined>]>, v.SchemaWithPipe<readonly [v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MaxLengthAction<string, 64, undefined>]>, undefined>, v.MaxLengthAction<string[], 32, undefined>]>], undefined>, undefined>;
|
|
8
|
+
readonly search: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.MaxLengthAction<string, 200, undefined>]>, undefined>;
|
|
9
|
+
}, undefined>;
|
|
10
|
+
type MediaListInput = v.InferOutput<typeof mediaListInputSchema>;
|
|
11
|
+
interface MediaItem {
|
|
12
|
+
readonly id: number;
|
|
13
|
+
readonly title: string;
|
|
14
|
+
readonly mime: string;
|
|
15
|
+
readonly size: number;
|
|
16
|
+
readonly storageKey: string;
|
|
17
|
+
readonly alt: string | null;
|
|
18
|
+
readonly url: string;
|
|
19
|
+
readonly thumbnailUrl: string;
|
|
20
|
+
readonly uploadedAt: string;
|
|
21
|
+
readonly uploadedById: number;
|
|
22
|
+
readonly width: number | null;
|
|
23
|
+
readonly height: number | null;
|
|
24
|
+
}
|
|
25
|
+
interface MediaListResult {
|
|
26
|
+
readonly items: readonly MediaItem[];
|
|
27
|
+
readonly hasMore: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Domain error the media read path throws. Each transport maps it to its own
|
|
31
|
+
* shape (oRPC typed error / MCP envelope), keeping the service transport-neutral.
|
|
32
|
+
*/
|
|
33
|
+
export declare class MediaReadError extends Error {
|
|
34
|
+
readonly data: {
|
|
35
|
+
readonly code: "forbidden";
|
|
36
|
+
readonly capability: string;
|
|
37
|
+
} | {
|
|
38
|
+
readonly code: "not_found";
|
|
39
|
+
readonly id: number;
|
|
40
|
+
};
|
|
41
|
+
private constructor();
|
|
42
|
+
static forbidden(capability: string): MediaReadError;
|
|
43
|
+
static notFound(id: number): MediaReadError;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* List published media the caller may read, with MIME / filename filters and
|
|
47
|
+
* offset pagination. Fetches one extra row to report `hasMore` without a
|
|
48
|
+
* second COUNT query. Throws {@link MediaReadError}.
|
|
49
|
+
*/
|
|
50
|
+
export declare function listMedia(ctx: AppContext, input: MediaListInput): Promise<MediaListResult>;
|
|
51
|
+
/**
|
|
52
|
+
* Read a single published media item by id. A missing row, a non-media row, a
|
|
53
|
+
* draft, or corrupt meta all collapse to `not_found` so existence stays hidden.
|
|
54
|
+
*/
|
|
55
|
+
export declare function getMedia(ctx: AppContext, input: {
|
|
56
|
+
readonly id: number;
|
|
57
|
+
}): Promise<MediaItem>;
|
|
58
|
+
export declare function thumbnailFor(ctx: AppContext, url: string, mime: string): string;
|
|
59
|
+
/**
|
|
60
|
+
* Resolve a publicly-fetchable URL for a media row. Prefers the storage
|
|
61
|
+
* adapter's native URL; falls back to the worker-proxied serve route keyed on
|
|
62
|
+
* the entry id (not the storageKey — the serve route enforces `published`).
|
|
63
|
+
*/
|
|
64
|
+
export declare function resolveMediaUrl(storage: NonNullable<AppContext["storage"]>, storageKey: string, entryId: number, basePath?: string): Promise<string>;
|
|
65
|
+
export {};
|
|
66
|
+
//# sourceMappingURL=read-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-service.d.ts","sourceRoot":"","sources":["../src/read-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAO,MAAM,eAAe,CAAC;AAYrD,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAI7B,eAAO,MAAM,gBAAgB,UAAU,CAAC;AASxC,eAAO,MAAM,oBAAoB;;;;;aAgB/B,CAAC;AAEH,KAAK,cAAc,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAEjE,UAAU,SAAS;IACjB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,UAAU,eAAe;IACvB,QAAQ,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED;;;GAGG;AACH,qBAAa,cAAe,SAAQ,KAAK;IAKvC,QAAQ,CAAC,IAAI,EACT;QAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;QAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAC3D;QAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;QAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IAExD,OAAO;IAKP,MAAM,CAAC,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc;IAOpD,MAAM,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,cAAc;CAM5C;AAED;;;;GAIG;AACH,wBAAsB,SAAS,CAC7B,GAAG,EAAE,UAAU,EACf,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC,eAAe,CAAC,CAoC1B;AAED;;;GAGG;AACH,wBAAsB,QAAQ,CAC5B,GAAG,EAAE,UAAU,EACf,KAAK,EAAE;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC7B,OAAO,CAAC,SAAS,CAAC,CAapB;AA4BD,wBAAgB,YAAY,CAC1B,GAAG,EAAE,UAAU,EACf,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,GACX,MAAM,CAOR;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,WAAW,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,EAC3C,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,QAAQ,SAAK,GACZ,OAAO,CAAC,MAAM,CAAC,CAKjB"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { and, desc, entries, eq, escapeLikePattern, inArray, like, sql, withBasePath, } from "plumix/plugin";
|
|
2
|
+
import * as v from "valibot";
|
|
3
|
+
import { parseMediaMeta } from "./meta.js";
|
|
4
|
+
export const MEDIA_ENTRY_TYPE = "media";
|
|
5
|
+
const MEDIA_READ_CAPABILITY = "entry:media:read";
|
|
6
|
+
const DEFAULT_PAGE_SIZE = 24;
|
|
7
|
+
const MAX_PAGE_SIZE = 100;
|
|
8
|
+
// 320px-wide auto-format thumbnail — enough for the 160px admin card at 2× DPI.
|
|
9
|
+
const THUMBNAIL_OPTS = { width: 320, format: "auto", fit: "cover" };
|
|
10
|
+
export const mediaListInputSchema = v.object({
|
|
11
|
+
limit: v.optional(v.pipe(v.number(), v.integer(), v.minValue(1), v.maxValue(MAX_PAGE_SIZE)), DEFAULT_PAGE_SIZE),
|
|
12
|
+
offset: v.optional(v.pipe(v.number(), v.integer(), v.minValue(0)), 0),
|
|
13
|
+
// MIME filter: string form (`"image/"`) does a `LIKE 'image/%'` prefix match;
|
|
14
|
+
// array form matches the listed MIMEs exactly. Pushed into SQL so `limit`
|
|
15
|
+
// counts only matching rows.
|
|
16
|
+
accept: v.optional(v.union([
|
|
17
|
+
v.pipe(v.string(), v.maxLength(64)),
|
|
18
|
+
v.pipe(v.array(v.pipe(v.string(), v.maxLength(64))), v.maxLength(32)),
|
|
19
|
+
])),
|
|
20
|
+
search: v.optional(v.pipe(v.string(), v.trim(), v.maxLength(200))),
|
|
21
|
+
});
|
|
22
|
+
/**
|
|
23
|
+
* Domain error the media read path throws. Each transport maps it to its own
|
|
24
|
+
* shape (oRPC typed error / MCP envelope), keeping the service transport-neutral.
|
|
25
|
+
*/
|
|
26
|
+
export class MediaReadError extends Error {
|
|
27
|
+
static {
|
|
28
|
+
MediaReadError.prototype.name = "MediaReadError";
|
|
29
|
+
}
|
|
30
|
+
data;
|
|
31
|
+
constructor(data, message) {
|
|
32
|
+
super(message);
|
|
33
|
+
this.data = data;
|
|
34
|
+
}
|
|
35
|
+
static forbidden(capability) {
|
|
36
|
+
return new MediaReadError({ code: "forbidden", capability }, `missing capability: ${capability}`);
|
|
37
|
+
}
|
|
38
|
+
static notFound(id) {
|
|
39
|
+
return new MediaReadError({ code: "not_found", id }, `media ${id} not found`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* List published media the caller may read, with MIME / filename filters and
|
|
44
|
+
* offset pagination. Fetches one extra row to report `hasMore` without a
|
|
45
|
+
* second COUNT query. Throws {@link MediaReadError}.
|
|
46
|
+
*/
|
|
47
|
+
export async function listMedia(ctx, input) {
|
|
48
|
+
if (!ctx.auth.can(MEDIA_READ_CAPABILITY)) {
|
|
49
|
+
throw MediaReadError.forbidden(MEDIA_READ_CAPABILITY);
|
|
50
|
+
}
|
|
51
|
+
const conditions = [
|
|
52
|
+
eq(entries.type, MEDIA_ENTRY_TYPE),
|
|
53
|
+
eq(entries.status, "published"),
|
|
54
|
+
];
|
|
55
|
+
const acceptCondition = buildAcceptCondition(input.accept);
|
|
56
|
+
if (acceptCondition)
|
|
57
|
+
conditions.push(acceptCondition);
|
|
58
|
+
if (input.search) {
|
|
59
|
+
const pattern = `%${escapeLikePattern(input.search)}%`;
|
|
60
|
+
conditions.push(sql `(
|
|
61
|
+
${entries.title} LIKE ${pattern} ESCAPE '\\'
|
|
62
|
+
OR COALESCE(json_extract(${entries.meta}, '$.alt'), '') LIKE ${pattern} ESCAPE '\\'
|
|
63
|
+
)`);
|
|
64
|
+
}
|
|
65
|
+
const rows = await ctx.db
|
|
66
|
+
.select()
|
|
67
|
+
.from(entries)
|
|
68
|
+
.where(and(...conditions))
|
|
69
|
+
.orderBy(desc(entries.updatedAt), desc(entries.id))
|
|
70
|
+
.limit(input.limit + 1)
|
|
71
|
+
.offset(input.offset);
|
|
72
|
+
const hasMore = rows.length > input.limit;
|
|
73
|
+
const visibleRows = hasMore ? rows.slice(0, input.limit) : rows;
|
|
74
|
+
const items = [];
|
|
75
|
+
for (const row of visibleRows) {
|
|
76
|
+
const meta = parseMediaMeta(row.meta);
|
|
77
|
+
if (!meta)
|
|
78
|
+
continue;
|
|
79
|
+
items.push(await buildMediaItem(ctx, row, meta));
|
|
80
|
+
}
|
|
81
|
+
return { items, hasMore };
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Read a single published media item by id. A missing row, a non-media row, a
|
|
85
|
+
* draft, or corrupt meta all collapse to `not_found` so existence stays hidden.
|
|
86
|
+
*/
|
|
87
|
+
export async function getMedia(ctx, input) {
|
|
88
|
+
if (!ctx.auth.can(MEDIA_READ_CAPABILITY)) {
|
|
89
|
+
throw MediaReadError.forbidden(MEDIA_READ_CAPABILITY);
|
|
90
|
+
}
|
|
91
|
+
const row = await ctx.db.query.entries.findFirst({
|
|
92
|
+
where: eq(entries.id, input.id),
|
|
93
|
+
});
|
|
94
|
+
const meta = row ? parseMediaMeta(row.meta) : null;
|
|
95
|
+
if (row?.type !== MEDIA_ENTRY_TYPE || row.status !== "published" || !meta) {
|
|
96
|
+
throw MediaReadError.notFound(input.id);
|
|
97
|
+
}
|
|
98
|
+
return buildMediaItem(ctx, row, meta);
|
|
99
|
+
}
|
|
100
|
+
async function buildMediaItem(ctx, row, meta) {
|
|
101
|
+
const url = ctx.storage
|
|
102
|
+
? await resolveMediaUrl(ctx.storage, meta.storageKey, row.id, ctx.basePath)
|
|
103
|
+
: meta.storageKey;
|
|
104
|
+
// `publishedAt` is the "uploaded on" source of truth; fall back to createdAt.
|
|
105
|
+
const uploadedAt = (row.publishedAt ?? row.createdAt).toISOString();
|
|
106
|
+
return {
|
|
107
|
+
id: row.id,
|
|
108
|
+
title: row.title,
|
|
109
|
+
mime: meta.mime,
|
|
110
|
+
size: meta.size,
|
|
111
|
+
storageKey: meta.storageKey,
|
|
112
|
+
alt: meta.alt,
|
|
113
|
+
url,
|
|
114
|
+
thumbnailUrl: thumbnailFor(ctx, url, meta.mime),
|
|
115
|
+
uploadedAt,
|
|
116
|
+
uploadedById: row.authorId,
|
|
117
|
+
width: meta.width,
|
|
118
|
+
height: meta.height,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
export function thumbnailFor(ctx, url, mime) {
|
|
122
|
+
// imageDelivery transforms need an absolute, publicly-reachable source — the
|
|
123
|
+
// transform CDN fetches it itself. The worker-proxied serve fallback is
|
|
124
|
+
// relative, so skip transforms there.
|
|
125
|
+
if (!mime.startsWith("image/") || !ctx.imageDelivery)
|
|
126
|
+
return url;
|
|
127
|
+
if (!url.startsWith("http://") && !url.startsWith("https://"))
|
|
128
|
+
return url;
|
|
129
|
+
return ctx.imageDelivery.url(url, THUMBNAIL_OPTS);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Resolve a publicly-fetchable URL for a media row. Prefers the storage
|
|
133
|
+
* adapter's native URL; falls back to the worker-proxied serve route keyed on
|
|
134
|
+
* the entry id (not the storageKey — the serve route enforces `published`).
|
|
135
|
+
*/
|
|
136
|
+
export async function resolveMediaUrl(storage, storageKey, entryId, basePath = "") {
|
|
137
|
+
const direct = await storage.url(storageKey);
|
|
138
|
+
return (direct ?? withBasePath(`/_plumix/media/serve/${String(entryId)}`, basePath));
|
|
139
|
+
}
|
|
140
|
+
// Translate `accept` into a SQL predicate against the JSON `mime` field. Real
|
|
141
|
+
// MIME strings don't contain LIKE wildcards and the input is plugin/agent
|
|
142
|
+
// supplied, so no escaping is needed.
|
|
143
|
+
function buildAcceptCondition(accept) {
|
|
144
|
+
if (accept === undefined)
|
|
145
|
+
return undefined;
|
|
146
|
+
const mimeExpr = sql `json_extract(${entries.meta}, '$.mime')`;
|
|
147
|
+
if (typeof accept === "string") {
|
|
148
|
+
if (accept === "")
|
|
149
|
+
return undefined;
|
|
150
|
+
return like(mimeExpr, `${accept}%`);
|
|
151
|
+
}
|
|
152
|
+
if (accept.length === 0)
|
|
153
|
+
return undefined;
|
|
154
|
+
return inArray(mimeExpr, accept);
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=read-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-service.js","sourceRoot":"","sources":["../src/read-service.ts"],"names":[],"mappings":"AACA,OAAO,EACL,GAAG,EACH,IAAI,EACJ,OAAO,EACP,EAAE,EACF,iBAAiB,EACjB,OAAO,EACP,IAAI,EACJ,GAAG,EACH,YAAY,GACb,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAE7B,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAC;AACxC,MAAM,qBAAqB,GAAG,kBAAkB,CAAC;AAEjD,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAC7B,MAAM,aAAa,GAAG,GAAG,CAAC;AAE1B,gFAAgF;AAChF,MAAM,cAAc,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAW,CAAC;AAE7E,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,KAAK,EAAE,CAAC,CAAC,QAAQ,CACf,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,EACzE,iBAAiB,CAClB;IACD,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACrE,8EAA8E;IAC9E,0EAA0E;IAC1E,6BAA6B;IAC7B,MAAM,EAAE,CAAC,CAAC,QAAQ,CAChB,CAAC,CAAC,KAAK,CAAC;QACN,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QACnC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;KACtE,CAAC,CACH;IACD,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;CACnE,CAAC,CAAC;AAwBH;;;GAGG;AACH,MAAM,OAAO,cAAe,SAAQ,KAAK;IACvC;QACE,cAAc,CAAC,SAAS,CAAC,IAAI,GAAG,gBAAgB,CAAC;IACnD,CAAC;IAEQ,IAAI,CAE2C;IAExD,YAAoB,IAA4B,EAAE,OAAe;QAC/D,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,MAAM,CAAC,SAAS,CAAC,UAAkB;QACjC,OAAO,IAAI,cAAc,CACvB,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,EACjC,uBAAuB,UAAU,EAAE,CACpC,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,QAAQ,CAAC,EAAU;QACxB,OAAO,IAAI,cAAc,CACvB,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,EACzB,SAAS,EAAE,YAAY,CACxB,CAAC;IACJ,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,GAAe,EACf,KAAqB;IAErB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,qBAAqB,CAAC,EAAE,CAAC;QACzC,MAAM,cAAc,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,UAAU,GAAU;QACxB,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,gBAAgB,CAAC;QAClC,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC;KAChC,CAAC;IACF,MAAM,eAAe,GAAG,oBAAoB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3D,IAAI,eAAe;QAAE,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACtD,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,MAAM,OAAO,GAAG,IAAI,iBAAiB,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC;QACvD,UAAU,CAAC,IAAI,CAAC,GAAG,CAAA;QACf,OAAO,CAAC,KAAK,SAAS,OAAO;iCACJ,OAAO,CAAC,IAAI,wBAAwB,OAAO;MACtE,CAAC,CAAC;IACN,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,EAAE;SACtB,MAAM,EAAE;SACR,IAAI,CAAC,OAAO,CAAC;SACb,KAAK,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC;SACzB,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;SAClD,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC;SACtB,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACxB,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC;IAC1C,MAAM,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAEhE,MAAM,KAAK,GAAgB,EAAE,CAAC;IAC9B,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,KAAK,CAAC,IAAI,CAAC,MAAM,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAC5B,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,GAAe,EACf,KAA8B;IAE9B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,qBAAqB,CAAC,EAAE,CAAC;QACzC,MAAM,cAAc,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;QAC/C,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC;KAChC,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACnD,IAAI,GAAG,EAAE,IAAI,KAAK,gBAAgB,IAAI,GAAG,CAAC,MAAM,KAAK,WAAW,IAAI,CAAC,IAAI,EAAE,CAAC;QAC1E,MAAM,cAAc,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;AACxC,CAAC;AAED,KAAK,UAAU,cAAc,CAC3B,GAAe,EACf,GAAgC,EAChC,IAAoD;IAEpD,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO;QACrB,CAAC,CAAC,MAAM,eAAe,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,QAAQ,CAAC;QAC3E,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;IACpB,8EAA8E;IAC9E,MAAM,UAAU,GAAG,CAAC,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;IACpE,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,GAAG;QACH,YAAY,EAAE,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC;QAC/C,UAAU;QACV,YAAY,EAAE,GAAG,CAAC,QAAQ;QAC1B,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,GAAe,EACf,GAAW,EACX,IAAY;IAEZ,6EAA6E;IAC7E,wEAAwE;IACxE,sCAAsC;IACtC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa;QAAE,OAAO,GAAG,CAAC;IACjE,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,GAAG,CAAC;IAC1E,OAAO,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;AACpD,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,OAA2C,EAC3C,UAAkB,EAClB,OAAe,EACf,QAAQ,GAAG,EAAE;IAEb,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC7C,OAAO,CACL,MAAM,IAAI,YAAY,CAAC,wBAAwB,MAAM,CAAC,OAAO,CAAC,EAAE,EAAE,QAAQ,CAAC,CAC5E,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,0EAA0E;AAC1E,sCAAsC;AACtC,SAAS,oBAAoB,CAC3B,MAA8C;IAE9C,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC3C,MAAM,QAAQ,GAAG,GAAG,CAAQ,gBAAgB,OAAO,CAAC,IAAI,aAAa,CAAC;IACtE,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,IAAI,MAAM,KAAK,EAAE;YAAE,OAAO,SAAS,CAAC;QACpC,OAAO,IAAI,CAAC,QAAQ,EAAE,GAAG,MAAM,GAAG,CAAC,CAAC;IACtC,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC1C,OAAO,OAAO,CAAC,QAAQ,EAAE,MAAkB,CAAC,CAAC;AAC/C,CAAC"}
|
package/dist/rpc.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rpc.d.ts","sourceRoot":"","sources":["../src/rpc.ts"],"names":[],"mappings":"AA2BA,UAAU,eAAe;IACvB,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAyED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,eAAe,GACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA0UzB"}
|