@qping/plugin-bus 0.2.0 → 0.4.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/dist/actions.d.ts +223 -0
- package/dist/bootstrap.d.ts +3 -1
- package/dist/bootstrap.mjs +5 -1
- package/dist/dev.d.ts +5 -0
- package/dist/dev.mjs +80 -0
- package/dist/developmentRefresh.d.ts +9 -0
- package/dist/hostEnv.d.ts +9 -0
- package/dist/hotkeyKeycaps.d.ts +2 -0
- package/dist/node.d.ts +35 -17
- package/dist/node.mjs +209 -26
- package/dist/protocol.d.ts +1 -0
- package/dist/protocol.mjs +1 -0
- package/dist/router.d.ts +3 -1
- package/dist/search.d.ts +7 -0
- package/dist/search.mjs +17 -0
- package/dist/webClient.d.ts +2 -1
- package/dist/webClient.mjs +26 -1
- package/dist/webTypes.d.ts +15 -0
- package/package.json +60 -50
- package/src/actions.ts +164 -0
- package/src/bootstrap.ts +159 -159
- package/src/dev.ts +14 -0
- package/src/developmentRefresh.ts +95 -0
- package/src/hostEnv.ts +21 -0
- package/src/hotkeyKeycaps.ts +28 -0
- package/src/node.ts +163 -44
- package/src/protocol.ts +1 -0
- package/src/router.ts +199 -196
- package/src/search.ts +22 -0
- package/src/webClient.ts +3 -0
- package/src/webTypes.ts +16 -0
package/dist/node.mjs
CHANGED
|
@@ -167,6 +167,7 @@ var Routes = {
|
|
|
167
167
|
Initialize: "host.event.initialize",
|
|
168
168
|
Search: "host.event.search",
|
|
169
169
|
Key: "host.event.key",
|
|
170
|
+
DetailAction: "host.event.detailAction",
|
|
170
171
|
LanguageChanged: "host.event.languageChanged",
|
|
171
172
|
ThemeChanged: "host.event.themeChanged",
|
|
172
173
|
InputActionCaptured: "host.event.inputActionCaptured"
|
|
@@ -339,7 +340,10 @@ var HandlerRouter = class {
|
|
|
339
340
|
}
|
|
340
341
|
const deadlineMs = deadlineFromTimeoutMs(env.timeoutMs);
|
|
341
342
|
try {
|
|
342
|
-
const result = await requestScope.run(
|
|
343
|
+
const result = await requestScope.run(
|
|
344
|
+
{ deadlineMs },
|
|
345
|
+
() => handler(env.payload, { sessionId: env.sessionId })
|
|
346
|
+
);
|
|
343
347
|
this.send(this.responseFor(env, result ?? {}));
|
|
344
348
|
} catch (err) {
|
|
345
349
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -527,13 +531,120 @@ async function completeHandshake(transport, token, timeoutMs = 1e4) {
|
|
|
527
531
|
});
|
|
528
532
|
}
|
|
529
533
|
|
|
534
|
+
// src/hostEnv.ts
|
|
535
|
+
function asTheme(value) {
|
|
536
|
+
return value === "light" ? "light" : "dark";
|
|
537
|
+
}
|
|
538
|
+
function asHostEnv(payload) {
|
|
539
|
+
return {
|
|
540
|
+
locale: typeof payload?.locale === "string" ? payload.locale : "en-US",
|
|
541
|
+
fallbackLocale: typeof payload?.fallbackLocale === "string" ? payload.fallbackLocale : "en-US",
|
|
542
|
+
theme: asTheme(payload?.theme)
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
// src/actions.ts
|
|
547
|
+
var Key = {
|
|
548
|
+
Enter: "Enter",
|
|
549
|
+
Tab: "Tab",
|
|
550
|
+
Space: "Space",
|
|
551
|
+
Delete: "Delete",
|
|
552
|
+
Backspace: "Backspace",
|
|
553
|
+
Escape: "Escape",
|
|
554
|
+
Left: "Left",
|
|
555
|
+
Right: "Right",
|
|
556
|
+
Up: "Up",
|
|
557
|
+
Down: "Down",
|
|
558
|
+
A: "A",
|
|
559
|
+
B: "B",
|
|
560
|
+
C: "C",
|
|
561
|
+
D: "D",
|
|
562
|
+
E: "E",
|
|
563
|
+
F: "F",
|
|
564
|
+
G: "G",
|
|
565
|
+
H: "H",
|
|
566
|
+
I: "I",
|
|
567
|
+
J: "J",
|
|
568
|
+
K: "K",
|
|
569
|
+
L: "L",
|
|
570
|
+
M: "M",
|
|
571
|
+
N: "N",
|
|
572
|
+
O: "O",
|
|
573
|
+
P: "P",
|
|
574
|
+
Q: "Q",
|
|
575
|
+
R: "R",
|
|
576
|
+
S: "S",
|
|
577
|
+
T: "T",
|
|
578
|
+
U: "U",
|
|
579
|
+
V: "V",
|
|
580
|
+
W: "W",
|
|
581
|
+
X: "X",
|
|
582
|
+
Y: "Y",
|
|
583
|
+
Z: "Z",
|
|
584
|
+
D0: "D0",
|
|
585
|
+
D1: "D1",
|
|
586
|
+
D2: "D2",
|
|
587
|
+
D3: "D3",
|
|
588
|
+
D4: "D4",
|
|
589
|
+
D5: "D5",
|
|
590
|
+
D6: "D6",
|
|
591
|
+
D7: "D7",
|
|
592
|
+
D8: "D8",
|
|
593
|
+
D9: "D9",
|
|
594
|
+
F1: "F1",
|
|
595
|
+
F2: "F2",
|
|
596
|
+
F3: "F3",
|
|
597
|
+
F4: "F4",
|
|
598
|
+
F5: "F5",
|
|
599
|
+
F6: "F6",
|
|
600
|
+
F7: "F7",
|
|
601
|
+
F8: "F8",
|
|
602
|
+
F9: "F9",
|
|
603
|
+
F10: "F10",
|
|
604
|
+
F11: "F11",
|
|
605
|
+
F12: "F12"
|
|
606
|
+
};
|
|
607
|
+
var Modifiers = {
|
|
608
|
+
None: 0,
|
|
609
|
+
Control: 1,
|
|
610
|
+
Alt: 2,
|
|
611
|
+
ControlAlt: 3,
|
|
612
|
+
Shift: 4,
|
|
613
|
+
ControlShift: 5,
|
|
614
|
+
AltShift: 6,
|
|
615
|
+
ControlAltShift: 7
|
|
616
|
+
};
|
|
617
|
+
var HostAction = {
|
|
618
|
+
Copy: "copy",
|
|
619
|
+
CopyAndPaste: "copyAndPaste",
|
|
620
|
+
AddClipboardHistory: "addClipboardHistory",
|
|
621
|
+
Execute: "execute",
|
|
622
|
+
OpenInExplorer: "openInExplorer",
|
|
623
|
+
OpenInBrowser: "openInBrowser",
|
|
624
|
+
OpenPlugin: "openPlugin",
|
|
625
|
+
Run: "run",
|
|
626
|
+
Kill: "kill"
|
|
627
|
+
};
|
|
628
|
+
function toActionManifest(definition) {
|
|
629
|
+
const entry = {
|
|
630
|
+
id: definition.id,
|
|
631
|
+
title: definition.title
|
|
632
|
+
};
|
|
633
|
+
if (definition.description) entry.description = definition.description;
|
|
634
|
+
if (definition.hotkey) entry.hotkey = definition.hotkey;
|
|
635
|
+
return entry;
|
|
636
|
+
}
|
|
637
|
+
|
|
530
638
|
// src/node.ts
|
|
639
|
+
var ItemCacheLimit = 1e3;
|
|
640
|
+
var SessionCacheLimit = 8;
|
|
531
641
|
var Plugin = class {
|
|
532
642
|
#handlers = /* @__PURE__ */ new Map();
|
|
643
|
+
#actions = /* @__PURE__ */ new Map();
|
|
533
644
|
#searchHandler = null;
|
|
534
|
-
#actionHandler = null;
|
|
535
645
|
#initializeHandler = null;
|
|
536
646
|
#runtime = null;
|
|
647
|
+
#itemsBySession = /* @__PURE__ */ new Map();
|
|
537
648
|
initialize(handler) {
|
|
538
649
|
this.#initializeHandler = handler;
|
|
539
650
|
return this;
|
|
@@ -542,8 +653,27 @@ var Plugin = class {
|
|
|
542
653
|
this.#searchHandler = handler;
|
|
543
654
|
return this;
|
|
544
655
|
}
|
|
545
|
-
|
|
546
|
-
|
|
656
|
+
/**
|
|
657
|
+
* Registers every action this plugin offers. The list is sent to the host in the initialize
|
|
658
|
+
* response, so the host knows the ids, labels and hotkeys before any search runs; search items
|
|
659
|
+
* and the detail page then reference them by id only.
|
|
660
|
+
*/
|
|
661
|
+
actions(definitions) {
|
|
662
|
+
if (!Array.isArray(definitions)) {
|
|
663
|
+
throw new Error("plugin.actions requires an array of action definitions.");
|
|
664
|
+
}
|
|
665
|
+
for (const definition of definitions) {
|
|
666
|
+
if (!definition?.id) {
|
|
667
|
+
throw new Error("plugin.actions requires every action to have an id.");
|
|
668
|
+
}
|
|
669
|
+
if (this.#actions.has(definition.id)) {
|
|
670
|
+
throw new Error(`plugin.actions has a duplicate action id: ${definition.id}`);
|
|
671
|
+
}
|
|
672
|
+
if (typeof definition.execute !== "function") {
|
|
673
|
+
throw new Error(`plugin.actions requires an execute function for action: ${definition.id}`);
|
|
674
|
+
}
|
|
675
|
+
this.#actions.set(definition.id, definition);
|
|
676
|
+
}
|
|
547
677
|
return this;
|
|
548
678
|
}
|
|
549
679
|
handle(action, handler) {
|
|
@@ -592,14 +722,19 @@ var Plugin = class {
|
|
|
592
722
|
*/
|
|
593
723
|
buildRoutes() {
|
|
594
724
|
const routes = {};
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
725
|
+
routes[Routes.PluginCall.Initialize] = async (p) => {
|
|
726
|
+
const result = this.#initializeHandler ? await this.#initializeHandler(asInitializeParams(p)) : {};
|
|
727
|
+
const body = result && typeof result === "object" ? { ...result } : {};
|
|
728
|
+
return { ...body, actions: [...this.#actions.values()].map(toActionManifest) };
|
|
729
|
+
};
|
|
598
730
|
if (this.#searchHandler) {
|
|
599
|
-
routes[Routes.PluginCall.Search] = (p) =>
|
|
731
|
+
routes[Routes.PluginCall.Search] = async (p, request) => {
|
|
732
|
+
const result = await this.#searchHandler(asSearchParams(p));
|
|
733
|
+
return { items: this.#trackItems(request?.sessionId ?? "default", result?.items ?? []) };
|
|
734
|
+
};
|
|
600
735
|
}
|
|
601
|
-
if (this.#
|
|
602
|
-
routes[Routes.PluginCall.InvokeAction] = (p) => this.#
|
|
736
|
+
if (this.#actions.size > 0) {
|
|
737
|
+
routes[Routes.PluginCall.InvokeAction] = (p, request) => this.#invokeAction(request?.sessionId ?? "default", p);
|
|
603
738
|
}
|
|
604
739
|
for (const [action, handler] of this.#handlers) {
|
|
605
740
|
const route = pluginCallRoute(action);
|
|
@@ -615,13 +750,69 @@ var Plugin = class {
|
|
|
615
750
|
async stop() {
|
|
616
751
|
if (this.#runtime) await this.#runtime.close();
|
|
617
752
|
}
|
|
753
|
+
/** Remembers the full items and returns the trimmed rows the host actually renders. */
|
|
754
|
+
#trackItems(sessionId, items) {
|
|
755
|
+
const sessionItems = this.#sessionItems(sessionId);
|
|
756
|
+
const wire = [];
|
|
757
|
+
for (const item of items) {
|
|
758
|
+
if (!item || typeof item !== "object") continue;
|
|
759
|
+
const id = typeof item.id === "string" ? item.id : "";
|
|
760
|
+
if (id) {
|
|
761
|
+
sessionItems.delete(id);
|
|
762
|
+
sessionItems.set(id, item);
|
|
763
|
+
}
|
|
764
|
+
wire.push(toWireItem(item));
|
|
765
|
+
}
|
|
766
|
+
while (sessionItems.size > ItemCacheLimit) {
|
|
767
|
+
const oldest = sessionItems.keys().next();
|
|
768
|
+
if (oldest.done) break;
|
|
769
|
+
sessionItems.delete(oldest.value);
|
|
770
|
+
}
|
|
771
|
+
return wire;
|
|
772
|
+
}
|
|
773
|
+
async #invokeAction(sessionId, payload) {
|
|
774
|
+
const env = asHostEnv(payload);
|
|
775
|
+
const actionId = typeof payload?.actionId === "string" ? payload.actionId : "";
|
|
776
|
+
const itemId = typeof payload?.itemId === "string" ? payload.itemId : "";
|
|
777
|
+
const query = typeof payload?.query === "string" ? payload.query : "";
|
|
778
|
+
const definition = this.#actions.get(actionId);
|
|
779
|
+
if (!definition) {
|
|
780
|
+
throw new Error(`unknown action: ${actionId}`);
|
|
781
|
+
}
|
|
782
|
+
const outcome = await definition.execute({
|
|
783
|
+
...env,
|
|
784
|
+
actionId,
|
|
785
|
+
itemId,
|
|
786
|
+
query,
|
|
787
|
+
item: this.#itemsBySession.get(sessionId)?.get(itemId)
|
|
788
|
+
});
|
|
789
|
+
return outcome ?? {};
|
|
790
|
+
}
|
|
791
|
+
#sessionItems(sessionId) {
|
|
792
|
+
const key = sessionId || "default";
|
|
793
|
+
let items = this.#itemsBySession.get(key);
|
|
794
|
+
if (!items) {
|
|
795
|
+
items = /* @__PURE__ */ new Map();
|
|
796
|
+
this.#itemsBySession.set(key, items);
|
|
797
|
+
while (this.#itemsBySession.size > SessionCacheLimit) {
|
|
798
|
+
const oldest = this.#itemsBySession.keys().next();
|
|
799
|
+
if (oldest.done) break;
|
|
800
|
+
this.#itemsBySession.delete(oldest.value);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
return items;
|
|
804
|
+
}
|
|
618
805
|
};
|
|
619
|
-
function
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
theme: asTheme(p?.theme)
|
|
806
|
+
function toWireItem(item) {
|
|
807
|
+
const wire = {
|
|
808
|
+
id: item.id,
|
|
809
|
+
title: item.title
|
|
624
810
|
};
|
|
811
|
+
if (typeof item.subtitle === "string") wire.subtitle = item.subtitle;
|
|
812
|
+
if (typeof item.priority === "number") wire.priority = item.priority;
|
|
813
|
+
if (item.icon) wire.icon = item.icon;
|
|
814
|
+
if (Array.isArray(item.actions)) wire.actions = item.actions.filter((id) => typeof id === "string");
|
|
815
|
+
return wire;
|
|
625
816
|
}
|
|
626
817
|
function asInitializeParams(p) {
|
|
627
818
|
const messages = p?.messages;
|
|
@@ -637,17 +828,6 @@ function asSearchParams(p) {
|
|
|
637
828
|
mode: p?.mode === "plugin" ? "plugin" : "global"
|
|
638
829
|
};
|
|
639
830
|
}
|
|
640
|
-
function asActionParams(p) {
|
|
641
|
-
return {
|
|
642
|
-
...asHostEnv(p),
|
|
643
|
-
itemId: typeof p?.itemId === "string" ? p.itemId : "",
|
|
644
|
-
actionId: typeof p?.actionId === "string" ? p.actionId : "",
|
|
645
|
-
query: typeof p?.query === "string" ? p.query : ""
|
|
646
|
-
};
|
|
647
|
-
}
|
|
648
|
-
function asTheme(value) {
|
|
649
|
-
return value === "light" ? "light" : "dark";
|
|
650
|
-
}
|
|
651
831
|
function isStringRecord(value) {
|
|
652
832
|
return !!value && typeof value === "object" && !Array.isArray(value) && Object.values(value).every((v) => typeof v === "string");
|
|
653
833
|
}
|
|
@@ -663,6 +843,9 @@ function createPlugin() {
|
|
|
663
843
|
return new Plugin();
|
|
664
844
|
}
|
|
665
845
|
export {
|
|
846
|
+
HostAction,
|
|
847
|
+
Key,
|
|
848
|
+
Modifiers,
|
|
666
849
|
Plugin,
|
|
667
850
|
createPlugin
|
|
668
851
|
};
|
package/dist/protocol.d.ts
CHANGED
|
@@ -62,6 +62,7 @@ export declare const Routes: {
|
|
|
62
62
|
readonly Initialize: "host.event.initialize";
|
|
63
63
|
readonly Search: "host.event.search";
|
|
64
64
|
readonly Key: "host.event.key";
|
|
65
|
+
readonly DetailAction: "host.event.detailAction";
|
|
65
66
|
readonly LanguageChanged: "host.event.languageChanged";
|
|
66
67
|
readonly ThemeChanged: "host.event.themeChanged";
|
|
67
68
|
readonly InputActionCaptured: "host.event.inputActionCaptured";
|
package/dist/protocol.mjs
CHANGED
|
@@ -49,6 +49,7 @@ var Routes = {
|
|
|
49
49
|
Initialize: "host.event.initialize",
|
|
50
50
|
Search: "host.event.search",
|
|
51
51
|
Key: "host.event.key",
|
|
52
|
+
DetailAction: "host.event.detailAction",
|
|
52
53
|
LanguageChanged: "host.event.languageChanged",
|
|
53
54
|
ThemeChanged: "host.event.themeChanged",
|
|
54
55
|
InputActionCaptured: "host.event.inputActionCaptured"
|
package/dist/router.d.ts
CHANGED
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
* and correlate their responses. Mirrors the C# MessageBus routing rules on the Node side.
|
|
5
5
|
*/
|
|
6
6
|
import { type Envelope } from "./protocol.ts";
|
|
7
|
-
type Handler = (payload: unknown
|
|
7
|
+
type Handler = (payload: unknown, context: {
|
|
8
|
+
sessionId: string;
|
|
9
|
+
}) => Promise<unknown> | unknown;
|
|
8
10
|
type Sender = (env: Envelope) => void;
|
|
9
11
|
export declare const DefaultHostCallTimeoutMs = 30000;
|
|
10
12
|
/** Remaining ms of the inbound plugin.call timeout, if currently inside a request. */
|
package/dist/search.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns whether every character in `pattern` occurs in `target` in the same order.
|
|
3
|
+
* Matching is case-insensitive and characters do not need to be adjacent.
|
|
4
|
+
*
|
|
5
|
+
* @example isSubsequence("gthb", "GitHub") // true
|
|
6
|
+
*/
|
|
7
|
+
export declare function isSubsequence(pattern: string, target: string): boolean;
|
package/dist/search.mjs
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// src/search.ts
|
|
2
|
+
function isSubsequence(pattern, target) {
|
|
3
|
+
if (!pattern) return true;
|
|
4
|
+
if (!target) return false;
|
|
5
|
+
const needle = pattern.toLowerCase();
|
|
6
|
+
const haystack = target.toLowerCase();
|
|
7
|
+
let patternIndex = 0;
|
|
8
|
+
for (let targetIndex = 0; targetIndex < haystack.length && patternIndex < needle.length; targetIndex += 1) {
|
|
9
|
+
if (haystack[targetIndex] === needle[patternIndex]) {
|
|
10
|
+
patternIndex += 1;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return patternIndex === needle.length;
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
isSubsequence
|
|
17
|
+
};
|
package/dist/webClient.d.ts
CHANGED
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
import { mytoolsI18n } from "./i18n.ts";
|
|
9
9
|
import type { MyToolsThemePayload } from "./webTypes.ts";
|
|
10
10
|
export { mytoolsI18n } from "./i18n.ts";
|
|
11
|
+
export { renderHotkeyKeycaps } from "./hotkeyKeycaps.ts";
|
|
11
12
|
export { HostEvents } from "./webTypes.ts";
|
|
12
|
-
export type { MyToolsHostInitializePayload, MyToolsHostKeyPayload, MyToolsHostSearchPayload, MyToolsInputActionCapturedPayload, MyToolsLanguageChangedPayload, MyToolsThemeChangedPayload, MyToolsThemePayload, } from "./webTypes.ts";
|
|
13
|
+
export type { MyToolsHostActionDefinition, MyToolsHostDetailActionPayload, MyToolsHostInitializePayload, MyToolsHostKeyPayload, MyToolsHostSearchPayload, MyToolsInputActionCapturedPayload, MyToolsLanguageChangedPayload, MyToolsThemeChangedPayload, MyToolsThemePayload, } from "./webTypes.ts";
|
|
13
14
|
export interface WebBusClient {
|
|
14
15
|
/** Sends plugin.call.<method>. Bare names are prefixed; full routes are left as-is. */
|
|
15
16
|
call<T = unknown>(method: string, payload?: unknown, timeoutMs?: number): Promise<T>;
|
package/dist/webClient.mjs
CHANGED
|
@@ -2370,6 +2370,7 @@ var Routes = {
|
|
|
2370
2370
|
Initialize: "host.event.initialize",
|
|
2371
2371
|
Search: "host.event.search",
|
|
2372
2372
|
Key: "host.event.key",
|
|
2373
|
+
DetailAction: "host.event.detailAction",
|
|
2373
2374
|
LanguageChanged: "host.event.languageChanged",
|
|
2374
2375
|
ThemeChanged: "host.event.themeChanged",
|
|
2375
2376
|
InputActionCaptured: "host.event.inputActionCaptured"
|
|
@@ -2379,6 +2380,29 @@ function pluginCallRoute(method) {
|
|
|
2379
2380
|
return method.startsWith(Routes.Prefix.PluginCall) ? method : `${Routes.Prefix.PluginCall}${method}`;
|
|
2380
2381
|
}
|
|
2381
2382
|
|
|
2383
|
+
// src/hotkeyKeycaps.ts
|
|
2384
|
+
function renderHotkeyKeycaps(element, hotkey) {
|
|
2385
|
+
const normalized = hotkey.trim();
|
|
2386
|
+
element.hidden = normalized.length === 0;
|
|
2387
|
+
element.setAttribute("aria-label", normalized);
|
|
2388
|
+
element.classList.add("hotkey-keycaps");
|
|
2389
|
+
const keycaps = normalized.length === 0 ? [] : normalized.split("+").map((token) => createKeycap(token.trim()));
|
|
2390
|
+
element.replaceChildren(...keycaps);
|
|
2391
|
+
}
|
|
2392
|
+
function createKeycap(token) {
|
|
2393
|
+
const keycap = document.createElement("span");
|
|
2394
|
+
keycap.className = "hotkey-keycap";
|
|
2395
|
+
keycap.setAttribute("aria-hidden", "true");
|
|
2396
|
+
if (token.toLowerCase() === "enter" || token.toLowerCase() === "return") {
|
|
2397
|
+
keycap.classList.add("hotkey-keycap-enter");
|
|
2398
|
+
keycap.textContent = "\u21B5";
|
|
2399
|
+
keycap.title = "Enter";
|
|
2400
|
+
} else {
|
|
2401
|
+
keycap.textContent = token;
|
|
2402
|
+
}
|
|
2403
|
+
return keycap;
|
|
2404
|
+
}
|
|
2405
|
+
|
|
2382
2406
|
// src/webTypes.ts
|
|
2383
2407
|
var HostEvents = Routes.HostEvent;
|
|
2384
2408
|
|
|
@@ -2595,5 +2619,6 @@ function handshake(timeoutMs) {
|
|
|
2595
2619
|
export {
|
|
2596
2620
|
HostEvents,
|
|
2597
2621
|
createWebBusClient,
|
|
2598
|
-
mytoolsI18n
|
|
2622
|
+
mytoolsI18n,
|
|
2623
|
+
renderHotkeyKeycaps
|
|
2599
2624
|
};
|
package/dist/webTypes.d.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
export interface MyToolsHostActionDefinition {
|
|
2
|
+
id: string;
|
|
3
|
+
/** Host-localized action display name. */
|
|
4
|
+
name: string;
|
|
5
|
+
/** Host-validated display form, for example `Ctrl+H`; absent means click-only. */
|
|
6
|
+
hotkey?: string | null;
|
|
7
|
+
}
|
|
1
8
|
export interface MyToolsHostInitializePayload {
|
|
2
9
|
protocolVersion: string;
|
|
3
10
|
pluginId: string;
|
|
@@ -10,6 +17,7 @@ export interface MyToolsHostInitializePayload {
|
|
|
10
17
|
fallbackLocale: string;
|
|
11
18
|
translationRevision: string;
|
|
12
19
|
messages: Record<string, string>;
|
|
20
|
+
actions: MyToolsHostActionDefinition[];
|
|
13
21
|
theme?: string;
|
|
14
22
|
themeTokens?: Record<string, string>;
|
|
15
23
|
}
|
|
@@ -29,6 +37,12 @@ export interface MyToolsHostSearchPayload {
|
|
|
29
37
|
export interface MyToolsHostKeyPayload {
|
|
30
38
|
key: string;
|
|
31
39
|
}
|
|
40
|
+
/** Payload explicitly returned in an action outcome's `web.payload`. */
|
|
41
|
+
export interface MyToolsHostDetailActionPayload {
|
|
42
|
+
actionId?: string;
|
|
43
|
+
action?: string;
|
|
44
|
+
[key: string]: unknown;
|
|
45
|
+
}
|
|
32
46
|
export interface MyToolsInputActionCapturedPayload {
|
|
33
47
|
requestId: string;
|
|
34
48
|
cancelled?: boolean;
|
|
@@ -44,6 +58,7 @@ export declare const HostEvents: {
|
|
|
44
58
|
readonly Initialize: "host.event.initialize";
|
|
45
59
|
readonly Search: "host.event.search";
|
|
46
60
|
readonly Key: "host.event.key";
|
|
61
|
+
readonly DetailAction: "host.event.detailAction";
|
|
47
62
|
readonly LanguageChanged: "host.event.languageChanged";
|
|
48
63
|
readonly ThemeChanged: "host.event.themeChanged";
|
|
49
64
|
readonly InputActionCaptured: "host.event.inputActionCaptured";
|
package/package.json
CHANGED
|
@@ -1,50 +1,60 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@qping/plugin-bus",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "v3 message-bus runtime for MyTools plugins (named-pipe transport).",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"files": [
|
|
7
|
-
"dist",
|
|
8
|
-
"src"
|
|
9
|
-
],
|
|
10
|
-
"exports": {
|
|
11
|
-
"./node": {
|
|
12
|
-
"types": "./dist/node.d.ts",
|
|
13
|
-
"import": "./dist/node.mjs",
|
|
14
|
-
"default": "./dist/node.mjs"
|
|
15
|
-
},
|
|
16
|
-
"./protocol": {
|
|
17
|
-
"types": "./dist/protocol.d.ts",
|
|
18
|
-
"import": "./dist/protocol.mjs",
|
|
19
|
-
"default": "./dist/protocol.mjs"
|
|
20
|
-
},
|
|
21
|
-
"./bootstrap": {
|
|
22
|
-
"types": "./dist/bootstrap.d.ts",
|
|
23
|
-
"import": "./dist/bootstrap.mjs",
|
|
24
|
-
"default": "./dist/bootstrap.mjs"
|
|
25
|
-
},
|
|
26
|
-
"./web": {
|
|
27
|
-
"types": "./dist/webClient.d.ts",
|
|
28
|
-
"import": "./dist/webClient.mjs",
|
|
29
|
-
"default": "./dist/webClient.mjs"
|
|
30
|
-
},
|
|
31
|
-
"./i18n": {
|
|
32
|
-
"types": "./dist/i18n.d.ts",
|
|
33
|
-
"import": "./dist/i18n.mjs",
|
|
34
|
-
"default": "./dist/i18n.mjs"
|
|
35
|
-
},
|
|
36
|
-
"./
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@qping/plugin-bus",
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "v3 message-bus runtime for MyTools plugins (named-pipe transport).",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist",
|
|
8
|
+
"src"
|
|
9
|
+
],
|
|
10
|
+
"exports": {
|
|
11
|
+
"./node": {
|
|
12
|
+
"types": "./dist/node.d.ts",
|
|
13
|
+
"import": "./dist/node.mjs",
|
|
14
|
+
"default": "./dist/node.mjs"
|
|
15
|
+
},
|
|
16
|
+
"./protocol": {
|
|
17
|
+
"types": "./dist/protocol.d.ts",
|
|
18
|
+
"import": "./dist/protocol.mjs",
|
|
19
|
+
"default": "./dist/protocol.mjs"
|
|
20
|
+
},
|
|
21
|
+
"./bootstrap": {
|
|
22
|
+
"types": "./dist/bootstrap.d.ts",
|
|
23
|
+
"import": "./dist/bootstrap.mjs",
|
|
24
|
+
"default": "./dist/bootstrap.mjs"
|
|
25
|
+
},
|
|
26
|
+
"./web": {
|
|
27
|
+
"types": "./dist/webClient.d.ts",
|
|
28
|
+
"import": "./dist/webClient.mjs",
|
|
29
|
+
"default": "./dist/webClient.mjs"
|
|
30
|
+
},
|
|
31
|
+
"./i18n": {
|
|
32
|
+
"types": "./dist/i18n.d.ts",
|
|
33
|
+
"import": "./dist/i18n.mjs",
|
|
34
|
+
"default": "./dist/i18n.mjs"
|
|
35
|
+
},
|
|
36
|
+
"./search": {
|
|
37
|
+
"types": "./dist/search.d.ts",
|
|
38
|
+
"import": "./dist/search.mjs",
|
|
39
|
+
"default": "./dist/search.mjs"
|
|
40
|
+
},
|
|
41
|
+
"./dev": {
|
|
42
|
+
"types": "./dist/dev.d.ts",
|
|
43
|
+
"import": "./dist/dev.mjs",
|
|
44
|
+
"default": "./dist/dev.mjs"
|
|
45
|
+
},
|
|
46
|
+
"./package.json": "./package.json"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"i18next": "^25.3.2"
|
|
50
|
+
},
|
|
51
|
+
"scripts": {
|
|
52
|
+
"clean": "node -e \"fs.rmSync('dist',{recursive:true,force:true})\"",
|
|
53
|
+
"build": "npm run clean && node build-sdk.mjs",
|
|
54
|
+
"check": "node build-sdk.mjs"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"esbuild": "^0.25.8",
|
|
58
|
+
"typescript": "^7.0.2"
|
|
59
|
+
}
|
|
60
|
+
}
|