@devultur/self-host 1.0.2 → 1.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/README.md +10 -1
- package/dist/{chunk-VF4KBW3I.js → chunk-PQO3X57I.js} +11 -3
- package/dist/index.d.ts +124 -7
- package/dist/index.js +1270 -258
- package/dist/transcode/container.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -30,6 +30,10 @@ compatibility_date = "2026-10-01"
|
|
|
30
30
|
binding = "MEDIA_BUCKET"
|
|
31
31
|
bucket_name = "my-media"
|
|
32
32
|
|
|
33
|
+
[[r2_buckets]]
|
|
34
|
+
binding = "KEYS_BUCKET" # per-object encryption keys: required when security.encrypt is on
|
|
35
|
+
bucket_name = "my-media-keys"
|
|
36
|
+
|
|
33
37
|
[[kv_namespaces]]
|
|
34
38
|
binding = "MEDIA_KV" # pending uploads and transcode job state
|
|
35
39
|
id = "<your KV namespace id>"
|
|
@@ -44,13 +48,16 @@ new_sqlite_classes = ["DownloadLink"]
|
|
|
44
48
|
```
|
|
45
49
|
|
|
46
50
|
```bash
|
|
51
|
+
wrangler r2 bucket create my-media
|
|
52
|
+
wrangler r2 bucket create my-media-keys # keep it private and backed up
|
|
47
53
|
wrangler secret put DELIVERY_SIGN_SECRET # signs viewer tokens and links
|
|
48
54
|
wrangler secret put WORKER_AUTH_SECRET # your backend's bearer on control routes
|
|
49
55
|
wrangler secret put TRANSCODE_WEBHOOK_SECRET # signs transcode callbacks
|
|
50
56
|
wrangler deploy
|
|
51
57
|
```
|
|
52
58
|
|
|
53
|
-
Without its secrets the Worker fails closed: control routes answer `503`.
|
|
59
|
+
Without its secrets the Worker fails closed: control routes answer `503`. With encryption at rest on and no
|
|
60
|
+
`KEYS_BUCKET`, private writes answer `503 keys_bucket_missing` instead of storing plaintext. Call it from your backend with
|
|
54
61
|
[`@devultur/server`](https://www.npmjs.com/package/@devultur/server). The Worker is built from plugins:
|
|
55
62
|
`createWorker({ plugins })` takes your rules, your own auth, hooks before a credential is issued, and routes and
|
|
56
63
|
middleware of your own.
|
|
@@ -61,6 +68,8 @@ middleware of your own.
|
|
|
61
68
|
[github.com/devultur/devultur/blob/main/docs/guides/self-host.md](https://github.com/devultur/devultur/blob/main/docs/guides/self-host.md).
|
|
62
69
|
- Plugins (auth, request state, hooks, example plugins):
|
|
63
70
|
[github.com/devultur/devultur/blob/main/docs/guides/plugins.md](https://github.com/devultur/devultur/blob/main/docs/guides/plugins.md).
|
|
71
|
+
- Retention and holds (compliance and governance locks, holds, audit, caveats):
|
|
72
|
+
[github.com/devultur/devultur/blob/main/docs/guides/object-lock.md](https://github.com/devultur/devultur/blob/main/docs/guides/object-lock.md).
|
|
64
73
|
|
|
65
74
|
## License
|
|
66
75
|
|
|
@@ -187,9 +187,9 @@ async function encryptForStorage(keysBucket, objectStorageKey, body, keyMetadata
|
|
|
187
187
|
const { cryptoKey, iv, enc } = await createObjectEncryption(keysBucket, objectStorageKey, keyMetadata);
|
|
188
188
|
return { body: await encryptBytes(body, cryptoKey, iv), enc };
|
|
189
189
|
}
|
|
190
|
-
function shouldEncryptAtRest(policy, key
|
|
190
|
+
function shouldEncryptAtRest(policy, key) {
|
|
191
191
|
const isHlsAsset = key.endsWith(".ts") || key.endsWith(".m3u8");
|
|
192
|
-
return Boolean(policy.encrypt) && visibilityFromKey(key) === "private" && !isHlsAsset
|
|
192
|
+
return Boolean(policy.encrypt) && visibilityFromKey(key) === "private" && !isHlsAsset;
|
|
193
193
|
}
|
|
194
194
|
async function loadStorageKey(keysBucket, objectStorageKey, keyId) {
|
|
195
195
|
if (!keysBucket) return null;
|
|
@@ -262,7 +262,8 @@ async function signJobTicket(secret, job, nowMs = Date.now()) {
|
|
|
262
262
|
jti: runId,
|
|
263
263
|
iat: issuedAt,
|
|
264
264
|
exp: issuedAt + JOB_TICKET_TTL_SECONDS,
|
|
265
|
-
...job.context ? { context: job.context } : {}
|
|
265
|
+
...job.context ? { context: job.context } : {},
|
|
266
|
+
...job.location ? { loc: { root: job.location.root, folder: job.location.folder } } : {}
|
|
266
267
|
},
|
|
267
268
|
ticketKey(secret)
|
|
268
269
|
);
|
|
@@ -279,6 +280,12 @@ async function verifyJobTicket(secret, ticket, videoId) {
|
|
|
279
280
|
...isRecord(claims.context) ? { context: claims.context } : {}
|
|
280
281
|
};
|
|
281
282
|
}
|
|
283
|
+
async function verifyJobLocation(secret, ticket, videoId) {
|
|
284
|
+
const claims = await verifyViewerToken(ticket, ticketKey(secret));
|
|
285
|
+
if (claims?.typ !== JOB_TICKET_TYPE || claims.sub !== videoId || !isRecord(claims.loc)) return null;
|
|
286
|
+
const { root, folder } = claims.loc;
|
|
287
|
+
return typeof root === "string" && typeof folder === "string" ? { root, folder } : null;
|
|
288
|
+
}
|
|
282
289
|
|
|
283
290
|
// src/transcode/runner.ts
|
|
284
291
|
var TranscodeRunnerName = {
|
|
@@ -446,6 +453,7 @@ export {
|
|
|
446
453
|
JOB_TICKET_HEADER,
|
|
447
454
|
signJobTicket,
|
|
448
455
|
verifyJobTicket,
|
|
456
|
+
verifyJobLocation,
|
|
449
457
|
TranscodeRunnerName,
|
|
450
458
|
RUN_SCRIPT_COMMAND,
|
|
451
459
|
TranscodeLaunchErrorCode,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as hono_types from 'hono/types';
|
|
2
2
|
import { Context, MiddlewareHandler, Hono } from 'hono';
|
|
3
|
-
import { Visibility, SecurityPolicy, CacheRule, TranscodeSettings, TranscodeOutputKeys, TranscodeOutputUrls } from '@devultur/core';
|
|
3
|
+
import { Visibility, ObjectLock, SecurityPolicy, CacheRule, TranscodeSettings, TranscodeOutputKeys, TranscodeOutputUrls } from '@devultur/core';
|
|
4
4
|
import { T as TranscodeContainerNamespace } from './cloudflare-kZ7J3LQ2.js';
|
|
5
5
|
|
|
6
|
-
/** What an upload token allows (claims `res`, `visibility`, `max_bytes`, `max_files`, `file_ttl`). */
|
|
6
|
+
/** What an upload token allows (claims `res`, `visibility`, `max_bytes`, `max_files`, `file_ttl`, `lock`). */
|
|
7
7
|
interface UploadGrant {
|
|
8
8
|
/** Token's `jti`: best-effort counter for `maxFiles`. */
|
|
9
9
|
tokenId: string;
|
|
@@ -14,6 +14,8 @@ interface UploadGrant {
|
|
|
14
14
|
maxFiles?: number;
|
|
15
15
|
/** TTL (seconds) of each file uploaded with the token. */
|
|
16
16
|
fileExpiresIn?: number;
|
|
17
|
+
/** Lock every file uploaded with the token gets at least (a request can make it stricter, never looser). */
|
|
18
|
+
lock?: ObjectLock;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
/** A download link as the Worker hands it to plugins. */
|
|
@@ -40,6 +42,8 @@ interface RouteResult {
|
|
|
40
42
|
redeemedLink?: DownloadLinkInfo;
|
|
41
43
|
/** `transcode.complete` deleted the video's original (`config.transcode.deleteOriginalOnSuccess`). */
|
|
42
44
|
originalDeleted?: boolean;
|
|
45
|
+
/** `transcode.complete` was asked to delete the original but kept it: it's locked (retention or hold). */
|
|
46
|
+
originalRetained?: boolean;
|
|
43
47
|
/** The transcode callback carried a valid job ticket: the job it belongs to. */
|
|
44
48
|
transcodeJob?: TranscodeJob;
|
|
45
49
|
}
|
|
@@ -154,9 +158,14 @@ interface WorkerConfig {
|
|
|
154
158
|
/**
|
|
155
159
|
* R2 custom metadata added to every object the request uploads (also on the later credential-less PUT), for example
|
|
156
160
|
* which app or user uploaded it. Keys the Worker owns (integrity `sha256*`, `expiresAt`, `security`, `enc`,
|
|
157
|
-
* `derivedFrom`) are dropped from it.
|
|
161
|
+
* `derivedFrom`, `lock`) are dropped from it.
|
|
158
162
|
*/
|
|
159
163
|
uploadMetadata?: Record<string, string>;
|
|
164
|
+
/**
|
|
165
|
+
* Default lock of an uploaded file: retention (`governance` or `compliance`, until a date or for a period) and hold.
|
|
166
|
+
* The upload request (or its upload token) overrides it. Unset: files aren't locked.
|
|
167
|
+
*/
|
|
168
|
+
lock?: ObjectLock;
|
|
160
169
|
transcode?: TranscodeConfig;
|
|
161
170
|
}
|
|
162
171
|
/** What an auth plugin established about the request's credential. */
|
|
@@ -209,6 +218,26 @@ declare function isAuthenticated(context: AnyContext$2): boolean;
|
|
|
209
218
|
*/
|
|
210
219
|
declare function updateRequestState(context: AnyContext$2, patch: RequestStatePatch): RequestState;
|
|
211
220
|
|
|
221
|
+
declare const LOCK_AUDIT_PREFIX = "__lock-audit/";
|
|
222
|
+
type LockAuditAction = "set" | "extend" | "shorten" | "remove" | "hold" | "release" | "delete_rejected" | "overwrite_rejected" | "original_retained";
|
|
223
|
+
interface LockAuditRecord {
|
|
224
|
+
/** ISO time of the event. */
|
|
225
|
+
at: string;
|
|
226
|
+
action: LockAuditAction;
|
|
227
|
+
/** Virtual keys the event is about. */
|
|
228
|
+
keys: string[];
|
|
229
|
+
before: ObjectLock | null;
|
|
230
|
+
after: ObjectLock | null;
|
|
231
|
+
/** The request's plugin context (who the auth layer said is calling), or null. */
|
|
232
|
+
actor: PluginContext | null;
|
|
233
|
+
/** `applied`: the change landed. `rejected`: the Worker refused it. `skipped`: a delete didn't run (retained raw). */
|
|
234
|
+
outcome: "applied" | "rejected" | "skipped";
|
|
235
|
+
/** The change used the governance privilege (`bypassGovernance` approved by `authorizeLockChange`). */
|
|
236
|
+
bypass?: boolean;
|
|
237
|
+
/** Why it was rejected (a response code). */
|
|
238
|
+
reason?: string;
|
|
239
|
+
}
|
|
240
|
+
|
|
212
241
|
/** What is being issued: a viewer token, an upload token, a download link or the transcode runner's token. */
|
|
213
242
|
type CredentialKind = "viewer" | "upload" | "download-link" | "service";
|
|
214
243
|
interface CredentialRequest {
|
|
@@ -242,10 +271,39 @@ type AnyContext$1 = Context<any>;
|
|
|
242
271
|
type IssueCredentialHook = (context: AnyContext$1, request: CredentialRequest) => CredentialDecision | Promise<CredentialDecision>;
|
|
243
272
|
/** A response refuses the redemption (returned as is, and the use is NOT spent); `null` lets it go on. */
|
|
244
273
|
type BeforeLinkRedeemHook = (context: AnyContext$1, link: DownloadLinkInfo) => Response | null | Promise<Response | null>;
|
|
274
|
+
/**
|
|
275
|
+
* What a lock change does: `set` a first (or expired) retention, `extend` it, `shorten` or `remove` it; `hold` or
|
|
276
|
+
* `release` a hold.
|
|
277
|
+
*/
|
|
278
|
+
type LockChangeAction = "set" | "extend" | "shorten" | "remove" | "hold" | "release";
|
|
279
|
+
interface LockChangeRequest {
|
|
280
|
+
action: LockChangeAction;
|
|
281
|
+
/** The virtual keys it changes (for a bulk hold by prefix: this page of them). */
|
|
282
|
+
keys: string[];
|
|
283
|
+
/** A bulk hold by prefix: the prefix the request named. */
|
|
284
|
+
prefix?: string;
|
|
285
|
+
before: ObjectLock | null;
|
|
286
|
+
after: ObjectLock | null;
|
|
287
|
+
}
|
|
288
|
+
type LockChangeDecision = {
|
|
289
|
+
allow: false;
|
|
290
|
+
response: Response;
|
|
291
|
+
} | {
|
|
292
|
+
allow: true;
|
|
293
|
+
};
|
|
294
|
+
/**
|
|
295
|
+
* Before the Worker changes a lock. Refuse with a response, or allow. Approving a governance `shorten`/`remove` asked
|
|
296
|
+
* with `bypassGovernance` takes at least one of these hooks, and all of them must allow it (decision 4 of #3).
|
|
297
|
+
*/
|
|
298
|
+
type AuthorizeLockChangeHook = (context: AnyContext$1, request: LockChangeRequest) => LockChangeDecision | Promise<LockChangeDecision>;
|
|
299
|
+
/** After a lock event (change, rejected delete or overwrite, retained original), to store the record elsewhere. */
|
|
300
|
+
type OnLockAuditHook = (context: AnyContext$1, record: LockAuditRecord) => void | Promise<void>;
|
|
245
301
|
/** The hooks of every plugin, in plugin order. */
|
|
246
302
|
interface PluginHooks {
|
|
247
303
|
issueCredential: IssueCredentialHook[];
|
|
248
304
|
beforeLinkRedeem: BeforeLinkRedeemHook[];
|
|
305
|
+
authorizeLockChange: AuthorizeLockChangeHook[];
|
|
306
|
+
onLockAudit: OnLockAuditHook[];
|
|
249
307
|
}
|
|
250
308
|
|
|
251
309
|
type AnyMiddleware = MiddlewareHandler<any>;
|
|
@@ -276,6 +334,10 @@ interface WorkerPlugin {
|
|
|
276
334
|
issueCredential?: IssueCredentialHook;
|
|
277
335
|
/** Before `GET /v1/download/{id}` spends a use of a link that still has one. */
|
|
278
336
|
beforeLinkRedeem?: BeforeLinkRedeemHook;
|
|
337
|
+
/** Before `PUT /v1/lock` changes a lock: refuse it, or approve a governance bypass. */
|
|
338
|
+
authorizeLockChange?: AuthorizeLockChangeHook;
|
|
339
|
+
/** After every lock event, with its audit record. Runs after the response. */
|
|
340
|
+
onLockAudit?: OnLockAuditHook;
|
|
279
341
|
}
|
|
280
342
|
interface ComposedPlugins {
|
|
281
343
|
middleware: AnyMiddleware[];
|
|
@@ -339,6 +401,11 @@ declare function isServiceToken(payload: Record<string, unknown> | null | undefi
|
|
|
339
401
|
*/
|
|
340
402
|
declare function verifyViewerToken(token: string | undefined, secret: string): Promise<Record<string, unknown> | null>;
|
|
341
403
|
declare function hashKey(key: string): Promise<string>;
|
|
404
|
+
/**
|
|
405
|
+
* Lists and batch-deletes every object under `prefix` (R2 deletes up to 1000 keys/call) and returns how many it
|
|
406
|
+
* deleted. Idempotent: empty prefix → 0. It bypasses object locks: routes delete through `guardedDeletePrefix` and
|
|
407
|
+
* `deleteKeysFor` (object-lock/guard.ts). Use this only for regenerable data (image variants) or after the guard ran.
|
|
408
|
+
*/
|
|
342
409
|
declare function deletePrefix(bucket: R2Bucket, prefix: string): Promise<number>;
|
|
343
410
|
|
|
344
411
|
interface ImageTransformParams {
|
|
@@ -369,6 +436,45 @@ declare function readImageOriginScope(request: Request, secret: string | undefin
|
|
|
369
436
|
/** Is this Cloudflare Images' signed subrequest? It's not delivery to the client: it isn't gated or counted. */
|
|
370
437
|
declare function isImageOriginRequest(request: Request, secret: string | undefined): Promise<boolean>;
|
|
371
438
|
|
|
439
|
+
declare const KEYS_BUCKET_MISSING_CODE = "keys_bucket_missing";
|
|
440
|
+
declare const ENCRYPTION_KEY_MISSING_CODE = "encryption_key_missing";
|
|
441
|
+
|
|
442
|
+
/** Retention expiry (ISO) of a locked object. */
|
|
443
|
+
declare const LOCK_UNTIL_HEADER = "x-devultur-lock-until";
|
|
444
|
+
/** `true` while a hold is set. */
|
|
445
|
+
declare const LOCK_HOLD_HEADER = "x-devultur-lock-hold";
|
|
446
|
+
|
|
447
|
+
/** Prefixes the Worker keeps for lock sidecars and audit records: no route reads or writes a key under them. */
|
|
448
|
+
declare const RESERVED_LOCK_PREFIXES: readonly ["__lock/", "__lock-audit/"];
|
|
449
|
+
|
|
450
|
+
/** Objects changed per request: a list of keys may name at most this many; a prefix is walked this many at a time. */
|
|
451
|
+
declare const HOLD_PAGE_SIZE = 50;
|
|
452
|
+
interface HoldSkip {
|
|
453
|
+
key: string;
|
|
454
|
+
/**
|
|
455
|
+
* `not_found`, `unchanged` (already in that state), `lock_conflict` (changed concurrently: retry it) or
|
|
456
|
+
* `lock_record_unreadable` (a release of a lock record that can't be read: an operator must repair it).
|
|
457
|
+
*/
|
|
458
|
+
reason: "not_found" | "unchanged" | "lock_conflict" | "lock_record_unreadable";
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/** `customMetadata` key holding the lock set at upload (JSON `{ retention?, hold }`). Owned by the Worker. */
|
|
462
|
+
declare const LOCK_METADATA_KEY = "lock";
|
|
463
|
+
|
|
464
|
+
declare const LOCK_SIDECAR_PREFIX = "__lock/";
|
|
465
|
+
interface LockSidecar {
|
|
466
|
+
/** Increases by one on every change. */
|
|
467
|
+
revision: number;
|
|
468
|
+
/** The object version this lock applies to (see `objectVersionOf`). */
|
|
469
|
+
objectVersion: string;
|
|
470
|
+
lock: ObjectLock;
|
|
471
|
+
/** ISO time the hold was released (a `period` then counts from here). */
|
|
472
|
+
holdReleasedAt?: string;
|
|
473
|
+
/** ISO time of the last change. */
|
|
474
|
+
updatedAt: string;
|
|
475
|
+
}
|
|
476
|
+
type LockSource = "sidecar" | "upload" | "none";
|
|
477
|
+
|
|
372
478
|
interface CredentialPolicyOptions {
|
|
373
479
|
/** Longest lifetime, in seconds, per kind of credential. A longer request is shortened to it, not refused. */
|
|
374
480
|
maxTtlSeconds?: Partial<Record<CredentialKind, number>>;
|
|
@@ -407,6 +513,11 @@ declare function workerSecretAuth(): WorkerPlugin;
|
|
|
407
513
|
declare function defaultPlugins(config?: WorkerConfig): WorkerPlugin[];
|
|
408
514
|
|
|
409
515
|
declare const MAX_ASSET_LIST_LIMIT = 1000;
|
|
516
|
+
/**
|
|
517
|
+
* Lock-record reads per page (one subrequest each, plus the listing's own): well under the Workers subrequest limit
|
|
518
|
+
* on any plan, whatever share of the page has expired.
|
|
519
|
+
*/
|
|
520
|
+
declare const MAX_EXPIRED_LOOKUPS = 32;
|
|
410
521
|
interface AssetListEntry {
|
|
411
522
|
key: string;
|
|
412
523
|
path: string;
|
|
@@ -417,17 +528,23 @@ interface AssetListEntry {
|
|
|
417
528
|
uploaded: string;
|
|
418
529
|
cacheControl: string | null;
|
|
419
530
|
visibility: Visibility;
|
|
531
|
+
/** Past its `expiresAt` but still retained: listed (the owner can still read it), and not deleted. */
|
|
532
|
+
expired?: true;
|
|
533
|
+
/** The retention that keeps an expired entry (its effective expiry), when it has a date. */
|
|
534
|
+
retainedUntil?: string;
|
|
535
|
+
/** An expired entry kept by a hold. */
|
|
536
|
+
hold?: true;
|
|
420
537
|
}
|
|
421
538
|
|
|
539
|
+
/** Has the object expired (TTL)? From then on we respond 410 even if the sweeper hasn't deleted it yet. Pure. */
|
|
540
|
+
declare function isObjectExpired(customMetadata: Record<string, string> | undefined, now?: number): boolean;
|
|
541
|
+
|
|
422
542
|
/** The unit's tag: a hash (Cloudflare's tags are case-insensitive but paths aren't). */
|
|
423
543
|
declare function edgeCacheTag(storagePrefix: string, virtualKey: string): Promise<string>;
|
|
424
544
|
|
|
425
545
|
/** `Cache-Control` served: the one stored on the object (for private, no shared caches) or the one for a generated id. */
|
|
426
546
|
declare function servedCacheControl(stored: string | undefined, isPrivate: boolean): string;
|
|
427
547
|
|
|
428
|
-
/** Has the object expired (TTL)? From then on we respond 410 even if the sweeper hasn't deleted it yet. Pure. */
|
|
429
|
-
declare function isObjectExpired(customMetadata: Record<string, string> | undefined, now?: number): boolean;
|
|
430
|
-
|
|
431
548
|
declare const UPLOAD_TOKEN_TYPE = "upload";
|
|
432
549
|
/** Short-lived: it's a JWT (an auth layer can also reject it if the credential that issued it is no longer valid). */
|
|
433
550
|
declare const MAX_UPLOAD_TOKEN_TTL_SECONDS: number;
|
|
@@ -527,4 +644,4 @@ interface CreateWorkerOptions {
|
|
|
527
644
|
}
|
|
528
645
|
declare function createWorker(options?: CreateWorkerOptions): Hono<WorkerApp, hono_types.BlankSchema, "/">;
|
|
529
646
|
|
|
530
|
-
export { type AllowedCredential, type AssetListEntry, type BeforeLinkRedeemHook, type ComposedPlugins, type CreateWorkerOptions, type CredentialDecision, type CredentialKind, type CredentialPolicyOptions, type CredentialRequest, DownloadLink, type DownloadLinkInfo, type DownloadLinkRecord, type DownloadLinkStorage, type EncodeMetrics, type ImageTransformParams, type IssueCredentialHook, type Json, MAX_ASSET_LIST_LIMIT, MAX_UPLOAD_TOKEN_TTL_SECONDS, MaxResolution, ObjectMeta, type PendingUploadInfo, type PluginContext, type PluginMiddleware, type PluginRoute, type RawStorageClass, type RequestAccess, type RequestState, type RequestStatePatch, type RouteResult, TOKEN_REJECTED_CODE, type TranscodeConfig, type TranscodeJob, UPLOAD_TOKEN_TYPE, type UploadGrant, type UploadRules, type UploadTypeRule, type WorkerApp, WorkerAuthErrorCode, type WorkerConfig, type WorkerEnv, type WorkerPlugin, type WorkerVariables, cancelPendingUpload, createWorker, credentialPolicy, defaultPlugins, deletePrefix, downloadLinks, edgeCacheTag, getPendingUpload, getRequestState, getRouteResult, hashKey, imageOriginAuthorization, isAuthenticated, isImageOriginRequest, isObjectExpired, isOpenRoute, isServiceToken, isUploadUrl, isVariantKey, logEncodeMetrics, parseEncodeMetrics, parseTransformParams, readImageOriginScope, readStoryboardKey, readTokenScopes, readTranscodeOutputKeys, readTranscodeOutputs, servedCacheControl, staticConfig, storageKey, updateRequestState, uploadGrantFromClaims, variantPrefix, vcpuSecondsPerVideoMinute, verifyViewerToken, withOutputUrls, workerSecretAuth };
|
|
647
|
+
export { type AllowedCredential, type AssetListEntry, type AuthorizeLockChangeHook, type BeforeLinkRedeemHook, type ComposedPlugins, type CreateWorkerOptions, type CredentialDecision, type CredentialKind, type CredentialPolicyOptions, type CredentialRequest, DownloadLink, type DownloadLinkInfo, type DownloadLinkRecord, type DownloadLinkStorage, ENCRYPTION_KEY_MISSING_CODE, type EncodeMetrics, HOLD_PAGE_SIZE, type HoldSkip, type ImageTransformParams, type IssueCredentialHook, type Json, KEYS_BUCKET_MISSING_CODE, LOCK_AUDIT_PREFIX, LOCK_HOLD_HEADER, LOCK_METADATA_KEY, LOCK_SIDECAR_PREFIX, LOCK_UNTIL_HEADER, type LockAuditAction, type LockAuditRecord, type LockChangeAction, type LockChangeDecision, type LockChangeRequest, type LockSidecar, type LockSource, MAX_ASSET_LIST_LIMIT, MAX_EXPIRED_LOOKUPS, MAX_UPLOAD_TOKEN_TTL_SECONDS, MaxResolution, ObjectMeta, type OnLockAuditHook, type PendingUploadInfo, type PluginContext, type PluginMiddleware, type PluginRoute, RESERVED_LOCK_PREFIXES, type RawStorageClass, type RequestAccess, type RequestState, type RequestStatePatch, type RouteResult, TOKEN_REJECTED_CODE, type TranscodeConfig, type TranscodeJob, UPLOAD_TOKEN_TYPE, type UploadGrant, type UploadRules, type UploadTypeRule, type WorkerApp, WorkerAuthErrorCode, type WorkerConfig, type WorkerEnv, type WorkerPlugin, type WorkerVariables, cancelPendingUpload, createWorker, credentialPolicy, defaultPlugins, deletePrefix, downloadLinks, edgeCacheTag, getPendingUpload, getRequestState, getRouteResult, hashKey, imageOriginAuthorization, isAuthenticated, isImageOriginRequest, isObjectExpired, isOpenRoute, isServiceToken, isUploadUrl, isVariantKey, logEncodeMetrics, parseEncodeMetrics, parseTransformParams, readImageOriginScope, readStoryboardKey, readTokenScopes, readTranscodeOutputKeys, readTranscodeOutputs, servedCacheControl, staticConfig, storageKey, updateRequestState, uploadGrantFromClaims, variantPrefix, vcpuSecondsPerVideoMinute, verifyViewerToken, withOutputUrls, workerSecretAuth };
|