@camstack/addon-admin-ui 1.2.41 → 1.2.43

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 (94) hide show
  1. package/dist/assets/{AddLocationWizard-BMebDBIA.js → AddLocationWizard-Dnf9kZ5r.js} +1 -1
  2. package/dist/assets/{AddonCollectionPage-r3MDTb2U.js → AddonCollectionPage-DobriBmU.js} +1 -1
  3. package/dist/assets/{Addons-IfPdw6C0.js → Addons-B7taoyzE.js} +1 -1
  4. package/dist/assets/{AdminTabs-BN9bq2Fe.js → AdminTabs-hau3Oq2w.js} +1 -1
  5. package/dist/assets/{AiProfiles-CaU_0vCA.js → AiProfiles-BXg8urSU.js} +1 -1
  6. package/dist/assets/{BrokerForm-pR2D2FEG.js → BrokerForm-DMRliUMR.js} +1 -1
  7. package/dist/assets/{Build-BDfaId30.js → Build-D-MV56ph.js} +1 -1
  8. package/dist/assets/{Capabilities-DCYvjUOV.js → Capabilities-Dfs9TBXT.js} +1 -1
  9. package/dist/assets/{CapabilityBadges-BrUlJxX7.js → CapabilityBadges-rZaJpe-r.js} +1 -1
  10. package/dist/assets/{Cluster-sFTMFphL.js → Cluster-CNaEmKuP.js} +1 -1
  11. package/dist/assets/{ClusterRecordingTab-CKyWHM6i.js → ClusterRecordingTab-D_qfLxjW.js} +1 -1
  12. package/dist/assets/{Dashboard-jy4FWmQo.js → Dashboard-D2Km6w0o.js} +1 -1
  13. package/dist/assets/{Data-BE3nk7HN.js → Data-BcTXKJLE.js} +1 -1
  14. package/dist/assets/{DetectionIntelligence-CVACMVUz.js → DetectionIntelligence-BHXgW4p9.js} +1 -1
  15. package/dist/assets/DeviceAggregateSection-G3C6ALwH.js +1 -0
  16. package/dist/assets/{DeviceDetail-BN3ud2_r.js → DeviceDetail-D6EZRLKt.js} +1 -1
  17. package/dist/assets/{Devices-Xl3xsFW3.js → Devices-C5gDyb40.js} +1 -1
  18. package/dist/assets/{EmbedPlayerPage-NqPvTLKU.js → EmbedPlayerPage-CIk_V5wD.js} +1 -1
  19. package/dist/assets/{Events-Bq860K-k.js → Events-C4Xo_6D0.js} +1 -1
  20. package/dist/assets/{FormBuilder-BrkB_Vuo.js → FormBuilder-BvzfIJkp.js} +1 -1
  21. package/dist/assets/{Identity-5C3sPUQm.js → Identity-Dk8VwQOh.js} +1 -1
  22. package/dist/assets/{IntegrationDetail-TpeJiSq_.js → IntegrationDetail-CtERtnf6.js} +1 -1
  23. package/dist/assets/{Integrations-D7OMgnaW.js → Integrations-DOf8izlg.js} +1 -1
  24. package/dist/assets/{Integrations-DrSyeMHp.js → Integrations-DSCtpUFM.js} +1 -1
  25. package/dist/assets/{Logs-q6ZBX4ns.js → Logs-Lzg2Qt7o.js} +1 -1
  26. package/dist/assets/{MotionZonesSettings-blj7QMMa.js → MotionZonesSettings-hjCnvBIA.js} +1 -1
  27. package/dist/assets/{MyAccess-DtT6FFYG.js → MyAccess-BhHaCPdH.js} +1 -1
  28. package/dist/assets/{Network-Z4oREGTh.js → Network-MeAb64sZ.js} +1 -1
  29. package/dist/assets/{NodeAddonsSettingsPanel-DiBk6Fev.js → NodeAddonsSettingsPanel-bV2Ww4Wh.js} +1 -1
  30. package/dist/assets/{NodeInferenceDevices-LHaBTVxw.js → NodeInferenceDevices-Cc_NZqWJ.js} +1 -1
  31. package/dist/assets/{Notifications-BZLN5NsG.js → Notifications-BR6cx8Hv.js} +1 -1
  32. package/dist/assets/{Pipeline-Dt2CTPL5.js → Pipeline-DFQ87Avn.js} +1 -1
  33. package/dist/assets/{Plates-z1VqssCX.js → Plates-B4O-rVMN.js} +1 -1
  34. package/dist/assets/{PrivacyMaskSettings-BgOgmwS6.js → PrivacyMaskSettings-CbY9zqSC.js} +1 -1
  35. package/dist/assets/{ProviderIcon-D3veqTWe.js → ProviderIcon-DZYXOFvU.js} +1 -1
  36. package/dist/assets/{Recordings-T7rllaEV.js → Recordings-Dme3V8Jw.js} +1 -1
  37. package/dist/assets/{ScanNetworkModal-o5xFugCK.js → ScanNetworkModal-BuBzYCPB.js} +1 -1
  38. package/dist/assets/{Settings-cx5X8HsR.js → Settings-C9ZmiEfV.js} +1 -1
  39. package/dist/assets/{Showroom-CDrrv1TO.js → Showroom-KslYrDnf.js} +1 -1
  40. package/dist/assets/{Terminal-D5vXOWT2.js → Terminal-BX4vePXd.js} +1 -1
  41. package/dist/assets/{_virtual_mf-localSharedImportMap___mfe_internal__admin_ui_host-BlAsWS9v.js → _virtual_mf-localSharedImportMap___mfe_internal__admin_ui_host-BXg-GMD0.js} +1 -1
  42. package/dist/assets/{boxes-rTzctUbU.js → boxes-CJQaMCB6.js} +1 -1
  43. package/dist/assets/{build-cluster-graph-Coy_GdHx.js → build-cluster-graph-D82pulL4.js} +1 -1
  44. package/dist/assets/circle-check-big-CqEcBAg-.js +1 -0
  45. package/dist/assets/{circle-x-D0bWsIts.js → circle-x-B9ZqB4Ao.js} +1 -1
  46. package/dist/assets/clock-B84Yi90W.js +1 -0
  47. package/dist/assets/{copy-DySg8B81.js → copy-BWulDE8Q.js} +1 -1
  48. package/dist/assets/{debounced-invalidate-D5kf3uDk.js → debounced-invalidate-BaeAhcuT.js} +1 -1
  49. package/dist/assets/{dist-CKpGYpil.js → dist-CPBY6nE_.js} +1 -1
  50. package/dist/assets/dist-s9fu7Ygs.js +345 -0
  51. package/dist/assets/{download-CF59Q1Zv.js → download-BGQRs_h_.js} +1 -1
  52. package/dist/assets/{face-bbox-DOKrhacR.js → face-bbox-DdUR76Az.js} +1 -1
  53. package/dist/assets/{hostInit-D_uPN66O.js → hostInit-exDg1REQ.js} +1 -1
  54. package/dist/assets/index-DercvAak.js +4 -0
  55. package/dist/assets/{key-round-DFR8IuYK.js → key-round-B8s_k3cE.js} +1 -1
  56. package/dist/assets/{mf-entry-bootstrap-0-803942ee.js → mf-entry-bootstrap-0-d503194b.js} +2 -2
  57. package/dist/assets/{pencil-Chd1XFvs.js → pencil-BmeMW4-K.js} +1 -1
  58. package/dist/assets/play-D1I3FH7D.js +1 -0
  59. package/dist/assets/{player-overlays-RSBJ34HJ.js → player-overlays-DT4na72S.js} +1 -1
  60. package/dist/assets/plus-CKS7XgbR.js +1 -0
  61. package/dist/assets/{radio-CN2vqo__.js → radio-CiY55fJZ.js} +1 -1
  62. package/dist/assets/{refresh-cw-Blid1l_b.js → refresh-cw-CirIJMRS.js} +1 -1
  63. package/dist/assets/remoteEntry-CCaURJJa.js +1 -0
  64. package/dist/assets/rotate-ccw-CmYyLdLk.js +1 -0
  65. package/dist/assets/rotate-cw-BOfSACBG.js +1 -0
  66. package/dist/assets/search-t5MLCJxU.js +1 -0
  67. package/dist/assets/{send-CInmQKy1.js → send-DAsOvh5L.js} +1 -1
  68. package/dist/assets/{server-CsrhvWyN.js → server-BxU2t63R.js} +1 -1
  69. package/dist/assets/{square-check-big-rQeR1daL.js → square-check-big-Y_w5k-fR.js} +1 -1
  70. package/dist/assets/square-p36JRKMx.js +1 -0
  71. package/dist/assets/src-BVb5fdJF.js +345 -0
  72. package/dist/assets/{src-RAEsAO7u.js → src-BWPt2sEf.js} +4 -4
  73. package/dist/assets/{undo-2-DWkYdwKX.js → undo-2-OojIYRG7.js} +1 -1
  74. package/dist/assets/{upload-COgXhe8s.js → upload-DOKu1lJx.js} +1 -1
  75. package/dist/assets/{useEventInvalidation-CINRwQED.js → useEventInvalidation-Dit4mCQp.js} +1 -1
  76. package/dist/assets/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__admin_ui_host__remoteEntry-_hash_-DZ3nAi20.js → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__admin_ui_host__remoteEntry-_hash_-BRWueNnj.js} +2 -2
  77. package/dist/assets/{wifi-CRvgXCEx.js → wifi-NFfDvxQg.js} +1 -1
  78. package/dist/assets/{zap-Bz2U4Gui.js → zap-BVgWWqtR.js} +1 -1
  79. package/dist/index.html +5 -5
  80. package/dist/server/addon.js +175 -12
  81. package/package.json +1 -1
  82. package/dist/assets/DeviceAggregateSection-BGpxGM1L.js +0 -1
  83. package/dist/assets/circle-check-big-CRchJGb3.js +0 -1
  84. package/dist/assets/clock-C25GXwpo.js +0 -1
  85. package/dist/assets/dist-DBLYemqE.js +0 -345
  86. package/dist/assets/index-D1Lv9nnm.js +0 -4
  87. package/dist/assets/play-BS6NorXW.js +0 -1
  88. package/dist/assets/plus-CLA9DCBk.js +0 -1
  89. package/dist/assets/remoteEntry-C9ffs8f0.js +0 -1
  90. package/dist/assets/rotate-ccw-twRh3mwW.js +0 -1
  91. package/dist/assets/rotate-cw-CMVPPwHk.js +0 -1
  92. package/dist/assets/search-BmreiQPf.js +0 -1
  93. package/dist/assets/square-BAUrJi-y.js +0 -1
  94. package/dist/assets/src-CrugYgqk.js +0 -345
