@hailer/app-sdk 2.13.0 → 2.15.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 +6 -5
- package/lib/app-sdk.js +2 -2
- package/lib/app-sdk.js.map +4 -4
- package/lib/hailer-api.d.ts +3 -0
- package/lib/index.d.ts +1 -0
- package/lib/modules/action.d.ts +22 -0
- package/lib/modules/file.d.ts +137 -1
- package/lib/modules/permission.d.ts +1 -1
- package/lib/types.d.ts +36 -0
- package/package.json +1 -1
package/lib/hailer-api.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ import { Admin } from './modules/admin';
|
|
|
16
16
|
import { MetricsApi } from './modules/metrics';
|
|
17
17
|
import { HttpApi } from './modules/http';
|
|
18
18
|
import { CredentialApi } from './modules/credential';
|
|
19
|
+
import { ActionApi } from './modules/action';
|
|
19
20
|
export interface Options {
|
|
20
21
|
/** When connected is called the host is ready to receive calls */
|
|
21
22
|
connected?: () => void;
|
|
@@ -55,6 +56,8 @@ export declare class HailerApi {
|
|
|
55
56
|
http: HttpApi;
|
|
56
57
|
/** Securely store and retrieve credentials (API keys, username/password pairs, etc.) */
|
|
57
58
|
credential: CredentialApi;
|
|
59
|
+
/** Trigger workspace actions and read back their runs */
|
|
60
|
+
action: ActionApi;
|
|
58
61
|
/** All public endpoints, which can be accessed while not logged in to Hailer. */
|
|
59
62
|
public: HailerPublicApi;
|
|
60
63
|
/** User interface commands */
|
package/lib/index.d.ts
CHANGED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Client } from '@wishcore/wish-rpc';
|
|
2
|
+
import { ActionRun, ActionTriggerTarget } from '../types';
|
|
3
|
+
export declare class ActionApi {
|
|
4
|
+
private client;
|
|
5
|
+
constructor(client: Client);
|
|
6
|
+
/**
|
|
7
|
+
* Triggers an action. Waits up to 25 s; a longer run is returned still
|
|
8
|
+
* in progress and must be polled with `getRun`.
|
|
9
|
+
*
|
|
10
|
+
* @param target one of `actionId` or `key`, plus optional `workspaceId` (defaults to the app's workspace)
|
|
11
|
+
* @param input delivered as the payload of a `manual` event
|
|
12
|
+
*
|
|
13
|
+
* @throws {HailerError} if the action is not found or the user may not trigger it
|
|
14
|
+
*/
|
|
15
|
+
trigger(target: ActionTriggerTarget, input?: unknown): Promise<ActionRun>;
|
|
16
|
+
/**
|
|
17
|
+
* Gets one run. Non-admins can only read runs they triggered.
|
|
18
|
+
*
|
|
19
|
+
* @throws {HailerError} if the run is not found or the user may not read it
|
|
20
|
+
*/
|
|
21
|
+
getRun(runId: string): Promise<ActionRun>;
|
|
22
|
+
}
|
package/lib/modules/file.d.ts
CHANGED
|
@@ -10,9 +10,74 @@ export interface FileResponse {
|
|
|
10
10
|
export interface UploadOptions {
|
|
11
11
|
/** Whether the file should be publicly accessible */
|
|
12
12
|
isPublic?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Scope the file to the app's workspace (irreversible). A scoped file is readable only by its owner,
|
|
15
|
+
* workspace admins and its readers; set readers with `setReaders`. Cannot be combined with `isPublic`,
|
|
16
|
+
* and not available to guests. This is the only way to scope a file.
|
|
17
|
+
*/
|
|
18
|
+
scoped?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/** Owner, workspace and readers of a file. `workspaceId` and `readers` are absent for an unscoped file. */
|
|
21
|
+
export interface FileScope {
|
|
22
|
+
_id: string;
|
|
23
|
+
/** Owner of the file */
|
|
24
|
+
uid: string;
|
|
25
|
+
/** Workspace the file is scoped to */
|
|
26
|
+
workspaceId?: string;
|
|
27
|
+
/** Reader entries, see `FileApi.readers` */
|
|
28
|
+
readers?: string[];
|
|
29
|
+
}
|
|
30
|
+
export interface FileListOptions {
|
|
31
|
+
/** One keyword or up to 20. A keyword matches a case-insensitive substring of the file name or of any tag. */
|
|
32
|
+
search?: string | string[];
|
|
33
|
+
/** `all` (default) requires every keyword to match, `any` at least one */
|
|
34
|
+
matchType?: 'all' | 'any';
|
|
35
|
+
skip?: number;
|
|
36
|
+
/** 1-100, default 100 */
|
|
37
|
+
limit?: number;
|
|
38
|
+
sortBy?: 'name' | 'created';
|
|
39
|
+
reverse?: boolean;
|
|
13
40
|
}
|
|
41
|
+
export interface ScopedFile {
|
|
42
|
+
_id: string;
|
|
43
|
+
name: string;
|
|
44
|
+
/** Owner of the file */
|
|
45
|
+
uid: string;
|
|
46
|
+
workspaceId: string;
|
|
47
|
+
type?: string;
|
|
48
|
+
length?: number;
|
|
49
|
+
created?: number;
|
|
50
|
+
updated?: number;
|
|
51
|
+
tags?: string[];
|
|
52
|
+
}
|
|
53
|
+
export interface FileListResponse {
|
|
54
|
+
files: ScopedFile[];
|
|
55
|
+
hasMore: boolean;
|
|
56
|
+
total: number;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Builders for `setReaders` entries. Only full members of the app's workspace ever match a reader:
|
|
60
|
+
* guests never do, not even through a team or a `user_` entry.
|
|
61
|
+
*/
|
|
62
|
+
export declare const fileReaders: {
|
|
63
|
+
/** Every full member of the workspace */
|
|
64
|
+
workspace: (workspaceId: string) => string;
|
|
65
|
+
/** The full members of a team; guests in the team are skipped */
|
|
66
|
+
team: (teamId: string) => string;
|
|
67
|
+
/** A single full member; a guest is rejected */
|
|
68
|
+
user: (userId: string) => string;
|
|
69
|
+
};
|
|
14
70
|
export declare class FileApi {
|
|
15
71
|
private client;
|
|
72
|
+
/** Builders for `setReaders` entries: `readers.workspace(id)`, `readers.team(id)`, `readers.user(id)` */
|
|
73
|
+
readonly readers: {
|
|
74
|
+
/** Every full member of the workspace */
|
|
75
|
+
workspace: (workspaceId: string) => string;
|
|
76
|
+
/** The full members of a team; guests in the team are skipped */
|
|
77
|
+
team: (teamId: string) => string;
|
|
78
|
+
/** A single full member; a guest is rejected */
|
|
79
|
+
user: (userId: string) => string;
|
|
80
|
+
};
|
|
16
81
|
constructor(client: Client);
|
|
17
82
|
/**
|
|
18
83
|
* Gets a file by ID and returns it as base64 data
|
|
@@ -39,7 +104,8 @@ export declare class FileApi {
|
|
|
39
104
|
/**
|
|
40
105
|
* Appends tags to a file, deduping against the existing list.
|
|
41
106
|
*
|
|
42
|
-
* Tags are case-sensitive free-form strings (trimmed, 1-64 characters, max 50 per file).
|
|
107
|
+
* Tags are case-sensitive free-form strings (trimmed, 1-64 characters, max 50 per file). On a scoped
|
|
108
|
+
* file only its owner or a workspace admin may change tags; readers can read them but not edit.
|
|
43
109
|
*
|
|
44
110
|
* @param fileId The ID of the file to tag
|
|
45
111
|
* @param tags Tags to add
|
|
@@ -51,6 +117,7 @@ export declare class FileApi {
|
|
|
51
117
|
addTags(fileId: string, tags: string[]): Promise<string[]>;
|
|
52
118
|
/**
|
|
53
119
|
* Removes tags from a file by case-sensitive exact match. Tags not present are silently ignored.
|
|
120
|
+
* On a scoped file only its owner or a workspace admin may change tags.
|
|
54
121
|
*
|
|
55
122
|
* @param fileId The ID of the file to untag
|
|
56
123
|
* @param tags Tags to remove
|
|
@@ -60,5 +127,74 @@ export declare class FileApi {
|
|
|
60
127
|
* @throws {HailerError} if validation fails or the file cannot be edited
|
|
61
128
|
*/
|
|
62
129
|
removeTags(fileId: string, tags: string[]): Promise<string[]>;
|
|
130
|
+
/**
|
|
131
|
+
* Gets the owner, workspace and readers of a file you can read. Use it as an "is this file scoped?"
|
|
132
|
+
* probe: `workspaceId` is absent for an unscoped file.
|
|
133
|
+
*
|
|
134
|
+
* @param fileId The ID of the file
|
|
135
|
+
*
|
|
136
|
+
* @throws {HailerError} if the file does not exist or you cannot read it (guests cannot read scoped
|
|
137
|
+
* files), or if it is scoped to a workspace other than the app's (403)
|
|
138
|
+
*/
|
|
139
|
+
getScope(fileId: string): Promise<FileScope>;
|
|
140
|
+
/**
|
|
141
|
+
* Replaces the readers of a file scoped to the app's workspace. Files are scoped only at upload
|
|
142
|
+
* (`upload(..., { scoped: true })`); an unscoped file is refused (403) rather than scoped here.
|
|
143
|
+
*
|
|
144
|
+
* Requires being the file's owner (while a full member) or a workspace admin; not available to guests.
|
|
145
|
+
* A non-admin may only add teams they belong to. Every entry must belong to the app's workspace, and
|
|
146
|
+
* `user_` must name a full member, not a guest.
|
|
147
|
+
*
|
|
148
|
+
* @param fileId The ID of the file
|
|
149
|
+
* @param readers The complete new reader list (max 100); build entries with `readers.*`. Send `[]` to
|
|
150
|
+
* leave only the owner and workspace admins.
|
|
151
|
+
*
|
|
152
|
+
* @returns The resulting scope
|
|
153
|
+
*
|
|
154
|
+
* @throws {HailerError} if validation fails, the file is not scoped to the app's workspace, or you may
|
|
155
|
+
* not manage it
|
|
156
|
+
*/
|
|
157
|
+
setReaders(fileId: string, readers: string[]): Promise<FileScope>;
|
|
158
|
+
/**
|
|
159
|
+
* Lists the scoped files of the app's workspace that the user can read: their own, those they are a
|
|
160
|
+
* reader of, or all of them for a workspace admin. Unscoped files are not listed.
|
|
161
|
+
*
|
|
162
|
+
* @param options Search by name/tags and paging
|
|
163
|
+
*
|
|
164
|
+
* @returns A page of files, whether more exist, and the total match count
|
|
165
|
+
*
|
|
166
|
+
* @throws {HailerError} if validation fails, or for a guest
|
|
167
|
+
*/
|
|
168
|
+
list(options?: FileListOptions): Promise<FileListResponse>;
|
|
169
|
+
/**
|
|
170
|
+
* Transfers a file scoped to the app's workspace to another full member of it (not a guest). Workspace
|
|
171
|
+
* admins only. The previous owner loses access unless they are a reader.
|
|
172
|
+
*
|
|
173
|
+
* @param fileId The ID of the file
|
|
174
|
+
* @param userId The new owner
|
|
175
|
+
*
|
|
176
|
+
* @throws {HailerError} if you are not a workspace admin, the file is not scoped to the app's workspace,
|
|
177
|
+
* or the user is not a full member
|
|
178
|
+
*/
|
|
179
|
+
setOwner(fileId: string, userId: string): Promise<boolean>;
|
|
180
|
+
/**
|
|
181
|
+
* Permanently deletes files scoped to the app's workspace that you own. Ids of files owned by someone
|
|
182
|
+
* else are skipped without an error, even for a workspace admin; re-list to see what is left. If any id
|
|
183
|
+
* is not a file scoped to the app's workspace, the whole call is refused (403) and nothing is removed:
|
|
184
|
+
* an app can never delete the user's other files.
|
|
185
|
+
*
|
|
186
|
+
* @param fileIds 1-100 file ids
|
|
187
|
+
*
|
|
188
|
+
* @returns `true` once the request is processed
|
|
189
|
+
*
|
|
190
|
+
* @throws {HailerError} if validation fails, or any file is not scoped to the app's workspace
|
|
191
|
+
*/
|
|
192
|
+
remove(fileIds: string[]): Promise<boolean>;
|
|
193
|
+
/**
|
|
194
|
+
* An older Hailer ignores the `scoped` upload argument and stores the file unscoped. Fail loudly rather
|
|
195
|
+
* than hand back a file the app believes is restricted. Only a missing `file.getScope` (wish-rpc code
|
|
196
|
+
* 300) or an unscoped result means an older Hailer; any other error is passed on as is.
|
|
197
|
+
*/
|
|
198
|
+
private assertScoped;
|
|
63
199
|
private toBase64;
|
|
64
200
|
}
|
package/lib/types.d.ts
CHANGED
|
@@ -453,6 +453,42 @@ export interface Settings {
|
|
|
453
453
|
theme: 'light' | 'dark';
|
|
454
454
|
preferredLanguages: string[];
|
|
455
455
|
}
|
|
456
|
+
/** One of actionId or key. workspaceId is optional, needed with a key in a private app. */
|
|
457
|
+
export interface ActionTriggerTarget {
|
|
458
|
+
actionId?: string;
|
|
459
|
+
key?: string;
|
|
460
|
+
workspaceId?: string;
|
|
461
|
+
}
|
|
462
|
+
/** `queued` and `running` are in progress, the rest are final. */
|
|
463
|
+
export type ActionRunStatus = 'queued' | 'running' | 'completed' | 'runtime_error' | 'timeout' | 'output_limit' | 'infra_error' | 'cancelled' | 'config_error' | 'denied';
|
|
464
|
+
export type ActionEvent = 'manual' | 'phase.activity-created' | 'phase.activity-updated' | 'phase.activity-moved' | 'workspace.member-joined' | 'workspace.member-left' | 'schedule.run';
|
|
465
|
+
export declare const ACTION_RUN_ACTIVE_STATUSES: ActionRunStatus[];
|
|
466
|
+
/** One run of an action. Fields marked "admins only" are absent for other users. */
|
|
467
|
+
export interface ActionRun {
|
|
468
|
+
_id: string;
|
|
469
|
+
actionId: string;
|
|
470
|
+
workspaceId: string;
|
|
471
|
+
event: ActionEvent;
|
|
472
|
+
/** Absent on scheduled runs */
|
|
473
|
+
triggeredBy?: string;
|
|
474
|
+
status: ActionRunStatus;
|
|
475
|
+
exitCode?: number | null;
|
|
476
|
+
/** Return value of `execute(input)` */
|
|
477
|
+
output?: unknown;
|
|
478
|
+
/** Detail for abnormal statuses */
|
|
479
|
+
message?: string | null;
|
|
480
|
+
wallTimeMs?: number | null;
|
|
481
|
+
created: number;
|
|
482
|
+
finishedAt?: number | null;
|
|
483
|
+
/** Admins only */
|
|
484
|
+
arguments?: string;
|
|
485
|
+
/** Admins only */
|
|
486
|
+
stdout?: string | null;
|
|
487
|
+
/** Admins only */
|
|
488
|
+
stderr?: string | null;
|
|
489
|
+
/** Admins only */
|
|
490
|
+
execRunId?: string | null;
|
|
491
|
+
}
|
|
456
492
|
export type CredentialType = 'basic' | 'apiKey' | 'custom';
|
|
457
493
|
export interface CredentialBasicData {
|
|
458
494
|
username: string;
|