@jsm-mit/sultana-assets-rust-package 0.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 (35) hide show
  1. package/README.md +86 -0
  2. package/declarations/sultana-assets-rust/sultana-assets-rust.did +98 -0
  3. package/declarations/sultana-assets-rust/sultana-assets-rust.did.d.ts +129 -0
  4. package/declarations/sultana-assets-rust/sultana-assets-rust.did.js +143 -0
  5. package/dist/actor-base.d.ts +46 -0
  6. package/dist/actor-base.d.ts.map +1 -0
  7. package/dist/actor-base.js +87 -0
  8. package/dist/actors/admin-actor.d.ts +72 -0
  9. package/dist/actors/admin-actor.d.ts.map +1 -0
  10. package/dist/actors/admin-actor.js +86 -0
  11. package/dist/actors/assets-actor.d.ts +38 -0
  12. package/dist/actors/assets-actor.d.ts.map +1 -0
  13. package/dist/actors/assets-actor.js +54 -0
  14. package/dist/actors/salon-actor.d.ts +64 -0
  15. package/dist/actors/salon-actor.d.ts.map +1 -0
  16. package/dist/actors/salon-actor.js +92 -0
  17. package/dist/actors/uploads-actor.d.ts +74 -0
  18. package/dist/actors/uploads-actor.d.ts.map +1 -0
  19. package/dist/actors/uploads-actor.js +97 -0
  20. package/dist/actors/worker-actor.d.ts +72 -0
  21. package/dist/actors/worker-actor.d.ts.map +1 -0
  22. package/dist/actors/worker-actor.js +86 -0
  23. package/dist/constants.d.ts +33 -0
  24. package/dist/constants.d.ts.map +1 -0
  25. package/dist/constants.js +45 -0
  26. package/dist/index.d.ts +11 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +8 -0
  29. package/dist/interfaces.d.ts +97 -0
  30. package/dist/interfaces.d.ts.map +1 -0
  31. package/dist/interfaces.js +1 -0
  32. package/dist/mappers.d.ts +11 -0
  33. package/dist/mappers.d.ts.map +1 -0
  34. package/dist/mappers.js +38 -0
  35. package/package.json +58 -0
