sanity-plugin-mux-input 3.0.4 → 4.0.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.
Files changed (130) hide show
  1. package/README.md +0 -2
  2. package/dist/index.d.ts +134 -193
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +2893 -4417
  5. package/dist/index.js.map +1 -1
  6. package/package.json +33 -43
  7. package/dist/index.cjs +0 -7270
  8. package/dist/index.cjs.map +0 -1
  9. package/dist/index.d.cts +0 -347
  10. package/sanity.json +0 -8
  11. package/src/_exports/index.ts +0 -73
  12. package/src/actions/assets.ts +0 -152
  13. package/src/actions/secrets.ts +0 -111
  14. package/src/actions/upload.ts +0 -310
  15. package/src/clients/upChunkObservable.ts +0 -54
  16. package/src/components/AddCaptionDialog.tsx +0 -440
  17. package/src/components/CaptionsDialog.tsx +0 -23
  18. package/src/components/ConfigureApi.styled.tsx +0 -19
  19. package/src/components/ConfigureApi.tsx +0 -296
  20. package/src/components/DraggableWatermark.tsx +0 -877
  21. package/src/components/EditCaptionDialog.tsx +0 -510
  22. package/src/components/EditThumbnailDialog.tsx +0 -122
  23. package/src/components/ErrorBoundaryCard.tsx +0 -96
  24. package/src/components/FileInputButton.tsx +0 -54
  25. package/src/components/FileInputMenuItem.styled.tsx +0 -36
  26. package/src/components/FileInputMenuItem.tsx +0 -85
  27. package/src/components/FormField.tsx +0 -38
  28. package/src/components/IconInfo.tsx +0 -22
  29. package/src/components/ImportVideosFromMux.tsx +0 -342
  30. package/src/components/Input.styled.tsx +0 -22
  31. package/src/components/Input.tsx +0 -78
  32. package/src/components/InputBrowser.tsx +0 -41
  33. package/src/components/InputError.tsx +0 -17
  34. package/src/components/MuxLogo.tsx +0 -42
  35. package/src/components/Onboard.tsx +0 -65
  36. package/src/components/PageSelector.tsx +0 -54
  37. package/src/components/Player.styled.tsx +0 -55
  38. package/src/components/Player.tsx +0 -117
  39. package/src/components/PlayerActionsMenu.tsx +0 -190
  40. package/src/components/ResyncMetadata.tsx +0 -280
  41. package/src/components/SelectAsset.tsx +0 -39
  42. package/src/components/SelectSortOptions.tsx +0 -45
  43. package/src/components/SpinnerBox.tsx +0 -16
  44. package/src/components/StudioTool.tsx +0 -24
  45. package/src/components/TextTracksEditor.tsx +0 -117
  46. package/src/components/TextTracksManager.tsx +0 -737
  47. package/src/components/UploadConfiguration.tsx +0 -694
  48. package/src/components/UploadPlaceholder.tsx +0 -88
  49. package/src/components/UploadProgress.tsx +0 -80
  50. package/src/components/Uploader.styled.tsx +0 -66
  51. package/src/components/Uploader.tsx +0 -498
  52. package/src/components/VideoDetails/DeleteDialog.tsx +0 -147
  53. package/src/components/VideoDetails/VideoDetails.tsx +0 -358
  54. package/src/components/VideoDetails/VideoReferences.tsx +0 -63
  55. package/src/components/VideoDetails/useVideoDetails.ts +0 -103
  56. package/src/components/VideoInBrowser.tsx +0 -245
  57. package/src/components/VideoMetadata.tsx +0 -45
  58. package/src/components/VideoPlayer.tsx +0 -235
  59. package/src/components/VideoThumbnail.tsx +0 -138
  60. package/src/components/VideosBrowser.tsx +0 -100
  61. package/src/components/documentPreview/DocumentPreview.tsx +0 -83
  62. package/src/components/documentPreview/DraftStatus.tsx +0 -34
  63. package/src/components/documentPreview/MissingSchemaType.tsx +0 -32
  64. package/src/components/documentPreview/PaneItemPreview.tsx +0 -74
  65. package/src/components/documentPreview/PublishedStatus.tsx +0 -35
  66. package/src/components/documentPreview/TimeAgo.tsx +0 -12
  67. package/src/components/documentPreview/paneItemTypes.ts +0 -7
  68. package/src/components/icons/Audio.tsx +0 -13
  69. package/src/components/icons/Resolution.tsx +0 -12
  70. package/src/components/icons/StopWatch.tsx +0 -20
  71. package/src/components/icons/ToolIcon.tsx +0 -19
  72. package/src/components/uploadConfiguration/PlaybackPolicy.tsx +0 -133
  73. package/src/components/uploadConfiguration/PlaybackPolicyOption.tsx +0 -76
  74. package/src/components/uploadConfiguration/PlaybackPolicyWarning.tsx +0 -29
  75. package/src/components/uploadConfiguration/ResolutionTierSelector.tsx +0 -72
  76. package/src/components/uploadConfiguration/StaticRenditionSelector.tsx +0 -180
  77. package/src/components/withFocusRing/helpers.ts +0 -24
  78. package/src/components/withFocusRing/index.ts +0 -1
  79. package/src/components/withFocusRing/withFocusRing.ts +0 -30
  80. package/src/context/DialogStateContext.tsx +0 -36
  81. package/src/context/DrmPlaybackWarningContext.tsx +0 -93
  82. package/src/hooks/useAccessControl.ts +0 -13
  83. package/src/hooks/useAssetDocumentValues.ts +0 -11
  84. package/src/hooks/useAssets.ts +0 -68
  85. package/src/hooks/useCancelUpload.ts +0 -22
  86. package/src/hooks/useClient.ts +0 -8
  87. package/src/hooks/useDialogState.ts +0 -11
  88. package/src/hooks/useDocReferences.ts +0 -21
  89. package/src/hooks/useFetchFileSize.ts +0 -54
  90. package/src/hooks/useImportMuxAssets.ts +0 -132
  91. package/src/hooks/useInView.ts +0 -42
  92. package/src/hooks/useMediaMetadata.ts +0 -103
  93. package/src/hooks/useMuxAssets.ts +0 -179
  94. package/src/hooks/useMuxPolling.ts +0 -49
  95. package/src/hooks/useResyncAsset.ts +0 -110
  96. package/src/hooks/useResyncMuxMetadata.ts +0 -176
  97. package/src/hooks/useSaveSecrets.ts +0 -78
  98. package/src/hooks/useSecretsDocumentValues.ts +0 -38
  99. package/src/hooks/useSecretsFormState.ts +0 -47
  100. package/src/plugin.tsx +0 -31
  101. package/src/sanity-ui.d.ts +0 -5
  102. package/src/schema.ts +0 -196
  103. package/src/util/addKeysToMuxData.ts +0 -30
  104. package/src/util/areSecretsSignable.ts +0 -5
  105. package/src/util/asserters.ts +0 -36
  106. package/src/util/assetTitlePlaceholder.ts +0 -31
  107. package/src/util/constants.ts +0 -15
  108. package/src/util/convertWatermarkToMux.ts +0 -160
  109. package/src/util/createSearchFilter.ts +0 -76
  110. package/src/util/createUrlParamsObject.ts +0 -29
  111. package/src/util/extractFiles.ts +0 -67
  112. package/src/util/formatBytes.ts +0 -32
  113. package/src/util/formatDriveShareLink.ts +0 -64
  114. package/src/util/formatSeconds.ts +0 -49
  115. package/src/util/generateJwt.ts +0 -57
  116. package/src/util/getAnimatedPosterSrc.ts +0 -26
  117. package/src/util/getPlaybackPolicy.ts +0 -69
  118. package/src/util/getPosterSrc.ts +0 -28
  119. package/src/util/getStoryboardSrc.ts +0 -27
  120. package/src/util/getVideoMetadata.ts +0 -23
  121. package/src/util/getVideoSrc.ts +0 -23
  122. package/src/util/isSigned.ts +0 -20
  123. package/src/util/parsers.ts +0 -5
  124. package/src/util/pluginVersion.ts +0 -1
  125. package/src/util/readSecrets.ts +0 -38
  126. package/src/util/roundPxString.ts +0 -16
  127. package/src/util/textTracks.ts +0 -222
  128. package/src/util/tryWithSuspend.ts +0 -22
  129. package/src/util/types.ts +0 -596
  130. package/v2-incompatible.js +0 -11
