@devultur/convex 1.5.0 → 1.5.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.
@@ -0,0 +1,22 @@
1
+ "use client";
2
+ import "../chunk-O76FU54F.js";
3
+ import {
4
+ DevulturApiContext,
5
+ DevulturContext,
6
+ DevulturProgressContext,
7
+ useCanDeliver,
8
+ useDevultur,
9
+ useDevulturApi,
10
+ useDevulturOptional,
11
+ useDevulturProgress
12
+ } from "../chunk-FOBFHC4A.js";
13
+ export {
14
+ DevulturApiContext,
15
+ DevulturContext,
16
+ DevulturProgressContext,
17
+ useCanDeliver,
18
+ useDevultur,
19
+ useDevulturApi,
20
+ useDevulturOptional,
21
+ useDevulturProgress
22
+ };
@@ -0,0 +1,39 @@
1
+ import { DevulturMedia } from '@devultur/core';
2
+ import { M as MediaRenderOptions } from '../contexts-6F8TJINX.js';
3
+ export { D as DevulturApi, b as DevulturApiContext, c as DevulturContext, d as DevulturContextValue, e as DevulturProgressContext, f as DevulturProgressContextValue, U as UploadOptions, g as UploadedMedia, u as useCanDeliver, i as useDevultur, j as useDevulturApi, k as useDevulturOptional, l as useDevulturProgress } from '../contexts-6F8TJINX.js';
4
+ import 'react';
5
+ import '@devultur/react';
6
+ import 'convex/server';
7
+ import 'convex/values';
8
+
9
+ /**
10
+ * Ready-to-use delivery URL for a key, with the context's viewer token already injected. The consumer
11
+ * never touches the token or the query — it only declares what it wants (download, resize, etc.).
12
+ *
13
+ * @example
14
+ * <img src={useMediaUrl(key)} />
15
+ * <a href={useMediaUrl(key, { download: true })} download>Download</a>
16
+ * <img src={useMediaUrl(key, { width: 512, format: "webp" })} />
17
+ */
18
+ declare function useMediaUrl(key: string | null | undefined, options?: MediaRenderOptions): string | null;
19
+ interface VideoProps {
20
+ src: string;
21
+ token: string | undefined;
22
+ captions: {
23
+ locale: string;
24
+ label: string;
25
+ src: string;
26
+ }[];
27
+ /** Session secret → `<VideoPlayer>` sends it in `${SESSION_HEADER}` on hls.js/captions requests. */
28
+ sessionSecret?: string;
29
+ }
30
+ /**
31
+ * Token-transparent props for `<VideoPlayer>` from a video reference: builds the HLS playlist `src`,
32
+ * the viewer `token` (only if private), and the `captions` for the requested locales.
33
+ * The consumer just does `<VideoPlayer {...useVideoProps(lesson.video, { locales })} />`.
34
+ */
35
+ declare function useVideoProps(media: DevulturMedia | null | undefined, options?: {
36
+ locales?: string[];
37
+ }): VideoProps | null;
38
+
39
+ export { type VideoProps, useMediaUrl, useVideoProps };
@@ -0,0 +1,28 @@
1
+ "use client";
2
+ import {
3
+ useMediaUrl,
4
+ useVideoProps
5
+ } from "../chunk-AUAWZ5BD.js";
6
+ import "../chunk-O76FU54F.js";
7
+ import {
8
+ DevulturApiContext,
9
+ DevulturContext,
10
+ DevulturProgressContext,
11
+ useCanDeliver,
12
+ useDevultur,
13
+ useDevulturApi,
14
+ useDevulturOptional,
15
+ useDevulturProgress
16
+ } from "../chunk-FOBFHC4A.js";
17
+ export {
18
+ DevulturApiContext,
19
+ DevulturContext,
20
+ DevulturProgressContext,
21
+ useCanDeliver,
22
+ useDevultur,
23
+ useDevulturApi,
24
+ useDevulturOptional,
25
+ useDevulturProgress,
26
+ useMediaUrl,
27
+ useVideoProps
28
+ };
package/dist/react.d.ts CHANGED
@@ -1,134 +1,18 @@
1
1
  import React from 'react';
