@vicinae/api 0.3.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 +37 -0
- package/bin/run.js +9 -0
- package/dist/api/ai.d.ts +110 -0
- package/dist/api/ai.js +120 -0
- package/dist/api/alert.d.ts +22 -0
- package/dist/api/alert.js +61 -0
- package/dist/api/bus.d.ts +95 -0
- package/dist/api/bus.js +211 -0
- package/dist/api/cache.d.ts +117 -0
- package/dist/api/cache.js +52 -0
- package/dist/api/clipboard.d.ts +34 -0
- package/dist/api/clipboard.js +52 -0
- package/dist/api/color.d.ts +24 -0
- package/dist/api/color.js +24 -0
- package/dist/api/components/action-pannel.d.ts +23 -0
- package/dist/api/components/action-pannel.js +30 -0
- package/dist/api/components/actions.d.ts +52 -0
- package/dist/api/components/actions.js +81 -0
- package/dist/api/components/detail.d.ts +21 -0
- package/dist/api/components/detail.js +12 -0
- package/dist/api/components/dropdown.d.ts +36 -0
- package/dist/api/components/dropdown.js +21 -0
- package/dist/api/components/empty-view.d.ts +9 -0
- package/dist/api/components/empty-view.js +12 -0
- package/dist/api/components/form.d.ts +81 -0
- package/dist/api/components/form.js +53 -0
- package/dist/api/components/grid.d.ts +117 -0
- package/dist/api/components/grid.js +80 -0
- package/dist/api/components/index.d.ts +7 -0
- package/dist/api/components/index.js +23 -0
- package/dist/api/components/list.d.ts +109 -0
- package/dist/api/components/list.js +53 -0
- package/dist/api/components/menu-bar.d.ts +26 -0
- package/dist/api/components/menu-bar.js +25 -0
- package/dist/api/components/metadata.d.ts +23 -0
- package/dist/api/components/metadata.js +27 -0
- package/dist/api/components/tag.d.ts +16 -0
- package/dist/api/components/tag.js +28 -0
- package/dist/api/context/index.d.ts +1 -0
- package/dist/api/context/index.js +17 -0
- package/dist/api/context/navigation-context.d.ts +7 -0
- package/dist/api/context/navigation-context.js +8 -0
- package/dist/api/context/navigation-provider.d.ts +4 -0
- package/dist/api/context/navigation-provider.js +40 -0
- package/dist/api/controls.d.ts +3 -0
- package/dist/api/controls.js +20 -0
- package/dist/api/environment.d.ts +118 -0
- package/dist/api/environment.js +17 -0
- package/dist/api/hooks/index.d.ts +2 -0
- package/dist/api/hooks/index.js +18 -0
- package/dist/api/hooks/use-applications.d.ts +2 -0
- package/dist/api/hooks/use-applications.js +19 -0
- package/dist/api/hooks/use-imperative-form-handle.d.ts +3 -0
- package/dist/api/hooks/use-imperative-form-handle.js +25 -0
- package/dist/api/hooks/use-navigation.d.ts +4 -0
- package/dist/api/hooks/use-navigation.js +13 -0
- package/dist/api/hooks.d.ts +1 -0
- package/dist/api/hooks.js +24 -0
- package/dist/api/icon.d.ts +444 -0
- package/dist/api/icon.js +448 -0
- package/dist/api/image.d.ts +35 -0
- package/dist/api/image.js +84 -0
- package/dist/api/index.d.ts +19 -0
- package/dist/api/index.js +35 -0
- package/dist/api/keyboard.d.ts +16 -0
- package/dist/api/keyboard.js +12 -0
- package/dist/api/lib/result.d.ts +9 -0
- package/dist/api/lib/result.js +11 -0
- package/dist/api/local-storage.d.ts +13 -0
- package/dist/api/local-storage.js +31 -0
- package/dist/api/oauth.d.ts +319 -0
- package/dist/api/oauth.js +166 -0
- package/dist/api/preference.d.ts +5 -0
- package/dist/api/preference.js +18 -0
- package/dist/api/proto/application.d.ts +48 -0
- package/dist/api/proto/application.js +378 -0
- package/dist/api/proto/clipboard.d.ts +65 -0
- package/dist/api/proto/clipboard.js +614 -0
- package/dist/api/proto/common.d.ts +28 -0
- package/dist/api/proto/common.js +102 -0
- package/dist/api/proto/extension.d.ts +68 -0
- package/dist/api/proto/extension.js +604 -0
- package/dist/api/proto/google/protobuf/struct.d.ts +107 -0
- package/dist/api/proto/google/protobuf/struct.js +456 -0
- package/dist/api/proto/ipc.d.ts +64 -0
- package/dist/api/proto/ipc.js +604 -0
- package/dist/api/proto/manager.d.ts +82 -0
- package/dist/api/proto/manager.js +689 -0
- package/dist/api/proto/oauth.d.ts +55 -0
- package/dist/api/proto/oauth.js +379 -0
- package/dist/api/proto/storage.d.ts +80 -0
- package/dist/api/proto/storage.js +804 -0
- package/dist/api/proto/ui.d.ts +186 -0
- package/dist/api/proto/ui.js +1993 -0
- package/dist/api/toast.d.ts +168 -0
- package/dist/api/toast.js +152 -0
- package/dist/api/utils.d.ts +15 -0
- package/dist/api/utils.js +64 -0
- package/dist/commands/build/index.d.ts +11 -0
- package/dist/commands/build/index.js +123 -0
- package/dist/commands/develop/index.d.ts +10 -0
- package/dist/commands/develop/index.js +193 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +17 -0
- package/dist/schemas/manifest.d.ts +75 -0
- package/dist/schemas/manifest.js +4 -0
- package/dist/utils/logger.d.ts +13 -0
- package/dist/utils/logger.js +38 -0
- package/dist/utils/utils.d.ts +2 -0
- package/dist/utils/utils.js +19 -0
- package/dist/utils/vicinae.d.ts +12 -0
- package/dist/utils/vicinae.js +33 -0
- package/package.json +73 -0
package/README.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
This package lets you extend the [Vicinae](https://docs.vicinae.com/) launcher using React and TypeScript.
|
|
2
|
+
|
|
3
|
+
# Getting started
|
|
4
|
+
|
|
5
|
+
Install the package:
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
npm install @vicinae/api
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
# Versioning
|
|
12
|
+
|
|
13
|
+
The `@vicinae/api` package follows the same versioning as the main `vicinae` binary, since the API is always embedded in the binary.
|
|
14
|
+
|
|
15
|
+
# CLI usage
|
|
16
|
+
|
|
17
|
+
The package exports the `vici` binary which is used to build and run extensions in development mode.
|
|
18
|
+
|
|
19
|
+
While convenience scripts are already provided in the boilerplate, you can still call the binary manually:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npx vici --help
|
|
23
|
+
|
|
24
|
+
# assuming vicinae is running
|
|
25
|
+
npx vici develop
|
|
26
|
+
npx vici build -o my/output/path
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
# API developers
|
|
30
|
+
|
|
31
|
+
If you are working on developing the API, it is recommended to point `@vicinae/api` to the local api directory:
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
npm install /path/to/vicinae/source/api
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Note that you need to recompile the `api` package on every change you make to it.
|
package/bin/run.js
ADDED
package/dist/api/ai.d.ts
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { ImageLike } from "./image";
|
|
2
|
+
export declare namespace AI {
|
|
3
|
+
/**
|
|
4
|
+
* Returns a prompt completion.
|
|
5
|
+
*
|
|
6
|
+
* @param prompt - The prompt to ask the AI.
|
|
7
|
+
* @param options - Options to control which and how the AI model should behave.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { Detail, AI, LaunchProps } from "@raycast/api";
|
|
12
|
+
* import { usePromise } from "@raycast/utils";
|
|
13
|
+
* import { useState } from "react";
|
|
14
|
+
*
|
|
15
|
+
* export default function Command(props: LaunchProps<{ arguments: { prompt: string } }>) {
|
|
16
|
+
* const [data, setData] = useState("");
|
|
17
|
+
* const { isLoading } = usePromise(
|
|
18
|
+
* async (prompt) => {
|
|
19
|
+
* const stream = AI.ask(prompt);
|
|
20
|
+
* stream.on("data", (data) => {
|
|
21
|
+
* setData((x) => x + data);
|
|
22
|
+
* });
|
|
23
|
+
* await stream;
|
|
24
|
+
* },
|
|
25
|
+
* [props.arguments.prompt]
|
|
26
|
+
* );
|
|
27
|
+
*
|
|
28
|
+
* return <Detail isLoading={isLoading} markdown={data} />;
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
function ask(prompt: string, options?: AskOptions): Promise<string> & {
|
|
33
|
+
on(event: "data", listener: (chunk: string) => void): void;
|
|
34
|
+
};
|
|
35
|
+
type AskOptions = {
|
|
36
|
+
/**
|
|
37
|
+
* Concrete tasks, such as fixing grammar, require less creativity while open-ended questions, such as generating ideas, require more.
|
|
38
|
+
* If a number is passed, it needs to be in the range 0-2. For larger values, 2 will be used. For lower values, 0 will be used.
|
|
39
|
+
*/
|
|
40
|
+
creativity?: Creativity;
|
|
41
|
+
/**
|
|
42
|
+
* The AI model to use to answer to the prompt.
|
|
43
|
+
*/
|
|
44
|
+
model?: Model | string | __DeprecatedModelUnion;
|
|
45
|
+
/**
|
|
46
|
+
* Abort signal to cancel the request.
|
|
47
|
+
*/
|
|
48
|
+
signal?: AbortSignal;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Concrete tasks, such as fixing grammar, require less creativity while open-ended questions, such as generating ideas, require more.
|
|
52
|
+
* If a number is passed, it needs to be in the range 0-2. For larger values, 2 will be used. For lower values, 0 will be used.
|
|
53
|
+
*/
|
|
54
|
+
type Creativity = "none" | "low" | "medium" | "high" | "maximum" | number;
|
|
55
|
+
/**
|
|
56
|
+
* The AI model to use to answer to the prompt.
|
|
57
|
+
* @defaultValue `AI.Model["OpenAI_GPT4o-mini"]`
|
|
58
|
+
*/
|
|
59
|
+
enum Model {
|
|
60
|
+
OpenAI_GPT4 = "openai-gpt-4",
|
|
61
|
+
"OpenAI_GPT4-turbo" = "openai-gpt-4-turbo",
|
|
62
|
+
OpenAI_GPT4o = "openai-gpt-4o",
|
|
63
|
+
"OpenAI_GPT4o-mini" = "openai-gpt-4o-mini",
|
|
64
|
+
Anthropic_Claude_Haiku = "anthropic-claude-haiku",
|
|
65
|
+
Anthropic_Claude_Opus = "anthropic-claude-opus",
|
|
66
|
+
Anthropic_Claude_Sonnet = "anthropic-claude-sonnet",
|
|
67
|
+
MixtraL_8x7B = "mixtral-8x7b",
|
|
68
|
+
"Mistral_Nemo" = "mistral-nemo",
|
|
69
|
+
"Mistral_Large2" = "mistral-large-2",
|
|
70
|
+
Llama3_70B = "llama3-70b",
|
|
71
|
+
"Llama3.1_70B" = "llama3.1-70b",
|
|
72
|
+
"Llama3.1_8B" = "llama3.1-8b",
|
|
73
|
+
"Llama3.1_405B" = "llama3.1-405b",
|
|
74
|
+
"Perplexity_Llama3.1_Sonar_Huge" = "perplexity-llama-3.1-sonar-huge-128k-online",
|
|
75
|
+
"Perplexity_Llama3.1_Sonar_Large" = "perplexity-llama-3.1-sonar-large-128k-online",
|
|
76
|
+
"Perplexity_Llama3.1_Sonar_Small" = "perplexity-llama-3.1-sonar-small-128k-online",
|
|
77
|
+
/** @deprecated Use `AI.Model["OpenAI_GPT4o-mini"]` instead */
|
|
78
|
+
"OpenAI_GPT3.5-turbo-instruct" = "openai-gpt-3.5-turbo-instruct",
|
|
79
|
+
/** @deprecated Use `AI.Model.Llama3_70B` instead */
|
|
80
|
+
Llama2_70B = "llama2-70b",
|
|
81
|
+
/** @deprecated Use `AI.Model.Perplexity_Llama3_Sonar_Large` instead */
|
|
82
|
+
Perplexity_Sonar_Medium_Online = "perplexity-sonar-medium-online",
|
|
83
|
+
/** @deprecated Use `AI.Model.Perplexity_Llama3_Sonar_Small` instead */
|
|
84
|
+
Perplexity_Sonar_Small_Online = "perplexity-sonar-small-online",
|
|
85
|
+
/** @deprecated Use `AI.Model.Llama3_70B` instead */
|
|
86
|
+
Codellama_70B_instruct = "codellama-70b-instruct",
|
|
87
|
+
/** @deprecated Use `AI.Model["Perplexity_Llama3.1_Sonar_Large"]` instead */
|
|
88
|
+
Perplexity_Llama3_Sonar_Large = "perplexity-llama-3-sonar-large-online",
|
|
89
|
+
/** @deprecated Use `AI.Model["Perplexity_Llama3.1_Sonar_Small"]` instead */
|
|
90
|
+
Perplexity_Llama3_Sonar_Small = "perplexity-llama-3-sonar-small-online",
|
|
91
|
+
/** @deprecated Use `AI.Model["OpenAI_GPT4o-mini"]` instead */
|
|
92
|
+
"OpenAI_GPT3.5-turbo" = "openai-gpt-3.5-turbo"
|
|
93
|
+
}
|
|
94
|
+
/** @deprecated Use the `AI.Model` enum instead */
|
|
95
|
+
type __DeprecatedModelUnion = "openai-gpt-3.5-turbo-instruct" | "openai-gpt-3.5-turbo" | "openai-gpt-4" | "openai-gpt-4-turbo" | "anthropic-claude-haiku" | "anthropic-claude-opus" | "anthropic-claude-sonnet" | "perplexity-sonar-medium-online" | "perplexity-sonar-small-online" | "llama2-70b" | "mixtral-8x7b" | "codellama-70b-instruct"
|
|
96
|
+
/** @deprecated */
|
|
97
|
+
| "gpt-3.5-turbo"
|
|
98
|
+
/** @deprecated */
|
|
99
|
+
| "gpt-3.5-turbo-instruct"
|
|
100
|
+
/** @deprecated */
|
|
101
|
+
| "gpt-4"
|
|
102
|
+
/** @deprecated */
|
|
103
|
+
| "text-davinci-003";
|
|
104
|
+
type ModelInfo = {
|
|
105
|
+
id: string;
|
|
106
|
+
name: string;
|
|
107
|
+
icon?: ImageLike;
|
|
108
|
+
};
|
|
109
|
+
const getModels: () => Promise<AI.ModelInfo[]>;
|
|
110
|
+
}
|
package/dist/api/ai.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AI = void 0;
|
|
4
|
+
const stream_1 = require("stream");
|
|
5
|
+
const bus_1 = require("./bus");
|
|
6
|
+
const crypto_1 = require("crypto");
|
|
7
|
+
var AI;
|
|
8
|
+
(function (AI) {
|
|
9
|
+
/**
|
|
10
|
+
* Returns a prompt completion.
|
|
11
|
+
*
|
|
12
|
+
* @param prompt - The prompt to ask the AI.
|
|
13
|
+
* @param options - Options to control which and how the AI model should behave.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* import { Detail, AI, LaunchProps } from "@raycast/api";
|
|
18
|
+
* import { usePromise } from "@raycast/utils";
|
|
19
|
+
* import { useState } from "react";
|
|
20
|
+
*
|
|
21
|
+
* export default function Command(props: LaunchProps<{ arguments: { prompt: string } }>) {
|
|
22
|
+
* const [data, setData] = useState("");
|
|
23
|
+
* const { isLoading } = usePromise(
|
|
24
|
+
* async (prompt) => {
|
|
25
|
+
* const stream = AI.ask(prompt);
|
|
26
|
+
* stream.on("data", (data) => {
|
|
27
|
+
* setData((x) => x + data);
|
|
28
|
+
* });
|
|
29
|
+
* await stream;
|
|
30
|
+
* },
|
|
31
|
+
* [props.arguments.prompt]
|
|
32
|
+
* );
|
|
33
|
+
*
|
|
34
|
+
* return <Detail isLoading={isLoading} markdown={data} />;
|
|
35
|
+
* }
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
function ask(prompt, options) {
|
|
39
|
+
const handlerId = (0, crypto_1.randomUUID)();
|
|
40
|
+
const emitter = new stream_1.EventEmitter;
|
|
41
|
+
const promise = new Promise((resolve, reject) => {
|
|
42
|
+
let answer = '';
|
|
43
|
+
bus_1.bus.request('ai.create-completion', {
|
|
44
|
+
prompt,
|
|
45
|
+
options,
|
|
46
|
+
callback: handlerId
|
|
47
|
+
})
|
|
48
|
+
.then(({ data }) => {
|
|
49
|
+
if (!data.started) {
|
|
50
|
+
reject(new Error("Could not create completion"));
|
|
51
|
+
}
|
|
52
|
+
const { unsubscribe } = bus_1.bus.subscribe(handlerId, (...args) => {
|
|
53
|
+
const data = args[0];
|
|
54
|
+
answer += data.token;
|
|
55
|
+
emitter.emit('data', data.token);
|
|
56
|
+
if (data.done) {
|
|
57
|
+
unsubscribe();
|
|
58
|
+
resolve(answer);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
if (options?.signal) {
|
|
62
|
+
options.signal.addEventListener('abort', () => {
|
|
63
|
+
bus_1.bus.request('ai.abort-completion');
|
|
64
|
+
unsubscribe();
|
|
65
|
+
resolve(answer);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
.catch(err => reject(err));
|
|
70
|
+
});
|
|
71
|
+
return Object.assign(promise, {
|
|
72
|
+
on: emitter.on.bind(emitter)
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
AI.ask = ask;
|
|
76
|
+
/**
|
|
77
|
+
* The AI model to use to answer to the prompt.
|
|
78
|
+
* @defaultValue `AI.Model["OpenAI_GPT4o-mini"]`
|
|
79
|
+
*/
|
|
80
|
+
let Model;
|
|
81
|
+
(function (Model) {
|
|
82
|
+
Model["OpenAI_GPT4"] = "openai-gpt-4";
|
|
83
|
+
Model["OpenAI_GPT4-turbo"] = "openai-gpt-4-turbo";
|
|
84
|
+
Model["OpenAI_GPT4o"] = "openai-gpt-4o";
|
|
85
|
+
Model["OpenAI_GPT4o-mini"] = "openai-gpt-4o-mini";
|
|
86
|
+
Model["Anthropic_Claude_Haiku"] = "anthropic-claude-haiku";
|
|
87
|
+
Model["Anthropic_Claude_Opus"] = "anthropic-claude-opus";
|
|
88
|
+
Model["Anthropic_Claude_Sonnet"] = "anthropic-claude-sonnet";
|
|
89
|
+
Model["MixtraL_8x7B"] = "mixtral-8x7b";
|
|
90
|
+
Model["Mistral_Nemo"] = "mistral-nemo";
|
|
91
|
+
Model["Mistral_Large2"] = "mistral-large-2";
|
|
92
|
+
Model["Llama3_70B"] = "llama3-70b";
|
|
93
|
+
Model["Llama3.1_70B"] = "llama3.1-70b";
|
|
94
|
+
Model["Llama3.1_8B"] = "llama3.1-8b";
|
|
95
|
+
Model["Llama3.1_405B"] = "llama3.1-405b";
|
|
96
|
+
Model["Perplexity_Llama3.1_Sonar_Huge"] = "perplexity-llama-3.1-sonar-huge-128k-online";
|
|
97
|
+
Model["Perplexity_Llama3.1_Sonar_Large"] = "perplexity-llama-3.1-sonar-large-128k-online";
|
|
98
|
+
Model["Perplexity_Llama3.1_Sonar_Small"] = "perplexity-llama-3.1-sonar-small-128k-online";
|
|
99
|
+
/** @deprecated Use `AI.Model["OpenAI_GPT4o-mini"]` instead */
|
|
100
|
+
Model["OpenAI_GPT3.5-turbo-instruct"] = "openai-gpt-3.5-turbo-instruct";
|
|
101
|
+
/** @deprecated Use `AI.Model.Llama3_70B` instead */
|
|
102
|
+
Model["Llama2_70B"] = "llama2-70b";
|
|
103
|
+
/** @deprecated Use `AI.Model.Perplexity_Llama3_Sonar_Large` instead */
|
|
104
|
+
Model["Perplexity_Sonar_Medium_Online"] = "perplexity-sonar-medium-online";
|
|
105
|
+
/** @deprecated Use `AI.Model.Perplexity_Llama3_Sonar_Small` instead */
|
|
106
|
+
Model["Perplexity_Sonar_Small_Online"] = "perplexity-sonar-small-online";
|
|
107
|
+
/** @deprecated Use `AI.Model.Llama3_70B` instead */
|
|
108
|
+
Model["Codellama_70B_instruct"] = "codellama-70b-instruct";
|
|
109
|
+
/** @deprecated Use `AI.Model["Perplexity_Llama3.1_Sonar_Large"]` instead */
|
|
110
|
+
Model["Perplexity_Llama3_Sonar_Large"] = "perplexity-llama-3-sonar-large-online";
|
|
111
|
+
/** @deprecated Use `AI.Model["Perplexity_Llama3.1_Sonar_Small"]` instead */
|
|
112
|
+
Model["Perplexity_Llama3_Sonar_Small"] = "perplexity-llama-3-sonar-small-online";
|
|
113
|
+
/** @deprecated Use `AI.Model["OpenAI_GPT4o-mini"]` instead */
|
|
114
|
+
Model["OpenAI_GPT3.5-turbo"] = "openai-gpt-3.5-turbo";
|
|
115
|
+
})(Model = AI.Model || (AI.Model = {}));
|
|
116
|
+
AI.getModels = async () => {
|
|
117
|
+
const res = await bus_1.bus.request('ai.get-models');
|
|
118
|
+
return res.data.models;
|
|
119
|
+
};
|
|
120
|
+
})(AI || (exports.AI = AI = {}));
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Image } from './image';
|
|
2
|
+
export declare namespace Alert {
|
|
3
|
+
type Options = {
|
|
4
|
+
title: string;
|
|
5
|
+
dismissAction?: ActionOptions;
|
|
6
|
+
icon?: Image.ImageLike;
|
|
7
|
+
message?: string;
|
|
8
|
+
primaryAction?: ActionOptions;
|
|
9
|
+
rememberUserChoice?: boolean;
|
|
10
|
+
};
|
|
11
|
+
enum ActionStyle {
|
|
12
|
+
Default = "default",
|
|
13
|
+
Destructive = "destructive",
|
|
14
|
+
Cancel = "cancel"
|
|
15
|
+
}
|
|
16
|
+
type ActionOptions = {
|
|
17
|
+
title: string;
|
|
18
|
+
style?: ActionStyle;
|
|
19
|
+
onAction?: () => void;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export declare const confirmAlert: (options: Alert.Options) => Promise<boolean>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.confirmAlert = exports.Alert = void 0;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
|
+
const bus_1 = require("./bus");
|
|
6
|
+
const ui_1 = require("./proto/ui");
|
|
7
|
+
var Alert;
|
|
8
|
+
(function (Alert) {
|
|
9
|
+
let ActionStyle;
|
|
10
|
+
(function (ActionStyle) {
|
|
11
|
+
ActionStyle["Default"] = "default";
|
|
12
|
+
ActionStyle["Destructive"] = "destructive";
|
|
13
|
+
ActionStyle["Cancel"] = "cancel";
|
|
14
|
+
})(ActionStyle = Alert.ActionStyle || (Alert.ActionStyle = {}));
|
|
15
|
+
})(Alert || (exports.Alert = Alert = {}));
|
|
16
|
+
;
|
|
17
|
+
const styleMap = {
|
|
18
|
+
[Alert.ActionStyle.Default]: ui_1.ConfirmAlertActionStyle.Default,
|
|
19
|
+
[Alert.ActionStyle.Destructive]: ui_1.ConfirmAlertActionStyle.Destructive,
|
|
20
|
+
[Alert.ActionStyle.Cancel]: ui_1.ConfirmAlertActionStyle.Cancel,
|
|
21
|
+
};
|
|
22
|
+
const confirmAlert = async (options) => {
|
|
23
|
+
return new Promise(async (resolve) => {
|
|
24
|
+
const handle = (0, node_crypto_1.randomUUID)();
|
|
25
|
+
let confirmCallback = () => { };
|
|
26
|
+
let cancelCallback = () => { };
|
|
27
|
+
const { unsubscribe } = bus_1.bus.subscribe(handle, (...args) => {
|
|
28
|
+
callback(!!args[0]);
|
|
29
|
+
});
|
|
30
|
+
const callback = (value) => {
|
|
31
|
+
if (value)
|
|
32
|
+
confirmCallback();
|
|
33
|
+
else
|
|
34
|
+
cancelCallback();
|
|
35
|
+
unsubscribe();
|
|
36
|
+
resolve(value);
|
|
37
|
+
};
|
|
38
|
+
const req = ui_1.ConfirmAlertRequest.create({
|
|
39
|
+
handle,
|
|
40
|
+
title: options.title,
|
|
41
|
+
description: options.message ?? "Are you sure?",
|
|
42
|
+
rememberUserChoice: false,
|
|
43
|
+
primaryAction: {
|
|
44
|
+
title: options.primaryAction?.title ?? 'Confirm',
|
|
45
|
+
style: styleMap[options.primaryAction?.style ?? Alert.ActionStyle.Default],
|
|
46
|
+
},
|
|
47
|
+
dismissAction: {
|
|
48
|
+
title: options.dismissAction?.title ?? 'Cancel',
|
|
49
|
+
style: styleMap[options.dismissAction?.style ?? Alert.ActionStyle.Cancel],
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
if (options.primaryAction?.onAction) {
|
|
53
|
+
confirmCallback = options.primaryAction.onAction;
|
|
54
|
+
}
|
|
55
|
+
if (options.dismissAction?.onAction) {
|
|
56
|
+
cancelCallback = options.dismissAction.onAction;
|
|
57
|
+
}
|
|
58
|
+
await bus_1.bus.turboRequest('ui.confirmAlert', req);
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
exports.confirmAlert = confirmAlert;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { MessagePort } from "worker_threads";
|
|
2
|
+
import * as ipc from './proto/ipc';
|
|
3
|
+
import * as extension from './proto/extension';
|
|
4
|
+
import { Result } from './lib/result';
|
|
5
|
+
export type Message<T = Record<string, any>> = {
|
|
6
|
+
envelope: {
|
|
7
|
+
id: string;
|
|
8
|
+
type: 'request' | 'response' | 'event';
|
|
9
|
+
action: string;
|
|
10
|
+
};
|
|
11
|
+
error: {
|
|
12
|
+
message?: string;
|
|
13
|
+
} | null;
|
|
14
|
+
data: T;
|
|
15
|
+
};
|
|
16
|
+
declare namespace EventListener {
|
|
17
|
+
type ArgValue = string | number | Record<any, any> | boolean | null | undefined;
|
|
18
|
+
type Callback = (...args: EventListener.ArgValue[]) => void;
|
|
19
|
+
}
|
|
20
|
+
type EventListenerInfo = {
|
|
21
|
+
callback: EventListener.Callback;
|
|
22
|
+
};
|
|
23
|
+
type Requests = {
|
|
24
|
+
[K in keyof Required<extension.RequestData>]: {
|
|
25
|
+
[R in keyof Required<Required<extension.RequestData>[K]>]: {
|
|
26
|
+
data: NonNullable<Required<extension.RequestData>[K][R]>;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
type Responses = {
|
|
31
|
+
[K in keyof Required<extension.ResponseData>]: {
|
|
32
|
+
[R in keyof Required<Required<extension.ResponseData>[K]>]: {
|
|
33
|
+
data: NonNullable<Required<extension.ResponseData>[K][R]>;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
type EndpointMapping = {
|
|
38
|
+
"app.list": "app.list";
|
|
39
|
+
"app.open": "app.open";
|
|
40
|
+
'ui.render': 'ui.render';
|
|
41
|
+
'ui.showToast': 'ui.showToast';
|
|
42
|
+
'ui.hideToast': 'ui.hideToast';
|
|
43
|
+
'ui.updateToast': 'ui.updateToast';
|
|
44
|
+
'ui.pushView': 'ui.pushView';
|
|
45
|
+
'ui.popView': 'ui.popView';
|
|
46
|
+
'ui.closeMainWindow': 'ui.closeMainWindow';
|
|
47
|
+
'ui.showHud': 'ui.showHud';
|
|
48
|
+
'ui.setSearchText': 'ui.setSearchText';
|
|
49
|
+
'ui.confirmAlert': 'ui.confirmAlert';
|
|
50
|
+
'ui.getSelectedText': 'ui.getSelectedText';
|
|
51
|
+
'storage.get': 'storage.get';
|
|
52
|
+
'storage.set': 'storage.set';
|
|
53
|
+
'storage.remove': 'storage.remove';
|
|
54
|
+
'storage.clear': 'storage.clear';
|
|
55
|
+
'storage.list': 'storage.list';
|
|
56
|
+
'oauth.authorize': 'oauth.authorize';
|
|
57
|
+
'clipboard.copy': 'clipboard.copy';
|
|
58
|
+
'clipboard.paste': 'clipboard.paste';
|
|
59
|
+
};
|
|
60
|
+
type RequestEndpoint = keyof EndpointMapping;
|
|
61
|
+
type ResponseEndpoint = EndpointMapping[RequestEndpoint];
|
|
62
|
+
type ExtractRequestType<T extends RequestEndpoint> = T extends `${infer Category}.${infer Action}` ? Category extends keyof Requests ? Action extends keyof Requests[Category] ? Requests[Category][Action] : never : never : never;
|
|
63
|
+
type ExtractResponseType<T extends ResponseEndpoint> = T extends `${infer Category}.${infer Action}` ? Category extends keyof Responses ? Action extends keyof Responses[Category] ? Responses[Category][Action] : never : never : never;
|
|
64
|
+
type Map = {
|
|
65
|
+
[K in RequestEndpoint]: {
|
|
66
|
+
request: ExtractRequestType<K>['data'];
|
|
67
|
+
response: ExtractResponseType<EndpointMapping[K]>['data'];
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
declare class Bus {
|
|
71
|
+
private readonly port;
|
|
72
|
+
private requestMap;
|
|
73
|
+
private safeRequestMap;
|
|
74
|
+
private eventListeners;
|
|
75
|
+
turboRequest<T extends RequestEndpoint>(endpoint: T, data: Map[T]['request']): Promise<Result<Map[T]['response'], Error>>;
|
|
76
|
+
private handleSafeMessage;
|
|
77
|
+
emitCrash(errorText: string): void;
|
|
78
|
+
constructor(port: MessagePort);
|
|
79
|
+
listEventListeners(type: string): EventListenerInfo[];
|
|
80
|
+
subscribe(type: string, cb: EventListenerInfo['callback']): {
|
|
81
|
+
unsubscribe: () => void;
|
|
82
|
+
};
|
|
83
|
+
emit(action: string, data: Record<string, any>): void;
|
|
84
|
+
sendMessage(message: ipc.ExtensionMessage): void;
|
|
85
|
+
request2(data: extension.RequestData, options?: {
|
|
86
|
+
timeout?: number;
|
|
87
|
+
}): Promise<Result<extension.ResponseData, Error>>;
|
|
88
|
+
request<T = Record<string, any>>(action: string, data?: Record<string, any>, options?: {
|
|
89
|
+
timeout?: number;
|
|
90
|
+
rejectOnError?: boolean;
|
|
91
|
+
}): Promise<Message<T>>;
|
|
92
|
+
}
|
|
93
|
+
export declare const createHandler: (handler: (...args: any[]) => void) => string;
|
|
94
|
+
export declare const bus: Bus;
|
|
95
|
+
export {};
|
package/dist/api/bus.js
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.bus = exports.createHandler = void 0;
|
|
37
|
+
const crypto_1 = require("crypto");
|
|
38
|
+
const worker_threads_1 = require("worker_threads");
|
|
39
|
+
const ipc = __importStar(require("./proto/ipc"));
|
|
40
|
+
const extension = __importStar(require("./proto/extension"));
|
|
41
|
+
const result_1 = require("./lib/result");
|
|
42
|
+
;
|
|
43
|
+
class Bus {
|
|
44
|
+
port;
|
|
45
|
+
requestMap = new Map();
|
|
46
|
+
safeRequestMap = new Map();
|
|
47
|
+
eventListeners = new Map();
|
|
48
|
+
async turboRequest(endpoint, data) {
|
|
49
|
+
const [category, requestId] = endpoint.split('.');
|
|
50
|
+
const request = extension.RequestData.create({ [category]: { [requestId]: data } });
|
|
51
|
+
const res = await this.request2(request);
|
|
52
|
+
if (!res.ok) {
|
|
53
|
+
return (0, result_1.Err)(res.error);
|
|
54
|
+
}
|
|
55
|
+
const resData = res.value[category]?.[requestId];
|
|
56
|
+
if (!resData)
|
|
57
|
+
return (0, result_1.Err)(Error(`Invalid response for request of type ${endpoint}: ${JSON.stringify(res, null, 2)}`));
|
|
58
|
+
//console.error(`Got valid response for ${endpoint}`);
|
|
59
|
+
return (0, result_1.Ok)(resData);
|
|
60
|
+
}
|
|
61
|
+
handleSafeMessage(message) {
|
|
62
|
+
if (message.response) {
|
|
63
|
+
//console.log('got response response', message.response.requestId);
|
|
64
|
+
const request = this.safeRequestMap.get(message.response.requestId);
|
|
65
|
+
if (!request) {
|
|
66
|
+
//console.error(`Received response for unknown request ${message.response.requestId}`);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
this.requestMap.delete(message.response.requestId);
|
|
70
|
+
request.resolve(message.response);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (message.event) {
|
|
74
|
+
const { id, generic } = message.event;
|
|
75
|
+
//console.error('got event with id', id);
|
|
76
|
+
if (generic) {
|
|
77
|
+
const listeners = this.listEventListeners(id);
|
|
78
|
+
const args = JSON.parse(generic.json);
|
|
79
|
+
for (const listener of listeners) {
|
|
80
|
+
listener.callback(...(args ?? []));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
emitCrash(errorText) {
|
|
86
|
+
this.sendMessage({
|
|
87
|
+
event: {
|
|
88
|
+
id: (0, crypto_1.randomUUID)(),
|
|
89
|
+
crash: { text: errorText }
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
constructor(port) {
|
|
94
|
+
this.port = port;
|
|
95
|
+
if (!port)
|
|
96
|
+
return;
|
|
97
|
+
port.on('message', (buf) => {
|
|
98
|
+
this.handleSafeMessage(ipc.ExtensionMessage.decode(buf));
|
|
99
|
+
});
|
|
100
|
+
port.on('messageerror', (error) => {
|
|
101
|
+
console.error(`Message error from manager`, error);
|
|
102
|
+
});
|
|
103
|
+
port.on('close', () => {
|
|
104
|
+
console.error(`Parent port closed prematurely`);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
listEventListeners(type) {
|
|
108
|
+
return this.eventListeners.get(type) ?? [];
|
|
109
|
+
}
|
|
110
|
+
subscribe(type, cb) {
|
|
111
|
+
const item = { callback: cb };
|
|
112
|
+
let listeners = this.eventListeners.get(type);
|
|
113
|
+
if (!listeners) {
|
|
114
|
+
this.eventListeners.set(type, [item]);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
listeners.push(item);
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
unsubscribe: () => {
|
|
121
|
+
const listeners = this.eventListeners.get(type) ?? [];
|
|
122
|
+
const index = listeners.indexOf(item);
|
|
123
|
+
if (index != -1) {
|
|
124
|
+
listeners.splice(index, 1);
|
|
125
|
+
if (listeners.length === 0) {
|
|
126
|
+
this.eventListeners.delete(type);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
emit(action, data) {
|
|
133
|
+
const message = ipc.ExtensionMessage.create({
|
|
134
|
+
event: {
|
|
135
|
+
id: action,
|
|
136
|
+
generic: { json: JSON.stringify([data]) }
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
this.sendMessage(message);
|
|
140
|
+
}
|
|
141
|
+
sendMessage(message) {
|
|
142
|
+
this.port.postMessage(ipc.ExtensionMessage.encode(message).finish());
|
|
143
|
+
}
|
|
144
|
+
request2(data, options = {}) {
|
|
145
|
+
const req = extension.Request.create({ requestId: (0, crypto_1.randomUUID)(), data });
|
|
146
|
+
return new Promise((resolve, reject) => {
|
|
147
|
+
let timeout;
|
|
148
|
+
if (options.timeout) {
|
|
149
|
+
timeout = setTimeout(() => resolve((0, result_1.Err)(Error(`request timed out`))), options.timeout);
|
|
150
|
+
}
|
|
151
|
+
const resolver = (response) => {
|
|
152
|
+
clearTimeout(timeout);
|
|
153
|
+
if (response.error) {
|
|
154
|
+
return resolve((0, result_1.Err)(new Error(response.error.errorText)));
|
|
155
|
+
}
|
|
156
|
+
if (!response.data) {
|
|
157
|
+
return resolve((0, result_1.Err)(new Error("No error and no data")));
|
|
158
|
+
}
|
|
159
|
+
resolve((0, result_1.Ok)(response.data));
|
|
160
|
+
};
|
|
161
|
+
try {
|
|
162
|
+
this.safeRequestMap.set(req.requestId, { resolve: resolver });
|
|
163
|
+
this.sendMessage({ request: req });
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
reject(error);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
request(action, data = {}, options = {}) {
|
|
171
|
+
const id = (0, crypto_1.randomUUID)();
|
|
172
|
+
const { rejectOnError = true } = options;
|
|
173
|
+
return new Promise((resolve, reject) => {
|
|
174
|
+
let timeout;
|
|
175
|
+
if (options.timeout) {
|
|
176
|
+
timeout = setTimeout(() => reject(new Error(`request timed out`)), options.timeout);
|
|
177
|
+
}
|
|
178
|
+
const resolver = (message) => {
|
|
179
|
+
clearTimeout(timeout);
|
|
180
|
+
if (message.error && rejectOnError) {
|
|
181
|
+
return reject(message.error.message ?? "Unknown error");
|
|
182
|
+
}
|
|
183
|
+
resolve(message);
|
|
184
|
+
};
|
|
185
|
+
try {
|
|
186
|
+
this.requestMap.set(id, { resolve: resolver });
|
|
187
|
+
const message = {
|
|
188
|
+
envelope: {
|
|
189
|
+
type: 'request',
|
|
190
|
+
action,
|
|
191
|
+
id
|
|
192
|
+
},
|
|
193
|
+
data,
|
|
194
|
+
error: null
|
|
195
|
+
};
|
|
196
|
+
this.port.postMessage(message);
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
reject(error);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
;
|
|
205
|
+
const createHandler = (handler) => {
|
|
206
|
+
const id = (0, crypto_1.randomUUID)();
|
|
207
|
+
exports.bus.subscribe(id, handler);
|
|
208
|
+
return id;
|
|
209
|
+
};
|
|
210
|
+
exports.createHandler = createHandler;
|
|
211
|
+
exports.bus = new Bus(worker_threads_1.parentPort);
|