@reset-framework/sdk 0.2.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reset-framework/sdk",
3
- "version": "0.2.1",
3
+ "version": "1.0.2",
4
4
  "type": "module",
5
5
  "description": "Browser-side SDK for Reset Framework applications.",
6
6
  "license": "MIT",
@@ -10,7 +10,11 @@
10
10
  "sideEffects": false,
11
11
  "types": "./src/index.d.ts",
12
12
  "exports": {
13
- ".": "./src/index.js",
13
+ ".": {
14
+ "types": "./src/index.d.ts",
15
+ "import": "./src/index.js",
16
+ "default": "./src/index.js"
17
+ },
14
18
  "./package.json": "./package.json"
15
19
  },
16
20
  "files": [
package/src/client.js CHANGED
@@ -5,6 +5,7 @@ import {
5
5
  invokeRaw,
6
6
  isResetRuntimeAvailable
7
7
  } from "./transport.js"
8
+ import { createEventApi } from "./events.js"
8
9
  import { ResetProtocolError } from "./errors.js"
9
10
 
10
11
  function isObjectLike(value) {
@@ -48,6 +49,19 @@ function requireBooleanField(record, field, command) {
48
49
  return value
49
50
  }
50
51
 
52
+ function requireNumberField(record, field, command) {
53
+ const value = record[field]
54
+
55
+ if (typeof value !== "number" || Number.isNaN(value)) {
56
+ throw new ResetProtocolError(
57
+ `Reset runtime returned an invalid '${field}' field for '${command}'.`,
58
+ { command }
59
+ )
60
+ }
61
+
62
+ return value
63
+ }
64
+
51
65
  function normalizeAppInfo(payload, command) {
52
66
  const record = requireObject(payload, command)
53
67
 
@@ -72,6 +86,17 @@ function normalizeRuntimeInfo(payload, command) {
72
86
  })
73
87
  }
74
88
 
89
+ function normalizeCapabilities(payload, command) {
90
+ const record = requireObject(payload, command)
91
+ const commands = Array.isArray(record.commands) ? record.commands : []
92
+ const permissions = Array.isArray(record.permissions) ? record.permissions : []
93
+
94
+ return Object.freeze({
95
+ commands: Object.freeze(commands.map((entry) => Object.freeze({ ...entry }))),
96
+ permissions: Object.freeze([...permissions])
97
+ })
98
+ }
99
+
75
100
  function createCommandApi(transport) {
76
101
  return Object.freeze({
77
102
  invoke(command, payload = {}) {
@@ -103,6 +128,18 @@ function createAppApi(transport) {
103
128
  },
104
129
  async getInfo() {
105
130
  return normalizeAppInfo(await transport.invoke("app.getInfo"), "app.getInfo")
131
+ },
132
+ show() {
133
+ return transport.invoke("app.show")
134
+ },
135
+ hide() {
136
+ return transport.invoke("app.hide")
137
+ },
138
+ quit() {
139
+ return transport.invoke("app.quit")
140
+ },
141
+ relaunch() {
142
+ return transport.invoke("app.relaunch")
106
143
  }
107
144
  })
108
145
  }
@@ -133,6 +170,395 @@ function createRuntimeApi(transport) {
133
170
  },
134
171
  async getInfo() {
135
172
  return normalizeRuntimeInfo(await transport.invoke("runtime.getInfo"), "runtime.getInfo")
173
+ },
174
+ async getCapabilities() {
175
+ return normalizeCapabilities(
176
+ await transport.invoke("runtime.getCapabilities"),
177
+ "runtime.getCapabilities"
178
+ )
179
+ }
180
+ })
181
+ }
182
+
183
+ function createWindowApi(transport) {
184
+ return Object.freeze({
185
+ getCurrent() {
186
+ return transport.invoke("window.getCurrent")
187
+ },
188
+ getInfo() {
189
+ return transport.invoke("window.getInfo")
190
+ },
191
+ list() {
192
+ return transport.invoke("window.list")
193
+ },
194
+ show() {
195
+ return transport.invoke("window.show")
196
+ },
197
+ hide() {
198
+ return transport.invoke("window.hide")
199
+ },
200
+ focus() {
201
+ return transport.invoke("window.focus")
202
+ },
203
+ close() {
204
+ return transport.invoke("window.close")
205
+ },
206
+ minimize() {
207
+ return transport.invoke("window.minimize")
208
+ },
209
+ maximize() {
210
+ return transport.invoke("window.maximize")
211
+ },
212
+ center() {
213
+ return transport.invoke("window.center")
214
+ },
215
+ setTitle(title) {
216
+ return transport.invoke("window.setTitle", { title })
217
+ },
218
+ setSize(width, height) {
219
+ return transport.invoke("window.setSize", { width, height })
220
+ },
221
+ setResizable(resizable) {
222
+ return transport.invoke("window.setResizable", { resizable })
223
+ }
224
+ })
225
+ }
226
+
227
+ function createDialogApi(transport) {
228
+ return Object.freeze({
229
+ openFile(options = {}) {
230
+ return transport.invoke("dialog.openFile", options)
231
+ },
232
+ saveFile(options = {}) {
233
+ return transport.invoke("dialog.saveFile", options)
234
+ },
235
+ message(title, message) {
236
+ return transport.invoke("dialog.message", { title, message })
237
+ },
238
+ confirm(title, message) {
239
+ return transport.invoke("dialog.confirm", { title, message })
240
+ }
241
+ })
242
+ }
243
+
244
+ function createFsApi(transport) {
245
+ return Object.freeze({
246
+ async readTextFile(path) {
247
+ const payload = requireObject(await transport.invoke("fs.readTextFile", { path }), "fs.readTextFile")
248
+ return requireStringField(payload, "text", "fs.readTextFile")
249
+ },
250
+ writeTextFile(path, text, options = {}) {
251
+ return transport.invoke("fs.writeTextFile", {
252
+ path,
253
+ text,
254
+ ...options
255
+ })
256
+ },
257
+ async exists(path) {
258
+ const payload = requireObject(await transport.invoke("fs.exists", { path }), "fs.exists")
259
+ return requireBooleanField(payload, "exists", "fs.exists")
260
+ },
261
+ mkdir(path, options = {}) {
262
+ return transport.invoke("fs.mkdir", {
263
+ path,
264
+ ...options
265
+ })
266
+ },
267
+ remove(path, options = {}) {
268
+ return transport.invoke("fs.remove", {
269
+ path,
270
+ ...options
271
+ })
272
+ },
273
+ rename(from, to) {
274
+ return transport.invoke("fs.rename", { from, to })
275
+ },
276
+ async readDir(path) {
277
+ const payload = requireObject(await transport.invoke("fs.readDir", { path }), "fs.readDir")
278
+ return Array.isArray(payload.entries) ? payload.entries : []
279
+ }
280
+ })
281
+ }
282
+
283
+ function createPathApi(transport) {
284
+ return Object.freeze({
285
+ async join(...segments) {
286
+ const payload = requireObject(await transport.invoke("path.join", { segments }), "path.join")
287
+ return requireStringField(payload, "path", "path.join")
288
+ },
289
+ async basename(path) {
290
+ const payload = requireObject(await transport.invoke("path.basename", { path }), "path.basename")
291
+ return requireStringField(payload, "name", "path.basename")
292
+ },
293
+ async dirname(path) {
294
+ const payload = requireObject(await transport.invoke("path.dirname", { path }), "path.dirname")
295
+ return requireStringField(payload, "path", "path.dirname")
296
+ },
297
+ async resolve(path, base) {
298
+ const payload = requireObject(await transport.invoke("path.resolve", { path, base }), "path.resolve")
299
+ return requireStringField(payload, "path", "path.resolve")
300
+ },
301
+ async getHomeDir() {
302
+ const payload = requireObject(await transport.invoke("path.getHomeDir"), "path.getHomeDir")
303
+ return requireStringField(payload, "path", "path.getHomeDir")
304
+ },
305
+ async getTempDir() {
306
+ const payload = requireObject(await transport.invoke("path.getTempDir"), "path.getTempDir")
307
+ return requireStringField(payload, "path", "path.getTempDir")
308
+ },
309
+ async getAppDataDir() {
310
+ const payload = requireObject(await transport.invoke("path.getAppDataDir"), "path.getAppDataDir")
311
+ return requireStringField(payload, "path", "path.getAppDataDir")
312
+ },
313
+ async getAppConfigDir() {
314
+ const payload = requireObject(await transport.invoke("path.getAppConfigDir"), "path.getAppConfigDir")
315
+ return requireStringField(payload, "path", "path.getAppConfigDir")
316
+ },
317
+ async getCacheDir() {
318
+ const payload = requireObject(await transport.invoke("path.getCacheDir"), "path.getCacheDir")
319
+ return requireStringField(payload, "path", "path.getCacheDir")
320
+ },
321
+ getInfo() {
322
+ return transport.invoke("path.getInfo")
323
+ }
324
+ })
325
+ }
326
+
327
+ function createShellApi(transport) {
328
+ return Object.freeze({
329
+ openExternal(url) {
330
+ return transport.invoke("shell.openExternal", { url })
331
+ },
332
+ openPath(path) {
333
+ return transport.invoke("shell.openPath", { path })
334
+ },
335
+ showItemInFolder(path) {
336
+ return transport.invoke("shell.showItemInFolder", { path })
337
+ }
338
+ })
339
+ }
340
+
341
+ function createClipboardApi(transport) {
342
+ return Object.freeze({
343
+ async readText() {
344
+ const payload = requireObject(await transport.invoke("clipboard.readText"), "clipboard.readText")
345
+ return requireStringField(payload, "text", "clipboard.readText")
346
+ },
347
+ writeText(text) {
348
+ return transport.invoke("clipboard.writeText", { text })
349
+ }
350
+ })
351
+ }
352
+
353
+ function createNotificationApi(transport) {
354
+ return Object.freeze({
355
+ async isSupported() {
356
+ const payload = requireObject(
357
+ await transport.invoke("notification.isSupported"),
358
+ "notification.isSupported"
359
+ )
360
+ return requireBooleanField(payload, "supported", "notification.isSupported")
361
+ },
362
+ requestPermission() {
363
+ return transport.invoke("notification.requestPermission")
364
+ },
365
+ show(options) {
366
+ return transport.invoke("notification.show", options)
367
+ }
368
+ })
369
+ }
370
+
371
+ function createScreenApi(transport) {
372
+ return Object.freeze({
373
+ getCursorPosition() {
374
+ return transport.invoke("screen.getCursorPosition")
375
+ },
376
+ getPrimaryDisplay() {
377
+ return transport.invoke("screen.getPrimaryDisplay")
378
+ },
379
+ async getDisplays() {
380
+ const payload = requireObject(await transport.invoke("screen.getDisplays"), "screen.getDisplays")
381
+ return Array.isArray(payload.displays) ? payload.displays : []
382
+ }
383
+ })
384
+ }
385
+
386
+ function createStorageApi(transport) {
387
+ return Object.freeze({
388
+ async get(key) {
389
+ const payload = requireObject(await transport.invoke("storage.get", { key }), "storage.get")
390
+ return payload.value
391
+ },
392
+ set(key, value) {
393
+ return transport.invoke("storage.set", { key, value })
394
+ },
395
+ remove(key) {
396
+ return transport.invoke("storage.remove", { key })
397
+ },
398
+ clear() {
399
+ return transport.invoke("storage.clear")
400
+ },
401
+ async getAll() {
402
+ const payload = requireObject(await transport.invoke("storage.getAll"), "storage.getAll")
403
+ return requireObject(payload.entries ?? {}, "storage.getAll")
404
+ }
405
+ })
406
+ }
407
+
408
+ function createWebViewApi(transport) {
409
+ return Object.freeze({
410
+ getInfo() {
411
+ return transport.invoke("webview.getInfo")
412
+ },
413
+ reload() {
414
+ return transport.invoke("webview.reload")
415
+ },
416
+ goBack() {
417
+ return transport.invoke("webview.goBack")
418
+ },
419
+ goForward() {
420
+ return transport.invoke("webview.goForward")
421
+ },
422
+ navigate(options) {
423
+ return transport.invoke("webview.navigate", options)
424
+ },
425
+ setZoomFactor(factor) {
426
+ return transport.invoke("webview.setZoomFactor", { factor })
427
+ }
428
+ })
429
+ }
430
+
431
+ function createCryptoApi(transport) {
432
+ return Object.freeze({
433
+ getInfo() {
434
+ return transport.invoke("crypto.getInfo")
435
+ },
436
+ randomBytes(size, options = {}) {
437
+ return transport.invoke("crypto.randomBytes", {
438
+ size,
439
+ encoding: options.encoding
440
+ })
441
+ },
442
+ async randomUuid() {
443
+ const payload = requireObject(await transport.invoke("crypto.randomUuid"), "crypto.randomUuid")
444
+ return requireStringField(payload, "uuid", "crypto.randomUuid")
445
+ }
446
+ })
447
+ }
448
+
449
+ function createProcessApi(transport) {
450
+ return Object.freeze({
451
+ async getPid() {
452
+ const payload = requireObject(await transport.invoke("process.getPid"), "process.getPid")
453
+ return requireNumberField(payload, "pid", "process.getPid")
454
+ },
455
+ async getCwd() {
456
+ const payload = requireObject(await transport.invoke("process.getCwd"), "process.getCwd")
457
+ return requireStringField(payload, "path", "process.getCwd")
458
+ },
459
+ getInfo() {
460
+ return transport.invoke("process.getInfo")
461
+ }
462
+ })
463
+ }
464
+
465
+ function createPowerApi(transport) {
466
+ return Object.freeze({
467
+ getInfo() {
468
+ return transport.invoke("power.getInfo")
469
+ }
470
+ })
471
+ }
472
+
473
+ function createMenuApi(transport) {
474
+ return Object.freeze({
475
+ getInfo() {
476
+ return transport.invoke("menu.getInfo")
477
+ },
478
+ setApplicationMenu(items) {
479
+ return transport.invoke("menu.setApplicationMenu", { items })
480
+ },
481
+ clearApplicationMenu() {
482
+ return transport.invoke("menu.clearApplicationMenu")
483
+ }
484
+ })
485
+ }
486
+
487
+ function createTrayApi(transport) {
488
+ return Object.freeze({
489
+ getInfo() {
490
+ return transport.invoke("tray.getInfo")
491
+ },
492
+ create(options = {}) {
493
+ return transport.invoke("tray.create", options)
494
+ },
495
+ setTitle(title) {
496
+ return transport.invoke("tray.setTitle", { title })
497
+ },
498
+ setTooltip(tooltip) {
499
+ return transport.invoke("tray.setTooltip", { tooltip })
500
+ },
501
+ setMenu(items) {
502
+ return transport.invoke("tray.setMenu", { items })
503
+ },
504
+ destroy() {
505
+ return transport.invoke("tray.destroy")
506
+ }
507
+ })
508
+ }
509
+
510
+ function createShortcutApi(transport) {
511
+ return Object.freeze({
512
+ getInfo() {
513
+ return transport.invoke("shortcut.getInfo")
514
+ },
515
+ register(accelerator) {
516
+ return transport.invoke("shortcut.register", { accelerator })
517
+ },
518
+ unregister(accelerator) {
519
+ return transport.invoke("shortcut.unregister", { accelerator })
520
+ },
521
+ unregisterAll() {
522
+ return transport.invoke("shortcut.unregisterAll")
523
+ }
524
+ })
525
+ }
526
+
527
+ function createProtocolApi(transport) {
528
+ return Object.freeze({
529
+ getInfo() {
530
+ return transport.invoke("protocol.getInfo")
531
+ },
532
+ register(options = {}) {
533
+ return transport.invoke("protocol.register", options)
534
+ },
535
+ unregister(options = {}) {
536
+ return transport.invoke("protocol.unregister", options)
537
+ }
538
+ })
539
+ }
540
+
541
+ function createUpdaterApi(transport) {
542
+ return Object.freeze({
543
+ getInfo() {
544
+ return transport.invoke("updater.getInfo")
545
+ },
546
+ check(options = {}) {
547
+ return transport.invoke("updater.check", options)
548
+ },
549
+ download(options = {}) {
550
+ return transport.invoke("updater.download", options)
551
+ },
552
+ install(options = {}) {
553
+ return transport.invoke("updater.install", options)
554
+ }
555
+ })
556
+ }
557
+
558
+ function createNetApi(transport) {
559
+ return Object.freeze({
560
+ request(options) {
561
+ return transport.invoke("net.request", options)
136
562
  }
137
563
  })
138
564
  }
