@vicinae/api 0.9.1 → 0.9.2
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/dist/api/ai.js +2 -41
- package/dist/api/alert.js +8 -21
- package/dist/api/bus.d.ts +10 -7
- package/dist/api/bus.js +0 -33
- package/dist/api/cache.d.ts +64 -73
- package/dist/api/cache.js +163 -14
- package/dist/api/clipboard.d.ts +1 -1
- package/dist/api/clipboard.js +3 -9
- package/dist/api/controls.d.ts +3 -0
- package/dist/api/controls.js +5 -1
- package/dist/api/environment.d.ts +5 -0
- package/dist/api/file-search.d.ts +49 -0
- package/dist/api/file-search.js +49 -0
- package/dist/api/index.d.ts +2 -1
- package/dist/api/index.js +2 -1
- package/dist/api/lib/result.d.ts +3 -1
- package/dist/api/lib/result.js +2 -2
- package/dist/api/preference.js +2 -3
- package/dist/api/proto/application.d.ts +14 -0
- package/dist/api/proto/application.js +207 -37
- package/dist/api/proto/clipboard.js +38 -71
- package/dist/api/proto/common.js +2 -6
- package/dist/api/proto/daemon.js +5 -15
- package/dist/api/proto/extension.d.ts +16 -10
- package/dist/api/proto/extension.js +118 -91
- package/dist/api/proto/file-search.d.ts +42 -0
- package/dist/api/proto/file-search.js +290 -0
- package/dist/api/proto/google/protobuf/struct.js +9 -26
- package/dist/api/proto/ipc.js +53 -100
- package/dist/api/proto/manager.d.ts +2 -0
- package/dist/api/proto/manager.js +54 -49
- package/dist/api/proto/oauth.js +15 -33
- package/dist/api/proto/storage.js +29 -67
- package/dist/api/proto/ui.d.ts +11 -2
- package/dist/api/proto/ui.js +267 -254
- package/dist/api/proto/wlr-clipboard.js +4 -12
- package/dist/api/proto/wm.d.ts +111 -0
- package/dist/api/proto/wm.js +1266 -0
- package/dist/api/raycast/index.d.ts +24 -0
- package/dist/api/raycast/index.js +40 -0
- package/dist/api/raycast/system.d.ts +20 -0
- package/dist/api/raycast/system.js +73 -0
- package/dist/api/raycast/window-management.d.ts +42 -0
- package/dist/api/raycast/window-management.js +82 -0
- package/dist/api/toast.js +47 -5
- package/dist/api/utils.d.ts +5 -11
- package/dist/api/utils.js +20 -31
- package/dist/api/window-management.d.ts +39 -0
- package/dist/api/window-management.js +55 -0
- package/package.json +1 -1
package/dist/api/ai.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.AI = void 0;
|
|
4
|
-
const stream_1 = require("stream");
|
|
5
|
-
const crypto_1 = require("crypto");
|
|
6
|
-
const bus_1 = require("./bus");
|
|
7
4
|
var AI;
|
|
8
5
|
(function (AI) {
|
|
9
6
|
/**
|
|
@@ -36,42 +33,7 @@ var AI;
|
|
|
36
33
|
* ```
|
|
37
34
|
*/
|
|
38
35
|
function ask(prompt, options) {
|
|
39
|
-
|
|
40
|
-
const emitter = new stream_1.EventEmitter();
|
|
41
|
-
const promise = new Promise((resolve, reject) => {
|
|
42
|
-
let answer = "";
|
|
43
|
-
bus_1.bus
|
|
44
|
-
.request("ai.create-completion", {
|
|
45
|
-
prompt,
|
|
46
|
-
options,
|
|
47
|
-
callback: handlerId,
|
|
48
|
-
})
|
|
49
|
-
.then(({ data }) => {
|
|
50
|
-
if (!data.started) {
|
|
51
|
-
reject(new Error("Could not create completion"));
|
|
52
|
-
}
|
|
53
|
-
const { unsubscribe } = bus_1.bus.subscribe(handlerId, (...args) => {
|
|
54
|
-
const data = args[0];
|
|
55
|
-
answer += data.token;
|
|
56
|
-
emitter.emit("data", data.token);
|
|
57
|
-
if (data.done) {
|
|
58
|
-
unsubscribe();
|
|
59
|
-
resolve(answer);
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
if (options?.signal) {
|
|
63
|
-
options.signal.addEventListener("abort", () => {
|
|
64
|
-
bus_1.bus.request("ai.abort-completion");
|
|
65
|
-
unsubscribe();
|
|
66
|
-
resolve(answer);
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
})
|
|
70
|
-
.catch((err) => reject(err));
|
|
71
|
-
});
|
|
72
|
-
return Object.assign(promise, {
|
|
73
|
-
on: emitter.on.bind(emitter),
|
|
74
|
-
});
|
|
36
|
+
throw new Error('not implemented');
|
|
75
37
|
}
|
|
76
38
|
AI.ask = ask;
|
|
77
39
|
/**
|
|
@@ -115,7 +77,6 @@ var AI;
|
|
|
115
77
|
Model["OpenAI_GPT3.5-turbo"] = "openai-gpt-3.5-turbo";
|
|
116
78
|
})(Model = AI.Model || (AI.Model = {}));
|
|
117
79
|
AI.getModels = async () => {
|
|
118
|
-
|
|
119
|
-
return res.data.models;
|
|
80
|
+
throw new Error('not implemented');
|
|
120
81
|
};
|
|
121
82
|
})(AI || (exports.AI = AI = {}));
|
package/dist/api/alert.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.confirmAlert = exports.Alert = void 0;
|
|
4
|
-
const node_crypto_1 = require("node:crypto");
|
|
5
4
|
const bus_1 = require("./bus");
|
|
6
5
|
const ui_1 = require("./proto/ui");
|
|
7
6
|
var Alert;
|
|
@@ -20,22 +19,7 @@ const styleMap = {
|
|
|
20
19
|
};
|
|
21
20
|
const confirmAlert = async (options) => {
|
|
22
21
|
return new Promise(async (resolve) => {
|
|
23
|
-
const handle = (0, node_crypto_1.randomUUID)();
|
|
24
|
-
let confirmCallback = () => { };
|
|
25
|
-
let cancelCallback = () => { };
|
|
26
|
-
const { unsubscribe } = bus_1.bus.subscribe(handle, (...args) => {
|
|
27
|
-
callback(!!args[0]);
|
|
28
|
-
});
|
|
29
|
-
const callback = (value) => {
|
|
30
|
-
if (value)
|
|
31
|
-
confirmCallback();
|
|
32
|
-
else
|
|
33
|
-
cancelCallback();
|
|
34
|
-
unsubscribe();
|
|
35
|
-
resolve(value);
|
|
36
|
-
};
|
|
37
22
|
const req = ui_1.ConfirmAlertRequest.create({
|
|
38
|
-
handle,
|
|
39
23
|
title: options.title,
|
|
40
24
|
description: options.message ?? "Are you sure?",
|
|
41
25
|
rememberUserChoice: false,
|
|
@@ -48,13 +32,16 @@ const confirmAlert = async (options) => {
|
|
|
48
32
|
style: styleMap[options.dismissAction?.style ?? Alert.ActionStyle.Cancel],
|
|
49
33
|
},
|
|
50
34
|
});
|
|
51
|
-
|
|
52
|
-
|
|
35
|
+
const res = await bus_1.bus.turboRequest("ui.confirmAlert", req);
|
|
36
|
+
if (!res.ok)
|
|
37
|
+
return false;
|
|
38
|
+
if (res.value.confirmed) {
|
|
39
|
+
options.primaryAction?.onAction?.();
|
|
53
40
|
}
|
|
54
|
-
|
|
55
|
-
|
|
41
|
+
else {
|
|
42
|
+
options.dismissAction?.onAction?.();
|
|
56
43
|
}
|
|
57
|
-
|
|
44
|
+
resolve(res.value.confirmed);
|
|
58
45
|
});
|
|
59
46
|
};
|
|
60
47
|
exports.confirmAlert = confirmAlert;
|
package/dist/api/bus.d.ts
CHANGED
|
@@ -37,6 +37,7 @@ type Responses = {
|
|
|
37
37
|
type EndpointMapping = {
|
|
38
38
|
"app.list": "app.list";
|
|
39
39
|
"app.open": "app.open";
|
|
40
|
+
"app.getDefault": "app.getDefault";
|
|
40
41
|
"ui.render": "ui.render";
|
|
41
42
|
"ui.showToast": "ui.showToast";
|
|
42
43
|
"ui.hideToast": "ui.hideToast";
|
|
@@ -48,6 +49,14 @@ type EndpointMapping = {
|
|
|
48
49
|
"ui.setSearchText": "ui.setSearchText";
|
|
49
50
|
"ui.confirmAlert": "ui.confirmAlert";
|
|
50
51
|
"ui.getSelectedText": "ui.getSelectedText";
|
|
52
|
+
"wm.ping": "wm.ping";
|
|
53
|
+
"wm.getActiveWindow": "wm.getActiveWindow";
|
|
54
|
+
"wm.getActiveWorkspace": "wm.getActiveWorkspace";
|
|
55
|
+
"wm.getWindows": "wm.getWindows";
|
|
56
|
+
"wm.getWorkspaces": "wm.getWorkspaces";
|
|
57
|
+
"wm.setWindowBounds": "wm.setWindowBounds";
|
|
58
|
+
"fileSearch.search": "fileSearch.search";
|
|
59
|
+
"ui.popToRoot": "ui.popToRoot";
|
|
51
60
|
"storage.get": "storage.get";
|
|
52
61
|
"storage.set": "storage.set";
|
|
53
62
|
"storage.remove": "storage.remove";
|
|
@@ -88,13 +97,7 @@ declare class Bus {
|
|
|
88
97
|
};
|
|
89
98
|
replaceEventHandler(id: string, handler: EventListenerInfo['callback']): void;
|
|
90
99
|
removeEventHandler(id: string): void;
|
|
91
|
-
request2
|
|
92
|
-
timeout?: number;
|
|
93
|
-
}): Promise<Result<extension.ResponseData, Error>>;
|
|
94
|
-
request<T = Record<string, any>>(action: string, data?: Record<string, any>, options?: {
|
|
95
|
-
timeout?: number;
|
|
96
|
-
rejectOnError?: boolean;
|
|
97
|
-
}): Promise<Message<T>>;
|
|
100
|
+
private request2;
|
|
98
101
|
}
|
|
99
102
|
/**
|
|
100
103
|
* IPC bus to communicate with the extension manager.
|
package/dist/api/bus.js
CHANGED
|
@@ -181,39 +181,6 @@ class Bus {
|
|
|
181
181
|
}
|
|
182
182
|
});
|
|
183
183
|
}
|
|
184
|
-
request(action, data = {}, options = {}) {
|
|
185
|
-
const id = (0, crypto_1.randomUUID)();
|
|
186
|
-
const { rejectOnError = true } = options;
|
|
187
|
-
return new Promise((resolve, reject) => {
|
|
188
|
-
let timeout;
|
|
189
|
-
if (options.timeout) {
|
|
190
|
-
timeout = setTimeout(() => reject(new Error(`request timed out`)), options.timeout);
|
|
191
|
-
}
|
|
192
|
-
const resolver = (message) => {
|
|
193
|
-
clearTimeout(timeout);
|
|
194
|
-
if (message.error && rejectOnError) {
|
|
195
|
-
return reject(message.error.message ?? "Unknown error");
|
|
196
|
-
}
|
|
197
|
-
resolve(message);
|
|
198
|
-
};
|
|
199
|
-
try {
|
|
200
|
-
this.requestMap.set(id, { resolve: resolver });
|
|
201
|
-
const message = {
|
|
202
|
-
envelope: {
|
|
203
|
-
type: "request",
|
|
204
|
-
action,
|
|
205
|
-
id,
|
|
206
|
-
},
|
|
207
|
-
data,
|
|
208
|
-
error: null,
|
|
209
|
-
};
|
|
210
|
-
this.port.postMessage(message);
|
|
211
|
-
}
|
|
212
|
-
catch (error) {
|
|
213
|
-
reject(error);
|
|
214
|
-
}
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
184
|
}
|
|
218
185
|
/**
|
|
219
186
|
* IPC bus to communicate with the extension manager.
|
package/dist/api/cache.d.ts
CHANGED
|
@@ -1,56 +1,46 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* @returns the full path to the directory where the data is stored on disk.
|
|
4
|
-
*/
|
|
5
|
-
get storageDirectory(): string;
|
|
6
|
-
/**
|
|
7
|
-
* @returns the data for the given key. If there is no data for the key, `undefined` is returned.
|
|
8
|
-
* @remarks If you want to just check for the existence of a key, use {@link has}.
|
|
9
|
-
*/
|
|
10
|
-
get(key: string): string | undefined;
|
|
11
|
-
/**
|
|
12
|
-
* @returns `true` if data for the key exists, `false` otherwise.
|
|
13
|
-
* @remarks You can use this method to check for entries without affecting the LRU access.
|
|
14
|
-
*/
|
|
15
|
-
has(key: string): boolean;
|
|
16
|
-
/**
|
|
17
|
-
* @returns `true` if the cache is empty, `false` otherwise.
|
|
18
|
-
*/
|
|
19
|
-
get isEmpty(): boolean;
|
|
20
|
-
/**
|
|
21
|
-
* Sets the data for the given key.
|
|
22
|
-
* If the data exceeds the configured `capacity`, the least recently used entries are removed.
|
|
23
|
-
* This also notifies registered subscribers (see {@link subscribe}).
|
|
24
|
-
*/
|
|
25
|
-
set(key: string, data: string): void;
|
|
26
|
-
/**
|
|
27
|
-
* Removes the data for the given key.
|
|
28
|
-
* This also notifies registered subscribers (see {@link subscribe}).
|
|
29
|
-
* @returns `true` if data for the key was removed, `false` otherwise.
|
|
30
|
-
*/
|
|
31
|
-
remove(key: string): boolean;
|
|
32
|
-
/**
|
|
33
|
-
* Clears all stored data.
|
|
34
|
-
* This also notifies registered subscribers (see {@link subscribe}) unless the `notifySubscribers` option is set to `false`.
|
|
35
|
-
*/
|
|
36
|
-
clear(options?: {
|
|
37
|
-
notifySubscribers: boolean;
|
|
38
|
-
}): void;
|
|
1
|
+
export declare namespace Cache {
|
|
39
2
|
/**
|
|
40
|
-
*
|
|
41
|
-
* @returns a function that can be called to remove the subscriber.
|
|
3
|
+
* The options for creating a new {@link Cache}.
|
|
42
4
|
*/
|
|
43
|
-
|
|
5
|
+
interface Options {
|
|
6
|
+
/**
|
|
7
|
+
* If set, the Cache will be namespaced via a subdirectory.
|
|
8
|
+
* This can be useful to separate the caches for individual commands of an extension.
|
|
9
|
+
* By default, the cache is shared between the commands of an extension.
|
|
10
|
+
*/
|
|
11
|
+
namespace?: string;
|
|
12
|
+
/**
|
|
13
|
+
* The capacity in bytes. If the stored data exceeds the capacity, the least recently used data is removed.
|
|
14
|
+
* The default capacity is 10 MB.
|
|
15
|
+
*/
|
|
16
|
+
capacity?: number;
|
|
17
|
+
}
|
|
18
|
+
type Subscriber = (key: string | undefined, data: string | undefined) => void;
|
|
19
|
+
type Subscription = () => void;
|
|
44
20
|
}
|
|
45
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Caching abstraction that stores data on disk and supports LRU (least recently used) access.
|
|
23
|
+
* Values can only be stored as plain text strings, so it is up to you to serialize your data in an appropriate way.
|
|
24
|
+
* For instance, you could store json using `JSON.stringify` and `JSON.parse` it back.
|
|
25
|
+
* If you need to store binary data, you could encode it in base64.
|
|
26
|
+
*
|
|
27
|
+
* Unlike the local storage API, this API exclusively uses the extension's support directory to store its data.
|
|
28
|
+
* No calls to internal Vicinae APIs are required, hence why all methods in this class are synchronous.
|
|
29
|
+
* Another major difference is that cache data is not encrypted, so it's not suitable to store secrets.
|
|
30
|
+
* (local storage currently isn't either, but that will change in the future)
|
|
31
|
+
*/
|
|
32
|
+
export declare class Cache {
|
|
46
33
|
constructor(options?: Cache.Options);
|
|
47
34
|
/**
|
|
48
35
|
* @returns the full path to the directory where the data is stored on disk.
|
|
36
|
+
* @remarks This is provided for informative purpose only. You should not attempt to mutate anything
|
|
37
|
+
* in this directory by yourself. Also note that the way cache data is serialized on disk can (will) change
|
|
38
|
+
* across versions.
|
|
49
39
|
*/
|
|
50
40
|
get storageDirectory(): string;
|
|
51
41
|
/**
|
|
52
|
-
* @returns the data for the given key
|
|
53
|
-
* @remarks
|
|
42
|
+
* @returns the data for the given key, or `undefined` if there is no data.
|
|
43
|
+
* @remarks To solely check for existence of a key, use {@link has}.
|
|
54
44
|
*/
|
|
55
45
|
get(key: string): string | undefined;
|
|
56
46
|
/**
|
|
@@ -59,13 +49,14 @@ export declare class Cache implements AbstractCache {
|
|
|
59
49
|
*/
|
|
60
50
|
has(key: string): boolean;
|
|
61
51
|
/**
|
|
62
|
-
* @returns
|
|
52
|
+
* @returns whether the cache is empty.
|
|
63
53
|
*/
|
|
64
54
|
get isEmpty(): boolean;
|
|
65
55
|
/**
|
|
66
56
|
* Sets the data for the given key.
|
|
67
57
|
* If the data exceeds the configured `capacity`, the least recently used entries are removed.
|
|
68
58
|
* This also notifies registered subscribers (see {@link subscribe}).
|
|
59
|
+
* @remarks An individual cache entry cannot be bigger than the configured capacity. If this happens, an error will be thrown.
|
|
69
60
|
*/
|
|
70
61
|
set(key: string, data: string): void;
|
|
71
62
|
/**
|
|
@@ -86,32 +77,32 @@ export declare class Cache implements AbstractCache {
|
|
|
86
77
|
* @returns a function that can be called to remove the subscriber.
|
|
87
78
|
*/
|
|
88
79
|
subscribe(subscriber: Cache.Subscriber): Cache.Subscription;
|
|
89
|
-
private
|
|
90
|
-
private
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
80
|
+
private keyDataPath;
|
|
81
|
+
private readKeyData;
|
|
82
|
+
private writeKeyData;
|
|
83
|
+
private keyHash;
|
|
84
|
+
private get dataDir();
|
|
85
|
+
private dataPath;
|
|
86
|
+
private get indexPath();
|
|
87
|
+
private updateLRU;
|
|
88
|
+
private popLRU;
|
|
89
|
+
private removeImpl;
|
|
90
|
+
private initIndex;
|
|
91
|
+
private loadIndex;
|
|
92
|
+
private removeCacheDirectory;
|
|
93
|
+
private syncIndex;
|
|
94
|
+
private emptyIndex;
|
|
95
|
+
/**
|
|
96
|
+
* We store this inside the cache index file in order to know
|
|
97
|
+
* when a breaking change occurs.
|
|
98
|
+
* If we want to change the way the data is stored we just change this,
|
|
99
|
+
* which will force a full cache clear and use the new format.
|
|
100
|
+
*/
|
|
101
|
+
private revision;
|
|
102
|
+
private capacity;
|
|
103
|
+
private subscribers;
|
|
104
|
+
private storageDir;
|
|
105
|
+
private index;
|
|
106
|
+
private static DEFAULT_CACHE_SIZE;
|
|
107
|
+
private static CACHE_DIR_NAME;
|
|
116
108
|
}
|
|
117
|
-
export {};
|
package/dist/api/cache.js
CHANGED
|
@@ -1,61 +1,210 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.Cache = void 0;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const node_fs_1 = require("node:fs");
|
|
9
|
+
const node_crypto_1 = require("node:crypto");
|
|
10
|
+
const environment_1 = require("./environment");
|
|
11
|
+
/**
|
|
12
|
+
* Caching abstraction that stores data on disk and supports LRU (least recently used) access.
|
|
13
|
+
* Values can only be stored as plain text strings, so it is up to you to serialize your data in an appropriate way.
|
|
14
|
+
* For instance, you could store json using `JSON.stringify` and `JSON.parse` it back.
|
|
15
|
+
* If you need to store binary data, you could encode it in base64.
|
|
16
|
+
*
|
|
17
|
+
* Unlike the local storage API, this API exclusively uses the extension's support directory to store its data.
|
|
18
|
+
* No calls to internal Vicinae APIs are required, hence why all methods in this class are synchronous.
|
|
19
|
+
* Another major difference is that cache data is not encrypted, so it's not suitable to store secrets.
|
|
20
|
+
* (local storage currently isn't either, but that will change in the future)
|
|
21
|
+
*/
|
|
4
22
|
class Cache {
|
|
5
|
-
constructor(options) {
|
|
23
|
+
constructor(options) {
|
|
24
|
+
this.storageDir = node_path_1.default.join(environment_1.environment.supportPath, Cache.CACHE_DIR_NAME);
|
|
25
|
+
this.capacity = options?.capacity ?? Cache.DEFAULT_CACHE_SIZE;
|
|
26
|
+
if (options?.namespace) {
|
|
27
|
+
this.storageDir = node_path_1.default.join(this.storageDir, options.namespace);
|
|
28
|
+
}
|
|
29
|
+
(0, node_fs_1.mkdirSync)(this.dataDir, { recursive: true });
|
|
30
|
+
this.index = this.loadIndex() ?? this.emptyIndex();
|
|
31
|
+
if (this.index.revision !== this.revision) {
|
|
32
|
+
this.clear();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
6
35
|
/**
|
|
7
36
|
* @returns the full path to the directory where the data is stored on disk.
|
|
37
|
+
* @remarks This is provided for informative purpose only. You should not attempt to mutate anything
|
|
38
|
+
* in this directory by yourself. Also note that the way cache data is serialized on disk can (will) change
|
|
39
|
+
* across versions.
|
|
8
40
|
*/
|
|
9
41
|
get storageDirectory() {
|
|
10
|
-
return
|
|
42
|
+
return this.storageDir;
|
|
11
43
|
}
|
|
12
44
|
/**
|
|
13
|
-
* @returns the data for the given key
|
|
14
|
-
* @remarks
|
|
45
|
+
* @returns the data for the given key, or `undefined` if there is no data.
|
|
46
|
+
* @remarks To solely check for existence of a key, use {@link has}.
|
|
15
47
|
*/
|
|
16
48
|
get(key) {
|
|
17
|
-
|
|
49
|
+
const info = this.index.keys[key];
|
|
50
|
+
if (!info)
|
|
51
|
+
return undefined;
|
|
52
|
+
this.updateLRU(key);
|
|
53
|
+
this.syncIndex();
|
|
54
|
+
return this.readKeyData(key);
|
|
18
55
|
}
|
|
19
56
|
/**
|
|
20
57
|
* @returns `true` if data for the key exists, `false` otherwise.
|
|
21
58
|
* @remarks You can use this method to check for entries without affecting the LRU access.
|
|
22
59
|
*/
|
|
23
60
|
has(key) {
|
|
24
|
-
return
|
|
61
|
+
return typeof this.index.keys[key] !== 'undefined';
|
|
25
62
|
}
|
|
26
63
|
/**
|
|
27
|
-
* @returns
|
|
64
|
+
* @returns whether the cache is empty.
|
|
28
65
|
*/
|
|
29
66
|
get isEmpty() {
|
|
30
|
-
return
|
|
67
|
+
return Object.keys(this.index.keys).length === 0;
|
|
31
68
|
}
|
|
32
69
|
/**
|
|
33
70
|
* Sets the data for the given key.
|
|
34
71
|
* If the data exceeds the configured `capacity`, the least recently used entries are removed.
|
|
35
72
|
* This also notifies registered subscribers (see {@link subscribe}).
|
|
73
|
+
* @remarks An individual cache entry cannot be bigger than the configured capacity. If this happens, an error will be thrown.
|
|
36
74
|
*/
|
|
37
|
-
set(key, data) {
|
|
75
|
+
set(key, data) {
|
|
76
|
+
if (data.length > this.capacity) {
|
|
77
|
+
throw new Error(`A single cache entry cannot be bigger than the total capacity of the cache. The data for key ${key} is ${data.length} bytes long while the capacity is set to ${this.capacity}. You should either reduce the amount of data stored or increase the cache's capacity.`);
|
|
78
|
+
}
|
|
79
|
+
const info = this.index.keys[key];
|
|
80
|
+
let newTotalSize = this.index.size + data.length - (info?.size ?? 0);
|
|
81
|
+
if (newTotalSize > this.capacity) {
|
|
82
|
+
this.popLRU();
|
|
83
|
+
return this.set(key, data); // FIXME: get rid of recursion
|
|
84
|
+
}
|
|
85
|
+
this.index.size = newTotalSize;
|
|
86
|
+
this.index.keys[key] = { size: data.length };
|
|
87
|
+
this.updateLRU(key);
|
|
88
|
+
for (const sub of this.subscribers) {
|
|
89
|
+
sub(key, data);
|
|
90
|
+
}
|
|
91
|
+
this.writeKeyData(key, data);
|
|
92
|
+
this.syncIndex();
|
|
93
|
+
}
|
|
38
94
|
/**
|
|
39
95
|
* Removes the data for the given key.
|
|
40
96
|
* This also notifies registered subscribers (see {@link subscribe}).
|
|
41
97
|
* @returns `true` if data for the key was removed, `false` otherwise.
|
|
42
98
|
*/
|
|
43
99
|
remove(key) {
|
|
44
|
-
|
|
100
|
+
const removed = this.removeImpl(key);
|
|
101
|
+
this.syncIndex();
|
|
102
|
+
return removed;
|
|
45
103
|
}
|
|
46
104
|
/**
|
|
47
105
|
* Clears all stored data.
|
|
48
106
|
* This also notifies registered subscribers (see {@link subscribe}) unless the `notifySubscribers` option is set to `false`.
|
|
49
107
|
*/
|
|
50
|
-
clear(options) {
|
|
108
|
+
clear(options) {
|
|
109
|
+
const notify = options?.notifySubscribers ?? true;
|
|
110
|
+
this.removeCacheDirectory();
|
|
111
|
+
this.initIndex();
|
|
112
|
+
if (!notify)
|
|
113
|
+
return;
|
|
114
|
+
for (const key of Object.keys(this.index.keys)) {
|
|
115
|
+
for (const subscriber of this.subscribers) {
|
|
116
|
+
subscriber(key, undefined);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
51
120
|
/**
|
|
52
121
|
* Registers a new subscriber that gets notified when cache data is set or removed.
|
|
53
122
|
* @returns a function that can be called to remove the subscriber.
|
|
54
123
|
*/
|
|
55
124
|
subscribe(subscriber) {
|
|
56
|
-
|
|
125
|
+
this.subscribers.push(subscriber);
|
|
126
|
+
return () => {
|
|
127
|
+
this.subscribers.splice(this.subscribers.indexOf(subscriber), 1);
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
keyDataPath(key) {
|
|
131
|
+
return this.dataPath(this.keyHash(key));
|
|
132
|
+
}
|
|
133
|
+
readKeyData(key) {
|
|
134
|
+
return (0, node_fs_1.readFileSync)(this.keyDataPath(key), 'utf8');
|
|
135
|
+
}
|
|
136
|
+
writeKeyData(key, data) {
|
|
137
|
+
(0, node_fs_1.writeFileSync)(this.keyDataPath(key), data);
|
|
138
|
+
}
|
|
139
|
+
keyHash(key) {
|
|
140
|
+
return (0, node_crypto_1.hash)('md5', key);
|
|
141
|
+
}
|
|
142
|
+
get dataDir() {
|
|
143
|
+
return node_path_1.default.join(this.storageDir, 'data');
|
|
144
|
+
}
|
|
145
|
+
dataPath(id) {
|
|
146
|
+
return node_path_1.default.join(this.dataDir, id);
|
|
147
|
+
}
|
|
148
|
+
get indexPath() {
|
|
149
|
+
return node_path_1.default.join(this.storageDir, 'index.json');
|
|
57
150
|
}
|
|
58
|
-
|
|
59
|
-
|
|
151
|
+
updateLRU(key) {
|
|
152
|
+
const idx = this.index.lru.findIndex((entry) => key == entry.key);
|
|
153
|
+
if (idx !== -1)
|
|
154
|
+
this.index.lru.splice(idx, 1);
|
|
155
|
+
this.index.lru.unshift({ key, lastUsedAt: Date.now() });
|
|
156
|
+
}
|
|
157
|
+
popLRU() {
|
|
158
|
+
if (this.index.lru.length === 0)
|
|
159
|
+
return;
|
|
160
|
+
this.removeImpl(this.index.lru.pop().key);
|
|
161
|
+
}
|
|
162
|
+
removeImpl(key) {
|
|
163
|
+
const info = this.index.keys[key];
|
|
164
|
+
if (!info)
|
|
165
|
+
return false;
|
|
166
|
+
(0, node_fs_1.rmSync)(this.keyDataPath(key), { force: true });
|
|
167
|
+
this.index.size -= info.size;
|
|
168
|
+
delete this.index.keys[key];
|
|
169
|
+
for (const sub of this.subscribers) {
|
|
170
|
+
sub(key, undefined);
|
|
171
|
+
}
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
initIndex() {
|
|
175
|
+
const index = { revision: this.revision, keys: {}, size: 0, lru: [] };
|
|
176
|
+
(0, node_fs_1.mkdirSync)(this.dataDir, { recursive: true });
|
|
177
|
+
const indexPath = node_path_1.default.join(this.storageDir, "index.json");
|
|
178
|
+
(0, node_fs_1.writeFileSync)(indexPath, JSON.stringify(index, null, 2));
|
|
179
|
+
return index;
|
|
180
|
+
}
|
|
181
|
+
loadIndex() {
|
|
182
|
+
const indexPath = node_path_1.default.join(this.storageDir, "index.json");
|
|
183
|
+
if (!(0, node_fs_1.existsSync)(indexPath))
|
|
184
|
+
return null;
|
|
185
|
+
return JSON.parse((0, node_fs_1.readFileSync)(indexPath, 'utf8'));
|
|
186
|
+
}
|
|
187
|
+
removeCacheDirectory() {
|
|
188
|
+
(0, node_fs_1.rmSync)(this.dataDir, { recursive: true, force: true });
|
|
189
|
+
}
|
|
190
|
+
syncIndex() {
|
|
191
|
+
(0, node_fs_1.writeFileSync)(this.indexPath, JSON.stringify(this.index, null, 2));
|
|
192
|
+
}
|
|
193
|
+
emptyIndex() {
|
|
194
|
+
return { revision: this.revision, keys: {}, lru: [], size: 0 };
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* We store this inside the cache index file in order to know
|
|
198
|
+
* when a breaking change occurs.
|
|
199
|
+
* If we want to change the way the data is stored we just change this,
|
|
200
|
+
* which will force a full cache clear and use the new format.
|
|
201
|
+
*/
|
|
202
|
+
revision = '1';
|
|
203
|
+
capacity;
|
|
204
|
+
subscribers = [];
|
|
205
|
+
storageDir;
|
|
206
|
+
index;
|
|
207
|
+
static DEFAULT_CACHE_SIZE = 1e7;
|
|
208
|
+
static CACHE_DIR_NAME = ".cache";
|
|
60
209
|
}
|
|
61
210
|
exports.Cache = Cache;
|
package/dist/api/clipboard.d.ts
CHANGED
package/dist/api/clipboard.js
CHANGED
|
@@ -34,18 +34,12 @@ exports.Clipboard = {
|
|
|
34
34
|
});
|
|
35
35
|
},
|
|
36
36
|
async read(options) {
|
|
37
|
-
|
|
38
|
-
options,
|
|
39
|
-
});
|
|
40
|
-
return res.data.content;
|
|
37
|
+
throw new Error('Clipboard.read not implemented');
|
|
41
38
|
},
|
|
42
39
|
async readText(options) {
|
|
43
|
-
|
|
44
|
-
options,
|
|
45
|
-
});
|
|
46
|
-
return res.data.content;
|
|
40
|
+
throw new Error('Clipboard.readText not implemented');
|
|
47
41
|
},
|
|
48
42
|
async clear(text) {
|
|
49
|
-
|
|
43
|
+
throw new Error('Clibpoard.clear not implemented');
|
|
50
44
|
},
|
|
51
45
|
};
|
package/dist/api/controls.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
export declare const closeMainWindow: () => Promise<void>;
|
|
2
2
|
export declare const clearSearchBar: () => Promise<void>;
|
|
3
3
|
export declare const getSelectedText: () => Promise<string>;
|
|
4
|
+
export declare const popToRoot: (options?: {
|
|
5
|
+
clearSearchBar?: boolean;
|
|
6
|
+
}) => Promise<void>;
|
package/dist/api/controls.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getSelectedText = exports.clearSearchBar = exports.closeMainWindow = void 0;
|
|
3
|
+
exports.popToRoot = exports.getSelectedText = exports.clearSearchBar = exports.closeMainWindow = void 0;
|
|
4
4
|
const bus_1 = require("./bus");
|
|
5
5
|
const closeMainWindow = async () => {
|
|
6
6
|
await bus_1.bus.turboRequest("ui.closeMainWindow", {});
|
|
@@ -18,3 +18,7 @@ const getSelectedText = async () => {
|
|
|
18
18
|
return response.value.text;
|
|
19
19
|
};
|
|
20
20
|
exports.getSelectedText = getSelectedText;
|
|
21
|
+
const popToRoot = async (options) => {
|
|
22
|
+
await bus_1.bus.turboRequest('ui.popToRoot', { clearSearchBar: options?.clearSearchBar ?? false });
|
|
23
|
+
};
|
|
24
|
+
exports.popToRoot = popToRoot;
|
|
@@ -121,5 +121,10 @@ export interface Environment {
|
|
|
121
121
|
tag: string;
|
|
122
122
|
commit: string;
|
|
123
123
|
};
|
|
124
|
+
/**
|
|
125
|
+
* Whether we run an actual Raycast extension in compatibility mode.
|
|
126
|
+
* This is used internally to provide Raycast-compatible interfaces.
|
|
127
|
+
*/
|
|
128
|
+
isRaycast: boolean;
|
|
124
129
|
}
|
|
125
130
|
export declare const environment: Environment;
|