doover-js 0.10.1 → 0.11.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.
@@ -3,6 +3,12 @@ import type { Alarm, CreateAlarmRequest, PatchAlarmRequest } from "../types/open
3
3
  export declare class AlarmsApi {
4
4
  private readonly rest;
5
5
  constructor(rest: RestClient);
6
+ /** Every alarm on every channel of an agent the caller can see. */
7
+ listAgentAlarms(agentId: string): Promise<Alarm[]>;
8
+ listAgentAlarms(identifier: {
9
+ agentId: string;
10
+ }): Promise<Alarm[]>;
11
+ private _listAgentAlarms;
6
12
  listAlarms(agentId: string, channelName: string): Promise<Alarm[]>;
7
13
  listAlarms(identifier: {
8
14
  agentId: string;
@@ -6,6 +6,13 @@ class AlarmsApi {
6
6
  constructor(rest) {
7
7
  this.rest = rest;
8
8
  }
9
+ listAgentAlarms(...args) {
10
+ const { agentId } = (0, _args_1.resolveAgentArgs)(args);
11
+ return this._listAgentAlarms(agentId);
12
+ }
13
+ _listAgentAlarms(agentId) {
14
+ return this.rest.get(`/agents/${agentId}/alarms`);
15
+ }
9
16
  listAlarms(...args) {
10
17
  const { agentId, channelName } = (0, _args_1.resolveChannelArgs)(args);
11
18
  return this._listAlarms(agentId, channelName);
@@ -1,5 +1,5 @@
1
1
  import type { RestClient } from "../http/rest-client";
2
- import type { CreateEndpointRequest, CreateNotificationSubscriptionRequest, NotificationDataResponse, NotificationEndpoint, NotificationEndpointsResponse, NotificationSubscribersResponse, NotificationSubscriptionCreateResponse, NotificationSubscriptionsResponse, UpdateEndpointRequest, UpdateMeWebPushEndpointRequest, UpdateNotificationSubscriptionRequest } from "../types/openapi";
2
+ import type { CreateEndpointRequest, CreateNotificationSubscriptionRequest, NotificationDataResponse, NotificationEndpoint, NotificationEndpointSummariesResponse, NotificationEndpointsResponse, NotificationSubscribersResponse, NotificationSubscriptionCreateResponse, NotificationSubscriptionsResponse, UpdateEndpointRequest, UpdateMeWebPushEndpointRequest, UpdateNotificationSubscriptionRequest } from "../types/openapi";
3
3
  export declare class NotificationsApi {
4
4
  private readonly rest;
5
5
  constructor(rest: RestClient);
@@ -13,6 +13,16 @@ export declare class NotificationsApi {
13
13
  agentId: string;
14
14
  }, name?: string): Promise<NotificationEndpointsResponse>;
15
15
  private _getAgentNotificationEndpoints;
16
+ /**
17
+ * Delivery readiness for each endpoint, without addresses or credentials.
18
+ * Readable with either notification-read or manage-subscriptions rights, so
19
+ * a delegated subscription manager can list endpoints it can't otherwise see.
20
+ */
21
+ getAgentNotificationEndpointSummaries(agentId: string): Promise<NotificationEndpointSummariesResponse>;
22
+ getAgentNotificationEndpointSummaries(identifier: {
23
+ agentId: string;
24
+ }): Promise<NotificationEndpointSummariesResponse>;
25
+ private _getAgentNotificationEndpointSummaries;
16
26
  createNotificationEndpoint(agentId: string, body: CreateEndpointRequest): Promise<NotificationEndpoint>;
17
27
  createNotificationEndpoint(identifier: {
18
28
  agentId: string;
@@ -48,6 +58,15 @@ export declare class NotificationsApi {
48
58
  agentId: string;
49
59
  }, subscribed_to?: string): Promise<NotificationSubscriptionsResponse>;
50
60
  private _getAgentDefaultNotificationSubscriptions;
61
+ /**
62
+ * Update every default subscription this subscriber holds on `subscribedTo`
63
+ * at once. Omitted fields keep their current value.
64
+ */
65
+ updateDefaultNotificationSubscription(agentId: string, subscribedTo: string, body: UpdateNotificationSubscriptionRequest): Promise<unknown>;
66
+ updateDefaultNotificationSubscription(identifier: {
67
+ agentId: string;
68
+ }, subscribedTo: string, body: UpdateNotificationSubscriptionRequest): Promise<unknown>;
69
+ private _updateDefaultNotificationSubscription;
51
70
  deleteDefaultNotificationSubscription(agentId: string, subscribedTo: string): Promise<unknown>;
52
71
  deleteDefaultNotificationSubscription(identifier: {
53
72
  agentId: string;
@@ -23,6 +23,13 @@ class NotificationsApi {
23
23
  _getAgentNotificationEndpoints(agentId, name) {
24
24
  return this.rest.get(`/agents/${agentId}/notifications/endpoints`, { name });
25
25
  }
26
+ getAgentNotificationEndpointSummaries(...args) {
27
+ const { agentId } = (0, _args_1.resolveAgentArgs)(args);
28
+ return this._getAgentNotificationEndpointSummaries(agentId);
29
+ }
30
+ _getAgentNotificationEndpointSummaries(agentId) {
31
+ return this.rest.get(`/agents/${agentId}/notifications/endpoints/summary`);
32
+ }
26
33
  createNotificationEndpoint(...args) {
27
34
  if (typeof args[0] === "string") {
28
35
  return this._createNotificationEndpoint(args[0], args[1]);
@@ -93,6 +100,16 @@ class NotificationsApi {
93
100
  _getAgentDefaultNotificationSubscriptions(agentId, subscribed_to) {
94
101
  return this.rest.get(`/agents/${agentId}/notifications/subscriptions/default`, { subscribed_to });
95
102
  }
103
+ updateDefaultNotificationSubscription(...args) {
104
+ if (typeof args[0] === "string") {
105
+ return this._updateDefaultNotificationSubscription(args[0], args[1], args[2]);
106
+ }
107
+ const id = args[0];
108
+ return this._updateDefaultNotificationSubscription(id.agentId, args[1], args[2]);
109
+ }
110
+ _updateDefaultNotificationSubscription(agentId, subscribedTo, body) {
111
+ return this.rest.patch(`/agents/${agentId}/notifications/subscriptions/default/${subscribedTo}`, body);
112
+ }
96
113
  deleteDefaultNotificationSubscription(...args) {
97
114
  if (typeof args[0] === "string") {
98
115
  return this._deleteDefaultNotificationSubscription(args[0], args[1]);
@@ -9,6 +9,7 @@ const multiplex_gateway_1 = require("./multiplex-gateway");
9
9
  /** "<subclient>.<method>" → spec. Drives the generic non-core facades. */
10
10
  const NONCORE_METHODS = {
11
11
  // alarms
12
+ "alarms.listAgentAlarms": { cap: "alarms.read", kind: "read-fanout-first", agentScoped: true },
12
13
  "alarms.listAlarms": { cap: "alarms.read", kind: "read-fanout-first", agentScoped: true },
13
14
  "alarms.getAlarm": { cap: "alarms.read", kind: "read-fanout-first", agentScoped: true },
14
15
  "alarms.createAlarm": { cap: "alarms.write", kind: "write-route", agentScoped: true },
@@ -25,6 +26,7 @@ const NONCORE_METHODS = {
25
26
  // notifications (reads)
26
27
  "notifications.getAgentNotifications": { cap: "notifications.read", kind: "read-fanout-first", agentScoped: true },
27
28
  "notifications.getAgentNotificationEndpoints": { cap: "notifications.read", kind: "read-fanout-first", agentScoped: true },
29
+ "notifications.getAgentNotificationEndpointSummaries": { cap: "notifications.read", kind: "read-fanout-first", agentScoped: true },
28
30
  "notifications.getAgentNotificationSubscriptions": { cap: "notifications.read", kind: "read-fanout-first", agentScoped: true },
29
31
  "notifications.getAgentDefaultNotificationSubscriptions": { cap: "notifications.read", kind: "read-fanout-first", agentScoped: true },
30
32
  "notifications.getAgentNotificationSubscribers": { cap: "notifications.read", kind: "read-fanout-first", agentScoped: true },
@@ -35,6 +37,7 @@ const NONCORE_METHODS = {
35
37
  "notifications.deleteNotificationEndpoint": { cap: "notifications.write", kind: "write-route", agentScoped: true },
36
38
  "notifications.testNotificationEndpoint": { cap: "notifications.write", kind: "write-route", agentScoped: true },
37
39
  "notifications.createNotificationSubscription": { cap: "notifications.write", kind: "write-route", agentScoped: true },
40
+ "notifications.updateDefaultNotificationSubscription": { cap: "notifications.write", kind: "write-route", agentScoped: true },
38
41
  "notifications.deleteDefaultNotificationSubscription": { cap: "notifications.write", kind: "write-route", agentScoped: true },
39
42
  "notifications.updateNotificationSubscription": { cap: "notifications.write", kind: "write-route", agentScoped: true },
40
43
  "notifications.deleteNotificationSubscription": { cap: "notifications.write", kind: "write-route", agentScoped: true },
@@ -290,10 +290,23 @@ function setupRest(responseFactory) {
290
290
  await alarms.createAlarm("a1", "c1", { name: "a", key: "x", operator: "gt", value: 1 });
291
291
  await alarms.getAlarm("a1", "c1", "alarm");
292
292
  await alarms.putAlarm("a1", "c1", "alarm", { name: "a", key: "x", operator: "gt", value: 1 });
293
+ // A rate alarm states its condition with rate_threshold/rate_window_ms and
294
+ // must leave `value` unset.
295
+ await alarms.createAlarm("a1", "c1", {
296
+ name: "rising",
297
+ key: "level",
298
+ operator: "gt",
299
+ rate_threshold: 0.05,
300
+ rate_window_ms: 600000,
301
+ topic_name: "level-rising",
302
+ notification_policy: "opt-in",
303
+ messages: { alarm: { notify: true, text: "Level rising fast" } },
304
+ });
293
305
  await alarms.patchAlarm("a1", "c1", "alarm", { enabled: false });
306
+ await alarms.patchAlarm("a1", "c1", "alarm", { messages: { ok: { notify: false } } });
294
307
  await alarms.deleteAlarm("a1", "c1", "alarm");
295
308
  (0, chai_1.expect)(await aggregateBlob.text()).to.equal("agg");
296
- (0, chai_1.expect)(fetchMock.callCount).to.equal(10);
309
+ (0, chai_1.expect)(fetchMock.callCount).to.equal(12);
297
310
  });
298
311
  (0, mocha_1.it)("covers connections and notifications methods", async () => {
299
312
  const { rest, fetchMock } = setupRest(() => (0, helpers_1.createJsonResponse)({ subscriptions: [], endpoints: [], subscribers: [] }));
@@ -312,6 +325,7 @@ function setupRest(responseFactory) {
312
325
  (0, chai_1.expect)(syncCall.args[1].method).to.equal("POST");
313
326
  await notifications.getAgentNotifications("a1");
314
327
  await notifications.getAgentNotificationEndpoints("a1", "browser");
328
+ await notifications.getAgentNotificationEndpointSummaries("a1");
315
329
  await notifications.createNotificationEndpoint("a1", {
316
330
  name: "browser",
317
331
  type: 3,
@@ -328,6 +342,11 @@ function setupRest(responseFactory) {
328
342
  topic_filter: ["*"],
329
343
  });
330
344
  await notifications.getAgentDefaultNotificationSubscriptions("a1", "a2");
345
+ await notifications.updateDefaultNotificationSubscription("a1", "a2", {
346
+ severity: 5,
347
+ topic_filter: ["^dev/alarms/default/[^/]+/triggered$"],
348
+ topic_filter_mode: "regex",
349
+ });
331
350
  await notifications.deleteDefaultNotificationSubscription("a1", "a2");
332
351
  await notifications.updateNotificationSubscription("a1", "s1", { severity: 4 });
333
352
  await notifications.deleteNotificationSubscription("a1", "s1");
@@ -340,7 +359,15 @@ function setupRest(responseFactory) {
340
359
  expires_at: 1,
341
360
  });
342
361
  await notifications.getWebPushPublicKey();
343
- (0, chai_1.expect)(fetchMock.callCount).to.equal(21);
362
+ const summaryCall = fetchMock
363
+ .getCalls()
364
+ .find((call) => call.args[0].endsWith("/agents/a1/notifications/endpoints/summary"));
365
+ (0, chai_1.expect)(summaryCall).to.not.equal(undefined);
366
+ const defaultPatch = fetchMock
367
+ .getCalls()
368
+ .find((call) => call.args[0].endsWith("/agents/a1/notifications/subscriptions/default/a2") && call.args[1].method === "PATCH");
369
+ (0, chai_1.expect)(defaultPatch).to.not.equal(undefined);
370
+ (0, chai_1.expect)(fetchMock.callCount).to.equal(23);
344
371
  });
345
372
  (0, mocha_1.it)("covers permissions, processors, and turn methods", async () => {
346
373
  const { rest, fetchMock } = setupRest(() => (0, helpers_1.createJsonResponse)({ db: { agent_id: "a1", is_superuser: false, resources: [] } }));
@@ -48,6 +48,10 @@ export interface Alarm {
48
48
  id: string;
49
49
  name: string;
50
50
  description: string;
51
+ /** Channel the alarm lives on — set on every alarm the REST API returns. */
52
+ channel_name?: string;
53
+ topic_name?: string;
54
+ notification_policy?: "default" | "opt-in";
51
55
  enabled: boolean;
52
56
  key: string;
53
57
  operator: AlarmOperator;
@@ -56,8 +60,29 @@ export interface Alarm {
56
60
  expiry_mins: number | null;
57
61
  entered_state_ts: number;
58
62
  alarm_pending_ms: number | null;
63
+ rate_threshold?: number | null;
64
+ rate_window_ms?: number | null;
65
+ rate_baseline_value?: number | null;
66
+ rate_baseline_ts?: number | null;
67
+ messages?: AlarmMessages | null;
59
68
  __source?: SourceProvenance;
60
69
  }
70
+ /**
71
+ * Per-transition notification override. `notify` and `text` are independent:
72
+ * turning notifications off keeps whatever wording was set, and `text: null`
73
+ * means "use the auto-generated message".
74
+ */
75
+ export interface AlarmStateMessage {
76
+ notify?: boolean;
77
+ text?: string | null;
78
+ }
79
+ /** Notification overrides keyed by the state being entered. */
80
+ export interface AlarmMessages {
81
+ alarm?: AlarmStateMessage;
82
+ ok?: AlarmStateMessage;
83
+ pending?: AlarmStateMessage;
84
+ no_data?: AlarmStateMessage;
85
+ }
61
86
  export type AlarmOperator = "eq" | "ge" | "gt" | "le" | "lt";
62
87
  export type AlarmState = "NoData" | "OK" | "Alarm" | "AlarmPending";
63
88
  export interface ConnectionSubscription {
@@ -84,6 +109,12 @@ export interface ConnectionDetails {
84
109
  subscriptions: ConnectionSubscription[];
85
110
  __source?: SourceProvenance;
86
111
  }
112
+ /**
113
+ * How a subscription's `topic_filter` entries are matched. `exact` is literal
114
+ * (and the server's default when the field is absent); `regex` matches each
115
+ * expression against the whole canonical topic. Entries are ORed either way.
116
+ */
117
+ export type NotificationTopicFilterMode = "exact" | "regex";
87
118
  export interface NotificationSubscriptionEndpoint {
88
119
  id: string;
89
120
  name: string;
@@ -95,6 +126,7 @@ export interface NotificationSubscription {
95
126
  subscribed_to: string;
96
127
  severity: number;
97
128
  topic_filter: string[];
129
+ topic_filter_mode: NotificationTopicFilterMode;
98
130
  endpoints: NotificationSubscriptionEndpoint[];
99
131
  __source?: SourceProvenance;
100
132
  }
@@ -108,6 +140,21 @@ export interface NotificationEndpoint {
108
140
  default: boolean;
109
141
  __source?: SourceProvenance;
110
142
  }
143
+ /**
144
+ * Delivery readiness for an endpoint, without its destination address or
145
+ * `extra_data` — the one endpoint listing a delegated subscription manager is
146
+ * allowed to see.
147
+ */
148
+ export interface NotificationEndpointSummary {
149
+ id: string;
150
+ type: number;
151
+ priority: number | null;
152
+ name: string;
153
+ display_name: string | null;
154
+ default: boolean;
155
+ ready: boolean;
156
+ __source?: SourceProvenance;
157
+ }
111
158
  export interface ResourcePermission {
112
159
  permission_id: string;
113
160
  permission: string;
@@ -1,5 +1,5 @@
1
- import type { AgentAggregate, AgentPermission, Alarm, Aggregate, Channel, ConnectionDetails, ConnectionSubscription, ConnectionSubscriptionLog, DataSeries, MessageStructure, NotificationEndpoint, NotificationSubscription, ResourcePermission, TurnCredential } from "./common";
2
- export type { AgentAggregate, AgentPermission, Alarm, Aggregate, Channel, ConnectionDetails, ConnectionSubscription, ConnectionSubscriptionLog, DataSeries, MessageStructure, NotificationEndpoint, NotificationSubscription, ResourcePermission, TurnCredential, };
1
+ import type { AgentAggregate, AgentPermission, Alarm, AlarmMessages, AlarmStateMessage, Aggregate, Channel, ConnectionDetails, ConnectionSubscription, ConnectionSubscriptionLog, DataSeries, MessageStructure, NotificationEndpoint, NotificationEndpointSummary, NotificationSubscription, NotificationTopicFilterMode, ResourcePermission, TurnCredential } from "./common";
2
+ export type { AgentAggregate, AgentPermission, Alarm, AlarmMessages, AlarmStateMessage, Aggregate, Channel, ConnectionDetails, ConnectionSubscription, ConnectionSubscriptionLog, DataSeries, MessageStructure, NotificationEndpoint, NotificationEndpointSummary, NotificationSubscription, NotificationTopicFilterMode, ResourcePermission, TurnCredential, };
3
3
  export interface BatchMessagesResponse {
4
4
  results: MessageStructure[];
5
5
  count: number;
@@ -41,6 +41,9 @@ export interface NotificationDataResponse {
41
41
  export interface NotificationEndpointsResponse {
42
42
  endpoints: NotificationEndpoint[];
43
43
  }
44
+ export interface NotificationEndpointSummariesResponse {
45
+ endpoints: NotificationEndpointSummary[];
46
+ }
44
47
  export interface NotificationSubscriptionsResponse {
45
48
  subscriptions: NotificationSubscription[];
46
49
  }
@@ -101,10 +104,30 @@ export interface CreateAlarmRequest {
101
104
  enabled?: boolean;
102
105
  key: string;
103
106
  operator: Alarm["operator"];
104
- value: unknown;
107
+ /**
108
+ * The threshold to compare against. Required for a threshold alarm, and
109
+ * must be left out entirely for a rate alarm — which states its condition
110
+ * with `rate_threshold` instead.
111
+ */
112
+ value?: unknown;
105
113
  expiry_mins?: number | null;
106
114
  alarm_pending_ms?: number | null;
107
- }
115
+ /** Stable slug used in notification topics. Derived from `name` if absent. */
116
+ topic_name?: string;
117
+ notification_policy?: Alarm["notification_policy"];
118
+ /**
119
+ * Units per second, judged over at least `rate_window_ms`. Setting the pair
120
+ * makes this a rate-of-change alarm; they must be set together.
121
+ */
122
+ rate_threshold?: number | null;
123
+ rate_window_ms?: number | null;
124
+ messages?: AlarmMessages | null;
125
+ }
126
+ /**
127
+ * Every field is optional; each is merged rather than replaced. `messages` is
128
+ * merged state by state and field by field, so `{messages: {ok: {notify:
129
+ * false}}}` leaves the stored text alone, and an explicit `null` clears.
130
+ */
108
131
  export interface PatchAlarmRequest extends Partial<CreateAlarmRequest> {
109
132
  }
110
133
  export interface CreateEndpointRequest {
@@ -124,10 +147,13 @@ export interface CreateNotificationSubscriptionRequest {
124
147
  endpoint_id?: string | null;
125
148
  severity: number;
126
149
  topic_filter: string[];
150
+ /** Defaults to `exact` server-side when absent. */
151
+ topic_filter_mode?: NotificationTopicFilterMode;
127
152
  }
128
153
  export interface UpdateNotificationSubscriptionRequest {
129
154
  severity?: number;
130
155
  topic_filter?: string[];
156
+ topic_filter_mode?: NotificationTopicFilterMode;
131
157
  }
132
158
  export interface UpdateMeWebPushEndpointRequest {
133
159
  old_endpoint: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "doover-js",
3
- "version": "0.10.1",
3
+ "version": "0.11.0",
4
4
  "description": "TypeScript client for Doover.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",