@@ -0,0 +1,86 @@
1
+ import { Principal } from "@icp-sdk/core/principal";
2
+ import { ActorBase } from "../actor-base.js";
3
+ import { mapWorkerView } from "../mappers.js";
4
+ /**
5
+ * Administration of sultana-assets-rust. There is no admin identity on this canister:
6
+ * administration goes THROUGH sultana-core-motoko — core's superadmin calls proxy endpoints
7
+ * on core (setAssetWorkers, deleteAssetRaw) and core forwards them here. The core-only
8
+ * methods below therefore answer `false` (or trap) for every caller but the configured core
9
+ * canister; they are here for wiring scripts, tests and diagnosis.
10
+ */
11
+ export class AssetsRustAdminActor extends ActorBase {
12
+ /**
13
+ * Claim-once bootstrap: while no core canister is configured anyone may set it (call it
14
+ * right after a deploy); afterwards only the current core canister may re-point it.
15
+ * @param corePrincipal - The sultana-core-motoko canister this canister trusts.
16
+ * @returns A Promise that resolves to `true` when set, `false` when the seat is taken by
17
+ * another principal than the caller.
18
+ * @throws CanisterError - The canister trapped.
19
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
20
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
21
+ */
22
+ async setCoreCanisterAsyncUnsafe(corePrincipal) {
23
+ return this.executeFunctionAsyncUnsafe(() => this.actor.set_core_canister(Principal.fromText(corePrincipal)));
24
+ }
25
+ /**
26
+ * @returns A Promise that resolves to the trusted core canister, or `null` when none is
27
+ * configured yet (a fresh deploy).
28
+ * @throws CanisterError - The canister trapped.
29
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
30
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
31
+ */
32
+ async getCoreCanisterAsyncUnsafe() {
33
+ const result = await this.executeFunctionAsyncUnsafe(() => this.actor.get_core_canister());
34
+ return result.length === 0 ? null : result[0].toText();
35
+ }
36
+ /**
37
+ * Core-canister only: replaces the transcoding-worker list. The real path is core's
38
+ * superadmin proxy (sultana-core-motoko-package `AdminActor.setAssetWorkersAsyncUnsafe`).
39
+ * @param workers - Each worker's identity and its FULL upload-endpoint URL.
40
+ * @returns A Promise that resolves to `true` when replaced, `false` when the caller is
41
+ * not the core canister.
42
+ * @throws CanisterError - The canister trapped.
43
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
44
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
45
+ */
46
+ async setWorkersAsyncUnsafe(workers) {
47
+ return this.executeFunctionAsyncUnsafe(() => this.actor.set_workers(workers.map((w) => ({ principal: Principal.fromText(w.principal), url: w.url }))));
48
+ }
49
+ /**
50
+ * @returns A Promise that resolves to the configured transcoding workers (empty on a
51
+ * fresh deploy).
52
+ * @throws CanisterError - The canister trapped.
53
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
54
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
55
+ */
56
+ async getWorkersAsyncUnsafe() {
57
+ const workers = await this.executeFunctionAsyncUnsafe(() => this.actor.get_workers());
58
+ return workers.map(mapWorkerView);
59
+ }
60
+ /**
61
+ * Core-canister only: raw removal of an asset's bytes (and its thumb or poster) with no
62
+ * core deregister — cleanup of orphaned bytes. The real path is core's superadmin proxy
63
+ * `deleteAssetRaw`.
64
+ * @param assetId - The asset to remove.
65
+ * @returns A Promise that resolves to `true` when removed, `false` when the caller is not
66
+ * the core canister or the asset does not exist.
67
+ * @throws CanisterError - The canister trapped.
68
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
69
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
70
+ */
71
+ async deleteAssetAsyncUnsafe(assetId) {
72
+ return this.executeFunctionAsyncUnsafe(() => this.actor.delete_asset(assetId));
73
+ }
74
+ /**
75
+ * Core-canister only: runs the stale-reservation sweep now (the canister also runs it
76
+ * every hour). Reservations older than `ttlMs` are marked failed in core and dropped.
77
+ * @param ttlMs - Age in milliseconds after which a reservation counts as stale.
78
+ * @returns A Promise that resolves to the number of reservations swept.
79
+ * @throws CanisterError - The canister trapped: "caller is not the core canister".
80
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
81
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
82
+ */
83
+ async runReservationSweepAsyncUnsafe(ttlMs) {
84
+ return this.executeFunctionAsyncUnsafe(() => this.actor.run_reservation_sweep(BigInt(ttlMs) * 1000000n));
85
+ }
86
+ }
@@ -0,0 +1,38 @@
1
+ import { ActorBase } from "../actor-base.js";
2
+ import type { AssetInfoView, HttpGetInput, HttpResponseView } from "../interfaces.js";
3
+ /** Reads: what is stored and how it is served. All queries — anonymous callers are fine. */
4
+ export declare class AssetsRustAssetsActor extends ActorBase {
5
+ /**
6
+ * @param assetId - The asset.
7
+ * @returns A Promise that resolves to the asset's description, or `null` when nothing is
8
+ * stored under the id.
9
+ * @throws CanisterError - The canister trapped.
10
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
11
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
12
+ */
13
+ getAssetInfoAsyncUnsafe(assetId: string): Promise<AssetInfoView | null>;
14
+ /**
15
+ * Every asset physically stored — the raw storage view, independent of any salon library:
16
+ * thumbnails, posters and orphans included.
17
+ * @returns A Promise that resolves to every stored asset.
18
+ * @throws CanisterError - The canister trapped.
19
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
20
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
21
+ */
22
+ listAssetsAsyncUnsafe(): Promise<AssetInfoView[]>;
23
+ /**
24
+ * GET of an asset through the canister's `http_request` query — what the HTTP gateway
25
+ * calls, without the gateway: 200 with the whole file (certified; for a multi-chunk file
26
+ * only the first chunk, the rest streams), 206 for a Range header, 404 when not stored.
27
+ * @param assetId - The asset.
28
+ * @param input - Request headers, e.g. a Range.
29
+ * @returns A Promise that resolves to the response.
30
+ * @throws CanisterError - The canister trapped.
31
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
32
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
33
+ */
34
+ httpRequestAsyncUnsafe(assetId: string, input?: HttpGetInput): Promise<HttpResponseView>;
35
+ /** The public URL of an asset on this canister (see {@link assetUrl}). */
36
+ assetUrl(assetId: string): string;
37
+ }
38
+ //# sourceMappingURL=assets-actor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assets-actor.d.ts","sourceRoot":"","sources":["../../src/actors/assets-actor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAGtF,4FAA4F;AAC5F,qBAAa,qBAAsB,SAAQ,SAAS;IAChD;;;;;;;OAOG;IACU,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAKpF;;;;;;;OAOG;IACU,qBAAqB,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;IAK9D;;;;;;;;;;OAUG;IACU,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,GAAE,YAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAYzG,0EAA0E;IACnE,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;CAG3C"}
@@ -0,0 +1,54 @@
1
+ import { ActorBase } from "../actor-base.js";
2
+ import { assetUrl } from "../constants.js";
3
+ import { mapAssetInfoView, mapHttpResponseView } from "../mappers.js";
4
+ /** Reads: what is stored and how it is served. All queries — anonymous callers are fine. */
5
+ export class AssetsRustAssetsActor extends ActorBase {
6
+ /**
7
+ * @param assetId - The asset.
8
+ * @returns A Promise that resolves to the asset's description, or `null` when nothing is
9
+ * stored under the id.
10
+ * @throws CanisterError - The canister trapped.
11
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
12
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
13
+ */
14
+ async getAssetInfoAsyncUnsafe(assetId) {
15
+ const result = await this.executeFunctionAsyncUnsafe(() => this.actor.get_asset_info(assetId));
16
+ return result.length === 0 ? null : mapAssetInfoView(result[0]);
17
+ }
18
+ /**
19
+ * Every asset physically stored — the raw storage view, independent of any salon library:
20
+ * thumbnails, posters and orphans included.
21
+ * @returns A Promise that resolves to every stored asset.
22
+ * @throws CanisterError - The canister trapped.
23
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
24
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
25
+ */
26
+ async listAssetsAsyncUnsafe() {
27
+ const assets = await this.executeFunctionAsyncUnsafe(() => this.actor.list_assets());
28
+ return assets.map(mapAssetInfoView);
29
+ }
30
+ /**
31
+ * GET of an asset through the canister's `http_request` query — what the HTTP gateway
32
+ * calls, without the gateway: 200 with the whole file (certified; for a multi-chunk file
33
+ * only the first chunk, the rest streams), 206 for a Range header, 404 when not stored.
34
+ * @param assetId - The asset.
35
+ * @param input - Request headers, e.g. a Range.
36
+ * @returns A Promise that resolves to the response.
37
+ * @throws CanisterError - The canister trapped.
38
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
39
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
40
+ */
41
+ async httpRequestAsyncUnsafe(assetId, input = {}) {
42
+ const response = await this.executeFunctionAsyncUnsafe(() => this.actor.http_request({
43
+ method: "GET",
44
+ url: `/asset/${assetId}`,
45
+ headers: Object.entries(input.headers ?? {}),
46
+ body: new Uint8Array(),
47
+ }));
48
+ return mapHttpResponseView(response);
49
+ }
50
+ /** The public URL of an asset on this canister (see {@link assetUrl}). */
51
+ assetUrl(assetId) {
52
+ return assetUrl(this.canisterId, assetId);
53
+ }
54
+ }
@@ -0,0 +1,64 @@
1
+ import { ActorBase } from "../actor-base.js";
2
+ import type { ReservationView, ReserveRenderInput, ReserveTranscodingUploadInput, UploadImageInput } from "../interfaces.js";
3
+ /**
4
+ * A salon owner's library on sultana-assets-rust. Every method here asks sultana-core-motoko
5
+ * first (inter-canister): core decides whether the caller is the salon's current owner and
6
+ * whether the salon's storage quota allows it, and core keeps the library entry. A refusal by
7
+ * core — or a core that cannot be reached — comes back as a trap.
8
+ */
9
+ export declare class AssetsRustSalonActor extends ActorBase {
10
+ /**
11
+ * Single-shot image upload into the salon's library: core's canUploadAsset, a generated
12
+ * thumbnail, both stored, then core's registerAsset (both removed again when that fails).
13
+ * @param input - Salon, image and an optional service to attach it to.
14
+ * @returns A Promise that resolves to the image's asset id.
15
+ * @throws CanisterError - The canister trapped: anonymous caller, file too large, "upload
16
+ * not authorized: …" (core refused or unreachable), "thumbnail generation failed:
17
+ * …" (not an image), "register failed, rolled back: …".
18
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
19
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
20
+ */
21
+ uploadImageAsyncUnsafe(input: UploadImageInput): Promise<string>;
22
+ /**
23
+ * Deletes any asset of the salon's library (videos included), core first: core removes
24
+ * the library entry (blocked while a salon service still uses it), then the bytes and the
25
+ * thumb or poster go. An unfinished transcoding job's rabbit task is closed as cancelled.
26
+ * @param salonId - The salon.
27
+ * @param assetId - The asset.
28
+ * @returns A Promise that resolves to `true` when bytes were removed, `false` when core
29
+ * allowed the delete but no bytes were stored under the id.
30
+ * @throws CanisterError - The canister trapped: anonymous caller, "deregister failed
31
+ * (delete blocked): …" (core refused or unreachable).
32
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
33
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
34
+ */
35
+ deleteSalonAssetAsyncUnsafe(salonId: string, assetId: string): Promise<boolean>;
36
+ /**
37
+ * Reserves a transcoding job — nothing is stored yet. Core admits it (owner, quota hold)
38
+ * and gets a #Pending library entry; a rabbit task is enqueued. The caller then uploads the
39
+ * source straight to one of the returned worker URLs (sultana-core-motoko-package's
40
+ * VideoUploadClient does the whole flow).
41
+ * @param input - Salon, kind (default video) and the library name.
42
+ * @returns A Promise that resolves to the reserved id and the worker upload URLs.
43
+ * @throws CanisterError - The canister trapped: anonymous caller, "no transcoding workers
44
+ * configured", "upload not authorized: …", "pending registration failed: …", a
45
+ * rabbit failure.
46
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
47
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
48
+ */
49
+ reserveTranscodingUploadAsyncUnsafe(input: ReserveTranscodingUploadInput): Promise<ReservationView>;
50
+ /**
51
+ * Reserves a promo render: a new video a worker makes from a stored picture or video and
52
+ * a stored music track. The inputs are checked here (stored, right content types, settings
53
+ * in range) before core is asked. The caller then asks a worker to start the render.
54
+ * @param input - Salon, the two stored inputs and the render settings.
55
+ * @returns A Promise that resolves to the reserved id and the worker URLs.
56
+ * @throws CanisterError - The canister trapped: anonymous caller, "no transcoding workers
57
+ * configured", a bad id shape, an input that is not stored or of the wrong type,
58
+ * a setting out of range, "upload not authorized: …", a rabbit failure.
59
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
60
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
61
+ */
62
+ reserveRenderAsyncUnsafe(input: ReserveRenderInput): Promise<ReservationView>;
63
+ }
64
+ //# sourceMappingURL=salon-actor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"salon-actor.d.ts","sourceRoot":"","sources":["../../src/actors/salon-actor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,6BAA6B,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAG7H;;;;;GAKG;AACH,qBAAa,oBAAqB,SAAQ,SAAS;IAC/C;;;;;;;;;;OAUG;IACU,sBAAsB,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC;IAY7E;;;;;;;;;;;;OAYG;IACU,2BAA2B,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI5F;;;;;;;;;;;;OAYG;IACU,mCAAmC,CAAC,KAAK,EAAE,6BAA6B,GAAG,OAAO,CAAC,eAAe,CAAC;IAWhH;;;;;;;;;;;OAWG;IACU,wBAAwB,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,eAAe,CAAC;CAe7F"}
@@ -0,0 +1,92 @@
1
+ import { ActorBase } from "../actor-base.js";
2
+ import { mapReservationView, toCandidOpt, toCandidRenderMode, toCandidTranscodingKind } from "../mappers.js";
3
+ /**
4
+ * A salon owner's library on sultana-assets-rust. Every method here asks sultana-core-motoko
5
+ * first (inter-canister): core decides whether the caller is the salon's current owner and
6
+ * whether the salon's storage quota allows it, and core keeps the library entry. A refusal by
7
+ * core — or a core that cannot be reached — comes back as a trap.
8
+ */
9
+ export class AssetsRustSalonActor extends ActorBase {
10
+ /**
11
+ * Single-shot image upload into the salon's library: core's canUploadAsset, a generated
12
+ * thumbnail, both stored, then core's registerAsset (both removed again when that fails).
13
+ * @param input - Salon, image and an optional service to attach it to.
14
+ * @returns A Promise that resolves to the image's asset id.
15
+ * @throws CanisterError - The canister trapped: anonymous caller, file too large, "upload
16
+ * not authorized: …" (core refused or unreachable), "thumbnail generation failed:
17
+ * …" (not an image), "register failed, rolled back: …".
18
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
19
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
20
+ */
21
+ async uploadImageAsyncUnsafe(input) {
22
+ return this.executeFunctionAsyncUnsafe(() => this.actor.upload_image({
23
+ salonId: input.salonId,
24
+ name: input.name,
25
+ contentType: input.contentType,
26
+ data: input.data,
27
+ targetSalonServiceId: toCandidOpt(input.targetSalonServiceId),
28
+ }));
29
+ }
30
+ /**
31
+ * Deletes any asset of the salon's library (videos included), core first: core removes
32
+ * the library entry (blocked while a salon service still uses it), then the bytes and the
33
+ * thumb or poster go. An unfinished transcoding job's rabbit task is closed as cancelled.
34
+ * @param salonId - The salon.
35
+ * @param assetId - The asset.
36
+ * @returns A Promise that resolves to `true` when bytes were removed, `false` when core
37
+ * allowed the delete but no bytes were stored under the id.
38
+ * @throws CanisterError - The canister trapped: anonymous caller, "deregister failed
39
+ * (delete blocked): …" (core refused or unreachable).
40
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
41
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
42
+ */
43
+ async deleteSalonAssetAsyncUnsafe(salonId, assetId) {
44
+ return this.executeFunctionAsyncUnsafe(() => this.actor.delete_salon_asset({ salonId, id: assetId }));
45
+ }
46
+ /**
47
+ * Reserves a transcoding job — nothing is stored yet. Core admits it (owner, quota hold)
48
+ * and gets a #Pending library entry; a rabbit task is enqueued. The caller then uploads the
49
+ * source straight to one of the returned worker URLs (sultana-core-motoko-package's
50
+ * VideoUploadClient does the whole flow).
51
+ * @param input - Salon, kind (default video) and the library name.
52
+ * @returns A Promise that resolves to the reserved id and the worker upload URLs.
53
+ * @throws CanisterError - The canister trapped: anonymous caller, "no transcoding workers
54
+ * configured", "upload not authorized: …", "pending registration failed: …", a
55
+ * rabbit failure.
56
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
57
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
58
+ */
59
+ async reserveTranscodingUploadAsyncUnsafe(input) {
60
+ const reservation = await this.executeFunctionAsyncUnsafe(() => this.actor.reserve_transcoding_upload({
61
+ salonId: input.salonId,
62
+ kind: input.kind === undefined ? [] : [toCandidTranscodingKind(input.kind)],
63
+ name: toCandidOpt(input.name),
64
+ }));
65
+ return mapReservationView(reservation);
66
+ }
67
+ /**
68
+ * Reserves a promo render: a new video a worker makes from a stored picture or video and
69
+ * a stored music track. The inputs are checked here (stored, right content types, settings
70
+ * in range) before core is asked. The caller then asks a worker to start the render.
71
+ * @param input - Salon, the two stored inputs and the render settings.
72
+ * @returns A Promise that resolves to the reserved id and the worker URLs.
73
+ * @throws CanisterError - The canister trapped: anonymous caller, "no transcoding workers
74
+ * configured", a bad id shape, an input that is not stored or of the wrong type,
75
+ * a setting out of range, "upload not authorized: …", a rabbit failure.
76
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
77
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
78
+ */
79
+ async reserveRenderAsyncUnsafe(input) {
80
+ const reservation = await this.executeFunctionAsyncUnsafe(() => this.actor.reserve_render({
81
+ salonId: input.salonId,
82
+ sourceAssetId: input.sourceAssetId,
83
+ audioAssetId: input.audioAssetId,
84
+ mode: toCandidRenderMode(input.mode),
85
+ musicVolumePct: input.musicVolumePct,
86
+ musicStartSec: toCandidOpt(input.musicStartSec),
87
+ slideDurationSec: toCandidOpt(input.slideDurationSec),
88
+ name: toCandidOpt(input.name),
89
+ }));
90
+ return mapReservationView(reservation);
91
+ }
92
+ }
@@ -0,0 +1,74 @@
1
+ import { ActorBase } from "../actor-base.js";
2
+ import type { ChunkedUploadOptions, StartUploadInput, UploadAssetInput } from "../interfaces.js";
3
+ /**
4
+ * Generic uploads, not tied to a salon: a chunked session (start → chunks → finish) or a
5
+ * single-shot upload. Any signed-in caller may upload; the session belongs to its starter.
6
+ * Salon-library uploads go through {@link AssetsRustSalonActor} instead.
7
+ */
8
+ export declare class AssetsRustUploadsActor extends ActorBase {
9
+ /**
10
+ * Opens a chunked upload session owned by the caller. An unfinished session is purged
11
+ * after 30 minutes.
12
+ * @param input - Name, content type and the number of chunks that will follow.
13
+ * @returns A Promise that resolves to the new asset id (the session id).
14
+ * @throws CanisterError - The canister trapped: anonymous caller, totalChunks 0.
15
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
16
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
17
+ */
18
+ startUploadAsyncUnsafe(input: StartUploadInput): Promise<string>;
19
+ /**
20
+ * Stores one chunk of an open session (the caller's own session, or — for a worker — a
21
+ * system session it started). Re-sending an index overwrites it.
22
+ * @param assetId - The session id.
23
+ * @param index - 0-based chunk index, below the session's totalChunks.
24
+ * @param data - At most ASSETS_RUST_LIMITS.chunkSizeBytes.
25
+ * @throws CanisterError - The canister trapped: chunk too big, unknown session, not the
26
+ * session owner, index out of range.
27
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
28
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
29
+ */
30
+ uploadChunkAsyncUnsafe(assetId: string, index: number, data: Uint8Array): Promise<void>;
31
+ /**
32
+ * Assembles the session into a stored, certified asset.
33
+ * @param assetId - The session id.
34
+ * @returns A Promise that resolves to the asset id.
35
+ * @throws CanisterError - The canister trapped: unknown session, not the session owner,
36
+ * not all chunks received.
37
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
38
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
39
+ */
40
+ finishUploadAsyncUnsafe(assetId: string): Promise<string>;
41
+ /**
42
+ * Drops an open session and its chunks.
43
+ * @param assetId - The session id.
44
+ * @returns A Promise that resolves to `true` when dropped, `false` when there is no such
45
+ * session (finished, aborted or purged).
46
+ * @throws CanisterError - The canister trapped: not the session owner.
47
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
48
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
49
+ */
50
+ abortUploadAsyncUnsafe(assetId: string): Promise<boolean>;
51
+ /**
52
+ * Single-shot upload of a small file.
53
+ * @param input - Name, content type and at most ASSETS_RUST_LIMITS.chunkSizeBytes of data.
54
+ * @returns A Promise that resolves to the new asset id.
55
+ * @throws CanisterError - The canister trapped: anonymous caller, file too large.
56
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
57
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
58
+ */
59
+ uploadAssetAsyncUnsafe(input: UploadAssetInput): Promise<string>;
60
+ /**
61
+ * Uploads `bytes` of any size as one asset: start, every chunk in order, finish. A failed
62
+ * chunk or finish aborts the session (best effort) before the error is re-thrown.
63
+ * @param name - The asset's name.
64
+ * @param contentType - The asset's content type (served as Content-Type).
65
+ * @param bytes - The file.
66
+ * @param options - Chunk size and a progress callback.
67
+ * @returns A Promise that resolves to the stored asset's id.
68
+ * @throws CanisterError - The canister trapped in one of the three steps.
69
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
70
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
71
+ */
72
+ uploadBytesAsyncUnsafe(name: string, contentType: string, bytes: Uint8Array, options?: ChunkedUploadOptions): Promise<string>;
73
+ }
74
+ //# sourceMappingURL=uploads-actor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uploads-actor.d.ts","sourceRoot":"","sources":["../../src/actors/uploads-actor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEjG;;;;GAIG;AACH,qBAAa,sBAAuB,SAAQ,SAAS;IACjD;;;;;;;;OAQG;IACU,sBAAsB,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC;IAI7E;;;;;;;;;;OAUG;IACU,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpG;;;;;;;;OAQG;IACU,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAItE;;;;;;;;OAQG;IACU,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAItE;;;;;;;OAOG;IACU,sBAAsB,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC;IAI7E;;;;;;;;;;;OAWG;IACU,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,MAAM,CAAC;CAgBjJ"}
@@ -0,0 +1,97 @@
1
+ import { ActorBase } from "../actor-base.js";
2
+ import { splitIntoChunks } from "../constants.js";
3
+ /**
4
+ * Generic uploads, not tied to a salon: a chunked session (start → chunks → finish) or a
5
+ * single-shot upload. Any signed-in caller may upload; the session belongs to its starter.
6
+ * Salon-library uploads go through {@link AssetsRustSalonActor} instead.
7
+ */
8
+ export class AssetsRustUploadsActor extends ActorBase {
9
+ /**
10
+ * Opens a chunked upload session owned by the caller. An unfinished session is purged
11
+ * after 30 minutes.
12
+ * @param input - Name, content type and the number of chunks that will follow.
13
+ * @returns A Promise that resolves to the new asset id (the session id).
14
+ * @throws CanisterError - The canister trapped: anonymous caller, totalChunks 0.
15
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
16
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
17
+ */
18
+ async startUploadAsyncUnsafe(input) {
19
+ return this.executeFunctionAsyncUnsafe(() => this.actor.start_upload({ name: input.name, contentType: input.contentType, totalChunks: input.totalChunks }));
20
+ }
21
+ /**
22
+ * Stores one chunk of an open session (the caller's own session, or — for a worker — a
23
+ * system session it started). Re-sending an index overwrites it.
24
+ * @param assetId - The session id.
25
+ * @param index - 0-based chunk index, below the session's totalChunks.
26
+ * @param data - At most ASSETS_RUST_LIMITS.chunkSizeBytes.
27
+ * @throws CanisterError - The canister trapped: chunk too big, unknown session, not the
28
+ * session owner, index out of range.
29
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
30
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
31
+ */
32
+ async uploadChunkAsyncUnsafe(assetId, index, data) {
33
+ await this.executeFunctionAsyncUnsafe(() => this.actor.upload_chunk(assetId, index, data));
34
+ }
35
+ /**
36
+ * Assembles the session into a stored, certified asset.
37
+ * @param assetId - The session id.
38
+ * @returns A Promise that resolves to the asset id.
39
+ * @throws CanisterError - The canister trapped: unknown session, not the session owner,
40
+ * not all chunks received.
41
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
42
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
43
+ */
44
+ async finishUploadAsyncUnsafe(assetId) {
45
+ return this.executeFunctionAsyncUnsafe(() => this.actor.finish_upload(assetId));
46
+ }
47
+ /**
48
+ * Drops an open session and its chunks.
49
+ * @param assetId - The session id.
50
+ * @returns A Promise that resolves to `true` when dropped, `false` when there is no such
51
+ * session (finished, aborted or purged).
52
+ * @throws CanisterError - The canister trapped: not the session owner.
53
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
54
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
55
+ */
56
+ async abortUploadAsyncUnsafe(assetId) {
57
+ return this.executeFunctionAsyncUnsafe(() => this.actor.abort_upload(assetId));
58
+ }
59
+ /**
60
+ * Single-shot upload of a small file.
61
+ * @param input - Name, content type and at most ASSETS_RUST_LIMITS.chunkSizeBytes of data.
62
+ * @returns A Promise that resolves to the new asset id.
63
+ * @throws CanisterError - The canister trapped: anonymous caller, file too large.
64
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
65
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
66
+ */
67
+ async uploadAssetAsyncUnsafe(input) {
68
+ return this.executeFunctionAsyncUnsafe(() => this.actor.upload_asset({ name: input.name, contentType: input.contentType, data: input.data }));
69
+ }
70
+ /**
71
+ * Uploads `bytes` of any size as one asset: start, every chunk in order, finish. A failed
72
+ * chunk or finish aborts the session (best effort) before the error is re-thrown.
73
+ * @param name - The asset's name.
74
+ * @param contentType - The asset's content type (served as Content-Type).
75
+ * @param bytes - The file.
76
+ * @param options - Chunk size and a progress callback.
77
+ * @returns A Promise that resolves to the stored asset's id.
78
+ * @throws CanisterError - The canister trapped in one of the three steps.
79
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
80
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
81
+ */
82
+ async uploadBytesAsyncUnsafe(name, contentType, bytes, options = {}) {
83
+ const chunks = splitIntoChunks(bytes, options.chunkSizeBytes);
84
+ const assetId = await this.startUploadAsyncUnsafe({ name, contentType, totalChunks: chunks.length });
85
+ try {
86
+ for (let index = 0; index < chunks.length; index++) {
87
+ await this.uploadChunkAsyncUnsafe(assetId, index, chunks[index]);
88
+ options.onProgress?.({ uploadedChunks: index + 1, totalChunks: chunks.length });
89
+ }
90
+ return await this.finishUploadAsyncUnsafe(assetId);
91
+ }
92
+ catch (err) {
93
+ await this.abortUploadAsyncUnsafe(assetId).catch(() => false);
94
+ throw err;
95
+ }
96
+ }
97
+ }
@@ -0,0 +1,72 @@
1
+ import { ActorBase } from "../actor-base.js";
2
+ import type { ChunkedUploadOptions, SystemStartUploadInput } from "../interfaces.js";
3
+ /**
4
+ * The transcoding worker's side: it stores a finished result under the id the salon
5
+ * reserved. Every method traps unless the caller's principal is on the canister's worker list
6
+ * (`set_workers`, driven by core's superadmin).
7
+ */
8
+ export declare class AssetsRustWorkerActor extends ActorBase {
9
+ /**
10
+ * Opens a chunked upload session under a reserved id.
11
+ * @param input - The reserved id, name, content type and number of chunks.
12
+ * @returns A Promise that resolves to the id.
13
+ * @throws CanisterError - The canister trapped: "caller is not a transcoding worker",
14
+ * totalChunks 0, "asset already exists".
15
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
16
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
17
+ */
18
+ systemStartUploadAsyncUnsafe(input: SystemStartUploadInput): Promise<string>;
19
+ /**
20
+ * Stores one chunk of a session this worker started.
21
+ * @param assetId - The session id.
22
+ * @param index - 0-based chunk index.
23
+ * @param data - At most ASSETS_RUST_LIMITS.chunkSizeBytes.
24
+ * @throws CanisterError - The canister trapped: chunk too big, unknown session, not the
25
+ * session owner, index out of range.
26
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
27
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
28
+ */
29
+ uploadChunkAsyncUnsafe(assetId: string, index: number, data: Uint8Array): Promise<void>;
30
+ /**
31
+ * Opens a system session under `assetId` and sends every chunk of `bytes` — everything but
32
+ * the finish, because a video and its poster are finished together
33
+ * ({@link finishSystemUploadAsyncUnsafe}).
34
+ * @param assetId - The reserved id (or the poster's own id).
35
+ * @param name - The stored name.
36
+ * @param contentType - The stored content type.
37
+ * @param bytes - The file.
38
+ * @param options - Chunk size and a progress callback.
39
+ * @throws CanisterError - The canister trapped in start or in a chunk.
40
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
41
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
42
+ */
43
+ systemUploadBytesAsyncUnsafe(assetId: string, name: string, contentType: string, bytes: Uint8Array, options?: ChunkedUploadOptions): Promise<void>;
44
+ /**
45
+ * Finishes the result (and its poster session, when given) and — when the id was
46
+ * reserved by a salon — registers it in that salon's core library with the poster as its
47
+ * thumb. Safe to retry after a failed registration: stored bytes are not stored again.
48
+ * @param assetId - The reserved id.
49
+ * @param posterId - The poster frame's session id, uploaded alongside.
50
+ * @returns A Promise that resolves to the asset id.
51
+ * @throws CanisterError - The canister trapped: "caller is not a transcoding worker",
52
+ * "posterId must differ from the video id", an incomplete session, "asset register
53
+ * failed: …" (core refused or unreachable; the reservation is kept for a retry).
54
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
55
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
56
+ */
57
+ finishSystemUploadAsyncUnsafe(assetId: string, posterId?: string): Promise<string>;
58
+ /**
59
+ * Reports a failed transcode: the salon's #Pending library entry becomes #Failed(reason)
60
+ * and the reservation is dropped.
61
+ * @param assetId - The reserved id.
62
+ * @param reason - What went wrong (a JSON error payload the front translates).
63
+ * @returns A Promise that resolves to `true` when reported, `false` when there is no such
64
+ * reservation (finished, deleted or swept).
65
+ * @throws CanisterError - The canister trapped: "caller is not a transcoding worker",
66
+ * "markAssetFailed rejected: …" (the reservation is kept; the sweep retries).
67
+ * @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
68
+ * @throws CriticalCanisterError - Transport failure or an unreachable canister.
69
+ */
70
+ failSystemUploadAsyncUnsafe(assetId: string, reason: string): Promise<boolean>;
71
+ }
72
+ //# sourceMappingURL=worker-actor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-actor.d.ts","sourceRoot":"","sources":["../../src/actors/worker-actor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAErF;;;;GAIG;AACH,qBAAa,qBAAsB,SAAQ,SAAS;IAChD;;;;;;;;OAQG;IACU,4BAA4B,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC;IAIzF;;;;;;;;;OASG;IACU,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpG;;;;;;;;;;;;OAYG;IACU,4BAA4B,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC;IAUnK;;;;;;;;;;;;OAYG;IACU,6BAA6B,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAI/F;;;;;;;;;;;OAWG;IACU,2BAA2B,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAG9F"}