@@ -1,6 +1,6 @@
1
1
  import path from "node:path";
2
2
  import { fileURLToPath } from "node:url";
3
- //#region ../types/dist/event-category-41fKf-q9.mjs
3
+ //#region ../types/dist/event-category-Cv9dO26A.mjs
4
4
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
5
5
  EventCategory["SystemBoot"] = "system.boot";
6
6
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -16,6 +16,13 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
16
16
  */
17
17
  EventCategory["SystemRestartCompleted"] = "system.restart-completed";
18
18
  /**
19
+ * A newer addon or server-root package version was found by the
20
+ * authoritative registry check. Emitted once per
21
+ * `(target, packageName, currentVersion, latestVersion)` transition; repeated
22
+ * polling of the same result is deduplicated by the checker.
23
+ */
24
+ EventCategory["UpdateAvailable"] = "update.available";
25
+ /**
19
26
  * Readiness transition for a capability provider. Every producer emits
20
27
  * this event on `onInitialize` completion, `onDestroy`, and
21
28
  * `$node.reconnect`; every consumer that needs to gate on a cross-process
@@ -13754,8 +13761,35 @@ var NcDeliverySchema = _enum([
13754
13761
  "immediate",
13755
13762
  "track-end",
13756
13763
  "device-event",
13757
- "package-event"
13764
+ "package-event",
13765
+ "system-event"
13766
+ ]);
13767
+ /**
13768
+ * Stable Notification Center vocabulary over infrastructure/liveness events.
13769
+ * Bus categories are normalized into these intent-level kinds so rules do not
13770
+ * depend on a provider's raw event name or payload shape.
13771
+ */
13772
+ var NcSystemEventKindSchema = _enum([
13773
+ "camera-online",
13774
+ "camera-offline",
13775
+ "stream-online",
13776
+ "stream-offline",
13777
+ "node-online",
13778
+ "node-offline",
13779
+ "addon-update-available",
13780
+ "server-update-available"
13758
13781
  ]);
