unifi-cli 0.2.0__tar.gz → 0.2.2__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 (35) hide show
  1. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/.github/workflows/ci.yml +4 -4
  2. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/.github/workflows/release.yml +13 -13
  3. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/CHANGELOG.md +22 -0
  4. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/Cargo.lock +240 -4
  5. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/Cargo.toml +2 -1
  6. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/Makefile +4 -1
  7. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/PKG-INFO +1 -1
  8. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/src/api/tests.rs +18 -0
  9. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/src/api/types.rs +27 -0
  10. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/src/commands/clients.rs +50 -4
  11. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/src/commands/devices.rs +49 -5
  12. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/src/commands/events.rs +42 -20
  13. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/src/commands/networks.rs +1 -1
  14. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/src/commands/protect.rs +6 -6
  15. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/src/commands/system.rs +2 -2
  16. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/src/main.rs +146 -22
  17. unifi_cli-0.2.2/src/output.rs +218 -0
  18. unifi_cli-0.2.2/src/schema.rs +609 -0
  19. unifi_cli-0.2.2/tests/fixtures/clispec-v0.2.json +135 -0
  20. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/tests/mock_server.rs +88 -30
  21. unifi_cli-0.2.2/tests/spec_compliance.rs +126 -0
  22. unifi_cli-0.2.0/src/output.rs +0 -114
  23. unifi_cli-0.2.0/src/schema.rs +0 -346
  24. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/.gitignore +0 -0
  25. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/LICENSE +0 -0
  26. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/README.md +0 -0
  27. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/prek.toml +0 -0
  28. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/pyproject.toml +0 -0
  29. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/src/api/client.rs +0 -0
  30. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/src/api/mod.rs +0 -0
  31. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/src/commands/mod.rs +0 -0
  32. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/src/lib.rs +0 -0
  33. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/src/tui.rs +0 -0
  34. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/unifi_cli/__init__.py +0 -0
  35. {unifi_cli-0.2.0 → unifi_cli-0.2.2}/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
 
@@ -2,8 +2,30 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+
6
+
7
+ ## [0.2.2](https://github.com/rvben/unifi-cli/compare/v0.2.1...v0.2.2) - 2026-06-11
8
+
9
+ ### Added
10
+
11
+ - **schema**: upgrade to clispec v0.2 schema shape and add compliance features ([25ba5fd](https://github.com/rvben/unifi-cli/commit/25ba5fd365e4124117dcd648d08f4888c118d6a4))
12
+
13
+ ### Fixed
14
+
15
+ - **schema**: promote --yes to global flag and add conflict error kind ([2da61c5](https://github.com/rvben/unifi-cli/commit/2da61c57b3d4e4863293e795950f6a28e5999dd9))
16
+
17
+ ## [0.2.1](https://github.com/rvben/unifi-cli/compare/v0.2.0...v0.2.1) - 2026-06-03
18
+
19
+ 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)).
20
+
21
+ ### Fixed
22
+
23
+ - **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))
24
+
5
25
  ## [0.2.0](https://github.com/rvben/unifi-cli/compare/v0.1.7...v0.2.0) - 2026-05-23
6
26
 
27
+ Thanks to [@l3wi](https://github.com/l3wi) for reporting the TLS certificate validation issue ([#2](https://github.com/rvben/unifi-cli/pull/2)).
28
+
7
29
  ### Breaking Changes
8
30
 
9
31
  - **security**: verify controller TLS certificates by default ([9555a86](https://github.com/rvben/unifi-cli/commit/9555a8671d80a706b7c9ee00215a3cbfcf842d16))
@@ -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.0"
2789
+ version = "0.2.2"
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.0"
3
+ version = "0.2.2"
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.0
3
+ Version: 0.2.2
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: Environment :: Console
6
6
  Classifier: Intended Audience :: System Administrators
@@ -510,6 +510,24 @@ fn deserialize_port_entry() {
510
510
  assert_eq!(port.tx_bytes, Some(1048576));
511
511
  }
512
512
 
513
+ #[test]
514
+ fn deserialize_port_entry_poe_power_as_string() {
515
+ // The legacy /stat/device endpoint may return poe_power as a JSON
516
+ // string (e.g. "0.00") depending on firmware. Verify both string and
517
+ // empty-string forms decode without error.
518
+ let json = r#"{"port_idx": 1, "poe_power": "0.00"}"#;
519
+ let port: PortEntry = serde_json::from_str(json).unwrap();
520
+ assert_eq!(port.poe_power, Some(0.0));
521
+
522
+ let json = r#"{"port_idx": 1, "poe_power": "4.50"}"#;
523
+ let port: PortEntry = serde_json::from_str(json).unwrap();
524
+ assert_eq!(port.poe_power, Some(4.5));
525
+
526
+ let json = r#"{"port_idx": 1, "poe_power": ""}"#;
527
+ let port: PortEntry = serde_json::from_str(json).unwrap();
528
+ assert_eq!(port.poe_power, None);
529
+ }
530
+
513
531
  #[test]
514
532
  fn deserialize_port_entry_minimal() {
515
533
  let json = r#"{}"#;
@@ -285,6 +285,9 @@ pub struct PortEntry {
285
285
  pub full_duplex: bool,
286
286
  #[serde(default)]
287
287
  pub poe_enable: bool,
288
+ // The legacy /stat/device endpoint may return this as a JSON string
289
+ // (e.g. "0.00") or as a JSON number depending on firmware. Accept either form.
290
+ #[serde(default, deserialize_with = "deserialize_string_or_number_f64")]
288
291
  pub poe_power: Option<f64>,
289
292
  #[serde(default)]
290
293
  pub port_poe: bool,
@@ -292,6 +295,30 @@ pub struct PortEntry {
292
295
  pub rx_bytes: Option<u64>,
293
296
  }
294
297
 
298
+ fn deserialize_string_or_number_f64<'de, D>(deserializer: D) -> Result<Option<f64>, D::Error>
299
+ where
300
+ D: serde::Deserializer<'de>,
301
+ {
302
+ use serde::de::Error;
303
+ #[derive(Deserialize)]
304
+ #[serde(untagged)]
305
+ enum StringOrNumber {
306
+ Number(f64),
307
+ String(String),
308
+ }
309
+ match Option::<StringOrNumber>::deserialize(deserializer)? {
310
+ None => Ok(None),
311
+ Some(StringOrNumber::Number(n)) => Ok(Some(n)),
312
+ Some(StringOrNumber::String(s)) => {
313
+ if s.is_empty() {
314
+ Ok(None)
315
+ } else {
316
+ s.parse::<f64>().map(Some).map_err(D::Error::custom)
317
+ }
318
+ }
319
+ }
320
+ }
321
+
295
322
  // Device with port_table from Legacy stat/device endpoint
296
323
  #[derive(Debug, Deserialize)]
297
324
  pub struct DeviceWithPorts {