2
- import { DevulturMedia, MediaUrlOptions, Visibility, ProcessingPhase, FailureReason, MediaStatusValue } from '@devultur/core';
3
- import { UploadProgress, BakeOutputFormat, MediaUploadState, MediaUploadError } from '@devultur/react';
2
+ import { V as ViewerTokenAction, a as ViewerTokenArgs, D as DevulturApi } from './contexts-6F8TJINX.js';
3
+ export { b as DevulturApiContext, c as DevulturContext, d as DevulturContextValue, e as DevulturProgressContext, f as DevulturProgressContextValue, T as TokenStatus, U as UploadOptions, g as UploadedMedia, h as ViewerTokenResult, u as useCanDeliver, i as useDevultur, j as useDevulturApi, k as useDevulturOptional, l as useDevulturProgress } from './contexts-6F8TJINX.js';
4
+ import { BakeOutputFormat, MediaUploadState, MediaUploadError } from '@devultur/react';
4
5
  export { MediaUploadError, MediaUploadState, UploadProgress } from '@devultur/react';
5
- import { FunctionReference } from 'convex/server';
6
- import { Value } from 'convex/values';
7
- import { A as AttachmentLabels, M as MediaLibraryLabels, P as PreviewLabels, a as MediaPickerLabels, b as MediaFetchError } from './preview-labels-C2nUUY_f.js';
6
+ import { A as AttachmentLabels, b as MediaFetchError, M as MediaLibraryLabels, P as PreviewLabels, a as MediaPickerLabels } from './preview-labels-C2nUUY_f.js';
8
7
  export { c as AttachmentKind, d as MediaFetchErrorCode, e as defaultAttachmentLabels, f as defaultMediaLibraryLabels, g as defaultMediaPickerLabels, h as defaultPreviewLabels, i as formatDuration, j as formatFileSize } from './preview-labels-C2nUUY_f.js';
8
+ import { Visibility, DevulturMedia, MediaUrlOptions, MediaStatusValue, ProcessingPhase, FailureReason } from '@devultur/core';
9
+ import { VideoProps } from './react/hooks.js';
10
+ export { useMediaUrl, useVideoProps } from './react/hooks.js';
9
11
  import { M as MediaRecord } from './types-C0ruHUcu.js';
10
12
  import { P as PdfjsLoader } from './pdf-render-BwJGagvz.js';
11
13
  export { a as PdfjsModule } from './pdf-render-BwJGagvz.js';
