@visualautomate/plugin-sdk 0.6.1 → 0.8.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.
@@ -0,0 +1,42 @@
1
+ /** The console a step has: these four methods, and no others. */
2
+ export interface PluginConsole {
3
+ log(...args: unknown[]): void;
4
+ error(...args: unknown[]): void;
5
+ warn(...args: unknown[]): void;
6
+ info(...args: unknown[]): void;
7
+ }
8
+ export interface LoadOptions {
9
+ /**
10
+ * The `fetch` the step gets. Pass a guarded one to apply an egress rule;
11
+ * without it, this process's own.
12
+ */
13
+ fetch?: typeof fetch;
14
+ /** Where the step's console output goes. Defaults to this process's console. */
15
+ console?: Partial<PluginConsole>;
16
+ /** How long the code's top level may take to run, in milliseconds. */
17
+ timeoutMs?: number;
18
+ }
19
+ /** A console with exactly the platform's four methods, writing where `target` says. */
20
+ export declare function pluginConsole(target?: Partial<PluginConsole>): PluginConsole;
21
+ /**
22
+ * The globals a step's context starts with: the platform's list, taken from
23
+ * this process where the platform takes them from its own, and the blocked
24
+ * names set to undefined.
25
+ */
26
+ export declare function sandboxGlobals(options?: LoadOptions): Record<string, unknown>;
27
+ /**
28
+ * Evaluate a step's code as the runner does, and return what it exported.
29
+ *
30
+ * The code is wrapped exactly as the runner wraps it, on one line with nothing
31
+ * added after it, so a file the platform cannot load fails to load here too:
32
+ * a last line that is a `//` comment with no newline after it comments out the
33
+ * wrapper's closing bracket on the platform, and does here.
34
+ */
35
+ export declare function loadPluginCode(code: string, require: (name: string) => unknown, options?: LoadOptions): unknown;
36
+ /**
37
+ * The function the runner calls, from what the code exported: the export
38
+ * itself if it is a function, else its `execute`, else its `default` if that is
39
+ * a function. `null` when there is none, which the runner reports as "Plugin
40
+ * must export an execute function".
41
+ */
42
+ export declare function executeOf(exported: unknown): ((...args: unknown[]) => unknown) | null;
@@ -53,6 +53,10 @@ export interface SimulateOptions {
53
53
  * Give `connections` a fake that answers the requests your plugin makes,
54
54
  * and assert on what it was asked for — that is a better test of an
55
55
  * integration step than any simulation of a provider would be.
56
+ *
57
+ * @deprecated for `connections`: only VisualAutomate's own apps act as a
58
+ * connected account, so a step you build is never given one. Stub `fetch`
59
+ * through loadPluginCode instead.
56
60
  */
57
61
  connections?: PluginConnections;
58
62
  media?: PluginMedia;
package/dist/types.d.ts CHANGED
@@ -50,7 +50,10 @@ export interface StorageListResult {
50
50
  * ceiling is refused rather than silently dropped.
51
51
  */
52
52
  export interface PluginStorage {
53
- /** Write a file. Bytes may be a string, a Buffer or any typed array. */
53
+ /**
54
+ * Write a file. Bytes are a string or a Uint8Array: there is no `Buffer` in a
55
+ * step's context.
56
+ */
54
57
  put(path: string, data: Uint8Array | string, contentType?: string): Promise<StorageResult>;
55
58
  /** Read a file back. `null` when it is not there. */
56
59
  get(path: string): Promise<Uint8Array | null>;
@@ -69,6 +72,13 @@ export interface PluginStorage {
69
72
  * to between one minute and one hour; the default is fifteen minutes.
70
73
  */
71
74
  signedUrl(path: string, expiresInSeconds?: number): Promise<string | null>;
75
+ /**
76
+ * A link on VisualAutomate's own domain that opens the file, for somebody
77
+ * with no account: a mail, a message, a page. The storage bucket's own
78
+ * address (signedUrl) is right for an API that fetches the file; this one is
79
+ * right for a person. Fifteen minutes unless `expiresInSeconds` says otherwise.
80
+ */
81
+ shareUrl(path: string, expiresInSeconds?: number): Promise<string | null>;
72
82
  /**
73
83
  * Pull a URL straight into storage without the bytes passing through this
74
84
  * step. A hundred-megabyte file costs the run no memory and no egress,
@@ -87,14 +97,26 @@ export interface PluginStorage {
87
97
  * The account's plan caps how many keys it may hold.
88
98
  */
89
99
  export interface PluginState {
90
- /** The stored value, or `null` when the key has never been set. */
100
+ /** The stored value, or `null` when the key has never been set or has expired. */
91
101
  get(key: string): Promise<unknown>;
102
+ /**
103
+ * Store a JSON value, at most 128 KB once encoded. With `ttlSeconds`, which
104
+ * must be at least 60, it is forgotten after that many seconds.
105
+ */
92
106
  set(key: string, value: unknown, options?: {
93
107
  ttlSeconds?: number;
94
108
  }): Promise<void>;
95
109
  delete(key: string): Promise<void>;
110
+ /**
111
+ * The keys under a prefix, each with when it expires (`null` for never).
112
+ * `complete` is false when there were more than one call returns.
113
+ */
96
114
  list(prefix?: string): Promise<{
97
- keys: string[];
115
+ keys: Array<{
116
+ key: string;
117
+ expiresAt: string | null;
118
+ }>;
119
+ complete: boolean;
98
120
  }>;
99
121
  }
100
122
  /**
@@ -185,7 +207,14 @@ export interface PluginContext {
185
207
  state: PluginState;
186
208
  /** ffmpeg. Absent when the server has no sandbox or storage configured. */
187
209
  media?: PluginMedia;
188
- /** The accounts this step was configured with. Absent when it has none. */
210
+ /**
211
+ * The accounts this step was configured with. Absent when it has none.
212
+ *
213
+ * @deprecated Only VisualAutomate's own apps act as a connected account, so
214
+ * a step you build never has this: the platform refuses a step that names
215
+ * an account. Take the user's key in a property of type "secret" and send
216
+ * it to the API's own host with fetch.
217
+ */
189
218
  connections?: PluginConnections;
190
219
  }
191
220
  /**
@@ -262,7 +291,14 @@ export type PluginPropertyType = "string" | "number" | "boolean" | "select" | "m
262
291
  * `json` above: that one keeps its value structured, so `return 5` would be
263
292
  * saved as the number five and the step would run nothing.
264
293
  */
265
- | "code" | "color" | "date"
294
+ | "code"
295
+ /**
296
+ * A key the user types in: an API key, a token. A string to your code and to
297
+ * a declared call (`Bearer {{config.apiKey}}`), and masked wherever it is
298
+ * shown, because it is the one value on a step that somebody looking over a
299
+ * shoulder must not be able to read off.
300
+ */
301
+ | "secret" | "color" | "date"
266
302
  /** An account the user connected. Rendered as a picker, not a text box. */
267
303
  | "connection"
268
304
  /**
@@ -301,6 +337,49 @@ export interface PluginProperty {
301
337
  * `outlook`. A module inherits its app's, so it does not repeat this.
302
338
  */
303
339
  provider?: string;
340
+ /** Longer help, shown on request rather than under the input. */
341
+ help?: string;
342
+ /** Shown but not editable. */
343
+ disabled?: boolean;
344
+ /**
345
+ * For `select` and `multiselect`: read the options from the user's account
346
+ * instead of listing them, e.g. the channels of the chosen Slack workspace.
347
+ */
348
+ optionsFrom?: OptionsSource;
349
+ /**
350
+ * For `secret`: the properties that say where this secret is sent, such as
351
+ * a server URL. A stored secret is only kept when those are unchanged, so
352
+ * pointing the URL somewhere else cannot carry the key along.
353
+ */
354
+ sentTo?: string[];
355
+ /**
356
+ * For `secret`: the value is sent exactly as typed and never computed with,
357
+ * which lets the platform keep it out of the step's code entirely.
358
+ */
359
+ verbatim?: boolean;
360
+ }
361
+ /**
362
+ * Where a select's options come from: one GET as the account in `connection`,
363
+ * a list in the answer, and what each option shows and stores.
364
+ */
365
+ export interface OptionsSource {
366
+ /** The `connection` property whose account the options are read as. */
367
+ connection: string;
368
+ request: {
369
+ path: string;
370
+ query?: Record<string, unknown>;
371
+ headers?: Record<string, string>;
372
+ };
373
+ /** Where the list is in the answer (`""` when the answer is the list), and how many to offer. */
374
+ items: {
375
+ path: string;
376
+ limit?: number;
377
+ };
378
+ paginate?: Record<string, unknown>;
379
+ /** What each option shows, e.g. `{{item.name}}`. */
380
+ label: string;
381
+ /** What choosing it stores, e.g. `{{item.id}}`. */
382
+ value: string;
304
383
  }
305
384
  /**
306
385
  * How a step reaches the account it acts as.
@@ -35,12 +35,3 @@ export declare function validatePluginCode(code: string): CodeCheck;
35
35
  * the command that installs the version the sandbox has.
36
36
  */
37
37
  export declare function sandboxRequire(load: (name: string) => unknown): (name: string) => unknown;
38
- /**
39
- * Evaluate a step's code the way the sandbox wraps it: as the body of a function
40
- * given `module`, `exports` and `require`, in strict mode. Returns what it exported.
41
- *
42
- * Not a security boundary — this runs your own code on your own machine. It is
43
- * here so a file the sandbox cannot load (an `export` statement, a top-level
44
- * `await`) fails here too, rather than passing a looser loader.
45
- */
46
- export declare function loadPluginCode(code: string, require: (name: string) => unknown): unknown;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@visualautomate/plugin-sdk",
3
- "version": "0.6.1",
3
+ "version": "0.8.0",
4
4
  "description": "Types and a local runner for building VisualAutomate plugins.",
5
5
  "license": "MIT",
6
6
  "type": "module",