@ceralive/modem-control 1.0.0 → 1.2.0
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 +341 -0
- package/dist/backend/at-lease.d.ts +59 -0
- package/dist/backend/at-lease.js +118 -0
- package/dist/backend/cell-info.d.ts +46 -0
- package/dist/backend/cell-info.js +124 -0
- package/dist/backend/constants.d.ts +24 -0
- package/{src/backend/constants.ts → dist/backend/constants.js} +4 -9
- package/dist/backend/device-classifier.d.ts +46 -0
- package/dist/backend/device-classifier.js +258 -0
- package/dist/backend/enrichment.d.ts +28 -0
- package/dist/backend/enrichment.js +59 -0
- package/dist/backend/features.d.ts +61 -0
- package/dist/backend/features.js +109 -0
- package/dist/backend/identity-ladder.d.ts +57 -0
- package/dist/backend/identity-ladder.js +158 -0
- package/dist/backend/identity-registry.d.ts +51 -0
- package/dist/backend/identity-registry.js +101 -0
- package/dist/backend/index.d.ts +30 -0
- package/dist/backend/index.js +35 -0
- package/dist/backend/lifecycle-interlock.d.ts +25 -0
- package/dist/backend/lifecycle-interlock.js +18 -0
- package/dist/backend/managed-objects.d.ts +39 -0
- package/dist/backend/managed-objects.js +82 -0
- package/dist/backend/mapping.d.ts +11 -0
- package/dist/backend/mapping.js +148 -0
- package/dist/backend/mm-backend.d.ts +44 -0
- package/dist/backend/mm-backend.js +154 -0
- package/dist/backend/mm-location.d.ts +21 -0
- package/dist/backend/mm-location.js +237 -0
- package/dist/backend/mm-mutations.d.ts +42 -0
- package/dist/backend/mm-mutations.js +259 -0
- package/dist/backend/modem-actor.d.ts +41 -0
- package/dist/backend/modem-actor.js +78 -0
- package/dist/backend/nm-auto-apn.d.ts +54 -0
- package/dist/backend/nm-auto-apn.js +124 -0
- package/dist/backend/nm-gsm-fields.d.ts +23 -0
- package/dist/backend/nm-gsm-fields.js +107 -0
- package/dist/backend/nmcli-nm-port.d.ts +28 -0
- package/dist/backend/nmcli-nm-port.js +173 -0
- package/dist/backend/nmcli-runner.d.ts +24 -0
- package/dist/backend/nmcli-runner.js +35 -0
- package/dist/backend/observer.d.ts +37 -0
- package/dist/backend/observer.js +219 -0
- package/dist/backend/power-contract.d.ts +49 -0
- package/dist/backend/power-contract.js +34 -0
- package/dist/backend/recovery-attribution.d.ts +32 -0
- package/dist/backend/recovery-attribution.js +57 -0
- package/dist/backend/recovery-budget.d.ts +45 -0
- package/dist/backend/recovery-budget.js +44 -0
- package/dist/backend/recovery-ladder.d.ts +94 -0
- package/dist/backend/recovery-ladder.js +116 -0
- package/dist/backend/router-ethernet.d.ts +19 -0
- package/dist/backend/router-ethernet.js +66 -0
- package/dist/backend/row-store.d.ts +13 -0
- package/dist/backend/row-store.js +82 -0
- package/dist/backend/signal-setup.d.ts +30 -0
- package/dist/backend/signal-setup.js +92 -0
- package/dist/backend/sim-unlock.d.ts +13 -0
- package/dist/backend/sim-unlock.js +153 -0
- package/dist/backend/transition-preconditions.d.ts +101 -0
- package/dist/backend/transition-preconditions.js +132 -0
- package/dist/backend/usage/accounting.d.ts +39 -0
- package/dist/backend/usage/accounting.js +73 -0
- package/dist/backend/usage/billing-cycle.d.ts +11 -0
- package/dist/backend/usage/billing-cycle.js +39 -0
- package/dist/backend/usage/boot-id.d.ts +6 -0
- package/{src/backend/usage/boot-id.ts → dist/backend/usage/boot-id.js} +7 -7
- package/dist/backend/usage/index.d.ts +8 -0
- package/dist/backend/usage/index.js +11 -0
- package/dist/backend/usage/policy-store.d.ts +50 -0
- package/dist/backend/usage/policy-store.js +161 -0
- package/dist/backend/usage/policy-write.d.ts +65 -0
- package/dist/backend/usage/policy-write.js +112 -0
- package/dist/backend/usage/proc-net-dev.d.ts +18 -0
- package/{src/backend/usage/proc-net-dev.ts → dist/backend/usage/proc-net-dev.js} +39 -47
- package/dist/backend/usage/sampler.d.ts +75 -0
- package/dist/backend/usage/sampler.js +211 -0
- package/dist/backend/usage/store.d.ts +38 -0
- package/dist/backend/usage/store.js +126 -0
- package/dist/backend/usb-device-snapshot.d.ts +31 -0
- package/dist/backend/usb-device-snapshot.js +1 -0
- package/dist/backend/usb-enumerator.d.ts +21 -0
- package/dist/backend/usb-enumerator.js +153 -0
- package/dist/backend/usb-mode-transition.d.ts +29 -0
- package/dist/backend/usb-mode-transition.js +216 -0
- package/dist/band/band-names.d.ts +42 -0
- package/dist/band/band-names.js +150 -0
- package/dist/band/certification.d.ts +84 -0
- package/dist/band/certification.js +127 -0
- package/dist/band/certified-bands.json +4 -0
- package/dist/band/index.d.ts +2 -0
- package/dist/band/index.js +8 -0
- package/dist/capability/detect.d.ts +52 -0
- package/dist/capability/detect.js +86 -0
- package/dist/capability/five-g-preference.d.ts +104 -0
- package/dist/capability/five-g-preference.js +171 -0
- package/dist/capability/index.d.ts +3 -0
- package/dist/capability/index.js +10 -0
- package/dist/capability/support-claim.d.ts +39 -0
- package/dist/capability/support-claim.js +81 -0
- package/dist/domain/brand.d.ts +10 -0
- package/dist/domain/brand.js +21 -0
- package/dist/domain/errors.d.ts +32 -0
- package/dist/domain/errors.js +48 -0
- package/dist/domain/generation.d.ts +8 -0
- package/dist/domain/generation.js +12 -0
- package/dist/domain/guards.d.ts +6 -0
- package/dist/domain/guards.js +127 -0
- package/dist/domain/identity.d.ts +109 -0
- package/dist/domain/identity.js +86 -0
- package/dist/domain/index.d.ts +14 -0
- package/dist/domain/index.js +18 -0
- package/dist/domain/mm-enums.d.ts +12 -0
- package/dist/domain/mm-enums.js +139 -0
- package/dist/domain/modem-presentation.d.ts +10 -0
- package/dist/domain/modem-presentation.js +39 -0
- package/dist/domain/observation.d.ts +39 -0
- package/dist/domain/observation.js +4 -0
- package/dist/domain/operation.d.ts +118 -0
- package/dist/domain/operation.js +85 -0
- package/dist/domain/physical-identity.d.ts +43 -0
- package/dist/domain/physical-identity.js +113 -0
- package/{src/domain/policy.ts → dist/domain/policy.d.ts} +34 -69
- package/dist/domain/policy.js +38 -0
- package/dist/domain/shadow-divergence.d.ts +27 -0
- package/dist/domain/shadow-divergence.js +70 -0
- package/dist/domain/snapshot.d.ts +53 -0
- package/dist/domain/snapshot.js +75 -0
- package/{src/domain/state.ts → dist/domain/state.d.ts} +23 -122
- package/dist/domain/state.js +38 -0
- package/dist/fcc/coverage.d.ts +63 -0
- package/dist/fcc/coverage.js +102 -0
- package/dist/fcc/index.d.ts +3 -0
- package/dist/fcc/index.js +12 -0
- package/dist/fcc/policy-store.d.ts +40 -0
- package/dist/fcc/policy-store.js +146 -0
- package/dist/fcc/policy-write.d.ts +32 -0
- package/dist/fcc/policy-write.js +37 -0
- package/dist/hardware/hilink-protocol.d.ts +39 -0
- package/dist/hardware/hilink-protocol.js +58 -0
- package/dist/hardware/index.d.ts +3 -0
- package/dist/hardware/index.js +15 -0
- package/dist/hardware/router-parsers.d.ts +89 -0
- package/dist/hardware/router-parsers.js +234 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +27 -0
- package/dist/journal/codec.d.ts +44 -0
- package/dist/journal/codec.js +198 -0
- package/dist/journal/engine.d.ts +28 -0
- package/dist/journal/engine.js +68 -0
- package/dist/journal/entry.d.ts +74 -0
- package/dist/journal/entry.js +56 -0
- package/dist/journal/index.d.ts +6 -0
- package/dist/journal/index.js +6 -0
- package/dist/journal/legacy-ceraui.d.ts +73 -0
- package/dist/journal/legacy-ceraui.js +227 -0
- package/dist/journal/recovery.d.ts +58 -0
- package/dist/journal/recovery.js +117 -0
- package/dist/journal/store.d.ts +55 -0
- package/dist/journal/store.js +150 -0
- package/dist/location/fix-state.d.ts +53 -0
- package/dist/location/fix-state.js +75 -0
- package/dist/location/index.d.ts +2 -0
- package/dist/location/index.js +8 -0
- package/dist/location/nmea.d.ts +10 -0
- package/dist/location/nmea.js +89 -0
- package/dist/observations/envelope.d.ts +63 -0
- package/dist/observations/envelope.js +77 -0
- package/dist/observations/freshness.d.ts +28 -0
- package/dist/observations/freshness.js +76 -0
- package/dist/observations/index.d.ts +13 -0
- package/dist/observations/index.js +24 -0
- package/dist/observations/metric.d.ts +61 -0
- package/dist/observations/metric.js +73 -0
- package/dist/observations/model.d.ts +80 -0
- package/dist/observations/model.js +11 -0
- package/dist/observations/provenance.d.ts +94 -0
- package/dist/observations/provenance.js +67 -0
- package/dist/observations/raw.d.ts +42 -0
- package/dist/observations/raw.js +146 -0
- package/dist/observations/reading.d.ts +51 -0
- package/dist/observations/reading.js +65 -0
- package/dist/observations/sources/hilink.d.ts +10 -0
- package/dist/observations/sources/hilink.js +84 -0
- package/dist/observations/sources/modemmanager.d.ts +18 -0
- package/dist/observations/sources/modemmanager.js +239 -0
- package/dist/observations/sources/router-shared.d.ts +29 -0
- package/dist/observations/sources/router-shared.js +68 -0
- package/dist/observations/sources/ufi.d.ts +10 -0
- package/dist/observations/sources/ufi.js +111 -0
- package/dist/observations/sources/zte.d.ts +7 -0
- package/dist/observations/sources/zte.js +71 -0
- package/dist/observations/state-separation.d.ts +64 -0
- package/dist/observations/state-separation.js +52 -0
- package/dist/operation-ids.d.ts +2 -0
- package/dist/operation-ids.js +26 -0
- package/dist/operations/contracts.d.ts +72 -0
- package/dist/operations/contracts.js +1 -0
- package/dist/operations/index.d.ts +1 -0
- package/dist/operations/index.js +1 -0
- package/dist/operations/operation-engine.d.ts +16 -0
- package/dist/operations/operation-engine.js +194 -0
- package/dist/ports/index.d.ts +12 -0
- package/{src/ports/index.ts → dist/ports/index.js} +12 -8
- package/dist/ports/location.d.ts +87 -0
- package/dist/ports/location.js +36 -0
- package/dist/ports/modem-manager.d.ts +89 -0
- package/dist/ports/modem-manager.js +9 -0
- package/dist/ports/mutation-admission.d.ts +27 -0
- package/dist/ports/mutation-admission.js +9 -0
- package/dist/ports/network-manager.d.ts +68 -0
- package/dist/ports/network-manager.js +13 -0
- package/{src/ports/observation.ts → dist/ports/observation.d.ts} +16 -27
- package/dist/ports/observation.js +7 -0
- package/dist/ports/ops.d.ts +44 -0
- package/dist/ports/ops.js +16 -0
- package/{src/ports/receipts.ts → dist/ports/receipts.d.ts} +5 -27
- package/dist/ports/receipts.js +9 -0
- package/dist/ports/reconcile.d.ts +33 -0
- package/dist/ports/reconcile.js +200 -0
- package/dist/ports/resource-ownership.d.ts +29 -0
- package/dist/ports/resource-ownership.js +1 -0
- package/dist/ports/router.d.ts +19 -0
- package/dist/ports/router.js +7 -0
- package/dist/ports/sms.d.ts +64 -0
- package/dist/ports/sms.js +24 -0
- package/dist/ports/uhubctl.d.ts +6 -0
- package/dist/ports/uhubctl.js +1 -0
- package/dist/providers/contracts.d.ts +124 -0
- package/dist/providers/contracts.js +10 -0
- package/dist/providers/huawei-hilink/index.d.ts +2 -0
- package/dist/providers/huawei-hilink/index.js +2 -0
- package/dist/providers/huawei-hilink/operations.d.ts +20 -0
- package/dist/providers/huawei-hilink/operations.js +56 -0
- package/dist/providers/huawei-hilink/provider.d.ts +52 -0
- package/dist/providers/huawei-hilink/provider.js +76 -0
- package/dist/providers/huawei-hilink/runtime.d.ts +22 -0
- package/dist/providers/huawei-hilink/runtime.js +171 -0
- package/dist/providers/huawei-hilink/session.d.ts +28 -0
- package/dist/providers/huawei-hilink/session.js +120 -0
- package/dist/providers/huawei-hilink/transport.d.ts +19 -0
- package/dist/providers/huawei-hilink/transport.js +1 -0
- package/dist/providers/index.d.ts +8 -0
- package/dist/providers/index.js +8 -0
- package/dist/providers/matcher.d.ts +3 -0
- package/dist/providers/matcher.js +205 -0
- package/dist/providers/modem-manager/errors.d.ts +7 -0
- package/dist/providers/modem-manager/errors.js +37 -0
- package/dist/providers/modem-manager/generic-operations.d.ts +10 -0
- package/dist/providers/modem-manager/generic-operations.js +209 -0
- package/dist/providers/modem-manager/index.d.ts +4 -0
- package/dist/providers/modem-manager/index.js +4 -0
- package/dist/providers/modem-manager/module-operations.d.ts +21 -0
- package/dist/providers/modem-manager/module-operations.js +118 -0
- package/dist/providers/modem-manager/provider.d.ts +41 -0
- package/dist/providers/modem-manager/provider.js +155 -0
- package/dist/providers/modem-manager/runtime-composition-operation.d.ts +32 -0
- package/dist/providers/modem-manager/runtime-composition-operation.js +151 -0
- package/dist/providers/modem-manager/snapshot.d.ts +5 -0
- package/dist/providers/modem-manager/snapshot.js +204 -0
- package/dist/providers/modem-manager/types.d.ts +137 -0
- package/dist/providers/modem-manager/types.js +1 -0
- package/dist/providers/network-manager/adapter.d.ts +71 -0
- package/dist/providers/network-manager/adapter.js +348 -0
- package/dist/providers/network-manager/index.d.ts +2 -0
- package/dist/providers/network-manager/index.js +2 -0
- package/dist/providers/network-manager/types.d.ts +171 -0
- package/dist/providers/network-manager/types.js +77 -0
- package/dist/providers/registry.d.ts +13 -0
- package/dist/providers/registry.js +33 -0
- package/dist/providers/ufi-himi/index.d.ts +6 -0
- package/dist/providers/ufi-himi/index.js +6 -0
- package/dist/providers/ufi-himi/operations.d.ts +41 -0
- package/dist/providers/ufi-himi/operations.js +66 -0
- package/dist/providers/ufi-himi/prohibitions.d.ts +62 -0
- package/dist/providers/ufi-himi/prohibitions.js +88 -0
- package/dist/providers/ufi-himi/provider.d.ts +41 -0
- package/dist/providers/ufi-himi/provider.js +204 -0
- package/dist/providers/ufi-himi/qualcomm-evidence.d.ts +32 -0
- package/dist/providers/ufi-himi/qualcomm-evidence.js +51 -0
- package/dist/providers/ufi-himi/session.d.ts +46 -0
- package/dist/providers/ufi-himi/session.js +92 -0
- package/dist/providers/ufi-himi/transport.d.ts +29 -0
- package/dist/providers/ufi-himi/transport.js +25 -0
- package/dist/providers/zte-goform/index.d.ts +2 -0
- package/dist/providers/zte-goform/index.js +2 -0
- package/dist/providers/zte-goform/provider.d.ts +56 -0
- package/dist/providers/zte-goform/provider.js +101 -0
- package/dist/providers/zte-goform/session.d.ts +23 -0
- package/dist/providers/zte-goform/session.js +197 -0
- package/dist/providers/zte-goform/transport.d.ts +16 -0
- package/dist/providers/zte-goform/transport.js +1 -0
- package/dist/radio/band-truth.d.ts +50 -0
- package/dist/radio/band-truth.js +92 -0
- package/dist/radio/index.d.ts +3 -0
- package/dist/radio/index.js +10 -0
- package/dist/radio/mode-combinations.d.ts +88 -0
- package/dist/radio/mode-combinations.js +198 -0
- package/dist/radio/mode-truth.d.ts +67 -0
- package/dist/radio/mode-truth.js +112 -0
- package/dist/redact.d.ts +15 -0
- package/dist/redact.js +189 -0
- package/dist/safety/composition-root.d.ts +28 -0
- package/dist/safety/composition-root.js +65 -0
- package/dist/safety/flock-resource-ownership.d.ts +11 -0
- package/dist/safety/flock-resource-ownership.js +138 -0
- package/dist/safety/index.d.ts +2 -0
- package/dist/safety/index.js +2 -0
- package/dist/sms/dbus-messaging.d.ts +17 -0
- package/dist/sms/dbus-messaging.js +185 -0
- package/dist/sms/inbox-store.d.ts +10 -0
- package/dist/sms/inbox-store.js +82 -0
- package/dist/sms/index.d.ts +4 -0
- package/dist/sms/index.js +10 -0
- package/dist/sms/mmcli-parse.d.ts +54 -0
- package/dist/sms/mmcli-parse.js +224 -0
- package/dist/sms/normalize.d.ts +42 -0
- package/dist/sms/normalize.js +95 -0
- package/dist/testing/domain-fakes.d.ts +58 -0
- package/dist/testing/domain-fakes.js +98 -0
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.js +17 -0
- package/dist/testing/provider-fakes.d.ts +45 -0
- package/dist/testing/provider-fakes.js +64 -0
- package/dist/transport/calls.d.ts +9 -0
- package/dist/transport/calls.js +88 -0
- package/dist/transport/codec.d.ts +3 -0
- package/dist/transport/codec.js +207 -0
- package/dist/transport/dbus-native.d.ts +57 -0
- package/dist/transport/dbus-native.js +17 -0
- package/dist/transport/errors.d.ts +21 -0
- package/{src/transport/errors.ts → dist/transport/errors.js} +34 -46
- package/dist/transport/index.d.ts +4 -0
- package/dist/transport/index.js +9 -0
- package/dist/transport/signals.d.ts +15 -0
- package/dist/transport/signals.js +123 -0
- package/dist/transport/signature.d.ts +7 -0
- package/dist/transport/signature.js +94 -0
- package/dist/transport/transport.d.ts +2 -0
- package/dist/transport/transport.js +202 -0
- package/dist/transport/types.d.ts +61 -0
- package/dist/transport/types.js +19 -0
- package/dist/usb-mode/catalog-schema.d.ts +139 -0
- package/dist/usb-mode/catalog-schema.js +97 -0
- package/dist/usb-mode/catalog.d.ts +21 -0
- package/{src/usb-mode/catalog.ts → dist/usb-mode/catalog.js} +10 -32
- package/dist/usb-mode/certified-catalog.json +67 -0
- package/dist/usb-mode/index.d.ts +6 -0
- package/dist/usb-mode/index.js +16 -0
- package/dist/usb-mode/ingestion.d.ts +111 -0
- package/dist/usb-mode/ingestion.js +187 -0
- package/dist/usb-mode/promotion-review.d.ts +21 -0
- package/dist/usb-mode/promotion-review.js +87 -0
- package/dist/usb-mode/runtime-capability.d.ts +59 -0
- package/dist/usb-mode/runtime-capability.js +157 -0
- package/dist/usb-mode/usb-devices-parse.d.ts +36 -0
- package/dist/usb-mode/usb-devices-parse.js +157 -0
- package/dist/ussd/calls.d.ts +32 -0
- package/dist/ussd/calls.js +96 -0
- package/dist/ussd/index.d.ts +5 -0
- package/dist/ussd/index.js +12 -0
- package/dist/ussd/mm-ussd.d.ts +37 -0
- package/dist/ussd/mm-ussd.js +205 -0
- package/dist/ussd/refusal.d.ts +53 -0
- package/dist/ussd/refusal.js +154 -0
- package/dist/ussd/registration.d.ts +20 -0
- package/dist/ussd/registration.js +101 -0
- package/dist/ussd/session.d.ts +106 -0
- package/dist/ussd/session.js +163 -0
- package/package.json +38 -4
- package/src/backend/at-lease.test.ts +0 -106
- package/src/backend/at-lease.ts +0 -158
- package/src/backend/cell-info.test.ts +0 -154
- package/src/backend/cell-info.ts +0 -160
- package/src/backend/device-classifier.test.ts +0 -168
- package/src/backend/device-classifier.ts +0 -248
- package/src/backend/enrichment.ts +0 -96
- package/src/backend/features.test.ts +0 -162
- package/src/backend/features.ts +0 -179
- package/src/backend/identity-ladder.test.ts +0 -117
- package/src/backend/identity-ladder.ts +0 -221
- package/src/backend/identity-registry.test.ts +0 -89
- package/src/backend/identity-registry.ts +0 -151
- package/src/backend/index.ts +0 -236
- package/src/backend/lifecycle-interlock.ts +0 -38
- package/src/backend/managed-objects.ts +0 -108
- package/src/backend/mapping.ts +0 -160
- package/src/backend/mm-backend.ts +0 -191
- package/src/backend/mm-mutations.ts +0 -228
- package/src/backend/modem-actor.test.ts +0 -95
- package/src/backend/modem-actor.ts +0 -112
- package/src/backend/nm-auto-apn.ts +0 -161
- package/src/backend/nm-gsm-fields.ts +0 -122
- package/src/backend/nmcli-nm-port.ts +0 -228
- package/src/backend/nmcli-runner.ts +0 -52
- package/src/backend/observer.ts +0 -297
- package/src/backend/power-contract.test.ts +0 -40
- package/src/backend/power-contract.ts +0 -83
- package/src/backend/recovery-attribution.test.ts +0 -102
- package/src/backend/recovery-attribution.ts +0 -86
- package/src/backend/recovery-budget.test.ts +0 -64
- package/src/backend/recovery-budget.ts +0 -84
- package/src/backend/recovery-ladder.test.ts +0 -257
- package/src/backend/recovery-ladder.ts +0 -249
- package/src/backend/router-ethernet.test.ts +0 -71
- package/src/backend/router-ethernet.ts +0 -90
- package/src/backend/row-store.ts +0 -105
- package/src/backend/signal-setup.ts +0 -112
- package/src/backend/sim-unlock.ts +0 -193
- package/src/backend/transition-preconditions.ts +0 -149
- package/src/backend/uhubctl-power-hook.test.ts +0 -274
- package/src/backend/uhubctl-power-hook.ts +0 -377
- package/src/backend/usage/accounting.test.ts +0 -147
- package/src/backend/usage/accounting.ts +0 -123
- package/src/backend/usage/billing-cycle.test.ts +0 -62
- package/src/backend/usage/billing-cycle.ts +0 -45
- package/src/backend/usage/index.ts +0 -60
- package/src/backend/usage/policy-store.test.ts +0 -164
- package/src/backend/usage/policy-store.ts +0 -216
- package/src/backend/usage/policy-write.test.ts +0 -198
- package/src/backend/usage/policy-write.ts +0 -207
- package/src/backend/usage/proc-net-dev.test.ts +0 -56
- package/src/backend/usage/sampler.test.ts +0 -327
- package/src/backend/usage/sampler.ts +0 -282
- package/src/backend/usage/store.test.ts +0 -148
- package/src/backend/usage/store.ts +0 -177
- package/src/backend/usb-enumerator.test.ts +0 -87
- package/src/backend/usb-enumerator.ts +0 -181
- package/src/backend/usb-mode-transition.test.ts +0 -323
- package/src/backend/usb-mode-transition.ts +0 -253
- package/src/domain/brand.ts +0 -29
- package/src/domain/errors.ts +0 -77
- package/src/domain/guards.test.ts +0 -218
- package/src/domain/guards.ts +0 -144
- package/src/domain/identity.test.ts +0 -83
- package/src/domain/identity.ts +0 -165
- package/src/domain/index.ts +0 -12
- package/src/domain/snapshot.test.ts +0 -266
- package/src/domain/snapshot.ts +0 -120
- package/src/index.test.ts +0 -6
- package/src/index.ts +0 -15
- package/src/ports/README.md +0 -61
- package/src/ports/forbidden-surface.test.ts +0 -241
- package/src/ports/modem-manager.ts +0 -72
- package/src/ports/network-manager.ts +0 -87
- package/src/ports/ops.ts +0 -60
- package/src/ports/ops.type-test.ts +0 -39
- package/src/ports/receipts.test.ts +0 -153
- package/src/ports/reconcile.test.ts +0 -152
- package/src/ports/reconcile.ts +0 -338
- package/src/ports/router.ts +0 -29
- package/src/redact.test.ts +0 -82
- package/src/redact.ts +0 -73
- package/src/transport/README.md +0 -65
- package/src/transport/calls.ts +0 -113
- package/src/transport/characterization.test.ts +0 -260
- package/src/transport/codec.test.ts +0 -118
- package/src/transport/codec.ts +0 -240
- package/src/transport/conformance-python.test.ts +0 -152
- package/src/transport/conformance-same-lib.test.ts +0 -115
- package/src/transport/dbus-native-lib.d.ts +0 -19
- package/src/transport/dbus-native.ts +0 -85
- package/src/transport/index.ts +0 -30
- package/src/transport/no-library-leak.test.ts +0 -61
- package/src/transport/reliability.test.ts +0 -173
- package/src/transport/signals.ts +0 -150
- package/src/transport/signature.ts +0 -110
- package/src/transport/test-support/fake-service.ts +0 -168
- package/src/transport/test-support/independent-producer.py +0 -110
- package/src/transport/test-support/private-bus.ts +0 -66
- package/src/transport/transport.ts +0 -250
- package/src/transport/types.ts +0 -118
- package/src/usb-mode/catalog-schema.test.ts +0 -181
- package/src/usb-mode/catalog-schema.ts +0 -113
- package/src/usb-mode/certified-catalog.json +0 -67
- package/src/usb-mode/index.ts +0 -58
- package/src/usb-mode/ingestion.test.ts +0 -268
- package/src/usb-mode/ingestion.ts +0 -297
- package/src/usb-mode/promotion-review.ts +0 -117
- package/src/usb-mode/usb-devices-parse.ts +0 -196
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// Method-call dispatch and reply correlation for the D-Bus transport seam.
|
|
2
|
+
//
|
|
3
|
+
// A call marshals its body through the codec, registers a pending record so a bus drop can
|
|
4
|
+
// reject it, and installs a per-call reply callback guarded by a `done` flag — so a reply
|
|
5
|
+
// that arrives after the call already timed out or the connection dropped is silently
|
|
6
|
+
// ignored rather than mis-correlated onto a stale promise. `rejectAll` mass-rejects every
|
|
7
|
+
// in-flight call when the connection drops.
|
|
8
|
+
import { decodeBody, encodeBody } from './codec.js';
|
|
9
|
+
import { messageType } from './dbus-native.js';
|
|
10
|
+
import { DisconnectedError, TransportError } from './errors.js';
|
|
11
|
+
export const DEFAULT_CALL_TIMEOUT_MS = 30_000;
|
|
12
|
+
export class CallDispatcher {
|
|
13
|
+
#pending = new Set();
|
|
14
|
+
#callTimeoutMs;
|
|
15
|
+
constructor(callTimeoutMs) {
|
|
16
|
+
this.#callTimeoutMs = callTimeoutMs;
|
|
17
|
+
}
|
|
18
|
+
async call(bus, connected, call) {
|
|
19
|
+
if (!connected || bus === null) {
|
|
20
|
+
throw new DisconnectedError('cannot call method: transport not connected');
|
|
21
|
+
}
|
|
22
|
+
const signature = call.signature ?? '';
|
|
23
|
+
const args = call.args ?? [];
|
|
24
|
+
const message = {
|
|
25
|
+
type: messageType.methodCall,
|
|
26
|
+
destination: call.destination,
|
|
27
|
+
path: call.path,
|
|
28
|
+
interface: call.interface,
|
|
29
|
+
member: call.member,
|
|
30
|
+
};
|
|
31
|
+
if (signature.length > 0) {
|
|
32
|
+
// Throws UnsupportedSignatureError / BigIntRequiredError before anything hits
|
|
33
|
+
// the wire.
|
|
34
|
+
message.signature = signature;
|
|
35
|
+
message.body = encodeBody(signature, args);
|
|
36
|
+
}
|
|
37
|
+
const timeoutMs = call.timeoutMs ?? this.#callTimeoutMs;
|
|
38
|
+
const pendingSet = this.#pending;
|
|
39
|
+
return new Promise((resolve, reject) => {
|
|
40
|
+
let done = false;
|
|
41
|
+
const pending = {
|
|
42
|
+
settle: finish,
|
|
43
|
+
reject: (error) => {
|
|
44
|
+
finish();
|
|
45
|
+
reject(error);
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
function finish() {
|
|
49
|
+
if (done) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
done = true;
|
|
53
|
+
clearTimeout(timer);
|
|
54
|
+
pendingSet.delete(pending);
|
|
55
|
+
}
|
|
56
|
+
const timer = setTimeout(() => {
|
|
57
|
+
finish();
|
|
58
|
+
reject(new TransportError(`Method call ${call.interface}.${call.member} timed out after ${timeoutMs}ms`));
|
|
59
|
+
}, timeoutMs);
|
|
60
|
+
pendingSet.add(pending);
|
|
61
|
+
bus.invoke(message, function reply(error, ...body) {
|
|
62
|
+
if (done) {
|
|
63
|
+
// Reply arrived after timeout/disconnect already settled the promise — ignore.
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
finish();
|
|
67
|
+
if (error) {
|
|
68
|
+
reject(error instanceof Error ? error : new TransportError(String(error)));
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
const replySignature = this.signature ?? '';
|
|
73
|
+
const decoded = replySignature.length > 0 ? decodeBody(replySignature, body) : [];
|
|
74
|
+
resolve({ signature: replySignature, body: decoded });
|
|
75
|
+
}
|
|
76
|
+
catch (decodeError) {
|
|
77
|
+
reject(decodeError);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
rejectAll(cause) {
|
|
83
|
+
for (const pending of this.#pending) {
|
|
84
|
+
pending.reject(cause);
|
|
85
|
+
}
|
|
86
|
+
this.#pending.clear();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
// Signature-aware encode / decode between the transport's public value vocabulary
|
|
2
|
+
// (`DbusValue`, `bigint` for 64-bit, `DbusVariant`) and the shape the underlying
|
|
3
|
+
// `@httptoolkit/dbus-native` marshaller consumes and produces.
|
|
4
|
+
//
|
|
5
|
+
// Two invariants this layer enforces that the library does not:
|
|
6
|
+
// * 64-bit `x`/`t` are `bigint` end-to-end. On decode the library returns Long.js
|
|
7
|
+
// objects (only under `ReturnLongjs: true`); we convert them to `bigint` losslessly
|
|
8
|
+
// via their exact decimal `toString()`. On encode the library accepts a decimal
|
|
9
|
+
// string for the full 64-bit range but silently truncates a `number` above 2^53 —
|
|
10
|
+
// so we require a `bigint` and convert it to a decimal string ourselves.
|
|
11
|
+
// * `h` (UNIX_FD) is rejected up front with a typed error rather than reaching the
|
|
12
|
+
// library, which would throw a generic "Unknown/Unsupported type" instead.
|
|
13
|
+
import { BigIntRequiredError, SixtyFourBitRangeError, UnsupportedSignatureError } from './errors.js';
|
|
14
|
+
import { parseSignature, signatureFromNode } from './signature.js';
|
|
15
|
+
const INT64_MIN = -(2n ** 63n);
|
|
16
|
+
const INT64_MAX = 2n ** 63n - 1n;
|
|
17
|
+
const UINT64_MAX = 2n ** 64n - 1n;
|
|
18
|
+
function isLongLike(value) {
|
|
19
|
+
return (typeof value === 'object' &&
|
|
20
|
+
value !== null &&
|
|
21
|
+
typeof value.low === 'number' &&
|
|
22
|
+
typeof value.high === 'number' &&
|
|
23
|
+
typeof value.unsigned === 'boolean');
|
|
24
|
+
}
|
|
25
|
+
function longToBigInt(value) {
|
|
26
|
+
return BigInt(value.toString());
|
|
27
|
+
}
|
|
28
|
+
// ── Encode ─────────────────────────────────────────────────────────────────────────
|
|
29
|
+
// Public values → library-native body. `assertSupportedSignature` is applied to the
|
|
30
|
+
// whole signature first, so no `h` reaches the recursion.
|
|
31
|
+
export function encodeBody(signature, args) {
|
|
32
|
+
if (signature.includes('h')) {
|
|
33
|
+
throw new UnsupportedSignatureError(signature, 'h');
|
|
34
|
+
}
|
|
35
|
+
const nodes = parseSignature(signature);
|
|
36
|
+
if (nodes.length !== args.length) {
|
|
37
|
+
throw new Error(`Body arity ${args.length} does not match signature "${signature}" (${nodes.length} types)`);
|
|
38
|
+
}
|
|
39
|
+
return nodes.map((node, i) => encodeNode(node, args[i]));
|
|
40
|
+
}
|
|
41
|
+
function encodeNode(node, value) {
|
|
42
|
+
switch (node.type) {
|
|
43
|
+
case 'x':
|
|
44
|
+
return encode64(node.type, value, INT64_MIN, INT64_MAX);
|
|
45
|
+
case 't':
|
|
46
|
+
return encode64(node.type, value, 0n, UINT64_MAX);
|
|
47
|
+
case 'a':
|
|
48
|
+
return encodeArray(node, value);
|
|
49
|
+
case '(':
|
|
50
|
+
return encodeStruct(node, value);
|
|
51
|
+
case '{':
|
|
52
|
+
return encodeDictEntry(node, value);
|
|
53
|
+
case 'v':
|
|
54
|
+
return encodeVariant(value);
|
|
55
|
+
default:
|
|
56
|
+
// y b n q i u d s o g — the library validates range/type on marshal.
|
|
57
|
+
return value;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function encode64(type, value, min, max) {
|
|
61
|
+
if (typeof value !== 'bigint') {
|
|
62
|
+
throw new BigIntRequiredError(type, value);
|
|
63
|
+
}
|
|
64
|
+
if (value < min || value > max) {
|
|
65
|
+
throw new SixtyFourBitRangeError(type, value);
|
|
66
|
+
}
|
|
67
|
+
// Decimal string: the library parses this across the full 64-bit range losslessly.
|
|
68
|
+
return value.toString();
|
|
69
|
+
}
|
|
70
|
+
function encodeArray(node, value) {
|
|
71
|
+
const element = node.child[0];
|
|
72
|
+
// `ay` byte arrays pass straight through as a Uint8Array / Buffer (index-addressable).
|
|
73
|
+
if (element.type === 'y' && value instanceof Uint8Array) {
|
|
74
|
+
return value;
|
|
75
|
+
}
|
|
76
|
+
if (!Array.isArray(value)) {
|
|
77
|
+
throw new Error(`Expected array for signature "a${element.type}"`);
|
|
78
|
+
}
|
|
79
|
+
return value.map((item) => encodeNode(element, item));
|
|
80
|
+
}
|
|
81
|
+
function encodeStruct(node, value) {
|
|
82
|
+
if (!Array.isArray(value)) {
|
|
83
|
+
throw new Error('Expected array for struct value');
|
|
84
|
+
}
|
|
85
|
+
if (value.length !== node.child.length) {
|
|
86
|
+
throw new Error(`Struct arity ${value.length} does not match ${node.child.length} field types`);
|
|
87
|
+
}
|
|
88
|
+
return node.child.map((child, i) => encodeNode(child, value[i]));
|
|
89
|
+
}
|
|
90
|
+
function encodeDictEntry(node, value) {
|
|
91
|
+
if (!Array.isArray(value) || value.length !== 2) {
|
|
92
|
+
throw new Error('Expected [key, value] pair for dict entry');
|
|
93
|
+
}
|
|
94
|
+
const keyNode = node.child[0];
|
|
95
|
+
const valueNode = node.child[1];
|
|
96
|
+
return [encodeNode(keyNode, value[0]), encodeNode(valueNode, value[1])];
|
|
97
|
+
}
|
|
98
|
+
function encodeVariant(value) {
|
|
99
|
+
const asVariant = value;
|
|
100
|
+
if (typeof asVariant?.signature !== 'string' || !('value' in asVariant)) {
|
|
101
|
+
throw new Error('Expected a DbusVariant ({ signature, value }) for variant field');
|
|
102
|
+
}
|
|
103
|
+
if (asVariant.signature.includes('h')) {
|
|
104
|
+
throw new UnsupportedSignatureError(asVariant.signature, 'h');
|
|
105
|
+
}
|
|
106
|
+
const inner = parseSignature(asVariant.signature);
|
|
107
|
+
if (inner.length !== 1) {
|
|
108
|
+
throw new Error(`Variant signature "${asVariant.signature}" must be exactly one complete type`);
|
|
109
|
+
}
|
|
110
|
+
return [asVariant.signature, encodeNode(inner[0], asVariant.value)];
|
|
111
|
+
}
|
|
112
|
+
// ── Decode ─────────────────────────────────────────────────────────────────────────
|
|
113
|
+
// Library-native body → public values. The library must have been created with
|
|
114
|
+
// `ReturnLongjs: true` so `x`/`t` arrive as Long objects (this transport does exactly
|
|
115
|
+
// that); a raw `number` in a 64-bit slot means that flag was lost and is treated as a
|
|
116
|
+
// bug, not silently accepted.
|
|
117
|
+
export function decodeBody(signature, body) {
|
|
118
|
+
if (signature.includes('h')) {
|
|
119
|
+
throw new UnsupportedSignatureError(signature, 'h');
|
|
120
|
+
}
|
|
121
|
+
const nodes = parseSignature(signature);
|
|
122
|
+
return nodes.map((node, i) => decodeNode(node, body[i]));
|
|
123
|
+
}
|
|
124
|
+
function decodeNode(node, value) {
|
|
125
|
+
switch (node.type) {
|
|
126
|
+
case 'x':
|
|
127
|
+
case 't':
|
|
128
|
+
return decode64(node.type, value);
|
|
129
|
+
case 'a':
|
|
130
|
+
return decodeArray(node, value);
|
|
131
|
+
case '(':
|
|
132
|
+
return decodeStruct(node, value);
|
|
133
|
+
case '{':
|
|
134
|
+
return decodeDictEntry(node, value);
|
|
135
|
+
case 'v':
|
|
136
|
+
return decodeVariant(value);
|
|
137
|
+
case 'y':
|
|
138
|
+
case 'b':
|
|
139
|
+
case 'n':
|
|
140
|
+
case 'q':
|
|
141
|
+
case 'i':
|
|
142
|
+
case 'u':
|
|
143
|
+
case 'd':
|
|
144
|
+
case 's':
|
|
145
|
+
case 'o':
|
|
146
|
+
case 'g':
|
|
147
|
+
return value;
|
|
148
|
+
default:
|
|
149
|
+
throw new UnsupportedSignatureError(node.type, node.type);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
function decode64(type, value) {
|
|
153
|
+
if (isLongLike(value)) {
|
|
154
|
+
return longToBigInt(value);
|
|
155
|
+
}
|
|
156
|
+
if (typeof value === 'bigint') {
|
|
157
|
+
return value;
|
|
158
|
+
}
|
|
159
|
+
// A plain number reaching here means ReturnLongjs was not applied — refuse it rather
|
|
160
|
+
// than risk having already lost precision above 2^53.
|
|
161
|
+
throw new BigIntRequiredError(type, value);
|
|
162
|
+
}
|
|
163
|
+
function decodeArray(node, value) {
|
|
164
|
+
const element = node.child[0];
|
|
165
|
+
if (element.type === 'y') {
|
|
166
|
+
// `ay`: the library returns a Buffer; normalise to a plain Uint8Array.
|
|
167
|
+
if (value instanceof Uint8Array) {
|
|
168
|
+
return new Uint8Array(value);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (!Array.isArray(value)) {
|
|
172
|
+
throw new Error(`Expected array while decoding "a${element.type}"`);
|
|
173
|
+
}
|
|
174
|
+
return value.map((item) => decodeNode(element, item));
|
|
175
|
+
}
|
|
176
|
+
function decodeStruct(node, value) {
|
|
177
|
+
if (!Array.isArray(value)) {
|
|
178
|
+
throw new Error('Expected array while decoding struct');
|
|
179
|
+
}
|
|
180
|
+
return node.child.map((child, i) => decodeNode(child, value[i]));
|
|
181
|
+
}
|
|
182
|
+
function decodeDictEntry(node, value) {
|
|
183
|
+
if (!Array.isArray(value) || value.length !== 2) {
|
|
184
|
+
throw new Error('Expected [key, value] pair while decoding dict entry');
|
|
185
|
+
}
|
|
186
|
+
const keyNode = node.child[0];
|
|
187
|
+
const valueNode = node.child[1];
|
|
188
|
+
return [decodeNode(keyNode, value[0]), decodeNode(valueNode, value[1])];
|
|
189
|
+
}
|
|
190
|
+
// The library decodes a variant to `[parseTree, [innerValue]]`. We recover the inner
|
|
191
|
+
// signature from the tree and decode the contained value recursively, preserving both.
|
|
192
|
+
function decodeVariant(value) {
|
|
193
|
+
if (!Array.isArray(value) || value.length !== 2) {
|
|
194
|
+
throw new Error('Malformed variant from library (expected [tree, [value]])');
|
|
195
|
+
}
|
|
196
|
+
const tree = value[0];
|
|
197
|
+
const inner = value[1];
|
|
198
|
+
if (!Array.isArray(tree) || tree.length !== 1 || !Array.isArray(inner)) {
|
|
199
|
+
throw new Error('Malformed variant tree from library');
|
|
200
|
+
}
|
|
201
|
+
const innerNode = tree[0];
|
|
202
|
+
const innerSignature = signatureFromNode(innerNode);
|
|
203
|
+
return {
|
|
204
|
+
signature: innerSignature,
|
|
205
|
+
value: decodeNode(innerNode, inner[0]),
|
|
206
|
+
};
|
|
207
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export interface RawMessage {
|
|
2
|
+
type?: number;
|
|
3
|
+
path?: string;
|
|
4
|
+
interface?: string;
|
|
5
|
+
member?: string;
|
|
6
|
+
destination?: string;
|
|
7
|
+
sender?: string;
|
|
8
|
+
signature?: string;
|
|
9
|
+
body?: unknown[];
|
|
10
|
+
errorName?: string;
|
|
11
|
+
serial?: number;
|
|
12
|
+
replySerial?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface ReplyContext {
|
|
15
|
+
signature?: string;
|
|
16
|
+
message?: RawMessage;
|
|
17
|
+
}
|
|
18
|
+
export type ReplyCallback = (this: ReplyContext, error: unknown, ...body: unknown[]) => void;
|
|
19
|
+
export interface RawConnection {
|
|
20
|
+
on(event: string, handler: (...args: unknown[]) => void): void;
|
|
21
|
+
once(event: string, handler: (...args: unknown[]) => void): void;
|
|
22
|
+
removeListener(event: string, handler: (...args: unknown[]) => void): void;
|
|
23
|
+
removeAllListeners(event?: string): void;
|
|
24
|
+
listenerCount(event: string): number;
|
|
25
|
+
end(): void;
|
|
26
|
+
}
|
|
27
|
+
export interface RawBus {
|
|
28
|
+
connection: RawConnection;
|
|
29
|
+
invoke(message: RawMessage, callback: ReplyCallback): void;
|
|
30
|
+
addMatch(rule: string): Promise<unknown>;
|
|
31
|
+
removeMatch(rule: string): Promise<unknown>;
|
|
32
|
+
disconnect(): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
export interface CreateClientOptions {
|
|
35
|
+
busAddress?: string;
|
|
36
|
+
socket?: string;
|
|
37
|
+
ReturnLongjs?: boolean;
|
|
38
|
+
direct?: boolean;
|
|
39
|
+
}
|
|
40
|
+
export interface DbusNativeModule {
|
|
41
|
+
createClient(options: CreateClientOptions): RawBus;
|
|
42
|
+
messageType: {
|
|
43
|
+
invalid: number;
|
|
44
|
+
methodCall: number;
|
|
45
|
+
methodReturn: number;
|
|
46
|
+
error: number;
|
|
47
|
+
signal: number;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export declare const messageType: {
|
|
51
|
+
invalid: number;
|
|
52
|
+
methodCall: number;
|
|
53
|
+
methodReturn: number;
|
|
54
|
+
error: number;
|
|
55
|
+
signal: number;
|
|
56
|
+
};
|
|
57
|
+
export declare function createClient(options: CreateClientOptions): RawBus;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Internal typed facade over the `@httptoolkit/dbus-native` CommonJS module.
|
|
2
|
+
//
|
|
3
|
+
// The library ships a `types.d.ts` that covers only a fraction of the surface we use
|
|
4
|
+
// (no `invoke`, `addMatch`, `connection`, or `messageType`), so we describe the exact
|
|
5
|
+
// parts we depend on here and cast once, at this single boundary. NOTHING in this file
|
|
6
|
+
// is re-exported from the package's public entry (`../index.ts`): the raw library types
|
|
7
|
+
// stay quarantined behind the transport seam. See `./README.md` for why this library
|
|
8
|
+
// was chosen and the documented fallback (`@particle/dbus-next`).
|
|
9
|
+
import * as dbusNativeModule from '@httptoolkit/dbus-native';
|
|
10
|
+
// Bun/Node CJS interop: `import *` yields the module namespace whose `default` (when
|
|
11
|
+
// present) is `module.exports`. One cast confines the untyped surface to this line.
|
|
12
|
+
const resolved = (dbusNativeModule.default ??
|
|
13
|
+
dbusNativeModule);
|
|
14
|
+
export const messageType = resolved.messageType;
|
|
15
|
+
export function createClient(options) {
|
|
16
|
+
return resolved.createClient(options);
|
|
17
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare class TransportError extends Error {
|
|
2
|
+
constructor(message: string, options?: ErrorOptions);
|
|
3
|
+
}
|
|
4
|
+
export declare class UnsupportedSignatureError extends TransportError {
|
|
5
|
+
readonly signature: string;
|
|
6
|
+
readonly unsupportedType: string;
|
|
7
|
+
constructor(signature: string, unsupportedType: string);
|
|
8
|
+
}
|
|
9
|
+
export declare class BigIntRequiredError extends TransportError {
|
|
10
|
+
readonly signature: string;
|
|
11
|
+
readonly received: string;
|
|
12
|
+
constructor(signature: string, received: unknown);
|
|
13
|
+
}
|
|
14
|
+
export declare class SixtyFourBitRangeError extends TransportError {
|
|
15
|
+
readonly signature: string;
|
|
16
|
+
readonly value: bigint;
|
|
17
|
+
constructor(signature: string, value: bigint);
|
|
18
|
+
}
|
|
19
|
+
export declare class DisconnectedError extends TransportError {
|
|
20
|
+
constructor(message?: string);
|
|
21
|
+
}
|
|
@@ -3,72 +3,60 @@
|
|
|
3
3
|
// Wire data crossing the transport boundary is never compile-time checked, so every
|
|
4
4
|
// failure mode that a caller (or the A3.x D-Bus backend) must branch on is a real,
|
|
5
5
|
// exported class — never a bare thrown string or a generic Error.
|
|
6
|
-
|
|
7
6
|
export class TransportError extends Error {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
constructor(message, options) {
|
|
8
|
+
super(message, options);
|
|
9
|
+
this.name = 'TransportError';
|
|
10
|
+
}
|
|
12
11
|
}
|
|
13
|
-
|
|
14
12
|
// A D-Bus signature contained a type this transport refuses to handle. The only such
|
|
15
13
|
// type today is `h` (UNIX_FD / file-descriptor passing): the transport never marshals
|
|
16
14
|
// or unmarshals a file descriptor, so encountering `h` in an outgoing call signature,
|
|
17
15
|
// a reply signature, a signal signature, or nested inside a variant throws this rather
|
|
18
16
|
// than silently dropping or coercing the descriptor.
|
|
19
17
|
export class UnsupportedSignatureError extends TransportError {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
this.signature = signature;
|
|
30
|
-
this.unsupportedType = unsupportedType;
|
|
31
|
-
}
|
|
18
|
+
signature;
|
|
19
|
+
unsupportedType;
|
|
20
|
+
constructor(signature, unsupportedType) {
|
|
21
|
+
super(`D-Bus signature "${signature}" contains unsupported type "${unsupportedType}": ` +
|
|
22
|
+
'UNIX_FD / file-descriptor passing is not supported by this transport');
|
|
23
|
+
this.name = 'UnsupportedSignatureError';
|
|
24
|
+
this.signature = signature;
|
|
25
|
+
this.unsupportedType = unsupportedType;
|
|
26
|
+
}
|
|
32
27
|
}
|
|
33
|
-
|
|
34
28
|
// A 64-bit field (`x` INT64 / `t` UINT64) was handed a JavaScript `number` on encode.
|
|
35
29
|
// A `number` cannot carry the full 64-bit range without silent precision loss above
|
|
36
30
|
// 2^53, so the transport requires a `bigint` for these fields and refuses `number`
|
|
37
31
|
// loudly instead of corrupting the value on the wire.
|
|
38
32
|
export class BigIntRequiredError extends TransportError {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
this.signature = signature;
|
|
49
|
-
this.received = typeof received;
|
|
50
|
-
}
|
|
33
|
+
signature;
|
|
34
|
+
received;
|
|
35
|
+
constructor(signature, received) {
|
|
36
|
+
super(`D-Bus 64-bit field "${signature}" requires a bigint, received ${typeof received} ` +
|
|
37
|
+
`(${String(received)}): a JS number silently loses precision above 2^53`);
|
|
38
|
+
this.name = 'BigIntRequiredError';
|
|
39
|
+
this.signature = signature;
|
|
40
|
+
this.received = typeof received;
|
|
41
|
+
}
|
|
51
42
|
}
|
|
52
|
-
|
|
53
43
|
// A 64-bit value was outside the range representable by its signed/unsigned field.
|
|
54
44
|
export class SixtyFourBitRangeError extends TransportError {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
45
|
+
signature;
|
|
46
|
+
value;
|
|
47
|
+
constructor(signature, value) {
|
|
48
|
+
super(`Value ${value} is out of range for 64-bit D-Bus field "${signature}"`);
|
|
49
|
+
this.name = 'SixtyFourBitRangeError';
|
|
50
|
+
this.signature = signature;
|
|
51
|
+
this.value = value;
|
|
52
|
+
}
|
|
64
53
|
}
|
|
65
|
-
|
|
66
54
|
// The bus connection dropped (or was never established) while a method call was
|
|
67
55
|
// in-flight or pending. The call rejects with this instead of hanging forever; the
|
|
68
56
|
// transport's own reconnect loop keeps running independently.
|
|
69
57
|
export class DisconnectedError extends TransportError {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
58
|
+
constructor(message = 'D-Bus connection is not established') {
|
|
59
|
+
super(message);
|
|
60
|
+
this.name = 'DisconnectedError';
|
|
61
|
+
}
|
|
74
62
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { BigIntRequiredError, DisconnectedError, SixtyFourBitRangeError, TransportError, UnsupportedSignatureError, } from './errors.js';
|
|
2
|
+
export { createDbusTransport } from './transport.js';
|
|
3
|
+
export type { DbusTransport, DbusTransportOptions, DbusValue, DbusVariant, MethodCall, MethodReply, ReconnectOptions, SignalEvent, SignalListener, SignalSpec, Subscription, TransportEvent, } from './types.js';
|
|
4
|
+
export { isVariant, variant } from './types.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Public surface of the D-Bus transport seam.
|
|
2
|
+
//
|
|
3
|
+
// This is the ONLY module the rest of `@ceralive/modem-control` (and the A3.x D-Bus
|
|
4
|
+
// backend) imports from `./transport`. Every type here is the transport's own — no
|
|
5
|
+
// `@httptoolkit/dbus-native` type is re-exported, so swapping the underlying library
|
|
6
|
+
// (documented fallback: `@particle/dbus-next`) is invisible to callers. See README.md.
|
|
7
|
+
export { BigIntRequiredError, DisconnectedError, SixtyFourBitRangeError, TransportError, UnsupportedSignatureError, } from './errors.js';
|
|
8
|
+
export { createDbusTransport } from './transport.js';
|
|
9
|
+
export { isVariant, variant } from './types.js';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type RawBus, type RawMessage } from './dbus-native.js';
|
|
2
|
+
import type { SignalListener, SignalSpec, Subscription } from './types.js';
|
|
3
|
+
export interface SignalHost {
|
|
4
|
+
currentBus(): RawBus | null;
|
|
5
|
+
isConnected(): boolean;
|
|
6
|
+
emitError(error: unknown): void;
|
|
7
|
+
}
|
|
8
|
+
export declare class SignalRegistry {
|
|
9
|
+
#private;
|
|
10
|
+
constructor(host: SignalHost);
|
|
11
|
+
subscribe(spec: SignalSpec, listener: SignalListener): Promise<Subscription>;
|
|
12
|
+
count(): number;
|
|
13
|
+
reissueRules(bus: RawBus): Promise<void>;
|
|
14
|
+
dispatch(message: RawMessage): void;
|
|
15
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// Signal subscription and match-rule tracking for the D-Bus transport seam.
|
|
2
|
+
//
|
|
3
|
+
// The transport's single persistent `message` listener fans out here: `dispatch` walks the
|
|
4
|
+
// live subscription registry and delivers each decoded signal to every matching listener.
|
|
5
|
+
// Match rules are refcounted so N subscriptions sharing a rule add/remove it on the bus
|
|
6
|
+
// exactly once, and `reissueRules` re-adds every live rule after a reconnect — so
|
|
7
|
+
// subscribing/unsubscribing never grows the connection's listener count (the 100-cycle
|
|
8
|
+
// leak check depends on this).
|
|
9
|
+
import { decodeBody } from './codec.js';
|
|
10
|
+
import { messageType } from './dbus-native.js';
|
|
11
|
+
function buildMatchRule(spec) {
|
|
12
|
+
const parts = [`type='signal'`, `interface='${spec.interface}'`, `member='${spec.member}'`];
|
|
13
|
+
if (spec.path !== undefined) {
|
|
14
|
+
parts.push(`path='${spec.path}'`);
|
|
15
|
+
}
|
|
16
|
+
if (spec.sender !== undefined) {
|
|
17
|
+
parts.push(`sender='${spec.sender}'`);
|
|
18
|
+
}
|
|
19
|
+
return parts.join(',');
|
|
20
|
+
}
|
|
21
|
+
function signalMatches(spec, message) {
|
|
22
|
+
if (message.interface !== spec.interface || message.member !== spec.member) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
if (spec.path !== undefined && message.path !== spec.path) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
if (spec.sender !== undefined && message.sender !== spec.sender) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
export class SignalRegistry {
|
|
34
|
+
#host;
|
|
35
|
+
#subscriptions = new Map();
|
|
36
|
+
#matchRuleRefcount = new Map();
|
|
37
|
+
#nextSubId = 1;
|
|
38
|
+
constructor(host) {
|
|
39
|
+
this.#host = host;
|
|
40
|
+
}
|
|
41
|
+
async subscribe(spec, listener) {
|
|
42
|
+
const rule = buildMatchRule(spec);
|
|
43
|
+
const id = this.#nextSubId++;
|
|
44
|
+
this.#subscriptions.set(id, { id, spec, listener, rule });
|
|
45
|
+
await this.#addMatchRule(rule);
|
|
46
|
+
let removed = false;
|
|
47
|
+
return {
|
|
48
|
+
unsubscribe: async () => {
|
|
49
|
+
if (removed) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
removed = true;
|
|
53
|
+
this.#subscriptions.delete(id);
|
|
54
|
+
await this.#removeMatchRule(rule);
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
count() {
|
|
59
|
+
return this.#subscriptions.size;
|
|
60
|
+
}
|
|
61
|
+
// Re-issue every live match rule against a freshly established bus so a reconnect
|
|
62
|
+
// resubscribes transparently. Called by `#establish` before it swaps in the new bus, so
|
|
63
|
+
// the fresh bus is passed in explicitly rather than read from the host.
|
|
64
|
+
async reissueRules(bus) {
|
|
65
|
+
for (const rule of this.#matchRuleRefcount.keys()) {
|
|
66
|
+
await bus.addMatch(rule);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
dispatch(message) {
|
|
70
|
+
if (message.type !== messageType.signal) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
for (const record of this.#subscriptions.values()) {
|
|
74
|
+
if (!signalMatches(record.spec, message)) {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
let body;
|
|
78
|
+
try {
|
|
79
|
+
const signature = message.signature ?? '';
|
|
80
|
+
body = signature.length > 0 ? decodeBody(signature, message.body ?? []) : [];
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
this.#host.emitError(error);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const event = {
|
|
87
|
+
path: message.path ?? '',
|
|
88
|
+
interface: message.interface ?? '',
|
|
89
|
+
member: message.member ?? '',
|
|
90
|
+
sender: message.sender,
|
|
91
|
+
signature: message.signature ?? '',
|
|
92
|
+
body,
|
|
93
|
+
};
|
|
94
|
+
try {
|
|
95
|
+
record.listener(event);
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
this.#host.emitError(error);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
async #addMatchRule(rule) {
|
|
103
|
+
const current = this.#matchRuleRefcount.get(rule) ?? 0;
|
|
104
|
+
this.#matchRuleRefcount.set(rule, current + 1);
|
|
105
|
+
const bus = this.#host.currentBus();
|
|
106
|
+
if (current === 0 && this.#host.isConnected() && bus) {
|
|
107
|
+
await bus.addMatch(rule);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
async #removeMatchRule(rule) {
|
|
111
|
+
const current = this.#matchRuleRefcount.get(rule) ?? 0;
|
|
112
|
+
if (current <= 1) {
|
|
113
|
+
this.#matchRuleRefcount.delete(rule);
|
|
114
|
+
const bus = this.#host.currentBus();
|
|
115
|
+
if (current === 1 && this.#host.isConnected() && bus) {
|
|
116
|
+
await bus.removeMatch(rule).catch(() => undefined);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
this.#matchRuleRefcount.set(rule, current - 1);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface SignatureNode {
|
|
2
|
+
readonly type: string;
|
|
3
|
+
readonly child: readonly SignatureNode[];
|
|
4
|
+
}
|
|
5
|
+
export declare function assertSupportedSignature(signature: string): void;
|
|
6
|
+
export declare function parseSignature(signature: string): SignatureNode[];
|
|
7
|
+
export declare function signatureFromNode(node: SignatureNode): string;
|