12
-
13
- /** What a viewer token action returns: the token with its lifetime, or the bare token (default lifetime). */
14
- type ViewerTokenResult = {
15
- token: string;
16
- expiresIn: number;
17
- } | string;
18
- /** Extra arguments sent with `sessionSecret` to the viewer token action. */
19
- type ViewerTokenArgs = Record<string, Value>;
20
- /**
21
- * Where the viewer token for the current `tokenArgs` stands: not requested yet, being issued (no token yet), held, or
22
- * failed (the action threw or returned no token). A renewal in flight, or one that failed, keeps `"ready"`.
23
- */
24
- type TokenStatus = "idle" | "loading" | "ready" | "error";
25
-
26
- /** Transform/delivery options for media URLs (without `token`, which the context injects). */
27
- type MediaRenderOptions = Omit<MediaUrlOptions, "token">;
28
- /**
29
- * The viewer token action: the component's `issueViewerToken` (as `defineDevulturFunctions` or `exposeApi` export it,
30
- * where `sessionSecret` is optional) or an app's own, which may require it. The providers always send it.
31
- */
32
- type ViewerTokenAction = FunctionReference<"action", "public", {
33
- sessionSecret?: string;
34
- }>;
35
- interface MediaSession {
36
- token: string | null;
37
- /** Where the viewer token stands; `"error"` makes private previews fail fast with `token_unavailable`. */
38
- tokenStatus: TokenStatus;
39
- /** Why the last issuance failed (the action threw or returned no token), while `tokenStatus` is `"error"`. */
40
- tokenError: Error | null;
41
- /** Issues the viewer token again (after a failure, for example). Resolves to the new token, or `null`. */
42
- retryToken: () => Promise<string | null>;
43
- /**
44
- * Asks for the viewer token where it's issued lazily (`<DevulturViewerProvider lazyToken>`): the first private media
45
- * shown calls it, and so must code that reads `token` itself. A no-op once asked, and where the token is issued
46
- * right away (the default).
47
- */
48
- requestToken: () => void;
49
- baseUrl: string | null;
50
- /** Browser session secret → sent in `${SESSION_HEADER}` on every private delivery. */
51
- sessionSecret: string;
52
- /** Delivery URL from a reference (non-hook → usable in handlers and `.map`). Token-transparent. */
53
- url: (media: DevulturMedia, options?: MediaRenderOptions) => string;
54
- /** Downloads a video's subtitle text for a locale (auth-transparent). */
55
- getCaptionsText: (media: DevulturMedia, locale: string) => Promise<string>;
56
- /**
57
- * Re-issues the viewer token (new session fingerprint with the current UA/IP) and updates the context.
58
- * Single-flight: concurrent calls share the same issuance. Returns the new token (or null if it
59
- * failed). The render uses it to transparently recover from a 401 `session_mismatch`.
60
- */
61
- reissueToken: () => Promise<string | null>;
62
- }
63
-
64
- type AnyAction = FunctionReference<"action">;
65
- type AnyMutation = FunctionReference<"mutation">;
66
- type AnyQuery = FunctionReference<"query">;
67
- interface DevulturApi {
68
- issueViewerToken: AnyAction;
69
- createUploadUrl: AnyAction;
70
- /** Records an upload in the component after its PUT, so it shows in `listMedia`. Optional (uploads still work). */
71
- confirmUpload?: AnyAction;
72
- deleteMedia: AnyAction;
73
- /** Deletes the full folder of a video (raw/hls/thumbnails/captions). Required to delete videos. */
74
- deleteVideo?: AnyAction;
75
- /** Requests the transcode of an uploaded video. Required by `useMediaUpload` for auto-process. */
76
- processVideo?: AnyAction;
77
- getMedia?: AnyQuery;
78
- /** The library, newest first. Required by `useMediaLibrary` and `<MediaLibrary>`. */
79
- listMediaPage?: AnyQuery;
80
- /** The library matching a search. Required by `useMediaLibrary` and `<MediaLibrary>` to search. */
81
- searchMedia?: AnyQuery;
82
- saveProgress?: AnyMutation;
83
- loadProgress?: AnyQuery;
84
- markComplete?: AnyMutation;
85
- resetProgress?: AnyMutation;
86
- }
87
- interface UploadOptions {
88
- /**
89
- * Visibility override for this resource. Omitted → `config.upload.visibility` on your server, else the Worker's
90
- * default by type. Your guard can still rewrite it.
91
- */
92
- visibility?: Visibility;
93
- /** Progress of the PUT: bytes sent, total bytes and their fraction (0 to 1). */
94
- onProgress?: (progress: UploadProgress) => void;
95
- /** Aborts the PUT → `upload()` rejects with an `AbortError`. */
96
- signal?: AbortSignal;
97
- /** A PDF's page count to record with it, a hint (`countPdfPages` from `@devultur/convex/pdfjs` counts it). */
98
- pageCount?: number;
99
- }
100
- /**
101
- * The reference `upload()` resolves to: a `DevulturMedia` whose `key` is always set (the uploaded object's key; a
102
- * video's raw file, what `processVideo` takes). It stores as-is in a `dv.media()` field.
103
- */
104
- type UploadedMedia = DevulturMedia & {
105
- readonly key: string;
106
- };
107
- /**
108
- * What `useDevultur()` returns. Under a `<DevulturViewerProvider>`, `uploadUrl`, `upload` and `deleteMedia` throw a
109
- * `DevulturCapabilityError` (`capability_unavailable`).
110
- */
111
- interface DevulturContextValue extends MediaSession {
112
- uploadUrl: (file: File) => Promise<{
113
- url: string;
114
- key: string;
115
- }>;
116
- /** Uploads a file (reporting progress), records it in the component, and returns the reference ready to save. */
117
- upload: (file: File, options?: UploadOptions) => Promise<UploadedMedia>;
118
- /** Deletes a media by reference: video → full folder; image/file → the object. */
119
- deleteMedia: (media: DevulturMedia) => void;
120
- }
121
- declare function useDevultur(): DevulturContextValue;
122
- /**
123
- * `useDevultur()` for components that also render outside a provider: the same value under `<DevulturProvider>` or
124
- * `<DevulturViewerProvider>`, and `null` outside both instead of throwing.
125
- */
126
- declare function useDevulturOptional(): DevulturContextValue | null;
127
- /**
128
- * The `api` passed to `<DevulturProvider>`: your app's exported Devultur functions. Under a `<DevulturViewerProvider>`
129
- * it throws a `DevulturCapabilityError`.
130
- */
131
- declare function useDevulturApi(): DevulturApi;
14
+ import 'convex/server';
15
+ import 'convex/values';
132
16
 
