asyar-sdk 1.15.4 → 1.15.6

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.
@@ -17,7 +17,7 @@ exports.ICON_DATA = {
17
17
  `,
18
18
  settings: `
19
19
  <circle cx="12" cy="12" r="3" />
20
- <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09a1.65 1.65 0 0 0-1.08-1.51 1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09a1.65 1.65 0 0 0 1.51-1.08 1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1.08 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9c.26.6.77 1.05 1.41 1.08H21a2 2 0 1 1 0 4h-.09c-.64.03-1.15.48-1.41 1.08z" />
20
+ <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09a1.65 1.65 0 0 0-1.08-1.51 1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09a1.65 1.65 0 0 0 1.51-1.08 1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1.08 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9c.26.6.77 1.05 1.41 1.08H21a2 2 0 1 1 0 4h-.09c-.64.03-1.15.58-1.41 1.08z" />
21
21
  `,
22
22
  keyboard: `
23
23
  <rect x="2" y="5" width="20" height="14" rx="2" />
@@ -1,11 +1,69 @@
1
+ /**
2
+ * Context passed to a registered `onClick` handler when the user clicks the
3
+ * tray icon itself or one of its menu items.
4
+ *
5
+ * `itemPath` identifies the clicked node: the top-level id at index 0,
6
+ * followed by any submenu ids drilled into to reach the leaf. For a plain
7
+ * click on the tray icon, `itemPath` contains only the top-level id.
8
+ *
9
+ * `checked` is populated for `CheckMenuItem` leaves: it holds the NEW state
10
+ * after the native auto-toggle. For non-check items it is `undefined`.
11
+ */
12
+ export interface StatusBarClickContext {
13
+ itemPath: string[];
14
+ checked?: boolean;
15
+ }
16
+ /**
17
+ * A single tray-icon + menu node registered by an extension.
18
+ *
19
+ * Top-level rules (enforced by the SDK proxy + Rust host):
20
+ * - `id` must be non-empty and unique among the extension's top-level items.
21
+ * - At least one of `icon` or `iconPath` must be provided (the tray needs
22
+ * a glyph to render in the menu bar).
23
+ * - `separator`, `checked`, `enabled: false` are NOT valid at the top
24
+ * level — they only make sense inside a submenu.
25
+ *
26
+ * Submenu rules:
27
+ * - Nesting depth is capped at 4 (the top level counts as 1).
28
+ * - Sibling ids must be unique, except `separator: true` rows which are
29
+ * id-less dividers.
30
+ * - `checked` / `enabled` / `separator` are only valid inside a submenu.
31
+ */
1
32
  export interface IStatusBarItem {
2
- id: string;
33
+ /**
34
+ * Item id. REQUIRED for top-level items and every non-separator child —
35
+ * validation throws at `registerItem` time if missing. Declared optional
36
+ * here so `{ separator: true }` divider rows type-check inside `submenu`
37
+ * arrays (they carry no id/text).
38
+ */
39
+ id?: string;
40
+ /** Emoji / unicode prefix / short label used next to `text` in menus. */
3
41
  icon?: string;
4
- text: string;
42
+ /** Filesystem path or `asyar-extension://{id}/...` URI for the tray image. */
43
+ iconPath?: string;
44
+ /**
45
+ * Tooltip at the top level; label shown in the menu at deeper levels.
46
+ * REQUIRED everywhere except separator rows (same rationale as `id`).
47
+ */
48
+ text?: string;
49
+ /** `✓` state — valid only inside a submenu. */
50
+ checked?: boolean;
51
+ /** Nested menu entries. If present the tray click opens this dropdown. */
52
+ submenu?: IStatusBarItem[];
53
+ /** `false` greys out the entry — valid only inside a submenu. */
54
+ enabled?: boolean;
55
+ /** Divider row — valid only inside a submenu. */
56
+ separator?: boolean;
57
+ /**
58
+ * Fires when the user clicks this item (tray icon click for top level,
59
+ * menu click for submenu leaves). Stripped from the IPC payload and kept
60
+ * in the proxy's local dispatch table.
61
+ */
62
+ onClick?: (ctx: StatusBarClickContext) => void;
5
63
  }
6
64
  export interface IStatusBarService {
7
65
  registerItem(item: IStatusBarItem): void;
8
- updateItem(id: string, updates: Partial<Pick<IStatusBarItem, 'icon' | 'text'>>): void;
66
+ updateItem(id: string, updates: Partial<IStatusBarItem>): void;
9
67
  unregisterItem(id: string): void;
10
68
  }
11
69
  //# sourceMappingURL=IStatusBarService.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"IStatusBarService.d.ts","sourceRoot":"","sources":["../../src/services/IStatusBarService.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC,YAAY,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,CAAC;IACzC,UAAU,CACR,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC,GACtD,IAAI,CAAC;IACR,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC"}
1
+ {"version":3,"file":"IStatusBarService.d.ts","sourceRoot":"","sources":["../../src/services/IStatusBarService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,yEAAyE;IACzE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0EAA0E;IAC1E,OAAO,CAAC,EAAE,cAAc,EAAE,CAAC;IAC3B,iEAAiE;IACjE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iDAAiD;IACjD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,IAAI,CAAC;CAChD;AAED,MAAM,WAAW,iBAAiB;IAChC,YAAY,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,CAAC;IACzC,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC;IAC/D,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC"}
@@ -1,8 +1,22 @@
1
1
  import type { IStatusBarService, IStatusBarItem } from './IStatusBarService';
2
2
  import { BaseServiceProxy } from './BaseServiceProxy';
3
+ /**
4
+ * Proxy for the host-side status-bar service. Each top-level item the
5
+ * extension registers becomes an independent menu-bar tray icon; this proxy
6
+ * keeps the local `onClick` dispatch table and ships the serializable tree
7
+ * over the broker.
8
+ *
9
+ * The proxy validates the tree up-front so malformed input fails before the
10
+ * IPC round-trip.
11
+ */
3
12
  export declare class StatusBarServiceProxy extends BaseServiceProxy implements IStatusBarService {
13
+ /** Top-level id → flat map of `'topId[:...]' -> onClick handler`. */
14
+ private handlersByTop;
15
+ private clickListenerBound;
4
16
  registerItem(item: IStatusBarItem): void;
5
- updateItem(id: string, updates: Partial<Pick<IStatusBarItem, 'icon' | 'text'>>): void;
17
+ updateItem(id: string, updates: Partial<IStatusBarItem>): void;
6
18
  unregisterItem(id: string): void;
19
+ private ensureClickListener;
20
+ private dispatchClick;
7
21
  }
8
22
  //# sourceMappingURL=StatusBarServiceProxy.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"StatusBarServiceProxy.d.ts","sourceRoot":"","sources":["../../src/services/StatusBarServiceProxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,qBAAa,qBAAsB,SAAQ,gBAAiB,YAAW,iBAAiB;IACtF,YAAY,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IAKxC,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC,GAAG,IAAI;IAIrF,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;CAGjC"}
1
+ {"version":3,"file":"StatusBarServiceProxy.d.ts","sourceRoot":"","sources":["../../src/services/StatusBarServiceProxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,cAAc,EAEf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAatD;;;;;;;;GAQG;AACH,qBAAa,qBACX,SAAQ,gBACR,YAAW,iBAAiB;IAE5B,qEAAqE;IACrE,OAAO,CAAC,aAAa,CAGjB;IAEJ,OAAO,CAAC,kBAAkB,CAAS;IAEnC,YAAY,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IAcxC,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI;IAwB9D,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAShC,OAAO,CAAC,mBAAmB;IAQ3B,OAAO,CAAC,aAAa;CA6BtB"}
@@ -2,16 +2,92 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.StatusBarServiceProxy = void 0;
4
4
  const BaseServiceProxy_1 = require("./BaseServiceProxy");
5
+ const statusBarValidation_1 = require("./statusBarValidation");
6
+ /**
7
+ * Proxy for the host-side status-bar service. Each top-level item the
8
+ * extension registers becomes an independent menu-bar tray icon; this proxy
9
+ * keeps the local `onClick` dispatch table and ships the serializable tree
10
+ * over the broker.
11
+ *
12
+ * The proxy validates the tree up-front so malformed input fails before the
13
+ * IPC round-trip.
14
+ */
5
15
  class StatusBarServiceProxy extends BaseServiceProxy_1.BaseServiceProxy {
16
+ constructor() {
17
+ super(...arguments);
18
+ /** Top-level id → flat map of `'topId[:...]' -> onClick handler`. */
19
+ this.handlersByTop = new Map();
20
+ this.clickListenerBound = false;
21
+ }
6
22
  registerItem(item) {
7
- const fullItem = Object.assign(Object.assign({}, item), { extensionId: this.extensionId });
8
- this.broker.invoke('statusBar:registerItem', { item: fullItem }).catch(err => console.warn('[StatusBarServiceProxy] registerItem failed:', err));
23
+ (0, statusBarValidation_1.validateTopLevelStatusBarItem)(item);
24
+ // `id` is guaranteed non-empty after validation above.
25
+ this.handlersByTop.set(item.id, (0, statusBarValidation_1.collectHandlers)(item));
26
+ this.ensureClickListener();
27
+ const fullItem = Object.assign(Object.assign({}, (0, statusBarValidation_1.stripHandlers)(item)), { extensionId: this.extensionId });
28
+ this.broker
29
+ .invoke('statusBar:registerItem', { item: fullItem })
30
+ .catch((err) => console.warn('[StatusBarServiceProxy] registerItem failed:', err));
9
31
  }
10
32
  updateItem(id, updates) {
11
- this.broker.invoke('statusBar:updateItem', { extensionId: this.extensionId, id, updates }).catch(err => console.warn('[StatusBarServiceProxy] updateItem failed:', err));
33
+ // `updates` is merged with the existing item on the extension side; the
34
+ // host rebuilds the tray from scratch with the merged tree, so we
35
+ // validate the merge result shape here too.
36
+ const merged = Object.assign({ id, text: '' }, updates);
37
+ if (typeof merged.id !== 'string' || merged.id.trim() === '') {
38
+ throw new Error('updateItem requires a non-empty id');
39
+ }
40
+ (0, statusBarValidation_1.validateTopLevelStatusBarItem)(merged);
41
+ this.handlersByTop.set(merged.id, (0, statusBarValidation_1.collectHandlers)(merged));
42
+ this.ensureClickListener();
43
+ const fullItem = Object.assign(Object.assign({}, (0, statusBarValidation_1.stripHandlers)(merged)), { extensionId: this.extensionId });
44
+ this.broker
45
+ .invoke('statusBar:updateItem', {
46
+ extensionId: this.extensionId,
47
+ id,
48
+ item: fullItem,
49
+ })
50
+ .catch((err) => console.warn('[StatusBarServiceProxy] updateItem failed:', err));
12
51
  }
13
52
  unregisterItem(id) {
14
- this.broker.invoke('statusBar:unregisterItem', { extensionId: this.extensionId, id }).catch(err => console.warn('[StatusBarServiceProxy] unregisterItem failed:', err));
53
+ this.handlersByTop.delete(id);
54
+ this.broker
55
+ .invoke('statusBar:unregisterItem', { extensionId: this.extensionId, id })
56
+ .catch((err) => console.warn('[StatusBarServiceProxy] unregisterItem failed:', err));
57
+ }
58
+ ensureClickListener() {
59
+ if (this.clickListenerBound)
60
+ return;
61
+ this.clickListenerBound = true;
62
+ this.broker.on('asyar:event:statusBar:click', (payload) => this.dispatchClick(payload));
63
+ }
64
+ dispatchClick(payload) {
65
+ if (!payload || !Array.isArray(payload.itemPath) || payload.itemPath.length === 0) {
66
+ console.warn('[StatusBarServiceProxy] click payload missing itemPath', payload);
67
+ return;
68
+ }
69
+ const [topId] = payload.itemPath;
70
+ const handlers = this.handlersByTop.get(topId);
71
+ if (!handlers) {
72
+ // Top-level id not tracked — likely a stale click after unregister, or
73
+ // a registration the proxy never saw. Log once so we surface it in
74
+ // devtools but stay silent for no-handler leaves (below) since those
75
+ // are a legitimate design case for parent submenu rows.
76
+ console.warn(`[StatusBarServiceProxy] no handler map for top-level id '${topId}'`, { known: [...this.handlersByTop.keys()] });
77
+ return;
78
+ }
79
+ const key = payload.itemPath.join(':');
80
+ const handler = handlers.get(key);
81
+ // Silent on missing leaf handlers: parent rows with submenus intentionally
82
+ // omit onClick, and firing a native click on them still dispatches here.
83
+ if (!handler)
84
+ return;
85
+ try {
86
+ handler({ itemPath: payload.itemPath, checked: payload.checked });
87
+ }
88
+ catch (err) {
89
+ console.warn('[StatusBarServiceProxy] onClick handler threw:', err);
90
+ }
15
91
  }
16
92
  }
17
93
  exports.StatusBarServiceProxy = StatusBarServiceProxy;
@@ -1 +1 @@
1
- {"version":3,"file":"StatusBarServiceProxy.js","sourceRoot":"","sources":["../../src/services/StatusBarServiceProxy.ts"],"names":[],"mappings":";;;AACA,yDAAsD;AAEtD,MAAa,qBAAsB,SAAQ,mCAAgB;IACzD,YAAY,CAAC,IAAoB;QAC/B,MAAM,QAAQ,mCAAQ,IAAI,KAAE,WAAW,EAAE,IAAI,CAAC,WAAW,GAAE,CAAC;QAC5D,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,wBAAwB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,8CAA8C,EAAE,GAAG,CAAC,CAAC,CAAC;IACnJ,CAAC;IAED,UAAU,CAAC,EAAU,EAAE,OAAuD;QAC5E,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,sBAAsB,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,4CAA4C,EAAE,GAAG,CAAC,CAAC,CAAC;IAC3K,CAAC;IAED,cAAc,CAAC,EAAU;QACvB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,0BAA0B,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,gDAAgD,EAAE,GAAG,CAAC,CAAC,CAAC;IAC1K,CAAC;CACF;AAbD,sDAaC"}
1
+ {"version":3,"file":"StatusBarServiceProxy.js","sourceRoot":"","sources":["../../src/services/StatusBarServiceProxy.ts"],"names":[],"mappings":"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"}
@@ -5,37 +5,246 @@ const StatusBarServiceProxy_1 = require("./StatusBarServiceProxy");
5
5
  const MessageBroker_1 = require("../ipc/MessageBroker");
6
6
  vitest_1.vi.mock('../ipc/MessageBroker', () => ({
7
7
  MessageBroker: {
8
- getInstance: vitest_1.vi.fn(() => ({ invoke: vitest_1.vi.fn(), on: vitest_1.vi.fn(), off: vitest_1.vi.fn() })),
8
+ getInstance: vitest_1.vi.fn(),
9
9
  },
10
10
  }));
11
+ function makeBroker() {
12
+ const listeners = new Map();
13
+ return {
14
+ invoke: vitest_1.vi.fn().mockResolvedValue(undefined),
15
+ on: vitest_1.vi.fn((event, fn) => {
16
+ if (!listeners.has(event))
17
+ listeners.set(event, new Set());
18
+ listeners.get(event).add(fn);
19
+ }),
20
+ off: vitest_1.vi.fn(),
21
+ emit(event, payload) {
22
+ const set = listeners.get(event);
23
+ if (set)
24
+ for (const fn of set)
25
+ fn(payload);
26
+ },
27
+ };
28
+ }
11
29
  function makeProxy() {
12
- const mockInvoke = vitest_1.vi.fn().mockResolvedValue(undefined);
13
- vitest_1.vi.mocked(MessageBroker_1.MessageBroker.getInstance).mockReturnValue({
14
- invoke: mockInvoke, on: vitest_1.vi.fn(), off: vitest_1.vi.fn(),
15
- });
30
+ const broker = makeBroker();
31
+ vitest_1.vi.mocked(MessageBroker_1.MessageBroker.getInstance).mockReturnValue(broker);
16
32
  const proxy = new StatusBarServiceProxy_1.StatusBarServiceProxy();
17
33
  proxy.setExtensionId('ext.test');
18
- return { proxy, mockInvoke };
34
+ return { proxy, broker };
19
35
  }
20
- (0, vitest_1.describe)('StatusBarServiceProxy', () => {
21
- (0, vitest_1.beforeEach)(() => vitest_1.vi.clearAllMocks());
22
- (0, vitest_1.it)('registerItem → "statusBar:registerItem"', () => {
23
- const { proxy, mockInvoke } = makeProxy();
24
- proxy.registerItem({ id: 'i1' });
25
- const call = mockInvoke.mock.calls.find(c => c[0] === 'statusBar:registerItem');
36
+ function topLevel(overrides = {}) {
37
+ return Object.assign({ id: 'top', icon: '☕', text: 'Coffee' }, overrides);
38
+ }
39
+ (0, vitest_1.beforeEach)(() => vitest_1.vi.clearAllMocks());
40
+ // ── Happy path ─────────────────────────────────────────────────────────────
41
+ (0, vitest_1.describe)('registerItem happy path', () => {
42
+ (0, vitest_1.it)('sends statusBar:registerItem with the stripped tree + extensionId', () => {
43
+ const { proxy, broker } = makeProxy();
44
+ proxy.registerItem(topLevel());
45
+ const call = broker.invoke.mock.calls.find((c) => c[0] === 'statusBar:registerItem');
26
46
  (0, vitest_1.expect)(call).toBeDefined();
47
+ (0, vitest_1.expect)(call[1]).toMatchObject({
48
+ item: vitest_1.expect.objectContaining({
49
+ id: 'top',
50
+ icon: '☕',
51
+ text: 'Coffee',
52
+ extensionId: 'ext.test',
53
+ }),
54
+ });
27
55
  });
28
- (0, vitest_1.it)('updateItem "statusBar:updateItem"', () => {
29
- const { proxy, mockInvoke } = makeProxy();
30
- proxy.updateItem('i1', {});
31
- const call = mockInvoke.mock.calls.find(c => c[0] === 'statusBar:updateItem');
56
+ (0, vitest_1.it)('accepts a 2-level submenu tree', () => {
57
+ const { proxy, broker } = makeProxy();
58
+ proxy.registerItem(topLevel({
59
+ submenu: [
60
+ { id: 'play', text: 'Play', checked: true },
61
+ { separator: true },
62
+ { id: 'next', text: 'Next', enabled: false },
63
+ ],
64
+ }));
65
+ const call = broker.invoke.mock.calls.find((c) => c[0] === 'statusBar:registerItem');
32
66
  (0, vitest_1.expect)(call).toBeDefined();
67
+ const submenu = call[1].item.submenu;
68
+ (0, vitest_1.expect)(submenu).toHaveLength(3);
69
+ (0, vitest_1.expect)(submenu[0]).toMatchObject({ id: 'play', checked: true });
70
+ (0, vitest_1.expect)(submenu[1]).toMatchObject({ separator: true });
71
+ (0, vitest_1.expect)(submenu[2]).toMatchObject({ id: 'next', enabled: false });
72
+ });
73
+ (0, vitest_1.it)('strips onClick handlers from the IPC payload', () => {
74
+ const { proxy, broker } = makeProxy();
75
+ const onClick = vitest_1.vi.fn();
76
+ proxy.registerItem(topLevel({
77
+ onClick,
78
+ submenu: [{ id: 'sub', text: 'Sub', onClick }],
79
+ }));
80
+ const call = broker.invoke.mock.calls.find((c) => c[0] === 'statusBar:registerItem');
81
+ const item = call[1].item;
82
+ (0, vitest_1.expect)(item).not.toHaveProperty('onClick');
83
+ (0, vitest_1.expect)(item.submenu[0]).not.toHaveProperty('onClick');
84
+ });
85
+ });
86
+ // ── Validation ─────────────────────────────────────────────────────────────
87
+ (0, vitest_1.describe)('registerItem validation (client-side)', () => {
88
+ function rejects(bad, matcher = /./) {
89
+ const { proxy, broker } = makeProxy();
90
+ (0, vitest_1.expect)(() => proxy.registerItem(bad)).toThrow(matcher);
91
+ // No IPC sent for rejected input.
92
+ (0, vitest_1.expect)(broker.invoke.mock.calls.find((c) => c[0] === 'statusBar:registerItem')).toBeUndefined();
93
+ }
94
+ (0, vitest_1.it)('rejects empty id', () => {
95
+ rejects(topLevel({ id: '' }), /id/);
96
+ });
97
+ (0, vitest_1.it)('rejects top-level without icon and iconPath', () => {
98
+ rejects({ id: 'x', text: 'x' }, /icon/i);
99
+ });
100
+ (0, vitest_1.it)('rejects top-level with checked', () => {
101
+ rejects(topLevel({ checked: true }), /checked/i);
102
+ });
103
+ (0, vitest_1.it)('rejects top-level with separator', () => {
104
+ rejects(topLevel({ separator: true }), /separator/i);
105
+ });
106
+ (0, vitest_1.it)('rejects top-level with enabled=false', () => {
107
+ rejects(topLevel({ enabled: false }), /disabled/i);
108
+ });
109
+ (0, vitest_1.it)('rejects id containing colon', () => {
110
+ rejects(topLevel({ id: 'bad:id' }), /separator/i);
111
+ });
112
+ (0, vitest_1.it)('rejects duplicate submenu sibling ids', () => {
113
+ rejects(topLevel({
114
+ submenu: [
115
+ { id: 'dup', text: 'A' },
116
+ { id: 'dup', text: 'B' },
117
+ ],
118
+ }), /duplicate/i);
119
+ });
120
+ (0, vitest_1.it)('rejects submenu nested deeper than depth 4', () => {
121
+ rejects(topLevel({
122
+ submenu: [
123
+ {
124
+ id: 'l2',
125
+ text: 'L2',
126
+ submenu: [
127
+ {
128
+ id: 'l3',
129
+ text: 'L3',
130
+ submenu: [
131
+ {
132
+ id: 'l4',
133
+ text: 'L4',
134
+ submenu: [{ id: 'l5', text: 'L5' }],
135
+ },
136
+ ],
137
+ },
138
+ ],
139
+ },
140
+ ],
141
+ }), /depth/i);
33
142
  });
34
- (0, vitest_1.it)('unregisterItem "statusBar:unregisterItem"', () => {
35
- const { proxy, mockInvoke } = makeProxy();
36
- proxy.unregisterItem('i1');
37
- const call = mockInvoke.mock.calls.find(c => c[0] === 'statusBar:unregisterItem');
143
+ (0, vitest_1.it)('accepts exactly depth 4', () => {
144
+ const { proxy } = makeProxy();
145
+ (0, vitest_1.expect)(() => proxy.registerItem(topLevel({
146
+ submenu: [
147
+ {
148
+ id: 'l2',
149
+ text: 'L2',
150
+ submenu: [
151
+ {
152
+ id: 'l3',
153
+ text: 'L3',
154
+ submenu: [{ id: 'l4', text: 'L4' }],
155
+ },
156
+ ],
157
+ },
158
+ ],
159
+ }))).not.toThrow();
160
+ });
161
+ });
162
+ // ── unregister / update ─────────────────────────────────────────────────────
163
+ (0, vitest_1.describe)('unregisterItem', () => {
164
+ (0, vitest_1.it)('sends the unregister IPC with extensionId + id', () => {
165
+ const { proxy, broker } = makeProxy();
166
+ proxy.unregisterItem('top');
167
+ const call = broker.invoke.mock.calls.find((c) => c[0] === 'statusBar:unregisterItem');
168
+ (0, vitest_1.expect)(call).toBeDefined();
169
+ (0, vitest_1.expect)(call[1]).toMatchObject({ extensionId: 'ext.test', id: 'top' });
170
+ });
171
+ });
172
+ (0, vitest_1.describe)('updateItem', () => {
173
+ (0, vitest_1.it)('re-validates and sends merged tree', () => {
174
+ const { proxy, broker } = makeProxy();
175
+ proxy.updateItem('top', { icon: '🍵', text: 'Tea' });
176
+ const call = broker.invoke.mock.calls.find((c) => c[0] === 'statusBar:updateItem');
38
177
  (0, vitest_1.expect)(call).toBeDefined();
178
+ (0, vitest_1.expect)(call[1].item).toMatchObject({
179
+ id: 'top',
180
+ icon: '🍵',
181
+ text: 'Tea',
182
+ extensionId: 'ext.test',
183
+ });
184
+ });
185
+ (0, vitest_1.it)('throws when the merged shape violates top-level rules', () => {
186
+ const { proxy } = makeProxy();
187
+ // no icon / no iconPath
188
+ (0, vitest_1.expect)(() => proxy.updateItem('top', { text: 'Tea' })).toThrow(/icon/i);
189
+ });
190
+ });
191
+ // ── Click dispatch ──────────────────────────────────────────────────────────
192
+ (0, vitest_1.describe)('click dispatch', () => {
193
+ (0, vitest_1.it)('routes tray-item-click events to matching onClick handlers', () => {
194
+ const { proxy, broker } = makeProxy();
195
+ const onTop = vitest_1.vi.fn();
196
+ const onLeaf = vitest_1.vi.fn();
197
+ proxy.registerItem(topLevel({
198
+ onClick: onTop,
199
+ submenu: [
200
+ {
201
+ id: 'timer',
202
+ text: 'Timer',
203
+ submenu: [{ id: '30m', text: '30m', onClick: onLeaf }],
204
+ },
205
+ ],
206
+ }));
207
+ broker.emit('asyar:event:statusBar:click', {
208
+ itemPath: ['top', 'timer', '30m'],
209
+ });
210
+ (0, vitest_1.expect)(onLeaf).toHaveBeenCalledWith(vitest_1.expect.objectContaining({ itemPath: ['top', 'timer', '30m'] }));
211
+ (0, vitest_1.expect)(onTop).not.toHaveBeenCalled();
212
+ });
213
+ (0, vitest_1.it)('forwards the checked flag when present', () => {
214
+ const { proxy, broker } = makeProxy();
215
+ const onClick = vitest_1.vi.fn();
216
+ proxy.registerItem(topLevel({
217
+ submenu: [{ id: 'play', text: 'Play', checked: true, onClick }],
218
+ }));
219
+ broker.emit('asyar:event:statusBar:click', {
220
+ itemPath: ['top', 'play'],
221
+ checked: false,
222
+ });
223
+ (0, vitest_1.expect)(onClick).toHaveBeenCalledWith({
224
+ itemPath: ['top', 'play'],
225
+ checked: false,
226
+ });
227
+ });
228
+ (0, vitest_1.it)('ignores events for unknown top-level ids', () => {
229
+ const { proxy, broker } = makeProxy();
230
+ const onClick = vitest_1.vi.fn();
231
+ proxy.registerItem(topLevel({ onClick }));
232
+ broker.emit('asyar:event:statusBar:click', { itemPath: ['other'] });
233
+ (0, vitest_1.expect)(onClick).not.toHaveBeenCalled();
234
+ });
235
+ (0, vitest_1.it)('ignores malformed click payloads without throwing', () => {
236
+ const { proxy, broker } = makeProxy();
237
+ proxy.registerItem(topLevel());
238
+ (0, vitest_1.expect)(() => broker.emit('asyar:event:statusBar:click', undefined)).not.toThrow();
239
+ (0, vitest_1.expect)(() => broker.emit('asyar:event:statusBar:click', { itemPath: [] })).not.toThrow();
240
+ (0, vitest_1.expect)(() => broker.emit('asyar:event:statusBar:click', {})).not.toThrow();
241
+ });
242
+ (0, vitest_1.it)('routes top-level click when itemPath has length 1', () => {
243
+ const { proxy, broker } = makeProxy();
244
+ const onTop = vitest_1.vi.fn();
245
+ proxy.registerItem(topLevel({ onClick: onTop }));
246
+ broker.emit('asyar:event:statusBar:click', { itemPath: ['top'] });
247
+ (0, vitest_1.expect)(onTop).toHaveBeenCalledWith(vitest_1.expect.objectContaining({ itemPath: ['top'] }));
39
248
  });
40
249
  });
41
250
  //# sourceMappingURL=StatusBarServiceProxy.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"StatusBarServiceProxy.test.js","sourceRoot":"","sources":["../../src/services/StatusBarServiceProxy.test.ts"],"names":[],"mappings":";;AAAA,mCAA8D;AAC9D,mEAAgE;AAChE,wDAAqD;AAErD,WAAE,CAAC,IAAI,CAAC,sBAAsB,EAAE,GAAG,EAAE,CAAC,CAAC;IACrC,aAAa,EAAE;QACb,WAAW,EAAE,WAAE,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,WAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,WAAE,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,WAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;KAC3E;CACF,CAAC,CAAC,CAAC;AAEJ,SAAS,SAAS;IAChB,MAAM,UAAU,GAAG,WAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;IACxD,WAAE,CAAC,MAAM,CAAC,6BAAa,CAAC,WAAW,CAAC,CAAC,eAAe,CAAC;QACnD,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,WAAE,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,WAAE,CAAC,EAAE,EAAE;KACvC,CAAC,CAAC;IACV,MAAM,KAAK,GAAG,IAAI,6CAAqB,EAAE,CAAC;IAC1C,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;IACjC,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;AAC/B,CAAC;AAED,IAAA,iBAAQ,EAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,IAAA,mBAAU,EAAC,GAAG,EAAE,CAAC,WAAE,CAAC,aAAa,EAAE,CAAC,CAAC;IAErC,IAAA,WAAE,EAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,SAAS,EAAE,CAAC;QAC1C,KAAK,CAAC,YAAY,CAAC,EAAE,EAAE,EAAE,IAAI,EAAS,CAAC,CAAC;QACxC,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,wBAAwB,CAAC,CAAC;QAChF,IAAA,eAAM,EAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,SAAS,EAAE,CAAC;QAC1C,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,EAAS,CAAC,CAAC;QAClC,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,sBAAsB,CAAC,CAAC;QAC9E,IAAA,eAAM,EAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,SAAS,EAAE,CAAC;QAC1C,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QAC3B,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,0BAA0B,CAAC,CAAC;QAClF,IAAA,eAAM,EAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IAC7B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"StatusBarServiceProxy.test.js","sourceRoot":"","sources":["../../src/services/StatusBarServiceProxy.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { IStatusBarItem } from './IStatusBarService';
2
+ /** Maximum submenu nesting depth. Top-level items are depth 1. */
3
+ export declare const MAX_STATUS_BAR_DEPTH = 4;
4
+ /**
5
+ * Validate a top-level status-bar tree client-side before sending it over
6
+ * the broker. Mirrors the Rust `validate_top_level` rules. Throws a
7
+ * `StatusBarValidationError` on the first violation.
8
+ */
9
+ export declare function validateTopLevelStatusBarItem(item: IStatusBarItem): void;
10
+ export declare class StatusBarValidationError extends Error {
11
+ constructor(message: string);
12
+ }
13
+ /**
14
+ * Strip `onClick` callbacks from the tree before IPC serialization. Returns
15
+ * a deep copy safe to postMessage, leaving the original untouched so the
16
+ * SDK can keep dispatching to the original handlers.
17
+ */
18
+ export declare function stripHandlers(item: IStatusBarItem): IStatusBarItem;
19
+ /**
20
+ * Walk the tree collecting `onClick` handlers keyed by their
21
+ * `:`-joined item path. Used by the proxy to dispatch tray click events.
22
+ */
23
+ export declare function collectHandlers(item: IStatusBarItem): Map<string, (ctx: {
24
+ itemPath: string[];
25
+ checked?: boolean;
26
+ }) => void>;
27
+ //# sourceMappingURL=statusBarValidation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statusBarValidation.d.ts","sourceRoot":"","sources":["../../src/services/statusBarValidation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,kEAAkE;AAClE,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAEtC;;;;GAIG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,CAkDxE;AA+CD,qBAAa,wBAAyB,SAAQ,KAAK;gBACrC,OAAO,EAAE,MAAM;CAI5B;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,cAAc,GAAG,cAAc,CAOlE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,cAAc,GACnB,GAAG,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,KAAK,IAAI,CAAC,CAOvE"}
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.StatusBarValidationError = exports.MAX_STATUS_BAR_DEPTH = void 0;
15
+ exports.validateTopLevelStatusBarItem = validateTopLevelStatusBarItem;
16
+ exports.stripHandlers = stripHandlers;
17
+ exports.collectHandlers = collectHandlers;
18
+ /** Maximum submenu nesting depth. Top-level items are depth 1. */
19
+ exports.MAX_STATUS_BAR_DEPTH = 4;
20
+ /**
21
+ * Validate a top-level status-bar tree client-side before sending it over
22
+ * the broker. Mirrors the Rust `validate_top_level` rules. Throws a
23
+ * `StatusBarValidationError` on the first violation.
24
+ */
25
+ function validateTopLevelStatusBarItem(item) {
26
+ if (!item || typeof item !== 'object') {
27
+ throw new StatusBarValidationError('Status-bar item must be an object');
28
+ }
29
+ if (typeof item.id !== 'string' || item.id.trim() === '') {
30
+ throw new StatusBarValidationError('Top-level status-bar item id must be a non-empty string');
31
+ }
32
+ if (typeof item.text !== 'string') {
33
+ throw new StatusBarValidationError(`Top-level status-bar item '${item.id}' requires a string 'text' field`);
34
+ }
35
+ if (item.separator === true) {
36
+ throw new StatusBarValidationError(`Top-level status-bar items cannot be separators (item '${item.id}')`);
37
+ }
38
+ if (item.checked !== undefined) {
39
+ throw new StatusBarValidationError(`Top-level status-bar items cannot have a checked state (item '${item.id}')`);
40
+ }
41
+ if (item.enabled === false) {
42
+ throw new StatusBarValidationError(`Top-level status-bar items cannot be disabled (item '${item.id}')`);
43
+ }
44
+ const hasIcon = (typeof item.icon === 'string' && item.icon.length > 0) ||
45
+ (typeof item.iconPath === 'string' && item.iconPath.length > 0);
46
+ if (!hasIcon) {
47
+ throw new StatusBarValidationError(`Top-level status-bar item '${item.id}' must provide 'icon' or 'iconPath'`);
48
+ }
49
+ if (item.id.includes(':')) {
50
+ throw new StatusBarValidationError(`Status-bar item id '${item.id}' cannot contain ':' (reserved path separator)`);
51
+ }
52
+ if (Array.isArray(item.submenu)) {
53
+ validateSiblings(item.submenu, 2);
54
+ }
55
+ else if (item.submenu !== undefined) {
56
+ throw new StatusBarValidationError(`submenu on item '${item.id}' must be an array when present`);
57
+ }
58
+ }
59
+ function validateSiblings(items, depth) {
60
+ if (depth > exports.MAX_STATUS_BAR_DEPTH) {
61
+ throw new StatusBarValidationError(`Status-bar submenu nested deeper than max depth ${exports.MAX_STATUS_BAR_DEPTH}`);
62
+ }
63
+ const seenIds = new Set();
64
+ for (const child of items) {
65
+ if (!child || typeof child !== 'object') {
66
+ throw new StatusBarValidationError('Submenu item must be an object');
67
+ }
68
+ if (child.separator === true) {
69
+ if (child.submenu !== undefined) {
70
+ throw new StatusBarValidationError('Separator rows cannot have a submenu');
71
+ }
72
+ if (child.checked !== undefined) {
73
+ throw new StatusBarValidationError('Separator rows cannot be checkable');
74
+ }
75
+ continue;
76
+ }
77
+ if (typeof child.id !== 'string' || child.id.trim() === '') {
78
+ throw new StatusBarValidationError('Submenu item id must be a non-empty string');
79
+ }
80
+ if (child.id.includes(':')) {
81
+ throw new StatusBarValidationError(`Status-bar item id '${child.id}' cannot contain ':' (reserved path separator)`);
82
+ }
83
+ if (seenIds.has(child.id)) {
84
+ throw new StatusBarValidationError(`Duplicate sibling id '${child.id}' inside submenu`);
85
+ }
86
+ seenIds.add(child.id);
87
+ if (Array.isArray(child.submenu)) {
88
+ validateSiblings(child.submenu, depth + 1);
89
+ }
90
+ else if (child.submenu !== undefined) {
91
+ throw new StatusBarValidationError(`submenu on item '${child.id}' must be an array when present`);
92
+ }
93
+ }
94
+ }
95
+ class StatusBarValidationError extends Error {
96
+ constructor(message) {
97
+ super(message);
98
+ this.name = 'StatusBarValidationError';
99
+ }
100
+ }
101
+ exports.StatusBarValidationError = StatusBarValidationError;
102
+ /**
103
+ * Strip `onClick` callbacks from the tree before IPC serialization. Returns
104
+ * a deep copy safe to postMessage, leaving the original untouched so the
105
+ * SDK can keep dispatching to the original handlers.
106
+ */
107
+ function stripHandlers(item) {
108
+ const { onClick: _onClick, submenu } = item, rest = __rest(item, ["onClick", "submenu"]);
109
+ const copy = Object.assign({}, rest);
110
+ if (Array.isArray(submenu)) {
111
+ copy.submenu = submenu.map(stripHandlers);
112
+ }
113
+ return copy;
114
+ }
115
+ /**
116
+ * Walk the tree collecting `onClick` handlers keyed by their
117
+ * `:`-joined item path. Used by the proxy to dispatch tray click events.
118
+ */
119
+ function collectHandlers(item) {
120
+ const out = new Map();
121
+ walk(item, [], out);
122
+ return out;
123
+ }
124
+ function walk(item, parentPath, out) {
125
+ var _a;
126
+ if (item.separator === true)
127
+ return;
128
+ // Non-separator items carry an id by contract (validator enforces
129
+ // non-empty). Fallback to '' is purely for type safety here.
130
+ const path = [...parentPath, (_a = item.id) !== null && _a !== void 0 ? _a : ''];
131
+ if (typeof item.onClick === 'function') {
132
+ out.set(path.join(':'), item.onClick);
133
+ }
134
+ if (Array.isArray(item.submenu)) {
135
+ for (const child of item.submenu) {
136
+ walk(child, path, out);
137
+ }
138
+ }
139
+ }
140
+ //# sourceMappingURL=statusBarValidation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statusBarValidation.js","sourceRoot":"","sources":["../../src/services/statusBarValidation.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "asyar-sdk",
3
- "version": "1.15.4",
3
+ "version": "1.15.6",
4
4
  "main": "dist/index.js",
5
5
  "bin": {
6
6
  "asyar": "./dist/cli/index.js"