13782
+ /**
13783
+ * One coherent system-event condition. `kinds` is the required opt-in safety
13784
+ * gate; the remaining lists are optional narrowing filters relevant to the
13785
+ * selected kinds.
13786
+ */
13787
+ var NcSystemEventConditionSchema = object({
13788
+ kinds: array(NcSystemEventKindSchema).min(1),
13789
+ deviceIds: array(number().int()).min(1).optional(),
13790
+ nodeIds: array(string().min(1)).min(1).optional(),
13791
+ packageNames: array(string().min(1)).min(1).optional()
13792
+ });
13759
13793
  /** Weekly schedule — OR of windows; absence on the rule = always active. */
13760
13794
  var NcScheduleSchema = object({
13761
13795
  windows: array(object({
@@ -14060,6 +14094,8 @@ var NcConditionsSchema = object({
14060
14094
  "picked-up",
14061
14095
  "both"
14062
14096
  ]).optional(),
14097
+ /** Infrastructure/liveness/update event matcher (`system-event` delivery). */
14098
+ systemEvent: NcSystemEventConditionSchema.optional(),
14063
14099
  /**
14064
14100
  * PERSONAL-RULE custom zones (viewer-drawn). Inline normalized polygons
14065
14101
  * (MaskShape vocabulary). A record passes when its bbox overlaps ANY
@@ -14279,7 +14315,8 @@ var NcTestResultSchema = object({
14279
14315
  "object-event",
14280
14316
  "track",
14281
14317
  "device-event",
14282
- "package-event"
14318
+ "package-event",
14319
+ "system-event"
14283
14320
  ]),
14284
14321
  deviceId: number(),
14285
14322
  timestamp: number(),
@@ -14301,7 +14338,8 @@ var NcConditionDescriptorSchema = object({
14301
14338
  "schedule",
14302
14339
  "device",
14303
14340
  "package",
14304
- "occupancy"
14341
+ "occupancy",
14342
+ "system"
14305
14343
  ]),
14306
14344
  label: string(),
14307
14345
  /** Editor widget the UI renders — never hardcode per-condition forms. */
@@ -14319,7 +14357,8 @@ var NcConditionDescriptorSchema = object({
14319
14357
  "crossingSelect",
14320
14358
  "polygonDraw",
14321
14359
  "occupancy",
14322
- "deviceState"
14360
+ "deviceState",
14361
+ "systemEvent"
14323
14362
  ]),
14324
14363
  operator: _enum([
14325
14364
  "in",
@@ -14378,7 +14417,8 @@ var NcHistoryRecordKindSchema = _enum([
14378
14417
  "object-event",
14379
14418
  "track-end",
14380
14419
  "device-event",
14381
- "package-event"
14420
+ "package-event",
14421
+ "system-event"
14382
14422
  ]);
14383
14423
  /** Subject summary frozen on the row at fire time (survives rule/record edits). */
14384
14424
  var NcHistorySubjectSchema = object({
@@ -14386,7 +14426,14 @@ var NcHistorySubjectSchema = object({
14386
14426
  label: string().optional(),
14387
14427
  confidence: number().optional(),
14388
14428
  zones: array(string()),
14389
- timestamp: number()
14429
+ timestamp: number(),
14430
+ systemEvent: object({
14431
+ kind: NcSystemEventKindSchema,
14432
+ subject: string(),
14433
+ title: string(),
14434
+ body: string(),
14435
+ data: record(string(), unknown())
14436
+ }).optional()
14390
14437
  });
14391
14438
  /**
14392
14439
  * One delivery-history row. This is a read-only VIEW over the durable
@@ -14746,6 +14793,76 @@ object({
14746
14793
  * Each provider returns a static descriptor; the core enumerates them
14747
14794
  * to validate the `integration=` query param and resolve the consent
14748
14795
  * label + the scopes baked into the issued token.
14796
+ *
14797
+ * ## Declaring one
14798
+ *
14799
+ * An OAuth client is integration-specific knowledge — who the client is, what
14800
+ * it may ask for, where it may be sent — so it is declared by the ADDON that
14801
+ * owns the integration, never by the kernel and never as a branch inside
14802
+ * `oauth2-routes.ts` ([D101](../../../../docs/decisions/adr-0101.md)). Three
14803
+ * steps, no others:
14804
+ *
14805
+ * 1. Add `{ "name": "oauth-integration" }` to the addon's `camstack.addons[]`
14806
+ * manifest entry. This is also what tells the hub, at addon-LOAD time, that
14807
+ * a descriptor is owed — see "the boot window" below.
14808
+ * 2. Return a provider from `onInitialize()`:
14809
+ *
14810
+ * ```ts
14811
+ * const provider: IOauthIntegrationProvider = {
14812
+ * getDescriptor: async () => ({
14813
+ * integrationId: 'my-thing', // the `integration=` query param
14814
+ * displayName: 'My Thing',
14815
+ * requestedScopes: [ … ], // see below
14816
+ * allowedRedirectPrefixes: ['https://callback.example/'],
14817
+ * }),
14818
+ * }
14819
+ * return [{ capability: oauthIntegrationCapability, provider }]
14820
+ * ```
14821
+ *
14822
+ * The descriptor must be **static** — it is read on the authorize path, so
14823
+ * never put an await on network or disk behind it, and never register it
14824
+ * behind one either (a provider is registered only once `onInitialize`
14825
+ * RETURNS, so anything awaited before the return delays linking).
14826
+ * 3. Nothing else. There is no allow-list to join, no id to register with the
14827
+ * core, and no per-integration branch anywhere: `/api/oauth2/authorize` and
14828
+ * `/api/oauth2/integrations` are built from this collection alone.
14829
+ *
14830
+ * **Scopes. `requestedScopes` has exactly ONE meaning: what the integration
14831
+ * NEEDS to function.** Not a blast radius, not a conservative
14832
+ * under-declaration, not a description of some other path the addon happens to
14833
+ * have. Derive it from what the client actually calls **with this token** —
14834
+ * every tRPC path against `METHOD_ACCESS_MAP`, plus an `addon:` grant for every
14835
+ * addon HTTP route it posts to — and write the call that justifies each entry
14836
+ * next to it. Two integrations once used this field to mean two different
14837
+ * things; the operator ruled there is one meaning, and any third integration
14838
+ * inherits it (2026-08-09).
14839
+ *
14840
+ * This is not documentation, it is the ENFORCEMENT INPUT. Since
14841
+ * [D103](../../../../docs/decisions/adr-0103.md) the `/addon/:addonId/*` gate
14842
+ * checks an integration token's grant before letting it reach an
14843
+ * `access: 'authenticated'` route, so an **under-declaration is an integration
14844
+ * that stops working** — a missing `addon:` entry means `403 Token scope
14845
+ * mismatch` on every control the client tries to actuate. Widen the descriptor
14846
+ * honestly rather than weakening a check to make a route pass.
14847
+ *
14848
+ * Prefer a narrow `capability:` scope to a `category:` one unless the client
14849
+ * genuinely needs a whole family; a category scope grants every future member
14850
+ * of that category too. `category:system [create]` has been rejected once and
14851
+ * should stay rejected: it hands `addons.installPackage` to an integration.
14852
+ *
14853
+ * Calls the ADDON itself makes over `ctx.api` run as the addon and are not
14854
+ * scope-checked, so they are not what this field describes — but reaching the
14855
+ * addon's route in the first place IS, and that is the entry to declare.
14856
+ *
14857
+ * **The boot window.** An addon registers its provider after its runner forks
14858
+ * and initialises, so between hub start and that moment this collection is
14859
+ * incomplete and an `integrationId` can be legitimately absent. The core does
14860
+ * not wait, poll or cache around this ([D3](../../../../docs/decisions/adr-0003.md)):
14861
+ * it compares the manifest declarers against the registered providers and
14862
+ * answers `503 temporarily_unavailable` (with `Retry-After` and the pending
14863
+ * addon ids) instead of `400 unknown integration`, and reports
14864
+ * `complete: false` on `GET /api/oauth2/integrations`. A client should retry
14865
+ * while the list is incomplete rather than conclude the hub cannot do OAuth.
14749
14866
  */
14750
14867
  var OauthIntegrationDescriptorSchema = object({
14751
14868
  /** Stable id used as the `integration=` query param, e.g. 'export-alexa'. */
@@ -14776,7 +14893,30 @@ var OauthIntegrationDescriptorSchema = object({
14776
14893
  * present, /api/oauth2/authorize bakes THIS into the code instead of the
14777
14894
  * hub-global `publicHubUrl()`, so a forked exporter addon (which can't set
14778
14895
  * the hub's env) drives the claim that its cloud Lambda routes back on. */
14779
- hubUrl: string().optional()
14896
+ hubUrl: string().optional(),
14897
+ /**
14898
+ * How long a REFRESH token issued for this integration lives — seconds, or
14899
+ * `'never'` for a token minted with no `exp` claim at all. Omit to keep the
14900
+ * 30-day default, which is what every link used before this field existed.
14901
+ *
14902
+ * Declared here for the same reason `requestedScopes` is: the integration
14903
+ * knows what it needs. Amazon's account linking and a Home Assistant config
14904
+ * entry are both meant to survive indefinitely, and re-linking is a manual
14905
+ * user action, so a 30-day expiry silently unlinks a working integration.
14906
+ *
14907
+ * **The security posture, stated so it is owned deliberately.** A refresh
14908
+ * token that never expires is permanent access if it leaks. What bounds it is
14909
+ * revocation, not time: `oauthRefresh` re-reads the session on every use and
14910
+ * returns `null` once `revokedAt` is set, as does `oauthVerifyAccessToken`.
14911
+ * The one gap is the ACCESS token — it is a plain signed JWT that nothing
14912
+ * re-checks against the session on the `/trpc` and `/addon/*` paths, so
14913
+ * revoking a link takes effect there only after its remaining hour. That hour
14914
+ * is why the access TTL is not configurable.
14915
+ *
14916
+ * The value is baked into the authorization code at `/authorize` and travels
14917
+ * on the tokens, so editing this field changes FUTURE links only.
14918
+ */
14919
+ refreshTokenTtlSec: union([number().int().positive(), literal("never")]).optional()
14780
14920
  });
14781
14921
  method(_void(), OauthIntegrationDescriptorSchema);
14782
14922
  /**
@@ -17880,11 +18020,29 @@ var SsoBridgeClaimsSchema = object({
17880
18020
  codeChallenge: string().optional(),
17881
18021
  /** OAuth session registry id — set on `oauth-access`/`oauth-refresh`
17882
18022
  * tokens so the verify path can check the session is not revoked. */
17883
- sessionId: string().optional()
18023
+ sessionId: string().optional(),
18024
+ /**
18025
+ * The refresh lifetime this LINK was created with, in seconds, or `'never'`.
18026
+ * Baked into the code at `/authorize` from the integration's descriptor and
18027
+ * carried forward so `oauthRefresh` re-mints with the same lifetime. It rides
18028
+ * on the token rather than being re-read from the descriptor on purpose:
18029
+ * editing a descriptor must not retroactively extend or shorten a link the
18030
+ * operator already consented to.
18031
+ */
18032
+ refreshTtl: union([number().int().positive(), literal("never")]).optional()
17884
18033
  });
17885
18034
  method(object({
17886
18035
  claims: SsoBridgeClaimsSchema,
17887
- ttlSec: number().int().positive().optional()
18036
+ /**
18037
+ * Seconds, or `'never'` for a token minted with NO `exp` claim.
18038
+ *
18039
+ * `'never'` is a literal rather than `undefined`/`0` because omitting
18040
+ * this field already means "the 5-minute SSO hand-off default", and
18041
+ * `jwt.sign` THROWS on `{ expiresIn: undefined }` — a "no expiry" that
18042
+ * went through the numeric path would fail at mint time and break
18043
+ * linking rather than produce an eternal token.
18044
+ */
18045
+ ttlSec: union([number().int().positive(), literal("never")]).optional()
17888
18046
  }), object({ token: string() })), method(object({ token: string() }), SsoBridgeClaimsSchema.nullable());
17889
18047
  var ProviderListEntrySchema = discriminatedUnion("shouldSaveDiskSpace", [object({
17890
18048
  providerId: string().min(1),
@@ -23620,7 +23778,12 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
23620
23778
  hubUrl: string(),
23621
23779
  /** PKCE (RFC 7636) S256 challenge. Baked into the signed code; a code
23622
23780
  * that carries one can ONLY be exchanged with the matching verifier. */
23623
- codeChallenge: string().optional()
23781
+ codeChallenge: string().optional(),
23782
+ /** The integration's declared refresh lifetime — seconds, or `'never'`.
23783
+ * From `OauthIntegrationDescriptor.refreshTokenTtlSec`. Baked into the
23784
+ * code so the link carries its own lifetime; omit for the 30-day
23785
+ * default. */
23786
+ refreshTtlSec: union([number().int().positive(), literal("never")]).optional()
23624
23787
  }), object({ code: string() }), {
23625
23788
  kind: "mutation",
23626
23789
  access: "create"
@@ -29700,7 +29863,7 @@ var AdminUIAddon = class extends BaseAddon {
29700
29863
  capability: adminUiCapability,
29701
29864
  provider: {
29702
29865
  getStaticDir: async () => ({ staticDir: resolveAdminUiDistDir() }),
29703
- getVersion: async () => ({ version: "1.2.41" })
29866
+ getVersion: async () => ({ version: "1.2.43" })
29704
29867
  }
29705
29868
  }];
29706
29869
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-admin-ui",
3
- "version": "1.2.41",
3
+ "version": "1.2.43",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Admin UI — Vite frontend build and server-side addon",
@@ -1 +0,0 @@
1
- import{An as e,Kn as t,Ma as n,ja as r,kn as i,qn as a,zn as o}from"./src-RAEsAO7u.js";import{I as s,K as c,Q as l,S as u,W as d,o as f,q as p,x as m}from"./_virtual_mf___mfe_internal__admin_ui_host__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-DTufy7Ue.js";import{X as h}from"./src-CrugYgqk.js";import{t as g}from"./FormBuilder-BrkB_Vuo.js";import{S as _,r as v}from"./index-D1Lv9nnm.js";import{n as y,r as b,t as x}from"./SchemaTabBar-BrF8ZUiR.js";import{t as S}from"./StableTabPanel-p16epZGa.js";l();function C({schema:e,values:t,pendingKeys:n,onChange:r,onAction:i,onSave:a,onDiscard:o,disabled:s,activeSubTab:c,onSubTabChange:l,flattenTabs:f=!1,deviceId:h}){let _=e.tabs??[],v=d(()=>{let t=new Map;for(let n of e.sections){let e=n.tab??`general`,r=t.get(e)??[];r.push(n),t.set(e,r)}return t},[e.sections]),b=new Set(_.map(e=>e.id)),C=[..._,...[...v.keys()].filter(e=>!b.has(e)).map(e=>({id:e,label:e,icon:`wrench`,order:100}))],w=C[0]?.id??`general`,[T,E]=p(w),D=l!==void 0,O=new Set(C.map(e=>e.id)),k=D?c&&O.has(c)?c:w:O.has(T)?T:w,A=e=>{D?l(e):E(e)},j=v.get(k)??[],M={sections:j.length<=1?j.length===1?[{...j[0],title:``}]:j:j.every(e=>!e.title)?[{...j[0],title:``,fields:j.flatMap(e=>e.fields)}]:j},N=m(y,{pendingCount:n.length,onSave:()=>a(n),onDiscard:()=>o(n),saving:s});if(f||C.length<=1)return u(`div`,{className:`flex flex-col gap-3`,children:[m(g,{schema:e,values:t,onChange:r,onAction:i,disabled:s,deviceId:h}),N]});let P=new Map,F=new Map;for(let[e,t]of v){P.set(e,t.length);let r=new Set,i=e=>{for(let t of e)if(`key`in t&&typeof t.key==`string`&&r.add(t.key),t.type===`group`)i(t.fields);else if(t.type===`sub-tabs`)for(let e of t.tabs)i(e.fields)};for(let e of t)i(e.fields);let a=n.filter(e=>r.has(e)).length;a>0&&F.set(e,a)}return u(`div`,{className:`flex flex-col gap-3`,children:[m(x,{tabs:C.map(e=>({id:e.id,label:e.label})),activeId:k,onChange:A,countByTab:P,pendingByTab:F}),m(S,{tabKey:k,children:m(g,{schema:M,values:t,onChange:r,onAction:i,disabled:s,deviceId:h})}),N]})}var w=`device-export`,T=`export`,E=`Export`;function D(e){return e.type===`separator`||e.type===`info`||e.type===`object-array`||e.type===`widget`||e.type===`addon-action-button`||e.type===`device-action-button`?!1:e.type===`group`?e.fields.some(D):e.type===`sub-tabs`?e.tabs.some(e=>e.fields.some(D)):e.writerCapName===w}function O(e){return e.fields.some(D)}l();function k(e,t){return t&&t===`admin`?e:!0}function A(e){if(!e)return null;let t={sections:[...e.sections].toSorted((e,t)=>{let n=e.tab??`general`,r=t.tab??`general`;return n===r?O(e)&&O(t)?e.id.localeCompare(t.id):(e.order??0)-(t.order??0):n.localeCompare(r)})};return e.tabs?{...t,tabs:e.tabs}:t}function j(e){return e.type===`separator`||e.type===`info`||e.type===`button`||e.type===`widget`||e.type===`addon-action-button`||e.type===`device-action-button`}function M(e){return e.key}function N(e){if(!j(e))return e.value}function P(e){return j(e)?null:e}function F(e,t){for(let n of e)if(t(n),n.type===`group`)F(n.fields,t);else if(n.type===`sub-tabs`)for(let e of n.tabs)F(e.fields,t)}function I(e){if(!e)return{};let t={};for(let n of e.sections)F(n.fields,e=>{let n=M(e);n!==null&&(t[n]=N(e))});return t}function L(e,t){if(!e)return null;let n=null;for(let r of e.sections)if(F(r.fields,e=>{if(n!==null||M(e)!==t)return;let r=P(e);r&&r.writerCapName&&r.writerAddonId&&(n={capName:r.writerCapName,addonId:r.writerAddonId})}),n!==null)break;return n}function R(e){return{...e,fields:e.fields.map(z)}}function z(e){return e.type===`separator`||e.type===`info`||e.type===`button`||e.type===`object-array`?e:{...e,readonlyField:!0}}function B(e,t){return e&&{...e,sections:e.sections.map(e=>({...e,fields:e.fields.map(e=>{let n=P(e);return n?k(t,n.minRole)?e:z(e):e})}))}}function V({deviceId:l,sectionFilter:p,activeSubTab:g,onSubTabChange:y,flattenSubTabs:x,subTabGrouping:S}){let w=f(),{user:T}=v(),E=T?.isAdmin===!0,D=c(!1),{data:k,isLoading:j}=e({deviceId:l},{refetchInterval:()=>D.current?!1:2500,enabled:Number.isFinite(l)}),{data:M}=i({deviceId:l},{enabled:Number.isFinite(l)}),N=k?.settings??null,P=k?.live??null,F=d(()=>{if(!N&&!P)return null;let e=N?.sections??[],t=(P?.sections??[]).map(R),n=[...e,...t],r=p?n.filter(p):n.filter(e=>e.location!==`top-tab`&&!O(e));if(r.length===0)return null;if(S){let e=r.map(e=>({...e,tab:S.groupOf(e)})),t=new Set(e.map(e=>e.tab)),n=S.tabs.filter(e=>t.has(e.id));return n.length>0?{tabs:n,sections:e}:{sections:e}}let i=new Set;for(let e of r)i.add(e.tab??`general`);let a=[...N?.tabs??[],...(P?.tabs??[]).filter(e=>!(N?.tabs??[]).some(t=>t.id===e.id))].filter(e=>i.has(e.id));return a.length>0?{tabs:a,sections:r}:{sections:r}},[N,P,p,S]),z=d(()=>A(F),[F]),V=d(()=>B(z,E),[z,E]),H=d(()=>I(V),[V]),U=n(),W=r(),G=t(),K=o(),q=a({onSuccess:()=>{w.invalidateQueries({queryKey:[[`deviceManager`,`getDeviceAggregate`]]})}}),J={isPending:q.isPending,mutate:e=>{q.mutate({deviceId:l,changes:[...e]})}},Y=b({schema:V,serverValues:H,onImmediateSave:s(e=>{let t=Object.entries(e).map(([e,t])=>{let n=L(V,e);return n?{writerCapName:n.capName,writerAddonId:n.addonId,key:e,value:t}:null}).filter(e=>e!==null);t.length>0&&J.mutate(t)},[V,J]),onDeferredSave:s(e=>{let t=Object.entries(e).map(([e,t])=>{let n=L(V,e);return n?{writerCapName:n.capName,writerAddonId:n.addonId,key:e,value:t}:null}).filter(e=>e!==null);t.length>0&&J.mutate(t)},[V,J])}),{values:X,pendingKeys:Z,handleChange:Q,handleSave:$,handleDiscard:ee}=Y;if(D.current=Y.editingPaused,j)return u(`div`,{className:`flex items-center justify-center py-12 text-foreground-subtle`,children:[m(_,{className:`h-4 w-4 animate-spin mr-2`}),m(`span`,{className:`text-xs`,children:`Loading device aggregate…`})]});if(!V||V.sections.length===0)return m(`div`,{className:`text-xs text-foreground-subtle italic py-4 text-center`,children:`No aggregate contributions for this device.`});async function te(e,t,n){if(e===`regenerate-rtsp-token`){let e=[`rtspUrl:`,`regenerateToken:`].find(e=>t.startsWith(e));if(!e)throw Error(`regenerate-rtsp-token: unrecognised key "${t}" (expected "rtspUrl:<streamId>" or "regenerateToken:<streamId>")`);let n=t.slice(e.length);if(!n)throw Error(`regenerate-rtsp-token: key "${t}" has no streamId after prefix`);let r=h(l,n);await U.mutateAsync({brokerId:r}),w.invalidateQueries({queryKey:[[`deviceManager`,`getDeviceAggregate`]]});return}if(e===`test-probe`){if(!M)return{status:`error`,error:`Device metadata not loaded yet`};try{return await G.mutateAsync({addonId:M.addonId,type:M.type,key:t,value:n})}catch(e){return{status:`error`,error:e instanceof Error?e.message:String(e)}}}if(e===`refresh-probe`){if(!t.startsWith(`probedInfo:`))throw Error(`refresh-probe: unrecognised key "${t}" (expected "probedInfo:<streamId>")`);let e=t.slice(11);if(!e)throw Error(`refresh-probe: key "${t}" has no streamId after prefix`);let n=h(l,e),r=await W.mutateAsync({brokerId:n});return w.invalidateQueries({queryKey:[[`deviceManager`,`getDeviceAggregate`]]}),r}if(e===`device-custom-action`){let e=await K.mutateAsync({deviceId:l,action:t,input:n});return w.invalidateQueries({queryKey:[[`deviceManager`,`getDeviceAggregate`]]}),e}throw Error(`[device-aggregate] unknown action "${e}"`)}return m(C,{schema:V,values:X,pendingKeys:Z,onChange:Q,onAction:te,onSave:$,onDiscard:ee,disabled:J.isPending,activeSubTab:g,onSubTabChange:y,flattenTabs:x,deviceId:l})}export{O as i,T as n,E as r,V as t};
@@ -1 +0,0 @@
1
- import{G as e}from"./index-D1Lv9nnm.js";var t=e(`circle-check-big`,[[`path`,{d:`M21.801 10A10 10 0 1 1 17 3.335`,key:`yps3ct`}],[`path`,{d:`m9 11 3 3L22 4`,key:`1pflzl`}]]);export{t};
@@ -1 +0,0 @@
1
- import{G as e}from"./index-D1Lv9nnm.js";var t=e(`clock`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`polyline`,{points:`12 6 12 12 16 14`,key:`68esgv`}]]);export{t};