@devultur/convex 1.4.1 → 1.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -1
- package/dist/chunk-JZYKPLI4.js +185 -0
- package/dist/{chunk-EX3W77VY.js → chunk-YYOZ3PDH.js} +16 -3
- package/dist/{error-labels-BfqcFh2R.d.ts → error-labels-D0Vbp-qA.d.ts} +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/locales/es-formal.d.ts +12 -0
- package/dist/locales/es-formal.js +64 -0
- package/dist/locales/es.d.ts +4 -3
- package/dist/locales/es.js +10 -156
- package/dist/{media-picker-labels-CiVcNUZo.d.ts → preview-labels-B-2mra1h.d.ts} +58 -1
- package/dist/react.d.ts +11 -56
- package/dist/react.js +25 -8
- package/package.json +8 -4
package/README.md
CHANGED
|
@@ -654,7 +654,12 @@ any other error, so your app keeps its own fallback. A code it doesn't know gets
|
|
|
654
654
|
`devulturErrorLabels` is the English map, typed `Record<DevulturErrorCode, string | ((details) => string)>`:
|
|
655
655
|
`DevulturErrorCode` is the union of every stable code (`DEVULTUR_ERROR_CODES` lists them), and a function label reads
|
|
656
656
|
the error's details, such as `file_too_large`'s `limit`. `@devultur/convex/locales/es` exports the Spanish map under
|
|
657
|
-
the same name
|
|
657
|
+
the same name.
|
|
658
|
+
|
|
659
|
+
`@devultur/convex/locales/es` addresses the reader with «tú» ("Vuelve a intentarlo"). For «usted» ("Vuelva a
|
|
660
|
+
intentarlo", "No tiene permiso…"), import the same names from `@devultur/convex/locales/es-formal`: it exports exactly
|
|
661
|
+
what `locales/es` does (error, attachment, preview, library and picker labels), and differs only in the strings that
|
|
662
|
+
address the reader.
|
|
658
663
|
|
|
659
664
|
```tsx
|
|
660
665
|
import { describeDevulturError } from "@devultur/convex";
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatDuration,
|
|
3
|
+
formatFileSize
|
|
4
|
+
} from "./chunk-QBHIZBOQ.js";
|
|
5
|
+
import {
|
|
6
|
+
describeDevulturError,
|
|
7
|
+
formatBytes,
|
|
8
|
+
formatDate,
|
|
9
|
+
labelText
|
|
10
|
+
} from "./chunk-YYOZ3PDH.js";
|
|
11
|
+
|
|
12
|
+
// src/locales/es.ts
|
|
13
|
+
var LOCALE = "es";
|
|
14
|
+
var devulturErrorLabels = {
|
|
15
|
+
file_too_large: (details) => {
|
|
16
|
+
const limit = typeof details.limit === "number" ? formatBytes(details.limit, LOCALE) : null;
|
|
17
|
+
return limit ? `El archivo supera el tama\xF1o m\xE1ximo (${limit}).` : "El archivo supera el tama\xF1o m\xE1ximo.";
|
|
18
|
+
},
|
|
19
|
+
content_type_not_allowed: "Este tipo de archivo no est\xE1 permitido.",
|
|
20
|
+
content_type_mismatch: "El contenido del archivo no coincide con su tipo.",
|
|
21
|
+
content_unverified: "No se pudo verificar la subida. Vuelve a intentarlo.",
|
|
22
|
+
unsupported_content_type: "Este tipo de archivo no es compatible.",
|
|
23
|
+
media_type_mismatch: "El tipo de archivo no coincide con el tipo de contenido esperado.",
|
|
24
|
+
already_exists: "Ya existe un archivo con este nombre.",
|
|
25
|
+
write_conflict: "El archivo cambi\xF3 mientras se guardaba. Vuelve a intentarlo.",
|
|
26
|
+
upload_not_found: "No se encontr\xF3 la subida o ya venci\xF3. Vuelve a empezarla.",
|
|
27
|
+
invalid_upload_key: "Esta subida no es v\xE1lida.",
|
|
28
|
+
invalid_path: "La ruta del archivo no es v\xE1lida.",
|
|
29
|
+
path_required: "Esta subida necesita una ruta de archivo.",
|
|
30
|
+
invalid_expires_in: "El tiempo de vencimiento no es v\xE1lido.",
|
|
31
|
+
invalid_file_expires_in: "El tiempo de vencimiento del archivo no es v\xE1lido.",
|
|
32
|
+
invalid_cache_control: "La configuraci\xF3n de cach\xE9 no es v\xE1lida.",
|
|
33
|
+
invalid_limits: "Los l\xEDmites de la subida no son v\xE1lidos.",
|
|
34
|
+
invalid_prefix: "La carpeta no es v\xE1lida.",
|
|
35
|
+
invalid_visibility: "La visibilidad debe ser p\xFAblica o privada.",
|
|
36
|
+
invalid_cursor: "La p\xE1gina de resultados no es v\xE1lida. Vuelve a cargar la lista.",
|
|
37
|
+
invalid_sha256: "La suma de verificaci\xF3n del archivo no es v\xE1lida.",
|
|
38
|
+
sha256_mismatch: "El archivo se da\xF1\xF3 durante la subida. Vuelve a intentarlo.",
|
|
39
|
+
max_files_reached: "Alcanzaste el n\xFAmero m\xE1ximo de archivos para esta subida.",
|
|
40
|
+
invalid_multipart: "La solicitud de subida no es v\xE1lida.",
|
|
41
|
+
invalid_size: "El tama\xF1o del archivo no es v\xE1lido.",
|
|
42
|
+
invalid_part: "Una parte de la subida no es v\xE1lida. Vuelve a intentarlo.",
|
|
43
|
+
invalid_parts: "La subida est\xE1 incompleta. Vuelve a intentarlo.",
|
|
44
|
+
part_size_mismatch: "Una parte de la subida tiene un tama\xF1o incorrecto. Vuelve a intentarlo.",
|
|
45
|
+
part_sha256_required: "A una parte de la subida le falta la suma de verificaci\xF3n.",
|
|
46
|
+
invalid_media_metadata: (details) => {
|
|
47
|
+
if (details.field === "title") return "El t\xEDtulo no puede tener m\xE1s de 200 caracteres.";
|
|
48
|
+
if (details.field === "alt") return "El texto alternativo no puede tener m\xE1s de 1000 caracteres.";
|
|
49
|
+
if (details.field === "tags") return "Usa como m\xE1ximo 20 etiquetas, de hasta 50 caracteres cada una.";
|
|
50
|
+
return "Los datos del archivo no son v\xE1lidos.";
|
|
51
|
+
},
|
|
52
|
+
expired: "Este archivo ya venci\xF3.",
|
|
53
|
+
invalid_key: "La referencia del archivo no es v\xE1lida.",
|
|
54
|
+
invalid_max_uses: "El n\xFAmero de usos no es v\xE1lido.",
|
|
55
|
+
link_exists: "Este enlace de descarga ya existe.",
|
|
56
|
+
link_not_found: "Este enlace de descarga no existe.",
|
|
57
|
+
link_expired: "Este enlace de descarga ya venci\xF3.",
|
|
58
|
+
link_used: "Este enlace de descarga ya se us\xF3.",
|
|
59
|
+
not_configured: "Esta funci\xF3n no est\xE1 configurada.",
|
|
60
|
+
retention_active: (details) => {
|
|
61
|
+
if (details.hold === true) return "Este archivo tiene una retenci\xF3n legal y no se puede modificar ni eliminar.";
|
|
62
|
+
const until = formatDate(details.until, LOCALE);
|
|
63
|
+
return until ? `Este archivo est\xE1 protegido hasta el ${until} y no se puede modificar ni eliminar antes de esa fecha.` : "Este archivo est\xE1 protegido y no se puede modificar ni eliminar.";
|
|
64
|
+
},
|
|
65
|
+
lock_conflict: "La protecci\xF3n del archivo cambi\xF3 mientras tanto. Vuelve a intentarlo.",
|
|
66
|
+
compliance_extend_only: "La protecci\xF3n de este archivo solo se puede extender.",
|
|
67
|
+
lock_privilege_required: "No tienes permiso para acortar ni quitar la protecci\xF3n de este archivo.",
|
|
68
|
+
lock_record_unreadable: "No se pudo leer la protecci\xF3n del archivo.",
|
|
69
|
+
lock_below_minimum: "Esta subida requiere una protecci\xF3n m\xE1s estricta.",
|
|
70
|
+
invalid_lock: "La configuraci\xF3n de protecci\xF3n no es v\xE1lida.",
|
|
71
|
+
invalid_hold: "La configuraci\xF3n de retenci\xF3n legal no es v\xE1lida.",
|
|
72
|
+
reserved_key: "Este nombre de archivo est\xE1 reservado.",
|
|
73
|
+
keys_bucket_missing: "En este momento no se pueden guardar archivos de forma segura.",
|
|
74
|
+
encryption_key_missing: "Este archivo ya no se puede leer. Vuelve a subirlo.",
|
|
75
|
+
unauthorized: "No tienes autorizaci\xF3n para hacer esto.",
|
|
76
|
+
session_mismatch: "Tu sesi\xF3n cambi\xF3. Vuelve a cargar la p\xE1gina.",
|
|
77
|
+
token_rejected: "Se deneg\xF3 el acceso.",
|
|
78
|
+
reserved_user_id: "Este identificador de usuario est\xE1 reservado.",
|
|
79
|
+
invalid_scopes: "Los permisos solicitados no son v\xE1lidos.",
|
|
80
|
+
user_mismatch: "Solo puedes ver y cambiar tu propio progreso.",
|
|
81
|
+
transcode_not_configured: "El procesamiento de video no est\xE1 configurado.",
|
|
82
|
+
transcode_runner_unavailable: "El procesamiento de video est\xE1 ocupado en este momento. Vuelve a intentarlo m\xE1s tarde.",
|
|
83
|
+
transcode_launch_failed: "No se pudo procesar el video.",
|
|
84
|
+
original_not_retained: "El video original ya no est\xE1 disponible, as\xED que no se puede volver a procesar. Vuelve a subirlo.",
|
|
85
|
+
locale_not_allowed: "Los subt\xEDtulos no est\xE1n disponibles en este idioma.",
|
|
86
|
+
captions_provider_rate_limited: "El servicio de subt\xEDtulos est\xE1 ocupado en este momento. Vuelve a intentarlo m\xE1s tarde.",
|
|
87
|
+
captions_provider_error: "No se pudieron generar los subt\xEDtulos.",
|
|
88
|
+
captions_failed: "No se pudieron generar los subt\xEDtulos.",
|
|
89
|
+
webhook_secret_missing: "El procesamiento de video no est\xE1 configurado.",
|
|
90
|
+
worker_auth_secret_missing: "El servicio de medios no est\xE1 configurado.",
|
|
91
|
+
worker_error: "El servicio de medios no pudo completar la solicitud.",
|
|
92
|
+
http_error: "No se pudo cargar el archivo.",
|
|
93
|
+
too_large: "El archivo es demasiado grande para la vista previa.",
|
|
94
|
+
unsupported_type: "Este tipo de archivo no tiene vista previa.",
|
|
95
|
+
type_mismatch: "El contenido del archivo no coincide con su tipo.",
|
|
96
|
+
token_unavailable: "No se pudo autorizar el acceso a este archivo. Vuelve a intentarlo.",
|
|
97
|
+
page_cap: (details) => {
|
|
98
|
+
const { shown, total } = details;
|
|
99
|
+
if (typeof shown !== "number" || typeof total !== "number") return "Solo se muestran las primeras p\xE1ginas.";
|
|
100
|
+
return `Solo se muestran las primeras ${shown.toLocaleString(LOCALE)} de ${total.toLocaleString(LOCALE)} p\xE1ginas.`;
|
|
101
|
+
},
|
|
102
|
+
render_failed: "No se pudo mostrar el archivo.",
|
|
103
|
+
capability_unavailable: "Esta aplicaci\xF3n no puede hacer eso aqu\xED."
|
|
104
|
+
};
|
|
105
|
+
var previewLabels = {
|
|
106
|
+
document: (title, pageCount) => `${title}, ${pagesText(pageCount)}`,
|
|
107
|
+
page: (page, pageCount) => `P\xE1gina ${page} de ${pageCount}`,
|
|
108
|
+
loading: "Cargando\u2026",
|
|
109
|
+
pageCap: (shown, total) => `Se muestran las primeras ${shown} de ${total} p\xE1ginas.`,
|
|
110
|
+
error: (code) => code === "page_cap" ? "Descarga el archivo para ver todas las p\xE1ginas." : labelText(devulturErrorLabels[code]),
|
|
111
|
+
thumbnail: (title) => title,
|
|
112
|
+
untitledPdf: "PDF",
|
|
113
|
+
untitledMedia: "Vista previa",
|
|
114
|
+
download: "Descargar"
|
|
115
|
+
};
|
|
116
|
+
function pagesText(pageCount) {
|
|
117
|
+
return pageCount === 1 ? "1 p\xE1gina" : `${pageCount.toLocaleString(LOCALE)} p\xE1ginas`;
|
|
118
|
+
}
|
|
119
|
+
var KIND_TEXT = {
|
|
120
|
+
image: "Imagen",
|
|
121
|
+
video: "Video",
|
|
122
|
+
pdf: "PDF",
|
|
123
|
+
audio: "Audio",
|
|
124
|
+
text: "Texto",
|
|
125
|
+
file: "Archivo"
|
|
126
|
+
};
|
|
127
|
+
var attachmentLabels = {
|
|
128
|
+
locale: LOCALE,
|
|
129
|
+
size: formatFileSize,
|
|
130
|
+
pages: pagesText,
|
|
131
|
+
duration: formatDuration,
|
|
132
|
+
kind: (kind) => KIND_TEXT[kind],
|
|
133
|
+
download: "Descargar",
|
|
134
|
+
open: "Abrir vista previa",
|
|
135
|
+
untitled: "Archivo sin t\xEDtulo"
|
|
136
|
+
};
|
|
137
|
+
var mediaLibraryLabels = {
|
|
138
|
+
search: "Buscar archivos",
|
|
139
|
+
searchPlaceholder: "Busca por t\xEDtulo o nombre de archivo",
|
|
140
|
+
typeFilter: "Tipo",
|
|
141
|
+
allTypes: "Todos los tipos",
|
|
142
|
+
types: { image: "Im\xE1genes", video: "Videos", file: "Archivos" },
|
|
143
|
+
results: "Archivos",
|
|
144
|
+
loading: "Cargando archivos\u2026",
|
|
145
|
+
empty: "Todav\xEDa no hay archivos.",
|
|
146
|
+
noResults: (search) => `Nada coincide con \xAB${search}\xBB.`,
|
|
147
|
+
loadMore: "Cargar m\xE1s",
|
|
148
|
+
loadingMore: "Cargando\u2026",
|
|
149
|
+
error: (error) => describeDevulturError(error, devulturErrorLabels) ?? "No se pudieron cargar los archivos.",
|
|
150
|
+
retry: "Reintentar",
|
|
151
|
+
size: (bytes) => formatFileSize(bytes, LOCALE)
|
|
152
|
+
};
|
|
153
|
+
var mediaPickerLabels = {
|
|
154
|
+
upload: (multiple) => multiple ? "Subir archivos" : "Subir un archivo",
|
|
155
|
+
dropHint: (multiple) => multiple ? "o suelta los archivos aqu\xED" : "o suelta un archivo aqu\xED",
|
|
156
|
+
uploads: "Subidas",
|
|
157
|
+
progress: (filename) => `Subiendo ${filename}`,
|
|
158
|
+
percent: (percent) => `${percent} %`,
|
|
159
|
+
uploading: (filename) => `Subiendo ${filename}.`,
|
|
160
|
+
uploaded: (filename) => `${filename} se subi\xF3 y qued\xF3 seleccionado.`,
|
|
161
|
+
cancel: "Cancelar",
|
|
162
|
+
cancelUpload: (filename) => `Cancelar la subida de ${filename}`,
|
|
163
|
+
cancelled: (filename) => `Se cancel\xF3 la subida de ${filename}.`,
|
|
164
|
+
notAccepted: (filename) => `${filename} no es un tipo de archivo que se pueda elegir aqu\xED.`,
|
|
165
|
+
uploadError: (error) => describeDevulturError(error, devulturErrorLabels) ?? "La subida fall\xF3. Vuelve a intentarlo.",
|
|
166
|
+
retry: "Reintentar",
|
|
167
|
+
dismiss: "Descartar",
|
|
168
|
+
selection: "Archivos seleccionados",
|
|
169
|
+
empty: "No hay nada seleccionado.",
|
|
170
|
+
remove: "Quitar",
|
|
171
|
+
removeItem: (name) => `Quitar ${name}`,
|
|
172
|
+
clear: "Limpiar",
|
|
173
|
+
replace: "Reemplazar",
|
|
174
|
+
selected: (name) => `${name} seleccionado.`,
|
|
175
|
+
removed: (name) => `${name} se quit\xF3.`,
|
|
176
|
+
cleared: "Se limpi\xF3 la selecci\xF3n."
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
export {
|
|
180
|
+
devulturErrorLabels,
|
|
181
|
+
previewLabels,
|
|
182
|
+
attachmentLabels,
|
|
183
|
+
mediaLibraryLabels,
|
|
184
|
+
mediaPickerLabels
|
|
185
|
+
};
|
|
@@ -81,6 +81,8 @@ var DEVULTUR_ERROR_CODES = [
|
|
|
81
81
|
"unsupported_type",
|
|
82
82
|
"type_mismatch",
|
|
83
83
|
"token_unavailable",
|
|
84
|
+
"page_cap",
|
|
85
|
+
"render_failed",
|
|
84
86
|
// `DevulturCapabilityError` (an action the provider wasn't given)
|
|
85
87
|
"capability_unavailable"
|
|
86
88
|
];
|
|
@@ -104,6 +106,9 @@ function devulturErrorOf(error) {
|
|
|
104
106
|
}
|
|
105
107
|
|
|
106
108
|
// src/error-labels.ts
|
|
109
|
+
function labelText(label, details = {}) {
|
|
110
|
+
return typeof label === "function" ? label(details) : label;
|
|
111
|
+
}
|
|
107
112
|
function formatBytes(bytes, locale) {
|
|
108
113
|
const isMegabytes = bytes >= 1e6;
|
|
109
114
|
const amount = isMegabytes ? bytes / 1e6 : bytes / 1e3;
|
|
@@ -202,6 +207,12 @@ var devulturErrorLabels = {
|
|
|
202
207
|
unsupported_type: "This file type can't be previewed.",
|
|
203
208
|
type_mismatch: "The file's content doesn't match its type.",
|
|
204
209
|
token_unavailable: "Access to this file couldn't be granted. Try again.",
|
|
210
|
+
page_cap: (details) => {
|
|
211
|
+
const { shown, total } = details;
|
|
212
|
+
if (typeof shown !== "number" || typeof total !== "number") return "Only the first pages are shown.";
|
|
213
|
+
return `Only the first ${shown.toLocaleString("en")} of ${total.toLocaleString("en")} pages are shown.`;
|
|
214
|
+
},
|
|
215
|
+
render_failed: "The file couldn't be displayed.",
|
|
205
216
|
capability_unavailable: "This app can't do that here."
|
|
206
217
|
};
|
|
207
218
|
function asRecord(value) {
|
|
@@ -211,7 +222,9 @@ function codedErrorOf(error) {
|
|
|
211
222
|
if (!(error instanceof Error)) return null;
|
|
212
223
|
const { code, status, details, limit } = error;
|
|
213
224
|
const statusField = typeof status === "number" ? { status } : {};
|
|
214
|
-
if (error.name === "MediaFetchError" && typeof code === "string")
|
|
225
|
+
if (error.name === "MediaFetchError" && typeof code === "string") {
|
|
226
|
+
return { code, details: { ...asRecord(details), ...statusField } };
|
|
227
|
+
}
|
|
215
228
|
if (error.name === "DevulturCapabilityError") return { code: "capability_unavailable", details: {} };
|
|
216
229
|
if (error.name !== "DevulturApiError") return null;
|
|
217
230
|
const limitField = typeof limit === "number" ? { limit } : {};
|
|
@@ -229,8 +242,7 @@ function describeDevulturError(error, labels) {
|
|
|
229
242
|
const descriptor = descriptorOf(error);
|
|
230
243
|
if (!descriptor) return null;
|
|
231
244
|
const code = isDevulturErrorCode(descriptor.code) ? descriptor.code : "worker_error";
|
|
232
|
-
|
|
233
|
-
return typeof label === "function" ? label(descriptor.details) : label;
|
|
245
|
+
return labelText(labels?.[code] ?? devulturErrorLabels[code], descriptor.details);
|
|
234
246
|
}
|
|
235
247
|
|
|
236
248
|
export {
|
|
@@ -238,6 +250,7 @@ export {
|
|
|
238
250
|
isDevulturErrorCode,
|
|
239
251
|
isDevulturError,
|
|
240
252
|
devulturErrorOf,
|
|
253
|
+
labelText,
|
|
241
254
|
formatBytes,
|
|
242
255
|
formatDate,
|
|
243
256
|
devulturErrorLabels,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
declare const DEVULTUR_ERROR_CODES: readonly ["file_too_large", "content_type_not_allowed", "content_type_mismatch", "content_unverified", "unsupported_content_type", "media_type_mismatch", "already_exists", "write_conflict", "upload_not_found", "invalid_upload_key", "invalid_path", "path_required", "invalid_expires_in", "invalid_file_expires_in", "invalid_cache_control", "invalid_limits", "invalid_prefix", "invalid_visibility", "invalid_cursor", "invalid_sha256", "sha256_mismatch", "max_files_reached", "invalid_multipart", "invalid_size", "invalid_part", "invalid_parts", "part_size_mismatch", "part_sha256_required", "invalid_media_metadata", "expired", "invalid_key", "invalid_max_uses", "link_exists", "link_not_found", "link_expired", "link_used", "not_configured", "retention_active", "lock_conflict", "compliance_extend_only", "lock_privilege_required", "lock_record_unreadable", "lock_below_minimum", "invalid_lock", "invalid_hold", "reserved_key", "keys_bucket_missing", "encryption_key_missing", "unauthorized", "session_mismatch", "token_rejected", "reserved_user_id", "invalid_scopes", "user_mismatch", "transcode_not_configured", "transcode_runner_unavailable", "transcode_launch_failed", "original_not_retained", "locale_not_allowed", "captions_provider_rate_limited", "captions_provider_error", "captions_failed", "webhook_secret_missing", "worker_auth_secret_missing", "worker_error", "http_error", "too_large", "unsupported_type", "type_mismatch", "token_unavailable", "capability_unavailable"];
|
|
1
|
+
declare const DEVULTUR_ERROR_CODES: readonly ["file_too_large", "content_type_not_allowed", "content_type_mismatch", "content_unverified", "unsupported_content_type", "media_type_mismatch", "already_exists", "write_conflict", "upload_not_found", "invalid_upload_key", "invalid_path", "path_required", "invalid_expires_in", "invalid_file_expires_in", "invalid_cache_control", "invalid_limits", "invalid_prefix", "invalid_visibility", "invalid_cursor", "invalid_sha256", "sha256_mismatch", "max_files_reached", "invalid_multipart", "invalid_size", "invalid_part", "invalid_parts", "part_size_mismatch", "part_sha256_required", "invalid_media_metadata", "expired", "invalid_key", "invalid_max_uses", "link_exists", "link_not_found", "link_expired", "link_used", "not_configured", "retention_active", "lock_conflict", "compliance_extend_only", "lock_privilege_required", "lock_record_unreadable", "lock_below_minimum", "invalid_lock", "invalid_hold", "reserved_key", "keys_bucket_missing", "encryption_key_missing", "unauthorized", "session_mismatch", "token_rejected", "reserved_user_id", "invalid_scopes", "user_mismatch", "transcode_not_configured", "transcode_runner_unavailable", "transcode_launch_failed", "original_not_retained", "locale_not_allowed", "captions_provider_rate_limited", "captions_provider_error", "captions_failed", "webhook_secret_missing", "worker_auth_secret_missing", "worker_error", "http_error", "too_large", "unsupported_type", "type_mismatch", "token_unavailable", "page_cap", "render_failed", "capability_unavailable"];
|
|
2
2
|
/** A stable error code: match on it, not on `message`. */
|
|
3
3
|
type DevulturErrorCode = (typeof DEVULTUR_ERROR_CODES)[number];
|
|
4
4
|
declare function isDevulturErrorCode(code: unknown): code is DevulturErrorCode;
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { FunctionReference, FunctionVisibility, DefaultFunctionArgs, GenericQuer
|
|
|
4
4
|
import { PropertyValidators, Value, ConvexError } from 'convex/values';
|
|
5
5
|
import { D as DevulturComponentConfig, M as MediaRecord } from './types-LrusGVDf.js';
|
|
6
6
|
export { P as ProgressRecord } from './types-LrusGVDf.js';
|
|
7
|
-
export { a as DEVULTUR_ERROR_CODES, b as DevulturErrorCode, c as DevulturErrorDetails, d as DevulturErrorLabel, D as DevulturErrorLabels, e as describeDevulturError, f as devulturErrorLabels, i as isDevulturErrorCode } from './error-labels-
|
|
7
|
+
export { a as DEVULTUR_ERROR_CODES, b as DevulturErrorCode, c as DevulturErrorDetails, d as DevulturErrorLabel, D as DevulturErrorLabels, e as describeDevulturError, f as devulturErrorLabels, i as isDevulturErrorCode } from './error-labels-D0Vbp-qA.js';
|
|
8
8
|
export { dv } from './validators.js';
|
|
9
9
|
|
|
10
10
|
/**
|
package/dist/index.js
CHANGED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { A as AttachmentLabels, M as MediaLibraryLabels, a as MediaPickerLabels, P as PreviewLabels } from '../preview-labels-B-2mra1h.js';
|
|
2
|
+
import { D as DevulturErrorLabels } from '../error-labels-D0Vbp-qA.js';
|
|
3
|
+
import '../types-LrusGVDf.js';
|
|
4
|
+
import '@devultur/core';
|
|
5
|
+
|
|
6
|
+
declare const devulturErrorLabels: DevulturErrorLabels;
|
|
7
|
+
declare const attachmentLabels: AttachmentLabels;
|
|
8
|
+
declare const previewLabels: PreviewLabels;
|
|
9
|
+
declare const mediaLibraryLabels: MediaLibraryLabels;
|
|
10
|
+
declare const mediaPickerLabels: MediaPickerLabels;
|
|
11
|
+
|
|
12
|
+
export { attachmentLabels, devulturErrorLabels, mediaLibraryLabels, mediaPickerLabels, previewLabels };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import {
|
|
2
|
+
attachmentLabels,
|
|
3
|
+
devulturErrorLabels,
|
|
4
|
+
mediaLibraryLabels,
|
|
5
|
+
mediaPickerLabels,
|
|
6
|
+
previewLabels
|
|
7
|
+
} from "../chunk-JZYKPLI4.js";
|
|
8
|
+
import "../chunk-QBHIZBOQ.js";
|
|
9
|
+
import {
|
|
10
|
+
describeDevulturError,
|
|
11
|
+
labelText
|
|
12
|
+
} from "../chunk-YYOZ3PDH.js";
|
|
13
|
+
|
|
14
|
+
// src/locales/es-formal.ts
|
|
15
|
+
var TRY_AGAIN = "Vuelva a intentarlo.";
|
|
16
|
+
var TRY_AGAIN_LATER = "Vuelva a intentarlo m\xE1s tarde.";
|
|
17
|
+
var devulturErrorLabels2 = {
|
|
18
|
+
...devulturErrorLabels,
|
|
19
|
+
content_unverified: `No se pudo verificar la subida. ${TRY_AGAIN}`,
|
|
20
|
+
write_conflict: `El archivo cambi\xF3 mientras se guardaba. ${TRY_AGAIN}`,
|
|
21
|
+
upload_not_found: "No se encontr\xF3 la subida o ya venci\xF3. Vuelva a empezarla.",
|
|
22
|
+
invalid_cursor: "La p\xE1gina de resultados no es v\xE1lida. Vuelva a cargar la lista.",
|
|
23
|
+
sha256_mismatch: `El archivo se da\xF1\xF3 durante la subida. ${TRY_AGAIN}`,
|
|
24
|
+
max_files_reached: "Alcanz\xF3 el n\xFAmero m\xE1ximo de archivos para esta subida.",
|
|
25
|
+
invalid_part: `Una parte de la subida no es v\xE1lida. ${TRY_AGAIN}`,
|
|
26
|
+
invalid_parts: `La subida est\xE1 incompleta. ${TRY_AGAIN}`,
|
|
27
|
+
part_size_mismatch: `Una parte de la subida tiene un tama\xF1o incorrecto. ${TRY_AGAIN}`,
|
|
28
|
+
invalid_media_metadata: (details) => {
|
|
29
|
+
if (details.field === "tags") return "Use como m\xE1ximo 20 etiquetas, de hasta 50 caracteres cada una.";
|
|
30
|
+
return labelText(devulturErrorLabels.invalid_media_metadata, details);
|
|
31
|
+
},
|
|
32
|
+
lock_conflict: `La protecci\xF3n del archivo cambi\xF3 mientras tanto. ${TRY_AGAIN}`,
|
|
33
|
+
lock_privilege_required: "No tiene permiso para acortar ni quitar la protecci\xF3n de este archivo.",
|
|
34
|
+
encryption_key_missing: "Este archivo ya no se puede leer. Vuelva a subirlo.",
|
|
35
|
+
unauthorized: "No tiene autorizaci\xF3n para hacer esto.",
|
|
36
|
+
session_mismatch: "Su sesi\xF3n cambi\xF3. Vuelva a cargar la p\xE1gina.",
|
|
37
|
+
user_mismatch: "Solo puede ver y cambiar su propio progreso.",
|
|
38
|
+
transcode_runner_unavailable: `El procesamiento de video est\xE1 ocupado en este momento. ${TRY_AGAIN_LATER}`,
|
|
39
|
+
original_not_retained: "El video original ya no est\xE1 disponible, as\xED que no se puede volver a procesar. Vuelva a subirlo.",
|
|
40
|
+
captions_provider_rate_limited: `El servicio de subt\xEDtulos est\xE1 ocupado en este momento. ${TRY_AGAIN_LATER}`,
|
|
41
|
+
token_unavailable: `No se pudo autorizar el acceso a este archivo. ${TRY_AGAIN}`
|
|
42
|
+
};
|
|
43
|
+
var attachmentLabels2 = attachmentLabels;
|
|
44
|
+
var previewLabels2 = {
|
|
45
|
+
...previewLabels,
|
|
46
|
+
error: (code) => code === "page_cap" ? "Descargue el archivo para ver todas las p\xE1ginas." : labelText(devulturErrorLabels2[code])
|
|
47
|
+
};
|
|
48
|
+
var mediaLibraryLabels2 = {
|
|
49
|
+
...mediaLibraryLabels,
|
|
50
|
+
searchPlaceholder: "Busque por t\xEDtulo o nombre de archivo",
|
|
51
|
+
error: (error) => describeDevulturError(error, devulturErrorLabels2) ?? "No se pudieron cargar los archivos."
|
|
52
|
+
};
|
|
53
|
+
var mediaPickerLabels2 = {
|
|
54
|
+
...mediaPickerLabels,
|
|
55
|
+
dropHint: (multiple) => multiple ? "o suelte los archivos aqu\xED" : "o suelte un archivo aqu\xED",
|
|
56
|
+
uploadError: (error) => describeDevulturError(error, devulturErrorLabels2) ?? `La subida fall\xF3. ${TRY_AGAIN}`
|
|
57
|
+
};
|
|
58
|
+
export {
|
|
59
|
+
attachmentLabels2 as attachmentLabels,
|
|
60
|
+
devulturErrorLabels2 as devulturErrorLabels,
|
|
61
|
+
mediaLibraryLabels2 as mediaLibraryLabels,
|
|
62
|
+
mediaPickerLabels2 as mediaPickerLabels,
|
|
63
|
+
previewLabels2 as previewLabels
|
|
64
|
+
};
|
package/dist/locales/es.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { A as AttachmentLabels, M as MediaLibraryLabels, a as MediaPickerLabels } from '../
|
|
2
|
-
import { D as DevulturErrorLabels } from '../error-labels-
|
|
1
|
+
import { A as AttachmentLabels, M as MediaLibraryLabels, a as MediaPickerLabels, P as PreviewLabels } from '../preview-labels-B-2mra1h.js';
|
|
2
|
+
import { D as DevulturErrorLabels } from '../error-labels-D0Vbp-qA.js';
|
|
3
3
|
import '../types-LrusGVDf.js';
|
|
4
4
|
import '@devultur/core';
|
|
5
5
|
|
|
6
6
|
declare const devulturErrorLabels: DevulturErrorLabels;
|
|
7
|
+
declare const previewLabels: PreviewLabels;
|
|
7
8
|
declare const attachmentLabels: AttachmentLabels;
|
|
8
9
|
declare const mediaLibraryLabels: MediaLibraryLabels;
|
|
9
10
|
declare const mediaPickerLabels: MediaPickerLabels;
|
|
10
11
|
|
|
11
|
-
export { attachmentLabels, devulturErrorLabels, mediaLibraryLabels, mediaPickerLabels };
|
|
12
|
+
export { attachmentLabels, devulturErrorLabels, mediaLibraryLabels, mediaPickerLabels, previewLabels };
|
package/dist/locales/es.js
CHANGED
|
@@ -1,162 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
// src/locales/es.ts
|
|
12
|
-
var LOCALE = "es";
|
|
13
|
-
var devulturErrorLabels = {
|
|
14
|
-
file_too_large: (details) => {
|
|
15
|
-
const limit = typeof details.limit === "number" ? formatBytes(details.limit, LOCALE) : null;
|
|
16
|
-
return limit ? `El archivo supera el tama\xF1o m\xE1ximo (${limit}).` : "El archivo supera el tama\xF1o m\xE1ximo.";
|
|
17
|
-
},
|
|
18
|
-
content_type_not_allowed: "Este tipo de archivo no est\xE1 permitido.",
|
|
19
|
-
content_type_mismatch: "El contenido del archivo no coincide con su tipo.",
|
|
20
|
-
content_unverified: "No se pudo verificar la subida. Vuelve a intentarlo.",
|
|
21
|
-
unsupported_content_type: "Este tipo de archivo no es compatible.",
|
|
22
|
-
media_type_mismatch: "El tipo de archivo no coincide con el tipo de contenido esperado.",
|
|
23
|
-
already_exists: "Ya existe un archivo con este nombre.",
|
|
24
|
-
write_conflict: "El archivo cambi\xF3 mientras se guardaba. Vuelve a intentarlo.",
|
|
25
|
-
upload_not_found: "No se encontr\xF3 la subida o ya venci\xF3. Vuelve a empezarla.",
|
|
26
|
-
invalid_upload_key: "Esta subida no es v\xE1lida.",
|
|
27
|
-
invalid_path: "La ruta del archivo no es v\xE1lida.",
|
|
28
|
-
path_required: "Esta subida necesita una ruta de archivo.",
|
|
29
|
-
invalid_expires_in: "El tiempo de vencimiento no es v\xE1lido.",
|
|
30
|
-
invalid_file_expires_in: "El tiempo de vencimiento del archivo no es v\xE1lido.",
|
|
31
|
-
invalid_cache_control: "La configuraci\xF3n de cach\xE9 no es v\xE1lida.",
|
|
32
|
-
invalid_limits: "Los l\xEDmites de la subida no son v\xE1lidos.",
|
|
33
|
-
invalid_prefix: "La carpeta no es v\xE1lida.",
|
|
34
|
-
invalid_visibility: "La visibilidad debe ser p\xFAblica o privada.",
|
|
35
|
-
invalid_cursor: "La p\xE1gina de resultados no es v\xE1lida. Vuelve a cargar la lista.",
|
|
36
|
-
invalid_sha256: "La suma de verificaci\xF3n del archivo no es v\xE1lida.",
|
|
37
|
-
sha256_mismatch: "El archivo se da\xF1\xF3 durante la subida. Vuelve a intentarlo.",
|
|
38
|
-
max_files_reached: "Alcanzaste el n\xFAmero m\xE1ximo de archivos para esta subida.",
|
|
39
|
-
invalid_multipart: "La solicitud de subida no es v\xE1lida.",
|
|
40
|
-
invalid_size: "El tama\xF1o del archivo no es v\xE1lido.",
|
|
41
|
-
invalid_part: "Una parte de la subida no es v\xE1lida. Vuelve a intentarlo.",
|
|
42
|
-
invalid_parts: "La subida est\xE1 incompleta. Vuelve a intentarlo.",
|
|
43
|
-
part_size_mismatch: "Una parte de la subida tiene un tama\xF1o incorrecto. Vuelve a intentarlo.",
|
|
44
|
-
part_sha256_required: "A una parte de la subida le falta la suma de verificaci\xF3n.",
|
|
45
|
-
invalid_media_metadata: (details) => {
|
|
46
|
-
if (details.field === "title") return "El t\xEDtulo no puede tener m\xE1s de 200 caracteres.";
|
|
47
|
-
if (details.field === "alt") return "El texto alternativo no puede tener m\xE1s de 1000 caracteres.";
|
|
48
|
-
if (details.field === "tags") return "Usa como m\xE1ximo 20 etiquetas, de hasta 50 caracteres cada una.";
|
|
49
|
-
return "Los datos del archivo no son v\xE1lidos.";
|
|
50
|
-
},
|
|
51
|
-
expired: "Este archivo ya venci\xF3.",
|
|
52
|
-
invalid_key: "La referencia del archivo no es v\xE1lida.",
|
|
53
|
-
invalid_max_uses: "El n\xFAmero de usos no es v\xE1lido.",
|
|
54
|
-
link_exists: "Este enlace de descarga ya existe.",
|
|
55
|
-
link_not_found: "Este enlace de descarga no existe.",
|
|
56
|
-
link_expired: "Este enlace de descarga ya venci\xF3.",
|
|
57
|
-
link_used: "Este enlace de descarga ya se us\xF3.",
|
|
58
|
-
not_configured: "Esta funci\xF3n no est\xE1 configurada.",
|
|
59
|
-
retention_active: (details) => {
|
|
60
|
-
if (details.hold === true) return "Este archivo tiene una retenci\xF3n legal y no se puede modificar ni eliminar.";
|
|
61
|
-
const until = formatDate(details.until, LOCALE);
|
|
62
|
-
return until ? `Este archivo est\xE1 protegido hasta el ${until} y no se puede modificar ni eliminar antes de esa fecha.` : "Este archivo est\xE1 protegido y no se puede modificar ni eliminar.";
|
|
63
|
-
},
|
|
64
|
-
lock_conflict: "La protecci\xF3n del archivo cambi\xF3 mientras tanto. Vuelve a intentarlo.",
|
|
65
|
-
compliance_extend_only: "La protecci\xF3n de este archivo solo se puede extender.",
|
|
66
|
-
lock_privilege_required: "No tienes permiso para acortar ni quitar la protecci\xF3n de este archivo.",
|
|
67
|
-
lock_record_unreadable: "No se pudo leer la protecci\xF3n del archivo.",
|
|
68
|
-
lock_below_minimum: "Esta subida requiere una protecci\xF3n m\xE1s estricta.",
|
|
69
|
-
invalid_lock: "La configuraci\xF3n de protecci\xF3n no es v\xE1lida.",
|
|
70
|
-
invalid_hold: "La configuraci\xF3n de retenci\xF3n legal no es v\xE1lida.",
|
|
71
|
-
reserved_key: "Este nombre de archivo est\xE1 reservado.",
|
|
72
|
-
keys_bucket_missing: "En este momento no se pueden guardar archivos de forma segura.",
|
|
73
|
-
encryption_key_missing: "Este archivo ya no se puede leer. Vuelve a subirlo.",
|
|
74
|
-
unauthorized: "No tienes autorizaci\xF3n para hacer esto.",
|
|
75
|
-
session_mismatch: "Tu sesi\xF3n cambi\xF3. Vuelve a cargar la p\xE1gina.",
|
|
76
|
-
token_rejected: "Se deneg\xF3 el acceso.",
|
|
77
|
-
reserved_user_id: "Este identificador de usuario est\xE1 reservado.",
|
|
78
|
-
invalid_scopes: "Los permisos solicitados no son v\xE1lidos.",
|
|
79
|
-
user_mismatch: "Solo puedes ver y cambiar tu propio progreso.",
|
|
80
|
-
transcode_not_configured: "El procesamiento de video no est\xE1 configurado.",
|
|
81
|
-
transcode_runner_unavailable: "El procesamiento de video est\xE1 ocupado en este momento. Vuelve a intentarlo m\xE1s tarde.",
|
|
82
|
-
transcode_launch_failed: "No se pudo procesar el video.",
|
|
83
|
-
original_not_retained: "El video original ya no est\xE1 disponible, as\xED que no se puede volver a procesar. Vuelve a subirlo.",
|
|
84
|
-
locale_not_allowed: "Los subt\xEDtulos no est\xE1n disponibles en este idioma.",
|
|
85
|
-
captions_provider_rate_limited: "El servicio de subt\xEDtulos est\xE1 ocupado en este momento. Vuelve a intentarlo m\xE1s tarde.",
|
|
86
|
-
captions_provider_error: "No se pudieron generar los subt\xEDtulos.",
|
|
87
|
-
captions_failed: "No se pudieron generar los subt\xEDtulos.",
|
|
88
|
-
webhook_secret_missing: "El procesamiento de video no est\xE1 configurado.",
|
|
89
|
-
worker_auth_secret_missing: "El servicio de medios no est\xE1 configurado.",
|
|
90
|
-
worker_error: "El servicio de medios no pudo completar la solicitud.",
|
|
91
|
-
http_error: "No se pudo cargar el archivo.",
|
|
92
|
-
too_large: "El archivo es demasiado grande para la vista previa.",
|
|
93
|
-
unsupported_type: "Este tipo de archivo no tiene vista previa.",
|
|
94
|
-
type_mismatch: "El contenido del archivo no coincide con su tipo.",
|
|
95
|
-
token_unavailable: "No se pudo autorizar el acceso a este archivo. Vuelve a intentarlo.",
|
|
96
|
-
capability_unavailable: "Esta aplicaci\xF3n no puede hacer eso aqu\xED."
|
|
97
|
-
};
|
|
98
|
-
var KIND_TEXT = {
|
|
99
|
-
image: "Imagen",
|
|
100
|
-
video: "Video",
|
|
101
|
-
pdf: "PDF",
|
|
102
|
-
audio: "Audio",
|
|
103
|
-
text: "Texto",
|
|
104
|
-
file: "Archivo"
|
|
105
|
-
};
|
|
106
|
-
var attachmentLabels = {
|
|
107
|
-
locale: LOCALE,
|
|
108
|
-
size: formatFileSize,
|
|
109
|
-
pages: (pageCount) => pageCount === 1 ? "1 p\xE1gina" : `${pageCount.toLocaleString(LOCALE)} p\xE1ginas`,
|
|
110
|
-
duration: formatDuration,
|
|
111
|
-
kind: (kind) => KIND_TEXT[kind],
|
|
112
|
-
download: "Descargar",
|
|
113
|
-
open: "Abrir vista previa",
|
|
114
|
-
untitled: "Archivo sin t\xEDtulo"
|
|
115
|
-
};
|
|
116
|
-
var mediaLibraryLabels = {
|
|
117
|
-
search: "Buscar archivos",
|
|
118
|
-
searchPlaceholder: "Busca por t\xEDtulo o nombre de archivo",
|
|
119
|
-
typeFilter: "Tipo",
|
|
120
|
-
allTypes: "Todos los tipos",
|
|
121
|
-
types: { image: "Im\xE1genes", video: "Videos", file: "Archivos" },
|
|
122
|
-
results: "Archivos",
|
|
123
|
-
loading: "Cargando archivos\u2026",
|
|
124
|
-
empty: "Todav\xEDa no hay archivos.",
|
|
125
|
-
noResults: (search) => `Nada coincide con \xAB${search}\xBB.`,
|
|
126
|
-
loadMore: "Cargar m\xE1s",
|
|
127
|
-
loadingMore: "Cargando\u2026",
|
|
128
|
-
error: (error) => describeDevulturError(error, devulturErrorLabels) ?? "No se pudieron cargar los archivos.",
|
|
129
|
-
retry: "Reintentar",
|
|
130
|
-
size: (bytes) => formatFileSize(bytes, LOCALE)
|
|
131
|
-
};
|
|
132
|
-
var mediaPickerLabels = {
|
|
133
|
-
upload: (multiple) => multiple ? "Subir archivos" : "Subir un archivo",
|
|
134
|
-
dropHint: (multiple) => multiple ? "o suelta los archivos aqu\xED" : "o suelta un archivo aqu\xED",
|
|
135
|
-
uploads: "Subidas",
|
|
136
|
-
progress: (filename) => `Subiendo ${filename}`,
|
|
137
|
-
percent: (percent) => `${percent} %`,
|
|
138
|
-
uploading: (filename) => `Subiendo ${filename}.`,
|
|
139
|
-
uploaded: (filename) => `${filename} se subi\xF3 y qued\xF3 seleccionado.`,
|
|
140
|
-
cancel: "Cancelar",
|
|
141
|
-
cancelUpload: (filename) => `Cancelar la subida de ${filename}`,
|
|
142
|
-
cancelled: (filename) => `Se cancel\xF3 la subida de ${filename}.`,
|
|
143
|
-
notAccepted: (filename) => `${filename} no es un tipo de archivo que se pueda elegir aqu\xED.`,
|
|
144
|
-
uploadError: (error) => describeDevulturError(error, devulturErrorLabels) ?? "La subida fall\xF3. Vuelve a intentarlo.",
|
|
145
|
-
retry: "Reintentar",
|
|
146
|
-
dismiss: "Descartar",
|
|
147
|
-
selection: "Archivos seleccionados",
|
|
148
|
-
empty: "No hay nada seleccionado.",
|
|
149
|
-
remove: "Quitar",
|
|
150
|
-
removeItem: (name) => `Quitar ${name}`,
|
|
151
|
-
clear: "Limpiar",
|
|
152
|
-
replace: "Reemplazar",
|
|
153
|
-
selected: (name) => `${name} seleccionado.`,
|
|
154
|
-
removed: (name) => `${name} se quit\xF3.`,
|
|
155
|
-
cleared: "Se limpi\xF3 la selecci\xF3n."
|
|
156
|
-
};
|
|
2
|
+
attachmentLabels,
|
|
3
|
+
devulturErrorLabels,
|
|
4
|
+
mediaLibraryLabels,
|
|
5
|
+
mediaPickerLabels,
|
|
6
|
+
previewLabels
|
|
7
|
+
} from "../chunk-JZYKPLI4.js";
|
|
8
|
+
import "../chunk-QBHIZBOQ.js";
|
|
9
|
+
import "../chunk-YYOZ3PDH.js";
|
|
157
10
|
export {
|
|
158
11
|
attachmentLabels,
|
|
159
12
|
devulturErrorLabels,
|
|
160
13
|
mediaLibraryLabels,
|
|
161
|
-
mediaPickerLabels
|
|
14
|
+
mediaPickerLabels,
|
|
15
|
+
previewLabels
|
|
162
16
|
};
|
|
@@ -111,4 +111,61 @@ interface MediaPickerLabels {
|
|
|
111
111
|
}
|
|
112
112
|
declare const defaultMediaPickerLabels: MediaPickerLabels;
|
|
113
113
|
|
|
114
|
-
|
|
114
|
+
/** Why a media couldn't be fetched or shown. Stable: match on it, not on `message`. */
|
|
115
|
+
type MediaFetchErrorCode =
|
|
116
|
+
/** The delivery answered with a non-2xx status (`status` has it), or never answered (a network failure: no `status`). */
|
|
117
|
+
"http_error"
|
|
118
|
+
/** `Content-Length`, or the streamed body, exceeds `maxBytes`. */
|
|
119
|
+
| "too_large"
|
|
120
|
+
/** The expected content type isn't one that can be previewed inline. */
|
|
121
|
+
| "unsupported_type"
|
|
122
|
+
/** The response's `Content-Type` doesn't agree with the expected one. */
|
|
123
|
+
| "type_mismatch"
|
|
124
|
+
/** No viewer token for private media: its issuance failed (`useDevultur().tokenError` has why) or was refused. */
|
|
125
|
+
| "token_unavailable"
|
|
126
|
+
/** The delivery refused the token for this browser session, also after a re-issue (video playback). */
|
|
127
|
+
| "session_mismatch"
|
|
128
|
+
/** A PDF has more pages than `maxPages`: only the first ones are shown (`details: { shown, total }`). */
|
|
129
|
+
| "page_cap"
|
|
130
|
+
/** The bytes arrived but couldn't be shown: pdf.js can't open the PDF, or the video can't be played. */
|
|
131
|
+
| "render_failed";
|
|
132
|
+
/** `ErrorOptions` plus the code's `details`. */
|
|
133
|
+
interface MediaFetchErrorOptions extends ErrorOptions {
|
|
134
|
+
details?: Readonly<Record<string, unknown>>;
|
|
135
|
+
}
|
|
136
|
+
declare class MediaFetchError extends Error {
|
|
137
|
+
readonly code: MediaFetchErrorCode;
|
|
138
|
+
/** HTTP status, for `http_error` when the delivery answered. */
|
|
139
|
+
readonly status?: number;
|
|
140
|
+
/** The code's extra fields, e.g. `page_cap`'s `{ shown, total }`. */
|
|
141
|
+
readonly details?: Readonly<Record<string, unknown>>;
|
|
142
|
+
constructor(code: MediaFetchErrorCode, message: string, status?: number, options?: MediaFetchErrorOptions);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Every string `<Preview>`, `<PdfThumbnail>` and their PDF pages show or announce. Pass any subset as `labels` on a
|
|
147
|
+
* component or on `PdfPreviewProvider`; the component's wins over the provider's, which wins over the English defaults.
|
|
148
|
+
*/
|
|
149
|
+
interface PreviewLabels {
|
|
150
|
+
/** Accessible name of a pdf.js document: its title and page count. */
|
|
151
|
+
document: (title: string, pageCount: number) => string;
|
|
152
|
+
/** Accessible name of one pdf.js page. */
|
|
153
|
+
page: (page: number, pageCount: number) => string;
|
|
154
|
+
/** Announced (visually hidden) while a preview loads, when no `loading` is passed. */
|
|
155
|
+
loading: string;
|
|
156
|
+
/** Note after the last rendered page when a PDF has more than `maxPages`; `fallback` follows it. */
|
|
157
|
+
pageCap: (shown: number, total: number) => string;
|
|
158
|
+
/** `title` of the default fallback's download link, for why it's shown (see `<Preview>`'s `fallback`). */
|
|
159
|
+
error: (code: MediaFetchErrorCode) => string;
|
|
160
|
+
/** Accessible name of a `<PdfThumbnail>`, from its title. */
|
|
161
|
+
thumbnail: (title: string) => string;
|
|
162
|
+
/** Name of a PDF (pdf.js document, `<iframe>` title, thumbnail) with no `title` and no filename. */
|
|
163
|
+
untitledPdf: string;
|
|
164
|
+
/** Name of an image or audio preview with no `title` and no filename. */
|
|
165
|
+
untitledMedia: string;
|
|
166
|
+
/** Text of the default fallback's download link when the media has no filename. */
|
|
167
|
+
download: string;
|
|
168
|
+
}
|
|
169
|
+
declare const defaultPreviewLabels: PreviewLabels;
|
|
170
|
+
|
|
171
|
+
export { type AttachmentLabels as A, type MediaLibraryLabels as M, type PreviewLabels as P, type MediaPickerLabels as a, MediaFetchError as b, type AttachmentKind as c, type MediaFetchErrorCode as d, defaultAttachmentLabels as e, defaultMediaLibraryLabels as f, defaultMediaPickerLabels as g, defaultPreviewLabels as h, formatDuration as i, formatFileSize as j };
|
package/dist/react.d.ts
CHANGED
|
@@ -3,34 +3,13 @@ import { DevulturMedia, MediaUrlOptions, Visibility, ProcessingPhase, FailureRea
|
|
|
3
3
|
import { BakeOutputFormat, MediaUploadState, MediaUploadError, UploadProgress } from '@devultur/react';
|
|
4
4
|
export { MediaUploadError, MediaUploadState, UploadProgress } from '@devultur/react';
|
|
5
5
|
import { FunctionReference } from 'convex/server';
|
|
6
|
+
import { A as AttachmentLabels, M as MediaLibraryLabels, P as PreviewLabels, a as MediaPickerLabels, b as MediaFetchError } from './preview-labels-B-2mra1h.js';
|
|
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-B-2mra1h.js';
|
|
6
8
|
import { Value } from 'convex/values';
|
|
7
|
-
import { A as AttachmentLabels, M as MediaLibraryLabels, a as MediaPickerLabels } from './media-picker-labels-CiVcNUZo.js';
|
|
8
|
-
export { b as AttachmentKind, d as defaultAttachmentLabels, c as defaultMediaLibraryLabels, e as defaultMediaPickerLabels, f as formatDuration, g as formatFileSize } from './media-picker-labels-CiVcNUZo.js';
|
|
9
9
|
import { M as MediaRecord } from './types-LrusGVDf.js';
|
|
10
10
|
import { P as PdfjsLoader } from './pdf-render-BwJGagvz.js';
|
|
11
11
|
export { a as PdfjsModule } from './pdf-render-BwJGagvz.js';
|
|
12
12
|
|
|
13
|
-
/** Why a media fetch was refused. Stable: match on it, not on `message`. */
|
|
14
|
-
type MediaFetchErrorCode =
|
|
15
|
-
/** The delivery answered with a non-2xx status (`status` has it). */
|
|
16
|
-
"http_error"
|
|
17
|
-
/** `Content-Length`, or the streamed body, exceeds `maxBytes`. */
|
|
18
|
-
| "too_large"
|
|
19
|
-
/** The expected content type isn't one that can be previewed inline. */
|
|
20
|
-
| "unsupported_type"
|
|
21
|
-
/** The response's `Content-Type` doesn't agree with the expected one. */
|
|
22
|
-
| "type_mismatch"
|
|
23
|
-
/** No viewer token for private media: its issuance failed (`useDevultur().tokenError` has why) or was refused. */
|
|
24
|
-
| "token_unavailable"
|
|
25
|
-
/** The delivery refused the token for this browser session, also after a re-issue (video playback). */
|
|
26
|
-
| "session_mismatch";
|
|
27
|
-
declare class MediaFetchError extends Error {
|
|
28
|
-
readonly code: MediaFetchErrorCode;
|
|
29
|
-
/** HTTP status, for `http_error`. */
|
|
30
|
-
readonly status?: number;
|
|
31
|
-
constructor(code: MediaFetchErrorCode, message: string, status?: number, options?: ErrorOptions);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
13
|
/** What a viewer token action returns: the token with its lifetime, or the bare token (default lifetime). */
|
|
35
14
|
type ViewerTokenResult = {
|
|
36
15
|
token: string;
|
|
@@ -311,32 +290,6 @@ interface MediaObjectUrl {
|
|
|
311
290
|
*/
|
|
312
291
|
declare function useMediaObjectUrl(media: DevulturMedia | null | undefined, options?: UseMediaObjectUrlOptions): MediaObjectUrl;
|
|
313
292
|
|
|
314
|
-
/**
|
|
315
|
-
* Every string `<Preview>`, `<PdfThumbnail>` and their PDF pages show or announce. Pass any subset as `labels` on a
|
|
316
|
-
* component or on `PdfPreviewProvider`; the component's wins over the provider's, which wins over the English defaults.
|
|
317
|
-
*/
|
|
318
|
-
interface PreviewLabels {
|
|
319
|
-
/** Accessible name of a pdf.js document: its title and page count. */
|
|
320
|
-
document: (title: string, pageCount: number) => string;
|
|
321
|
-
/** Accessible name of one pdf.js page. */
|
|
322
|
-
page: (page: number, pageCount: number) => string;
|
|
323
|
-
/** Announced (visually hidden) while a preview loads, when no `loading` is passed. */
|
|
324
|
-
loading: string;
|
|
325
|
-
/** Note after the last rendered page when a PDF has more than `maxPages`; `fallback` follows it. */
|
|
326
|
-
pageCap: (shown: number, total: number) => string;
|
|
327
|
-
/** `title` of the default fallback's download link when a fetch was refused or the type can't be previewed. */
|
|
328
|
-
error: (code: MediaFetchErrorCode) => string;
|
|
329
|
-
/** Accessible name of a `<PdfThumbnail>`, from its title. */
|
|
330
|
-
thumbnail: (title: string) => string;
|
|
331
|
-
/** Name of a PDF (pdf.js document, `<iframe>` title, thumbnail) with no `title` and no filename. */
|
|
332
|
-
untitledPdf: string;
|
|
333
|
-
/** Name of an image or audio preview with no `title` and no filename. */
|
|
334
|
-
untitledMedia: string;
|
|
335
|
-
/** Text of the default fallback's download link when the media has no filename. */
|
|
336
|
-
download: string;
|
|
337
|
-
}
|
|
338
|
-
declare const defaultPreviewLabels: PreviewLabels;
|
|
339
|
-
|
|
340
293
|
interface PdfPreviewConfig {
|
|
341
294
|
/**
|
|
342
295
|
* Imports pdf.js. Without it, PDFs render in an `<iframe>` (the browser's own viewer) and `<PdfThumbnail>` renders
|
|
@@ -547,13 +500,15 @@ interface PreviewProps {
|
|
|
547
500
|
/** Size cap for text previews. Default 1 MiB. */
|
|
548
501
|
maxTextBytes?: number;
|
|
549
502
|
/**
|
|
550
|
-
* Shown for types that don't preview inline
|
|
551
|
-
* As a function it receives why
|
|
552
|
-
* `
|
|
553
|
-
*
|
|
554
|
-
* (a
|
|
503
|
+
* Shown for types that don't preview inline, when the fetch or render fails, and after the `maxPages` note.
|
|
504
|
+
* Default: a `<DownloadLink>`. As a function it receives why, always a `MediaFetchError` (never `null`: it's only
|
|
505
|
+
* called with a cause): `http_error` when the delivery refused the fetch (`status`) or never answered (a network
|
|
506
|
+
* failure, no `status`), `too_large`, `type_mismatch`, `token_unavailable` (no viewer token, nothing fetched),
|
|
507
|
+
* `session_mismatch` (a video's session was refused), `unsupported_type` (the type doesn't preview inline, nothing
|
|
508
|
+
* fetched), `render_failed` (pdf.js can't open the PDF, or the video can't be played) or `page_cap` (the link after
|
|
509
|
+
* the `maxPages` note, with `details: { shown, total }`).
|
|
555
510
|
*/
|
|
556
|
-
fallback?: React.ReactNode | ((error: MediaFetchError
|
|
511
|
+
fallback?: React.ReactNode | ((error: MediaFetchError) => React.ReactNode);
|
|
557
512
|
/** Shown while a file loads. Default: `labels.loading`, visually hidden, in a `role="status"`. `null` → nothing. */
|
|
558
513
|
loading?: React.ReactNode;
|
|
559
514
|
/** Accessible name of the preview (`alt`, `title`, `aria-label`). Default: the filename (text: none). */
|
|
@@ -869,4 +824,4 @@ interface UseMediaUploadReturn {
|
|
|
869
824
|
*/
|
|
870
825
|
declare function useMediaUpload(options?: UseMediaUploadOptions): UseMediaUploadReturn;
|
|
871
826
|
|
|
872
|
-
export { AttachmentCard, type AttachmentCardProps, AttachmentLabels, type CaptionTrack, CropUpload, type CropUploadLabels, type CropUploadProps, type CropUploadRenderProps, type DevulturApi, type DevulturCapability, DevulturCapabilityError, DevulturProvider, DevulturViewerProvider, DocumentLink, type DocumentLinkProps, DownloadLink, Image, type ImageProps, MediaFetchError,
|
|
827
|
+
export { AttachmentCard, type AttachmentCardProps, AttachmentLabels, type CaptionTrack, CropUpload, type CropUploadLabels, type CropUploadProps, type CropUploadRenderProps, type DevulturApi, type DevulturCapability, DevulturCapabilityError, DevulturProvider, DevulturViewerProvider, 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 UploadedMedia, type UseMediaLibraryOptions, type UseMediaObjectUrlOptions, type UseMediaUploadOptions, type UseMediaUploadReturn, type VideoProps, type VideoState, type ViewerTokenArgs, type ViewerTokenResult, matchesAccept, useDevultur, useDevulturApi, useDevulturMedia, useDevulturProgress, useMediaLibrary, useMediaObjectUrl, useMediaPicker, useMediaUpload, useMediaUrl, useVideoProps, useVideoState };
|
package/dist/react.js
CHANGED
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
} from "./chunk-QBHIZBOQ.js";
|
|
24
24
|
import {
|
|
25
25
|
describeDevulturError
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-YYOZ3PDH.js";
|
|
27
27
|
|
|
28
28
|
// src/react.tsx
|
|
29
29
|
import React22 from "react";
|
|
@@ -71,15 +71,28 @@ async function isSessionMismatch(response) {
|
|
|
71
71
|
// src/media-fetch.ts
|
|
72
72
|
var MediaFetchError = class extends Error {
|
|
73
73
|
code;
|
|
74
|
-
/** HTTP status, for `http_error
|
|
74
|
+
/** HTTP status, for `http_error` when the delivery answered. */
|
|
75
75
|
status;
|
|
76
|
+
/** The code's extra fields, e.g. `page_cap`'s `{ shown, total }`. */
|
|
77
|
+
details;
|
|
76
78
|
constructor(code, message, status, options) {
|
|
77
79
|
super(message, options);
|
|
78
80
|
this.name = "MediaFetchError";
|
|
79
81
|
this.code = code;
|
|
80
82
|
this.status = status;
|
|
83
|
+
this.details = options?.details;
|
|
81
84
|
}
|
|
82
85
|
};
|
|
86
|
+
function networkError(cause) {
|
|
87
|
+
return new MediaFetchError("http_error", "Media fetch failed: no response", void 0, { cause });
|
|
88
|
+
}
|
|
89
|
+
function pageCapError(shown, total) {
|
|
90
|
+
const message = `Showing the first ${shown} of ${total} pages`;
|
|
91
|
+
return new MediaFetchError("page_cap", message, void 0, { details: { shown, total } });
|
|
92
|
+
}
|
|
93
|
+
function renderFailedError(cause) {
|
|
94
|
+
return new MediaFetchError("render_failed", "The media couldn't be rendered", void 0, { cause });
|
|
95
|
+
}
|
|
83
96
|
function tokenUnavailableError(cause) {
|
|
84
97
|
return new MediaFetchError("token_unavailable", "No viewer token: its issuance failed", void 0, { cause });
|
|
85
98
|
}
|
|
@@ -753,7 +766,9 @@ var ERROR_TEXT = {
|
|
|
753
766
|
unsupported_type: "This file type can't be previewed.",
|
|
754
767
|
type_mismatch: "The file's content doesn't match its type.",
|
|
755
768
|
token_unavailable: "Access to this file couldn't be granted. Try again.",
|
|
756
|
-
session_mismatch: "Your session changed. Reload the page."
|
|
769
|
+
session_mismatch: "Your session changed. Reload the page.",
|
|
770
|
+
page_cap: "Download the file to see every page.",
|
|
771
|
+
render_failed: "The file couldn't be displayed."
|
|
757
772
|
};
|
|
758
773
|
var defaultPreviewLabels = {
|
|
759
774
|
document: (title, pageCount) => `${title}, ${pageCount === 1 ? "1 page" : `${pageCount} pages`}`,
|
|
@@ -961,7 +976,7 @@ function PdfCanvasDocument(props) {
|
|
|
961
976
|
React9.useLayoutEffect(() => {
|
|
962
977
|
if (document2) setWidth(containerRef.current?.clientWidth ?? 0);
|
|
963
978
|
}, [document2]);
|
|
964
|
-
if (error) return /* @__PURE__ */ jsx6(Fragment2, { children: renderFallback(error) });
|
|
979
|
+
if (error) return /* @__PURE__ */ jsx6(Fragment2, { children: renderFallback(renderFailedError(error)) });
|
|
965
980
|
if (!document2) return /* @__PURE__ */ jsx6(Fragment2, { children: loading });
|
|
966
981
|
const shownPageCount = Math.min(document2.numPages, Math.max(1, maxPages));
|
|
967
982
|
const isTruncated = shownPageCount < document2.numPages;
|
|
@@ -987,7 +1002,7 @@ function PdfCanvasDocument(props) {
|
|
|
987
1002
|
isTruncated && /* @__PURE__ */ jsxs3("p", { children: [
|
|
988
1003
|
labels.pageCap(shownPageCount, document2.numPages),
|
|
989
1004
|
" ",
|
|
990
|
-
renderFallback(
|
|
1005
|
+
renderFallback(pageCapError(shownPageCount, document2.numPages))
|
|
991
1006
|
] })
|
|
992
1007
|
]
|
|
993
1008
|
}
|
|
@@ -1591,13 +1606,15 @@ import React17 from "react";
|
|
|
1591
1606
|
import { VideoPlayer } from "@devultur/react";
|
|
1592
1607
|
import { Fragment as Fragment6, jsx as jsx11 } from "react/jsx-runtime";
|
|
1593
1608
|
var UNAUTHORIZED = 401;
|
|
1609
|
+
var HLS_NETWORK_FAILURE = /Load(Error|TimeOut)$/;
|
|
1594
1610
|
function fetchErrorOf(error) {
|
|
1595
1611
|
if (error.status === UNAUTHORIZED && error.code === "session_mismatch") {
|
|
1596
1612
|
return new MediaFetchError("session_mismatch", "The delivery refused this session's token", UNAUTHORIZED);
|
|
1597
1613
|
}
|
|
1598
1614
|
if (error.status === UNAUTHORIZED) return tokenUnavailableError();
|
|
1599
1615
|
if (error.status) return new MediaFetchError("http_error", `Video fetch failed: ${error.status}`, error.status);
|
|
1600
|
-
return
|
|
1616
|
+
if (HLS_NETWORK_FAILURE.test(error.details)) return networkError(error);
|
|
1617
|
+
return renderFailedError(error);
|
|
1601
1618
|
}
|
|
1602
1619
|
function VideoPreview({ media, renderFallback, className }) {
|
|
1603
1620
|
const { tokenStatus, tokenError, reissueToken } = useDevultur();
|
|
@@ -1633,7 +1650,7 @@ function Preview({ media, contentType, fallback, loading, labels, ...viewProps }
|
|
|
1633
1650
|
const text = usePreviewLabels(labels);
|
|
1634
1651
|
if (!media) return null;
|
|
1635
1652
|
const renderFallback = (error) => {
|
|
1636
|
-
const fetchError = error instanceof MediaFetchError ? error :
|
|
1653
|
+
const fetchError = error instanceof MediaFetchError ? error : networkError(error);
|
|
1637
1654
|
if (typeof fallback === "function") return fallback(fetchError);
|
|
1638
1655
|
if (fallback !== void 0) return fallback;
|
|
1639
1656
|
return /* @__PURE__ */ jsx12(DefaultFallback, { media, error: fetchError, labels: text });
|
|
@@ -1660,7 +1677,7 @@ function Preview({ media, contentType, fallback, loading, labels, ...viewProps }
|
|
|
1660
1677
|
}
|
|
1661
1678
|
var unsupportedType = (contentType) => new MediaFetchError("unsupported_type", `Can't preview ${contentType ?? "an unknown type"} inline`);
|
|
1662
1679
|
function DefaultFallback({ media, error, labels }) {
|
|
1663
|
-
return /* @__PURE__ */ jsx12(DownloadLink, { media, title:
|
|
1680
|
+
return /* @__PURE__ */ jsx12(DownloadLink, { media, title: labels.error(error.code), children: media.filename ?? labels.download });
|
|
1664
1681
|
}
|
|
1665
1682
|
function LoadingStatus({ text }) {
|
|
1666
1683
|
return /* @__PURE__ */ jsx12("span", { role: "status", style: VISUALLY_HIDDEN, children: text });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devultur/convex",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.2",
|
|
4
4
|
"description": "Convex component for Devultur media: media records, uploads, transcodes, watch progress and React bindings",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"convex",
|
|
@@ -49,6 +49,10 @@
|
|
|
49
49
|
"./locales/es": {
|
|
50
50
|
"import": "./dist/locales/es.js",
|
|
51
51
|
"types": "./dist/locales/es.d.ts"
|
|
52
|
+
},
|
|
53
|
+
"./locales/es-formal": {
|
|
54
|
+
"import": "./dist/locales/es-formal.js",
|
|
55
|
+
"types": "./dist/locales/es-formal.d.ts"
|
|
52
56
|
}
|
|
53
57
|
},
|
|
54
58
|
"bin": {
|
|
@@ -59,8 +63,8 @@
|
|
|
59
63
|
"dist"
|
|
60
64
|
],
|
|
61
65
|
"dependencies": {
|
|
62
|
-
"@devultur/core": "1.4.
|
|
63
|
-
"@devultur/react": "1.4.
|
|
66
|
+
"@devultur/core": "1.4.2",
|
|
67
|
+
"@devultur/react": "1.4.2"
|
|
64
68
|
},
|
|
65
69
|
"peerDependencies": {
|
|
66
70
|
"convex": ">=1.25.0",
|
|
@@ -92,7 +96,7 @@
|
|
|
92
96
|
"access": "public"
|
|
93
97
|
},
|
|
94
98
|
"scripts": {
|
|
95
|
-
"build": "tsup src/index.ts src/validators.ts src/react.tsx src/pdfjs.ts src/locales/es.ts src/bin/init.ts --format esm --dts && tsc -p src/component/tsconfig.json",
|
|
99
|
+
"build": "tsup src/index.ts src/validators.ts src/react.tsx src/pdfjs.ts src/locales/es.ts src/locales/es-formal.ts src/bin/init.ts --format esm --dts && tsc -p src/component/tsconfig.json",
|
|
96
100
|
"codegen": "node scripts/codegen.ts",
|
|
97
101
|
"dev": "tsup src/index.ts src/react.tsx --format esm --dts --watch",
|
|
98
102
|
"typecheck": "tsc --noEmit"
|