@@ -1,27 +0,0 @@
1
- import type {SanityClient} from 'sanity'
2
-
3
- import {getPlaybackId} from '../util/getPlaybackPolicy'
4
- import {generateJwt} from './generateJwt'
5
- import {getPlaybackPolicyById} from './getPlaybackPolicy'
6
- import type {MuxStoryboardUrl, VideoAssetDocument} from './types'
7
-
8
- interface StoryboardSrcOptions {
9
- asset: VideoAssetDocument
10
- client: SanityClient
11
- }
12
-
13
- /**
14
- * May throw a Promise. Call this with {@link tryWithSuspend} or rethrow the Promise
15
- */
16
- export function getStoryboardSrc({asset, client}: StoryboardSrcOptions): MuxStoryboardUrl {
17
- const playbackId = getPlaybackId(asset)
18
- const searchParams = new URLSearchParams()
19
-
20
- const playbackPolicy = getPlaybackPolicyById(asset, playbackId)?.policy
21
- if (playbackPolicy === 'signed' || playbackPolicy === 'drm') {
22
- const token = generateJwt(client, playbackId, 's')
23
- searchParams.set('token', token)
24
- }
25
-
26
- return `https://image.mux.com/${playbackId}/storyboard.vtt?${searchParams}`
27
- }
@@ -1,23 +0,0 @@
1
- import {formatSeconds} from './formatSeconds'
2
- import type {MuxTextTrack, VideoAssetDocument} from './types'
3
-
4
- export default function getVideoMetadata(doc: VideoAssetDocument) {
5
- const id = doc.assetId || doc._id || ''
6
- const date = doc.data?.created_at
7
- ? new Date(Number(doc.data.created_at) * 1000)
8
- : new Date(doc._createdAt || doc._updatedAt || Date.now())
9
-
10
- return {
11
- title: doc.filename || id.slice(0, 12),
12
- id: id,
13
- playbackId: doc.playbackId,
14
- createdAt: date,
15
- duration: doc.data?.duration ? formatSeconds(doc.data?.duration) : undefined,
16
- playback_ids: doc.data?.playback_ids,
17
- aspect_ratio: doc.data?.aspect_ratio,
18
- max_stored_resolution: doc.data?.max_stored_resolution,
19
- max_stored_frame_rate: doc.data?.max_stored_frame_rate,
20
- text_tracks:
21
- doc.data?.tracks?.filter((track): track is MuxTextTrack => track.type === 'text') || [],
22
- }
23
- }
@@ -1,23 +0,0 @@
1
- import type {SanityClient} from 'sanity'
2
-
3
- import {generateJwt} from './generateJwt'
4
- import type {MuxPlaybackId, MuxVideoUrl} from './types'
5
-
6
- interface VideoSrcOptions {
7
- muxPlaybackId: MuxPlaybackId
8
- client: SanityClient
9
- }
10
-
11
- /**
12
- * May throw a Promise. Call this with {@link tryWithSuspend} or rethrow the Promise
13
- */
14
- export function getVideoSrc({client, muxPlaybackId}: VideoSrcOptions): MuxVideoUrl {
15
- const searchParams = new URLSearchParams()
16
-
17
- if (muxPlaybackId.policy === 'signed' || muxPlaybackId.policy === 'drm') {
18
- const token = generateJwt(client, muxPlaybackId.id, 'v')
19
- searchParams.set('token', token)
20
- }
21
-
22
- return `https://stream.mux.com/${muxPlaybackId.id}.m3u8?${searchParams}`
23
- }
@@ -1,20 +0,0 @@
1
- import {areSecretsSignable} from './areSecretsSignable'
2
- import type {Secrets, VideoAssetDocument} from './types'
3
-
4
- export function isSigned(asset: VideoAssetDocument, secrets: Secrets): boolean {
5
- const isAssetSigned = asset.data?.playback_ids?.[0]?.policy === 'signed'
6
- if (!isAssetSigned) {
7
- return false
8
- }
9
-
10
- if (areSecretsSignable(secrets)) {
11
- return true
12
- }
13
- console.error(
14
- 'Asset is signed',
15
- {asset},
16
- 'but secrets are missing signingKeyId and signingKeyPrivate',
17
- secrets
18
- )
19
- throw new TypeError(`Unable to access asset as signing keys are missing`)
20
- }
@@ -1,5 +0,0 @@
1
- import type {MuxAsset} from './types'
2
-
3
- export function parseMuxDate(date: MuxAsset['created_at']): Date {
4
- return new Date(Number(date) * 1000)
5
- }
@@ -1 +0,0 @@
1
- export const PLUGIN_VERSION_QUERY = {sanityVersion: process.env.PKG_VERSION!}
@@ -1,38 +0,0 @@
1
- // Utils with a readName prefix are suspendable and should only be called in the render body
2
- // Not inside event callbacks or a useEffect.
3
- // They may be called dynamically, unlike useEffect
4
-
5
- // @TODO rename to readSigningPair
6
-
7
- import type {SanityClient} from 'sanity'
8
- import {suspend} from 'suspend-react'
9
-
10
- import {cacheNs} from '../util/constants'
11
- import {type Secrets} from '../util/types'
12
-
13
- export const _id = 'secrets.mux' as const
14
-
15
- export function readSecrets(client: SanityClient): Secrets {
16
- const {projectId, dataset} = client.config()
17
- return suspend(async () => {
18
- const data = await client.fetch(
19
- /* groq */ `*[_id == $_id][0]{
20
- token,
21
- secretKey,
22
- enableSignedUrls,
23
- signingKeyId,
24
- signingKeyPrivate,
25
- drmConfigId
26
- }`,
27
- {_id}
28
- )
29
- return {
30
- token: data?.token || null,
31
- secretKey: data?.secretKey || null,
32
- enableSignedUrls: Boolean(data?.enableSignedUrls) || false,
33
- signingKeyId: data?.signingKeyId || null,
34
- signingKeyPrivate: data?.signingKeyPrivate || null,
35
- drmConfigId: data?.drmConfigId || null,
36
- }
37
- }, [cacheNs, _id, projectId, dataset])
38
- }
@@ -1,16 +0,0 @@
1
- /**
2
- * Rounds the numeric part of a px string to the nearest integer.
3
- * Returns undefined if the value is not a valid px string or not a finite number.
4
- * Avoids sending 0px (and JS -0); snaps to ±1 instead.
5
- */
6
- export function roundPxString(value: unknown): string | undefined {
7
- if (typeof value !== 'string') return undefined
8
- const trimmed = value.trim()
9
- if (!trimmed.endsWith('px')) return undefined
10
- const n = Number(trimmed.slice(0, -2))
11
- if (!Number.isFinite(n)) return undefined
12
- let rounded = Math.round(n)
13
- // Avoid sending 0px (and JS -0); keep sign when negative.
14
- if (rounded === 0) rounded = n < 0 ? -1 : 1
15
- return `${rounded}px`
16
- }
@@ -1,222 +0,0 @@
1
- import type {SanityClient} from '@sanity/client'
2
-
3
- import {getAsset} from '../actions/assets'
4
- import {generateJwt} from './generateJwt'
5
- import {getPlaybackId} from './getPlaybackPolicy'
6
- import {getPlaybackPolicy} from './getPlaybackPolicy'
7
- import type {MuxTextTrack, VideoAssetDocument} from './types'
8
-
9
- export function extractErrorMessage(
10
- error: unknown,
11
- defaultMessage = 'Failed to process request'
12
- ): string {
13
- let message = ''
14
-
15
- if (error && typeof error === 'object') {
16
- const err = error as {response?: {body?: {message?: string}}; message?: string}
17
- message = err.response?.body?.message || err.message || ''
18
- } else if (typeof error === 'string') {
19
- message = error
20
- }
21
-
22
- if (!message) {
23
- return defaultMessage
24
- }
25
-
26
- const match = message.match(/\(([^)]+)\)/)
27
- if (match && match[1]) {
28
- return match[1]
29
- }
30
-
31
- if (message.includes('responded with')) {
32
- const parts = message.split('(')
33
- if (parts.length > 1) {
34
- return parts[parts.length - 1].replace(')', '').trim()
35
- }
36
- }
37
-
38
- return message
39
- }
40
-
41
- export interface PollTrackStatusOptions {
42
- client: SanityClient
43
- assetId: string
44
- trackName: string
45
- trackLanguageCode: string
46
- maxAttempts?: number
47
- onTrackFound?: (track: MuxTextTrack) => void
48
- onTrackErrored?: (track: MuxTextTrack) => void
49
- onTrackReady?: (track: MuxTextTrack) => void
50
- }
51
-
52
- export interface PollTrackStatusResult {
53
- track: MuxTextTrack | undefined
54
- found: boolean
55
- status: 'ready' | 'preparing' | 'errored' | 'not-found'
56
- }
57
-
58
- /**
59
- * Polls Mux API to find and track the status of a newly added text track.
60
- * The track may be in "preparing" state initially, then become "ready" or "errored".
61
- *
62
- * @param options - Configuration options for polling
63
- * @returns Promise resolving to the poll result
64
- */
65
- export async function pollTrackStatus(
66
- options: PollTrackStatusOptions
67
- ): Promise<PollTrackStatusResult> {
68
- const {
69
- client,
70
- assetId,
71
- trackName,
72
- trackLanguageCode,
73
- maxAttempts = 10,
74
- onTrackFound,
75
- onTrackErrored,
76
- onTrackReady,
77
- } = options
78
-
79
- const trimmedName = trackName.trim()
80
- const trimmedLanguageCode = trackLanguageCode.trim()
81
- let newTrack: MuxTextTrack | undefined
82
- let attempts = 0
83
- let trackFound = false
84
-
85
- const findTrack = (textTracks: MuxTextTrack[]): MuxTextTrack | undefined => {
86
- let foundTrack = textTracks.find(
87
- (track) => track.name === trimmedName && track.language_code === trimmedLanguageCode
88
- )
89
-
90
- if (!foundTrack) {
91
- foundTrack = textTracks.find((track) => track.language_code === trimmedLanguageCode)
92
- }
93
-
94
- if (!foundTrack && textTracks.length > 0) {
95
- foundTrack = textTracks[textTracks.length - 1]
96
- }
97
-
98
- return foundTrack
99
- }
100
-
101
- while (attempts < maxAttempts) {
102
- try {
103
- if (attempts > 0) {
104
- await new Promise((resolve) => setTimeout(resolve, 1000))
105
- }
106
-
107
- const assetData = await getAsset(client, assetId)
108
- const textTracks =
109
- assetData.data.tracks?.filter((track): track is MuxTextTrack => track.type === 'text') || []
110
-
111
- const foundTrack = findTrack(textTracks)
112
-
113
- if (!foundTrack) {
114
- attempts++
115
- continue
116
- }
117
-
118
- trackFound = true
119
- newTrack = foundTrack
120
-
121
- if (onTrackFound) {
122
- onTrackFound(foundTrack)
123
- }
124
-
125
- if (foundTrack.status === 'ready') {
126
- if (onTrackReady) {
127
- onTrackReady(foundTrack)
128
- }
129
- break
130
- }
131
-
132
- if (foundTrack.status === 'errored') {
133
- if (onTrackErrored) {
134
- onTrackErrored(foundTrack)
135
- }
136
- return {
137
- track: foundTrack,
138
- found: true,
139
- status: 'errored',
140
- }
141
- }
142
- } catch (error) {
143
- console.error('Failed to fetch updated asset:', error)
144
- }
145
-
146
- attempts++
147
- }
148
-
149
- if (!newTrack || !trackFound) {
150
- return {
151
- track: undefined,
152
- found: false,
153
- status: 'not-found',
154
- }
155
- }
156
-
157
- if (newTrack.status === 'preparing') {
158
- return {
159
- track: newTrack,
160
- found: true,
161
- status: 'preparing',
162
- }
163
- }
164
-
165
- return {
166
- track: newTrack,
167
- found: true,
168
- status: 'ready',
169
- }
170
- }
171
-
172
- /**
173
- * May throw a Promise. Call this with {@link tryWithSuspend} or rethrow the Promise
174
- */
175
- export async function downloadVttFile(
176
- client: SanityClient,
177
- asset: VideoAssetDocument,
178
- track: MuxTextTrack
179
- ): Promise<void> {
180
- if (!track.id) {
181
- throw new Error('Track ID is missing')
182
- }
183
-
184
- if (track.status !== 'ready') {
185
- throw new Error(`Track is not ready yet. Status: ${track.status}`)
186
- }
187
-
188
- if (!asset.assetId) {
189
- throw new Error('Asset ID is required')
190
- }
191
-
192
- const playbackId = getPlaybackId(asset)
193
- if (!playbackId) {
194
- throw new Error('Playback ID is required')
195
- }
196
-
197
- const playbackPolicy = getPlaybackPolicy(asset)?.policy
198
-
199
- let downloadUrl = `https://stream.mux.com/${playbackId}/text/${track.id}.vtt`
200
-
201
- if (playbackPolicy === 'signed' || playbackPolicy === 'drm') {
202
- const token = generateJwt(client, playbackId, 'v')
203
- downloadUrl += `?token=${token}`
204
- }
205
-
206
- const response = await fetch(downloadUrl)
207
- if (!response.ok) {
208
- throw new Error(`Failed to download file: ${response.statusText}`)
209
- }
210
-
211
- const blob = await response.blob()
212
- const blobUrl = URL.createObjectURL(blob)
213
-
214
- const link = document.createElement('a')
215
- link.href = blobUrl
216
- link.download = `${asset.filename || 'captions'}-${track.language_code || 'en'}.vtt`
217
- document.body.appendChild(link)
218
- link.click()
219
- document.body.removeChild(link)
220
-
221
- URL.revokeObjectURL(blobUrl)
222
- }
@@ -1,22 +0,0 @@
1
- /**
2
- * When running `suspend()` from react-suspend a function may throw a Promise
3
- * causing unexpected behavior when catching.
4
- * @param block Your block of code that uses suspend
5
- * @param onError (optional) How to handle a regular Error
6
- * @returns Whatever is returned by the block if it succeeds, otherwise whatever is resolved by onError if defined
7
- * @throws rethrows the caught Promise to comply with Suspense logic
8
- */
9
- export function tryWithSuspend<T, E>(
10
- block: () => T,
11
- onError?: (error: Error) => E
12
- ): T | E | undefined {
13
- try {
14
- return block()
15
- } catch (errorOrPromise) {
16
- if (errorOrPromise instanceof Promise) {
17
- // react-suspend will throw a Promise
18
- throw errorOrPromise
19
- }
20
- return onError ? onError(errorOrPromise as Error) : undefined
21
- }
22
- }