@openrails/contentkit-ui 0.0.0-stage → 0.68.1
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 +470 -2
- package/dist/appearance.d.ts +38 -0
- package/dist/appearance.js +15 -0
- package/dist/appearance.js.map +1 -0
- package/dist/assets/hash.worker-BYfo-7MQ.js.map +1 -0
- package/dist/client/aspect.d.ts +6 -0
- package/dist/client/aspect.js +17 -0
- package/dist/client/aspect.js.map +1 -0
- package/dist/client/client.d.ts +53 -0
- package/dist/client/client.js +36 -0
- package/dist/client/client.js.map +1 -0
- package/dist/client/codes.d.ts +12 -0
- package/dist/client/codes.js +19 -0
- package/dist/client/codes.js.map +1 -0
- package/dist/client/content/bans.d.ts +15 -0
- package/dist/client/content/bans.js +40 -0
- package/dist/client/content/bans.js.map +1 -0
- package/dist/client/content/comments.d.ts +36 -0
- package/dist/client/content/comments.js +95 -0
- package/dist/client/content/comments.js.map +1 -0
- package/dist/client/content/favorites.d.ts +14 -0
- package/dist/client/content/favorites.js +42 -0
- package/dist/client/content/favorites.js.map +1 -0
- package/dist/client/content/moderation.d.ts +18 -0
- package/dist/client/content/moderation.js +37 -0
- package/dist/client/content/moderation.js.map +1 -0
- package/dist/client/content/polls.d.ts +47 -0
- package/dist/client/content/polls.js +151 -0
- package/dist/client/content/polls.js.map +1 -0
- package/dist/client/content/posts.d.ts +44 -0
- package/dist/client/content/posts.js +92 -0
- package/dist/client/content/posts.js.map +1 -0
- package/dist/client/content/reactions.d.ts +12 -0
- package/dist/client/content/reactions.js +36 -0
- package/dist/client/content/reactions.js.map +1 -0
- package/dist/client/content/types.d.ts +91 -0
- package/dist/client/content/types.js +8 -0
- package/dist/client/content/types.js.map +1 -0
- package/dist/client/crop.d.ts +32 -0
- package/dist/client/crop.js +103 -0
- package/dist/client/crop.js.map +1 -0
- package/dist/client/errors.d.ts +54 -0
- package/dist/client/errors.js +80 -0
- package/dist/client/errors.js.map +1 -0
- package/dist/client/gallery.d.ts +43 -0
- package/dist/client/gallery.js +86 -0
- package/dist/client/gallery.js.map +1 -0
- package/dist/client/generated/error-codes.d.ts +5 -0
- package/dist/client/generated/error-codes.js +131 -0
- package/dist/client/generated/error-codes.js.map +1 -0
- package/dist/client/generated/routes.d.ts +1086 -0
- package/dist/client/generated/routes.js +1400 -0
- package/dist/client/generated/routes.js.map +1 -0
- package/dist/client/generated/wire.d.ts +630 -0
- package/dist/client/generated/wire.js +6 -0
- package/dist/client/generated/wire.js.map +1 -0
- package/dist/client/http.d.ts +83 -0
- package/dist/client/http.js +82 -0
- package/dist/client/http.js.map +1 -0
- package/dist/client/image.d.ts +24 -0
- package/dist/client/image.js +65 -0
- package/dist/client/image.js.map +1 -0
- package/dist/client/index.d.ts +33 -0
- package/dist/client/media/api.d.ts +36 -0
- package/dist/client/media/api.js +61 -0
- package/dist/client/media/api.js.map +1 -0
- package/dist/client/media/client.d.ts +247 -0
- package/dist/client/media/client.js +407 -0
- package/dist/client/media/client.js.map +1 -0
- package/dist/client/media/encode.d.ts +3 -0
- package/dist/client/media/encode.js +8 -0
- package/dist/client/media/encode.js.map +1 -0
- package/dist/client/media/hash-stream.d.ts +6 -0
- package/dist/client/media/hash-stream.js +16 -0
- package/dist/client/media/hash-stream.js.map +1 -0
- package/dist/client/media/hash.d.ts +12 -0
- package/dist/client/media/hash.js +48 -0
- package/dist/client/media/hash.js.map +1 -0
- package/dist/client/media/hash.worker-inline.js +18 -0
- package/dist/client/media/hash.worker-inline.js.map +1 -0
- package/dist/client/media/pacer.d.ts +21 -0
- package/dist/client/media/pacer.js +25 -0
- package/dist/client/media/pacer.js.map +1 -0
- package/dist/client/media/queue.d.ts +112 -0
- package/dist/client/media/queue.js +274 -0
- package/dist/client/media/queue.js.map +1 -0
- package/dist/client/media/ref.d.ts +6 -0
- package/dist/client/media/ref.js +10 -0
- package/dist/client/media/ref.js.map +1 -0
- package/dist/client/media/rules.d.ts +54 -0
- package/dist/client/media/rules.js +143 -0
- package/dist/client/media/rules.js.map +1 -0
- package/dist/client/media/transport.d.ts +13 -0
- package/dist/client/media/transport.js +33 -0
- package/dist/client/media/transport.js.map +1 -0
- package/dist/client/media/windows.d.ts +15 -0
- package/dist/client/media/windows.js +39 -0
- package/dist/client/media/windows.js.map +1 -0
- package/dist/client/playback.d.ts +200 -0
- package/dist/client/playback.js +142 -0
- package/dist/client/playback.js.map +1 -0
- package/dist/client/player.d.ts +102 -0
- package/dist/client/player.js +155 -0
- package/dist/client/player.js.map +1 -0
- package/dist/client/public.d.ts +25 -0
- package/dist/client/public.js +18 -0
- package/dist/client/public.js.map +1 -0
- package/dist/client/rendition.d.ts +19 -0
- package/dist/client/rendition.js +16 -0
- package/dist/client/rendition.js.map +1 -0
- package/dist/client/route.d.ts +39 -0
- package/dist/client/route.js +31 -0
- package/dist/client/route.js.map +1 -0
- package/dist/client/taxonomy.d.ts +30 -0
- package/dist/client/taxonomy.js +77 -0
- package/dist/client/taxonomy.js.map +1 -0
- package/dist/client.js +33 -0
- package/dist/components/encode-progress.d.ts +15 -0
- package/dist/components/encode-progress.js +49 -0
- package/dist/components/encode-progress.js.map +1 -0
- package/dist/components/hover-preview.d.ts +29 -0
- package/dist/components/hover-preview.js +49 -0
- package/dist/components/hover-preview.js.map +1 -0
- package/dist/components/image-crop-dialog.d.ts +48 -0
- package/dist/components/image-crop-dialog.js +359 -0
- package/dist/components/image-crop-dialog.js.map +1 -0
- package/dist/components/lazy-mount.d.ts +10 -0
- package/dist/components/lazy-mount.js +22 -0
- package/dist/components/lazy-mount.js.map +1 -0
- package/dist/components/media-folder-editor.d.ts +59 -0
- package/dist/components/media-folder-editor.js +611 -0
- package/dist/components/media-folder-editor.js.map +1 -0
- package/dist/components/media-gallery.d.ts +54 -0
- package/dist/components/media-gallery.js +597 -0
- package/dist/components/media-gallery.js.map +1 -0
- package/dist/components/media-readiness-notice.d.ts +24 -0
- package/dist/components/media-readiness-notice.js +61 -0
- package/dist/components/media-readiness-notice.js.map +1 -0
- package/dist/components/player-controls.d.ts +71 -0
- package/dist/components/player-controls.js +264 -0
- package/dist/components/player-controls.js.map +1 -0
- package/dist/components/progress.d.ts +5 -0
- package/dist/components/progress.js +14 -0
- package/dist/components/progress.js.map +1 -0
- package/dist/components/rendition-img.d.ts +34 -0
- package/dist/components/rendition-img.js +78 -0
- package/dist/components/rendition-img.js.map +1 -0
- package/dist/components/slot-editor.d.ts +95 -0
- package/dist/components/slot-editor.js +182 -0
- package/dist/components/slot-editor.js.map +1 -0
- package/dist/components/slot-image.d.ts +23 -0
- package/dist/components/slot-image.js +48 -0
- package/dist/components/slot-image.js.map +1 -0
- package/dist/components/slot-upload.d.ts +41 -0
- package/dist/components/slot-upload.js +215 -0
- package/dist/components/slot-upload.js.map +1 -0
- package/dist/components/social/bans.d.ts +42 -0
- package/dist/components/social/bans.js +300 -0
- package/dist/components/social/bans.js.map +1 -0
- package/dist/components/social/comments.d.ts +42 -0
- package/dist/components/social/comments.js +517 -0
- package/dist/components/social/comments.js.map +1 -0
- package/dist/components/social/engagement.d.ts +45 -0
- package/dist/components/social/engagement.js +129 -0
- package/dist/components/social/engagement.js.map +1 -0
- package/dist/components/social/index.d.ts +6 -0
- package/dist/components/social/moderation.d.ts +32 -0
- package/dist/components/social/moderation.js +383 -0
- package/dist/components/social/moderation.js.map +1 -0
- package/dist/components/social/parts.d.ts +50 -0
- package/dist/components/social/parts.js +106 -0
- package/dist/components/social/parts.js.map +1 -0
- package/dist/components/social/poll-editor.d.ts +34 -0
- package/dist/components/social/poll-editor.js +567 -0
- package/dist/components/social/poll-editor.js.map +1 -0
- package/dist/components/social/poll.d.ts +30 -0
- package/dist/components/social/poll.js +252 -0
- package/dist/components/social/poll.js.map +1 -0
- package/dist/components/sortable-list.d.ts +29 -0
- package/dist/components/sortable-list.js +121 -0
- package/dist/components/sortable-list.js.map +1 -0
- package/dist/components/video-mini-player.d.ts +35 -0
- package/dist/components/video-mini-player.js +236 -0
- package/dist/components/video-mini-player.js.map +1 -0
- package/dist/components/video-player.d.ts +146 -0
- package/dist/components/video-player.js +630 -0
- package/dist/components/video-player.js.map +1 -0
- package/dist/components/video-poster-picker.d.ts +59 -0
- package/dist/components/video-poster-picker.js +335 -0
- package/dist/components/video-poster-picker.js.map +1 -0
- package/dist/components/video-poster.d.ts +24 -0
- package/dist/components/video-poster.js +46 -0
- package/dist/components/video-poster.js.map +1 -0
- package/dist/i18n/context.d.ts +4 -0
- package/dist/i18n/context.js +11 -0
- package/dist/i18n/context.js.map +1 -0
- package/dist/i18n/messages.d.ts +40 -0
- package/dist/i18n/messages.js +94 -0
- package/dist/i18n/messages.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +41 -0
- package/dist/locales/de.d.ts +2 -0
- package/dist/locales/de.js +271 -0
- package/dist/locales/de.js.map +1 -0
- package/dist/locales/en.d.ts +457 -0
- package/dist/locales/en.js +271 -0
- package/dist/locales/en.js.map +1 -0
- package/dist/locales/es.d.ts +2 -0
- package/dist/locales/es.js +271 -0
- package/dist/locales/es.js.map +1 -0
- package/dist/locales/ja.d.ts +2 -0
- package/dist/locales/ja.js +271 -0
- package/dist/locales/ja.js.map +1 -0
- package/dist/locales/ko.d.ts +2 -0
- package/dist/locales/ko.js +271 -0
- package/dist/locales/ko.js.map +1 -0
- package/dist/locales/social/de.d.ts +2 -0
- package/dist/locales/social/de.js +198 -0
- package/dist/locales/social/de.js.map +1 -0
- package/dist/locales/social/en.d.ts +195 -0
- package/dist/locales/social/en.js +198 -0
- package/dist/locales/social/en.js.map +1 -0
- package/dist/locales/social/es.d.ts +2 -0
- package/dist/locales/social/es.js +198 -0
- package/dist/locales/social/es.js.map +1 -0
- package/dist/locales/social/ja.d.ts +2 -0
- package/dist/locales/social/ja.js +198 -0
- package/dist/locales/social/ja.js.map +1 -0
- package/dist/locales/social/ko.d.ts +2 -0
- package/dist/locales/social/ko.js +198 -0
- package/dist/locales/social/ko.js.map +1 -0
- package/dist/locales/social/zh.d.ts +2 -0
- package/dist/locales/social/zh.js +198 -0
- package/dist/locales/social/zh.js.map +1 -0
- package/dist/locales/zh.d.ts +2 -0
- package/dist/locales/zh.js +271 -0
- package/dist/locales/zh.js.map +1 -0
- package/dist/provider.d.ts +22 -0
- package/dist/provider.js +59 -0
- package/dist/provider.js.map +1 -0
- package/dist/react/canonical.d.ts +33 -0
- package/dist/react/canonical.js +78 -0
- package/dist/react/canonical.js.map +1 -0
- package/dist/react/comments.d.ts +82 -0
- package/dist/react/comments.js +155 -0
- package/dist/react/comments.js.map +1 -0
- package/dist/react/config.d.ts +13 -0
- package/dist/react/config.js +14 -0
- package/dist/react/config.js.map +1 -0
- package/dist/react/context.d.ts +55 -0
- package/dist/react/context.js +42 -0
- package/dist/react/context.js.map +1 -0
- package/dist/react/crop.d.ts +49 -0
- package/dist/react/crop.js +107 -0
- package/dist/react/crop.js.map +1 -0
- package/dist/react/engagement.d.ts +38 -0
- package/dist/react/engagement.js +88 -0
- package/dist/react/engagement.js.map +1 -0
- package/dist/react/folder.d.ts +103 -0
- package/dist/react/folder.js +240 -0
- package/dist/react/folder.js.map +1 -0
- package/dist/react/gallery.d.ts +140 -0
- package/dist/react/gallery.js +477 -0
- package/dist/react/gallery.js.map +1 -0
- package/dist/react/index.d.ts +21 -0
- package/dist/react/inline-preview.d.ts +24 -0
- package/dist/react/inline-preview.js +76 -0
- package/dist/react/inline-preview.js.map +1 -0
- package/dist/react/player.d.ts +70 -0
- package/dist/react/player.js +214 -0
- package/dist/react/player.js.map +1 -0
- package/dist/react/polls.d.ts +74 -0
- package/dist/react/polls.js +176 -0
- package/dist/react/polls.js.map +1 -0
- package/dist/react/posts.d.ts +59 -0
- package/dist/react/posts.js +149 -0
- package/dist/react/posts.js.map +1 -0
- package/dist/react/provider.d.ts +27 -0
- package/dist/react/provider.js +49 -0
- package/dist/react/provider.js.map +1 -0
- package/dist/react/public.d.ts +39 -0
- package/dist/react/public.js +70 -0
- package/dist/react/public.js.map +1 -0
- package/dist/react/read.d.ts +52 -0
- package/dist/react/read.js +144 -0
- package/dist/react/read.js.map +1 -0
- package/dist/react/resources.d.ts +73 -0
- package/dist/react/resources.js +247 -0
- package/dist/react/resources.js.map +1 -0
- package/dist/react/slot.d.ts +104 -0
- package/dist/react/slot.js +185 -0
- package/dist/react/slot.js.map +1 -0
- package/dist/react/store.d.ts +51 -0
- package/dist/react/store.js +165 -0
- package/dist/react/store.js.map +1 -0
- package/dist/react/upload.d.ts +86 -0
- package/dist/react/upload.js +155 -0
- package/dist/react/upload.js.map +1 -0
- package/dist/react/use-resource.d.ts +44 -0
- package/dist/react/use-resource.js +74 -0
- package/dist/react/use-resource.js.map +1 -0
- package/dist/react/video.d.ts +118 -0
- package/dist/react/video.js +184 -0
- package/dist/react/video.js.map +1 -0
- package/dist/react/viewport.d.ts +19 -0
- package/dist/react/viewport.js +30 -0
- package/dist/react/viewport.js.map +1 -0
- package/dist/react.js +21 -0
- package/dist/scope.d.ts +14 -0
- package/dist/scope.js +30 -0
- package/dist/scope.js.map +1 -0
- package/dist/styles.css +3 -0
- package/dist/ui/alert-dialog.d.ts +18 -0
- package/dist/ui/alert-dialog.js +86 -0
- package/dist/ui/alert-dialog.js.map +1 -0
- package/dist/ui/alert.d.ts +10 -0
- package/dist/ui/alert.js +38 -0
- package/dist/ui/alert.js.map +1 -0
- package/dist/ui/avatar.d.ts +11 -0
- package/dist/ui/avatar.js +31 -0
- package/dist/ui/avatar.js.map +1 -0
- package/dist/ui/badge.d.ts +7 -0
- package/dist/ui/badge.js +31 -0
- package/dist/ui/badge.js.map +1 -0
- package/dist/ui/button.d.ts +8 -0
- package/dist/ui/button.js +46 -0
- package/dist/ui/button.js.map +1 -0
- package/dist/ui/dialog.d.ts +17 -0
- package/dist/ui/dialog.js +91 -0
- package/dist/ui/dialog.js.map +1 -0
- package/dist/ui/dropdown-menu.d.ts +15 -0
- package/dist/ui/dropdown-menu.js +105 -0
- package/dist/ui/dropdown-menu.js.map +1 -0
- package/dist/ui/input.d.ts +3 -0
- package/dist/ui/input.js +17 -0
- package/dist/ui/input.js.map +1 -0
- package/dist/ui/label.d.ts +3 -0
- package/dist/ui/label.js +15 -0
- package/dist/ui/label.js.map +1 -0
- package/dist/ui/progress.d.ts +7 -0
- package/dist/ui/progress.js +31 -0
- package/dist/ui/progress.js.map +1 -0
- package/dist/ui/select.d.ts +15 -0
- package/dist/ui/select.js +98 -0
- package/dist/ui/select.js.map +1 -0
- package/dist/ui/skeleton.d.ts +2 -0
- package/dist/ui/skeleton.js +14 -0
- package/dist/ui/skeleton.js.map +1 -0
- package/dist/ui/slider.d.ts +3 -0
- package/dist/ui/slider.js +35 -0
- package/dist/ui/slider.js.map +1 -0
- package/dist/ui/switch.d.ts +5 -0
- package/dist/ui/switch.js +20 -0
- package/dist/ui/switch.js.map +1 -0
- package/dist/ui/tabs.d.ts +10 -0
- package/dist/ui/tabs.js +47 -0
- package/dist/ui/tabs.js.map +1 -0
- package/dist/ui/textarea.d.ts +3 -0
- package/dist/ui/textarea.js +15 -0
- package/dist/ui/textarea.js.map +1 -0
- package/dist/ui/toggle-group.d.ts +5 -0
- package/dist/ui/toggle-group.js +23 -0
- package/dist/ui/toggle-group.js.map +1 -0
- package/dist/urls/index.d.ts +100 -0
- package/dist/urls.js +118 -0
- package/dist/urls.js.map +1 -0
- package/package.json +120 -3
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { CommitBody, Edit, FileInfo, Op, PresetRule, ReadResult, RefBody } from '../generated/wire.js';
|
|
2
|
+
import { Http } from '../http.js';
|
|
3
|
+
import { MediaApi, ReadOptions } from './api.js';
|
|
4
|
+
import { Transport } from './transport.js';
|
|
5
|
+
/** Upload tuning for the media module. */
|
|
6
|
+
export interface MediaOptions {
|
|
7
|
+
/** Sends presigned PUTs. Default XMLHttpRequest (upload progress), else fetch. */
|
|
8
|
+
transport?: Transport;
|
|
9
|
+
/** Parallel parts per multipart upload (the pacer may run fewer). Default 4. */
|
|
10
|
+
concurrency?: number;
|
|
11
|
+
/** Retries per part and per idempotent API call. Default 5. */
|
|
12
|
+
retries?: number;
|
|
13
|
+
/** Delay before retry attempt (0-based); retryAfter is the server's hint in seconds. */
|
|
14
|
+
retryDelay?: (attempt: number, retryAfter?: number) => number;
|
|
15
|
+
/** Seconds one part should take. Default 30. */
|
|
16
|
+
targetPartSeconds?: number;
|
|
17
|
+
}
|
|
18
|
+
export interface Progress {
|
|
19
|
+
/** processing: committed, waiting for the worker (put). */
|
|
20
|
+
phase: "hashing" | "uploading" | "completing" | "processing";
|
|
21
|
+
loaded: number;
|
|
22
|
+
total: number;
|
|
23
|
+
}
|
|
24
|
+
export interface UploadOptions {
|
|
25
|
+
ref: RefBody;
|
|
26
|
+
/** The upload path: a literal ("cover") or under a pattern ("originals/001.png"); the server cleans it and adds the extension. */
|
|
27
|
+
path: string;
|
|
28
|
+
/** Content type; default the file's. */
|
|
29
|
+
type?: string;
|
|
30
|
+
/** Aborting pauses: a multipart upload stays resumable from the last state. */
|
|
31
|
+
signal?: AbortSignal;
|
|
32
|
+
onProgress?: (p: Progress) => void;
|
|
33
|
+
/** State saved from onState, to resume a multipart upload of the same file. */
|
|
34
|
+
resume?: UploadState;
|
|
35
|
+
/** Resumable state after every change; null once the upload completed. Persist it to survive a reload. */
|
|
36
|
+
onState?: (s: UploadState | null) => void;
|
|
37
|
+
}
|
|
38
|
+
/** An upload, ready for a put op. */
|
|
39
|
+
export interface UploadedFile {
|
|
40
|
+
/** The path to commit: cleaned, with an extension, named by the server for a Named upload. */
|
|
41
|
+
path: string;
|
|
42
|
+
/**
|
|
43
|
+
* The name to commit: the folder's identical blob ("sha256-{hex}-{uuid}") when
|
|
44
|
+
* exists, else the staged upload ("u-{uuid}") the worker hashes and places
|
|
45
|
+
* after the commit.
|
|
46
|
+
*/
|
|
47
|
+
blob: string;
|
|
48
|
+
type: string;
|
|
49
|
+
size: number;
|
|
50
|
+
/** The identical file was already in the item's folder; nothing was sent. */
|
|
51
|
+
exists: boolean;
|
|
52
|
+
/** The host processes files on upload: commit it unattached now (the queue does). */
|
|
53
|
+
processOnUpload?: boolean;
|
|
54
|
+
}
|
|
55
|
+
/** The put op's fields besides path and blob. */
|
|
56
|
+
export interface PutOptions {
|
|
57
|
+
/** Refuse to replace an existing upload. Default false. */
|
|
58
|
+
createOnly?: boolean;
|
|
59
|
+
edit?: Edit | null;
|
|
60
|
+
meta?: Record<string, unknown>;
|
|
61
|
+
index?: number;
|
|
62
|
+
/** Wait until the worker processed the upload (waitFor). Default true. */
|
|
63
|
+
wait?: boolean;
|
|
64
|
+
/** How long to wait, ms. */
|
|
65
|
+
timeout?: number;
|
|
66
|
+
/** The upload, before the commit. */
|
|
67
|
+
onUploaded?: (up: UploadedFile) => void;
|
|
68
|
+
}
|
|
69
|
+
export interface WaitOptions {
|
|
70
|
+
signal?: AbortSignal;
|
|
71
|
+
/** Poll interval, ms. Default 1000. */
|
|
72
|
+
interval?: number;
|
|
73
|
+
/** ms; then render_timeout. Default 120000. */
|
|
74
|
+
timeout?: number;
|
|
75
|
+
}
|
|
76
|
+
export interface PlannedPart {
|
|
77
|
+
number: number;
|
|
78
|
+
offset: number;
|
|
79
|
+
size: number;
|
|
80
|
+
sha256?: string;
|
|
81
|
+
}
|
|
82
|
+
/** A multipart upload in flight; JSON-serializable. */
|
|
83
|
+
export interface UploadState {
|
|
84
|
+
ticket: string;
|
|
85
|
+
path: string;
|
|
86
|
+
/** The staged upload ("u-{uuid}") the parts write. */
|
|
87
|
+
blob: string;
|
|
88
|
+
type: string;
|
|
89
|
+
size: number;
|
|
90
|
+
ref: RefBody;
|
|
91
|
+
file: {
|
|
92
|
+
name?: string;
|
|
93
|
+
lastModified?: number;
|
|
94
|
+
size: number;
|
|
95
|
+
};
|
|
96
|
+
limits: {
|
|
97
|
+
minPartSize: number;
|
|
98
|
+
maxPartSize: number;
|
|
99
|
+
maxParts: number;
|
|
100
|
+
};
|
|
101
|
+
parts: PlannedPart[];
|
|
102
|
+
processOnUpload?: boolean;
|
|
103
|
+
}
|
|
104
|
+
/** An upload to a server-named (Named) path: a post's or poll's image. */
|
|
105
|
+
export interface NamedOptions {
|
|
106
|
+
/** The requested path; the server names the file. Default the file's name. */
|
|
107
|
+
path?: string;
|
|
108
|
+
signal?: AbortSignal;
|
|
109
|
+
onProgress?: (p: Progress) => void;
|
|
110
|
+
/** Wait until the worker processed it. Default true. */
|
|
111
|
+
wait?: boolean;
|
|
112
|
+
/** How long to wait, ms. */
|
|
113
|
+
timeout?: number;
|
|
114
|
+
}
|
|
115
|
+
/** An upload to a Named path, committed. */
|
|
116
|
+
export interface NamedUpload {
|
|
117
|
+
/** The server's name for it ("i-{uuid}"), which content routes take. */
|
|
118
|
+
name: string;
|
|
119
|
+
path: string;
|
|
120
|
+
file: FileInfo;
|
|
121
|
+
}
|
|
122
|
+
/** The media kinds of post and poll folders (content.Media.PostKind and PollKind). */
|
|
123
|
+
export interface ContentFolders {
|
|
124
|
+
/** Default "post". */
|
|
125
|
+
post?: string;
|
|
126
|
+
/** Default "poll". */
|
|
127
|
+
poll?: string;
|
|
128
|
+
}
|
|
129
|
+
/** A file to upload again when its blob is gone at commit; type defaults to the file's. */
|
|
130
|
+
export type CommitSource = Blob | {
|
|
131
|
+
file: Blob;
|
|
132
|
+
type?: string;
|
|
133
|
+
};
|
|
134
|
+
export interface CommitOptions {
|
|
135
|
+
signal?: AbortSignal;
|
|
136
|
+
/** UUID for this complete batch. Keep it with unchanged ops for a later retry; default a new UUID. */
|
|
137
|
+
operationID?: string;
|
|
138
|
+
/** Persist the active batch before sending it, including any replacement after re-upload. Resume with its ops and operation_id. */
|
|
139
|
+
onState?: (batch: CommitBody) => void;
|
|
140
|
+
/** Blob ("sha256-…") → the file it was uploaded from. */
|
|
141
|
+
sources?: Record<string, CommitSource>;
|
|
142
|
+
}
|
|
143
|
+
type Uploadable = Blob & {
|
|
144
|
+
name?: string;
|
|
145
|
+
lastModified?: number;
|
|
146
|
+
};
|
|
147
|
+
/** A path names a file by its full path or, for an upload, its stem ("cover" for "cover.png"). */
|
|
148
|
+
export declare const samePath: (file: string, path: string) => boolean;
|
|
149
|
+
/** The path without its extension. */
|
|
150
|
+
export declare const stem: (path: string) => string;
|
|
151
|
+
/** The media module: uploads, commits, reads, frames and HLS. */
|
|
152
|
+
export declare class MediaClient {
|
|
153
|
+
private readonly http;
|
|
154
|
+
readonly api: MediaApi;
|
|
155
|
+
private readonly transport;
|
|
156
|
+
private readonly concurrency;
|
|
157
|
+
private readonly retries;
|
|
158
|
+
private readonly delay;
|
|
159
|
+
private readonly targetSeconds;
|
|
160
|
+
private presetList?;
|
|
161
|
+
private readonly folders;
|
|
162
|
+
constructor(http: Http, o?: MediaOptions, folders?: ContentFolders);
|
|
163
|
+
/**
|
|
164
|
+
* Uploads file to the item's folder: it hashes the whole file (off the
|
|
165
|
+
* main thread) and presigns {path, type, size, sha256}, then sends nothing
|
|
166
|
+
* (the folder holds the identical blob), or stages it: one checksum-bound
|
|
167
|
+
* PUT up to 64 MiB, resumable multipart above. A refused presign throws
|
|
168
|
+
* before any bytes move. Commit the result with a put op (or use put());
|
|
169
|
+
* the worker then places a staged upload at the hash of its bytes.
|
|
170
|
+
*/
|
|
171
|
+
upload(file: Uploadable, o: UploadOptions): Promise<UploadedFile>;
|
|
172
|
+
/**
|
|
173
|
+
* Uploads file and commits it as a put to its path (with edit, meta and
|
|
174
|
+
* index), then by default waits until the worker processed it; resolves
|
|
175
|
+
* with the upload as an editor reads it.
|
|
176
|
+
*/
|
|
177
|
+
put(file: Uploadable, o: UploadOptions & PutOptions): Promise<FileInfo>;
|
|
178
|
+
/**
|
|
179
|
+
* Applies ops to the item in one conditional write; returns its uploads as
|
|
180
|
+
* an editor reads them. With sources (blob → the file uploaded as it), a
|
|
181
|
+
* not_uploaded refusal (the blob expired or is due for cleanup) uploads
|
|
182
|
+
* the affected files again and retries the commit once.
|
|
183
|
+
*/
|
|
184
|
+
commit(ref: RefBody, ops: Op[], o?: CommitOptions): Promise<FileInfo[]>;
|
|
185
|
+
/** The read API: the item's files under prefix in manifest order, with signed URLs for what this viewer may have. */
|
|
186
|
+
read(ref: RefBody, o?: ReadOptions & {
|
|
187
|
+
signal?: AbortSignal;
|
|
188
|
+
}): Promise<ReadResult>;
|
|
189
|
+
/**
|
|
190
|
+
* Polls an editor read until the upload at path (or with that stem) is
|
|
191
|
+
* processed: placed (not staged), nothing pending and its blob present (a
|
|
192
|
+
* frame grabbed).
|
|
193
|
+
* Rejects with its failure, not_found once it is gone, too_large while the
|
|
194
|
+
* item is full (nothing is processed until uploads are removed),
|
|
195
|
+
* render_timeout after the timeout.
|
|
196
|
+
*/
|
|
197
|
+
waitFor(ref: RefBody, path: string, o?: WaitOptions): Promise<FileInfo>;
|
|
198
|
+
/**
|
|
199
|
+
* The upload's editor view, for re-cropping: its URL and the upload's
|
|
200
|
+
* oriented size. Waits while it renders (an editor read asks for it);
|
|
201
|
+
* not_found when the path has no upload, render_timeout after the timeout
|
|
202
|
+
* (default 30 s).
|
|
203
|
+
*/
|
|
204
|
+
editorView(ref: RefBody, path: string, o?: WaitOptions): Promise<{
|
|
205
|
+
url: string;
|
|
206
|
+
width: number;
|
|
207
|
+
height: number;
|
|
208
|
+
edit?: Edit;
|
|
209
|
+
}>;
|
|
210
|
+
/**
|
|
211
|
+
* Every kind's public presets, fetched once per client: crop bounds,
|
|
212
|
+
* widths and default images. An item's current image is in its read's
|
|
213
|
+
* `public`, never built from a preset. Shared by every caller, so it takes
|
|
214
|
+
* no signal; a failed fetch is retried on the next call.
|
|
215
|
+
*/
|
|
216
|
+
presets(): Promise<PresetRule[]>;
|
|
217
|
+
/** A JPEG still of the video upload at path, t seconds in, w pixels wide (default the frame's). */
|
|
218
|
+
getFrame(ref: RefBody, path: string, t: number, w?: number, signal?: AbortSignal): Promise<Blob>;
|
|
219
|
+
/** The folder of an HLS ladder from a read's `hls`: `{media}/{kind}/{id}/hls/{dir}`; master.m3u8 and sprite.vtt resolve under it. */
|
|
220
|
+
hlsBase(ref: RefBody, dir: string): string;
|
|
221
|
+
/** hls.js `xhrSetup` for playlists on the API (the client's token and credentials); pass it to players as is. */
|
|
222
|
+
get xhrSetup(): (xhr: XMLHttpRequest, url: string) => Promise<void>;
|
|
223
|
+
/**
|
|
224
|
+
* Uploads an image to the item's server-named upload path and commits it
|
|
225
|
+
* (by default waiting until it is processed); resolves with the name content
|
|
226
|
+
* routes take: a poll or option image, a post cover.
|
|
227
|
+
*/
|
|
228
|
+
uploadNamed(ref: RefBody, file: Uploadable, o?: NamedOptions): Promise<NamedUpload>;
|
|
229
|
+
/** An image for a post's rich-text body: uploaded to the post's folder; resolves with the URL to place in the body. */
|
|
230
|
+
uploadInline(post: string, file: Uploadable, o?: NamedOptions): Promise<NamedUpload & {
|
|
231
|
+
url: string;
|
|
232
|
+
}>;
|
|
233
|
+
/** The media folder of a post. */
|
|
234
|
+
postRef(id: string): RefBody;
|
|
235
|
+
/** The media folder of a poll. */
|
|
236
|
+
pollRef(id: string): RefBody;
|
|
237
|
+
/** Discards a paused multipart upload. */
|
|
238
|
+
discard(state: UploadState): Promise<void>;
|
|
239
|
+
private resumeMultipart;
|
|
240
|
+
private multipart;
|
|
241
|
+
private complete;
|
|
242
|
+
private retry;
|
|
243
|
+
}
|
|
244
|
+
/** Exponential backoff from 1 s to 30 s with jitter, or the server's Retry-After. */
|
|
245
|
+
export declare function backoff(attempt: number, retryAfter?: number): number;
|
|
246
|
+
export declare function sleep(ms: number, signal?: AbortSignal): Promise<void>;
|
|
247
|
+
export {};
|
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
import { ContentKitError as e, aborted as t, failureError as n, throwIfAborted as r, toContentKitError as i } from "../errors.js";
|
|
2
|
+
import { call as a } from "../route.js";
|
|
3
|
+
import { MediaApi as o } from "./api.js";
|
|
4
|
+
import { sha256Hex as s } from "./hash.js";
|
|
5
|
+
import { Pacer as c } from "./pacer.js";
|
|
6
|
+
import { defaultTransport as l } from "./transport.js";
|
|
7
|
+
//#region src/client/media/client.ts
|
|
8
|
+
var u = /^i-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/, d = (e, t) => e === t || f(e) === t, f = (e) => {
|
|
9
|
+
let t = e.lastIndexOf(".");
|
|
10
|
+
return t > e.lastIndexOf("/") + 1 ? e.slice(0, t) : e;
|
|
11
|
+
}, p = class {
|
|
12
|
+
http;
|
|
13
|
+
api;
|
|
14
|
+
transport;
|
|
15
|
+
concurrency;
|
|
16
|
+
retries;
|
|
17
|
+
delay;
|
|
18
|
+
targetSeconds;
|
|
19
|
+
presetList;
|
|
20
|
+
folders;
|
|
21
|
+
constructor(e, t = {}, n = {}) {
|
|
22
|
+
this.http = e, this.folders = {
|
|
23
|
+
post: n.post ?? "post",
|
|
24
|
+
poll: n.poll ?? "poll"
|
|
25
|
+
}, this.api = new o(e), this.transport = t.transport ?? l, this.concurrency = t.concurrency ?? 4, this.retries = t.retries ?? 5, this.delay = t.retryDelay ?? h, this.targetSeconds = t.targetPartSeconds ?? 30;
|
|
26
|
+
}
|
|
27
|
+
async upload(t, n) {
|
|
28
|
+
let i = n.type || t.type;
|
|
29
|
+
if (!i) throw new e("invalid_request", "the file has no content type");
|
|
30
|
+
if (r(n.signal), n.resume) return this.resumeMultipart(t, n.resume, n);
|
|
31
|
+
let a = t.size, o = await s(t, {
|
|
32
|
+
signal: n.signal,
|
|
33
|
+
onProgress: (e) => n.onProgress?.({
|
|
34
|
+
phase: "hashing",
|
|
35
|
+
loaded: e,
|
|
36
|
+
total: a
|
|
37
|
+
})
|
|
38
|
+
}), c = () => this.api.presign({
|
|
39
|
+
ref: n.ref,
|
|
40
|
+
path: n.path,
|
|
41
|
+
type: i,
|
|
42
|
+
size: a,
|
|
43
|
+
sha256: o
|
|
44
|
+
}, n.signal), l = await c(), u = (e) => ({
|
|
45
|
+
path: e.path,
|
|
46
|
+
blob: e.blob,
|
|
47
|
+
type: i,
|
|
48
|
+
size: a,
|
|
49
|
+
exists: !!e.exists,
|
|
50
|
+
processOnUpload: !!e.process_on_upload
|
|
51
|
+
});
|
|
52
|
+
if (l.exists) return u(l);
|
|
53
|
+
if (l.multipart) {
|
|
54
|
+
let e = l.multipart, r = {
|
|
55
|
+
ticket: e.ticket,
|
|
56
|
+
path: l.path,
|
|
57
|
+
blob: l.blob,
|
|
58
|
+
type: i,
|
|
59
|
+
size: a,
|
|
60
|
+
ref: n.ref,
|
|
61
|
+
file: m(t),
|
|
62
|
+
limits: {
|
|
63
|
+
minPartSize: e.min_part_size,
|
|
64
|
+
maxPartSize: e.max_part_size,
|
|
65
|
+
maxParts: e.max_parts
|
|
66
|
+
},
|
|
67
|
+
parts: [],
|
|
68
|
+
processOnUpload: !!l.process_on_upload
|
|
69
|
+
};
|
|
70
|
+
return this.multipart(t, r, /* @__PURE__ */ new Set(), n);
|
|
71
|
+
}
|
|
72
|
+
return await this.retry(async () => {
|
|
73
|
+
l.exists || await this.transport(l.put, t, {
|
|
74
|
+
signal: n.signal,
|
|
75
|
+
onProgress: (e) => n.onProgress?.({
|
|
76
|
+
phase: "uploading",
|
|
77
|
+
loaded: e,
|
|
78
|
+
total: a
|
|
79
|
+
})
|
|
80
|
+
});
|
|
81
|
+
}, n.signal, async (e) => {
|
|
82
|
+
e.code === "storage" && e.status === 403 && (l = await c());
|
|
83
|
+
}), u(l);
|
|
84
|
+
}
|
|
85
|
+
async put(e, t) {
|
|
86
|
+
let n = await this.upload(e, t);
|
|
87
|
+
t.onUploaded?.(n);
|
|
88
|
+
let r = {
|
|
89
|
+
op: "put",
|
|
90
|
+
path: n.path,
|
|
91
|
+
blob: n.blob
|
|
92
|
+
};
|
|
93
|
+
t.createOnly && (r.create_id = crypto.randomUUID()), t.edit && (r.edit = t.edit), t.meta && (r.meta = t.meta), t.index !== void 0 && (r.index = t.index);
|
|
94
|
+
let i = await this.commit(t.ref, [r], {
|
|
95
|
+
signal: t.signal,
|
|
96
|
+
sources: { [n.blob]: {
|
|
97
|
+
file: e,
|
|
98
|
+
type: n.type
|
|
99
|
+
} }
|
|
100
|
+
});
|
|
101
|
+
return t.wait === !1 ? i.find((e) => e.path === n.path) ?? {
|
|
102
|
+
path: n.path,
|
|
103
|
+
type: n.type
|
|
104
|
+
} : (t.onProgress?.({
|
|
105
|
+
phase: "processing",
|
|
106
|
+
loaded: n.size,
|
|
107
|
+
total: n.size
|
|
108
|
+
}), this.waitFor(t.ref, n.path, {
|
|
109
|
+
signal: t.signal,
|
|
110
|
+
timeout: t.timeout
|
|
111
|
+
}));
|
|
112
|
+
}
|
|
113
|
+
async commit(t, n, r = {}) {
|
|
114
|
+
let i = this.http.captureChanges(), a = structuredClone({
|
|
115
|
+
ref: t,
|
|
116
|
+
ops: n,
|
|
117
|
+
operation_id: r.operationID ?? crypto.randomUUID()
|
|
118
|
+
});
|
|
119
|
+
r.onState?.(structuredClone(a));
|
|
120
|
+
let o;
|
|
121
|
+
try {
|
|
122
|
+
o = (await this.retry(() => this.api.commit(a, r.signal), r.signal)).files;
|
|
123
|
+
} catch (t) {
|
|
124
|
+
if (!(t instanceof e) || t.code !== "not_uploaded") throw t;
|
|
125
|
+
let n = r.sources ?? {}, i = a.ops.filter((e) => e.op === "put" && e.blob && e.blob in n), s = [...new Set(i.map((e) => e.blob))].filter((e) => !t.blobs || t.blobs.includes(e));
|
|
126
|
+
if (s.length === 0) throw t;
|
|
127
|
+
let c = /* @__PURE__ */ new Map();
|
|
128
|
+
for (let e of s) {
|
|
129
|
+
let t = n[e], o = t instanceof Blob ? t : t.file, s = t instanceof Blob ? void 0 : t.type, l = i.find((t) => t.blob === e);
|
|
130
|
+
c.set(e, (await this.upload(o, {
|
|
131
|
+
ref: a.ref,
|
|
132
|
+
path: l.path,
|
|
133
|
+
type: s,
|
|
134
|
+
signal: r.signal
|
|
135
|
+
})).blob);
|
|
136
|
+
}
|
|
137
|
+
let l = a.ops.map((e) => e.blob && c.has(e.blob) ? {
|
|
138
|
+
...e,
|
|
139
|
+
blob: c.get(e.blob)
|
|
140
|
+
} : e), u = {
|
|
141
|
+
ref: a.ref,
|
|
142
|
+
ops: l,
|
|
143
|
+
operation_id: crypto.randomUUID()
|
|
144
|
+
};
|
|
145
|
+
r.onState?.(structuredClone(u)), o = (await this.retry(() => this.api.commit(u, r.signal), r.signal)).files;
|
|
146
|
+
}
|
|
147
|
+
return i({
|
|
148
|
+
type: "media.committed",
|
|
149
|
+
ref: {
|
|
150
|
+
kind: t.kind,
|
|
151
|
+
id: t.id
|
|
152
|
+
},
|
|
153
|
+
files: o
|
|
154
|
+
}), o;
|
|
155
|
+
}
|
|
156
|
+
async read(e, t = {}) {
|
|
157
|
+
return this.api.itemURL(e), this.retry(() => this.api.read(e, t, t.signal), t.signal);
|
|
158
|
+
}
|
|
159
|
+
async waitFor(t, r, i = {}) {
|
|
160
|
+
let a = this.http.captureChanges(), o = Date.now() + (i.timeout ?? 12e4);
|
|
161
|
+
for (;;) {
|
|
162
|
+
let s = await this.read(t, {
|
|
163
|
+
editor: !0,
|
|
164
|
+
prefix: f(r),
|
|
165
|
+
signal: i.signal
|
|
166
|
+
}), c = s.files.find((e) => e.upload && d(e.path, r));
|
|
167
|
+
if (!c) throw new e("not_found", `no upload ${r}`, { status: 404 });
|
|
168
|
+
if (c.failed) throw n(c.failed);
|
|
169
|
+
if (!c.pending?.length && !c.staged && (c.size ?? 0) > 0) return a({
|
|
170
|
+
type: "media.processed",
|
|
171
|
+
ref: {
|
|
172
|
+
kind: t.kind,
|
|
173
|
+
id: t.id
|
|
174
|
+
},
|
|
175
|
+
file: c
|
|
176
|
+
}), c;
|
|
177
|
+
if (s.full) throw new e("too_large", `${r} waits: the item is full; remove uploads to process more`, { status: 413 });
|
|
178
|
+
if (Date.now() >= o) throw new e("render_timeout", `${r} is still processing`);
|
|
179
|
+
await g(i.interval ?? 1e3, i.signal);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
async editorView(t, r, i = {}) {
|
|
183
|
+
let a = Date.now() + (i.timeout ?? 3e4);
|
|
184
|
+
for (;;) {
|
|
185
|
+
let o = (await this.read(t, {
|
|
186
|
+
editor: !0,
|
|
187
|
+
prefix: f(r),
|
|
188
|
+
signal: i.signal
|
|
189
|
+
})).files.find((e) => e.upload && d(e.path, r));
|
|
190
|
+
if (!o) throw new e("not_found", `no upload ${r}`, { status: 404 });
|
|
191
|
+
if (o.editor_url && o.w && o.h) return {
|
|
192
|
+
url: o.editor_url,
|
|
193
|
+
width: o.w,
|
|
194
|
+
height: o.h,
|
|
195
|
+
...o.edit ? { edit: o.edit } : {}
|
|
196
|
+
};
|
|
197
|
+
if (o.failed) throw n(o.failed);
|
|
198
|
+
if (Date.now() >= a) throw new e("render_timeout", `the editor view of ${r} is still rendering`);
|
|
199
|
+
await g(i.interval ?? 1e3, i.signal);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
presets() {
|
|
203
|
+
return this.presetList ??= this.retry(() => this.api.presets()).catch((e) => {
|
|
204
|
+
throw this.presetList = void 0, e;
|
|
205
|
+
}), this.presetList;
|
|
206
|
+
}
|
|
207
|
+
getFrame(e, t, n, r, i) {
|
|
208
|
+
return this.retry(() => this.api.frame(e, t, n, r, i), i);
|
|
209
|
+
}
|
|
210
|
+
hlsBase(e, t) {
|
|
211
|
+
return `${this.api.itemURL(e)}/hls/${t}`;
|
|
212
|
+
}
|
|
213
|
+
get xhrSetup() {
|
|
214
|
+
return this.http.xhrSetup;
|
|
215
|
+
}
|
|
216
|
+
async uploadNamed(t, n, r = {}) {
|
|
217
|
+
let i = await this.put(n, {
|
|
218
|
+
ref: t,
|
|
219
|
+
path: r.path ?? (n.name || "image"),
|
|
220
|
+
signal: r.signal,
|
|
221
|
+
onProgress: r.onProgress,
|
|
222
|
+
wait: r.wait,
|
|
223
|
+
timeout: r.timeout
|
|
224
|
+
}), a = f(i.path.slice(i.path.lastIndexOf("/") + 1));
|
|
225
|
+
if (!u.test(a)) throw new e("invalid_request", `${i.path} is not a server-named upload path of ${t.kind}`);
|
|
226
|
+
return {
|
|
227
|
+
name: a,
|
|
228
|
+
path: i.path,
|
|
229
|
+
file: i
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
async uploadInline(e, t, n = {}) {
|
|
233
|
+
let r = await this.uploadNamed(this.postRef(e), t, n), i = await a(this.http, "POST", "/posts/{id}/images", {
|
|
234
|
+
params: { id: e },
|
|
235
|
+
body: { image: r.name },
|
|
236
|
+
signal: n.signal
|
|
237
|
+
});
|
|
238
|
+
return {
|
|
239
|
+
...r,
|
|
240
|
+
url: i.url
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
postRef(e) {
|
|
244
|
+
return {
|
|
245
|
+
kind: this.folders.post,
|
|
246
|
+
id: e
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
pollRef(e) {
|
|
250
|
+
return {
|
|
251
|
+
kind: this.folders.poll,
|
|
252
|
+
id: e
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
async discard(e) {
|
|
256
|
+
await this.api.abort(e.ref, { ticket: e.ticket });
|
|
257
|
+
}
|
|
258
|
+
async resumeMultipart(t, n, r) {
|
|
259
|
+
let i = m(t);
|
|
260
|
+
if (i.size !== n.size || i.name !== n.file.name || i.lastModified !== n.file.lastModified) throw new e("resume_mismatch", "the saved upload is for a different file");
|
|
261
|
+
let a;
|
|
262
|
+
try {
|
|
263
|
+
a = await this.retry(() => this.api.listParts(n.ref, { ticket: n.ticket }, r.signal), r.signal);
|
|
264
|
+
} catch (t) {
|
|
265
|
+
if (t instanceof e && t.code === "not_found") return this.complete(n, r);
|
|
266
|
+
throw t;
|
|
267
|
+
}
|
|
268
|
+
let o = /* @__PURE__ */ new Set();
|
|
269
|
+
for (let e of a.parts) {
|
|
270
|
+
let i = n.parts.find((t) => t.number === e.number);
|
|
271
|
+
if (!i || i.size !== e.size || e.sha256 && i.sha256 !== e.sha256) return await this.discard(n).catch(() => {}), r.onState?.(null), this.upload(t, {
|
|
272
|
+
...r,
|
|
273
|
+
resume: void 0
|
|
274
|
+
});
|
|
275
|
+
o.add(e.number);
|
|
276
|
+
}
|
|
277
|
+
return this.multipart(t, structuredClone(n), o, r);
|
|
278
|
+
}
|
|
279
|
+
async multipart(e, n, r, i) {
|
|
280
|
+
let a = new c({
|
|
281
|
+
...n.limits,
|
|
282
|
+
maxConcurrency: this.concurrency,
|
|
283
|
+
targetSeconds: this.targetSeconds
|
|
284
|
+
}), o = () => i.onState?.(structuredClone(n)), l = /* @__PURE__ */ new Map(), u = n.parts.filter((e) => r.has(e.number)).reduce((e, t) => e + t.size, 0), d = () => {
|
|
285
|
+
let e = u;
|
|
286
|
+
for (let t of l.values()) e += t;
|
|
287
|
+
i.onProgress?.({
|
|
288
|
+
phase: "uploading",
|
|
289
|
+
loaded: e,
|
|
290
|
+
total: n.size
|
|
291
|
+
});
|
|
292
|
+
}, f = n.parts.filter((e) => !r.has(e.number)), p = n.parts.reduce((e, t) => Math.max(e, t.offset + t.size), 0), m = () => {
|
|
293
|
+
let e = f.shift();
|
|
294
|
+
if (e || p >= n.size) return e;
|
|
295
|
+
let t = {
|
|
296
|
+
number: n.parts.length + 1,
|
|
297
|
+
offset: p,
|
|
298
|
+
size: Math.min(a.partSize(), n.size - p)
|
|
299
|
+
};
|
|
300
|
+
return p += t.size, n.parts.push(t), t;
|
|
301
|
+
}, h = new AbortController(), g = i.signal ? AbortSignal.any([i.signal, h.signal]) : h.signal, _ = 0, v = [], y = () => new Promise((e, n) => {
|
|
302
|
+
let r = () => {
|
|
303
|
+
g.removeEventListener("abort", i), _++, e();
|
|
304
|
+
}, i = () => {
|
|
305
|
+
v.splice(v.indexOf(r) >>> 0, 1), n(t(g));
|
|
306
|
+
};
|
|
307
|
+
if (_ < a.concurrency) return r();
|
|
308
|
+
if (g.aborted) return n(t(g));
|
|
309
|
+
g.addEventListener("abort", i, { once: !0 }), v.push(r);
|
|
310
|
+
}), b = () => {
|
|
311
|
+
for (_--; _ < a.concurrency && v.length;) v.shift()();
|
|
312
|
+
}, x = async (t) => {
|
|
313
|
+
let r = e.slice(t.offset, t.offset + t.size);
|
|
314
|
+
await this.retry(async () => {
|
|
315
|
+
t.sha256 || (t.sha256 = await s(r, { signal: g }), o());
|
|
316
|
+
let { parts: e } = await this.api.parts(n.ref, {
|
|
317
|
+
ticket: n.ticket,
|
|
318
|
+
parts: [{
|
|
319
|
+
number: t.number,
|
|
320
|
+
size: t.size,
|
|
321
|
+
sha256: t.sha256
|
|
322
|
+
}]
|
|
323
|
+
}, g), i = e[0]?.request;
|
|
324
|
+
await y();
|
|
325
|
+
let c = performance.now(), f = _;
|
|
326
|
+
try {
|
|
327
|
+
await this.transport(i, r, {
|
|
328
|
+
signal: g,
|
|
329
|
+
onProgress: (e) => {
|
|
330
|
+
l.set(t.number, e), d();
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
} finally {
|
|
334
|
+
l.delete(t.number), b();
|
|
335
|
+
}
|
|
336
|
+
a.record(t.size, performance.now() - c, f), u += t.size, d();
|
|
337
|
+
}, g);
|
|
338
|
+
};
|
|
339
|
+
o(), d();
|
|
340
|
+
let S = /* @__PURE__ */ new Set(), C;
|
|
341
|
+
for (;;) {
|
|
342
|
+
let e;
|
|
343
|
+
for (; C === void 0 && S.size < a.concurrency + 2 && (e = m());) {
|
|
344
|
+
o();
|
|
345
|
+
let t = x(e).then(() => void S.delete(t), (e) => {
|
|
346
|
+
S.delete(t), C === void 0 && (C = e, h.abort());
|
|
347
|
+
});
|
|
348
|
+
S.add(t);
|
|
349
|
+
}
|
|
350
|
+
if (S.size === 0) break;
|
|
351
|
+
await Promise.race(S);
|
|
352
|
+
}
|
|
353
|
+
if (C !== void 0) throw i.signal?.aborted ? t(i.signal) : C;
|
|
354
|
+
return this.complete(n, i);
|
|
355
|
+
}
|
|
356
|
+
async complete(e, t) {
|
|
357
|
+
t.onProgress?.({
|
|
358
|
+
phase: "completing",
|
|
359
|
+
loaded: e.size,
|
|
360
|
+
total: e.size
|
|
361
|
+
});
|
|
362
|
+
let n = await this.retry(() => this.api.complete(e.ref, { ticket: e.ticket }, t.signal), t.signal);
|
|
363
|
+
return t.onState?.(null), {
|
|
364
|
+
path: e.path,
|
|
365
|
+
blob: n.blob,
|
|
366
|
+
type: n.type,
|
|
367
|
+
size: n.size,
|
|
368
|
+
exists: !1,
|
|
369
|
+
processOnUpload: e.processOnUpload
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
async retry(e, n, r) {
|
|
373
|
+
for (let a = 0;; a++) try {
|
|
374
|
+
return await e();
|
|
375
|
+
} catch (e) {
|
|
376
|
+
let o = i(e);
|
|
377
|
+
if (n?.aborted) throw t(n);
|
|
378
|
+
if (!o.transient || a >= this.retries) throw o;
|
|
379
|
+
await g(this.delay(a, o.retryAfter), n), await r?.(o);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
};
|
|
383
|
+
function m(e) {
|
|
384
|
+
return {
|
|
385
|
+
name: e.name,
|
|
386
|
+
lastModified: e.lastModified,
|
|
387
|
+
size: e.size
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
function h(e, t) {
|
|
391
|
+
return t ? t * 1e3 : Math.min(3e4, 1e3 * 2 ** e) * (.75 + Math.random() * .5);
|
|
392
|
+
}
|
|
393
|
+
function g(e, n) {
|
|
394
|
+
return new Promise((r, i) => {
|
|
395
|
+
if (n?.aborted) return i(t(n));
|
|
396
|
+
let a = setTimeout(() => {
|
|
397
|
+
n?.removeEventListener("abort", o), r();
|
|
398
|
+
}, e), o = () => {
|
|
399
|
+
clearTimeout(a), i(t(n));
|
|
400
|
+
};
|
|
401
|
+
n?.addEventListener("abort", o, { once: !0 });
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
//#endregion
|
|
405
|
+
export { p as MediaClient, h as backoff, d as samePath, g as sleep, f as stem };
|
|
406
|
+
|
|
407
|
+
//# sourceMappingURL=client.js.map
|