unifi-cli 0.2.1__tar.gz → 0.2.3__tar.gz

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.
Files changed (36) hide show
  1. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/.github/workflows/ci.yml +4 -4
  2. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/.github/workflows/release.yml +23 -16
  3. unifi_cli-0.2.3/.gitignore +2 -0
  4. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/CHANGELOG.md +21 -1
  5. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/Cargo.lock +240 -4
  6. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/Cargo.toml +2 -1
  7. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/Makefile +4 -1
  8. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/PKG-INFO +1 -1
  9. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/src/api/client.rs +23 -4
  10. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/src/commands/clients.rs +50 -4
  11. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/src/commands/devices.rs +49 -5
  12. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/src/commands/events.rs +42 -20
  13. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/src/commands/networks.rs +1 -1
  14. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/src/commands/protect.rs +6 -6
  15. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/src/commands/system.rs +2 -2
  16. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/src/main.rs +146 -22
  17. unifi_cli-0.2.3/src/output.rs +218 -0
  18. unifi_cli-0.2.3/src/schema.rs +609 -0
  19. unifi_cli-0.2.3/tests/fixtures/clispec-v0.2.json +135 -0
  20. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/tests/mock_server.rs +162 -30
  21. unifi_cli-0.2.3/tests/spec_compliance.rs +126 -0
  22. unifi_cli-0.2.1/.gitignore +0 -1
  23. unifi_cli-0.2.1/src/output.rs +0 -114
  24. unifi_cli-0.2.1/src/schema.rs +0 -346
  25. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/LICENSE +0 -0
  26. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/README.md +0 -0
  27. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/prek.toml +0 -0
  28. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/pyproject.toml +0 -0
  29. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/src/api/mod.rs +0 -0
  30. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/src/api/tests.rs +0 -0
  31. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/src/api/types.rs +0 -0
  32. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/src/commands/mod.rs +0 -0
  33. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/src/lib.rs +0 -0
  34. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/src/tui.rs +0 -0
  35. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/unifi_cli/__init__.py +0 -0
  36. {unifi_cli-0.2.1 → unifi_cli-0.2.3}/unifi_cli/__main__.py +0 -0
@@ -15,7 +15,7 @@ jobs:
15
15
  name: Lint
16
16
  runs-on: ubuntu-latest
17
17
  steps:
18
- - uses: actions/checkout@v4
18
+ - uses: actions/checkout@v6
19
19
 
20
20
  - uses: dtolnay/rust-toolchain@stable
21
21
  with:
@@ -28,7 +28,7 @@ jobs:
28
28
  name: Test
29
29
  runs-on: ubuntu-latest
30
30
  steps:
31
- - uses: actions/checkout@v4
31
+ - uses: actions/checkout@v6
32
32
 
33
33
  - uses: dtolnay/rust-toolchain@stable
34
34
 
@@ -39,13 +39,13 @@ jobs:
39
39
  name: Coverage
40
40
  runs-on: ubuntu-latest
41
41
  steps:
42
- - uses: actions/checkout@v4
42
+ - uses: actions/checkout@v6
43
43
  - uses: dtolnay/rust-toolchain@stable
44
44
  - uses: taiki-e/install-action@cargo-tarpaulin
45
45
  - name: Generate coverage
46
46
  run: cargo tarpaulin --out xml
47
47
  - name: Upload to Codecov
48
- uses: codecov/codecov-action@v5
48
+ uses: codecov/codecov-action@v6
49
49
  with:
50
50
  files: cobertura.xml
51
51
  token: ${{ secrets.CODECOV_TOKEN }}
@@ -33,7 +33,7 @@ jobs:
33
33
  name: Run tests
34
34
  runs-on: ubuntu-latest
35
35
  steps:
36
- - uses: actions/checkout@v4
36
+ - uses: actions/checkout@v6
37
37
 
38
38
  - uses: dtolnay/rust-toolchain@stable
39
39
 
@@ -65,7 +65,7 @@ jobs:
65
65
  target: aarch64-apple-darwin
66
66
  runs-on: ${{ matrix.os }}
