@devultur/convex 1.0.2 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +151 -5
  2. package/dist/bin/init.js +9 -2
  3. package/dist/{chunk-FHWT3GD6.js → chunk-GKLFRSGI.js} +2 -0
  4. package/dist/component/_generated/api.d.ts +12 -0
  5. package/dist/component/_generated/api.d.ts.map +1 -1
  6. package/dist/component/_generated/api.js.map +1 -1
  7. package/dist/component/_generated/component.d.ts +55 -1
  8. package/dist/component/_generated/component.d.ts.map +1 -1
  9. package/dist/component/_generated/server.d.ts +1 -1
  10. package/dist/component/_generated/server.d.ts.map +1 -1
  11. package/dist/component/lock.d.ts +33 -0
  12. package/dist/component/lock.d.ts.map +1 -0
  13. package/dist/component/lock.js +47 -0
  14. package/dist/component/lock.js.map +1 -0
  15. package/dist/component/lockValidators.d.ts +25 -0
  16. package/dist/component/lockValidators.d.ts.map +1 -0
  17. package/dist/component/lockValidators.js +14 -0
  18. package/dist/component/lockValidators.js.map +1 -0
  19. package/dist/component/mediaClient.d.ts +3 -0
  20. package/dist/component/mediaClient.d.ts.map +1 -0
  21. package/dist/component/mediaClient.js +7 -0
  22. package/dist/component/mediaClient.js.map +1 -0
  23. package/dist/component/public.d.ts +78 -0
  24. package/dist/component/public.d.ts.map +1 -1
  25. package/dist/component/public.js +83 -19
  26. package/dist/component/public.js.map +1 -1
  27. package/dist/component/schema.d.ts +12 -1
  28. package/dist/component/schema.d.ts.map +1 -1
  29. package/dist/component/schema.js +13 -1
  30. package/dist/component/schema.js.map +1 -1
  31. package/dist/component/uploadKeys.d.ts +14 -0
  32. package/dist/component/uploadKeys.d.ts.map +1 -0
  33. package/dist/component/uploadKeys.js +23 -0
  34. package/dist/component/uploadKeys.js.map +1 -0
  35. package/dist/component/uploads.d.ts +119 -0
  36. package/dist/component/uploads.d.ts.map +1 -0
  37. package/dist/component/uploads.js +106 -0
  38. package/dist/component/uploads.js.map +1 -0
  39. package/dist/component/workerErrors.d.ts +17 -0
  40. package/dist/component/workerErrors.d.ts.map +1 -0
  41. package/dist/component/workerErrors.js +41 -0
  42. package/dist/component/workerErrors.js.map +1 -0
  43. package/dist/index.d.ts +147 -6
  44. package/dist/index.js +102 -4
  45. package/dist/react.d.ts +18 -5
  46. package/dist/react.js +35 -13
  47. package/dist/validators.d.ts +5 -3
  48. package/dist/validators.js +1 -1
  49. package/package.json +8 -3
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # @devultur/convex
2
2
 