@@ -142,6 +568,26 @@ export function createResetClient(source) {
142
568
  const commands = createCommandApi(transport)
143
569
  const app = createAppApi(transport)
144
570
  const runtime = createRuntimeApi(transport)
571
+ const events = createEventApi(transport)
572
+ const window = createWindowApi(transport)
573
+ const dialog = createDialogApi(transport)
574
+ const fs = createFsApi(transport)
575
+ const path = createPathApi(transport)
576
+ const shell = createShellApi(transport)
577
+ const clipboard = createClipboardApi(transport)
578
+ const notification = createNotificationApi(transport)
579
+ const screen = createScreenApi(transport)
580
+ const storage = createStorageApi(transport)
581
+ const webview = createWebViewApi(transport)
582
+ const crypto = createCryptoApi(transport)
583
+ const process = createProcessApi(transport)
584
+ const power = createPowerApi(transport)
585
+ const menu = createMenuApi(transport)
586
+ const tray = createTrayApi(transport)
587
+ const shortcut = createShortcutApi(transport)
588
+ const protocol = createProtocolApi(transport)
589
+ const updater = createUpdaterApi(transport)
590
+ const net = createNetApi(transport)
145
591
 
146
592
  return Object.freeze({
147
593
  isAvailable() {
@@ -152,7 +598,27 @@ export function createResetClient(source) {
152
598
  },
153
599
  commands,
154
600
  app,
155
- runtime
601
+ runtime,
602
+ events,
603
+ window,
604
+ dialog,
605
+ fs,
606
+ path,
607
+ shell,
608
+ clipboard,
609
+ notification,
610
+ screen,
611
+ storage,
612
+ webview,
613
+ crypto,
614
+ process,
615
+ power,
616
+ menu,
617
+ tray,
618
+ shortcut,
619
+ protocol,
620
+ updater,
621
+ net
156
622
  })
157
623
  }
158
624
 
@@ -168,3 +634,23 @@ export const reset = createResetClient()
168
634
  export const commands = reset.commands
169
635
  export const app = reset.app
170
636
  export const runtime = reset.runtime
637
+ export const events = reset.events
638
+ export const window = reset.window
639
+ export const dialog = reset.dialog
640
+ export const fs = reset.fs
641
+ export const path = reset.path
642
+ export const shell = reset.shell
643
+ export const clipboard = reset.clipboard
644
+ export const notification = reset.notification
645
+ export const screen = reset.screen
646
+ export const storage = reset.storage
647
+ export const webview = reset.webview
648
+ export const crypto = reset.crypto
649
+ export const process = reset.process
650
+ export const power = reset.power
651
+ export const menu = reset.menu
652
+ export const tray = reset.tray
653
+ export const shortcut = reset.shortcut
654
+ export const protocol = reset.protocol
655
+ export const updater = reset.updater
656
+ export const net = reset.net
package/src/errors.js CHANGED
@@ -26,6 +26,8 @@ export class ResetInvocationError extends ResetRuntimeError {
26
26
  constructor(command, message, response, options = {}) {
27
27
  super(message, options)
28
28
  this.command = command
29
+ this.code = response?.code
30
+ this.details = response?.details
29
31
  this.response = response
30
32
  }
31
33
  }
package/src/events.js ADDED
@@ -0,0 +1,123 @@
1
+ function getDefaultWindowTarget() {
2
+ if (typeof window === "undefined") {
3
+ return undefined
4
+ }
5
+
6
+ return window
7
+ }
8
+
9
+ function getState(target = getDefaultWindowTarget()) {
10
+ if (!target) {
11
+ return null
12
+ }
13
+
14
+ if (!target.__resetEventState) {
15
+ const listeners = new Map()
16
+
17
+ target.__resetEventState = {
18
+ listeners,
19
+ dispatch(envelope) {
20
+ const eventName = typeof envelope?.event === "string" ? envelope.event : ""
21
+ if (eventName === "") {
22
+ return
23
+ }
24
+
25
+ const handlers = listeners.get(eventName)
26
+ if (!handlers) {
27
+ return
28
+ }
29
+
30
+ for (const handler of [...handlers]) {
31
+ handler(envelope.payload)
32
+ }
33
+ }
34
+ }
35
+
36
+ Object.defineProperty(target, "__resetDispatchEvent", {
37
+ value: (envelope) => target.__resetEventState.dispatch(envelope),
38
+ configurable: false,
39
+ enumerable: false,
40
+ writable: false
41
+ })
42
+ }
43
+
44
+ return target.__resetEventState
45
+ }
46
+
47
+ export function listen(eventName, handler, target = getDefaultWindowTarget()) {
48
+ if (typeof eventName !== "string" || eventName.trim() === "") {
49
+ throw new TypeError("Reset event name must be a non-empty string.")
50
+ }
51
+
52
+ if (typeof handler !== "function") {
53
+ throw new TypeError("Reset event handler must be a function.")
54
+ }
55
+
56
+ const state = getState(target)
57
+ if (!state) {
58
+ return () => {}
59
+ }
60
+
61
+ const handlers = state.listeners.get(eventName) ?? new Set()
62
+ handlers.add(handler)
63
+ state.listeners.set(eventName, handlers)
64
+
65
+ return () => {
66
+ const current = state.listeners.get(eventName)
67
+ if (!current) {
68
+ return
69
+ }
70
+
71
+ current.delete(handler)
72
+ if (current.size === 0) {
73
+ state.listeners.delete(eventName)
74
+ }
75
+ }
76
+ }
77
+
78
+ export function once(eventName, handler, target = getDefaultWindowTarget()) {
79
+ let dispose = () => {}
80
+
81
+ dispose = listen(
82
+ eventName,
83
+ (payload) => {
84
+ dispose()
85
+ handler(payload)
86
+ },
87
+ target
88
+ )
89
+
90
+ return dispose
91
+ }
92
+
93
+ export function emitLocal(eventName, payload, target = getDefaultWindowTarget()) {
94
+ const state = getState(target)
95
+ if (!state) {
96
+ return
97
+ }
98
+
99
+ state.dispatch({
100
+ event: eventName,
101
+ payload
102
+ })
103
+ }
104
+
105
+ export function createEventApi(transport, target = getDefaultWindowTarget()) {
106
+ return Object.freeze({
107
+ listen(eventName, handler) {
108
+ return listen(eventName, handler, target)
109
+ },
110
+ once(eventName, handler) {
111
+ return once(eventName, handler, target)
112
+ },
113
+ emitLocal(eventName, payload) {
114
+ emitLocal(eventName, payload, target)
115
+ },
116
+ emit(eventName, payload = null) {
117
+ return transport.invoke("event.emit", {
118
+ event: eventName,
119
+ payload
120
+ })
121
+ }
122
+ })
123
+ }
package/src/index.d.ts CHANGED
@@ -6,6 +6,8 @@ export type ResetInvokeSuccess<T = unknown> = {
6
6
  export type ResetInvokeError = {
7
7
  ok: false;
8
8
  error: string;
9
+ code?: string;
10
+ details?: unknown;
9
11
  };
10
12
 
11
13
  export type ResetInvokeResponse<T = unknown> =
@@ -25,6 +27,11 @@ export interface ResetRuntime {
25
27
 
26
28
  export interface ResetRuntimeWindow {
27
29
  reset?: ResetRuntime;
30
+ __resetEventState?: {
31
+ listeners: Map<string, Set<(payload: unknown) => void>>;
32
+ dispatch(envelope: { event: string; payload: unknown }): void;
33
+ };
34
+ __resetDispatchEvent?: (envelope: { event: string; payload: unknown }) => void;
28
35
  }
29
36
 
30
37
  export interface ResetRuntimeSourceOptions {
@@ -66,6 +73,38 @@ export interface ResetAppInfo {
66
73
  windowTitle: string;
67
74
  }
68
75
 
76
+ export interface ResetPoint {
77
+ x: number;
78
+ y: number;
79
+ }
80
+
81
+ export interface ResetSize {
82
+ width: number;
83
+ height: number;
84
+ }
85
+
86
+ export interface ResetRect extends ResetPoint, ResetSize {}
87
+
88
+ export interface ResetWindowInfo {
89
+ id: string;
90
+ title: string;
91
+ frame: ResetRect;
92
+ position: ResetPoint;
93
+ size: ResetSize;
94
+ visible: boolean;
95
+ focused: boolean;
96
+ minimized: boolean;
97
+ maximized: boolean;
98
+ resizable: boolean;
99
+ }
100
+
101
+ export interface ResetDisplayInfo {
102
+ id: string;
103
+ frame: ResetRect;
104
+ visibleFrame: ResetRect;
105
+ scaleFactor: number;
106
+ }
107
+
69
108
  export interface ResetRuntimeInfo {
70
109
  platform: ResetPlatform;
71
110
  arch: ResetArchitecture;
@@ -74,12 +113,26 @@ export interface ResetRuntimeInfo {
74
113
  debug: boolean;
75
114
  }
76
115
 
116
+ export interface ResetCommandDescriptor {
117
+ command: string;
118
+ permission: string;
119
+ }
120
+
121
+ export interface ResetCapabilitiesInfo {
122
+ commands: ReadonlyArray<ResetCommandDescriptor>;
123
+ permissions: ReadonlyArray<string>;
124
+ }
125
+
77
126
  export interface ResetAppApi {
78
127
  getId(): Promise<string>;
79
128
  getName(): Promise<string>;
80
129
  getSlug(): Promise<string>;
81
130
  getVersion(): Promise<string>;
82
131
  getInfo(): Promise<ResetAppInfo>;
132
+ show(): Promise<{ visible: boolean }>;
133
+ hide(): Promise<{ hidden: boolean }>;
134
+ quit(): Promise<{ quitting: boolean }>;
135
+ relaunch(): Promise<{ relaunching: boolean }>;
83
136
  }
84
137
 
85
138
  export interface ResetRuntimeApi {
@@ -88,6 +141,281 @@ export interface ResetRuntimeApi {
88
141
  getFrameworkVersion(): Promise<string>;
89
142
  getBridgeVersion(): Promise<string>;
90
143
  getInfo(): Promise<ResetRuntimeInfo>;
144
+ getCapabilities(): Promise<ResetCapabilitiesInfo>;
145
+ }
146
+
147
+ export interface ResetWindowApi {
148
+ getCurrent(): Promise<ResetWindowInfo>;
149
+ getInfo(): Promise<ResetWindowInfo>;
150
+ list(): Promise<{ windows: ResetWindowInfo[] }>;
151
+ show(): Promise<ResetWindowInfo>;
152
+ hide(): Promise<ResetWindowInfo>;
153
+ focus(): Promise<ResetWindowInfo>;
154
+ close(): Promise<{ closed: boolean }>;
155
+ minimize(): Promise<ResetWindowInfo>;
156
+ maximize(): Promise<ResetWindowInfo>;
157
+ center(): Promise<ResetWindowInfo>;
158
+ setTitle(title: string): Promise<ResetWindowInfo>;
159
+ setSize(width: number, height: number): Promise<ResetWindowInfo>;
160
+ setResizable(resizable: boolean): Promise<ResetWindowInfo>;
161
+ }
162
+
163
+ export interface ResetDialogOpenFileOptions {
164
+ title?: string;
165
+ multiple?: boolean;
166
+ directory?: boolean;
167
+ }
168
+
169
+ export interface ResetDialogSaveFileOptions {
170
+ title?: string;
171
+ defaultPath?: string;
172
+ }
173
+
174
+ export interface ResetDialogApi {
175
+ openFile(options?: ResetDialogOpenFileOptions): Promise<{
176
+ canceled: boolean;
177
+ paths: string[];
178
+ }>;
179
+ saveFile(options?: ResetDialogSaveFileOptions): Promise<{
180
+ canceled: boolean;
181
+ path?: string;
182
+ }>;
183
+ message(title: string, message: string): Promise<{ confirmed: boolean }>;
184
+ confirm(title: string, message: string): Promise<{ confirmed: boolean }>;
185
+ }
186
+
187
+ export interface ResetDirectoryEntry {
188
+ name: string;
189
+ path: string;
190
+ kind: "file" | "directory" | "symlink" | "other";
191
+ }
192
+
193
+ export interface ResetFsApi {
194
+ readTextFile(path: string): Promise<string>;
195
+ writeTextFile(
196
+ path: string,
197
+ text: string,
198
+ options?: { createDirectories?: boolean }
199
+ ): Promise<{ written: boolean }>;
200
+ exists(path: string): Promise<boolean>;
201
+ mkdir(
202
+ path: string,
203
+ options?: { recursive?: boolean }
204
+ ): Promise<{ created: boolean }>;
205
+ remove(
206
+ path: string,
207
+ options?: { recursive?: boolean }
208
+ ): Promise<{ removed: boolean; count: number }>;
209
+ rename(from: string, to: string): Promise<{ renamed: boolean }>;
210
+ readDir(path: string): Promise<ResetDirectoryEntry[]>;
211
+ }
212
+
213
+ export interface ResetPathInfo {
214
+ homeDir: string;
215
+ tempDir: string;
216
+ appDataDir: string;
217
+ appConfigDir: string;
218
+ cacheDir: string;
219
+ }
220
+
221
+ export interface ResetPathApi {
222
+ join(...segments: string[]): Promise<string>;
223
+ basename(path: string): Promise<string>;
224
+ dirname(path: string): Promise<string>;
225
+ resolve(path: string, base?: string): Promise<string>;
226
+ getHomeDir(): Promise<string>;
227
+ getTempDir(): Promise<string>;
228
+ getAppDataDir(): Promise<string>;
229
+ getAppConfigDir(): Promise<string>;
230
+ getCacheDir(): Promise<string>;
231
+ getInfo(): Promise<ResetPathInfo>;
232
+ }
233
+
234
+ export interface ResetShellApi {
235
+ openExternal(url: string): Promise<{ opened: boolean }>;
236
+ openPath(path: string): Promise<{ opened: boolean }>;
237
+ showItemInFolder(path: string): Promise<{ shown: boolean }>;
238
+ }
239
+
240
+ export interface ResetClipboardApi {
241
+ readText(): Promise<string>;
242
+ writeText(text: string): Promise<{ written: boolean }>;
243
+ }
244
+
245
+ export interface ResetNotificationApi {
246
+ isSupported(): Promise<boolean>;
247
+ requestPermission(): Promise<{
248
+ supported: boolean;
249
+ authorized: boolean;
250
+ status: string;
251
+ }>;
252
+ show(options: { title: string; body?: string }): Promise<{
253
+ shown: boolean;
254
+ authorized: boolean;
255
+ id?: string;
256
+ }>;
257
+ }
258
+
259
+ export interface ResetScreenApi {
260
+ getCursorPosition(): Promise<ResetPoint>;
261
+ getPrimaryDisplay(): Promise<ResetDisplayInfo | null>;
262
+ getDisplays(): Promise<ResetDisplayInfo[]>;
263
+ }
264
+
265
+ export interface ResetStorageApi {
266
+ get<T = unknown>(key: string): Promise<T | null>;
267
+ set(key: string, value: unknown): Promise<{ key: string; stored: boolean }>;
268
+ remove(key: string): Promise<{ key: string; removed: boolean }>;
269
+ clear(): Promise<{ cleared: boolean }>;
270
+ getAll(): Promise<Record<string, unknown>>;
271
+ }
272
+
273
+ export interface ResetWebViewInfo {
274
+ title: string;
275
+ url: string;
276
+ canGoBack: boolean;
277
+ canGoForward: boolean;
278
+ loading: boolean;
279
+ estimatedProgress: number;
280
+ }
281
+
282
+ export interface ResetWebViewApi {
283
+ getInfo(): Promise<ResetWebViewInfo>;
284
+ reload(): Promise<ResetWebViewInfo>;
285
+ goBack(): Promise<ResetWebViewInfo>;
286
+ goForward(): Promise<ResetWebViewInfo>;
287
+ navigate(options: { url?: string; path?: string }): Promise<ResetWebViewInfo>;
288
+ setZoomFactor(factor: number): Promise<ResetWebViewInfo>;
289
+ }
290
+
291
+ export interface ResetCryptoApi {
292
+ getInfo(): Promise<{
293
+ supported: boolean;
294
+ encodings: string[];
295
+ maxRandomBytes: number;
296
+ }>;
297
+ randomBytes(
298
+ size: number,
299
+ options?: { encoding?: "hex" | "base64url" }
300
+ ): Promise<{
301
+ size: number;
302
+ encoding: "hex" | "base64url";
303
+ value: string;
304
+ }>;
305
+ randomUuid(): Promise<string>;
306
+ }
307
+
308
+ export interface ResetProcessInfo {
309
+ pid: number;
310
+ cwd: string;
311
+ platform: ResetPlatform;
312
+ arch: ResetArchitecture;
313
+ debug: boolean;
314
+ }
315
+
316
+ export interface ResetProcessApi {
317
+ getPid(): Promise<number>;
318
+ getCwd(): Promise<string>;
319
+ getInfo(): Promise<ResetProcessInfo>;
320
+ }
321
+
322
+ export interface ResetPowerInfo {
323
+ supported: boolean;
324
+ lowPowerMode: boolean;
325
+ thermalState: string;
326
+ }
327
+
328
+ export interface ResetPowerApi {
329
+ getInfo(): Promise<ResetPowerInfo>;
330
+ }
331
+
332
+ export interface ResetSupportInfo {
333
+ supported: boolean;
334
+ module: string;
335
+ platform: ResetPlatform | string;
336
+ }
337
+
338
+ export interface ResetMenuInfo extends ResetSupportInfo {
339
+ installed: boolean;
340
+ topLevelCount: number;
341
+ }
342
+
343
+ export interface ResetTrayInfo extends ResetSupportInfo {
344
+ created: boolean;
345
+ title: string;
346
+ tooltip: string;
347
+ hasMenu: boolean;
348
+ }
349
+
350
+ export interface ResetMenuItem {
351
+ id?: string;
352
+ label?: string;
353
+ enabled?: boolean;
354
+ checked?: boolean;
355
+ separator?: boolean;
356
+ submenu?: ResetMenuItem[];
357
+ }
358
+
359
+ export interface ResetMenuApi {
360
+ getInfo(): Promise<ResetMenuInfo>;
361
+ setApplicationMenu(items: ResetMenuItem[]): Promise<ResetMenuInfo>;
362
+ clearApplicationMenu(): Promise<ResetMenuInfo>;
363
+ }
364
+
365
+ export interface ResetTrayApi {
366
+ getInfo(): Promise<ResetTrayInfo>;
367
+ create(options?: {
368
+ title?: string;
369
+ tooltip?: string;
370
+ items?: ResetMenuItem[];
371
+ }): Promise<ResetTrayInfo>;
372
+ setTitle(title: string): Promise<ResetTrayInfo>;
373
+ setTooltip(tooltip: string): Promise<ResetTrayInfo>;
374
+ setMenu(items: ResetMenuItem[]): Promise<ResetTrayInfo>;
375
+ destroy(): Promise<{ destroyed: boolean }>;
376
+ }
377
+
378
+ export interface ResetShortcutApi {
379
+ getInfo(): Promise<ResetSupportInfo>;
380
+ register(accelerator: string): Promise<unknown>;
381
+ unregister(accelerator: string): Promise<unknown>;
382
+ unregisterAll(): Promise<unknown>;
383
+ }
384
+
385
+ export interface ResetProtocolApi {
386
+ getInfo(): Promise<ResetSupportInfo>;
387
+ register(options?: {
388
+ scheme?: string;
389
+ }): Promise<unknown>;
390
+ unregister(options?: {
391
+ scheme?: string;
392
+ }): Promise<unknown>;
393
+ }
394
+
395
+ export interface ResetUpdaterApi {
396
+ getInfo(): Promise<ResetSupportInfo>;
397
+ check(options?: Record<string, unknown>): Promise<unknown>;
398
+ download(options?: Record<string, unknown>): Promise<unknown>;
399
+ install(options?: Record<string, unknown>): Promise<unknown>;
400
+ }
401
+
402
+ export interface ResetNetResponse {
403
+ url: string;
404
+ status: number;
405
+ ok: boolean;
406
+ headers: Record<string, string>;
407
+ body: string;
408
+ bodyEncoding: "utf8" | "base64" | string;
409
+ }
410
+
411
+ export interface ResetNetApi {
412
+ request(options: {
413
+ url: string;
414
+ method?: string;
415
+ headers?: Record<string, string>;
416
+ body?: string;
417
+ timeoutMs?: number;
418
+ }): Promise<ResetNetResponse>;
91
419
  }
92
420
 
93
421
  export interface ResetClient {
@@ -96,6 +424,42 @@ export interface ResetClient {
96
424
  commands: ResetCommandApi;
97
425
  app: ResetAppApi;
98
426
  runtime: ResetRuntimeApi;
427
+ events: ResetEventApi;
428
+ window: ResetWindowApi;
429
+ dialog: ResetDialogApi;
430
+ fs: ResetFsApi;
431
+ path: ResetPathApi;
432
+ shell: ResetShellApi;
433
+ clipboard: ResetClipboardApi;
434
+ notification: ResetNotificationApi;
435
+ screen: ResetScreenApi;
436
+ storage: ResetStorageApi;
437
+ webview: ResetWebViewApi;
438
+ crypto: ResetCryptoApi;
439
+ process: ResetProcessApi;
440
+ power: ResetPowerApi;
441
+ menu: ResetMenuApi;
442
+ tray: ResetTrayApi;
443
+ shortcut: ResetShortcutApi;
444
+ protocol: ResetProtocolApi;
445
+ updater: ResetUpdaterApi;
446
+ net: ResetNetApi;
447
+ }
448
+
449
+ export interface ResetEventApi {
450
+ listen<T = unknown>(
451
+ eventName: string,
452
+ handler: (payload: T) => void
453
+ ): () => void;
454
+ once<T = unknown>(
455
+ eventName: string,
456
+ handler: (payload: T) => void
457
+ ): () => void;
458
+ emitLocal<T = unknown>(eventName: string, payload: T): void;
459
+ emit<T = unknown>(eventName: string, payload?: T): Promise<{
460
+ delivered: boolean;
461
+ event: string;
462
+ }>;
99
463
  }
100
464
 
101
465
  declare global {
@@ -119,6 +483,8 @@ export class ResetProtocolError extends ResetRuntimeError {
119
483
  export class ResetInvocationError extends ResetRuntimeError {
120
484
  command: string;
121
485
  response: ResetInvokeError;
486
+ code?: string;
487
+ details?: unknown;
122
488
  constructor(
123
489
  command: string,
124
490
  message: string,
@@ -157,3 +523,23 @@ export const reset: ResetClient;
157
523
  export const commands: ResetCommandApi;
158
524
  export const app: ResetAppApi;
159
525
  export const runtime: ResetRuntimeApi;
526
+ export const events: ResetEventApi;
527
+ export const window: ResetWindowApi;
528
+ export const dialog: ResetDialogApi;
529
+ export const fs: ResetFsApi;
530
+ export const path: ResetPathApi;
531
+ export const shell: ResetShellApi;
532
+ export const clipboard: ResetClipboardApi;
533
+ export const notification: ResetNotificationApi;
534
+ export const screen: ResetScreenApi;
535
+ export const storage: ResetStorageApi;
536
+ export const webview: ResetWebViewApi;
537
+ export const crypto: ResetCryptoApi;
538
+ export const process: ResetProcessApi;
539
+ export const power: ResetPowerApi;
540
+ export const menu: ResetMenuApi;
541
+ export const tray: ResetTrayApi;
542
+ export const shortcut: ResetShortcutApi;
543
+ export const protocol: ResetProtocolApi;
544
+ export const updater: ResetUpdaterApi;
545
+ export const net: ResetNetApi;
package/src/index.js CHANGED
@@ -1,14 +1,34 @@
1
1
  export {
2
2
  app,
3
+ clipboard,
3
4
  commands,
4
5
  createResetClient,
5
6
  createResetTransport,
7
+ crypto,
8
+ dialog,
9
+ events,
10
+ fs,
6
11
  getResetRuntime,
7
12
  invoke,
8
13
  invokeRaw,
9
14
  isResetRuntimeAvailable,
15
+ menu,
16
+ net,
17
+ notification,
18
+ path,
19
+ power,
20
+ process,
21
+ protocol,
10
22
  reset,
11
- runtime
23
+ screen,
24
+ shell,
25
+ shortcut,
26
+ storage,
27
+ runtime,
28
+ tray,
29
+ updater,
30
+ webview,
31
+ window
12
32
  } from "./client.js"
13
33
 
14
34
  export {
package/src/transport.js CHANGED
@@ -86,7 +86,23 @@ function normalizeResponse(command, response) {
86
86
  }
87
87
 
88
88
  if (response.ok === false) {
89
- if (typeof response.error !== "string" || response.error.trim() === "") {
89
+ if (typeof response.error === "string" && response.error.trim() !== "") {
90
+ return Object.freeze({
91
+ ok: false,
92
+ error: response.error,
93
+ code: undefined,
94
+ details: undefined
95
+ })
96
+ }
97
+
98
+ if (!isObjectLike(response.error)) {
99
+ throw new ResetProtocolError(
100
+ `Reset runtime returned an invalid error response for '${command}'.`,
101
+ { command }
102
+ )
103
+ }
104
+
105
+ if (typeof response.error.message !== "string" || response.error.message.trim() === "") {
90
106
  throw new ResetProtocolError(
91
107
  `Reset runtime returned an invalid error response for '${command}'.`,
92
108
  { command }
@@ -95,7 +111,9 @@ function normalizeResponse(command, response) {
95
111
 
96
112
  return Object.freeze({
97
113
  ok: false,
98
- error: response.error
114
+ error: response.error.message,
115
+ code: typeof response.error.code === "string" ? response.error.code : undefined,
116
+ details: response.error.details
99
117
  })
100
118
  }
101
119