67
67
  steps:
68
- - uses: actions/checkout@v4
68
+ - uses: actions/checkout@v6
69
69
  with:
70
70
  # Preserve target/ between runs on self-hosted runners for cargo
71
71
  # incremental rebuild. GitHub-hosted runners start clean each job
@@ -102,7 +102,7 @@ jobs:
102
102
 
103
103
  - name: Install uv
104
104
  if: matrix.target != 'aarch64-unknown-linux-gnu'
105
- uses: astral-sh/setup-uv@v6
105
+ uses: astral-sh/setup-uv@v8.2.0
106
106
 
107
107
  - name: Install maturin and zig
108
108
  # maturin-action provides its own maturin inside the manylinux
@@ -201,13 +201,13 @@ jobs:
201
201
  rm -rf release-package
202
202
 
203
203
  - name: Upload wheel
204
- uses: actions/upload-artifact@v4
204
+ uses: actions/upload-artifact@v7
205
205
  with:
206
206
  path: dist/*.whl
207
207
  name: wheel-${{ matrix.target }}
208
208
 
209
209
  - name: Upload release archives
210
- uses: actions/upload-artifact@v4
210
+ uses: actions/upload-artifact@v7
211
211
  with:
212
212
  path: |
213
213
  unifi-cli-*-${{ matrix.target }}.tar.gz*
@@ -219,9 +219,9 @@ jobs:
219
219
  runs-on: ubuntu-latest
220
220
  needs: test
221
221
  steps:
222
- - uses: actions/checkout@v4
222
+ - uses: actions/checkout@v6
223
223
 
224
- - uses: astral-sh/setup-uv@v6
224
+ - uses: astral-sh/setup-uv@v8.2.0
225
225
 
226
226
  - name: Install maturin
227
227
  shell: bash
@@ -235,7 +235,7 @@ jobs:
235
235
  - name: Build sdist
236
236
  run: maturin sdist
237
237
 
238
- - uses: actions/upload-artifact@v4
238
+ - uses: actions/upload-artifact@v7
239
239
  with:
240
240
  path: target/wheels/*.tar.gz
241
241
  name: sdist
@@ -244,12 +244,12 @@ jobs:
244
244
  runs-on: ubuntu-latest
245
245
  needs: [build, sdist]
246
246
  steps:
247
- - uses: actions/checkout@v4
247
+ - uses: actions/checkout@v6
248
248
 
249
249
  - uses: dtolnay/rust-toolchain@stable
250
250
 
251
251
  - name: Install uv
252
- uses: astral-sh/setup-uv@v5
252
+ uses: astral-sh/setup-uv@v8.2.0
253
253
  with:
254
254
  enable-cache: false
255
255
 
@@ -270,7 +270,7 @@ jobs:
270
270
  run: echo "Skipping crates.io publishing as requested"
271
271
 
272
272
  - name: Download all artifacts
273
- uses: actions/download-artifact@v4
273
+ uses: actions/download-artifact@v8
274
274
  with:
275
275
  path: artifacts
276
276
 
@@ -296,7 +296,7 @@ jobs:
296
296
 
297
297
  - name: Create Release
298
298
  if: ${{ inputs.dry_run != true }}
299
- uses: softprops/action-gh-release@v2
299
+ uses: softprops/action-gh-release@v3
300
300
  with:
301
301
  generate_release_notes: true
302
302
  files: |
@@ -317,7 +317,7 @@ jobs:
317
317
  if: ${{ !inputs.dry_run }}
318
318
  runs-on: ubuntu-latest
319
319
  steps:
320
- - uses: actions/download-artifact@v4
320
+ - uses: actions/download-artifact@v8
321
321
  with:
322
322
  path: /tmp/artifacts
323
323
 
@@ -332,7 +332,7 @@ jobs:
332
332
 
333
333
  - name: Update Homebrew formula
334
334
  env:
335
- GH_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
335
+ HOMEBREW_TAP_DEPLOY_KEY: ${{ secrets.HOMEBREW_TAP_DEPLOY_KEY }}
336
336
  run: |
337
337
  VERSION="${{ github.ref_name }}"
338
338
  VERSION_NUM="${VERSION#v}"
@@ -381,8 +381,15 @@ jobs:
381
381
  sed -i "s/SHA_AARCH64_UNKNOWN_LINUX_GNU/${{ steps.hashes.outputs.aarch64_unknown_linux_gnu }}/g" /tmp/unifi-cli.rb
382
382
  sed -i "s/SHA_X86_64_UNKNOWN_LINUX_GNU/${{ steps.hashes.outputs.x86_64_unknown_linux_gnu }}/g" /tmp/unifi-cli.rb
383
383
 
384
- # Clone tap repo, update formula, push
385
- git clone https://x-access-token:${GH_TOKEN}@github.com/rvben/homebrew-tap.git /tmp/tap
384
+ # Authenticate to the tap with a write deploy key scoped to
385
+ # rvben/homebrew-tap. The key does not expire, so cross-repo pushes
386
+ # keep working without periodic token rotation.
387
+ mkdir -p ~/.ssh
388
+ echo "$HOMEBREW_TAP_DEPLOY_KEY" > ~/.ssh/id_ed25519
389
+ chmod 600 ~/.ssh/id_ed25519
390
+ ssh-keyscan -t ed25519 github.com >> ~/.ssh/known_hosts 2>/dev/null
391
+
392
+ git clone git@github.com:rvben/homebrew-tap.git /tmp/tap
386
393
  mkdir -p /tmp/tap/Formula
387
394
  cp /tmp/unifi-cli.rb /tmp/tap/Formula/unifi-cli.rb
388
395
  cd /tmp/tap
@@ -0,0 +1,2 @@
1
+ /target
2
+ .claude/investigations/
@@ -3,11 +3,31 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
5
 
6
+
7
+
8
+ ## [0.2.3](https://github.com/rvben/unifi-cli/compare/v0.2.2...v0.2.3) - 2026-07-07
9
+
10
+ ### Fixed
11
+
12
+ - **events**: fall back to rest/alarm when stat/event is 404 on UniFi OS 9+ ([ac8a69c](https://github.com/rvben/unifi-cli/commit/ac8a69c743c5eab05def7bcd67e08e5b060275ea))
13
+
14
+ ## [0.2.2](https://github.com/rvben/unifi-cli/compare/v0.2.1...v0.2.2) - 2026-06-11
15
+
16
+ ### Added
17
+
18
+ - **schema**: upgrade to clispec v0.2 schema shape and add compliance features ([25ba5fd](https://github.com/rvben/unifi-cli/commit/25ba5fd365e4124117dcd648d08f4888c118d6a4))
19
+
20
+ ### Fixed
21
+
22
+ - **schema**: promote --yes to global flag and add conflict error kind ([2da61c5](https://github.com/rvben/unifi-cli/commit/2da61c57b3d4e4863293e795950f6a28e5999dd9))
23
+
6
24
  ## [0.2.1](https://github.com/rvben/unifi-cli/compare/v0.2.0...v0.2.1) - 2026-06-03
7
25
 
26
+ Thanks to [@captbaritone](https://github.com/captbaritone) for reporting and fixing the `poe_power` decode error ([#3](https://github.com/rvben/unifi-cli/pull/3)).
27
+
8
28
  ### Fixed
9
29
 
10
- - **devices**: accept poe_power as JSON string on non-PoE switches (#3) ([2cd0b5f](https://github.com/rvben/unifi-cli/commit/2cd0b5fc6547bbb2b77eb8259304114d2a779778))
30
+ - **devices**: accept poe_power as JSON string or number from the legacy /stat/device endpoint (#3) ([2cd0b5f](https://github.com/rvben/unifi-cli/commit/2cd0b5fc6547bbb2b77eb8259304114d2a779778))
11
31
 
12
32
  ## [0.2.0](https://github.com/rvben/unifi-cli/compare/v0.1.7...v0.2.0) - 2026-05-23
13
33
 
@@ -2,6 +2,20 @@
2
2
  # It is not intended for manual editing.
3
3
  version = 4
4
4
 
5
+ [[package]]
6
+ name = "ahash"
7
+ version = "0.8.12"
8
+ source = "registry+https://github.com/rust-lang/crates.io-index"
9
+ checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
10
+ dependencies = [
11
+ "cfg-if",
12
+ "getrandom 0.3.4",
13
+ "once_cell",
14
+ "serde",
15
+ "version_check",
16
+ "zerocopy",
17
+ ]
18
+
5
19
  [[package]]
6
20
  name = "aho-corasick"
7
21
  version = "1.1.4"
@@ -116,7 +130,16 @@ version = "0.5.3"
116
130
  source = "registry+https://github.com/rust-lang/crates.io-index"
117
131
  checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
118
132
  dependencies = [
119
- "bit-vec",
133
+ "bit-vec 0.6.3",
134
+ ]
135
+
136
+ [[package]]
137
+ name = "bit-set"
138
+ version = "0.8.0"
139
+ source = "registry+https://github.com/rust-lang/crates.io-index"
140
+ checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3"
141
+ dependencies = [
142
+ "bit-vec 0.8.0",
120
143
  ]
121
144
 
122
145
  [[package]]
@@ -125,6 +148,12 @@ version = "0.6.3"
125
148
  source = "registry+https://github.com/rust-lang/crates.io-index"
126
149
  checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
127
150
 
151
+ [[package]]
152
+ name = "bit-vec"
153
+ version = "0.8.0"
154
+ source = "registry+https://github.com/rust-lang/crates.io-index"
155
+ checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
156
+
128
157
  [[package]]
129
158
  name = "bitflags"
130
159
  version = "1.3.2"
@@ -146,12 +175,24 @@ dependencies = [
146
175
  "generic-array",
147
176
  ]
148
177
 
178
+ [[package]]
179
+ name = "borrow-or-share"
180
+ version = "0.2.4"
181
+ source = "registry+https://github.com/rust-lang/crates.io-index"
182
+ checksum = "dc0b364ead1874514c8c2855ab558056ebfeb775653e7ae45ff72f28f8f3166c"
183
+
149
184
  [[package]]
150
185
  name = "bumpalo"
151
186
  version = "3.20.3"
152
187
  source = "registry+https://github.com/rust-lang/crates.io-index"
153
188
  checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
154
189
 
190
+ [[package]]
191
+ name = "bytecount"
192
+ version = "0.6.9"
193
+ source = "registry+https://github.com/rust-lang/crates.io-index"
194
+ checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e"
195
+
155
196
  [[package]]
156
197
  name = "bytemuck"
157
198
  version = "1.25.0"
@@ -504,6 +545,15 @@ version = "1.16.0"
504
545
  source = "registry+https://github.com/rust-lang/crates.io-index"
505
546
  checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e"
506
547
 
548
+ [[package]]
549
+ name = "email_address"
550
+ version = "0.2.9"
551
+ source = "registry+https://github.com/rust-lang/crates.io-index"
552
+ checksum = "e079f19b08ca6239f47f8ba8509c11cf3ea30095831f7fed61441475edd8c449"
553
+ dependencies = [
554
+ "serde",
555
+ ]
556
+
507
557
  [[package]]
508
558
  name = "equivalent"
509
559
  version = "1.0.2"
@@ -535,10 +585,21 @@ version = "0.11.0"
535
585
  source = "registry+https://github.com/rust-lang/crates.io-index"
536
586
  checksum = "b95f7c0680e4142284cf8b22c14a476e87d61b004a3a0861872b32ef7ead40a2"
537
587
  dependencies = [
538
- "bit-set",
588
+ "bit-set 0.5.3",
539
589
  "regex",
540
590
  ]
541
591
 
592
+ [[package]]
593
+ name = "fancy-regex"
594
+ version = "0.14.0"
595
+ source = "registry+https://github.com/rust-lang/crates.io-index"
596
+ checksum = "6e24cb5a94bcae1e5408b0effca5cd7172ea3c5755049c5f3af4cd283a165298"
597
+ dependencies = [
598
+ "bit-set 0.8.0",
599
+ "regex-automata",
600
+ "regex-syntax",
601
+ ]
602
+
542
603
  [[package]]
543
604
  name = "fastrand"
544
605
  version = "2.4.1"
@@ -574,6 +635,17 @@ version = "0.4.2"
574
635
  source = "registry+https://github.com/rust-lang/crates.io-index"
575
636
  checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
576
637
 
638
+ [[package]]
639
+ name = "fluent-uri"
640
+ version = "0.3.2"
641
+ source = "registry+https://github.com/rust-lang/crates.io-index"
642
+ checksum = "1918b65d96df47d3591bed19c5cca17e3fa5d0707318e4b5ef2eae01764df7e5"
643
+ dependencies = [
644
+ "borrow-or-share",
645
+ "ref-cast",
646
+ "serde",
647
+ ]
648
+
577
649
  [[package]]
578
650
  name = "fnv"
579
651
  version = "1.0.7"
@@ -601,6 +673,16 @@ dependencies = [
601
673
  "percent-encoding",
602
674
  ]
603
675
 
676
+ [[package]]
677
+ name = "fraction"
678
+ version = "0.15.4"
679
+ source = "registry+https://github.com/rust-lang/crates.io-index"
680
+ checksum = "e076045bb43dac435333ed5f04caf35c7463631d0dae2deb2638d94dd0a5b872"
681
+ dependencies = [
682
+ "lazy_static",
683
+ "num",
684
+ ]
685
+
604
686
  [[package]]
605
687
  name = "futures"
606
688
  version = "0.3.32"
@@ -1096,6 +1178,31 @@ dependencies = [
1096
1178
  "wasm-bindgen",
1097
1179
  ]
1098
1180
 
1181
+ [[package]]
1182
+ name = "jsonschema"
1183
+ version = "0.28.3"
1184
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1185
+ checksum = "4b8f66fe41fa46a5c83ed1c717b7e0b4635988f427083108c8cf0a882cc13441"
1186
+ dependencies = [
1187
+ "ahash",
1188
+ "base64",
1189
+ "bytecount",
1190
+ "email_address",
1191
+ "fancy-regex 0.14.0",
1192
+ "fraction",
1193
+ "idna",
1194
+ "itoa",
1195
+ "num-cmp",
1196
+ "once_cell",
1197
+ "percent-encoding",
1198
+ "referencing",
1199
+ "regex-syntax",
1200
+ "reqwest",
1201
+ "serde",
1202
+ "serde_json",
1203
+ "uuid-simd",
1204
+ ]
1205
+
1099
1206
  [[package]]
1100
1207
  name = "kasuari"
1101
1208
  version = "0.4.12"
@@ -1269,6 +1376,45 @@ dependencies = [
1269
1376
  "minimal-lexical",
1270
1377
  ]
1271
1378
 
1379
+ [[package]]
1380
+ name = "num"
1381
+ version = "0.4.3"
1382
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1383
+ checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23"
1384
+ dependencies = [
1385
+ "num-bigint",
1386
+ "num-complex",
1387
+ "num-integer",
1388
+ "num-iter",
1389
+ "num-rational",
1390
+ "num-traits",
1391
+ ]
1392
+
1393
+ [[package]]
1394
+ name = "num-bigint"
1395
+ version = "0.4.6"
1396
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1397
+ checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
1398
+ dependencies = [
1399
+ "num-integer",
1400
+ "num-traits",
1401
+ ]
1402
+
1403
+ [[package]]
1404
+ name = "num-cmp"
1405
+ version = "0.1.0"
1406
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1407
+ checksum = "63335b2e2c34fae2fb0aa2cecfd9f0832a1e24b3b32ecec612c3426d46dc8aaa"
1408
+
1409
+ [[package]]
1410
+ name = "num-complex"
1411
+ version = "0.4.6"
1412
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1413
+ checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
1414
+ dependencies = [
1415
+ "num-traits",
1416
+ ]
1417
+
1272
1418
  [[package]]
1273
1419
  name = "num-conv"
1274
1420
  version = "0.2.2"
@@ -1286,6 +1432,37 @@ dependencies = [
1286
1432
  "syn 2.0.117",
1287
1433
  ]
1288
1434
 
1435
+ [[package]]
1436
+ name = "num-integer"
1437
+ version = "0.1.46"
1438
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1439
+ checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
1440
+ dependencies = [
1441
+ "num-traits",
1442
+ ]
1443
+
1444
+ [[package]]
1445
+ name = "num-iter"
1446
+ version = "0.1.45"
1447
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1448
+ checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
1449
+ dependencies = [
1450
+ "autocfg",
1451
+ "num-integer",
1452
+ "num-traits",
1453
+ ]
1454
+
1455
+ [[package]]
1456
+ name = "num-rational"
1457
+ version = "0.4.2"
1458
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1459
+ checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
1460
+ dependencies = [
1461
+ "num-bigint",
1462
+ "num-integer",
1463
+ "num-traits",
1464
+ ]
1465
+
1289
1466
  [[package]]
1290
1467
  name = "num-traits"
1291
1468
  version = "0.2.19"
@@ -1341,6 +1518,12 @@ dependencies = [
1341
1518
  "num-traits",
1342
1519
  ]
1343
1520
 
1521
+ [[package]]
1522
+ name = "outref"
1523
+ version = "0.5.2"
1524
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1525
+ checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e"
1526
+
1344
1527
  [[package]]
1345
1528
  name = "owo-colors"
1346
1529
  version = "4.3.0"
@@ -1767,6 +1950,39 @@ dependencies = [
1767
1950
  "thiserror 2.0.18",
1768
1951
  ]
1769
1952
 
1953
+ [[package]]
1954
+ name = "ref-cast"
1955
+ version = "1.0.25"
1956
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1957
+ checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d"
1958
+ dependencies = [
1959
+ "ref-cast-impl",
1960
+ ]
1961
+
1962
+ [[package]]
1963
+ name = "ref-cast-impl"
1964
+ version = "1.0.25"
1965
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1966
+ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da"
1967
+ dependencies = [
1968
+ "proc-macro2",
1969
+ "quote",
1970
+ "syn 2.0.117",
1971
+ ]
1972
+
1973
+ [[package]]
1974
+ name = "referencing"
1975
+ version = "0.28.3"
1976
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1977
+ checksum = "d0dcb5ab28989ad7c91eb1b9531a37a1a137cc69a0499aee4117cae4a107c464"
1978
+ dependencies = [
1979
+ "ahash",
1980
+ "fluent-uri",
1981
+ "once_cell",
1982
+ "percent-encoding",
1983
+ "serde_json",
1984
+ ]
1985
+
1770
1986
  [[package]]
1771
1987
  name = "regex"
1772
1988
  version = "1.12.3"
@@ -1806,7 +2022,9 @@ dependencies = [
1806
2022
  "bytes",
1807
2023
  "cookie",
1808
2024
  "cookie_store",
2025
+ "futures-channel",
1809
2026
  "futures-core",
2027
+ "futures-util",
1810
2028
  "http",
1811
2029
  "http-body",
1812
2030
  "http-body-util",
@@ -2228,7 +2446,7 @@ dependencies = [
2228
2446
  "anyhow",
2229
2447
  "base64",
2230
2448
  "bitflags 2.11.1",
2231
- "fancy-regex",
2449
+ "fancy-regex 0.11.0",
2232
2450
  "filedescriptor",
2233
2451
  "finl_unicode",
2234
2452
  "fixedbitset",
@@ -2568,12 +2786,13 @@ checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
2568
2786
 
2569
2787
  [[package]]
2570
2788
  name = "unifi-cli"
2571
- version = "0.2.1"
2789
+ version = "0.2.3"
2572
2790
  dependencies = [
2573
2791
  "clap",
2574
2792
  "clap_complete",
2575
2793
  "crossterm",
2576
2794
  "dirs",
2795
+ "jsonschema",
2577
2796
  "owo-colors",
2578
2797
  "ratatui",
2579
2798
  "reqwest",
@@ -2628,12 +2847,29 @@ dependencies = [
2628
2847
  "wasm-bindgen",
2629
2848
  ]
2630
2849
 
2850
+ [[package]]
2851
+ name = "uuid-simd"
2852
+ version = "0.8.0"
2853
+ source = "registry+https://github.com/rust-lang/crates.io-index"
2854
+ checksum = "23b082222b4f6619906941c17eb2297fff4c2fb96cb60164170522942a200bd8"
2855
+ dependencies = [
2856
+ "outref",
2857
+ "uuid",
2858
+ "vsimd",
2859
+ ]
2860
+
2631
2861
  [[package]]
2632
2862
  name = "version_check"
2633
2863
  version = "0.9.5"
2634
2864
  source = "registry+https://github.com/rust-lang/crates.io-index"
2635
2865
  checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
2636
2866
 
2867
+ [[package]]
2868
+ name = "vsimd"
2869
+ version = "0.8.0"
2870
+ source = "registry+https://github.com/rust-lang/crates.io-index"
2871
+ checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64"
2872
+
2637
2873
  [[package]]
2638
2874
  name = "vtparse"
2639
2875
  version = "0.6.2"
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "unifi-cli"
3
- version = "0.2.1"
3
+ version = "0.2.3"
4
4
  edition = "2024"
5
5
  rust-version = "1.90"
6
6
  description = "CLI for UniFi Network controller"
@@ -36,3 +36,4 @@ rpassword = "7.4.0"
36
36
  [dev-dependencies]
37
37
  tempfile = "3"
38
38
  wiremock = "0.6"
39
+ jsonschema = "0.28"
@@ -1,4 +1,4 @@
1
- .PHONY: build release test lint fmt check clean install release-patch release-minor release-major
1
+ .PHONY: build release test lint fmt check update-deps clean install release-patch release-minor release-major
2
2
 
3
3
  build:
4
4
  cargo build
@@ -18,6 +18,9 @@ fmt:
18
18
 
19
19
  check: lint test
20
20
 
21
+ update-deps:
22
+ upd --apply --max-bump minor --lang rust,actions
23
+
21
24
  clean:
22
25
  cargo clean
23
26
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: unifi-cli
3
- Version: 0.2.1
3
+ Version: 0.2.3
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: Environment :: Console
6
6
  Classifier: Intended Audience :: System Administrators
@@ -367,11 +367,30 @@ impl UnifiClient {
367
367
  }
368
368
 
369
369
  // Events
370
+ //
371
+ // Legacy `stat/event` was removed in UniFi Network 9+ (UniFi OS) and now
372
+ // returns api.err.NotFound (404). On those controllers the surviving REST
373
+ // surface for notable events is `rest/alarm`, whose records share this
374
+ // `Event` shape, so fall back to it. (The full live event stream on newer
375
+ // controllers is only exposed over the events WebSocket, which this REST
376
+ // client does not consume.)
370
377
  pub async fn list_events(&self, limit: usize) -> Result<Vec<Event>, ApiError> {
371
- let events: Vec<Event> = self
372
- .get_legacy(&format!("/stat/event?_limit={limit}"))
373
- .await?;
374
- Ok(events)
378
+ match self
379
+ .get_legacy::<Event>(&format!("/stat/event?_limit={limit}"))
380
+ .await
381
+ {
382
+ Ok(events) => Ok(events),
383
+ Err(ApiError::NotFound(_)) => {
384
+ let mut alarms: Vec<Event> = self.get_legacy("/rest/alarm").await?;
385
+ // `rest/alarm` is neither time-ordered nor limited server-side;
386
+ // present the most recent `limit` records to match the
387
+ // semantics `stat/event?_limit=` provided on older controllers.
388
+ alarms.sort_by_key(|e| std::cmp::Reverse(e.time));
389
+ alarms.truncate(limit);
390
+ Ok(alarms)
391
+ }
392
+ Err(e) => Err(e),
393
+ }
375
394
  }
376
395
 
377
396
  // Port table for a specific device