3
3
  [Convex](https://convex.dev) component for Devultur media: stores media records and watch progress in isolated
4
- tables, exposes upload, token, transcode and delete functions for your app, registers the transcode webhook, and
4
+ tables, exposes upload, token, transcode and delete functions for your app, serves the transcode webhook route, and
5
5
  ships typed validators and React bindings.
6
6
 
7
7
  ## Install
@@ -11,8 +11,26 @@ pnpm add @devultur/convex
11
11
  pnpm exec devultur-init
12
12
  ```
13
13
 
14
- `devultur-init` adds the component to `convex/convex.config.ts`, creates `convex/devultur.ts` with the exposed
15
- functions, and prints the Convex env vars to set (your media Worker's URL and credential).
14
+ `devultur-init` adds the component to `convex/convex.config.ts` (mounted with `httpPrefix: "/devultur/"`, see
15
+ [Webhook route](#webhook-route)), creates `convex/devultur.ts` with the exposed functions, and prints the Convex env
16
+ vars to set (your media Worker's URL and credential).
17
+
18
+ ## Webhook route
19
+
20
+ The component receives transcode and captions events on its own HTTP route, `POST /webhook`. Convex serves a
21
+ component's HTTP routes only when the app mounts the component with an `httpPrefix`:
22
+
23
+ ```typescript
24
+ // convex/convex.config.ts
25
+ app.use(devultur, { httpPrefix: "/devultur/", env: { /* see below */ } });
26
+ ```
27
+
28
+ With that prefix the route is `https://<deployment>.convex.site/devultur/webhook`. You don't need an `http.ts` entry
29
+ for it. `processVideo` sends the Worker that URL as the `callbackUrl`, and it follows the prefix you choose (with
30
+ `httpPrefix: "/media/"` it is `https://<deployment>.convex.site/media/webhook`).
31
+
32
+ Without `httpPrefix` the route doesn't exist: the Worker's events get `404`, the media record never leaves
33
+ `queued`, and every transcode fails with a timeout.
16
34
 
17
35
  ## Example
18
36
 
@@ -49,6 +67,94 @@ function CoverUpload({ onSaved }) {
49
67
  }
50
68
  ```
51
69
 
70
+ ## Upload progress
71
+
72
+ `upload(file, { onProgress, signal })` reports the PUT's progress and resolves to the stored reference:
73
+
74
+ ```tsx
75
+ const { upload } = useDevultur();
76
+
77
+ const media = await upload(file, {
78
+ onProgress: ({ loadedBytes, totalBytes, fraction }) => setPercent(Math.round(fraction * 100)),
79
+ signal: controller.signal, // aborts the PUT; upload() rejects with an AbortError
80
+ });
81
+ media.key; // the uploaded object's key ("private/image/<id>/<name>"; a video's raw file)
82
+ await saveCover({ cover: media }); // a DevulturMedia: stores as-is in a dv.media() field, key included
83
+ ```
84
+
85
+ The PUT goes through `XMLHttpRequest` (`fetch` reports no upload progress), in parts for large files. `key` is an
86
+ optional field of `DevulturMedia` and of `dv.media()` (since 1.1.0), so references stored without it stay valid. It
87
+ is informational: delivery URLs are still derived from `id`, `kind`, `visibility` and `filename`.
88
+
89
+ ## Media library
90
+
91
+ Every upload, whatever its kind, gets a record in the component's `media` table once its bytes are stored, so
92
+ `listMedia` lists your images, files and videos:
93
+
94
+ ```typescript
95
+ // convex/library.ts
96
+ import { Devultur, mediaFromRecord } from "@devultur/convex";
97
+ import { query } from "./_generated/server";
98
+ import { components } from "./_generated/api";
99
+
100
+ const devultur = new Devultur(components.devultur);
101
+
102
+ export const images = query({
103
+ args: {},
104
+ handler: async (ctx) => {
105
+ // Check who's asking first: listMedia returns every record, of every user.
106
+ const records = await devultur.listMedia(ctx, { type: "image" }); // or "video" | "file", or no filter
107
+ return records.map((record) => ({ record, media: mediaFromRecord(record) }));
108
+ },
109
+ });
110
+ ```
111
+
112
+ `listMedia` reads every record at once: fine for a handful, unbounded for a library. Page a library with
113
+ `listMediaPage`, newest first, on a `by_type` index:
114
+
115
+ ```typescript
116
+ import { paginationOptsValidator } from "convex/server";
117
+ import { v } from "convex/values";
118
+
119
+ export const imagesPage = query({
120
+ args: { paginationOpts: paginationOptsValidator },
121
+ handler: async (ctx, { paginationOpts }) => {
122
+ // Check who's asking first.
123
+ return devultur.listMediaPage(ctx, { type: "image", paginationOpts });
124
+ },
125
+ });
126
+ // React: usePaginatedQuery(api.library.imagesPage, {}, { initialNumItems: 24 })
127
+ ```
128
+
129
+ `Devultur.exposeApi` also returns a `listMediaPage` query (`{ type?, paginationOpts }`). It lists every user's media,
130
+ so export it only when every caller may see the whole library.
131
+
132
+ A record is written only after the Worker confirms the object exists, so an abandoned upload never shows up:
133
+
134
+ 1. After its PUT, the client calls `confirmUpload({ key, filename, width, height })`. The component asks the Worker
135
+ for the object (a `HEAD`) and records its size and content type. `useDevultur().upload()` and `useMediaUpload` do
136
+ this for you when the `api` you pass `<DevulturProvider>` has `confirmUpload` (add it to the functions you export
137
+ from `Devultur.exposeApi` in `convex/devultur.ts`). From your server: `devultur.confirmUpload(ctx, { key })`.
138
+ 2. `createUploadUrl` also schedules the same check for 25 hours later, past the longest an upload can take. An upload
139
+ whose client never confirmed is recorded then; one that was never stored, or was deleted, isn't.
140
+
141
+ A record's `key` is the media id for every kind (what `getMedia` takes), and `objectKey` is the uploaded object's key.
142
+ `confirmUpload` only accepts upload keys (`{visibility}/{image|file}/{id}/{name}`, `{visibility}/video/{id}/raw/{name}`)
143
+ and is idempotent: a video's transcode state stays as it is.
144
+
145
+ `confirmUpload`, like every function `exposeApi` returns (and the `devultur-init` template exports), has no auth of
146
+ its own: anyone who can call your Convex deployment can call it. Wrap it with your app's auth, as you would the other
147
+ exposed functions: export your own action that checks `ctx.auth` and then calls `devultur.confirmUpload(ctx, { key })`.
148
+ The caller only names the key: the record's visibility, size and content type come from the Worker's `HEAD` of the
149
+ object, never from the arguments.
150
+
151
+ `deleteMedia` removes an image's or a file's record once
152
+ the Worker deleted the object (a delete refused by a lock keeps it). `deleteVideo` removes a video's.
153
+
154
+ Records from before 1.1.0 (and a video only `processVideo` recorded) have no `visibility` or `objectKey`;
155
+ `mediaFromRecord` returns `null` for them. Nothing needs migrating: the new fields are optional. `listMedia` doesn't
156
+ report an object's lock: read it from an action with `devultur.getLock(ctx, record.objectKey)`.
157
+
52
158
  ## Using a self-hosted Worker
53
159
 
54
160
  The component talks to any Worker built with `createWorker()` from
@@ -83,8 +189,10 @@ npx convex env set DEVULTUR_API_URL https://media.example.com
83
189
  npx convex env set DEVULTUR_SECRET <the Worker's WORKER_AUTH_SECRET>
84
190
  ```
85
191
 
86
- **Webhooks.** You don't configure anything else. `processVideo` sends the Worker a `callbackUrl` that points at
87
- the component's route, `<CONVEX_SITE_URL>/devultur/webhook`. The transcode runner reports to the Worker with
192
+ **Webhooks.** Keep the `httpPrefix` in `app.use()`: without it Convex doesn't serve the component's route and every
193
+ transcode times out (see [Webhook route](#webhook-route)). Nothing else needs configuring. `processVideo` sends the
194
+ Worker a `callbackUrl` that points at the component's route, `https://<deployment>.convex.site/devultur/webhook`
195
+ (your app's `CONVEX_SITE_URL` followed by the prefix and `webhook`). The transcode runner reports to the Worker with
88
196
  `TRANSCODE_WEBHOOK_SECRET`. The Worker then forwards each event to the `callbackUrl` with
89
197
  `Authorization: Bearer <WORKER_AUTH_SECRET>`. The component accepts an event only when that bearer equals
90
198
  `DEVULTUR_SECRET`. If `DEVULTUR_SECRET` is wrong or missing, the component answers `401` to every event. Keep
@@ -95,6 +203,44 @@ webhooks with the `webhookCredential` your plugin sets in the request state (or
95
203
  none; see [Plugins](https://github.com/devultur/devultur/blob/main/docs/guides/plugins.md)). Set `DEVULTUR_SECRET`
96
204
  to that value, and make sure your plugin also accepts it as the bearer of the component's calls.
97
205
 
206
+ ## Errors
207
+
208
+ When the media Worker refuses a request, component actions throw a `ConvexError` whose `data` is
209
+ `{ code, message, status, details? }`. A plain `Error` would lose these fields across the component boundary. `code` is
210
+ the Worker's stable code: for example `retention_active`, `compliance_extend_only`, `lock_conflict`,
211
+ `lock_privilege_required`, `file_too_large`, or `worker_error` when the Worker sent none. `details` carries the rest of
212
+ the Worker's answer, such as the `{ key, mode, until, hold }` of a `retention_active`.
213
+
214
+ ```ts
215
+ import { devulturErrorOf } from "@devultur/convex";
216
+
217
+ try {
218
+ await devultur.setLock(ctx, key, { until });
219
+ } catch (error) {
220
+ const refusal = devulturErrorOf(error); // null when it isn't a Worker refusal
221
+ if (refusal?.code === "compliance_extend_only") {
222
+ // the date can only move later
223
+ }
224
+ throw error;
225
+ }
226
+ ```
227
+
228
+ `isDevulturError(error)` is the matching type guard. Errors that aren't Worker refusals, such as a network failure,
229
+ are rethrown unchanged.
230
+
231
+ ## Object lock
232
+
233
+ - `devultur.createUploadUrl(ctx, { filename, contentType, lock, hold })` locks a file from its first write.
234
+ - `devultur.getLock(ctx, key)` and `devultur.setLock(ctx, key, { mode, until, period, derivatives })` read and change
235
+ a file's retention.
236
+ - `devultur.setHold(ctx, keys)` and `devultur.releaseHold(ctx, keys)` set and release holds.
237
+
238
+ These are server-side calls: `exposeApi` never lets a browser choose or change a lock. Its `createUploadUrl` applies
239
+ `config.upload.lock` instead. A bulk hold by prefix runs on your server with `@devultur/core`'s
240
+ `createWorkerClient(...).lock.holdAll({ prefix })`. The
241
+ [Retention and holds](https://github.com/devultur/devultur/blob/main/docs/guides/object-lock.md) guide covers the model,
242
+ what's enforced and the caveats.
243
+
98
244
  ## Documentation
99
245
 
100
246
  Guides and API reference: [github.com/devultur/devultur/tree/main/docs](https://github.com/devultur/devultur/tree/main/docs).
package/dist/bin/init.js CHANGED
@@ -37,6 +37,10 @@ export default app;
37
37
  let content = readFileSync(configPath, "utf-8");
38
38
  if (content.includes("@devultur/convex")) {
39
39
  log("\u23ED\uFE0F convex.config.ts already has devultur \u2014 skipping");
40
+ if (!content.includes("httpPrefix")) {
41
+ log("\u26A0\uFE0F Mount it with an httpPrefix, or Convex doesn't serve its webhook route and every transcode times out:");
42
+ log(' app.use(devultur, { httpPrefix: "/devultur/", env: { ... } })');
43
+ }
40
44
  return;
41
45
  }
42
46
  if (!content.includes("defineApp")) {
@@ -72,6 +76,7 @@ import { components } from "./_generated/api";
72
76
  export const {
73
77
  issueViewerToken,
74
78
  createUploadUrl,
79
+ confirmUpload,
75
80
  deleteMedia,
76
81
  deleteVideo,
77
82
  processVideo,
@@ -112,6 +117,8 @@ console.log(`
112
117
  <App />
113
118
  </DevulturProvider>
114
119
 
115
- Webhook route is automatically registered at /devultur/webhook
116
- (no changes needed in your http.ts)
120
+ Transcode webhooks: Convex serves the component's webhook route only because
121
+ convex.config.ts mounts it with httpPrefix "/devultur/". The route is
122
+ POST https://<deployment>.convex.site/devultur/webhook
123
+ and processVideo sends it to the Worker as the callbackUrl (no changes needed in your http.ts).
117
124
  `);
@@ -4,6 +4,8 @@ var mediaFields = {
4
4
  id: v.string(),
5
5
  visibility: v.union(v.literal("public"), v.literal("private")),
6
6
  filename: v.optional(v.string()),
7
+ // The uploaded object's key, as `upload()` returns it. Optional: references stored before it stay valid.
8
+ key: v.optional(v.string()),
7
9
  width: v.optional(v.number()),
8
10
  height: v.optional(v.number())
9
11
  };
@@ -7,11 +7,23 @@
7
7
  * @module
8
8
  */
9
9
  import type * as http from "../http.js";
10
+ import type * as lock from "../lock.js";
11
+ import type * as lockValidators from "../lockValidators.js";
12
+ import type * as mediaClient from "../mediaClient.js";
10
13
  import type * as public_ from "../public.js";
14
+ import type * as uploadKeys from "../uploadKeys.js";
15
+ import type * as uploads from "../uploads.js";
16
+ import type * as workerErrors from "../workerErrors.js";
11
17
  import type { ApiFromModules, FilterApi, FunctionReference } from "convex/server";
12
18
  declare const fullApi: ApiFromModules<{
13
19
  http: typeof http;
20
+ lock: typeof lock;
21
+ lockValidators: typeof lockValidators;
22
+ mediaClient: typeof mediaClient;
14
23
  public: typeof public_;
24
+ uploadKeys: typeof uploadKeys;
25
+ uploads: typeof uploads;
26
+ workerErrors: typeof workerErrors;
15
27
  }>;
16
28
  /**
17
29
  * A utility for referencing Convex functions in your app's public API.
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/component/_generated/api.ts"],"names":[],"mappings":"AACA;;;;;;;GAOG;AAEH,OAAO,KAAK,KAAK,IAAI,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,KAAK,OAAO,MAAM,cAAc,CAAC;AAE7C,OAAO,KAAK,EACV,cAAc,EACd,SAAS,EACT,iBAAiB,EAClB,MAAM,eAAe,CAAC;AAGvB,QAAA,MAAM,OAAO,EAAE,cAAc,CAAC;IAC5B,IAAI,EAAE,OAAO,IAAI,CAAC;IAClB,MAAM,EAAE,OAAO,OAAO,CAAC;CACxB,CAAiB,CAAC;AAEnB;;;;;;;GAOG;AACH,eAAO,MAAM,GAAG,EAAE,SAAS,CACzB,OAAO,OAAO,EACd,iBAAiB,CAAC,GAAG,EAAE,QAAQ,CAAC,CACjB,CAAC;AAElB;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,EAAE,SAAS,CAC9B,OAAO,OAAO,EACd,iBAAiB,CAAC,GAAG,EAAE,UAAU,CAAC,CACnB,CAAC;AAElB,eAAO,MAAM,UAAU,EAAqC,EAAE,CAAC"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/component/_generated/api.ts"],"names":[],"mappings":"AACA;;;;;;;GAOG;AAEH,OAAO,KAAK,KAAK,IAAI,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,KAAK,IAAI,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,KAAK,cAAc,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,KAAK,WAAW,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,KAAK,OAAO,MAAM,cAAc,CAAC;AAC7C,OAAO,KAAK,KAAK,UAAU,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,KAAK,OAAO,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,KAAK,YAAY,MAAM,oBAAoB,CAAC;AAExD,OAAO,KAAK,EACV,cAAc,EACd,SAAS,EACT,iBAAiB,EAClB,MAAM,eAAe,CAAC;AAGvB,QAAA,MAAM,OAAO,EAAE,cAAc,CAAC;IAC5B,IAAI,EAAE,OAAO,IAAI,CAAC;IAClB,IAAI,EAAE,OAAO,IAAI,CAAC;IAClB,cAAc,EAAE,OAAO,cAAc,CAAC;IACtC,WAAW,EAAE,OAAO,WAAW,CAAC;IAChC,MAAM,EAAE,OAAO,OAAO,CAAC;IACvB,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,OAAO,EAAE,OAAO,OAAO,CAAC;IACxB,YAAY,EAAE,OAAO,YAAY,CAAC;CACnC,CAAiB,CAAC;AAEnB;;;;;;;GAOG;AACH,eAAO,MAAM,GAAG,EAAE,SAAS,CACzB,OAAO,OAAO,EACd,iBAAiB,CAAC,GAAG,EAAE,QAAQ,CAAC,CACjB,CAAC;AAElB;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,EAAE,SAAS,CAC9B,OAAO,OAAO,EACd,iBAAiB,CAAC,GAAG,EAAE,UAAU,CAAC,CACnB,CAAC;AAElB,eAAO,MAAM,UAAU,EAAqC,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/component/_generated/api.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB;;;;;;;GAOG;AAUH,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE1D,MAAM,OAAO,GAGR,MAAa,CAAC;AAEnB;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,GAAG,GAGZ,MAAa,CAAC;AAElB;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAGjB,MAAa,CAAC;AAElB,MAAM,CAAC,MAAM,UAAU,GAAG,iBAAiB,EAAmB,CAAC"}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/component/_generated/api.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB;;;;;;;GAOG;AAgBH,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE1D,MAAM,OAAO,GASR,MAAa,CAAC;AAEnB;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,GAAG,GAGZ,MAAa,CAAC;AAElB;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAGjB,MAAa,CAAC;AAElB,MAAM,CAAC,MAAM,UAAU,GAAG,iBAAiB,EAAmB,CAAC"}
@@ -19,6 +19,26 @@ import type { FunctionReference } from "convex/server";
19
19
  * ```
20
20
  */
21
21
  export type ComponentApi<Name extends string | undefined = string | undefined> = {
22
+ lock: {
23
+ getLock: FunctionReference<"action", "internal", {
24
+ key: string;
25
+ }, any, Name>;
26
+ releaseHold: FunctionReference<"action", "internal", {
27
+ keys: Array<string>;
28
+ }, any, Name>;
29
+ setHold: FunctionReference<"action", "internal", {
30
+ keys: Array<string>;
31
+ }, any, Name>;
32
+ setLock: FunctionReference<"action", "internal", {
33
+ bypassGovernance?: boolean;
34
+ derivatives?: "inherit" | "original-only";
35
+ key: string;
36
+ mode?: "governance" | "compliance";
37
+ period?: number;
38
+ remove?: true;
39
+ until?: string;
40
+ }, any, Name>;
41
+ };
22
42
  public: {
23
43
  createMedia: FunctionReference<"mutation", "internal", {
24
44
  contentType: string;
@@ -30,12 +50,24 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
30
50
  createUploadUrl: FunctionReference<"action", "internal", {
31
51
  contentType: string;
32
52
  filename: string;
53
+ hold?: boolean;
54
+ lock?: {
55
+ hold?: boolean;
56
+ retention?: {
57
+ derivatives?: "inherit" | "original-only";
58
+ mode: "governance" | "compliance";
59
+ period?: number;
60
+ until?: string;
61
+ };
62
+ };
63
+ visibility?: "public" | "private";
33
64
  }, any, Name>;
34
65
  deleteMediaAction: FunctionReference<"action", "internal", {
35
66
  key: string;
36
67
  }, any, Name>;
37
68
  deleteVideo: FunctionReference<"action", "internal", {
38
69
  videoId: string;
70
+ visibility?: "public" | "private";
39
71
  }, any, Name>;
40
72
  getCourseProgress: FunctionReference<"query", "internal", {
41
73
  userId: string;
@@ -53,6 +85,17 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
53
85
  listMedia: FunctionReference<"query", "internal", {
54
86
  type?: "video" | "image" | "file";
55
87
  }, any, Name>;
88
+ listMediaPage: FunctionReference<"query", "internal", {
89
+ paginationOpts: {
90
+ cursor: string | null;
91
+ endCursor?: string | null;
92
+ id?: number;
93
+ maximumBytesRead?: number;
94
+ maximumRowsRead?: number;
95
+ numItems: number;
96
+ };
97
+ type?: "video" | "image" | "file";
98
+ }, any, Name>;
56
99
  loadProgress: FunctionReference<"query", "internal", {
57
100
  userId: string;
58
101
  videoId: string;
@@ -78,16 +121,19 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
78
121
  }, any, Name>;
79
122
  updateMedia: FunctionReference<"mutation", "internal", {
80
123
  captionLocales?: Array<string>;
124
+ captionsPending?: boolean;
81
125
  duration?: number;
126
+ failureReason?: "invalid_input" | "unsupported_codec" | "timeout" | "capacity" | "internal";
82
127
  key: string;
83
128
  playlistUrl?: string;
129
+ retriable?: boolean;
84
130
  thumbnailKey?: string;
85
131
  transcodeError?: string;
86
132
  transcodeProgress?: {
87
133
  current: number;
88
134
  total: number;
89
135
  };
90
- transcodeStatus?: "transcoding" | "captioning" | "ready" | "failed";
136
+ transcodeStatus?: "queued" | "transcoding" | "captioning" | "ready" | "failed";
91
137
  }, any, Name>;
92
138
  upsertCaption: FunctionReference<"mutation", "internal", {
93
139
  locale: string;
@@ -96,5 +142,13 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
96
142
  vttUrl: string;
97
143
  }, any, Name>;
98
144
  };
145
+ uploads: {
146
+ confirmUpload: FunctionReference<"action", "internal", {
147
+ filename?: string;
148
+ height?: number;
149
+ key: string;
150
+ width?: number;
151
+ }, any, Name>;
152
+ };
99
153
  };
100
154
  //# sourceMappingURL=component.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../../src/component/_generated/component.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../../src/component/_generated/component.ts"],"names":[],"mappings":"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"}
@@ -12,8 +12,8 @@ import type { DataModel } from "./dataModel.js";
12
12
  * Typesafe environment variables declared in `convex.config.ts`.
13
13
  */
14
14
  type Env = {
15
- readonly DEVULTUR_SECRET: string;
16
15
  readonly DEVULTUR_API_URL: string;
16
+ readonly DEVULTUR_SECRET: string;
17
17
  };
18
18
  /**
19
19
  * Define a query in this Convex app's public API.
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/component/_generated/server.ts"],"names":[],"mappings":"AACA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,qBAAqB,EACtB,MAAM,eAAe,CAAC;AAUvB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD;;GAEG;AACH,KAAK,GAAG,GAAG;IACT,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;CACnC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,KAAK,EAAE,YAAY,CAAC,SAAS,EAAE,QAAQ,CAAgB,CAAC;AAErE;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,EAAE,YAAY,CAAC,SAAS,EAAE,UAAU,CACxC,CAAC;AAEvB;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,EAAE,eAAe,CAAC,SAAS,EAAE,QAAQ,CAAmB,CAAC;AAE9E;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,EAAE,eAAe,CAAC,SAAS,EAAE,UAAU,CAC3C,CAAC;AAE1B;;;;;;;;;;GAUG;AACH,eAAO,MAAM,MAAM,EAAE,aAAa,CAAC,SAAS,EAAE,QAAQ,CAAiB,CAAC;AAExE;;;;;GAKG;AACH,eAAO,MAAM,cAAc,EAAE,aAAa,CAAC,SAAS,EAAE,UAAU,CACzC,CAAC;AAExB;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,EAAE,iBAAqC,CAAC;AAC/D,eAAO,MAAM,GAAG,EAAE,GAAmC,CAAC;AAEtD;;;;;;;GAOG;AACH,MAAM,MAAM,QAAQ,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;AAElD;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;AAExD;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;AAEpD;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,qBAAqB,CAAC,SAAS,CAAC,CAAC;AAE9D;;;;;;;;GAQG;AACH,MAAM,MAAM,cAAc,GAAG,qBAAqB,CAAC,SAAS,CAAC,CAAC"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/component/_generated/server.ts"],"names":[],"mappings":"AACA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,qBAAqB,EACtB,MAAM,eAAe,CAAC;AAUvB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD;;GAEG;AACH,KAAK,GAAG,GAAG;IACT,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,KAAK,EAAE,YAAY,CAAC,SAAS,EAAE,QAAQ,CAAgB,CAAC;AAErE;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,EAAE,YAAY,CAAC,SAAS,EAAE,UAAU,CACxC,CAAC;AAEvB;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,EAAE,eAAe,CAAC,SAAS,EAAE,QAAQ,CAAmB,CAAC;AAE9E;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,EAAE,eAAe,CAAC,SAAS,EAAE,UAAU,CAC3C,CAAC;AAE1B;;;;;;;;;;GAUG;AACH,eAAO,MAAM,MAAM,EAAE,aAAa,CAAC,SAAS,EAAE,QAAQ,CAAiB,CAAC;AAExE;;;;;GAKG;AACH,eAAO,MAAM,cAAc,EAAE,aAAa,CAAC,SAAS,EAAE,UAAU,CACzC,CAAC;AAExB;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,EAAE,iBAAqC,CAAC;AAC/D,eAAO,MAAM,GAAG,EAAE,GAAmC,CAAC;AAEtD;;;;;;;GAOG;AACH,MAAM,MAAM,QAAQ,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;AAElD;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;AAExD;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;AAEpD;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,qBAAqB,CAAC,SAAS,CAAC,CAAC;AAE9D;;;;;;;;GAQG;AACH,MAAM,MAAM,cAAc,GAAG,qBAAqB,CAAC,SAAS,CAAC,CAAC"}
@@ -0,0 +1,33 @@
1
+ export declare const getLock: import("convex/server").RegisteredAction<"public", {
2
+ key: string;
3
+ }, Promise<import("@devultur/core").LockView>>;
4
+ export declare const setLock: import("convex/server").RegisteredAction<"public", {
5
+ mode?: "governance" | "compliance" | undefined;
6
+ until?: string | undefined;
7
+ period?: number | undefined;
8
+ derivatives?: "inherit" | "original-only" | undefined;
9
+ remove?: true | undefined;
10
+ bypassGovernance?: boolean | undefined;
11
+ key: string;
12
+ }, Promise<import("@devultur/core").LockView>>;
13
+ export declare const setHold: import("convex/server").RegisteredAction<"public", {
14
+ keys: string[];
15
+ }, Promise<{
16
+ updated: string[];
17
+ skipped: {
18
+ key: string;
19
+ reason: string;
20
+ }[];
21
+ pageSize: number;
22
+ }>>;
23
+ export declare const releaseHold: import("convex/server").RegisteredAction<"public", {
24
+ keys: string[];
25
+ }, Promise<{
26
+ updated: string[];
27
+ skipped: {
28
+ key: string;
29
+ reason: string;
30
+ }[];
31
+ pageSize: number;
32
+ }>>;
33
+ //# sourceMappingURL=lock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.d.ts","sourceRoot":"","sources":["../../src/component/lock.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,OAAO;;8CAGlB,CAAC;AAEH,eAAO,MAAM,OAAO;;;;;;;;8CAWlB,CAAC;AAcH,eAAO,MAAM,OAAO;;;;;aARG,MAAM;gBAAU,MAAM;;;GAW3C,CAAC;AAEH,eAAO,MAAM,WAAW;;;;;aAbD,MAAM;gBAAU,MAAM;;;GAgB3C,CAAC"}
@@ -0,0 +1,47 @@
1
+ // Object lock from the app's server: read and change an object's retention, and set or release holds on a list of
2
+ // keys. These are component functions, so only the app's own functions can call them (never a browser). A bulk hold
3
+ // by prefix stays on the app's server, with `@devultur/core`'s `createWorkerClient(...).lock.holdAll({ prefix })`.
4
+ // A refusal throws a `ConvexError` whose `data.code` is the Worker's (`retention_active`, `compliance_extend_only`,
5
+ // `lock_privilege_required`, `lock_conflict`, ...); see workerErrors.ts.
6
+ import { HOLD_PAGE_SIZE } from "@devultur/core";
7
+ import { v } from "convex/values";
8
+ import { derivativesValidator, retentionModeValidator } from "./lockValidators";
9
+ import { getMediaClient } from "./mediaClient";
10
+ import { workerAction } from "./workerErrors";
11
+ const keysValidator = v.array(v.string());
12
+ export const getLock = workerAction({
13
+ args: { key: v.string() },
14
+ handler: async (_ctx, args) => getMediaClient().lock.get(args.key),
15
+ });
16
+ export const setLock = workerAction({
17
+ args: {
18
+ key: v.string(),
19
+ mode: v.optional(retentionModeValidator),
20
+ until: v.optional(v.string()),
21
+ period: v.optional(v.number()),
22
+ derivatives: v.optional(derivativesValidator),
23
+ remove: v.optional(v.literal(true)),
24
+ bypassGovernance: v.optional(v.boolean()),
25
+ },
26
+ handler: async (_ctx, { key, ...options }) => getMediaClient().lock.set(key, options),
27
+ });
28
+ /** Holds every key, a page of {@link HOLD_PAGE_SIZE} at a time; returns what changed and what didn't. */
29
+ async function changeHolds(keys, hold) {
30
+ const lock = getMediaClient().lock;
31
+ const updated = [];
32
+ const skipped = [];
33
+ for await (const page of hold ? lock.holdAll(keys) : lock.releaseAll(keys)) {
34
+ updated.push(...page.updated);
35
+ skipped.push(...page.skipped);
36
+ }
37
+ return { updated, skipped, pageSize: HOLD_PAGE_SIZE };
38
+ }
39
+ export const setHold = workerAction({
40
+ args: { keys: keysValidator },
41
+ handler: async (_ctx, args) => changeHolds(args.keys, true),
42
+ });
43
+ export const releaseHold = workerAction({
44
+ args: { keys: keysValidator },
45
+ handler: async (_ctx, args) => changeHolds(args.keys, false),
46
+ });
47
+ //# sourceMappingURL=lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.js","sourceRoot":"","sources":["../../src/component/lock.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ export declare const retentionModeValidator: import("convex/values").VUnion<"governance" | "compliance", [import("convex/values").VLiteral<"governance", "required">, import("convex/values").VLiteral<"compliance", "required">], "required", never>;
2
+ export declare const derivativesValidator: import("convex/values").VUnion<"inherit" | "original-only", [import("convex/values").VLiteral<"inherit", "required">, import("convex/values").VLiteral<"original-only", "required">], "required", never>;
3
+ export declare const objectLockValidator: import("convex/values").VObject<{
4
+ retention?: {
5
+ until?: string | undefined;
6
+ period?: number | undefined;
7
+ derivatives?: "inherit" | "original-only" | undefined;
8
+ mode: "governance" | "compliance";
9
+ } | undefined;
10
+ hold?: boolean | undefined;
11
+ }, {
12
+ retention: import("convex/values").VObject<{
13
+ until?: string | undefined;
14
+ period?: number | undefined;
15
+ derivatives?: "inherit" | "original-only" | undefined;
16
+ mode: "governance" | "compliance";
17
+ } | undefined, {
18
+ mode: import("convex/values").VUnion<"governance" | "compliance", [import("convex/values").VLiteral<"governance", "required">, import("convex/values").VLiteral<"compliance", "required">], "required", never>;
19
+ until: import("convex/values").VString<string | undefined, "optional">;
20
+ period: import("convex/values").VFloat64<number | undefined, "optional">;
21
+ derivatives: import("convex/values").VUnion<"inherit" | "original-only" | undefined, [import("convex/values").VLiteral<"inherit", "required">, import("convex/values").VLiteral<"original-only", "required">], "optional", never>;
22
+ }, "optional", "mode" | "until" | "period" | "derivatives">;
23
+ hold: import("convex/values").VBoolean<boolean | undefined, "optional">;
24
+ }, "required", "retention" | "hold" | "retention.mode" | "retention.until" | "retention.period" | "retention.derivatives">;
25
+ //# sourceMappingURL=lockValidators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lockValidators.d.ts","sourceRoot":"","sources":["../../src/component/lockValidators.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,sBAAsB,0MAA4D,CAAC;AAChG,eAAO,MAAM,oBAAoB,0MAA4D,CAAC;AAE9F,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;0HAU9B,CAAC"}
@@ -0,0 +1,14 @@
1
+ // Validators of the object lock arguments (the shapes of `@devultur/core`'s `ObjectLock` and `SetLockOptions`).
2
+ import { v } from "convex/values";
3
+ export const retentionModeValidator = v.union(v.literal("governance"), v.literal("compliance"));
4
+ export const derivativesValidator = v.union(v.literal("inherit"), v.literal("original-only"));
5
+ export const objectLockValidator = v.object({
6
+ retention: v.optional(v.object({
7
+ mode: retentionModeValidator,
8
+ until: v.optional(v.string()),
9
+ period: v.optional(v.number()),
10
+ derivatives: v.optional(derivativesValidator),
11
+ })),
12
+ hold: v.optional(v.boolean()),
13
+ });
14
+ //# sourceMappingURL=lockValidators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lockValidators.js","sourceRoot":"","sources":["../../src/component/lockValidators.ts"],"names":[],"mappings":"AAAA,gHAAgH;AAChH,OAAO,EAAE,CAAC,EAAE,MAAM,eAAe,CAAC;AAElC,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC;AAChG,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC;AAE9F,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,SAAS,EAAE,CAAC,CAAC,QAAQ,CACpB,CAAC,CAAC,MAAM,CAAC;QACR,IAAI,EAAE,sBAAsB;QAC5B,KAAK,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QAC7B,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QAC9B,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,oBAAoB,CAAC;KAC7C,CAAC,CACF;IACD,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;CAC7B,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type WorkerClient } from "@devultur/core";
2
+ export declare function getMediaClient(): WorkerClient;
3
+ //# sourceMappingURL=mediaClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mediaClient.d.ts","sourceRoot":"","sources":["../../src/component/mediaClient.ts"],"names":[],"mappings":"AACA,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAGvE,wBAAgB,cAAc,IAAI,YAAY,CAE7C"}
@@ -0,0 +1,7 @@
1
+ // The component's client of the media Worker, from the env the app mounts the component with.
2
+ import { createWorkerClient } from "@devultur/core";
3
+ import { env } from "./_generated/server";
4
+ export function getMediaClient() {
5
+ return createWorkerClient(env.DEVULTUR_SECRET, env.DEVULTUR_API_URL);
6
+ }
7
+ //# sourceMappingURL=mediaClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mediaClient.js","sourceRoot":"","sources":["../../src/component/mediaClient.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,OAAO,EAAE,kBAAkB,EAAqB,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAE1C,MAAM,UAAU,cAAc;IAC7B,OAAO,kBAAkB,CAAC,GAAG,CAAC,eAAe,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAC;AACtE,CAAC"}