@fluxdeck/sdk 0.0.1

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/LICENSE.md ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mikhail Morozov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # Flux Deck SDK
@@ -0,0 +1,366 @@
1
+ //#region ../bindings/src/JsonValue.d.ts
2
+ type JsonValue = null | string | number | boolean | Array<JsonValue> | JsonObject;
3
+ type JsonObject = {
4
+ [key: string]: JsonValue;
5
+ };
6
+ //#endregion
7
+ //#region ../bindings/src/ServerResponseEvent.d.ts
8
+ type ServerResponseEvent = {
9
+ "event": "getPluginSettings";
10
+ payload: JsonValue;
11
+ };
12
+ //#endregion
13
+ //#region ../bindings/src/GetActionDto.d.ts
14
+ type GetActionDto = {
15
+ id: number;
16
+ uuid: string;
17
+ type: string;
18
+ group: string;
19
+ position: number;
20
+ settings: string | null;
21
+ children: { [key in string]?: Array<GetActionDto> };
22
+ };
23
+ //#endregion
24
+ //#region ../bindings/src/GetColorDto.d.ts
25
+ type GetColorDto = {
26
+ value: string | null;
27
+ };
28
+ //#endregion
29
+ //#region ../bindings/src/GetIconDto.d.ts
30
+ type GetIconDto = {
31
+ id: number | null;
32
+ path: string;
33
+ version: number;
34
+ color: string | null;
35
+ scale: number | null;
36
+ mode: string | null;
37
+ };
38
+ //#endregion
39
+ //#region ../bindings/src/TextAlign.d.ts
40
+ type TextAlign = "top" | "middle" | "bottom";
41
+ //#endregion
42
+ //#region ../bindings/src/GetTitleDto.d.ts
43
+ type GetTitleDto = {
44
+ value: string | null;
45
+ align: TextAlign | null;
46
+ font: string | null;
47
+ color: string | null;
48
+ size: number | null;
49
+ };
50
+ //#endregion
51
+ //#region ../bindings/src/GetStateSnapshotDto.d.ts
52
+ type GetStateSnapshotDto = {
53
+ id: number | null;
54
+ title: GetTitleDto | null;
55
+ icon: GetIconDto | null;
56
+ color: GetColorDto | null;
57
+ };
58
+ //#endregion
59
+ //#region ../bindings/src/GetItemStateDto.d.ts
60
+ type GetItemStateDto = {
61
+ id: number;
62
+ boardId: number;
63
+ row: number;
64
+ col: number;
65
+ state: GetStateSnapshotDto;
66
+ };
67
+ //#endregion
68
+ //#region ../bindings/src/GetPageDto.d.ts
69
+ type GetPageDto = {
70
+ boardId: number;
71
+ position: number;
72
+ name: string | null;
73
+ icon: string | null;
74
+ };
75
+ //#endregion
76
+ //#region ../bindings/src/GetBoardStateDto.d.ts
77
+ type GetBoardStateDto = {
78
+ boardId: number;
79
+ page: GetPageDto | null;
80
+ items: Array<GetItemStateDto>;
81
+ };
82
+ //#endregion
83
+ //#region ../bindings/src/GetLayoutDto.d.ts
84
+ type GetLayoutDto = {
85
+ profileId: number;
86
+ rows: number | null;
87
+ cols: number | null;
88
+ };
89
+ //#endregion
90
+ //#region ../bindings/src/GetStyleDto.d.ts
91
+ type GetStyleDto = {
92
+ profileId: number;
93
+ spacing: number | null;
94
+ itemBorder: number | null;
95
+ itemBorderColor: string | null;
96
+ itemBorderRadius: number | null;
97
+ itemBackgroundColor: string | null;
98
+ itemBackgroundImage: string | null;
99
+ backgroundImage: string | null;
100
+ backgroundColor: string | null;
101
+ };
102
+ //#endregion
103
+ //#region ../bindings/src/GetProfileStateDto.d.ts
104
+ type GetProfileStateDto = {
105
+ boardId: number;
106
+ pageId: number;
107
+ boards: Array<GetBoardStateDto>;
108
+ layout: GetLayoutDto;
109
+ style: GetStyleDto;
110
+ };
111
+ //#endregion
112
+ //#region ../bindings/src/ServerEvent.d.ts
113
+ type ServerEvent = {
114
+ "event": "trigger";
115
+ itemId: number;
116
+ action: GetActionDto;
117
+ kind: string;
118
+ } | {
119
+ "event": "sendToPlugin";
120
+ name: string;
121
+ payload: JsonValue;
122
+ } | {
123
+ "event": "sendToEditor";
124
+ name: string;
125
+ payload: JsonValue;
126
+ } | {
127
+ "event": "setPluginSettings";
128
+ name: string;
129
+ payload: JsonValue;
130
+ } | {
131
+ "event": "profileState";
132
+ payload: GetProfileStateDto;
133
+ } | {
134
+ "event": "boardState";
135
+ payload: GetBoardStateDto;
136
+ } | {
137
+ "event": "itemsState";
138
+ payload: Array<GetItemStateDto>;
139
+ } | {
140
+ "event": "styleState";
141
+ payload: GetStyleDto;
142
+ } | {
143
+ "event": "layoutState";
144
+ payload: GetLayoutDto;
145
+ };
146
+ //#endregion
147
+ //#region src/event-emitter.d.ts
148
+ type Listener<T> = (payload: T) => void;
149
+ //#endregion
150
+ //#region src/editor.d.ts
151
+ type SaveHandler = () => unknown;
152
+ declare class Editor {
153
+ private connection;
154
+ private bridge;
155
+ private params;
156
+ private saveHandler?;
157
+ private eventEmitter;
158
+ constructor();
159
+ onRecieveFromPlugin<T>(listener: Listener<T>): Promise<() => void>;
160
+ sendToPlugin<T extends JsonValue>(data: T): void;
161
+ getActionSettings(): Promise<JsonValue>;
162
+ onActionSave(handler: SaveHandler): () => void;
163
+ getPluginSettings(): Promise<ServerResponseEvent>;
164
+ setPluginSettings(data: JsonValue): Promise<void>;
165
+ }
166
+ //#endregion
167
+ //#region ../bindings/src/ClientRequestEvent.d.ts
168
+ type ClientRequestEvent = {
169
+ "event": "getPluginSettings";
170
+ name: string;
171
+ };
172
+ //#endregion
173
+ //#region src/types/connection.d.ts
174
+ type Handler<T extends ServerEvent["event"]> = (data: Extract<ServerEvent, {
175
+ event: T;
176
+ }>) => void;
177
+ type ResponseFor$1<T extends ClientRequestEvent["event"]> = Extract<ServerResponseEvent, {
178
+ event: T;
179
+ }>;
180
+ //#endregion
181
+ //#region ../bindings/src/SetPageIdPayload.d.ts
182
+ type SetPageIdPayload = {
183
+ profileId: number;
184
+ pageId: number;
185
+ };
186
+ //#endregion
187
+ //#region ../bindings/src/ClientEvent.d.ts
188
+ type ClientEvent = {
189
+ "event": "editorRegister";
190
+ payload: string;
191
+ } | {
192
+ "event": "pluginRegister";
193
+ payload: string;
194
+ } | {
195
+ "event": "sendToPlugin";
196
+ name: string;
197
+ payload: JsonValue;
198
+ } | {
199
+ "event": "sendToEditor";
200
+ name: string;
201
+ payload: JsonValue;
202
+ } | {
203
+ "event": "setPluginSettings";
204
+ name: string;
205
+ payload: JsonValue;
206
+ } | {
207
+ "event": "press";
208
+ payload: number;
209
+ } | {
210
+ "event": "release";
211
+ payload: number;
212
+ } | {
213
+ "event": "setPageId";
214
+ payload: SetPageIdPayload;
215
+ } | {
216
+ "event": "clientRegister";
217
+ payload: number;
218
+ };
219
+ //#endregion
220
+ //#region src/connection.d.ts
221
+ type ConnectionOptions = {
222
+ autoreconnect?: boolean;
223
+ };
224
+ declare class Connection {
225
+ private url;
226
+ private ws?;
227
+ private handlers;
228
+ private pendingRequests;
229
+ private options;
230
+ private status;
231
+ private resolve?;
232
+ private reject?;
233
+ private connectionPromise;
234
+ constructor(options?: ConnectionOptions);
235
+ private createBackoff;
236
+ reconnect(): void;
237
+ connect(): void;
238
+ close(): void;
239
+ private send;
240
+ sendEvent(event: ClientEvent): Promise<void>;
241
+ on<T extends ServerEvent["event"]>(event: T, handler: Handler<T>): () => void;
242
+ private onMessage;
243
+ request<E extends ClientRequestEvent>(event: E): Promise<ResponseFor$1<E["event"]>>;
244
+ }
245
+ //#endregion
246
+ //#region src/types/bridge.d.ts
247
+ type MessageHandler<T extends keyof EventRequests> = (payload: EventRequests[T], event: MessageEvent, respond?: (responsePayload: ResponseFor<T>) => void) => void;
248
+ type BridgeOptions = {
249
+ targetOrigin?: string;
250
+ timeout?: number;
251
+ debug?: boolean;
252
+ };
253
+ type MessageMeta = {
254
+ timestamp: number;
255
+ requestId?: number;
256
+ isRequest?: boolean;
257
+ isResponse?: boolean;
258
+ };
259
+ type BridgeMessage<T> = {
260
+ type: string;
261
+ payload: T;
262
+ meta: MessageMeta;
263
+ };
264
+ interface EventRequests {
265
+ SET_ACTION_SETTINGS: {
266
+ id: string;
267
+ };
268
+ GET_ACTION_SETTINGS: {
269
+ id: string;
270
+ };
271
+ }
272
+ interface EventResponses {
273
+ SET_ACTION_SETTINGS: {
274
+ settings: string | null;
275
+ };
276
+ GET_ACTION_SETTINGS: {
277
+ settings: string | null;
278
+ };
279
+ }
280
+ type ResponseFor<T extends keyof EventRequests> = T extends keyof EventResponses ? EventResponses[T] : never;
281
+ //#endregion
282
+ //#region src/bridge.d.ts
283
+ declare class Bridge<T extends keyof EventRequests = keyof EventRequests> {
284
+ private options;
285
+ private handlers;
286
+ private pendingRequests;
287
+ private requestId;
288
+ private isParent;
289
+ private target;
290
+ constructor(options?: BridgeOptions);
291
+ private init;
292
+ /**
293
+ * Установить цель для отправки сообщений (для родительского окна)
294
+ */
295
+ setTarget(iframeElement: HTMLIFrameElement): void;
296
+ /**
297
+ * Получить целевое окно для отправки сообщений
298
+ */
299
+ private getTargetWindow;
300
+ /**
301
+ * Обработка входящих сообщений
302
+ */
303
+ private handleMessage;
304
+ /**
305
+ * Отправить сообщение
306
+ */
307
+ send(type: string, payload?: unknown): void;
308
+ /**
309
+ * Отправить запрос и ждать ответа
310
+ */
311
+ request(type: T, payload: EventRequests[T], timeout?: number): Promise<ResponseFor<T>>;
312
+ /**
313
+ * Отправить ответ на запрос
314
+ */
315
+ private sendResponse;
316
+ /**
317
+ * Обработать ответ на запрос
318
+ */
319
+ private handleResponse;
320
+ /**
321
+ * Подписаться на событие
322
+ */
323
+ on(type: T, handler: MessageHandler<T>): () => void;
324
+ /**
325
+ * Отписаться от события
326
+ */
327
+ off(type: string): void;
328
+ /**
329
+ * Подписаться на событие один раз
330
+ */
331
+ once(type: T, handler: MessageHandler<T>): () => void;
332
+ /**
333
+ * Очистить все обработчики
334
+ */
335
+ destroy(): void;
336
+ }
337
+ //#endregion
338
+ //#region src/plugin.d.ts
339
+ type ActionData<T> = {
340
+ trigger: string;
341
+ settings: T;
342
+ };
343
+ interface Action<T> {
344
+ name: string;
345
+ onTrigger?: (data: ActionData<T>) => void;
346
+ }
347
+ declare class FluxDeck {
348
+ private connection;
349
+ private actions;
350
+ private pluginName?;
351
+ private eventEmitter;
352
+ constructor();
353
+ connect(): void;
354
+ private parseSettings;
355
+ private registerPlugin;
356
+ registerAction<T>(action: Action<T>): void;
357
+ onSetSettings<T>(listener: Listener<T>): Promise<() => void>;
358
+ onRecieveFromEditor<T>(listener: Listener<T>): Promise<() => void>;
359
+ sendToEditor<T extends JsonValue>(data: T): void;
360
+ getPluginSettings(): Promise<ServerResponseEvent>;
361
+ setPluginSettings<T extends JsonValue>(data: T): Promise<void>;
362
+ }
363
+ declare const fluxDeck: FluxDeck;
364
+ //#endregion
365
+ export { Action, ActionData, Bridge, type BridgeMessage, type BridgeOptions, Connection, Editor, FluxDeck, type MessageHandler, fluxDeck };
366
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../bindings/src/JsonValue.ts","../../bindings/src/ServerResponseEvent.ts","../../bindings/src/GetActionDto.ts","../../bindings/src/GetColorDto.ts","../../bindings/src/GetIconDto.ts","../../bindings/src/TextAlign.ts","../../bindings/src/GetTitleDto.ts","../../bindings/src/GetStateSnapshotDto.ts","../../bindings/src/GetItemStateDto.ts","../../bindings/src/GetPageDto.ts","../../bindings/src/GetBoardStateDto.ts","../../bindings/src/GetLayoutDto.ts","../../bindings/src/GetStyleDto.ts","../../bindings/src/GetProfileStateDto.ts","../../bindings/src/ServerEvent.ts","../src/event-emitter.ts","../src/editor.ts","../../bindings/src/ClientRequestEvent.ts","../src/types/connection.ts","../../bindings/src/SetPageIdPayload.ts","../../bindings/src/ClientEvent.ts","../src/connection.ts","../src/types/bridge.ts","../src/bridge.ts","../src/plugin.ts"],"sourcesContent":[],"mappings":";KAEY,SAAA,sCAAgD,MAAM,aAAa;AAAnE,KAA2F,UAAA,GAAlF;EAA6C,CAAA,GAAA,EAAA,MAAA,CAAA,EAAmE,SAAnE;CAAN;;;AAAhD,KCCA,mBAAA,GDDS;EAA6C,OAAA,EAAA,mBAAA;EAAN,OAAA,ECCe,SDDf;CAAmB;;;KEAnE,YAAA;EFAA,EAAA,EAAA,MAAA;EAAsD,IAAA,EAAA,MAAA;EAAN,IAAA,EAAA,MAAA;EAAmB,KAAA,EAAA,MAAA;EAAU,QAAA,EAAA,MAAA;EAAc,QAAA,EAAA,MAAU,GAAA,IAAA;gCEA4C,MAAM;ADCnK,CAAA;;;KEDY,WAAA;EHAA,KAAA,EAAA,MAAS,GAAA,IAAA;CAA6C;;;KIAtD,UAAA;EJAA,EAAA,EAAA,MAAA,GAAS,IAAA;EAA6C,IAAA,EAAA,MAAA;EAAN,OAAA,EAAA,MAAA;EAAmB,KAAA,EAAA,MAAA,GAAA,IAAA;EAAU,KAAA,EAAA,MAAA,GAAA,IAAA;EAAc,IAAA,EAAA,MAAA,GAAU,IAAA;;;;KKArG,SAAA;;;ALAA,KMCA,WAAA,GNDS;EAA6C,KAAA,EAAA,MAAA,GAAA,IAAA;EAAN,KAAA,EMCH,SNDG,GAAA,IAAA;EAAmB,IAAA,EAAA,MAAA,GAAA,IAAA;EAAU,KAAA,EAAA,MAAA,GAAA,IAAA;EAAc,IAAA,EAAA,MAAA,GAAU,IAAA;;;;AAArD,KOGhD,mBAAA,GPHgD;EAAmB,EAAA,EAAA,MAAA,GAAA,IAAA;EAAU,KAAA,EOG3B,WPH2B,GAAA,IAAA;EAAc,IAAA,EOGf,UPHyB,GAAA,IAAA;SOGC;;;;APHtG,KQCA,eAAA,GRDS;EAA6C,EAAA,EAAA,MAAA;EAAN,OAAA,EAAA,MAAA;EAAmB,GAAA,EAAA,MAAA;EAAU,GAAA,EAAA,MAAA;EAAc,KAAA,EQCT,mBRDuC;;;;KSAzH,UAAA;ETAA,OAAA,EAAA,MAAS;EAA6C,QAAA,EAAA,MAAA;EAAN,IAAA,EAAA,MAAA,GAAA,IAAA;EAAmB,IAAA,EAAA,MAAA,GAAA,IAAA;CAAU;;;AAAvB,KUEtD,gBAAA,GVFsD;EAAN,OAAA,EAAA,MAAA;EAAmB,IAAA,EUEvB,UVFuB,GAAA,IAAA;EAAU,KAAA,EUEP,KVFO,CUED,eVFC,CAAA;AAAE,CAAA;;;KWA/E,YAAA;EXAA,SAAA,EAAA,MAAS;EAA6C,IAAA,EAAA,MAAA,GAAA,IAAA;EAAN,IAAA,EAAA,MAAA,GAAA,IAAA;CAAmB;;;KYAnE,WAAA;EZAA,SAAA,EAAA,MAAS;EAA6C,OAAA,EAAA,MAAA,GAAA,IAAA;EAAN,UAAA,EAAA,MAAA,GAAA,IAAA;EAAmB,eAAA,EAAA,MAAA,GAAA,IAAA;EAAU,gBAAA,EAAA,MAAA,GAAA,IAAA;EAAc,mBAAU,EAAA,MAAoB,GAAA,IAAA;;;;ACCrI,CAAA;;;ADD4D,KaGhD,kBAAA,GbHgD;EAAmB,OAAA,EAAA,MAAA;EAAU,MAAA,EAAA,MAAA;EAAc,MAAA,EaG3B,KbHqC,CaG/B,gBbHmD,CAAA;UaGxB;SAAqB;;;;KCItH,WAAA;;;EbNA,MAAA,EaM4D,YbN5D;;;;ECDA,IAAA,EAAA,MAAA;WYO8I;;;EXP9I,IAAA,EAAA,MAAA;WWO+M;;;EVP/M,IAAA,EAAA,MAAA;WUOqR;;;ETPrR,OAAA,ESOwU,kBTP/T;;;WSOyX;ARN9Y,CAAA,GAAY;;WQM0b,MAAM;;EPJhc,OAAA,EAAA,YAAA;EAAkD,OAAA,EOIsc,WPJtc;CAA0B,GAAA;EAA0B,OAAA,EAAA,aAAA;EAAW,OAAA,EOI2b,YPJ3b;;;;APHjH,KeAA,QfAS,CAAA,CAAA,CAAA,GAAA,CAAA,OAAA,EeAe,CfAf,EAAA,GAAA,IAAA;;;KgBGhB,WAAA,GhBH6D,GAAA,GAAA,OAAA;AAAN,cgBU/C,MAAA,ChBV+C;EAAmB,QAAA,UAAA;EAAU,QAAA,MAAA;EAAc,QAAA,MAAU;;;;ECCrG,mBAAA,CAAA,CAAA,CAAmB,CAAA,QAAA,EekEU,QflEkC,CekEzB,CflEyB,CAAS,CAAA,EekEhC,OflEgC,CAAA,GAAA,GAAA,IAAA,CAAA;yBesE3D,iBAAiB;uBAQb,QAAQ;wBAqBb;EdpGZ,iBAAY,CAAA,CAAA,Ec4GC,Od5G0I,CcoGhI,mBAAA,CdpG+H;0BcmHlI,YAAS;;;;KCnH7B,kBAAA;EjBAA,OAAA,EAAA,mBAAS;EAA6C,IAAA,EAAA,MAAA;CAAN;;;AAAA,KkBEhD,OlBFgD,CAAA,UkBE9B,WlBF8B,CAAA,OAAA,CAAA,CAAA,GAAA,CAAA,IAAA,EkBGpD,OlBHoD,CkBG5C,WlBH4C,EAAA;EAAmB,KAAA,EkBGzC,ClBHyC;CAAU,CAAA,EAAA,GAAA,IAAA;KkBmB7E,wBAAsB,+BAA+B,QAC/D;EhBpBU,KAAA,EgBqBD,ChBrBC;;;;KiBAA,gBAAA;EnBAA,SAAA,EAAA,MAAS;EAA6C,MAAA,EAAA,MAAA;CAAN;;;AAAM,KoBEtD,WAAA,GpBFsD;EAAN,OAAA,EAAA,gBAAA;EAAmB,OAAA,EAAA,MAAA;CAAU,GAAA;EAAc,OAAA,EAAA,gBAA8B;;;;ECCzH,IAAA,EAAA,MAAA;WmBCoK;;;ElBFpK,IAAA,EAAA,MAAA;WkBEqO;;;EjBFrO,IAAA,EAAA,MAAA;WiBE2S;;;EhBF3S,OAAA,EAAA,MAAU;;;;ACAtB,CAAA,GAAY;;WeE+a;;EdD/a,OAAA,EAAA,gBAAW;;;;;KekBlB,iBAAA,GrBnB0E;EAAU,aAAA,CAAA,EAAA,OAAA;AAAE,CAAA;cqBuB9E,UAAA;;;EpBtBD,QAAA,QAAA;;;;ECDA,QAAA,OAAY;;;wBmB6CD;ElB7CX,QAAA,aAAW;;;;ECAX,QAAA,IAAA;mBiB4Ha,cAAc;eAIxB,6BACJ,YACE,QAAQ;;EhBlIT,OAAA,CAAA,UgBwKc,kBhBxKL,CAAA,CAAA,KAAA,EgByKV,ChBzKU,CAAA,EgB0KhB,OhB1KgB,CgB0KR,ahB1KQ,CgB0KI,ChB1KJ,CAAA,OAAA,CAAA,CAAA,CAAA;;;;KiBFT,+BAA+B,2BAChC,cAAc,WAChB,0CACqB,YAAY;AtBD9B,KsBIA,aAAA,GtBJS;EAA6C,YAAA,CAAA,EAAA,MAAA;EAAN,OAAA,CAAA,EAAA,MAAA;EAAmB,KAAA,CAAA,EAAA,OAAA;CAAU;AAAc,KsBU3F,WAAA,GtBVqG;;;;ECCrG,UAAA,CAAA,EAAA,OAAA;;KqBgBA;;EpBjBA,OAAA,EoBmBD,CpBnBC;QoBoBJ;;AlBpBI,UkB6BK,aAAA,ClB7BK;;;;ECAV,mBAAS,EAAA;;;;ACCT,UgBiCK,cAAA,ChBjCwC;;;;ECE7C,mBAAA,EAAA;IAAkD,QAAA,EAAA,MAAA,GAAA,IAAA;EAA0B,CAAA;;AAAqC,KeoCjH,WfpCiH,CAAA,UAAA,MeoCrF,afpCqF,CAAA,GeqC3H,CfrC2H,SAAA,MeqC3G,cfrC2G,GeqC1F,cfrC0F,CeqC3E,CfrC2E,CAAA,GAAA,KAAA;;;APHjH,cuBUC,MvBVQ,CAAA,UAAA,MuBUe,avBVf,GAAA,MuBUqC,avBVrC,CAAA,CAAA;EAA6C,QAAA,OAAA;EAAN,QAAA,QAAA;EAAmB,QAAA,eAAA;EAAU,QAAA,SAAA;EAAc,QAAA,QAAU;;wBuBkB1F;;EtBjBX;;;2BsBgDe;ErBjDf;;;;ECAA;;;;ECAA;;;;ECAA;;;gBkBiKF,YACG,cAAc,uBAEtB,QAAQ,YAAY;EjBnKb;;;;ECEA;;;EAAsG,QAAA,cAAA;EAAW;;;WgB2PlH,YAAY,eAAe;Ef7P1B;;;;ECDA;;;ac6QC,YAAY,eAAe;Eb3Q5B;;;EAAsE,OAAA,CAAA,CAAA,EAAA,IAAA;;;;AVFhB,KwBEtD,UxBFsD,CAAA,CAAA,CAAA,GAAA;EAAN,OAAA,EAAA,MAAA;EAAmB,QAAA,EwBInE,CxBJmE;CAAU;AAAc,UwBOtF,MxBPgG,CAAA,CAAA,CAAA,CAAA;;qBwBS5F,WAAW;;AvBRpB,cuBWC,QAAA,CvBXkB;;;;ECDnB,QAAA,YAAY;;;;ECAZ,QAAA,cAAW;4BqBwEK,OAAO;6BAIA,SAAS,KAAE;mCAUL,SAAS,KAAE;EpBtFxC,YAAA,CAAU,UoB0FG,SpB1FH,CAAA,CAAA,IAAA,EoB0FoB,CpB1FpB,CAAA,EAAA,IAAA;uBoBsGG,QAZkB,mBAAA;8BAuBP,iBAAiB,IAAC;;AnBjH1C,cmB8HC,QnB9HQ,EmB8HA,QnB9HA"}
package/dist/index.mjs ADDED
@@ -0,0 +1,2 @@
1
+ import{nanoid as e}from"nanoid";var t=class{options;handlers;pendingRequests;requestId;isParent;target;constructor(e={}){this.options={targetOrigin:`*`,timeout:5e3,debug:!1,...e},this.handlers=new Map,this.pendingRequests=new Map,this.requestId=0,this.isParent=window.parent!==window,this.target=null,this.init()}init(){window.addEventListener(`message`,this.handleMessage.bind(this)),this.options.debug&&console.log(`[IframeBridge] Инициализирован`,{isParent:this.isParent,targetOrigin:this.options.targetOrigin})}setTarget(e){e instanceof HTMLIFrameElement?this.target=e.contentWindow:console.error(`[IframeBridge] Неверный элемент iframe`)}getTargetWindow(){return this.isParent?window.parent:this.target?this.target:(console.error(`[IframeBridge] Target не установлен. Используйте setTarget() для родительского окна`),null)}handleMessage(e){if(this.options.targetOrigin!==`*`&&e.origin!==this.options.targetOrigin){this.options.debug&&console.warn(`[IframeBridge] Сообщение от неизвестного origin:`,e.origin);return}let{type:t,payload:n,meta:r}=e.data;if(!t)return;if(this.options.debug&&console.log(`[IframeBridge] Получено сообщение:`,{type:t,payload:n,_meta:r}),r?.isResponse&&r?.requestId!==void 0){this.handleResponse(r.requestId,n);return}let i=this.handlers.get(t);i&&(r?.isRequest&&r?.requestId!==void 0?i(n,e,t=>{this.sendResponse(r.requestId,t,e.source)}):i(n,e))}send(e,t={}){let n=this.getTargetWindow();if(!n)return;let r={type:e,payload:t,meta:{timestamp:Date.now()}};n.postMessage(r,this.options.targetOrigin),this.options.debug&&console.log(`[IframeBridge] Отправлено сообщение:`,r)}request(e,t,n=this.options.timeout){return new Promise((r,i)=>{let a=this.getTargetWindow();if(!a){i(Error(`Target window не найден`));return}let o=++this.requestId,s=window.setTimeout(()=>{this.pendingRequests.delete(o),i(Error(`Request timeout: ${e}`))},n);this.pendingRequests.set(o,{resolve:r,reject:i,timeoutId:s});let c={type:e,payload:t,meta:{requestId:o,isRequest:!0,timestamp:Date.now()}};a.postMessage(c,this.options.targetOrigin),this.options.debug&&console.log(`[IframeBridge] Отправлен запрос:`,c)})}sendResponse(e,t,n){let r={type:`__response__`,payload:t,meta:{requestId:e,isResponse:!0,timestamp:Date.now()}};n.postMessage(r,this.options.targetOrigin),this.options.debug&&console.log(`[IframeBridge] Отправлен ответ:`,r)}handleResponse(e,t,n){let r=this.pendingRequests.get(e);r&&(clearTimeout(r.timeoutId),this.pendingRequests.delete(e),n?r.reject(Error(n)):r.resolve(t))}on(e,t){return this.handlers.set(e,t),()=>this.off(e)}off(e){this.handlers.delete(e)}once(e,t){return this.on(e,(...n)=>{t(...n),this.off(e)})}destroy(){this.handlers.clear(),this.pendingRequests.forEach(({timeoutId:e})=>clearTimeout(e)),this.pendingRequests.clear(),window.removeEventListener(`message`,this.handleMessage.bind(this)),this.options.debug&&console.log(`[IframeBridge] Уничтожен`)}},n=t;function r(){return typeof process<`u`?`localhost`:location.hostname}const i={DISCONNECTED:0,CONNECTING:1,CONNECTED:2};var a=class{url=`ws://${r()}:3001/ws`;ws;handlers=[];pendingRequests=new Map;options={autoreconnect:!0};status=i.DISCONNECTED;resolve;reject;connectionPromise=new Promise((e,t)=>{this.resolve=e,this.reject=t});constructor(e={}){for(let t in e){let n=t;e[n]!=null&&(this.options[n]=e[n])}}createBackoff({min:e=1e3,max:t=32e3,factor:n=2}={}){let r=e;return{next(){let e=r;return r=Math.min(r*n,t),e},reset(){r=e}}}reconnect(){this.status===i.DISCONNECTED&&this.connect()}connect(){this.status=i.CONNECTING;let e=this.createBackoff();this.connectionPromise=new Promise((e,t)=>{this.resolve=e,this.reject=t}),this.ws?.close(),this.ws=new WebSocket(this.url),this.ws.onopen=()=>{this.status=i.CONNECTED,this.resolve?.(),e.reset()},this.ws.onmessage=e=>{this.onMessage(e.data)},this.ws.onclose=()=>{this.status=i.DISCONNECTED,this.options.autoreconnect&&setTimeout(()=>this.reconnect(),e.next())},this.ws.onerror=e=>{console.error(`WebSocket error:`,e),this.ws?.close(),this.reject?.()}}close(){this.ws?.close()}async send(e){await this.connectionPromise,this.ws?.send(JSON.stringify(e))}async sendEvent(e){return this.send({type:`event`,event:e})}on(e,t){let n={event:e,handler:t};return this.handlers.push(n),()=>{this.handlers=this.handlers.filter(e=>e!==n)}}onMessage(e){let t=JSON.parse(e);if(t.type===`response`&&t.requestId){let e=this.pendingRequests.get(t.requestId);e&&(this.pendingRequests.delete(t.requestId),e(t.event));return}if(t.type===`event`){let e=this.handlers.filter(e=>e.event==t.event.event);for(let n of e)n.handler(t.event)}}async request(t){let n=e();return await this.send({type:`request`,requestId:n,event:t}),new Promise(e=>{this.pendingRequests.set(n,t=>e(t))})}},o=class{listeners={};emit(e,t){for(let n of this.listeners[e]??[])n(t)}on(e,t){let n=this.listeners[e]??[];return n.push(t),this.listeners[e]=n,()=>{this.listeners[e]=this.listeners[e]?.filter(e=>e==t)??[]}}},s=class{connection;bridge;params;saveHandler;eventEmitter=new o;constructor(){if(typeof window>`u`)throw Error(`Flux Deck Editor must be used only in plugin editor`);let e=new URLSearchParams(location.search),t=t=>{let n=e.get(t);if(n===null)throw Error(`${t} must be provided`);return n};this.params={id:t(`id`),group:t(`group`)},this.connection=new a,this.connection.connect(),this.connection.sendEvent({event:`editorRegister`,payload:this.params.group}),this.connection.on(`sendToEditor`,e=>{this.eventEmitter.emit(`sendToEditor`,e.payload)}),this.bridge=new n,this.bridge.on(`SET_ACTION_SETTINGS`,(e,t,n)=>{if(e.id==this.params.id&&this.saveHandler){let e=this.saveHandler();try{let t=JSON.stringify(e);n?.({settings:t})}catch(e){console.error(e),n?.({settings:null})}}})}async onRecieveFromPlugin(e){return this.eventEmitter.on(`sendToEditor`,e)}sendToPlugin(e){this.connection.sendEvent({event:`sendToPlugin`,name:this.params.group,payload:e})}async getActionSettings(){return(e=>{try{return typeof e==`string`?JSON.parse(e):{}}catch(e){return console.error(e),{}}})((await this.bridge.request(`GET_ACTION_SETTINGS`,{id:this.params.id})).settings)}onActionSave(e){return this.saveHandler=e,()=>{this.saveHandler=void 0}}async getPluginSettings(){return await this.connection.request({name:this.params.group,event:`getPluginSettings`})}async setPluginSettings(e){return this.connection.sendEvent({name:this.params.group,event:`setPluginSettings`,payload:e})}},c=class{connection;actions=[];pluginName;eventEmitter=new o;constructor(){typeof process<`u`&&(this.pluginName=process?.argv[2]),this.connection=new a}connect(){if(typeof process<`u`&&!this.pluginName)throw Error(`No plugin name`);this.connection.on(`trigger`,e=>{for(let t of this.actions)t.name==e.action.type&&t.onTrigger?.({trigger:e.kind,settings:this.parseSettings(e.action.settings)})}),this.connection.on(`setPluginSettings`,e=>{this.eventEmitter.emit(`setPluginSettings`,e.payload)}),this.connection.on(`sendToPlugin`,e=>{this.eventEmitter.emit(`sendToPlugin`,e.payload)}),this.connection.connect(),this.pluginName&&this.registerPlugin(this.pluginName)}parseSettings(e){try{return JSON.parse(e??`{}`)}catch(e){return console.error(e),{}}}registerPlugin(e){this.connection.sendEvent({event:`pluginRegister`,payload:e})}registerAction(e){this.actions.push(e)}async onSetSettings(e){let t=this.eventEmitter.on(`setPluginSettings`,e);return e((await this.getPluginSettings()).payload),t}async onRecieveFromEditor(e){return this.eventEmitter.on(`sendToPlugin`,e)}sendToEditor(e){if(!this.pluginName)throw Error(`No plugin name`);this.connection.sendEvent({event:`sendToEditor`,name:this.pluginName,payload:e})}async getPluginSettings(){if(!this.pluginName)throw Error(`No plugin name`);return this.connection.request({name:this.pluginName,event:`getPluginSettings`})}async setPluginSettings(e){if(!this.pluginName)throw Error(`No plugin name`);return this.connection.sendEvent({name:this.pluginName,event:`setPluginSettings`,payload:e})}};const l=new c;export{t as Bridge,a as Connection,s as Editor,c as FluxDeck,l as fluxDeck};
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["message: BridgeMessage<unknown>","message: BridgeMessage<EventRequests[T]>","message: BridgeMessage<EventResponses[T]>","wrappedHandler: MessageHandler<T>","event","Bridge"],"sources":["../src/bridge.ts","../src/connection.ts","../src/event-emitter.ts","../src/editor.ts","../src/plugin.ts"],"sourcesContent":["// Vibecoded by Claude\n\nimport type {\n BridgeOptions,\n MessageHandler,\n PendingRequest,\n BridgeMessage,\n EventRequests,\n ResponseFor,\n EventResponses,\n} from \"./types/bridge\";\n\nexport class Bridge<T extends keyof EventRequests = keyof EventRequests> {\n private options: Required<BridgeOptions>;\n private handlers: Map<string, MessageHandler<T>>;\n private pendingRequests: Map<number, PendingRequest<T>>;\n private requestId: number;\n private isParent: boolean;\n private target: Window | null;\n\n constructor(options: BridgeOptions = {}) {\n this.options = {\n targetOrigin: \"*\",\n timeout: 5000,\n debug: false,\n ...options,\n };\n\n this.handlers = new Map();\n this.pendingRequests = new Map();\n this.requestId = 0;\n this.isParent = window.parent !== window;\n this.target = null;\n\n this.init();\n }\n\n private init(): void {\n window.addEventListener(\"message\", this.handleMessage.bind(this));\n\n if (this.options.debug) {\n console.log(\"[IframeBridge] Инициализирован\", {\n isParent: this.isParent,\n targetOrigin: this.options.targetOrigin,\n });\n }\n }\n\n /**\n * Установить цель для отправки сообщений (для родительского окна)\n */\n setTarget(iframeElement: HTMLIFrameElement): void {\n if (iframeElement instanceof HTMLIFrameElement) {\n this.target = iframeElement.contentWindow;\n } else {\n console.error(\"[IframeBridge] Неверный элемент iframe\");\n }\n }\n\n /**\n * Получить целевое окно для отправки сообщений\n */\n private getTargetWindow(): Window | null {\n // Если мы внутри iframe - отправляем родителю\n if (this.isParent) {\n return window.parent;\n }\n\n // Если мы родитель - отправляем в iframe\n if (this.target) {\n return this.target;\n }\n\n console.error(\n \"[IframeBridge] Target не установлен. Используйте setTarget() для родительского окна\",\n );\n\n return null;\n }\n\n /**\n * Обработка входящих сообщений\n */\n private handleMessage(event: MessageEvent): void {\n // Проверка origin\n // TODO: not necessary to check origin\n if (\n this.options.targetOrigin !== \"*\" &&\n event.origin !== this.options.targetOrigin\n ) {\n if (this.options.debug) {\n console.warn(\n \"[IframeBridge] Сообщение от неизвестного origin:\",\n event.origin,\n );\n }\n return;\n }\n\n const data = event.data as BridgeMessage<unknown>;\n const { type, payload, meta } = data;\n\n if (!type) return;\n\n if (this.options.debug) {\n console.log(\"[IframeBridge] Получено сообщение:\", {\n type,\n payload,\n _meta: meta,\n });\n }\n\n // Если это ответ на запрос\n if (meta?.isResponse && meta?.requestId !== undefined) {\n this.handleResponse(meta.requestId, payload as ResponseFor<T>);\n return;\n }\n\n // Обработка обычного события\n const handler = this.handlers.get(type);\n if (handler) {\n // Если нужен ответ\n if (meta?.isRequest && meta?.requestId !== undefined) {\n const respond = (responsePayload: EventResponses[T]): void => {\n this.sendResponse(\n meta.requestId!,\n responsePayload,\n event.source as Window,\n );\n };\n handler(payload as EventRequests[T], event, respond);\n } else {\n handler(payload as EventRequests[T], event);\n }\n }\n }\n\n /**\n * Отправить сообщение\n */\n send(type: string, payload: unknown = {}): void {\n const targetWindow = this.getTargetWindow();\n if (!targetWindow) return;\n\n const message: BridgeMessage<unknown> = {\n type,\n payload,\n meta: {\n timestamp: Date.now(),\n },\n };\n\n targetWindow.postMessage(message, this.options.targetOrigin);\n\n if (this.options.debug) {\n console.log(\"[IframeBridge] Отправлено сообщение:\", message);\n }\n }\n\n /**\n * Отправить запрос и ждать ответа\n */\n request(\n type: T,\n payload: EventRequests[T],\n timeout: number = this.options.timeout,\n ): Promise<ResponseFor<T>> {\n return new Promise((resolve, reject) => {\n const targetWindow = this.getTargetWindow();\n if (!targetWindow) {\n reject(new Error(\"Target window не найден\"));\n return;\n }\n\n const requestId = ++this.requestId;\n\n // Таймаут для запроса\n const timeoutId = window.setTimeout(() => {\n this.pendingRequests.delete(requestId);\n reject(new Error(`Request timeout: ${type}`));\n }, timeout);\n\n // Сохраняем промис\n this.pendingRequests.set(requestId, {\n resolve,\n reject,\n timeoutId,\n });\n\n const message: BridgeMessage<EventRequests[T]> = {\n type,\n payload,\n meta: {\n requestId,\n isRequest: true,\n timestamp: Date.now(),\n },\n };\n\n targetWindow.postMessage(message, this.options.targetOrigin);\n\n if (this.options.debug) {\n console.log(\"[IframeBridge] Отправлен запрос:\", message);\n }\n });\n }\n\n /**\n * Отправить ответ на запрос\n */\n private sendResponse(\n requestId: number,\n payload: EventResponses[T],\n targetWindow: Window,\n ): void {\n const message: BridgeMessage<EventResponses[T]> = {\n type: \"__response__\",\n payload,\n meta: {\n requestId,\n isResponse: true,\n timestamp: Date.now(),\n },\n };\n\n targetWindow.postMessage(message, this.options.targetOrigin);\n\n if (this.options.debug) {\n console.log(\"[IframeBridge] Отправлен ответ:\", message);\n }\n }\n\n /**\n * Обработать ответ на запрос\n */\n private handleResponse(\n requestId: number,\n payload: ResponseFor<T>,\n error?: string | null,\n ): void {\n const pending = this.pendingRequests.get(requestId);\n if (!pending) return;\n\n clearTimeout(pending.timeoutId);\n this.pendingRequests.delete(requestId);\n\n if (error) {\n pending.reject(new Error(error));\n } else {\n pending.resolve(payload);\n }\n }\n\n /**\n * Подписаться на событие\n */\n on(type: T, handler: MessageHandler<T>): () => void {\n this.handlers.set(type, handler);\n return () => this.off(type);\n }\n\n /**\n * Отписаться от события\n */\n off(type: string): void {\n this.handlers.delete(type);\n }\n\n /**\n * Подписаться на событие один раз\n */\n once(type: T, handler: MessageHandler<T>): () => void {\n const wrappedHandler: MessageHandler<T> = (...args) => {\n handler(...args);\n this.off(type);\n };\n return this.on(type, wrappedHandler);\n }\n\n /**\n * Очистить все обработчики\n */\n destroy(): void {\n this.handlers.clear();\n this.pendingRequests.forEach(({ timeoutId }) => clearTimeout(timeoutId));\n this.pendingRequests.clear();\n window.removeEventListener(\"message\", this.handleMessage.bind(this));\n\n if (this.options.debug) {\n console.log(\"[IframeBridge] Уничтожен\");\n }\n }\n}\n\nexport default Bridge;\nexport type { BridgeOptions, MessageHandler, BridgeMessage };\n","import { nanoid } from \"nanoid\";\nimport type { WsClientMessage } from \"@fluxdeck/bindings/WsClientMessage\";\nimport type {\n EventHandlers,\n PendingRequests,\n Handler,\n ResponseFor,\n EventHandler,\n} from \"./types/connection\";\nimport type { ClientRequestEvent } from \"@fluxdeck/bindings/ClientRequestEvent\";\nimport type { WsServerMessage } from \"@fluxdeck/bindings/WsServerMessage\";\nimport type { ClientEvent } from \"@fluxdeck/bindings/ClientEvent\";\nimport type { ServerEvent } from \"@fluxdeck/bindings/ServerEvent\";\n\nfunction getHostname() {\n return typeof process !== \"undefined\" ? \"localhost\" : location.hostname;\n}\n\nconst STATUS = { DISCONNECTED: 0, CONNECTING: 1, CONNECTED: 2 } as const;\ntype STATUS = (typeof STATUS)[keyof typeof STATUS];\n\ntype ConnectionOptions = {\n autoreconnect?: boolean;\n};\n\nexport class Connection {\n private url: string = `ws://${getHostname()}:3001/ws`;\n\n private ws?: WebSocket;\n\n private handlers: EventHandlers = [];\n private pendingRequests: PendingRequests = new Map();\n\n private options: Required<ConnectionOptions> = {\n autoreconnect: true,\n };\n\n private status: STATUS = STATUS.DISCONNECTED;\n\n private resolve?: () => void;\n private reject?: () => void;\n\n private connectionPromise: Promise<void> = new Promise((resolve, reject) => {\n this.resolve = resolve;\n this.reject = reject;\n });\n\n constructor(options: ConnectionOptions = {}) {\n for (const key in options) {\n const property = key as keyof ConnectionOptions;\n\n if (options[property] != undefined) {\n this.options[property] = options[property];\n }\n }\n }\n\n private createBackoff({ min = 1000, max = 32000, factor = 2 } = {}) {\n let delay = min;\n\n return {\n next() {\n const current = delay;\n delay = Math.min(delay * factor, max);\n return current;\n },\n reset() {\n delay = min;\n },\n };\n }\n\n reconnect() {\n if (this.status === STATUS.DISCONNECTED) {\n this.connect();\n }\n }\n\n connect() {\n this.status = STATUS.CONNECTING;\n\n const backoff = this.createBackoff();\n\n this.connectionPromise = new Promise((resolve, reject) => {\n this.resolve = resolve;\n this.reject = reject;\n });\n\n this.ws?.close();\n this.ws = new WebSocket(this.url);\n\n this.ws.onopen = () => {\n this.status = STATUS.CONNECTED;\n\n this.resolve?.();\n backoff.reset();\n };\n\n this.ws.onmessage = (event) => {\n this.onMessage(event.data);\n };\n\n this.ws.onclose = () => {\n this.status = STATUS.DISCONNECTED;\n\n if (this.options.autoreconnect) {\n setTimeout(() => this.reconnect(), backoff.next());\n }\n };\n\n this.ws.onerror = (err) => {\n console.error(\"WebSocket error:\", err);\n this.ws?.close();\n this.reject?.();\n };\n }\n\n close() {\n this.ws?.close();\n }\n\n private async send(msg: WsClientMessage): Promise<void> {\n await this.connectionPromise;\n this.ws?.send(JSON.stringify(msg));\n }\n\n async sendEvent(event: ClientEvent): Promise<void> {\n return this.send({ type: \"event\", event });\n }\n\n on<T extends ServerEvent[\"event\"]>(\n event: T,\n handler: Handler<T>,\n ): () => void {\n const eventHandler = { event, handler } as unknown as EventHandler<\n ServerEvent[\"event\"]\n >;\n\n this.handlers.push(eventHandler);\n\n return () => {\n this.handlers = this.handlers.filter((value) => value !== eventHandler);\n };\n }\n\n private onMessage(raw: string) {\n const msg = JSON.parse(raw) as WsServerMessage;\n\n if (msg.type === \"response\" && msg.requestId) {\n const resolve = this.pendingRequests.get(msg.requestId);\n\n if (resolve) {\n this.pendingRequests.delete(msg.requestId);\n resolve(msg.event);\n }\n\n return;\n }\n\n if (msg.type === \"event\") {\n const handlers = this.handlers.filter(\n (value) => value.event == msg.event.event,\n );\n\n for (const eventHandler of handlers) {\n eventHandler.handler(msg.event);\n }\n }\n }\n\n async request<E extends ClientRequestEvent>(\n event: E,\n ): Promise<ResponseFor<E[\"event\"]>> {\n const requestId = nanoid();\n\n await this.send({\n type: \"request\",\n requestId,\n event,\n });\n\n return new Promise((resolve) => {\n this.pendingRequests.set(requestId, (event) =>\n resolve(event as ResponseFor<E[\"event\"]>),\n );\n });\n }\n}\n","import type { ServerEvent } from \"@fluxdeck/bindings/ServerEvent\";\n\nexport type Listener<T> = (payload: T) => void;\n\nexport class EventEmitter {\n private listeners: Record<string, Listener<unknown>[]> = {};\n\n emit(event: string, data: unknown) {\n for (const listener of this.listeners[event] ?? []) {\n listener(data);\n }\n }\n\n on(event: ServerEvent[\"event\"], listener: Listener<unknown>) {\n const listeners = this.listeners[event] ?? [];\n listeners.push(listener);\n this.listeners[event] = listeners;\n return () => {\n this.listeners[event] =\n this.listeners[event]?.filter((cb) => cb == listener) ?? [];\n };\n }\n}\n","import type { JsonValue } from \"@fluxdeck/bindings/JsonValue\";\nimport Bridge from \"./bridge\";\nimport { Connection } from \"./connection\";\nimport { EventEmitter, Listener } from \"./event-emitter\";\n\ntype SaveHandler = () => unknown;\n\ntype EditorParams = {\n id: string;\n group: string;\n};\n\nexport class Editor {\n private connection: Connection;\n private bridge: Bridge;\n private params: EditorParams;\n private saveHandler?: SaveHandler;\n private eventEmitter = new EventEmitter();\n\n constructor() {\n if (typeof window === \"undefined\") {\n throw Error(\"Flux Deck Editor must be used only in plugin editor\");\n }\n\n const urlParams = new URLSearchParams(location.search);\n\n const getStringParam = (key: string): string => {\n const value = urlParams.get(key);\n\n if (value === null) {\n throw Error(`${key} must be provided`);\n }\n\n return value;\n };\n\n this.params = {\n id: getStringParam(\"id\"),\n group: getStringParam(\"group\"),\n };\n\n this.connection = new Connection();\n this.connection.connect();\n\n this.connection.sendEvent({\n event: \"editorRegister\",\n payload: this.params.group,\n });\n\n this.connection.on(\"sendToEditor\", (data) => {\n this.eventEmitter.emit(\"sendToEditor\", data.payload);\n });\n\n this.bridge = new Bridge();\n this.bridge.on(\"SET_ACTION_SETTINGS\", (payload, _event, respond) => {\n if (payload.id == this.params.id && this.saveHandler) {\n const settings = this.saveHandler();\n\n try {\n const string = JSON.stringify(settings);\n respond?.({ settings: string });\n } catch (err) {\n console.error(err);\n respond?.({ settings: null });\n }\n }\n });\n }\n\n async onRecieveFromPlugin<T>(listener: Listener<T>) {\n return this.eventEmitter.on(\"sendToEditor\", listener as Listener<unknown>);\n }\n\n sendToPlugin<T extends JsonValue>(data: T) {\n this.connection.sendEvent({\n event: \"sendToPlugin\",\n name: this.params.group,\n payload: data,\n });\n }\n\n async getActionSettings(): Promise<JsonValue> {\n const parse = (data: string | null) => {\n try {\n if (typeof data == \"string\") {\n return JSON.parse(data);\n } else {\n return {};\n }\n } catch (err) {\n console.error(err);\n return {};\n }\n };\n\n const response = await this.bridge.request(\"GET_ACTION_SETTINGS\", {\n id: this.params.id,\n });\n\n return parse(response.settings);\n }\n\n onActionSave(handler: SaveHandler) {\n this.saveHandler = handler;\n\n return () => {\n this.saveHandler = undefined;\n };\n }\n\n async getPluginSettings() {\n return await this.connection.request({\n name: this.params.group,\n event: \"getPluginSettings\",\n });\n }\n\n async setPluginSettings(data: JsonValue) {\n return this.connection.sendEvent({\n name: this.params.group,\n event: \"setPluginSettings\",\n payload: data,\n });\n }\n}\n","import type { JsonValue } from \"@fluxdeck/bindings/JsonValue\";\nimport { Connection } from \"./connection\";\nimport { EventEmitter, Listener } from \"./event-emitter\";\n\nexport type ActionData<T> = {\n trigger: string;\n settings: T;\n};\n\nexport interface Action<T> {\n name: string;\n onTrigger?: (data: ActionData<T>) => void;\n}\n\nexport class FluxDeck {\n private connection: Connection;\n private actions: Action<unknown>[] = [];\n\n private pluginName?: string;\n\n private eventEmitter = new EventEmitter();\n\n constructor() {\n if (typeof process != \"undefined\") {\n this.pluginName = process?.argv[2];\n }\n\n this.connection = new Connection();\n }\n\n connect() {\n if (typeof process != \"undefined\" && !this.pluginName) {\n throw Error(\"No plugin name\");\n }\n\n this.connection.on(\"trigger\", (data) => {\n for (const action of this.actions) {\n if (action.name == data.action.type) {\n action.onTrigger?.({\n trigger: data.kind,\n settings: this.parseSettings(data.action.settings),\n });\n }\n }\n });\n\n this.connection.on(\"setPluginSettings\", (data) => {\n this.eventEmitter.emit(\"setPluginSettings\", data.payload);\n });\n\n this.connection.on(\"sendToPlugin\", (data) => {\n this.eventEmitter.emit(\"sendToPlugin\", data.payload);\n });\n\n this.connection.connect();\n\n if (this.pluginName) {\n this.registerPlugin(this.pluginName);\n }\n }\n\n private parseSettings(str: string | null) {\n try {\n return JSON.parse(str ?? \"{}\");\n } catch (err) {\n console.error(err);\n return {};\n }\n }\n\n private registerPlugin(name: string) {\n this.connection.sendEvent({ event: \"pluginRegister\", payload: name });\n }\n\n registerAction<T>(action: Action<T>) {\n this.actions.push(action as Action<unknown>);\n }\n\n async onSetSettings<T>(listener: Listener<T>) {\n const on = this.eventEmitter.on(\n \"setPluginSettings\",\n listener as Listener<unknown>,\n );\n const settings = await this.getPluginSettings();\n listener(settings.payload as T);\n return on;\n }\n\n async onRecieveFromEditor<T>(listener: Listener<T>) {\n return this.eventEmitter.on(\"sendToPlugin\", listener as Listener<unknown>);\n }\n\n sendToEditor<T extends JsonValue>(data: T) {\n if (!this.pluginName) {\n throw Error(\"No plugin name\");\n }\n\n this.connection.sendEvent({\n event: \"sendToEditor\",\n name: this.pluginName,\n payload: data,\n });\n }\n\n async getPluginSettings() {\n if (!this.pluginName) {\n throw Error(\"No plugin name\");\n }\n\n return this.connection.request({\n name: this.pluginName,\n event: \"getPluginSettings\",\n });\n }\n\n async setPluginSettings<T extends JsonValue>(data: T) {\n if (!this.pluginName) {\n throw Error(\"No plugin name\");\n }\n\n return this.connection.sendEvent({\n name: this.pluginName,\n event: \"setPluginSettings\",\n payload: data,\n });\n }\n}\n\nexport const fluxDeck = new FluxDeck();\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@fluxdeck/sdk",
3
+ "version": "0.0.1",
4
+ "description": "Flux Deck SDK",
5
+ "license": "MIT",
6
+ "author": "Mikhail Morozov",
7
+ "type": "module",
8
+ "url": "https://github.com/inferst/fluxdeck",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/inferst/fluxdeck.git",
12
+ "directory": "packages/sdk"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/inferst/fluxdeck/issues"
16
+ },
17
+ "homepage": "https://github.com/inferst/fluxdeck/tree/main/packages/sdk#readme",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.mts",
21
+ "import": "./dist/index.mjs"
22
+ }
23
+ },
24
+ "main": "./dist/index.mjs",
25
+ "module": "./dist/index.mjs",
26
+ "types": "./dist/index.d.mts",
27
+ "source": "./src/index.ts",
28
+ "files": [
29
+ "dist",
30
+ "LICENSE.md",
31
+ "README.md"
32
+ ],
33
+ "sideEffects": false,
34
+ "publishConfig": {
35
+ "access": "public"
36
+ },
37
+ "scripts": {
38
+ "prepack": "pnpm run build",
39
+ "build": "tsc && tsdown",
40
+ "dev": "tsdown --watch",
41
+ "lint": "eslint \"src/**/*.{ts,tsx}\"",
42
+ "test": "vitest"
43
+ },
44
+ "dependencies": {
45
+ "nanoid": "^5.1.6"
46
+ },
47
+ "devDependencies": {
48
+ "@fluxdeck/configs": "workspace:*",
49
+ "@fluxdeck/bindings": "workspace:*",
50
+ "@types/node": "^22.18.12",
51
+ "eslint": "^10.0.0",
52
+ "tsdown": "^0.18.1",
53
+ "typescript": "^5.9.3",
54
+ "vitest": "^4.0.16"
55
+ }
56
+ }