@domicile-desktop/system-bluetooth 0.0.0-alpha-44d0983a58ce → 0.0.0-alpha-56dd6c187f4e

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/README.md CHANGED
@@ -2,22 +2,20 @@
2
2
 
3
3
  BlueZ for a Domicile shell: each adapter and whether it is powered or
4
4
  scanning, the devices it knows, and the requests that change them. Built on
5
- [`@domicile-desktop/sdk/system`](../chrome-sdk/README.md).
5
+ the desktop's `dbus` namespace ([`@domicile-desktop/sdk`](../chrome-sdk/README.md)).
6
6
 
7
7
  ## Usage
8
8
 
9
9
  ```ts
10
- import { system } from "@domicile-desktop/sdk/system";
11
10
  import { setPowered, watchBluetooth } from "@domicile-desktop/system-bluetooth/bluetooth";
12
11
 
13
- const host = system(domicile);
14
- const stop = watchBluetooth(host, (bluetooth) => {
12
+ const stop = watchBluetooth(domicile, (bluetooth) => {
15
13
  bluetooth.match({
16
14
  Err: () => hide(),
17
15
  Ok: ({ adapters, devices }) => show(adapters, devices),
18
16
  });
19
17
  });
20
- await setPowered(host, "/org/bluez/hci0", false);
18
+ await setPowered(domicile, "/org/bluez/hci0", false);
21
19
  ```
22
20
 
23
21
  - Reads `GetManagedObjects` once, then again when an object comes or goes or
@@ -1,5 +1,6 @@
1
1
  import type { Result } from "@cprussin/option-result";
2
- import type { System, SystemError } from "@domicile-desktop/sdk/system";
2
+ import type { Dbus } from "@domicile-desktop/sdk/desktop/dbus";
3
+ import type { SystemError } from "@domicile-desktop/sdk/system";
3
4
  /** A controller, such as `/org/bluez/hci0`. */