133
17
  /** What `useDevultur()` can do only under a `<DevulturProvider>` given the matching actions. */
134
18
  type DevulturCapability = "upload" | "uploadUrl" | "deleteMedia" | "api";
@@ -234,6 +118,27 @@ interface AttachmentCardProps extends Omit<React.HTMLAttributes<HTMLElement>, "c
234
118
  */
235
119
  declare function AttachmentCard({ media, contentType, onOpen, preview, headingLevel, locale, labels, ...articleProps }: AttachmentCardProps): React.JSX.Element | null;
236
120
 
121
+ interface DownloadLinkProps extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, "href" | "download" | "media"> {
122
+ media: DevulturMedia | null | undefined;
123
+ /** Name it downloads as. Without this it uses the upload's original name. */
124
+ filename?: string;
125
+ /**
126
+ * A private download that failed: `token_unavailable` right away when the viewer token couldn't be issued
127
+ * (`useDevultur().retryToken()` tries again), `http_error` when the delivery refused it.
128
+ */
129
+ onDownloadError?: (error: MediaFetchError) => void;
130
+ children: React.ReactNode;
131
+ }
132
+ /**
133
+ * `<a>` that downloads a media with its original name (token-transparent). The worker serves it with
134
+ * `Content-Disposition: attachment`, so a click downloads the file instead of opening it in a tab.
135
+ *
136
+ * Private: an `<a download>` NAVIGATES, and a navigation can't send `${SESSION_HEADER}` → with session
137
+ * binding the gate gives a 401. So, for private media, we intercept the click, blob-fetch with the header
138
+ * (like private `<Image>`) and trigger the download from the object URL. Public keeps native navigation.
139
+ */
140
+ declare function DownloadLink({ media, filename, onDownloadError, children, ...anchorProps }: DownloadLinkProps): React.JSX.Element | null;
141
+
237
142
  /** An explicit `srcSet` is passed through to the `<img>` as is, and wins over the one `widths` builds. */
