@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.
- package/README.md +86 -0
- package/declarations/sultana-assets-rust/sultana-assets-rust.did +98 -0
- package/declarations/sultana-assets-rust/sultana-assets-rust.did.d.ts +129 -0
- package/declarations/sultana-assets-rust/sultana-assets-rust.did.js +143 -0
- package/dist/actor-base.d.ts +46 -0
- package/dist/actor-base.d.ts.map +1 -0
- package/dist/actor-base.js +87 -0
- package/dist/actors/admin-actor.d.ts +72 -0
- package/dist/actors/admin-actor.d.ts.map +1 -0
- package/dist/actors/admin-actor.js +86 -0
- package/dist/actors/assets-actor.d.ts +38 -0
- package/dist/actors/assets-actor.d.ts.map +1 -0
- package/dist/actors/assets-actor.js +54 -0
- package/dist/actors/salon-actor.d.ts +64 -0
- package/dist/actors/salon-actor.d.ts.map +1 -0
- package/dist/actors/salon-actor.js +92 -0
- package/dist/actors/uploads-actor.d.ts +74 -0
- package/dist/actors/uploads-actor.d.ts.map +1 -0
- package/dist/actors/uploads-actor.js +97 -0
- package/dist/actors/worker-actor.d.ts +72 -0
- package/dist/actors/worker-actor.d.ts.map +1 -0
- package/dist/actors/worker-actor.js +86 -0
- package/dist/constants.d.ts +33 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +45 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/interfaces.d.ts +97 -0
- package/dist/interfaces.d.ts.map +1 -0
- package/dist/interfaces.js +1 -0
- package/dist/mappers.d.ts +11 -0
- package/dist/mappers.d.ts.map +1 -0
- package/dist/mappers.js +38 -0
- package/package.json +58 -0
package/README.md
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# @jsm-mit/sultana-assets-rust-package
|
|
2
|
+
|
|
3
|
+
TypeScript wrapper for the [`sultana-assets-rust`](../sultana-assets-rust) canister — Sultana's
|
|
4
|
+
asset storage on the Internet Computer (salon images, videos, music tracks, posters) — plus
|
|
5
|
+
the integration tests that prove it.
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { AssetsRustSalonActor, AssetsRustUploadsActor, AssetsRustAssetsActor } from "@jsm-mit/sultana-assets-rust-package";
|
|
9
|
+
|
|
10
|
+
// A salon owner puts an image into the salon's library. The canister asks
|
|
11
|
+
// sultana-core-motoko first (owner? quota?), makes a thumbnail, stores both and registers
|
|
12
|
+
// them in core — or traps and stores nothing.
|
|
13
|
+
const salon = new AssetsRustSalonActor(assetsCanisterId, ownerIdentity);
|
|
14
|
+
const imageId = await salon.uploadImageAsyncUnsafe({ salonId, name: "front.jpg", contentType: "image/jpeg", data });
|
|
15
|
+
|
|
16
|
+
// A video goes to a transcoding worker, not to the canister: reserve an id, then upload to
|
|
17
|
+
// one of the returned worker URLs (sultana-core-motoko-package's VideoUploadClient does it).
|
|
18
|
+
const { id, uploadUrls } = await salon.reserveTranscodingUploadAsyncUnsafe({ salonId, name: "promo" });
|
|
19
|
+
|
|
20
|
+
// Any file, any size, not tied to a salon: a chunked session.
|
|
21
|
+
const fileId = await new AssetsRustUploadsActor(assetsCanisterId, identity).uploadBytesAsyncUnsafe("notes.pdf", "application/pdf", bytes);
|
|
22
|
+
|
|
23
|
+
// Reads are anonymous.
|
|
24
|
+
const assets = new AssetsRustAssetsActor(assetsCanisterId);
|
|
25
|
+
const info = await assets.getAssetInfoAsyncUnsafe(imageId);
|
|
26
|
+
const url = assets.assetUrl(imageId); // https://<canister>.raw.icp0.io/asset/<id>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
One class per part of the canister:
|
|
30
|
+
|
|
31
|
+
| Class | Calls | Who |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| `AssetsRustAdminActor` | core link (claim-once), worker list, `delete_asset`, the reservation sweep | the core canister (via core's superadmin proxies); wiring scripts |
|
|
34
|
+
| `AssetsRustUploadsActor` | chunked session, single-shot upload, `uploadBytesAsyncUnsafe` | any signed-in caller |
|
|
35
|
+
| `AssetsRustSalonActor` | `upload_image`, `delete_salon_asset`, transcoding and render reservations | the salon's owner — core decides |
|
|
36
|
+
| `AssetsRustWorkerActor` | system upload of a transcoded result under a reserved id | listed transcoding workers |
|
|
37
|
+
| `AssetsRustAssetsActor` | `get_asset_info`, `list_assets`, `http_request`, `assetUrl` | anybody |
|
|
38
|
+
|
|
39
|
+
Every method is `…AsyncUnsafe` and throws one of three errors, like the other wrapper
|
|
40
|
+
packages:
|
|
41
|
+
|
|
42
|
+
- `CanisterError` — the canister trapped. sultana-assets-rust has no error variants: it
|
|
43
|
+
returns the value or traps, so `cause` is `{ errorKey: "Trap", errorMessage: <trap text>,
|
|
44
|
+
rawError }` — e.g. `"upload not authorized: core canUploadAsset rejected: …"`.
|
|
45
|
+
- `CallRefusedAtInspectionStage` — refused before execution (kept for the shared vocabulary;
|
|
46
|
+
the canister has no `inspect_message` today).
|
|
47
|
+
- `CriticalCanisterError` — anything else: transport, an unreachable canister, no cycles.
|
|
48
|
+
|
|
49
|
+
Methods the canister answers with `false` for a refusal (`setCoreCanister`, `setWorkers`,
|
|
50
|
+
`deleteAsset`, `abortUpload`, `failSystemUpload`) return that boolean. Views turn
|
|
51
|
+
`Principal` into text, `opt` into optional fields, variants into string unions and sizes
|
|
52
|
+
into `number`; timestamps stay `bigint` nanoseconds. `ASSETS_RUST_LIMITS` carries the
|
|
53
|
+
canister's limits (chunk size, render settings) for checks before a call. The raw candid
|
|
54
|
+
types are exported too, and `./declarations/*` gives the generated files.
|
|
55
|
+
|
|
56
|
+
`src/` is browser-safe — the same package serves the biz panel, the playground and the
|
|
57
|
+
transcoding worker.
|
|
58
|
+
|
|
59
|
+
Scripts: `build`, `typecheck`, `sync-declarations`, `test-suite`, `redeploy`, `sandbox`
|
|
60
|
+
(an interactive console: `npm run sandbox -- <canister-id>`, caller from `IDENTITY_PEM` in
|
|
61
|
+
`.env` or anonymous), `stamp-canister`, `publish-public`. See `CLAUDE.md` for who runs what.
|
|
62
|
+
|
|
63
|
+
## Integration tests
|
|
64
|
+
|
|
65
|
+
`npm run test-suite` reinstalls the current `../sultana-assets-rust` build into the crafting
|
|
66
|
+
table's `short-living` slot (lease 3 minutes) and runs `tests/test-suite.ts` there. No
|
|
67
|
+
`.env`, no PEMs: every identity is generated per run. A fresh canister has no core canister,
|
|
68
|
+
so the suite claims that claim-once seat for a generated identity and plays core itself.
|
|
69
|
+
|
|
70
|
+
What the suite covers: the core seat and the worker list; chunked and single-shot uploads
|
|
71
|
+
with every owner and size check; reads, HTTP 200/206/404, certification header and
|
|
72
|
+
streaming; the worker's system upload with a poster; `delete_asset` taking the thumb along;
|
|
73
|
+
the `reserve_render` input checks. What it leaves to `sultana-command-line-playground`: every
|
|
74
|
+
path where core says yes — the canister's calls out to core go to the generated identity and
|
|
75
|
+
fail, and the suite asserts exactly that trap. Rabbit is reached only after core agreed, so
|
|
76
|
+
the suite never touches it.
|
|
77
|
+
|
|
78
|
+
## Publishing
|
|
79
|
+
|
|
80
|
+
Bump the version by hand, commit, push, then `npm run publish-public`. It refuses unless this
|
|
81
|
+
repo and `../sultana-assets-rust` are on a clean, pushed `master` and the version is new on
|
|
82
|
+
npm; it reinstalls the canister's master into `short-living` (lease 1), checks that its
|
|
83
|
+
`candid:service` equals `declarations/sultana-assets-rust/sultana-assets-rust.did` as dfx
|
|
84
|
+
rewrites it (the hand-written .did is normalized by a local `dfx build --check` first), stamps
|
|
85
|
+
`sultanaAssets.{repo, repoUrl, commit}` into package.json, publishes and commits `Version bump
|
|
86
|
+
to <version>`.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
type AssetInfo = record {
|
|
2
|
+
id : text;
|
|
3
|
+
contentType : text;
|
|
4
|
+
name : text;
|
|
5
|
+
uploadedAt : int64;
|
|
6
|
+
totalSize : nat64;
|
|
7
|
+
chunkCount : nat32;
|
|
8
|
+
};
|
|
9
|
+
type StreamingCallbackToken = record {
|
|
10
|
+
key : text;
|
|
11
|
+
index : nat32;
|
|
12
|
+
contentEncoding : text;
|
|
13
|
+
sha256 : opt blob;
|
|
14
|
+
};
|
|
15
|
+
type StreamingCallbackHttpResponse = record {
|
|
16
|
+
body : blob;
|
|
17
|
+
token : opt StreamingCallbackToken;
|
|
18
|
+
};
|
|
19
|
+
type StreamingStrategy = variant {
|
|
20
|
+
Callback : record {
|
|
21
|
+
callback : func (StreamingCallbackToken) -> (StreamingCallbackHttpResponse) query;
|
|
22
|
+
token : StreamingCallbackToken;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
type HttpRequest = record {
|
|
26
|
+
url : text;
|
|
27
|
+
method : text;
|
|
28
|
+
body : blob;
|
|
29
|
+
headers : vec record { text; text };
|
|
30
|
+
};
|
|
31
|
+
type HttpResponse = record {
|
|
32
|
+
body : blob;
|
|
33
|
+
headers : vec record { text; text };
|
|
34
|
+
streaming_strategy : opt StreamingStrategy;
|
|
35
|
+
upgrade : opt bool;
|
|
36
|
+
status_code : nat16;
|
|
37
|
+
};
|
|
38
|
+
type UploadArgs = record { contentType : text; data : blob; name : text };
|
|
39
|
+
type WorkerEntry = record { "principal" : principal; url : text };
|
|
40
|
+
type ReserveTranscodingUpload = record { id : text; uploadUrls : vec text };
|
|
41
|
+
type StartUploadArgs = record {
|
|
42
|
+
contentType : text;
|
|
43
|
+
name : text;
|
|
44
|
+
totalChunks : nat32;
|
|
45
|
+
};
|
|
46
|
+
type SystemStartUploadArgs = record {
|
|
47
|
+
id : text;
|
|
48
|
+
contentType : text;
|
|
49
|
+
name : text;
|
|
50
|
+
totalChunks : nat32;
|
|
51
|
+
};
|
|
52
|
+
type FinishSystemUploadArgs = record { id : text; posterId : opt text };
|
|
53
|
+
type FailSystemUploadArgs = record { id : text; reason : text };
|
|
54
|
+
type UploadImageArgs = record {
|
|
55
|
+
contentType : text;
|
|
56
|
+
data : blob;
|
|
57
|
+
name : text;
|
|
58
|
+
salonId : text;
|
|
59
|
+
targetSalonServiceId : opt text;
|
|
60
|
+
};
|
|
61
|
+
type DeleteSalonAssetArgs = record { id : text; salonId : text };
|
|
62
|
+
type TranscodingKind = variant { Video; Audio };
|
|
63
|
+
type ReserveTranscodingUploadArgs = record { salonId : text; kind : opt TranscodingKind; name : opt text };
|
|
64
|
+
type RenderMode = variant { Replace; Mix };
|
|
65
|
+
type ReserveRenderArgs = record {
|
|
66
|
+
salonId : text;
|
|
67
|
+
sourceAssetId : text;
|
|
68
|
+
audioAssetId : text;
|
|
69
|
+
mode : RenderMode;
|
|
70
|
+
musicVolumePct : nat8;
|
|
71
|
+
musicStartSec : opt nat32;
|
|
72
|
+
slideDurationSec : opt nat16;
|
|
73
|
+
name : opt text;
|
|
74
|
+
};
|
|
75
|
+
service : () -> {
|
|
76
|
+
abort_upload : (text) -> (bool);
|
|
77
|
+
delete_asset : (text) -> (bool);
|
|
78
|
+
delete_salon_asset : (DeleteSalonAssetArgs) -> (bool);
|
|
79
|
+
fail_system_upload : (FailSystemUploadArgs) -> (bool);
|
|
80
|
+
finish_system_upload : (FinishSystemUploadArgs) -> (text);
|
|
81
|
+
finish_upload : (text) -> (text);
|
|
82
|
+
get_asset_info : (text) -> (opt AssetInfo) query;
|
|
83
|
+
get_core_canister : () -> (opt principal) query;
|
|
84
|
+
get_workers : () -> (vec WorkerEntry) query;
|
|
85
|
+
http_request : (HttpRequest) -> (HttpResponse) query;
|
|
86
|
+
http_request_streaming_callback : (StreamingCallbackToken) -> (StreamingCallbackHttpResponse) query;
|
|
87
|
+
list_assets : () -> (vec AssetInfo) query;
|
|
88
|
+
reserve_render : (ReserveRenderArgs) -> (ReserveTranscodingUpload);
|
|
89
|
+
reserve_transcoding_upload : (ReserveTranscodingUploadArgs) -> (ReserveTranscodingUpload);
|
|
90
|
+
run_reservation_sweep : (nat64) -> (nat32);
|
|
91
|
+
set_core_canister : (principal) -> (bool);
|
|
92
|
+
set_workers : (vec WorkerEntry) -> (bool);
|
|
93
|
+
start_upload : (StartUploadArgs) -> (text);
|
|
94
|
+
system_start_upload : (SystemStartUploadArgs) -> (text);
|
|
95
|
+
upload_asset : (UploadArgs) -> (text);
|
|
96
|
+
upload_chunk : (text, nat32, blob) -> ();
|
|
97
|
+
upload_image : (UploadImageArgs) -> (text);
|
|
98
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import type { Principal } from '@icp-sdk/core/principal';
|
|
2
|
+
import type { ActorMethod } from '@icp-sdk/core/agent';
|
|
3
|
+
import type { IDL } from '@icp-sdk/core/candid';
|
|
4
|
+
|
|
5
|
+
export interface AssetInfo {
|
|
6
|
+
'id' : string,
|
|
7
|
+
'contentType' : string,
|
|
8
|
+
'name' : string,
|
|
9
|
+
'totalSize' : bigint,
|
|
10
|
+
'chunkCount' : number,
|
|
11
|
+
'uploadedAt' : bigint,
|
|
12
|
+
}
|
|
13
|
+
export interface DeleteSalonAssetArgs { 'id' : string, 'salonId' : string }
|
|
14
|
+
export interface FailSystemUploadArgs { 'id' : string, 'reason' : string }
|
|
15
|
+
export interface FinishSystemUploadArgs {
|
|
16
|
+
'id' : string,
|
|
17
|
+
'posterId' : [] | [string],
|
|
18
|
+
}
|
|
19
|
+
export interface HttpRequest {
|
|
20
|
+
'url' : string,
|
|
21
|
+
'method' : string,
|
|
22
|
+
'body' : Uint8Array | number[],
|
|
23
|
+
'headers' : Array<[string, string]>,
|
|
24
|
+
}
|
|
25
|
+
export interface HttpResponse {
|
|
26
|
+
'body' : Uint8Array | number[],
|
|
27
|
+
'headers' : Array<[string, string]>,
|
|
28
|
+
'upgrade' : [] | [boolean],
|
|
29
|
+
'streaming_strategy' : [] | [StreamingStrategy],
|
|
30
|
+
'status_code' : number,
|
|
31
|
+
}
|
|
32
|
+
export type RenderMode = { 'Mix' : null } |
|
|
33
|
+
{ 'Replace' : null };
|
|
34
|
+
export interface ReserveRenderArgs {
|
|
35
|
+
'slideDurationSec' : [] | [number],
|
|
36
|
+
'musicStartSec' : [] | [number],
|
|
37
|
+
'audioAssetId' : string,
|
|
38
|
+
'mode' : RenderMode,
|
|
39
|
+
'name' : [] | [string],
|
|
40
|
+
'sourceAssetId' : string,
|
|
41
|
+
'musicVolumePct' : number,
|
|
42
|
+
'salonId' : string,
|
|
43
|
+
}
|
|
44
|
+
export interface ReserveTranscodingUpload {
|
|
45
|
+
'id' : string,
|
|
46
|
+
'uploadUrls' : Array<string>,
|
|
47
|
+
}
|
|
48
|
+
export interface ReserveTranscodingUploadArgs {
|
|
49
|
+
'kind' : [] | [TranscodingKind],
|
|
50
|
+
'name' : [] | [string],
|
|
51
|
+
'salonId' : string,
|
|
52
|
+
}
|
|
53
|
+
export interface StartUploadArgs {
|
|
54
|
+
'contentType' : string,
|
|
55
|
+
'name' : string,
|
|
56
|
+
'totalChunks' : number,
|
|
57
|
+
}
|
|
58
|
+
export interface StreamingCallbackHttpResponse {
|
|
59
|
+
'token' : [] | [StreamingCallbackToken],
|
|
60
|
+
'body' : Uint8Array | number[],
|
|
61
|
+
}
|
|
62
|
+
export interface StreamingCallbackToken {
|
|
63
|
+
'key' : string,
|
|
64
|
+
'sha256' : [] | [Uint8Array | number[]],
|
|
65
|
+
'index' : number,
|
|
66
|
+
'contentEncoding' : string,
|
|
67
|
+
}
|
|
68
|
+
export type StreamingStrategy = {
|
|
69
|
+
'Callback' : {
|
|
70
|
+
'token' : StreamingCallbackToken,
|
|
71
|
+
'callback' : [Principal, string],
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
export interface SystemStartUploadArgs {
|
|
75
|
+
'id' : string,
|
|
76
|
+
'contentType' : string,
|
|
77
|
+
'name' : string,
|
|
78
|
+
'totalChunks' : number,
|
|
79
|
+
}
|
|
80
|
+
export type TranscodingKind = { 'Audio' : null } |
|
|
81
|
+
{ 'Video' : null };
|
|
82
|
+
export interface UploadArgs {
|
|
83
|
+
'contentType' : string,
|
|
84
|
+
'data' : Uint8Array | number[],
|
|
85
|
+
'name' : string,
|
|
86
|
+
}
|
|
87
|
+
export interface UploadImageArgs {
|
|
88
|
+
'contentType' : string,
|
|
89
|
+
'data' : Uint8Array | number[],
|
|
90
|
+
'name' : string,
|
|
91
|
+
'targetSalonServiceId' : [] | [string],
|
|
92
|
+
'salonId' : string,
|
|
93
|
+
}
|
|
94
|
+
export interface WorkerEntry { 'url' : string, 'principal' : Principal }
|
|
95
|
+
export interface _SERVICE {
|
|
96
|
+
'abort_upload' : ActorMethod<[string], boolean>,
|
|
97
|
+
'delete_asset' : ActorMethod<[string], boolean>,
|
|
98
|
+
'delete_salon_asset' : ActorMethod<[DeleteSalonAssetArgs], boolean>,
|
|
99
|
+
'fail_system_upload' : ActorMethod<[FailSystemUploadArgs], boolean>,
|
|
100
|
+
'finish_system_upload' : ActorMethod<[FinishSystemUploadArgs], string>,
|
|
101
|
+
'finish_upload' : ActorMethod<[string], string>,
|
|
102
|
+
'get_asset_info' : ActorMethod<[string], [] | [AssetInfo]>,
|
|
103
|
+
'get_core_canister' : ActorMethod<[], [] | [Principal]>,
|
|
104
|
+
'get_workers' : ActorMethod<[], Array<WorkerEntry>>,
|
|
105
|
+
'http_request' : ActorMethod<[HttpRequest], HttpResponse>,
|
|
106
|
+
'http_request_streaming_callback' : ActorMethod<
|
|
107
|
+
[StreamingCallbackToken],
|
|
108
|
+
StreamingCallbackHttpResponse
|
|
109
|
+
>,
|
|
110
|
+
'list_assets' : ActorMethod<[], Array<AssetInfo>>,
|
|
111
|
+
'reserve_render' : ActorMethod<[ReserveRenderArgs], ReserveTranscodingUpload>,
|
|
112
|
+
'reserve_transcoding_upload' : ActorMethod<
|
|
113
|
+
[ReserveTranscodingUploadArgs],
|
|
114
|
+
ReserveTranscodingUpload
|
|
115
|
+
>,
|
|
116
|
+
'run_reservation_sweep' : ActorMethod<[bigint], number>,
|
|
117
|
+
'set_core_canister' : ActorMethod<[Principal], boolean>,
|
|
118
|
+
'set_workers' : ActorMethod<[Array<WorkerEntry>], boolean>,
|
|
119
|
+
'start_upload' : ActorMethod<[StartUploadArgs], string>,
|
|
120
|
+
'system_start_upload' : ActorMethod<[SystemStartUploadArgs], string>,
|
|
121
|
+
'upload_asset' : ActorMethod<[UploadArgs], string>,
|
|
122
|
+
'upload_chunk' : ActorMethod<
|
|
123
|
+
[string, number, Uint8Array | number[]],
|
|
124
|
+
undefined
|
|
125
|
+
>,
|
|
126
|
+
'upload_image' : ActorMethod<[UploadImageArgs], string>,
|
|
127
|
+
}
|
|
128
|
+
export declare const idlFactory: IDL.InterfaceFactory;
|
|
129
|
+
export declare const init: (args: { IDL: typeof IDL }) => IDL.Type[];
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
export const idlFactory = ({ IDL }) => {
|
|
2
|
+
const DeleteSalonAssetArgs = IDL.Record({
|
|
3
|
+
'id' : IDL.Text,
|
|
4
|
+
'salonId' : IDL.Text,
|
|
5
|
+
});
|
|
6
|
+
const FailSystemUploadArgs = IDL.Record({
|
|
7
|
+
'id' : IDL.Text,
|
|
8
|
+
'reason' : IDL.Text,
|
|
9
|
+
});
|
|
10
|
+
const FinishSystemUploadArgs = IDL.Record({
|
|
11
|
+
'id' : IDL.Text,
|
|
12
|
+
'posterId' : IDL.Opt(IDL.Text),
|
|
13
|
+
});
|
|
14
|
+
const AssetInfo = IDL.Record({
|
|
15
|
+
'id' : IDL.Text,
|
|
16
|
+
'contentType' : IDL.Text,
|
|
17
|
+
'name' : IDL.Text,
|
|
18
|
+
'totalSize' : IDL.Nat64,
|
|
19
|
+
'chunkCount' : IDL.Nat32,
|
|
20
|
+
'uploadedAt' : IDL.Int64,
|
|
21
|
+
});
|
|
22
|
+
const WorkerEntry = IDL.Record({
|
|
23
|
+
'url' : IDL.Text,
|
|
24
|
+
'principal' : IDL.Principal,
|
|
25
|
+
});
|
|
26
|
+
const HttpRequest = IDL.Record({
|
|
27
|
+
'url' : IDL.Text,
|
|
28
|
+
'method' : IDL.Text,
|
|
29
|
+
'body' : IDL.Vec(IDL.Nat8),
|
|
30
|
+
'headers' : IDL.Vec(IDL.Tuple(IDL.Text, IDL.Text)),
|
|
31
|
+
});
|
|
32
|
+
const StreamingCallbackToken = IDL.Record({
|
|
33
|
+
'key' : IDL.Text,
|
|
34
|
+
'sha256' : IDL.Opt(IDL.Vec(IDL.Nat8)),
|
|
35
|
+
'index' : IDL.Nat32,
|
|
36
|
+
'contentEncoding' : IDL.Text,
|
|
37
|
+
});
|
|
38
|
+
const StreamingCallbackHttpResponse = IDL.Record({
|
|
39
|
+
'token' : IDL.Opt(StreamingCallbackToken),
|
|
40
|
+
'body' : IDL.Vec(IDL.Nat8),
|
|
41
|
+
});
|
|
42
|
+
const StreamingStrategy = IDL.Variant({
|
|
43
|
+
'Callback' : IDL.Record({
|
|
44
|
+
'token' : StreamingCallbackToken,
|
|
45
|
+
'callback' : IDL.Func(
|
|
46
|
+
[StreamingCallbackToken],
|
|
47
|
+
[StreamingCallbackHttpResponse],
|
|
48
|
+
['query'],
|
|
49
|
+
),
|
|
50
|
+
}),
|
|
51
|
+
});
|
|
52
|
+
const HttpResponse = IDL.Record({
|
|
53
|
+
'body' : IDL.Vec(IDL.Nat8),
|
|
54
|
+
'headers' : IDL.Vec(IDL.Tuple(IDL.Text, IDL.Text)),
|
|
55
|
+
'upgrade' : IDL.Opt(IDL.Bool),
|
|
56
|
+
'streaming_strategy' : IDL.Opt(StreamingStrategy),
|
|
57
|
+
'status_code' : IDL.Nat16,
|
|
58
|
+
});
|
|
59
|
+
const RenderMode = IDL.Variant({ 'Mix' : IDL.Null, 'Replace' : IDL.Null });
|
|
60
|
+
const ReserveRenderArgs = IDL.Record({
|
|
61
|
+
'slideDurationSec' : IDL.Opt(IDL.Nat16),
|
|
62
|
+
'musicStartSec' : IDL.Opt(IDL.Nat32),
|
|
63
|
+
'audioAssetId' : IDL.Text,
|
|
64
|
+
'mode' : RenderMode,
|
|
65
|
+
'name' : IDL.Opt(IDL.Text),
|
|
66
|
+
'sourceAssetId' : IDL.Text,
|
|
67
|
+
'musicVolumePct' : IDL.Nat8,
|
|
68
|
+
'salonId' : IDL.Text,
|
|
69
|
+
});
|
|
70
|
+
const ReserveTranscodingUpload = IDL.Record({
|
|
71
|
+
'id' : IDL.Text,
|
|
72
|
+
'uploadUrls' : IDL.Vec(IDL.Text),
|
|
73
|
+
});
|
|
74
|
+
const TranscodingKind = IDL.Variant({
|
|
75
|
+
'Audio' : IDL.Null,
|
|
76
|
+
'Video' : IDL.Null,
|
|
77
|
+
});
|
|
78
|
+
const ReserveTranscodingUploadArgs = IDL.Record({
|
|
79
|
+
'kind' : IDL.Opt(TranscodingKind),
|
|
80
|
+
'name' : IDL.Opt(IDL.Text),
|
|
81
|
+
'salonId' : IDL.Text,
|
|
82
|
+
});
|
|
83
|
+
const StartUploadArgs = IDL.Record({
|
|
84
|
+
'contentType' : IDL.Text,
|
|
85
|
+
'name' : IDL.Text,
|
|
86
|
+
'totalChunks' : IDL.Nat32,
|
|
87
|
+
});
|
|
88
|
+
const SystemStartUploadArgs = IDL.Record({
|
|
89
|
+
'id' : IDL.Text,
|
|
90
|
+
'contentType' : IDL.Text,
|
|
91
|
+
'name' : IDL.Text,
|
|
92
|
+
'totalChunks' : IDL.Nat32,
|
|
93
|
+
});
|
|
94
|
+
const UploadArgs = IDL.Record({
|
|
95
|
+
'contentType' : IDL.Text,
|
|
96
|
+
'data' : IDL.Vec(IDL.Nat8),
|
|
97
|
+
'name' : IDL.Text,
|
|
98
|
+
});
|
|
99
|
+
const UploadImageArgs = IDL.Record({
|
|
100
|
+
'contentType' : IDL.Text,
|
|
101
|
+
'data' : IDL.Vec(IDL.Nat8),
|
|
102
|
+
'name' : IDL.Text,
|
|
103
|
+
'targetSalonServiceId' : IDL.Opt(IDL.Text),
|
|
104
|
+
'salonId' : IDL.Text,
|
|
105
|
+
});
|
|
106
|
+
return IDL.Service({
|
|
107
|
+
'abort_upload' : IDL.Func([IDL.Text], [IDL.Bool], []),
|
|
108
|
+
'delete_asset' : IDL.Func([IDL.Text], [IDL.Bool], []),
|
|
109
|
+
'delete_salon_asset' : IDL.Func([DeleteSalonAssetArgs], [IDL.Bool], []),
|
|
110
|
+
'fail_system_upload' : IDL.Func([FailSystemUploadArgs], [IDL.Bool], []),
|
|
111
|
+
'finish_system_upload' : IDL.Func([FinishSystemUploadArgs], [IDL.Text], []),
|
|
112
|
+
'finish_upload' : IDL.Func([IDL.Text], [IDL.Text], []),
|
|
113
|
+
'get_asset_info' : IDL.Func([IDL.Text], [IDL.Opt(AssetInfo)], ['query']),
|
|
114
|
+
'get_core_canister' : IDL.Func([], [IDL.Opt(IDL.Principal)], ['query']),
|
|
115
|
+
'get_workers' : IDL.Func([], [IDL.Vec(WorkerEntry)], ['query']),
|
|
116
|
+
'http_request' : IDL.Func([HttpRequest], [HttpResponse], ['query']),
|
|
117
|
+
'http_request_streaming_callback' : IDL.Func(
|
|
118
|
+
[StreamingCallbackToken],
|
|
119
|
+
[StreamingCallbackHttpResponse],
|
|
120
|
+
['query'],
|
|
121
|
+
),
|
|
122
|
+
'list_assets' : IDL.Func([], [IDL.Vec(AssetInfo)], ['query']),
|
|
123
|
+
'reserve_render' : IDL.Func(
|
|
124
|
+
[ReserveRenderArgs],
|
|
125
|
+
[ReserveTranscodingUpload],
|
|
126
|
+
[],
|
|
127
|
+
),
|
|
128
|
+
'reserve_transcoding_upload' : IDL.Func(
|
|
129
|
+
[ReserveTranscodingUploadArgs],
|
|
130
|
+
[ReserveTranscodingUpload],
|
|
131
|
+
[],
|
|
132
|
+
),
|
|
133
|
+
'run_reservation_sweep' : IDL.Func([IDL.Nat64], [IDL.Nat32], []),
|
|
134
|
+
'set_core_canister' : IDL.Func([IDL.Principal], [IDL.Bool], []),
|
|
135
|
+
'set_workers' : IDL.Func([IDL.Vec(WorkerEntry)], [IDL.Bool], []),
|
|
136
|
+
'start_upload' : IDL.Func([StartUploadArgs], [IDL.Text], []),
|
|
137
|
+
'system_start_upload' : IDL.Func([SystemStartUploadArgs], [IDL.Text], []),
|
|
138
|
+
'upload_asset' : IDL.Func([UploadArgs], [IDL.Text], []),
|
|
139
|
+
'upload_chunk' : IDL.Func([IDL.Text, IDL.Nat32, IDL.Vec(IDL.Nat8)], [], []),
|
|
140
|
+
'upload_image' : IDL.Func([UploadImageArgs], [IDL.Text], []),
|
|
141
|
+
});
|
|
142
|
+
};
|
|
143
|
+
export const init = ({ IDL }) => { return []; };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type ActorSubclass, HttpAgent, type Identity } from "@icp-sdk/core/agent";
|
|
2
|
+
import type { _SERVICE } from "../declarations/sultana-assets-rust/sultana-assets-rust.did.js";
|
|
3
|
+
/** The `cause` of a `CanisterError` thrown by this package — the canister trapped. */
|
|
4
|
+
export interface TrapCause {
|
|
5
|
+
/** Always "Trap": sultana-assets-rust has no error variants, every refusal is a trap. */
|
|
6
|
+
errorKey: "Trap";
|
|
7
|
+
/** The text the canister trapped with, e.g. "caller is not the upload owner". */
|
|
8
|
+
errorMessage: string;
|
|
9
|
+
/** The agent's error, untouched. */
|
|
10
|
+
rawError: unknown;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Base class for every per-domain actor wrapper (AssetsRustUploadsActor, …). Builds the
|
|
14
|
+
* HttpAgent + raw candid actor and owns the single choke point that turns the agent's
|
|
15
|
+
* failures into the three errors every wrapper package throws:
|
|
16
|
+
* - a trap is thrown as `Error("CanisterError", { cause: {errorKey: "Trap", errorMessage, rawError} })`
|
|
17
|
+
* — sultana-assets-rust returns no Framework.Result, it returns the value or traps;
|
|
18
|
+
* - an inspect-stage rejection is thrown as `Error("CallRefusedAtInspectionStage")`;
|
|
19
|
+
* - any other failure (unreachable canister, out of cycles, bad reply) is thrown as
|
|
20
|
+
* `Error("CriticalCanisterError", { cause: {logs: null, rawError} })`.
|
|
21
|
+
*/
|
|
22
|
+
export declare class ActorBase {
|
|
23
|
+
protected canisterId: string;
|
|
24
|
+
protected identity?: Identity | undefined;
|
|
25
|
+
protected host: string;
|
|
26
|
+
protected actor: ActorSubclass<_SERVICE>;
|
|
27
|
+
protected agent: HttpAgent;
|
|
28
|
+
/**
|
|
29
|
+
* @param canisterId - The sultana-assets-rust canister to talk to.
|
|
30
|
+
* @param identity - The caller; left out = anonymous (enough for the reads).
|
|
31
|
+
* @param host - The IC API host; default https://icp0.io.
|
|
32
|
+
*/
|
|
33
|
+
constructor(canisterId: string, identity?: Identity | undefined, host?: string);
|
|
34
|
+
private initAgentAndActor;
|
|
35
|
+
/**
|
|
36
|
+
* Rebuilds the HttpAgent and the actor from scratch — for long-lived consumers after a
|
|
37
|
+
* streak of failed calls, where a stale agent/connection is the usual suspect. Safe to
|
|
38
|
+
* call at any time.
|
|
39
|
+
*/
|
|
40
|
+
reinitializeAgent(): void;
|
|
41
|
+
/** Runs one canister call and translates its failure (see the class comment). */
|
|
42
|
+
protected executeFunctionAsyncUnsafe<T>(fnAsync: () => Promise<T>): Promise<T>;
|
|
43
|
+
protected isInspectionRejection(error: any): boolean;
|
|
44
|
+
protected extractTrapMessage(error: any): string | null;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=actor-base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actor-base.d.ts","sourceRoot":"","sources":["../src/actor-base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,SAAS,EAAE,KAAK,QAAQ,EAAS,MAAM,qBAAqB,CAAC;AAE1F,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gEAAgE,CAAC;AAG/F,sFAAsF;AACtF,MAAM,WAAW,SAAS;IACtB,yFAAyF;IACzF,QAAQ,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,YAAY,EAAE,MAAM,CAAC;IACrB,oCAAoC;IACpC,QAAQ,EAAE,OAAO,CAAC;CACrB;AAKD;;;;;;;;;GASG;AACH,qBAAa,SAAS;IASN,SAAS,CAAC,UAAU,EAAE,MAAM;IAAE,SAAS,CAAC,QAAQ,CAAC,EAAE,QAAQ;IAAE,SAAS,CAAC,IAAI,EAAE,MAAM;IAR/F,SAAS,CAAC,KAAK,EAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC1C,SAAS,CAAC,KAAK,EAAG,SAAS,CAAC;IAE5B;;;;OAIG;gBACmB,UAAU,EAAE,MAAM,EAAY,QAAQ,CAAC,EAAE,QAAQ,YAAA,EAAY,IAAI,GAAE,MAAqB;IAI9G,OAAO,CAAC,iBAAiB;IAWzB;;;;OAIG;IACI,iBAAiB,IAAI,IAAI;IAIhC,iFAAiF;cACjE,0BAA0B,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAqBpF,SAAS,CAAC,qBAAqB,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO;IASpD,SAAS,CAAC,kBAAkB,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM,GAAG,IAAI;CAU1D"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { HttpAgent, Actor } from "@icp-sdk/core/agent";
|
|
2
|
+
import { idlFactory } from "../declarations/sultana-assets-rust/sultana-assets-rust.did.js";
|
|
3
|
+
import { DEFAULT_HOST } from "./constants.js";
|
|
4
|
+
// IC error code of an explicit trap (ic0.trap — every ic_cdk::trap and every Rust panic).
|
|
5
|
+
const TRAP_ERROR_CODE = "IC0503";
|
|
6
|
+
/**
|
|
7
|
+
* Base class for every per-domain actor wrapper (AssetsRustUploadsActor, …). Builds the
|
|
8
|
+
* HttpAgent + raw candid actor and owns the single choke point that turns the agent's
|
|
9
|
+
* failures into the three errors every wrapper package throws:
|
|
10
|
+
* - a trap is thrown as `Error("CanisterError", { cause: {errorKey: "Trap", errorMessage, rawError} })`
|
|
11
|
+
* — sultana-assets-rust returns no Framework.Result, it returns the value or traps;
|
|
12
|
+
* - an inspect-stage rejection is thrown as `Error("CallRefusedAtInspectionStage")`;
|
|
13
|
+
* - any other failure (unreachable canister, out of cycles, bad reply) is thrown as
|
|
14
|
+
* `Error("CriticalCanisterError", { cause: {logs: null, rawError} })`.
|
|
15
|
+
*/
|
|
16
|
+
export class ActorBase {
|
|
17
|
+
canisterId;
|
|
18
|
+
identity;
|
|
19
|
+
host;
|
|
20
|
+
actor;
|
|
21
|
+
agent;
|
|
22
|
+
/**
|
|
23
|
+
* @param canisterId - The sultana-assets-rust canister to talk to.
|
|
24
|
+
* @param identity - The caller; left out = anonymous (enough for the reads).
|
|
25
|
+
* @param host - The IC API host; default https://icp0.io.
|
|
26
|
+
*/
|
|
27
|
+
constructor(canisterId, identity, host = DEFAULT_HOST) {
|
|
28
|
+
this.canisterId = canisterId;
|
|
29
|
+
this.identity = identity;
|
|
30
|
+
this.host = host;
|
|
31
|
+
this.initAgentAndActor();
|
|
32
|
+
}
|
|
33
|
+
initAgentAndActor() {
|
|
34
|
+
this.agent = HttpAgent.createSync({
|
|
35
|
+
host: this.host,
|
|
36
|
+
identity: this.identity,
|
|
37
|
+
});
|
|
38
|
+
this.actor = Actor.createActor(idlFactory, {
|
|
39
|
+
agent: this.agent,
|
|
40
|
+
canisterId: this.canisterId,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Rebuilds the HttpAgent and the actor from scratch — for long-lived consumers after a
|
|
45
|
+
* streak of failed calls, where a stale agent/connection is the usual suspect. Safe to
|
|
46
|
+
* call at any time.
|
|
47
|
+
*/
|
|
48
|
+
reinitializeAgent() {
|
|
49
|
+
this.initAgentAndActor();
|
|
50
|
+
}
|
|
51
|
+
/** Runs one canister call and translates its failure (see the class comment). */
|
|
52
|
+
async executeFunctionAsyncUnsafe(fnAsync) {
|
|
53
|
+
try {
|
|
54
|
+
return await fnAsync();
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
if (this.isInspectionRejection(err)) {
|
|
58
|
+
throw new Error("CallRefusedAtInspectionStage", { cause: err });
|
|
59
|
+
}
|
|
60
|
+
const trapMessage = this.extractTrapMessage(err);
|
|
61
|
+
if (trapMessage !== null) {
|
|
62
|
+
const cause = { errorKey: "Trap", errorMessage: trapMessage, rawError: err };
|
|
63
|
+
throw new Error("CanisterError", { cause });
|
|
64
|
+
}
|
|
65
|
+
throw new Error("CriticalCanisterError", { cause: { logs: null, rawError: err } });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// True if `error` is an IC reject caused by an inspect-stage refusal. sultana-assets-rust
|
|
69
|
+
// has no inspect_message today; kept so the error vocabulary stays the same as in the
|
|
70
|
+
// other wrapper packages. When the canister gets one, check the text it produces.
|
|
71
|
+
isInspectionRejection(error) {
|
|
72
|
+
const rejectText = error?.cause?.code?.rejectMessage || error?.message || "";
|
|
73
|
+
return rejectText.includes("canister_inspect_message explicitly refused message");
|
|
74
|
+
}
|
|
75
|
+
// The trap text when `error` is a trap of the canister, otherwise null. The replica
|
|
76
|
+
// reports it as "... Canister called `ic0.trap` with message: '<text>'.\nConsider ...";
|
|
77
|
+
// when the text cannot be cut out, the whole reject message is returned.
|
|
78
|
+
extractTrapMessage(error) {
|
|
79
|
+
const code = error?.cause?.code;
|
|
80
|
+
const rejectMessage = typeof code?.rejectMessage === "string" ? code.rejectMessage : "";
|
|
81
|
+
const isTrap = code?.rejectErrorCode === TRAP_ERROR_CODE || rejectMessage.includes("ic0.trap") || rejectMessage.includes("trapped explicitly");
|
|
82
|
+
if (!rejectMessage || !isTrap)
|
|
83
|
+
return null;
|
|
84
|
+
const match = rejectMessage.match(/with message: '([\s\S]*)'\./);
|
|
85
|
+
return match ? match[1] : rejectMessage;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { ActorBase } from "../actor-base.js";
|
|
2
|
+
import type { WorkerView } from "../interfaces.js";
|
|
3
|
+
/**
|
|
4
|
+
* Administration of sultana-assets-rust. There is no admin identity on this canister:
|
|
5
|
+
* administration goes THROUGH sultana-core-motoko — core's superadmin calls proxy endpoints
|
|
6
|
+
* on core (setAssetWorkers, deleteAssetRaw) and core forwards them here. The core-only
|
|
7
|
+
* methods below therefore answer `false` (or trap) for every caller but the configured core
|
|
8
|
+
* canister; they are here for wiring scripts, tests and diagnosis.
|
|
9
|
+
*/
|
|
10
|
+
export declare class AssetsRustAdminActor extends ActorBase {
|
|
11
|
+
/**
|
|
12
|
+
* Claim-once bootstrap: while no core canister is configured anyone may set it (call it
|
|
13
|
+
* right after a deploy); afterwards only the current core canister may re-point it.
|
|
14
|
+
* @param corePrincipal - The sultana-core-motoko canister this canister trusts.
|
|
15
|
+
* @returns A Promise that resolves to `true` when set, `false` when the seat is taken by
|
|
16
|
+
* another principal than the caller.
|
|
17
|
+
* @throws CanisterError - The canister trapped.
|
|
18
|
+
* @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
|
|
19
|
+
* @throws CriticalCanisterError - Transport failure or an unreachable canister.
|
|
20
|
+
*/
|
|
21
|
+
setCoreCanisterAsyncUnsafe(corePrincipal: string): Promise<boolean>;
|
|
22
|
+
/**
|
|
23
|
+
* @returns A Promise that resolves to the trusted core canister, or `null` when none is
|
|
24
|
+
* configured yet (a fresh deploy).
|
|
25
|
+
* @throws CanisterError - The canister trapped.
|
|
26
|
+
* @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
|
|
27
|
+
* @throws CriticalCanisterError - Transport failure or an unreachable canister.
|
|
28
|
+
*/
|
|
29
|
+
getCoreCanisterAsyncUnsafe(): Promise<string | null>;
|
|
30
|
+
/**
|
|
31
|
+
* Core-canister only: replaces the transcoding-worker list. The real path is core's
|
|
32
|
+
* superadmin proxy (sultana-core-motoko-package `AdminActor.setAssetWorkersAsyncUnsafe`).
|
|
33
|
+
* @param workers - Each worker's identity and its FULL upload-endpoint URL.
|
|
34
|
+
* @returns A Promise that resolves to `true` when replaced, `false` when the caller is
|
|
35
|
+
* not the core canister.
|
|
36
|
+
* @throws CanisterError - The canister trapped.
|
|
37
|
+
* @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
|
|
38
|
+
* @throws CriticalCanisterError - Transport failure or an unreachable canister.
|
|
39
|
+
*/
|
|
40
|
+
setWorkersAsyncUnsafe(workers: WorkerView[]): Promise<boolean>;
|
|
41
|
+
/**
|
|
42
|
+
* @returns A Promise that resolves to the configured transcoding workers (empty on a
|
|
43
|
+
* fresh deploy).
|
|
44
|
+
* @throws CanisterError - The canister trapped.
|
|
45
|
+
* @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
|
|
46
|
+
* @throws CriticalCanisterError - Transport failure or an unreachable canister.
|
|
47
|
+
*/
|
|
48
|
+
getWorkersAsyncUnsafe(): Promise<WorkerView[]>;
|
|
49
|
+
/**
|
|
50
|
+
* Core-canister only: raw removal of an asset's bytes (and its thumb or poster) with no
|
|
51
|
+
* core deregister — cleanup of orphaned bytes. The real path is core's superadmin proxy
|
|
52
|
+
* `deleteAssetRaw`.
|
|
53
|
+
* @param assetId - The asset to remove.
|
|
54
|
+
* @returns A Promise that resolves to `true` when removed, `false` when the caller is not
|
|
55
|
+
* the core canister or the asset does not exist.
|
|
56
|
+
* @throws CanisterError - The canister trapped.
|
|
57
|
+
* @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
|
|
58
|
+
* @throws CriticalCanisterError - Transport failure or an unreachable canister.
|
|
59
|
+
*/
|
|
60
|
+
deleteAssetAsyncUnsafe(assetId: string): Promise<boolean>;
|
|
61
|
+
/**
|
|
62
|
+
* Core-canister only: runs the stale-reservation sweep now (the canister also runs it
|
|
63
|
+
* every hour). Reservations older than `ttlMs` are marked failed in core and dropped.
|
|
64
|
+
* @param ttlMs - Age in milliseconds after which a reservation counts as stale.
|
|
65
|
+
* @returns A Promise that resolves to the number of reservations swept.
|
|
66
|
+
* @throws CanisterError - The canister trapped: "caller is not the core canister".
|
|
67
|
+
* @throws CallRefusedAtInspectionStage - The call was refused at the inspect stage.
|
|
68
|
+
* @throws CriticalCanisterError - Transport failure or an unreachable canister.
|
|
69
|
+
*/
|
|
70
|
+
runReservationSweepAsyncUnsafe(ttlMs: number): Promise<number>;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=admin-actor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-actor.d.ts","sourceRoot":"","sources":["../../src/actors/admin-actor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD;;;;;;GAMG;AACH,qBAAa,oBAAqB,SAAQ,SAAS;IAC/C;;;;;;;;;OASG;IACU,0BAA0B,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIhF;;;;;;OAMG;IACU,0BAA0B,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAKjE;;;;;;;;;OASG;IACU,qBAAqB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAI3E;;;;;;OAMG;IACU,qBAAqB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAK3D;;;;;;;;;;OAUG;IACU,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAItE;;;;;;;;OAQG;IACU,8BAA8B,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAG9E"}
|