@airdraft/plugin-media 0.2.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/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@airdraft/plugin-media` will be documented here.
4
+
5
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
@@ -0,0 +1,3 @@
1
+ export { withMedia } from './withMedia.js';
2
+ export type { WithMediaOptions, MediaUploadResult } from './withMedia.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { withMedia } from './withMedia.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA"}
@@ -0,0 +1,59 @@
1
+ import type { Plugin, MediaAdapter, StorageAdapter, MediaUploadResult } from '@airdraft/core';
2
+ export interface WithMediaOptions {
3
+ /** Required. The media adapter instance (handles binary storage). */
4
+ adapter: MediaAdapter;
5
+ /**
6
+ * Optional. A content StorageAdapter used to persist JSON sidecar files at
7
+ * `_media/{key}.json`. Activates the full media library feature set.
8
+ * Omitting this field leaves withMedia() fully backwards-compatible with v0.1.
9
+ */
10
+ storageAdapter?: StorageAdapter;
11
+ /** Storage key prefix. Default: 'uploads' */
12
+ prefix?: string;
13
+ /** Override key generation. Receives file metadata, returns the full key. */
14
+ generateKey?: (file: {
15
+ name: string;
16
+ type: string;
17
+ size: number;
18
+ }) => string;
19
+ /** MIME type allowlist. Checked before the adapter is called. Default: all types allowed. */
20
+ allowedTypes?: string[];
21
+ /** Max file size in bytes. Checked before the adapter is called. Default: unlimited. */
22
+ maxSize?: number;
23
+ }
24
+ export type { MediaUploadResult };
25
+ declare function sanitizeName(name: string): string;
26
+ declare function hash4(input: string): string;
27
+ declare function defaultGenerateKey(file: {
28
+ name: string;
29
+ type: string;
30
+ size: number;
31
+ }, prefix: string): string;
32
+ /**
33
+ * Adds media management to the Airdraft CMS.
34
+ *
35
+ * Registers four routes:
36
+ * POST /media/upload
37
+ * GET /media
38
+ * DELETE /media/:key
39
+ * GET /media/:key/url
40
+ *
41
+ * Also implements `hooks.transformEntry` to inject `{field}_url` companion
42
+ * fields for every `image`-type field in a collection.
43
+ *
44
+ * ```ts
45
+ * import { withMedia } from '@airdraft/plugin-media'
46
+ * import { LocalMediaAdapter } from '@airdraft/media-adapter-local'
47
+ *
48
+ * plugins: [
49
+ * withMedia({
50
+ * adapter: new LocalMediaAdapter({ root: process.cwd() + '/public' }),
51
+ * allowedTypes: ['image/jpeg', 'image/png', 'image/webp'],
52
+ * maxSize: 5 * 1024 * 1024,
53
+ * }),
54
+ * ]
55
+ * ```
56
+ */
57
+ export declare function withMedia(options: WithMediaOptions): Plugin;
58
+ export { defaultGenerateKey, sanitizeName, hash4 };
59
+ //# sourceMappingURL=withMedia.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"withMedia.d.ts","sourceRoot":"","sources":["../src/withMedia.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,MAAM,EACN,YAAY,EACZ,cAAc,EACd,iBAAiB,EAIlB,MAAM,gBAAgB,CAAA;AAMvB,MAAM,WAAW,gBAAgB;IAC/B,qEAAqE;IACrE,OAAO,EAAE,YAAY,CAAA;IACrB;;;;OAIG;IACH,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,6EAA6E;IAC7E,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAA;IAC5E,6FAA6F;IAC7F,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB,wFAAwF;IACxF,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAGD,YAAY,EAAE,iBAAiB,EAAE,CAAA;AA2BjC,iBAAS,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK1C;AAED,iBAAS,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEpC;AAED,iBAAS,kBAAkB,CACzB,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAClD,MAAM,EAAE,MAAM,GACb,MAAM,CAcR;AAwBD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CA6b3D;AAMD,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,KAAK,EAAE,CAAA"}
@@ -0,0 +1,510 @@
1
+ import { createHash } from 'node:crypto';
2
+ // ---------------------------------------------------------------------------
3
+ // Sidecar helpers
4
+ // ---------------------------------------------------------------------------
5
+ function sidecarPath(key) {
6
+ return '_media/' + key + '.json';
7
+ }
8
+ /** Normalise tag values: trim, lowercase, spaces/underscores → hyphens, max 50 chars, dedupe. */
9
+ function normalizeTags(tags) {
10
+ if (!Array.isArray(tags))
11
+ return undefined;
12
+ const seen = new Set();
13
+ const result = [];
14
+ for (const t of tags) {
15
+ if (typeof t !== 'string')
16
+ continue;
17
+ const normalized = t.trim().toLowerCase().replace(/[\s_]+/g, '-').slice(0, 50);
18
+ if (normalized && !seen.has(normalized)) {
19
+ seen.add(normalized);
20
+ result.push(normalized);
21
+ }
22
+ }
23
+ return result.length > 0 ? result : undefined;
24
+ }
25
+ function sanitizeName(name) {
26
+ return name
27
+ .replace(/[/\\]/g, '') // strip path separators
28
+ .replace(/[^a-zA-Z0-9._-]/g, '_') // replace unsafe chars
29
+ .toLowerCase();
30
+ }
31
+ function hash4(input) {
32
+ return createHash('sha1').update(input).digest('hex').slice(0, 4);
33
+ }
34
+ function defaultGenerateKey(file, prefix) {
35
+ const now = new Date();
36
+ const yyyy = now.getUTCFullYear();
37
+ const mm = String(now.getUTCMonth() + 1).padStart(2, '0');
38
+ const lastDot = file.name.lastIndexOf('.');
39
+ const stem = lastDot === -1 ? file.name : file.name.slice(0, lastDot);
40
+ const ext = lastDot === -1 ? '' : file.name.slice(lastDot + 1).toLowerCase();
41
+ const safeStem = sanitizeName(stem);
42
+ const h = hash4(file.name + Date.now());
43
+ const filename = ext ? `${safeStem}-${h}.${ext}` : `${safeStem}-${h}`;
44
+ return `${prefix}/${yyyy}/${mm}/${filename}`;
45
+ }
46
+ // ---------------------------------------------------------------------------
47
+ // Error helpers
48
+ // ---------------------------------------------------------------------------
49
+ function errorRes(status, code, message) {
50
+ return new Response(JSON.stringify({ error: { code, message, details: {} } }), { status, headers: { 'Content-Type': 'application/json' } });
51
+ }
52
+ function jsonRes(data, status = 200) {
53
+ return new Response(JSON.stringify(data), {
54
+ status,
55
+ headers: { 'Content-Type': 'application/json' },
56
+ });
57
+ }
58
+ // ---------------------------------------------------------------------------
59
+ // withMedia
60
+ // ---------------------------------------------------------------------------
61
+ /**
62
+ * Adds media management to the Airdraft CMS.
63
+ *
64
+ * Registers four routes:
65
+ * POST /media/upload
66
+ * GET /media
67
+ * DELETE /media/:key
68
+ * GET /media/:key/url
69
+ *
70
+ * Also implements `hooks.transformEntry` to inject `{field}_url` companion
71
+ * fields for every `image`-type field in a collection.
72
+ *
73
+ * ```ts
74
+ * import { withMedia } from '@airdraft/plugin-media'
75
+ * import { LocalMediaAdapter } from '@airdraft/media-adapter-local'
76
+ *
77
+ * plugins: [
78
+ * withMedia({
79
+ * adapter: new LocalMediaAdapter({ root: process.cwd() + '/public' }),
80
+ * allowedTypes: ['image/jpeg', 'image/png', 'image/webp'],
81
+ * maxSize: 5 * 1024 * 1024,
82
+ * }),
83
+ * ]
84
+ * ```
85
+ */
86
+ export function withMedia(options) {
87
+ const { adapter, storageAdapter, prefix = 'uploads', allowedTypes, maxSize } = options;
88
+ const genKey = options.generateKey
89
+ ? (file) => options.generateKey(file)
90
+ : (file) => defaultGenerateKey(file, prefix);
91
+ // ── POST /media/upload ───────────────────────────────────────────────────
92
+ async function handleUpload(req) {
93
+ if (req.method !== 'POST') {
94
+ return errorRes(405, 'METHOD_NOT_ALLOWED', 'Use POST /media/upload');
95
+ }
96
+ let formData;
97
+ try {
98
+ formData = await req.formData();
99
+ }
100
+ catch {
101
+ return errorRes(400, 'INVALID_REQUEST', 'Request must be multipart/form-data');
102
+ }
103
+ const file = formData.get('file');
104
+ if (!file || !(file instanceof File)) {
105
+ return errorRes(400, 'INVALID_REQUEST', 'Missing or invalid "file" field in form data');
106
+ }
107
+ if (allowedTypes && !allowedTypes.includes(file.type)) {
108
+ return errorRes(415, 'UNSUPPORTED_TYPE', `File type "${file.type}" is not allowed`);
109
+ }
110
+ if (maxSize !== undefined && file.size > maxSize) {
111
+ return errorRes(413, 'FILE_TOO_LARGE', `File exceeds maximum size of ${maxSize} bytes`);
112
+ }
113
+ const key = genKey({ name: file.name, type: file.type, size: file.size });
114
+ let result;
115
+ try {
116
+ result = await adapter.upload(key, file, { mimeType: file.type });
117
+ }
118
+ catch (err) {
119
+ console.error('[airdraft/plugin-media] Upload failed:', err);
120
+ return errorRes(502, 'UPLOAD_FAILED', 'Upload to storage adapter failed');
121
+ }
122
+ // Library mode: write sidecar (best-effort)
123
+ if (storageAdapter) {
124
+ const warnings = [];
125
+ const uploadedAt = new Date().toISOString();
126
+ const sidecarData = {
127
+ key,
128
+ name: file.name,
129
+ mimeType: file.type,
130
+ size: file.size,
131
+ uploadedAt,
132
+ ...(result.width != null ? { width: result.width } : {}),
133
+ ...(result.height != null ? { height: result.height } : {}),
134
+ };
135
+ try {
136
+ await storageAdapter.write(sidecarPath(key), JSON.stringify(sidecarData, null, 2), {
137
+ message: `chore: add media metadata for ${file.name}`,
138
+ });
139
+ }
140
+ catch (err) {
141
+ console.error('[airdraft/plugin-media] Sidecar write failed:', err);
142
+ warnings.push('metadata_save_failed');
143
+ }
144
+ const item = {
145
+ key,
146
+ name: file.name,
147
+ mimeType: file.type,
148
+ size: file.size,
149
+ uploadedAt,
150
+ url: result.url,
151
+ isIndexed: warnings.length === 0,
152
+ ...(result.width != null ? { width: result.width } : {}),
153
+ ...(result.height != null ? { height: result.height } : {}),
154
+ };
155
+ const body = { data: item };
156
+ if (warnings.length > 0)
157
+ body.warnings = warnings;
158
+ return jsonRes(body, 201);
159
+ }
160
+ return jsonRes({ data: result }, 201);
161
+ }
162
+ // ── GET /media ───────────────────────────────────────────────────────────
163
+ async function handleList(req) {
164
+ if (req.method !== 'GET') {
165
+ return errorRes(405, 'METHOD_NOT_ALLOWED', 'Use GET /media');
166
+ }
167
+ const url = new URL(req.url);
168
+ const listPrefix = url.searchParams.get('prefix') ?? undefined;
169
+ const limit = url.searchParams.has('limit')
170
+ ? parseInt(url.searchParams.get('limit'), 10)
171
+ : undefined;
172
+ const cursor = url.searchParams.get('cursor') ?? undefined;
173
+ const search = url.searchParams.get('search') ?? undefined;
174
+ const mimeTypeFilter = url.searchParams.get('mimeType') ?? undefined;
175
+ let result;
176
+ try {
177
+ result = await adapter.list({ prefix: listPrefix, limit, cursor });
178
+ }
179
+ catch (err) {
180
+ const msg = err instanceof Error ? err.message : 'Failed to list media';
181
+ return errorRes(502, 'ADAPTER_ERROR', msg);
182
+ }
183
+ // Without library mode: return MediaListItem-shaped items with isIndexed: false
184
+ if (!storageAdapter) {
185
+ return jsonRes({
186
+ data: result.items.map(item => ({
187
+ ...item,
188
+ uploadedAt: item.lastModified ?? '',
189
+ isIndexed: false,
190
+ })),
191
+ meta: { ...(result.cursor ? { cursor: result.cursor } : {}) },
192
+ });
193
+ }
194
+ // Library mode: enrich each item with sidecar data in parallel
195
+ const settled = await Promise.allSettled(result.items.map(async (item) => {
196
+ try {
197
+ const sidecarFile = await storageAdapter.read(sidecarPath(item.key));
198
+ if (sidecarFile) {
199
+ const meta = JSON.parse(sidecarFile.content);
200
+ return {
201
+ key: item.key,
202
+ name: typeof meta.name === 'string' ? meta.name : item.name,
203
+ mimeType: item.mimeType,
204
+ size: item.size,
205
+ uploadedAt: typeof meta.uploadedAt === 'string' ? meta.uploadedAt : (item.lastModified ?? ''),
206
+ url: item.url,
207
+ isIndexed: true,
208
+ ...(typeof meta.alt === 'string' ? { alt: meta.alt } : {}),
209
+ ...(typeof meta.caption === 'string' ? { caption: meta.caption } : {}),
210
+ ...(typeof meta.title === 'string' ? { title: meta.title } : {}),
211
+ ...(Array.isArray(meta.tags) ? { tags: meta.tags } : {}),
212
+ ...(typeof meta.width === 'number' ? { width: meta.width } : {}),
213
+ ...(typeof meta.height === 'number' ? { height: meta.height } : {}),
214
+ ...(typeof meta.uploadedBy === 'string' ? { uploadedBy: meta.uploadedBy } : {}),
215
+ };
216
+ }
217
+ }
218
+ catch {
219
+ // sidecar read failure → treat as ghost
220
+ }
221
+ return {
222
+ key: item.key,
223
+ name: item.name,
224
+ mimeType: item.mimeType,
225
+ size: item.size,
226
+ uploadedAt: item.lastModified ?? '',
227
+ url: item.url,
228
+ isIndexed: false,
229
+ };
230
+ }));
231
+ let items = settled
232
+ .map(r => (r.status === 'fulfilled' ? r.value : null))
233
+ .filter((i) => i !== null);
234
+ if (mimeTypeFilter) {
235
+ items = items.filter(i => mimeTypeFilter.endsWith('/')
236
+ ? i.mimeType.startsWith(mimeTypeFilter)
237
+ : i.mimeType === mimeTypeFilter);
238
+ }
239
+ if (search) {
240
+ const lower = search.toLowerCase();
241
+ items = items.filter(i => i.name.toLowerCase().includes(lower) ||
242
+ (i.alt ?? '').toLowerCase().includes(lower) ||
243
+ (i.caption ?? '').toLowerCase().includes(lower) ||
244
+ (i.title ?? '').toLowerCase().includes(lower));
245
+ }
246
+ return jsonRes({
247
+ data: items,
248
+ meta: { ...(result.cursor ? { cursor: result.cursor } : {}) },
249
+ });
250
+ }
251
+ // ── GET /media/:key ──────────────────────────────────────────────────────
252
+ async function handleGet(_req, key) {
253
+ if (!storageAdapter) {
254
+ return errorRes(501, 'NOT_IMPLEMENTED', 'Library mode requires storageAdapter to be configured');
255
+ }
256
+ let sidecarFile = null;
257
+ try {
258
+ sidecarFile = await storageAdapter.read(sidecarPath(key));
259
+ }
260
+ catch {
261
+ // no sidecar — ghost file
262
+ }
263
+ let resolvedUrl;
264
+ try {
265
+ resolvedUrl = await adapter.url(key);
266
+ }
267
+ catch {
268
+ return errorRes(404, 'NOT_FOUND', `Media key "${key}" not found`);
269
+ }
270
+ if (!sidecarFile) {
271
+ const item = {
272
+ key,
273
+ name: key.split('/').pop() ?? key,
274
+ mimeType: 'application/octet-stream',
275
+ size: 0,
276
+ uploadedAt: '',
277
+ url: resolvedUrl,
278
+ isIndexed: false,
279
+ };
280
+ return jsonRes({ data: item });
281
+ }
282
+ const meta = JSON.parse(sidecarFile.content);
283
+ const item = {
284
+ key,
285
+ name: typeof meta.name === 'string' ? meta.name : key,
286
+ mimeType: typeof meta.mimeType === 'string' ? meta.mimeType : 'application/octet-stream',
287
+ size: typeof meta.size === 'number' ? meta.size : 0,
288
+ uploadedAt: typeof meta.uploadedAt === 'string' ? meta.uploadedAt : '',
289
+ url: resolvedUrl,
290
+ isIndexed: true,
291
+ ...(typeof meta.alt === 'string' ? { alt: meta.alt } : {}),
292
+ ...(typeof meta.caption === 'string' ? { caption: meta.caption } : {}),
293
+ ...(typeof meta.title === 'string' ? { title: meta.title } : {}),
294
+ ...(Array.isArray(meta.tags) ? { tags: meta.tags } : {}),
295
+ ...(typeof meta.width === 'number' ? { width: meta.width } : {}),
296
+ ...(typeof meta.height === 'number' ? { height: meta.height } : {}),
297
+ ...(typeof meta.uploadedBy === 'string' ? { uploadedBy: meta.uploadedBy } : {}),
298
+ };
299
+ return jsonRes({ data: item });
300
+ }
301
+ // ── PATCH /media/:key ────────────────────────────────────────────────────
302
+ async function handlePatch(req, key) {
303
+ if (!storageAdapter) {
304
+ return errorRes(501, 'NOT_IMPLEMENTED', 'Library mode requires storageAdapter to be configured');
305
+ }
306
+ let patch;
307
+ try {
308
+ patch = await req.json();
309
+ }
310
+ catch {
311
+ return errorRes(400, 'INVALID_REQUEST', 'Request body must be valid JSON');
312
+ }
313
+ // Read existing sidecar for read-modify-write (GitHubAdapter requires sha)
314
+ let existing = null;
315
+ try {
316
+ existing = await storageAdapter.read(sidecarPath(key));
317
+ }
318
+ catch {
319
+ // no existing sidecar — creating from scratch
320
+ }
321
+ const current = existing
322
+ ? JSON.parse(existing.content)
323
+ : { key, uploadedAt: new Date().toISOString() };
324
+ // Apply patch — only editable fields; null clears the field
325
+ const editableFields = ['alt', 'caption', 'title', 'tags'];
326
+ for (const field of editableFields) {
327
+ if (!(field in patch))
328
+ continue;
329
+ if (patch[field] === null) {
330
+ delete current[field];
331
+ }
332
+ else if (field === 'tags') {
333
+ const normalized = normalizeTags(patch[field]);
334
+ if (normalized)
335
+ current[field] = normalized;
336
+ else
337
+ delete current[field];
338
+ }
339
+ else if (typeof patch[field] === 'string') {
340
+ current[field] = patch[field];
341
+ }
342
+ }
343
+ try {
344
+ await storageAdapter.write(sidecarPath(key), JSON.stringify(current, null, 2), {
345
+ message: `chore: update media metadata for ${key}`,
346
+ sha: existing?.sha,
347
+ });
348
+ }
349
+ catch (err) {
350
+ console.error('[airdraft/plugin-media] Sidecar patch failed:', err);
351
+ return errorRes(502, 'UPLOAD_FAILED', 'Failed to persist metadata update');
352
+ }
353
+ let resolvedUrl;
354
+ try {
355
+ resolvedUrl = await adapter.url(key);
356
+ }
357
+ catch {
358
+ return errorRes(404, 'NOT_FOUND', `Media key "${key}" not found`);
359
+ }
360
+ const item = {
361
+ key,
362
+ name: typeof current.name === 'string' ? current.name : key,
363
+ mimeType: typeof current.mimeType === 'string' ? current.mimeType : 'application/octet-stream',
364
+ size: typeof current.size === 'number' ? current.size : 0,
365
+ uploadedAt: typeof current.uploadedAt === 'string' ? current.uploadedAt : '',
366
+ url: resolvedUrl,
367
+ isIndexed: true,
368
+ ...(typeof current.alt === 'string' ? { alt: current.alt } : {}),
369
+ ...(typeof current.caption === 'string' ? { caption: current.caption } : {}),
370
+ ...(typeof current.title === 'string' ? { title: current.title } : {}),
371
+ ...(Array.isArray(current.tags) ? { tags: current.tags } : {}),
372
+ ...(typeof current.width === 'number' ? { width: current.width } : {}),
373
+ ...(typeof current.height === 'number' ? { height: current.height } : {}),
374
+ ...(typeof current.uploadedBy === 'string' ? { uploadedBy: current.uploadedBy } : {}),
375
+ };
376
+ return jsonRes({ data: item });
377
+ }
378
+ // ── DELETE /media/:key ───────────────────────────────────────────────────
379
+ async function handleDelete(_req, key) {
380
+ // Read sidecar sha before deletion (GitHubAdapter requires sha for delete)
381
+ let sidecarFile = null;
382
+ if (storageAdapter) {
383
+ try {
384
+ sidecarFile = await storageAdapter.read(sidecarPath(key));
385
+ }
386
+ catch {
387
+ // no sidecar — nothing to delete
388
+ }
389
+ }
390
+ try {
391
+ await adapter.delete(key);
392
+ }
393
+ catch (err) {
394
+ const msg = err instanceof Error ? err.message : String(err);
395
+ if (msg.includes('not found') || msg.includes('ENOENT') || msg.includes('NoSuchKey')) {
396
+ return errorRes(404, 'NOT_FOUND', `Media key "${key}" not found`);
397
+ }
398
+ console.error('[airdraft/plugin-media] Delete failed:', err);
399
+ return errorRes(502, 'DELETE_FAILED', 'Delete from storage adapter failed');
400
+ }
401
+ // Best-effort sidecar delete
402
+ if (storageAdapter && sidecarFile) {
403
+ try {
404
+ await storageAdapter.delete(sidecarPath(key), {
405
+ message: `chore: remove media metadata for ${key}`,
406
+ sha: sidecarFile.sha,
407
+ });
408
+ }
409
+ catch (err) {
410
+ console.error('[airdraft/plugin-media] Sidecar delete failed:', err);
411
+ }
412
+ }
413
+ return new Response(null, { status: 204 });
414
+ }
415
+ // ── GET /media/:key/url ──────────────────────────────────────────────────
416
+ async function handleUrl(req, key) {
417
+ if (req.method !== 'GET') {
418
+ return errorRes(405, 'METHOD_NOT_ALLOWED', 'Use GET /media/:key/url');
419
+ }
420
+ const url = await adapter.url(key);
421
+ return new Response(JSON.stringify({ data: { url } }), {
422
+ status: 200,
423
+ headers: { 'Content-Type': 'application/json' },
424
+ });
425
+ }
426
+ // ── transformEntry hook ──────────────────────────────────────────────────
427
+ async function transformEntry(entry, collection) {
428
+ const imageFields = Object.entries(collection.fields)
429
+ .filter(([, f]) => f.type === 'image')
430
+ .map(([name]) => name);
431
+ if (imageFields.length === 0)
432
+ return entry;
433
+ const updatedData = { ...entry.data };
434
+ for (const field of imageFields) {
435
+ const value = entry.data[field];
436
+ if (typeof value !== 'string' || !value)
437
+ continue;
438
+ // URL detection: already-resolved values pass through unchanged
439
+ const isResolved = value.startsWith('http://') ||
440
+ value.startsWith('https://') ||
441
+ value.startsWith('/');
442
+ const resolvedUrl = isResolved ? value : await adapter.url(value);
443
+ updatedData[`${field}_url`] = resolvedUrl;
444
+ // Sidecar enrichment — library mode only
445
+ if (!isResolved && storageAdapter) {
446
+ try {
447
+ const sidecarFile = await storageAdapter.read(sidecarPath(value));
448
+ if (sidecarFile) {
449
+ const meta = JSON.parse(sidecarFile.content);
450
+ const mediaObj = {
451
+ key: value,
452
+ url: resolvedUrl,
453
+ name: typeof meta.name === 'string' ? meta.name : value,
454
+ mimeType: typeof meta.mimeType === 'string' ? meta.mimeType : '',
455
+ size: typeof meta.size === 'number' ? meta.size : 0,
456
+ uploadedAt: typeof meta.uploadedAt === 'string' ? meta.uploadedAt : '',
457
+ };
458
+ if (typeof meta.alt === 'string')
459
+ mediaObj.alt = meta.alt;
460
+ if (typeof meta.caption === 'string')
461
+ mediaObj.caption = meta.caption;
462
+ if (typeof meta.title === 'string')
463
+ mediaObj.title = meta.title;
464
+ if (Array.isArray(meta.tags))
465
+ mediaObj.tags = meta.tags;
466
+ if (typeof meta.width === 'number')
467
+ mediaObj.width = meta.width;
468
+ if (typeof meta.height === 'number')
469
+ mediaObj.height = meta.height;
470
+ updatedData[`${field}_media`] = mediaObj;
471
+ }
472
+ }
473
+ catch {
474
+ // sidecar read failure is non-fatal; {field}_url is still injected
475
+ }
476
+ }
477
+ }
478
+ return { ...entry, data: updatedData };
479
+ }
480
+ // ── Plugin registration ──────────────────────────────────────────────────
481
+ return {
482
+ name: 'media',
483
+ routes: {
484
+ '/media/upload': async (req) => handleUpload(req),
485
+ '/media': async (req) => handleList(req),
486
+ '/media/:key/url': async (req) => {
487
+ const key = decodeURIComponent(new URL(req.url).pathname.split('/media/')[1]?.replace(/\/url$/, '') ?? '');
488
+ return handleUrl(req, key);
489
+ },
490
+ '/media/:key': async (req) => {
491
+ const key = decodeURIComponent(new URL(req.url).pathname.split('/media/')[1] ?? '');
492
+ if (req.method === 'GET')
493
+ return handleGet(req, key);
494
+ if (req.method === 'PATCH')
495
+ return handlePatch(req, key);
496
+ if (req.method === 'DELETE')
497
+ return handleDelete(req, key);
498
+ return errorRes(405, 'METHOD_NOT_ALLOWED', 'Allowed: GET, PATCH, DELETE');
499
+ },
500
+ },
501
+ hooks: {
502
+ transformEntry,
503
+ },
504
+ };
505
+ }
506
+ // ---------------------------------------------------------------------------
507
+ // Helpers (exported for testing)
508
+ // ---------------------------------------------------------------------------
509
+ export { defaultGenerateKey, sanitizeName, hash4 };
510
+ //# sourceMappingURL=withMedia.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"withMedia.js","sourceRoot":"","sources":["../src/withMedia.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@airdraft/plugin-media",
3
+ "version": "0.2.0",
4
+ "description": "Airdraft media plugin — image upload, optimisation, CDN",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": ["dist", "README.md", "CHANGELOG.md"],
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "dev": "tsc --watch",
18
+ "clean": "rm -rf dist",
19
+ "test": "vitest run",
20
+ "test:watch": "vitest",
21
+ "typecheck": "tsc --noEmit",
22
+ "prepublishOnly": "npm run build",
23
+ "release": "standard-version",
24
+ "release:patch": "standard-version --release-as patch",
25
+ "release:minor": "standard-version --release-as minor",
26
+ "release:major": "standard-version --release-as major"
27
+ },
28
+ "publishConfig": { "access": "public" },
29
+ "license": "MIT",
30
+ "devDependencies": {
31
+ "@types/node": "^20.0.0",
32
+ "standard-version": "^9.5.0",
33
+ "tsx": "^4.7.0",
34
+ "typescript": "^5.4.0",
35
+ "vitest": "^1.5.0"
36
+ },
37
+ "dependencies": {
38
+ "@airdraft/core": "*"
39
+ },
40
+ "engines": { "node": ">=18.0.0" }
41
+ }