@rakun-kit/core 1.7.0 → 1.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -33
- package/dist/cjs/media/index.js +1 -0
- package/dist/cjs/media/index.js.map +1 -1
- package/dist/cjs/media/publicMedia.js +114 -0
- package/dist/cjs/media/publicMedia.js.map +1 -0
- package/dist/docs/index.md +4 -0
- package/dist/esm/media/adapters/index.d.ts +20 -0
- package/dist/esm/media/adapters/index.d.ts.map +1 -1
- package/dist/esm/media/index.d.ts +1 -0
- package/dist/esm/media/index.d.ts.map +1 -1
- package/dist/esm/media/index.js +1 -0
- package/dist/esm/media/index.js.map +1 -1
- package/dist/esm/media/publicMedia.d.ts +7 -0
- package/dist/esm/media/publicMedia.d.ts.map +1 -0
- package/dist/esm/media/publicMedia.js +109 -0
- package/dist/esm/media/publicMedia.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -90,16 +90,16 @@ rakunBootstrap({
|
|
|
90
90
|
})
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
-
The default image processor is native `Bun.Image` when available and `sharp`
|
|
94
|
-
otherwise. Node.js image optimization therefore requires the optional `sharp`
|
|
95
|
-
peer. Bun also falls back to it when an OS-dependent codec cannot handle the
|
|
96
|
-
requested format. Custom `ImageProcessor` implementations provide
|
|
97
|
-
`metadata`, `transform`, and `placeholder`; the latter returns an inline
|
|
98
|
-
`{ dataUrl, mime }` LQIP. Bun uses native `Bun.Image.placeholder()`, while
|
|
99
|
-
Sharp produces the placeholder through its normal reduced transform and serves
|
|
100
|
-
as the fallback when the Bun method is unavailable. The
|
|
101
|
-
platform resolves crypto, filesystem, compression,
|
|
102
|
-
workers, and realtime capabilities. Polling is the safe realtime default when
|
|
93
|
+
The default image processor is native `Bun.Image` when available and `sharp`
|
|
94
|
+
otherwise. Node.js image optimization therefore requires the optional `sharp`
|
|
95
|
+
peer. Bun also falls back to it when an OS-dependent codec cannot handle the
|
|
96
|
+
requested format. Custom `ImageProcessor` implementations provide
|
|
97
|
+
`metadata`, `transform`, and `placeholder`; the latter returns an inline
|
|
98
|
+
`{ dataUrl, mime }` LQIP. Bun uses native `Bun.Image.placeholder()`, while
|
|
99
|
+
Sharp produces the placeholder through its normal reduced transform and serves
|
|
100
|
+
as the fallback when the Bun method is unavailable. The
|
|
101
|
+
platform resolves crypto, filesystem, compression,
|
|
102
|
+
workers, and realtime capabilities. Polling is the safe realtime default when
|
|
103
103
|
the host cannot keep persistent connections open. The Next and Express
|
|
104
104
|
adapters automatically serve configured SSE streams.
|
|
105
105
|
Calling `sseRealtime()` uses the API-relative `/realtime` endpoint; pass an
|
|
@@ -127,12 +127,12 @@ keyed by its content type and `_id`. Editor updates synchronize through the
|
|
|
127
127
|
authenticated `manager.contentCollaboration.sync` operation without changing
|
|
128
128
|
the MongoDB content snapshot or triggering revalidation. Save calls
|
|
129
129
|
`manager.contentCollaboration.save`, which materializes and validates the
|
|
130
|
-
server-side CRDT state before using the normal update and revalidation flow.
|
|
131
|
-
Draft promotion remains separate and promotes only a saved draft snapshot.
|
|
132
|
-
`manager.contentCollaboration.discard` restores the room from that persisted
|
|
133
|
-
snapshot, publishes the reset to connected editors, and marks the restored Yjs
|
|
134
|
-
state as saved without creating a new content revision. Shared templates expose
|
|
135
|
-
the equivalent `manager.templateCollaboration.discard` operation.
|
|
130
|
+
server-side CRDT state before using the normal update and revalidation flow.
|
|
131
|
+
Draft promotion remains separate and promotes only a saved draft snapshot.
|
|
132
|
+
`manager.contentCollaboration.discard` restores the room from that persisted
|
|
133
|
+
snapshot, publishes the reset to connected editors, and marks the restored Yjs
|
|
134
|
+
state as saved without creating a new content revision. Shared templates expose
|
|
135
|
+
the equivalent `manager.templateCollaboration.discard` operation.
|
|
136
136
|
|
|
137
137
|
The default adapter keeps working documents in process memory. Configure a
|
|
138
138
|
shared, durable implementation for replicated or restart-durable deployments:
|
|
@@ -142,33 +142,33 @@ rakunBootstrap({
|
|
|
142
142
|
// ...
|
|
143
143
|
collaboration: {
|
|
144
144
|
adapter: {
|
|
145
|
-
load: async (roomId) => loadRoom(roomId),
|
|
146
|
-
save: async (roomId, state) => saveRoom(roomId, state),
|
|
147
|
-
loadPresence: async (roomId) => loadRoomPresence(roomId),
|
|
148
|
-
savePresence: async (roomId, presence) => saveRoomPresence(roomId, presence),
|
|
149
|
-
delete: async (roomId) => deleteRoom(roomId),
|
|
145
|
+
load: async (roomId) => loadRoom(roomId),
|
|
146
|
+
save: async (roomId, state) => saveRoom(roomId, state),
|
|
147
|
+
loadPresence: async (roomId) => loadRoomPresence(roomId),
|
|
148
|
+
savePresence: async (roomId, presence) => saveRoomPresence(roomId, presence),
|
|
149
|
+
delete: async (roomId) => deleteRoom(roomId),
|
|
150
150
|
},
|
|
151
151
|
},
|
|
152
152
|
})
|
|
153
153
|
```
|
|
154
154
|
|
|
155
155
|
`state.update` and `state.savedStateVector` are opaque `Uint8Array` values.
|
|
156
|
-
Store them outside the public content record. The built-in manager applies this
|
|
156
|
+
Store them outside the public content record. The built-in manager applies this
|
|
157
157
|
to saved content edit screens and to each content type's shared Template.
|
|
158
158
|
Templates use their own `template:<contentType>` room rather than an individual
|
|
159
159
|
document room. Settings, route-layout overrides, and other administrative forms
|
|
160
160
|
remain local. Translation changes join the working document and are persisted
|
|
161
|
-
only by Save.
|
|
162
|
-
|
|
163
|
-
The sync response also includes ephemeral viewers keyed by browser-tab client
|
|
164
|
-
id, including the focused field. Presence expires automatically and is not
|
|
165
|
-
part of `state.update`, `state.savedStateVector`, or the persistent event log.
|
|
166
|
-
With SSE, the authenticated subscription owns the tab presence: server
|
|
167
|
-
heartbeats renew it and closing the last stream for that tab removes it, so the
|
|
168
|
-
manager does not send a periodic collaboration sync request just to stay
|
|
169
|
-
visible. Polling refreshes presence through its normal sync cycle.
|
|
170
|
-
`loadPresence` and `savePresence` are optional; implement both in replicated
|
|
171
|
-
deployments that need presence shared across processes.
|
|
161
|
+
only by Save.
|
|
162
|
+
|
|
163
|
+
The sync response also includes ephemeral viewers keyed by browser-tab client
|
|
164
|
+
id, including the focused field. Presence expires automatically and is not
|
|
165
|
+
part of `state.update`, `state.savedStateVector`, or the persistent event log.
|
|
166
|
+
With SSE, the authenticated subscription owns the tab presence: server
|
|
167
|
+
heartbeats renew it and closing the last stream for that tab removes it, so the
|
|
168
|
+
manager does not send a periodic collaboration sync request just to stay
|
|
169
|
+
visible. Polling refreshes presence through its normal sync cycle.
|
|
170
|
+
`loadPresence` and `savePresence` are optional; implement both in replicated
|
|
171
|
+
deployments that need presence shared across processes.
|
|
172
172
|
|
|
173
173
|
`@rakun-kit/manager-react` additionally stores these Yjs rooms per user in
|
|
174
174
|
IndexedDB, allowing cached content and Template fields to remain editable during
|
|
@@ -1155,6 +1155,14 @@ APIs:
|
|
|
1155
1155
|
|
|
1156
1156
|
The service supports prepare/finalize upload, URL generation, folders, and media optimization depending on adapter/configuration. Manager uploads encode original file names for transport, so Unicode names (including accents, non-Latin scripts, and emoji) are preserved without placing invalid characters in HTTP headers.
|
|
1157
1157
|
|
|
1158
|
+
Adapters can implement `getPublicObject` to let every Rakun server adapter proxy
|
|
1159
|
+
public media at its normal `/media/<key>` API route. This keeps browser
|
|
1160
|
+
URLs stable even when the object store is private or only supports expiring
|
|
1161
|
+
presigned URLs. The core handler validates the key under `public/`, forwards
|
|
1162
|
+
byte ranges, preserves object metadata, and applies long-lived caching by
|
|
1163
|
+
default. The storage adapter receives server-side credentials; never expose its
|
|
1164
|
+
presigned storage URL as the public media URL.
|
|
1165
|
+
|
|
1158
1166
|
Optimized video uploads use the `ffmpeg-static` peer dependency and produce an MP4 primary object plus MP4 and WebM entries in `sources`. Existing image-only optimize options remain compatible; use `video: { quality: 80 }` to configure video quality explicitly.
|
|
1159
1167
|
|
|
1160
1168
|
Existing images and videos can be reimported from the media manager with the selected optimization settings. The replacement uses new storage keys and updates the existing `Media` record only after every requested variant has been written, preserving its ID and content references. Preview generation stores a compact `data:image/...` string on `previewUrl` for LQIP use in `@rakun-kit/react` `Image`, instead of writing a separate preview object to storage.
|
package/dist/cjs/media/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/media/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAoBA,gDAWC;AAED,0CAYC;AA5CD,iDAGwB;AASxB,IAAI,aAA2B,CAAC;AAChC,IAAI,OAA2B,CAAC;AAEzB,MAAM,qBAAqB,GAAG,CAAC,MAA0B,EAAE,EAAE;IAClE,OAAO,GAAG,MAAM,CAAC;AACnB,CAAC,CAAC;AAFW,QAAA,qBAAqB,yBAEhC;AAEF,SAAgB,kBAAkB,CAAC,MAA0B;IAC3D,OAAO,GAAG,MAAM,CAAC;IAEjB,aAAa,GAAG,IAAA,4CAA6B,EAAC;QAC5C,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,0BAA0B,EAAE,MAAM,CAAC,0BAA0B;QAC7D,SAAS,EAAE,MAAM,CAAC,SAAS;KAC5B,CAAC,CAAC;IAEH,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,SAAgB,eAAe;IAC7B,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,kEAAkE,CACnE,CAAC;QACJ,CAAC;QAED,OAAO,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,iDAA+B;AAC/B,6CAA2B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/media/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAoBA,gDAWC;AAED,0CAYC;AA5CD,iDAGwB;AASxB,IAAI,aAA2B,CAAC;AAChC,IAAI,OAA2B,CAAC;AAEzB,MAAM,qBAAqB,GAAG,CAAC,MAA0B,EAAE,EAAE;IAClE,OAAO,GAAG,MAAM,CAAC;AACnB,CAAC,CAAC;AAFW,QAAA,qBAAqB,yBAEhC;AAEF,SAAgB,kBAAkB,CAAC,MAA0B;IAC3D,OAAO,GAAG,MAAM,CAAC;IAEjB,aAAa,GAAG,IAAA,4CAA6B,EAAC;QAC5C,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,0BAA0B,EAAE,MAAM,CAAC,0BAA0B;QAC7D,SAAS,EAAE,MAAM,CAAC,SAAS;KAC5B,CAAC,CAAC;IAEH,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,SAAgB,eAAe;IAC7B,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,kEAAkE,CACnE,CAAC;QACJ,CAAC;QAED,OAAO,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,iDAA+B;AAC/B,6CAA2B;AAC3B,gDAA6B"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handlePublicMediaRequest = exports.getPublicMediaKey = void 0;
|
|
4
|
+
const index_1 = require("./index");
|
|
5
|
+
const DEFAULT_CACHE_CONTROL = 'public, max-age=31536000, immutable';
|
|
6
|
+
const decodePathSegment = (segment) => {
|
|
7
|
+
try {
|
|
8
|
+
const value = decodeURIComponent(segment);
|
|
9
|
+
if (!value || value === '.' || value === '..' || value.includes('/'))
|
|
10
|
+
return null;
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
const getPublicMediaKey = (pathSegments) => {
|
|
18
|
+
if (pathSegments.length === 0)
|
|
19
|
+
return null;
|
|
20
|
+
const segments = pathSegments.map(decodePathSegment);
|
|
21
|
+
if (segments.some((segment) => segment === null))
|
|
22
|
+
return null;
|
|
23
|
+
return `public/${segments.join('/')}`;
|
|
24
|
+
};
|
|
25
|
+
exports.getPublicMediaKey = getPublicMediaKey;
|
|
26
|
+
const errorResponse = (status) => new Response(null, { status });
|
|
27
|
+
const isNotFoundError = (error) => {
|
|
28
|
+
if (!error || typeof error !== 'object')
|
|
29
|
+
return false;
|
|
30
|
+
const value = error;
|
|
31
|
+
return (value.name === 'NotFound' ||
|
|
32
|
+
value.name === 'NoSuchKey' ||
|
|
33
|
+
value.code === 'NotFound' ||
|
|
34
|
+
value.code === 'NoSuchKey' ||
|
|
35
|
+
value.$metadata?.httpStatusCode === 404);
|
|
36
|
+
};
|
|
37
|
+
const getErrorStatus = (error) => {
|
|
38
|
+
if (isNotFoundError(error))
|
|
39
|
+
return 404;
|
|
40
|
+
const status = error && typeof error === 'object'
|
|
41
|
+
? error.$metadata?.httpStatusCode
|
|
42
|
+
: undefined;
|
|
43
|
+
if (status === 416) {
|
|
44
|
+
return 416;
|
|
45
|
+
}
|
|
46
|
+
return 502;
|
|
47
|
+
};
|
|
48
|
+
const setDateHeader = (headers, name, value) => {
|
|
49
|
+
if (!value)
|
|
50
|
+
return;
|
|
51
|
+
headers.set(name, value instanceof Date ? value.toUTCString() : value);
|
|
52
|
+
};
|
|
53
|
+
const buildHeaders = (object) => {
|
|
54
|
+
const headers = new Headers({
|
|
55
|
+
'Cache-Control': object.cacheControl ?? DEFAULT_CACHE_CONTROL,
|
|
56
|
+
'X-Content-Type-Options': 'nosniff',
|
|
57
|
+
});
|
|
58
|
+
if (object.acceptRanges)
|
|
59
|
+
headers.set('Accept-Ranges', object.acceptRanges);
|
|
60
|
+
if (object.contentDisposition)
|
|
61
|
+
headers.set('Content-Disposition', object.contentDisposition);
|
|
62
|
+
if (object.contentEncoding)
|
|
63
|
+
headers.set('Content-Encoding', object.contentEncoding);
|
|
64
|
+
if (object.contentLanguage)
|
|
65
|
+
headers.set('Content-Language', object.contentLanguage);
|
|
66
|
+
if (object.contentLength !== undefined)
|
|
67
|
+
headers.set('Content-Length', String(object.contentLength));
|
|
68
|
+
if (object.contentRange)
|
|
69
|
+
headers.set('Content-Range', object.contentRange);
|
|
70
|
+
if (object.contentType)
|
|
71
|
+
headers.set('Content-Type', object.contentType);
|
|
72
|
+
if (object.etag)
|
|
73
|
+
headers.set('ETag', object.etag);
|
|
74
|
+
setDateHeader(headers, 'Expires', object.expires);
|
|
75
|
+
setDateHeader(headers, 'Last-Modified', object.lastModified);
|
|
76
|
+
return headers;
|
|
77
|
+
};
|
|
78
|
+
const handlePublicMediaRequest = async ({ request, pathSegments, }) => {
|
|
79
|
+
if (request.method !== 'GET' && request.method !== 'HEAD')
|
|
80
|
+
return null;
|
|
81
|
+
let adapter;
|
|
82
|
+
try {
|
|
83
|
+
adapter = (0, index_1.getMediaService)().rawAdapter;
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
if (!adapter.getPublicObject)
|
|
89
|
+
return null;
|
|
90
|
+
const key = (0, exports.getPublicMediaKey)(pathSegments);
|
|
91
|
+
if (!key)
|
|
92
|
+
return errorResponse(404);
|
|
93
|
+
try {
|
|
94
|
+
const object = await adapter.getPublicObject({
|
|
95
|
+
key,
|
|
96
|
+
method: request.method,
|
|
97
|
+
range: request.headers.get('Range') ?? undefined,
|
|
98
|
+
});
|
|
99
|
+
const headers = buildHeaders(object);
|
|
100
|
+
const status = object.status ?? (object.contentRange ? 206 : 200);
|
|
101
|
+
if (request.headers.get('If-None-Match') === object.etag) {
|
|
102
|
+
return new Response(null, { status: 304, headers });
|
|
103
|
+
}
|
|
104
|
+
return new Response(request.method === 'HEAD' ? null : object.body ?? null, {
|
|
105
|
+
status,
|
|
106
|
+
headers,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
return errorResponse(getErrorStatus(error));
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
exports.handlePublicMediaRequest = handlePublicMediaRequest;
|
|
114
|
+
//# sourceMappingURL=publicMedia.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publicMedia.js","sourceRoot":"","sources":["../../../src/media/publicMedia.ts"],"names":[],"mappings":"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"}
|
package/dist/docs/index.md
CHANGED
|
@@ -477,6 +477,10 @@ Core defines service contracts; concrete integrations are separate:
|
|
|
477
477
|
|
|
478
478
|
- Media: use `@rakun-kit/s3`, or local media from the selected framework
|
|
479
479
|
adapter. Configure the result as `media` in bootstrap.
|
|
480
|
+
- Storage adapters may expose `getPublicObject`; Next.js, Express and Bun then
|
|
481
|
+
serve public media through their normal `/media/<key>` API route. This
|
|
482
|
+
gives public Rakun media a stable application URL while the backing object
|
|
483
|
+
store remains private or uses expiring storage URLs.
|
|
480
484
|
- Mail: use `@rakun-kit/smtp` or `@rakun-kit/resend`; optionally render typed
|
|
481
485
|
templates with `@rakun-kit/jsx-email`. Configure delivery as `mail`.
|
|
482
486
|
- Translation: use `@rakun-kit/openai` or implement the core translation
|
|
@@ -4,6 +4,21 @@ export type PresignedPut = {
|
|
|
4
4
|
headers?: Record<string, string>;
|
|
5
5
|
key: string;
|
|
6
6
|
};
|
|
7
|
+
export type PublicMediaObject = {
|
|
8
|
+
body?: ReadableStream<Uint8Array>;
|
|
9
|
+
status?: number;
|
|
10
|
+
acceptRanges?: string;
|
|
11
|
+
cacheControl?: string;
|
|
12
|
+
contentDisposition?: string;
|
|
13
|
+
contentEncoding?: string;
|
|
14
|
+
contentLanguage?: string;
|
|
15
|
+
contentLength?: number;
|
|
16
|
+
contentRange?: string;
|
|
17
|
+
contentType?: string;
|
|
18
|
+
etag?: string;
|
|
19
|
+
expires?: Date | string;
|
|
20
|
+
lastModified?: Date | string;
|
|
21
|
+
};
|
|
7
22
|
export interface StorageAdapter {
|
|
8
23
|
createPresignedPut(input: {
|
|
9
24
|
key: string;
|
|
@@ -41,5 +56,10 @@ export interface StorageAdapter {
|
|
|
41
56
|
key: string;
|
|
42
57
|
access: MediaAccess;
|
|
43
58
|
}): string | null;
|
|
59
|
+
getPublicObject?(input: {
|
|
60
|
+
key: string;
|
|
61
|
+
method: 'GET' | 'HEAD';
|
|
62
|
+
range?: string;
|
|
63
|
+
}): Promise<PublicMediaObject>;
|
|
44
64
|
}
|
|
45
65
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/media/adapters/index.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAA;AAE9C,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,GAAG,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,MAAM,WAAW,cAAc;IAC7B,kBAAkB,CAAC,KAAK,EAAE;QACxB,GAAG,EAAE,MAAM,CAAA;QACX,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAA;QACZ,MAAM,EAAE,WAAW,CAAA;KACpB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;IAEzB,SAAS,CAAC,KAAK,EAAE;QACf,GAAG,EAAE,MAAM,CAAA;QACX,IAAI,EAAE,MAAM,CAAA;QACZ,OAAO,EAAE,UAAU,CAAA;QACnB,MAAM,EAAE,WAAW,CAAA;KACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAEjB,UAAU,CAAC,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC;QAC/D,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,IAAI,CAAC,EAAE,MAAM,CAAA;KACd,CAAC,CAAA;IAEF,kBAAkB,CAAC,KAAK,EAAE;QACxB,GAAG,EAAE,MAAM,CAAA;QACX,MAAM,EAAE,WAAW,CAAA;QACnB,gBAAgB,EAAE,MAAM,CAAA;KACzB,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,IAAI,CAAA;KAAE,CAAC,CAAA;IAE7C,YAAY,CAAC,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAExE,SAAS,CAAC,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,WAAW,CAAA;KAAE,GAAG,MAAM,GAAG,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/media/adapters/index.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAA;AAE9C,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,GAAG,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,CAAA;IACjC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,IAAI,GAAG,MAAM,CAAA;IACvB,YAAY,CAAC,EAAE,IAAI,GAAG,MAAM,CAAA;CAC7B,CAAA;AAED,MAAM,WAAW,cAAc;IAC7B,kBAAkB,CAAC,KAAK,EAAE;QACxB,GAAG,EAAE,MAAM,CAAA;QACX,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAA;QACZ,MAAM,EAAE,WAAW,CAAA;KACpB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;IAEzB,SAAS,CAAC,KAAK,EAAE;QACf,GAAG,EAAE,MAAM,CAAA;QACX,IAAI,EAAE,MAAM,CAAA;QACZ,OAAO,EAAE,UAAU,CAAA;QACnB,MAAM,EAAE,WAAW,CAAA;KACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAEjB,UAAU,CAAC,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC;QAC/D,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,IAAI,CAAC,EAAE,MAAM,CAAA;KACd,CAAC,CAAA;IAEF,kBAAkB,CAAC,KAAK,EAAE;QACxB,GAAG,EAAE,MAAM,CAAA;QACX,MAAM,EAAE,WAAW,CAAA;QACnB,gBAAgB,EAAE,MAAM,CAAA;KACzB,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,IAAI,CAAA;KAAE,CAAC,CAAA;IAE7C,YAAY,CAAC,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAExE,SAAS,CAAC,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,WAAW,CAAA;KAAE,GAAG,MAAM,GAAG,IAAI,CAAA;IAErE,eAAe,CAAC,CAAC,KAAK,EAAE;QACtB,GAAG,EAAE,MAAM,CAAA;QACX,MAAM,EAAE,KAAK,GAAG,MAAM,CAAA;QACtB,KAAK,CAAC,EAAE,MAAM,CAAA;KACf,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAA;CAC/B"}
|
|
@@ -11,4 +11,5 @@ export declare function createMediaService(config: MediaServiceConfig): MediaSer
|
|
|
11
11
|
export declare function getMediaService(): MediaService;
|
|
12
12
|
export * from "./mediaService.js";
|
|
13
13
|
export * from "./adapters/index.js";
|
|
14
|
+
export * from './publicMedia.js';
|
|
14
15
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/media/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAEL,KAAK,YAAY,EAClB,MAAM,gBAAgB,CAAC;AAExB,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,cAAc,CAAC;IACxB,aAAa,CAAC,EAAE,WAAW,CAAC;IAC5B,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAKF,eAAO,MAAM,qBAAqB,GAAI,QAAQ,kBAAkB,SAE/D,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG,YAAY,CAW3E;AAED,wBAAgB,eAAe,IAAI,YAAY,CAY9C;AAED,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/media/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAEL,KAAK,YAAY,EAClB,MAAM,gBAAgB,CAAC;AAExB,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,cAAc,CAAC;IACxB,aAAa,CAAC,EAAE,WAAW,CAAC;IAC5B,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAKF,eAAO,MAAM,qBAAqB,GAAI,QAAQ,kBAAkB,SAE/D,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG,YAAY,CAW3E;AAED,wBAAgB,eAAe,IAAI,YAAY,CAY9C;AAED,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAA"}
|
package/dist/esm/media/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/media/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,6BAA6B,GAE9B,MAAM,gBAAgB,CAAC;AASxB,IAAI,aAA2B,CAAC;AAChC,IAAI,OAA2B,CAAC;AAEhC,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,MAA0B,EAAE,EAAE;IAClE,OAAO,GAAG,MAAM,CAAC;AACnB,CAAC,CAAC;AAEF,MAAM,UAAU,kBAAkB,CAAC,MAA0B;IAC3D,OAAO,GAAG,MAAM,CAAC;IAEjB,aAAa,GAAG,6BAA6B,CAAC;QAC5C,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,0BAA0B,EAAE,MAAM,CAAC,0BAA0B;QAC7D,SAAS,EAAE,MAAM,CAAC,SAAS;KAC5B,CAAC,CAAC;IAEH,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,kEAAkE,CACnE,CAAC;QACJ,CAAC;QAED,OAAO,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/media/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,6BAA6B,GAE9B,MAAM,gBAAgB,CAAC;AASxB,IAAI,aAA2B,CAAC;AAChC,IAAI,OAA2B,CAAC;AAEhC,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,MAA0B,EAAE,EAAE;IAClE,OAAO,GAAG,MAAM,CAAC;AACnB,CAAC,CAAC;AAEF,MAAM,UAAU,kBAAkB,CAAC,MAA0B;IAC3D,OAAO,GAAG,MAAM,CAAC;IAEjB,aAAa,GAAG,6BAA6B,CAAC;QAC5C,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,0BAA0B,EAAE,MAAM,CAAC,0BAA0B;QAC7D,SAAS,EAAE,MAAM,CAAC,SAAS;KAC5B,CAAC,CAAC;IAEH,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,kEAAkE,CACnE,CAAC;QACJ,CAAC;QAED,OAAO,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type HandlePublicMediaRequestInput = {
|
|
2
|
+
request: Request;
|
|
3
|
+
pathSegments: string[];
|
|
4
|
+
};
|
|
5
|
+
export declare const getPublicMediaKey: (pathSegments: string[]) => string | null;
|
|
6
|
+
export declare const handlePublicMediaRequest: ({ request, pathSegments, }: HandlePublicMediaRequestInput) => Promise<Response | null>;
|
|
7
|
+
//# sourceMappingURL=publicMedia.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publicMedia.d.ts","sourceRoot":"","sources":["../../../src/media/publicMedia.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,6BAA6B,GAAG;IAC1C,OAAO,EAAE,OAAO,CAAA;IAChB,YAAY,EAAE,MAAM,EAAE,CAAA;CACvB,CAAA;AAYD,eAAO,MAAM,iBAAiB,GAAI,cAAc,MAAM,EAAE,KAAG,MAAM,GAAG,IAOnE,CAAA;AAoED,eAAO,MAAM,wBAAwB,GAAU,4BAG5C,6BAA6B,KAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAkCzD,CAAA"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { getMediaService } from './index.js';
|
|
2
|
+
const DEFAULT_CACHE_CONTROL = 'public, max-age=31536000, immutable';
|
|
3
|
+
const decodePathSegment = (segment) => {
|
|
4
|
+
try {
|
|
5
|
+
const value = decodeURIComponent(segment);
|
|
6
|
+
if (!value || value === '.' || value === '..' || value.includes('/'))
|
|
7
|
+
return null;
|
|
8
|
+
return value;
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
export const getPublicMediaKey = (pathSegments) => {
|
|
15
|
+
if (pathSegments.length === 0)
|
|
16
|
+
return null;
|
|
17
|
+
const segments = pathSegments.map(decodePathSegment);
|
|
18
|
+
if (segments.some((segment) => segment === null))
|
|
19
|
+
return null;
|
|
20
|
+
return `public/${segments.join('/')}`;
|
|
21
|
+
};
|
|
22
|
+
const errorResponse = (status) => new Response(null, { status });
|
|
23
|
+
const isNotFoundError = (error) => {
|
|
24
|
+
if (!error || typeof error !== 'object')
|
|
25
|
+
return false;
|
|
26
|
+
const value = error;
|
|
27
|
+
return (value.name === 'NotFound' ||
|
|
28
|
+
value.name === 'NoSuchKey' ||
|
|
29
|
+
value.code === 'NotFound' ||
|
|
30
|
+
value.code === 'NoSuchKey' ||
|
|
31
|
+
value.$metadata?.httpStatusCode === 404);
|
|
32
|
+
};
|
|
33
|
+
const getErrorStatus = (error) => {
|
|
34
|
+
if (isNotFoundError(error))
|
|
35
|
+
return 404;
|
|
36
|
+
const status = error && typeof error === 'object'
|
|
37
|
+
? error.$metadata?.httpStatusCode
|
|
38
|
+
: undefined;
|
|
39
|
+
if (status === 416) {
|
|
40
|
+
return 416;
|
|
41
|
+
}
|
|
42
|
+
return 502;
|
|
43
|
+
};
|
|
44
|
+
const setDateHeader = (headers, name, value) => {
|
|
45
|
+
if (!value)
|
|
46
|
+
return;
|
|
47
|
+
headers.set(name, value instanceof Date ? value.toUTCString() : value);
|
|
48
|
+
};
|
|
49
|
+
const buildHeaders = (object) => {
|
|
50
|
+
const headers = new Headers({
|
|
51
|
+
'Cache-Control': object.cacheControl ?? DEFAULT_CACHE_CONTROL,
|
|
52
|
+
'X-Content-Type-Options': 'nosniff',
|
|
53
|
+
});
|
|
54
|
+
if (object.acceptRanges)
|
|
55
|
+
headers.set('Accept-Ranges', object.acceptRanges);
|
|
56
|
+
if (object.contentDisposition)
|
|
57
|
+
headers.set('Content-Disposition', object.contentDisposition);
|
|
58
|
+
if (object.contentEncoding)
|
|
59
|
+
headers.set('Content-Encoding', object.contentEncoding);
|
|
60
|
+
if (object.contentLanguage)
|
|
61
|
+
headers.set('Content-Language', object.contentLanguage);
|
|
62
|
+
if (object.contentLength !== undefined)
|
|
63
|
+
headers.set('Content-Length', String(object.contentLength));
|
|
64
|
+
if (object.contentRange)
|
|
65
|
+
headers.set('Content-Range', object.contentRange);
|
|
66
|
+
if (object.contentType)
|
|
67
|
+
headers.set('Content-Type', object.contentType);
|
|
68
|
+
if (object.etag)
|
|
69
|
+
headers.set('ETag', object.etag);
|
|
70
|
+
setDateHeader(headers, 'Expires', object.expires);
|
|
71
|
+
setDateHeader(headers, 'Last-Modified', object.lastModified);
|
|
72
|
+
return headers;
|
|
73
|
+
};
|
|
74
|
+
export const handlePublicMediaRequest = async ({ request, pathSegments, }) => {
|
|
75
|
+
if (request.method !== 'GET' && request.method !== 'HEAD')
|
|
76
|
+
return null;
|
|
77
|
+
let adapter;
|
|
78
|
+
try {
|
|
79
|
+
adapter = getMediaService().rawAdapter;
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
if (!adapter.getPublicObject)
|
|
85
|
+
return null;
|
|
86
|
+
const key = getPublicMediaKey(pathSegments);
|
|
87
|
+
if (!key)
|
|
88
|
+
return errorResponse(404);
|
|
89
|
+
try {
|
|
90
|
+
const object = await adapter.getPublicObject({
|
|
91
|
+
key,
|
|
92
|
+
method: request.method,
|
|
93
|
+
range: request.headers.get('Range') ?? undefined,
|
|
94
|
+
});
|
|
95
|
+
const headers = buildHeaders(object);
|
|
96
|
+
const status = object.status ?? (object.contentRange ? 206 : 200);
|
|
97
|
+
if (request.headers.get('If-None-Match') === object.etag) {
|
|
98
|
+
return new Response(null, { status: 304, headers });
|
|
99
|
+
}
|
|
100
|
+
return new Response(request.method === 'HEAD' ? null : object.body ?? null, {
|
|
101
|
+
status,
|
|
102
|
+
headers,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
return errorResponse(getErrorStatus(error));
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
//# sourceMappingURL=publicMedia.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publicMedia.js","sourceRoot":"","sources":["../../../src/media/publicMedia.ts"],"names":[],"mappings":"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"}
|