238
143
  interface ImageProps extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, "src" | "width" | "height"> {
239
144
  /** Typed reference. `null`/`undefined` → renders `fallback` (or `externalFallback`). Its `alt` is the default `alt`. */
@@ -275,6 +180,68 @@ interface ImageProps extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, "sr
275
180
  */
276
181
  declare function Image({ media, width, height, fit, format, quality, widths, sizes, fallback, externalFallback, render, alt, onLoadError, ...imgProps }: ImageProps): React.JSX.Element;
277
182
 
183
+ interface MediaStatusReturn {
184
+ status: MediaStatusValue;
185
+ /** Typed progress: `phase` is the pipeline step (no `as any`). */
186
+ progress: {
187
+ current: number;
188
+ total: number;
189
+ percent: number;
190
+ phase?: ProcessingPhase;
191
+ } | null;
192
+ error: string | null;
193
+ /** Categorized failure reason (null if it didn't fail). */
194
+ failureReason: FailureReason | null;
195
+ /** Whether the failure is retriable (null if it didn't fail). */
196
+ retriable: boolean | null;
197
+ isQueued: boolean;
198
+ isTranscoding: boolean;
199
+ isCaptioning: boolean;
200
+ isReady: boolean;
201
+ isFailed: boolean;
202
+ playlistUrl: string | null;
203
+ thumbnailKey: string | null;
204
+ captionLocales: string[];
205
+ duration: number | null;
206
+ isLoading: boolean;
207
+ }
208
+ declare function useDevulturMedia(key: string | null | undefined): MediaStatusReturn;
209
+ interface CaptionTrack {
210
+ locale: string;
211
+ label: string;
212
+ src: string;
213
+ }
214
+ /**
215
+ * A video's pipeline state as a **discriminated union** on `phase`: the render is an exhaustive
216
+ * `switch` (no boolean ordering or `as any`), and adding a new phase is a compile error until it's
217
+ * handled. `processing` carries typed `step`/`percent`; `ready` carries the ref + props ready for
218
+ * `<VideoPlayer>` (token-transparent); `failed` carries a categorized `reason` + `retriable`.
219
+ */
220
+ type VideoState = {
221
+ phase: "idle";
222
+ } | {
223
+ phase: "queued";
224
+ } | {
225
+ phase: "processing";
226
+ step: ProcessingPhase;
227
+ percent: number;
228
+ } | {
229
+ phase: "ready";
230
+ media: DevulturMedia;
231
+ playlist: string;
232
+ duration: number;
233
+ captions: CaptionTrack[];
234
+ playerProps: VideoProps;
235
+ } | {
236
+ phase: "failed";
237
+ reason: FailureReason;
238
+ message: string;
239
+ retriable: boolean;
240
+ };
241
+ declare function useVideoState(media: DevulturMedia | null | undefined, options?: {
242
+ locales?: string[];
243
+ }): VideoState;
244
+
278
245
  /** What `renderItem` gets besides the record. */
279
246
  interface MediaLibraryItemState {
280
247
  /** The record's reference (`mediaFromRecord`), `null` for a record without a visibility. */
@@ -657,6 +624,38 @@ interface MediaLibraryState {
657
624
  */
658
625
  declare function useMediaLibrary(options?: UseMediaLibraryOptions): MediaLibraryState;
659
626
 
627
+ interface UseMediaUploadOptions {
628
+ /** Resource visibility. Omitted → `config.upload.visibility`, else the Worker's default by type. Your guard can rewrite it. */
629
+ visibility?: Visibility;
630
+ /** Fires ONCE, at the persistence point (PUT done + transcode requested). */
631
+ onComplete?: (media: DevulturMedia) => void;
632
+ onError?: (error: MediaUploadError) => void;
633
+ /** Deletes this old video/asset after a successful PUT (best-effort). */
634
+ replaces?: DevulturMedia | null;
635
+ /** Auto-request the transcode for videos. Default `true`; `false` = upload the raw file unprocessed. */
636
+ process?: boolean;
637
+ /** Caption locales to request when transcoding. */
638
+ locales?: string[];
639
+ }
640
+ interface UseMediaUploadReturn {
641
+ /** Triggers the upload; resolves with the `DevulturMedia` at the persistence point, or `null` if cancelled/failed. */
642
+ upload: (file: File) => Promise<DevulturMedia | null>;
643
+ /** The reactive state machine for the full cycle. */
644
+ state: MediaUploadState;
645
+ /** Aborts the in-progress PUT (`uploading` phase). */
646
+ cancel: () => void;
647
+ /** Returns to `idle` and clears everything. */
648
+ reset: () => void;
649
+ }
650
+ /**
651
+ * Unified upload primitive: hides the seam between the (imperative) upload and the (reactive)
652
+ * transcode behind ONE state machine. The consumer calls `upload(file)`, persists the ref in
653
+ * `onComplete`, and renders a `switch` over `state.phase`. Video triggers the transcode on its own;
654
+ * image/file go straight to `ready`. Requires `createUploadUrl` + `getMedia` in the provider (and
655
+ * `processVideo` for video).
656
+ */
657
+ declare function useMediaUpload(options?: UseMediaUploadOptions): UseMediaUploadReturn;
658
+
660
659
  interface DevulturViewerProviderProps {
661
660
  /** Media worker base (e.g. `https://media.your-domain.com`). */
662
661
  baseUrl: string;
@@ -694,15 +693,6 @@ interface DevulturViewerProviderProps {
694
693
  */
695
694
  declare function DevulturViewerProvider({ issueViewerToken, ...props }: DevulturViewerProviderProps): React.JSX.Element;
696
695
 
697
- interface ProgressContextValue {
698
- save: (videoId: string, position: number) => Promise<void>;
699
- load: (videoId: string) => Promise<{
700
- lastPosition: number;
701
- completedAt: Date | null;
702
- } | null>;
703
- markComplete: (videoId: string) => Promise<void>;
704
- reset: (videoId: string) => Promise<void>;
705
- }
706
696
  interface DevulturProviderProps {
707
697
  api: DevulturApi;
708
698
  /** Media worker base (e.g. `https://media.your-domain.com`). Required for `useMediaUrl`. */
@@ -722,147 +712,5 @@ interface DevulturProviderProps {
722
712
  children: React.ReactNode;
723
713
  }
724
714
  declare function DevulturProvider({ api, baseUrl, tokenArgs, issueViewerToken, children }: DevulturProviderProps): React.JSX.Element;
725
- declare function useDevulturProgress(): ProgressContextValue;
726
- /**
727
- * Ready-to-use delivery URL for a key, with the context's viewer token already injected. The consumer
728
- * never touches the token or the query — it only declares what it wants (download, resize, etc.).
729
- *
730
- * @example
731
- * <img src={useMediaUrl(key)} />
732
- * <a href={useMediaUrl(key, { download: true })} download>Download</a>
733
- * <img src={useMediaUrl(key, { width: 512, format: "webp" })} />
734
- */
735
- declare function useMediaUrl(key: string | null | undefined, options?: MediaRenderOptions): string | null;
736
- interface VideoProps {
737
- src: string;
738
- token: string | undefined;
739
- captions: {
740
- locale: string;
741
- label: string;
742
- src: string;
743
- }[];
744
- /** Session secret → `<VideoPlayer>` sends it in `${SESSION_HEADER}` on hls.js/captions requests. */
745
- sessionSecret?: string;
746
- }
747
- /**
748
- * Token-transparent props for `<VideoPlayer>` from a video reference: builds the HLS playlist `src`,
749
- * the viewer `token` (only if private), and the `captions` for the requested locales.
750
- * The consumer just does `<VideoPlayer {...useVideoProps(lesson.video, { locales })} />`.
751
- */
752
- declare function useVideoProps(media: DevulturMedia | null | undefined, options?: {
753
- locales?: string[];
754
- }): VideoProps | null;
755
- interface DownloadLinkProps extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, "href" | "download" | "media"> {
756
- media: DevulturMedia | null | undefined;
757
- /** Name it downloads as. Without this it uses the upload's original name. */
758
- filename?: string;
759
- /**
760
- * A private download that failed: `token_unavailable` right away when the viewer token couldn't be issued
761
- * (`useDevultur().retryToken()` tries again), `http_error` when the delivery refused it.
762
- */
763
- onDownloadError?: (error: MediaFetchError) => void;
764
- children: React.ReactNode;
765
- }
766
- /**
767
- * `<a>` that downloads a media with its original name (token-transparent). The worker serves it with
768
- * `Content-Disposition: attachment`, so a click downloads the file instead of opening it in a tab.
769
- *
770
- * Private: an `<a download>` NAVIGATES, and a navigation can't send `${SESSION_HEADER}` → with session
771
- * binding the gate gives a 401. So, for private media, we intercept the click, blob-fetch with the header
772
- * (like private `<Image>`) and trigger the download from the object URL. Public keeps native navigation.
773
- */
774
- declare function DownloadLink({ media, filename, onDownloadError, children, ...anchorProps }: DownloadLinkProps): React.JSX.Element | null;
775
- interface MediaStatusReturn {
776
- status: MediaStatusValue;
777
- /** Typed progress: `phase` is the pipeline step (no `as any`). */
778
- progress: {
779
- current: number;
780
- total: number;
781
- percent: number;
782
- phase?: ProcessingPhase;
783
- } | null;
784
- error: string | null;
785
- /** Categorized failure reason (null if it didn't fail). */
786
- failureReason: FailureReason | null;
787
- /** Whether the failure is retriable (null if it didn't fail). */
788
- retriable: boolean | null;
789
- isQueued: boolean;
790
- isTranscoding: boolean;
791
- isCaptioning: boolean;
792
- isReady: boolean;
793
- isFailed: boolean;
794
- playlistUrl: string | null;
795
- thumbnailKey: string | null;
796
- captionLocales: string[];
797
- duration: number | null;
798
- isLoading: boolean;
799
- }
800
- declare function useDevulturMedia(key: string | null | undefined): MediaStatusReturn;
801
- interface CaptionTrack {
802
- locale: string;
803
- label: string;
804
- src: string;
805
- }
806
- /**
807
- * A video's pipeline state as a **discriminated union** on `phase`: the render is an exhaustive
808
- * `switch` (no boolean ordering or `as any`), and adding a new phase is a compile error until it's
809
- * handled. `processing` carries typed `step`/`percent`; `ready` carries the ref + props ready for
810
- * `<VideoPlayer>` (token-transparent); `failed` carries a categorized `reason` + `retriable`.
811
- */
812
- type VideoState = {
813
- phase: "idle";
814
- } | {
815
- phase: "queued";
816
- } | {
817
- phase: "processing";
818
- step: ProcessingPhase;
819
- percent: number;
820
- } | {
821
- phase: "ready";
822
- media: DevulturMedia;
823
- playlist: string;
824
- duration: number;
825
- captions: CaptionTrack[];
826
- playerProps: VideoProps;
827
- } | {
828
- phase: "failed";
829
- reason: FailureReason;
830
- message: string;
831
- retriable: boolean;
832
- };
833
- declare function useVideoState(media: DevulturMedia | null | undefined, options?: {
834
- locales?: string[];
835
- }): VideoState;
836
- interface UseMediaUploadOptions {
837
- /** Resource visibility. Omitted → `config.upload.visibility`, else the Worker's default by type. Your guard can rewrite it. */
838
- visibility?: Visibility;
839
- /** Fires ONCE, at the persistence point (PUT done + transcode requested). */
840
- onComplete?: (media: DevulturMedia) => void;
841
- onError?: (error: MediaUploadError) => void;
842
- /** Deletes this old video/asset after a successful PUT (best-effort). */
843
- replaces?: DevulturMedia | null;
844
- /** Auto-request the transcode for videos. Default `true`; `false` = upload the raw file unprocessed. */
845
- process?: boolean;
846
- /** Caption locales to request when transcoding. */
847
- locales?: string[];
848
- }
849
- interface UseMediaUploadReturn {
850
- /** Triggers the upload; resolves with the `DevulturMedia` at the persistence point, or `null` if cancelled/failed. */
851
- upload: (file: File) => Promise<DevulturMedia | null>;
852
- /** The reactive state machine for the full cycle. */
853
- state: MediaUploadState;
854
- /** Aborts the in-progress PUT (`uploading` phase). */
855
- cancel: () => void;
856
- /** Returns to `idle` and clears everything. */
857
- reset: () => void;
858
- }
859
- /**
860
- * Unified upload primitive: hides the seam between the (imperative) upload and the (reactive)
861
- * transcode behind ONE state machine. The consumer calls `upload(file)`, persists the ref in
862
- * `onComplete`, and renders a `switch` over `state.phase`. Video triggers the transcode on its own;
863
- * image/file go straight to `ready`. Requires `createUploadUrl` + `getMedia` in the provider (and
864
- * `processVideo` for video).
865
- */
866
- declare function useMediaUpload(options?: UseMediaUploadOptions): UseMediaUploadReturn;
867
715
 
868
- export { AttachmentCard, type AttachmentCardProps, AttachmentLabels, type CaptionTrack, CropUpload, type CropUploadLabels, type CropUploadProps, type CropUploadRenderProps, type DevulturApi, type DevulturCapability, DevulturCapabilityError, type DevulturContextValue, DevulturProvider, DevulturViewerProvider, type DevulturViewerProviderProps, DocumentLink, type DocumentLinkProps, DownloadLink, Image, type ImageProps, MediaFetchError, MediaLibrary, type MediaLibraryItemState, MediaLibraryLabels, type MediaLibraryPart, type MediaLibraryProps, type MediaLibraryState, type MediaLibraryStatus, type MediaObjectUrl, MediaPicker, MediaPickerLabels, type MediaPickerLibraryProps, type MediaPickerProps, type MediaPickerSelectionProps, type MediaPickerState, type MediaPickerUpload$1 as MediaPickerUpload, type MediaPickerUploadProps, type MediaPickerUploads, type PdfPreviewConfig, PdfPreviewProvider, PdfThumbnail, type PdfThumbnailProps, PdfjsLoader, Preview, type PreviewKind, PreviewLabels, type PreviewProps, type TokenStatus, type UploadOptions, type UploadedMedia, type UseMediaLibraryOptions, type UseMediaObjectUrlOptions, type UseMediaUploadOptions, type UseMediaUploadReturn, type VideoProps, type VideoState, type ViewerTokenArgs, type ViewerTokenResult, matchesAccept, useDevultur, useDevulturApi, useDevulturMedia, useDevulturOptional, useDevulturProgress, useMediaLibrary, useMediaObjectUrl, useMediaPicker, useMediaUpload, useMediaUrl, useVideoProps, useVideoState };
716
+ export { AttachmentCard, type AttachmentCardProps, AttachmentLabels, type CaptionTrack, CropUpload, type CropUploadLabels, type CropUploadProps, type CropUploadRenderProps, DevulturApi, type DevulturCapability, DevulturCapabilityError, DevulturProvider, DevulturViewerProvider, type DevulturViewerProviderProps, DocumentLink, type DocumentLinkProps, DownloadLink, type DownloadLinkProps, Image, type ImageProps, MediaFetchError, MediaLibrary, type MediaLibraryItemState, MediaLibraryLabels, type MediaLibraryPart, type MediaLibraryProps, type MediaLibraryState, type MediaLibraryStatus, type MediaObjectUrl, MediaPicker, MediaPickerLabels, type MediaPickerLibraryProps, type MediaPickerProps, type MediaPickerSelectionProps, type MediaPickerState, type MediaPickerUpload$1 as MediaPickerUpload, type MediaPickerUploadProps, type MediaPickerUploads, type MediaStatusReturn, type PdfPreviewConfig, PdfPreviewProvider, PdfThumbnail, type PdfThumbnailProps, PdfjsLoader, Preview, type PreviewKind, PreviewLabels, type PreviewProps, type UseMediaLibraryOptions, type UseMediaObjectUrlOptions, type UseMediaUploadOptions, type UseMediaUploadReturn, VideoProps, type VideoState, ViewerTokenArgs, matchesAccept, useDevulturMedia, useMediaLibrary, useMediaObjectUrl, useMediaPicker, useMediaUpload, useVideoState };