4
5
  export type Adapter = {
5
6
  path: string;
@@ -28,7 +29,9 @@ export type Bluetooth = {
28
29
  devices: Device[];
29
30
  };
30
31
  /** The calls this library makes. */
31
- export type BluetoothSystem = Pick<System, "dbusCall" | "dbusMatch">;
32
+ export type BluetoothDesktop = {
33
+ readonly dbus: Pick<Dbus, "call" | "match">;
34
+ };
32
35
  /**
33
36
  * Calls `onBluetooth` with the adapters and connected devices now and after
34
37
  * each change, and returns a function that stops watching.
@@ -36,19 +39,33 @@ export type BluetoothSystem = Pick<System, "dbusCall" | "dbusMatch">;
36
39
  * An `Err` is a D-Bus failure, such as BlueZ not running. The watch keeps
37
40
  * listening after one, so a later change reads again.
38
41
  */
39
- export declare const watchBluetooth: (system: BluetoothSystem, onBluetooth: (bluetooth: Result<Bluetooth, SystemError>) => void) => (() => void);
42
+ export declare const watchBluetooth: (domicile: BluetoothDesktop, onBluetooth: (bluetooth: Result<Bluetooth, SystemError>) => void) => (() => void);
40
43
  /** Turn the adapter at `adapter` on or off. */
41
- export declare const setPowered: (system: Pick<System, "dbusCall">, adapter: string, powered: boolean) => Promise<Result<"set", SystemError>>;
44
+ export declare const setPowered: (domicile: {
45
+ readonly dbus: Pick<Dbus, "call">;
46
+ }, adapter: string, powered: boolean) => Promise<Result<"set", SystemError>>;
42
47
  /** Start scanning for devices. BlueZ stops when every scanner has asked. */
43
- export declare const startDiscovery: (system: Pick<System, "dbusCall">, adapter: string) => Promise<Result<"done", SystemError>>;
44
- export declare const stopDiscovery: (system: Pick<System, "dbusCall">, adapter: string) => Promise<Result<"done", SystemError>>;
48
+ export declare const startDiscovery: (domicile: {
49
+ readonly dbus: Pick<Dbus, "call">;
50
+ }, adapter: string) => Promise<Result<"done", SystemError>>;
51
+ export declare const stopDiscovery: (domicile: {
52
+ readonly dbus: Pick<Dbus, "call">;
53
+ }, adapter: string) => Promise<Result<"done", SystemError>>;
45
54
  /** Connect a paired device's profiles. */
46
- export declare const connect: (system: Pick<System, "dbusCall">, device: string) => Promise<Result<"done", SystemError>>;
47
- export declare const disconnect: (system: Pick<System, "dbusCall">, device: string) => Promise<Result<"done", SystemError>>;
55
+ export declare const connect: (domicile: {
56
+ readonly dbus: Pick<Dbus, "call">;
57
+ }, device: string) => Promise<Result<"done", SystemError>>;
58
+ export declare const disconnect: (domicile: {
59
+ readonly dbus: Pick<Dbus, "call">;
60
+ }, device: string) => Promise<Result<"done", SystemError>>;
48
61
  /**
49
62
  * Pair with a device, then trust it so it can reconnect on its own. With no
50
63
  * agent registered, BlueZ pairs only devices that need no code.
51
64
  */
52
- export declare const pair: (system: Pick<System, "dbusCall">, device: string) => Promise<Result<"done", SystemError>>;
65
+ export declare const pair: (domicile: {
66
+ readonly dbus: Pick<Dbus, "call">;
67
+ }, device: string) => Promise<Result<"done", SystemError>>;
53
68
  /** Remove a device and its pairing. */
54
- export declare const forget: (system: Pick<System, "dbusCall">, device: Pick<Device, "adapter" | "path">) => Promise<Result<"done", SystemError>>;
69
+ export declare const forget: (domicile: {
70
+ readonly dbus: Pick<Dbus, "call">;
71
+ }, device: Pick<Device, "adapter" | "path">) => Promise<Result<"done", SystemError>>;
package/dist/bluetooth.js CHANGED
@@ -20,14 +20,14 @@ const WATCHED = {
20
20
  * An `Err` is a D-Bus failure, such as BlueZ not running. The watch keeps
21
21
  * listening after one, so a later change reads again.
22
22
  */
23
- export const watchBluetooth = (system, onBluetooth) => {
23
+ export const watchBluetooth = (domicile, onBluetooth) => {
24
24
  const watch = { listening: undefined, stopped: false };
25
25
  const report = (bluetooth) => {
26
26
  if (!watch.stopped) {
27
27
  onBluetooth(bluetooth);
28
28
  }
29
29
  };
30
- follow(system, watch, report).catch((error) => {
30
+ follow(domicile, watch, report).catch((error) => {
31
31
  // biome-ignore lint/suspicious/noConsole: surfacing a background failure
32
32
  console.error("Failed to watch Bluetooth", error);
33
33
  });
@@ -37,7 +37,7 @@ export const watchBluetooth = (system, onBluetooth) => {
37
37
  };
38
38
  };
39
39
  /** Turn the adapter at `adapter` on or off. */
40
- export const setPowered = async (system, adapter, powered) => (await system.dbusCall({
40
+ export const setPowered = async (domicile, adapter, powered) => (await domicile.dbus.call({
41
41
  body: [ADAPTER, "Powered", { signature: "b", value: powered }],
42
42
  bus: Bus.System,
43
43
  destination: SERVICE,
@@ -47,16 +47,16 @@ export const setPowered = async (system, adapter, powered) => (await system.dbus
47
47
  signature: "ssv",
48
48
  })).map(() => "set");
49
49
  /** Start scanning for devices. BlueZ stops when every scanner has asked. */
50
- export const startDiscovery = (system, adapter) => call(system, adapter, ADAPTER, "StartDiscovery");
51
- export const stopDiscovery = (system, adapter) => call(system, adapter, ADAPTER, "StopDiscovery");
50
+ export const startDiscovery = (domicile, adapter) => call(domicile, adapter, ADAPTER, "StartDiscovery");
51
+ export const stopDiscovery = (domicile, adapter) => call(domicile, adapter, ADAPTER, "StopDiscovery");
52
52
  /** Connect a paired device's profiles. */
53
- export const connect = (system, device) => call(system, device, DEVICE, "Connect");
54
- export const disconnect = (system, device) => call(system, device, DEVICE, "Disconnect");
53
+ export const connect = (domicile, device) => call(domicile, device, DEVICE, "Connect");
54
+ export const disconnect = (domicile, device) => call(domicile, device, DEVICE, "Disconnect");
55
55
  /**
56
56
  * Pair with a device, then trust it so it can reconnect on its own. With no
57
57
  * agent registered, BlueZ pairs only devices that need no code.
58
58
  */
59
- export const pair = async (system, device) => (await call(system, device, DEVICE, "Pair")).andThenAsync(async () => (await system.dbusCall({
59
+ export const pair = async (domicile, device) => (await call(domicile, device, DEVICE, "Pair")).andThenAsync(async () => (await domicile.dbus.call({
60
60
  body: [DEVICE, "Trusted", { signature: "b", value: true }],
61
61
  bus: Bus.System,
62
62
  destination: SERVICE,
@@ -66,7 +66,7 @@ export const pair = async (system, device) => (await call(system, device, DEVICE
66
66
  signature: "ssv",
67
67
  })).map(() => "done"));
68
68
  /** Remove a device and its pairing. */
69
- export const forget = async (system, device) => (await system.dbusCall({
69
+ export const forget = async (domicile, device) => (await domicile.dbus.call({
70
70
  body: [device.path],
71
71
  bus: Bus.System,
72
72
  destination: SERVICE,
@@ -76,7 +76,7 @@ export const forget = async (system, device) => (await system.dbusCall({
76
76
  signature: "o",
77
77
  })).map(() => "done");
78
78
  /** A BlueZ method that takes no arguments. */
79
- const call = async (system, path, iface, member) => (await system.dbusCall({
79
+ const call = async (domicile, path, iface, member) => (await domicile.dbus.call({
80
80
  bus: Bus.System,
81
81
  destination: SERVICE,
82
82
  interface: iface,
@@ -84,8 +84,11 @@ const call = async (system, path, iface, member) => (await system.dbusCall({
84
84
  path,
85
85
  })).map(() => "done");
86
86
  /** Listen, read, then read again on each change until the match ends. */
87
- const follow = async (system, watch, report) => {
88
- const matched = await system.dbusMatch({ bus: Bus.System, sender: SERVICE });
87
+ const follow = async (domicile, watch, report) => {
88
+ const matched = await domicile.dbus.match({
89
+ bus: Bus.System,
90
+ sender: SERVICE,
91
+ });
89
92
  await matched.match({
90
93
  Err: (error) => {
91
94
  report(Err(error));
@@ -96,7 +99,7 @@ const follow = async (system, watch, report) => {
96
99
  if (watch.stopped) {
97
100
  listening.stop();
98
101
  }
99
- await changes(system, listening, report);
102
+ await changes(domicile, listening, report);
100
103
  const ended = await listening.ended;
101
104
  ended.match({
102
105
  Err: (error) => {
@@ -113,12 +116,12 @@ const follow = async (system, watch, report) => {
113
116
  * Read now, and again on each signal that changes what was read and after a
114
117
  * compositor restart.
115
118
  */
116
- const changes = async (system, listening, report) => {
119
+ const changes = async (domicile, listening, report) => {
117
120
  const reader = listening.items.getReader();
118
- report(await read(system));
121
+ report(await read(domicile));
119
122
  for (let next = await reader.read(); !next.done; next = await reader.read()) {
120
123
  if (next.value.kind === ListenedKind.Missed || matters(next.value.item)) {
121
- report(await read(system));
124
+ report(await read(domicile));
122
125
  }
123
126
  }
124
127
  };
@@ -142,7 +145,7 @@ const matters = (signal) => {
142
145
  }
143
146
  }
144
147
  };
145
- const read = async (system) => (await system.dbusCall({
148
+ const read = async (domicile) => (await domicile.dbus.call({
146
149
  bus: Bus.System,
147
150
  destination: SERVICE,
148
151
  interface: "org.freedesktop.DBus.ObjectManager",
@@ -1,10 +1,13 @@
1
1
  import type { Result } from "@cprussin/option-result";
2
- import type { System, SystemError } from "@domicile-desktop/sdk/system";
2
+ import type { Files } from "@domicile-desktop/sdk/desktop/files";
3
+ import type { SystemError } from "@domicile-desktop/sdk/system";
3
4
  /** The calls the check makes. Each works while the desktop is locked. */
4
- export type SysfsSystem = Pick<System, "readDir" | "readTextFile">;
5
+ export type SysfsDesktop = {
6
+ readonly files: Pick<Files, "readDir" | "readText">;
7
+ };
5
8
  /**
6
9
  * Whether there is a Bluetooth controller, or an rfkill switch for one. A
7
10
  * radio rfkill blocks can take its controller away with it, and its switch
8
11
  * stays.
9
12
  */
10
- export declare const hasBluetoothHardware: (system: SysfsSystem) => Promise<Result<boolean, SystemError>>;
13
+ export declare const hasBluetoothHardware: (domicile: SysfsDesktop) => Promise<Result<boolean, SystemError>>;
package/dist/hardware.js CHANGED
@@ -7,20 +7,20 @@ import { SystemErrorKind } from "@domicile-desktop/sdk/system";
7
7
  * radio rfkill blocks can take its controller away with it, and its switch
8
8
  * stays.
9
9
  */
10
- export const hasBluetoothHardware = async (system) => (await entriesOf(system, "/sys/class/bluetooth")).match({
10
+ export const hasBluetoothHardware = async (domicile) => (await entriesOf(domicile, "/sys/class/bluetooth")).match({
11
11
  Err: (error) => Promise.resolve(Err(error)),
12
12
  Ok: async (controllers) => controllers.length > 0
13
13
  ? Ok(true)
14
- : (await entriesOf(system, "/sys/class/rfkill")).match({
14
+ : (await entriesOf(domicile, "/sys/class/rfkill")).match({
15
15
  Err: (error) => Promise.resolve(Err(error)),
16
- Ok: (switches) => anyOf(switches, async (name) => (await lineOf(system, `/sys/class/rfkill/${name}/type`)).map((type) => type.match({
16
+ Ok: (switches) => anyOf(switches, async (name) => (await lineOf(domicile, `/sys/class/rfkill/${name}/type`)).map((type) => type.match({
17
17
  None: () => false,
18
18
  Some: (is) => is === "bluetooth",
19
19
  }))),
20
20
  }),
21
21
  });
22
22
  /** The names in `dir`; none when it does not exist, as when no driver made it. */
23
- const entriesOf = async (system, dir) => (await system.readDir(dir)).match({
23
+ const entriesOf = async (domicile, dir) => (await domicile.files.readDir(dir)).match({
24
24
  Err: (error) => error.kind === SystemErrorKind.NotFound ? Ok([]) : Err(error),
25
25
  Ok: (entries) => Ok(entries.map(({ name }) => name)),
26
26
  });
@@ -38,7 +38,7 @@ const anyOf = async (names, test) => {
38
38
  }
39
39
  };
40
40
  /** A one-line file under `/sys`, without its newline; `None` when missing. */
41
- const lineOf = async (system, path) => (await system.readTextFile(path)).match({
41
+ const lineOf = async (domicile, path) => (await domicile.files.readText(path)).match({
42
42
  Err: (error) => error.kind === SystemErrorKind.NotFound ? Ok(None()) : Err(error),
43
43
  Ok: (text) => Ok(Some(text.trim())),
44
44
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "dependencies": {
3
3
  "@cprussin/option-result": "^2.0.1",
4
- "@domicile-desktop/sdk": "0.0.0-alpha-44d0983a58ce",
4
+ "@domicile-desktop/sdk": "0.0.0-alpha-56dd6c187f4e",
5
5
  "zod": "^4.5.4"
6
6
  },
7
7
  "description": "BlueZ for a Domicile shell: whether each adapter is powered and which devices are connected, kept current, and turning adapters on and off.",
@@ -45,5 +45,5 @@
45
45
  "test:unit": "bun test"
46
46
  },
47
47
  "type": "module",
48
- "version": "0.0.0-alpha-44d0983a58ce"
48
+ "version": "0.0.0-alpha-56dd6c187f4e"
49
49
  }