@camstack/addon-advanced-notifier 1.1.12 → 1.1.14
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/dist/addon.js +278 -36
- package/dist/addon.mjs +278 -36
- package/dist/index.js +20 -12
- package/dist/index.mjs +20 -12
- package/package.json +1 -1
package/dist/addon.js
CHANGED
|
@@ -4632,7 +4632,7 @@ function _instanceof(cls, params = {}) {
|
|
|
4632
4632
|
return inst;
|
|
4633
4633
|
}
|
|
4634
4634
|
//#endregion
|
|
4635
|
-
//#region ../types/dist/sleep-
|
|
4635
|
+
//#region ../types/dist/sleep-MHm--th-.mjs
|
|
4636
4636
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
4637
4637
|
EventCategory["SystemBoot"] = "system.boot";
|
|
4638
4638
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -5894,6 +5894,7 @@ var CamStreamKindSchema = _enum([
|
|
|
5894
5894
|
"pull-rtsp",
|
|
5895
5895
|
"pull-rtmp",
|
|
5896
5896
|
"pull-http",
|
|
5897
|
+
"pull-flv",
|
|
5897
5898
|
"pull-rfc4571",
|
|
5898
5899
|
"push-annexb",
|
|
5899
5900
|
"derived"
|
|
@@ -7037,7 +7038,21 @@ var StorageLocationDeclarationSchema = object({
|
|
|
7037
7038
|
* slots (e.g. `recordingsLow` → `recordings`) so operators only need to
|
|
7038
7039
|
* configure the primary location.
|
|
7039
7040
|
*/
|
|
7040
|
-
defaultsTo: string().optional()
|
|
7041
|
+
defaultsTo: string().optional(),
|
|
7042
|
+
/**
|
|
7043
|
+
* Which node root the seeded `<id>:default` instance is placed under on a
|
|
7044
|
+
* FRESH install:
|
|
7045
|
+
* - `'data'` (default) — the node's data dir (`CAMSTACK_DATA` / boot dir),
|
|
7046
|
+
* the appData volume. Right for small/durable data (backups, logs, models).
|
|
7047
|
+
* - `'media'` — the dedicated media volume (`CAMSTACK_MEDIA_ROOT`) when that
|
|
7048
|
+
* env is set, else falls back to the data root. Right for bulky, hot media
|
|
7049
|
+
* (recordings, event media) that should stay off the appData disk.
|
|
7050
|
+
*
|
|
7051
|
+
* Only affects the seeded default's `basePath`; operators can repoint any
|
|
7052
|
+
* location afterwards, and a `defaultsTo` slot inherits its parent's root
|
|
7053
|
+
* regardless of this field. Absent (the common case) is treated as `'data'`.
|
|
7054
|
+
*/
|
|
7055
|
+
defaultRoot: _enum(["data", "media"]).optional()
|
|
7041
7056
|
});
|
|
7042
7057
|
var DecoderStatsSchema = object({
|
|
7043
7058
|
inputFps: number(),
|
|
@@ -7898,6 +7913,10 @@ var RtspRestreamEntrySchema = object({
|
|
|
7898
7913
|
var BrokerRtspClientSchema = object({
|
|
7899
7914
|
sessionId: string(),
|
|
7900
7915
|
remoteAddr: string(),
|
|
7916
|
+
/** Client `User-Agent` (e.g. `recorder` for the recorder's RTSP pull), or
|
|
7917
|
+
* null/absent when the client sent none. Lets the UI label a consumer by
|
|
7918
|
+
* purpose. Optional so a client built against an older schema stays valid. */
|
|
7919
|
+
userAgent: string().nullish(),
|
|
7901
7920
|
playing: boolean(),
|
|
7902
7921
|
muted: boolean(),
|
|
7903
7922
|
connectedAt: number(),
|
|
@@ -13199,7 +13218,7 @@ var AddBrokerInputSchema = object({
|
|
|
13199
13218
|
});
|
|
13200
13219
|
var AddBrokerResultSchema = object({ id: string() });
|
|
13201
13220
|
var IdInputSchema = object({ id: string() });
|
|
13202
|
-
var TestResultSchema = discriminatedUnion("ok", [object({
|
|
13221
|
+
var TestResultSchema$1 = discriminatedUnion("ok", [object({
|
|
13203
13222
|
ok: literal(true),
|
|
13204
13223
|
latencyMs: number()
|
|
13205
13224
|
}), object({
|
|
@@ -13222,7 +13241,7 @@ var StatusSchema = object({
|
|
|
13222
13241
|
brokerCount: number(),
|
|
13223
13242
|
embeddedRunning: boolean()
|
|
13224
13243
|
});
|
|
13225
|
-
method(_void(), array(BrokerInfoSchema)), method(IdInputSchema, BrokerConnectionDetailsSchema), method(AddBrokerInputSchema, AddBrokerResultSchema, { kind: "mutation" }), method(IdInputSchema, _void(), { kind: "mutation" }), method(IdInputSchema, TestResultSchema, { kind: "mutation" }), method(StartEmbeddedInputSchema, StartEmbeddedResultSchema, { kind: "mutation" }), method(IdInputSchema, _void(), { kind: "mutation" }), method(_void(), StatusSchema);
|
|
13244
|
+
method(_void(), array(BrokerInfoSchema)), method(IdInputSchema, BrokerConnectionDetailsSchema), method(AddBrokerInputSchema, AddBrokerResultSchema, { kind: "mutation" }), method(IdInputSchema, _void(), { kind: "mutation" }), method(IdInputSchema, TestResultSchema$1, { kind: "mutation" }), method(StartEmbeddedInputSchema, StartEmbeddedResultSchema, { kind: "mutation" }), method(IdInputSchema, _void(), { kind: "mutation" }), method(_void(), StatusSchema);
|
|
13226
13245
|
var NetworkEndpointSchema = object({
|
|
13227
13246
|
url: string(),
|
|
13228
13247
|
hostname: string(),
|
|
@@ -13256,29 +13275,210 @@ var NetworkEndpointEntrySchema = NetworkEndpointSchema.extend({
|
|
|
13256
13275
|
sourcePort: number().optional()
|
|
13257
13276
|
});
|
|
13258
13277
|
method(_void(), NetworkEndpointSchema, { kind: "mutation" }), method(_void(), _void(), { kind: "mutation" }), method(_void(), NetworkEndpointSchema.nullable()), method(_void(), NetworkAccessStatusSchema), method(_void(), array(NetworkEndpointEntrySchema).readonly());
|
|
13278
|
+
/**
|
|
13279
|
+
* notification-output — canonical, capability-gated notification delivery.
|
|
13280
|
+
*
|
|
13281
|
+
* Apprise-derived model (see
|
|
13282
|
+
* `docs/superpowers/specs/2026-07-03-notification-output-notifier-matrix.md`):
|
|
13283
|
+
* callers emit ONE canonical `Notification`; each provider declares a
|
|
13284
|
+
* per-kind capability descriptor (`TargetKind`), and the pure degrade
|
|
13285
|
+
* engine (`@camstack/types` `prepareNotification`) transcodes / degrades the
|
|
13286
|
+
* message to what the kind supports — callers never special-case a service.
|
|
13287
|
+
*
|
|
13288
|
+
* DESIGN DECISIONS (locked):
|
|
13289
|
+
* - Target CRUD lives on THIS cap (`upsertTarget` / `deleteTarget` /
|
|
13290
|
+
* `setTargetEnabled`), each provider persisting via the `settings-store`
|
|
13291
|
+
* cap. Rationale: the admin UI needs one uniform surface across the
|
|
13292
|
+
* notifiers addon AND the HA addon; the addon-`globalSettingsSchema`-array
|
|
13293
|
+
* alternative would fork the UI per addon and cannot host the
|
|
13294
|
+
* discovery→adopt flow.
|
|
13295
|
+
* - `listTargetKinds` / `listTargets` / `discoverTargets` return arrays →
|
|
13296
|
+
* the generated cap-mount auto-`concatCollection`-fans them across every
|
|
13297
|
+
* registered provider (notifiers addon + HA addon) so one catalog is
|
|
13298
|
+
* routable. `send` / `testTarget` / CRUD route to ONE provider by the
|
|
13299
|
+
* `addonId` the generated collection router extracts from the call input.
|
|
13300
|
+
* - `Attachment.bytes` is `Uint8Array`. Transport-safe: superjson (the tRPC
|
|
13301
|
+
* transformer) + UDS MsgPack both round-trip typed arrays — already used by
|
|
13302
|
+
* `storage` / `storage-provider` / `recording` caps over the same path. No
|
|
13303
|
+
* base64 fallback needed.
|
|
13304
|
+
*
|
|
13305
|
+
* TODO (deferred, closed-set change — separate decision): add
|
|
13306
|
+
* `providerKind: 'notify'` so notification providers surface on the unified
|
|
13307
|
+
* admin "Integrations" page.
|
|
13308
|
+
*/
|
|
13309
|
+
/**
|
|
13310
|
+
* Zentik-derived typed-media enum — the superset across every kind. Each
|
|
13311
|
+
* adapter picks what it supports and the degrade engine filters the rest.
|
|
13312
|
+
*/
|
|
13313
|
+
var AttachmentMediaTypeSchema = _enum([
|
|
13314
|
+
"image",
|
|
13315
|
+
"video",
|
|
13316
|
+
"gif",
|
|
13317
|
+
"audio",
|
|
13318
|
+
"icon"
|
|
13319
|
+
]);
|
|
13320
|
+
/**
|
|
13321
|
+
* A single attachment. Exactly one of `url` (remote source, most adapters
|
|
13322
|
+
* prefer this) or `bytes` (inline source; required for Pushover-style
|
|
13323
|
+
* bytes-only kinds) MUST be present — the degrade engine expresses a
|
|
13324
|
+
* url→bytes fetch as a `needsFetch` directive the adapter executes.
|
|
13325
|
+
*/
|
|
13326
|
+
var AttachmentSchema = object({
|
|
13327
|
+
mediaType: AttachmentMediaTypeSchema,
|
|
13328
|
+
url: string().optional(),
|
|
13329
|
+
bytes: _instanceof(Uint8Array).optional(),
|
|
13330
|
+
mime: string().optional(),
|
|
13331
|
+
name: string().optional()
|
|
13332
|
+
}).refine((a) => a.url !== void 0 || a.bytes !== void 0, { message: "Attachment requires either `url` or `bytes`" });
|
|
13333
|
+
var NotificationFormatSchema = _enum([
|
|
13334
|
+
"text",
|
|
13335
|
+
"markdown",
|
|
13336
|
+
"html"
|
|
13337
|
+
]);
|
|
13338
|
+
/** A single tap-through action button. */
|
|
13339
|
+
var NotificationActionSchema = object({
|
|
13340
|
+
id: string(),
|
|
13341
|
+
label: string(),
|
|
13342
|
+
url: string().optional()
|
|
13343
|
+
});
|
|
13344
|
+
/**
|
|
13345
|
+
* The canonical notification. `body` is the only hard field (Apprise model).
|
|
13346
|
+
* `priority` is a 5-level ORDINAL (1=lowest … 3=normal(default) … 5=urgent),
|
|
13347
|
+
* NOT a fixed severity enum — each kind declares its own `caps.levels` and
|
|
13348
|
+
* the adapter maps this ordinal onto its native level. `level?` is an
|
|
13349
|
+
* optional kind-native level id (`emergency`, `silent`, …) that overrides
|
|
13350
|
+
* `priority` for that one target.
|
|
13351
|
+
*/
|
|
13352
|
+
var NotificationSchema = object({
|
|
13353
|
+
body: string(),
|
|
13354
|
+
title: string().optional(),
|
|
13355
|
+
format: NotificationFormatSchema.default("text"),
|
|
13356
|
+
priority: number().int().min(1).max(5).default(3),
|
|
13357
|
+
level: string().optional(),
|
|
13358
|
+
attachments: array(AttachmentSchema).optional(),
|
|
13359
|
+
clickUrl: string().optional(),
|
|
13360
|
+
actions: array(NotificationActionSchema).optional(),
|
|
13361
|
+
sound: string().optional(),
|
|
13362
|
+
ttl: number().optional(),
|
|
13363
|
+
tag: string().optional(),
|
|
13364
|
+
deviceId: number().optional(),
|
|
13365
|
+
eventId: string().optional(),
|
|
13366
|
+
metadata: record(string(), unknown()).optional()
|
|
13367
|
+
});
|
|
13368
|
+
/** One declared native severity/priority level for a kind. */
|
|
13369
|
+
var TargetKindLevelSchema = object({
|
|
13370
|
+
id: string(),
|
|
13371
|
+
label: string(),
|
|
13372
|
+
/** Which canonical priority (1..5) this level maps to. `null` = qualitative-only. */
|
|
13373
|
+
ordinal: number().int().min(1).max(5).nullable(),
|
|
13374
|
+
flags: object({
|
|
13375
|
+
critical: boolean().optional(),
|
|
13376
|
+
silent: boolean().optional(),
|
|
13377
|
+
noPush: boolean().optional()
|
|
13378
|
+
}).optional(),
|
|
13379
|
+
/** e.g. Pushover `emergency` requires `retry` / `expire`. */
|
|
13380
|
+
requires: array(string()).optional(),
|
|
13381
|
+
description: string().optional()
|
|
13382
|
+
});
|
|
13383
|
+
/** The full capability block consulted before dispatch. */
|
|
13384
|
+
var TargetKindCapsSchema = object({
|
|
13385
|
+
attachments: object({
|
|
13386
|
+
mediaTypes: array(AttachmentMediaTypeSchema),
|
|
13387
|
+
mode: _enum([
|
|
13388
|
+
"url",
|
|
13389
|
+
"bytes",
|
|
13390
|
+
"both"
|
|
13391
|
+
]),
|
|
13392
|
+
max: number().int().nonnegative(),
|
|
13393
|
+
maxBytes: number().int().positive().optional()
|
|
13394
|
+
}),
|
|
13395
|
+
/** Max action buttons (0 = none). */
|
|
13396
|
+
actions: number().int().nonnegative(),
|
|
13397
|
+
levels: array(TargetKindLevelSchema),
|
|
13398
|
+
format: array(NotificationFormatSchema),
|
|
13399
|
+
clickUrl: boolean(),
|
|
13400
|
+
sound: boolean(),
|
|
13401
|
+
ttl: boolean(),
|
|
13402
|
+
bodyMaxLen: number().int().positive()
|
|
13403
|
+
});
|
|
13404
|
+
/**
|
|
13405
|
+
* `configSchema` is a `ConfigUISchema` tree passed through to the admin
|
|
13406
|
+
* FormBuilder. Stored as `z.unknown()` at the cap seam (mirrors
|
|
13407
|
+
* `device-provider.getChildCreationSchema` `CreationSchemaOutputSchema`) —
|
|
13408
|
+
* the union is large and not meant for runtime validation here; the exported
|
|
13409
|
+
* `TargetKind` type re-tightens `configSchema` to `ConfigUISchema`.
|
|
13410
|
+
*/
|
|
13411
|
+
var ConfigSchemaPassthrough = unknown();
|
|
13412
|
+
var TargetKindSchema = object({
|
|
13413
|
+
kind: string(),
|
|
13414
|
+
label: string(),
|
|
13415
|
+
icon: string(),
|
|
13416
|
+
/** Stamped by each provider so the concat-fanned catalog stays routable. */
|
|
13417
|
+
addonId: string(),
|
|
13418
|
+
configSchema: ConfigSchemaPassthrough,
|
|
13419
|
+
supportsDiscovery: boolean(),
|
|
13420
|
+
caps: TargetKindCapsSchema
|
|
13421
|
+
});
|
|
13422
|
+
/**
|
|
13423
|
+
* A persisted target. `config` holds secrets; providers REDACT secret fields
|
|
13424
|
+
* (return a presence marker only) when serving `listTargets` — never
|
|
13425
|
+
* round-trip a stored secret to the UI.
|
|
13426
|
+
*/
|
|
13427
|
+
var TargetSchema = object({
|
|
13428
|
+
id: string(),
|
|
13429
|
+
name: string(),
|
|
13430
|
+
kind: string(),
|
|
13431
|
+
addonId: string(),
|
|
13432
|
+
enabled: boolean(),
|
|
13433
|
+
config: record(string(), unknown())
|
|
13434
|
+
});
|
|
13435
|
+
/** A discovery-surfaced candidate (config is partial + non-secret). */
|
|
13436
|
+
var DiscoveredTargetSchema = object({
|
|
13437
|
+
kind: string(),
|
|
13438
|
+
suggestedName: string(),
|
|
13439
|
+
config: record(string(), unknown())
|
|
13440
|
+
});
|
|
13441
|
+
/** The degrade engine's report — what was resolved / dropped / degraded. */
|
|
13442
|
+
var RenderedAsSchema = object({
|
|
13443
|
+
level: string(),
|
|
13444
|
+
format: NotificationFormatSchema,
|
|
13445
|
+
attachmentsSent: number().int().nonnegative(),
|
|
13446
|
+
actionsSent: number().int().nonnegative(),
|
|
13447
|
+
truncated: boolean(),
|
|
13448
|
+
dropped: array(string())
|
|
13449
|
+
});
|
|
13450
|
+
var SendResultSchema = object({
|
|
13451
|
+
success: boolean(),
|
|
13452
|
+
error: string().optional(),
|
|
13453
|
+
renderedAs: RenderedAsSchema.optional()
|
|
13454
|
+
});
|
|
13455
|
+
/** Same shape as SendResult — kept as a distinct name for the test panel. */
|
|
13456
|
+
var TestResultSchema = SendResultSchema;
|
|
13259
13457
|
var notificationOutputCapability = {
|
|
13260
13458
|
name: "notification-output",
|
|
13261
13459
|
scope: "system",
|
|
13262
13460
|
mode: "collection",
|
|
13263
13461
|
methods: {
|
|
13462
|
+
listTargetKinds: method(object({}), array(TargetKindSchema)),
|
|
13463
|
+
listTargets: method(object({}), array(TargetSchema)),
|
|
13464
|
+
discoverTargets: method(object({
|
|
13465
|
+
kind: string(),
|
|
13466
|
+
config: record(string(), unknown()).optional()
|
|
13467
|
+
}), array(DiscoveredTargetSchema)),
|
|
13264
13468
|
send: method(object({
|
|
13265
|
-
|
|
13266
|
-
|
|
13267
|
-
|
|
13268
|
-
|
|
13269
|
-
|
|
13270
|
-
|
|
13271
|
-
|
|
13272
|
-
|
|
13273
|
-
|
|
13274
|
-
|
|
13275
|
-
|
|
13276
|
-
|
|
13277
|
-
}), _void(), { kind: "mutation" })
|
|
13278
|
-
sendTest: method(_void(), object({
|
|
13279
|
-
success: boolean(),
|
|
13280
|
-
error: string().optional()
|
|
13281
|
-
}), { kind: "mutation" })
|
|
13469
|
+
targetId: string(),
|
|
13470
|
+
notification: NotificationSchema
|
|
13471
|
+
}), SendResultSchema, { kind: "mutation" }),
|
|
13472
|
+
testTarget: method(object({
|
|
13473
|
+
targetId: string(),
|
|
13474
|
+
sample: NotificationSchema.optional()
|
|
13475
|
+
}), TestResultSchema, { kind: "mutation" }),
|
|
13476
|
+
upsertTarget: method(object({ target: TargetSchema }), TargetSchema, { kind: "mutation" }),
|
|
13477
|
+
deleteTarget: method(object({ targetId: string() }), _void(), { kind: "mutation" }),
|
|
13478
|
+
setTargetEnabled: method(object({
|
|
13479
|
+
targetId: string(),
|
|
13480
|
+
enabled: boolean()
|
|
13481
|
+
}), _void(), { kind: "mutation" })
|
|
13282
13482
|
}
|
|
13283
13483
|
};
|
|
13284
13484
|
/**
|
|
@@ -19275,13 +19475,49 @@ Object.freeze({
|
|
|
19275
19475
|
addonId: null,
|
|
19276
19476
|
access: "create"
|
|
19277
19477
|
},
|
|
19478
|
+
"notificationOutput.deleteTarget": {
|
|
19479
|
+
capName: "notification-output",
|
|
19480
|
+
capScope: "system",
|
|
19481
|
+
addonId: null,
|
|
19482
|
+
access: "delete"
|
|
19483
|
+
},
|
|
19484
|
+
"notificationOutput.discoverTargets": {
|
|
19485
|
+
capName: "notification-output",
|
|
19486
|
+
capScope: "system",
|
|
19487
|
+
addonId: null,
|
|
19488
|
+
access: "view"
|
|
19489
|
+
},
|
|
19490
|
+
"notificationOutput.listTargetKinds": {
|
|
19491
|
+
capName: "notification-output",
|
|
19492
|
+
capScope: "system",
|
|
19493
|
+
addonId: null,
|
|
19494
|
+
access: "view"
|
|
19495
|
+
},
|
|
19496
|
+
"notificationOutput.listTargets": {
|
|
19497
|
+
capName: "notification-output",
|
|
19498
|
+
capScope: "system",
|
|
19499
|
+
addonId: null,
|
|
19500
|
+
access: "view"
|
|
19501
|
+
},
|
|
19278
19502
|
"notificationOutput.send": {
|
|
19279
19503
|
capName: "notification-output",
|
|
19280
19504
|
capScope: "system",
|
|
19281
19505
|
addonId: null,
|
|
19282
19506
|
access: "create"
|
|
19283
19507
|
},
|
|
19284
|
-
"notificationOutput.
|
|
19508
|
+
"notificationOutput.setTargetEnabled": {
|
|
19509
|
+
capName: "notification-output",
|
|
19510
|
+
capScope: "system",
|
|
19511
|
+
addonId: null,
|
|
19512
|
+
access: "create"
|
|
19513
|
+
},
|
|
19514
|
+
"notificationOutput.testTarget": {
|
|
19515
|
+
capName: "notification-output",
|
|
19516
|
+
capScope: "system",
|
|
19517
|
+
addonId: null,
|
|
19518
|
+
access: "create"
|
|
19519
|
+
},
|
|
19520
|
+
"notificationOutput.upsertTarget": {
|
|
19285
19521
|
capName: "notification-output",
|
|
19286
19522
|
capScope: "system",
|
|
19287
19523
|
addonId: null,
|
|
@@ -21409,15 +21645,14 @@ var ConsoleOutput = class {
|
|
|
21409
21645
|
this.logger = logger;
|
|
21410
21646
|
}
|
|
21411
21647
|
async send(notification) {
|
|
21412
|
-
this.logger.info(`[${notification.
|
|
21648
|
+
this.logger.info(`[p${notification.priority}] ${notification.title ?? ""}: ${notification.body}`, notification.deviceId !== void 0 ? { tags: { deviceId: notification.deviceId } } : void 0);
|
|
21413
21649
|
}
|
|
21414
21650
|
async sendTest() {
|
|
21415
21651
|
await this.send({
|
|
21416
21652
|
title: "Test",
|
|
21417
|
-
|
|
21418
|
-
|
|
21419
|
-
|
|
21420
|
-
timestamp: Date.now()
|
|
21653
|
+
body: "Console output working",
|
|
21654
|
+
format: "text",
|
|
21655
|
+
priority: 3
|
|
21421
21656
|
});
|
|
21422
21657
|
return { success: true };
|
|
21423
21658
|
}
|
|
@@ -21685,12 +21920,11 @@ var AdvancedNotifierAddon = class extends BaseAddon {
|
|
|
21685
21920
|
const deviceId = Number.isFinite(deviceIdNum) ? deviceIdNum : void 0;
|
|
21686
21921
|
const notification = {
|
|
21687
21922
|
title,
|
|
21688
|
-
message,
|
|
21689
|
-
|
|
21690
|
-
|
|
21923
|
+
body: message,
|
|
21924
|
+
format: "text",
|
|
21925
|
+
priority: this.priorityToOrdinal(rule.priority),
|
|
21691
21926
|
deviceId,
|
|
21692
|
-
|
|
21693
|
-
timestamp: event.timestamp.getTime()
|
|
21927
|
+
metadata: event.data
|
|
21694
21928
|
};
|
|
21695
21929
|
let success = true;
|
|
21696
21930
|
let dispatchError;
|
|
@@ -21735,10 +21969,18 @@ var AdvancedNotifierAddon = class extends BaseAddon {
|
|
|
21735
21969
|
timestamp: event.timestamp.toISOString()
|
|
21736
21970
|
};
|
|
21737
21971
|
}
|
|
21738
|
-
|
|
21739
|
-
|
|
21740
|
-
|
|
21741
|
-
|
|
21972
|
+
/**
|
|
21973
|
+
* Map a rule's qualitative priority onto the canonical 1..5 ordinal.
|
|
21974
|
+
* Callers now pass ordinal priority; each `notification-output` provider
|
|
21975
|
+
* maps the ordinal onto its declared native level.
|
|
21976
|
+
*/
|
|
21977
|
+
priorityToOrdinal(priority) {
|
|
21978
|
+
switch (priority) {
|
|
21979
|
+
case "critical": return 5;
|
|
21980
|
+
case "high": return 4;
|
|
21981
|
+
case "low": return 2;
|
|
21982
|
+
default: return 3;
|
|
21983
|
+
}
|
|
21742
21984
|
}
|
|
21743
21985
|
};
|
|
21744
21986
|
//#endregion
|
package/dist/addon.mjs
CHANGED
|
@@ -4628,7 +4628,7 @@ function _instanceof(cls, params = {}) {
|
|
|
4628
4628
|
return inst;
|
|
4629
4629
|
}
|
|
4630
4630
|
//#endregion
|
|
4631
|
-
//#region ../types/dist/sleep-
|
|
4631
|
+
//#region ../types/dist/sleep-MHm--th-.mjs
|
|
4632
4632
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
4633
4633
|
EventCategory["SystemBoot"] = "system.boot";
|
|
4634
4634
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -5890,6 +5890,7 @@ var CamStreamKindSchema = _enum([
|
|
|
5890
5890
|
"pull-rtsp",
|
|
5891
5891
|
"pull-rtmp",
|
|
5892
5892
|
"pull-http",
|
|
5893
|
+
"pull-flv",
|
|
5893
5894
|
"pull-rfc4571",
|
|
5894
5895
|
"push-annexb",
|
|
5895
5896
|
"derived"
|
|
@@ -7033,7 +7034,21 @@ var StorageLocationDeclarationSchema = object({
|
|
|
7033
7034
|
* slots (e.g. `recordingsLow` → `recordings`) so operators only need to
|
|
7034
7035
|
* configure the primary location.
|
|
7035
7036
|
*/
|
|
7036
|
-
defaultsTo: string().optional()
|
|
7037
|
+
defaultsTo: string().optional(),
|
|
7038
|
+
/**
|
|
7039
|
+
* Which node root the seeded `<id>:default` instance is placed under on a
|
|
7040
|
+
* FRESH install:
|
|
7041
|
+
* - `'data'` (default) — the node's data dir (`CAMSTACK_DATA` / boot dir),
|
|
7042
|
+
* the appData volume. Right for small/durable data (backups, logs, models).
|
|
7043
|
+
* - `'media'` — the dedicated media volume (`CAMSTACK_MEDIA_ROOT`) when that
|
|
7044
|
+
* env is set, else falls back to the data root. Right for bulky, hot media
|
|
7045
|
+
* (recordings, event media) that should stay off the appData disk.
|
|
7046
|
+
*
|
|
7047
|
+
* Only affects the seeded default's `basePath`; operators can repoint any
|
|
7048
|
+
* location afterwards, and a `defaultsTo` slot inherits its parent's root
|
|
7049
|
+
* regardless of this field. Absent (the common case) is treated as `'data'`.
|
|
7050
|
+
*/
|
|
7051
|
+
defaultRoot: _enum(["data", "media"]).optional()
|
|
7037
7052
|
});
|
|
7038
7053
|
var DecoderStatsSchema = object({
|
|
7039
7054
|
inputFps: number(),
|
|
@@ -7894,6 +7909,10 @@ var RtspRestreamEntrySchema = object({
|
|
|
7894
7909
|
var BrokerRtspClientSchema = object({
|
|
7895
7910
|
sessionId: string(),
|
|
7896
7911
|
remoteAddr: string(),
|
|
7912
|
+
/** Client `User-Agent` (e.g. `recorder` for the recorder's RTSP pull), or
|
|
7913
|
+
* null/absent when the client sent none. Lets the UI label a consumer by
|
|
7914
|
+
* purpose. Optional so a client built against an older schema stays valid. */
|
|
7915
|
+
userAgent: string().nullish(),
|
|
7897
7916
|
playing: boolean(),
|
|
7898
7917
|
muted: boolean(),
|
|
7899
7918
|
connectedAt: number(),
|
|
@@ -13195,7 +13214,7 @@ var AddBrokerInputSchema = object({
|
|
|
13195
13214
|
});
|
|
13196
13215
|
var AddBrokerResultSchema = object({ id: string() });
|
|
13197
13216
|
var IdInputSchema = object({ id: string() });
|
|
13198
|
-
var TestResultSchema = discriminatedUnion("ok", [object({
|
|
13217
|
+
var TestResultSchema$1 = discriminatedUnion("ok", [object({
|
|
13199
13218
|
ok: literal(true),
|
|
13200
13219
|
latencyMs: number()
|
|
13201
13220
|
}), object({
|
|
@@ -13218,7 +13237,7 @@ var StatusSchema = object({
|
|
|
13218
13237
|
brokerCount: number(),
|
|
13219
13238
|
embeddedRunning: boolean()
|
|
13220
13239
|
});
|
|
13221
|
-
method(_void(), array(BrokerInfoSchema)), method(IdInputSchema, BrokerConnectionDetailsSchema), method(AddBrokerInputSchema, AddBrokerResultSchema, { kind: "mutation" }), method(IdInputSchema, _void(), { kind: "mutation" }), method(IdInputSchema, TestResultSchema, { kind: "mutation" }), method(StartEmbeddedInputSchema, StartEmbeddedResultSchema, { kind: "mutation" }), method(IdInputSchema, _void(), { kind: "mutation" }), method(_void(), StatusSchema);
|
|
13240
|
+
method(_void(), array(BrokerInfoSchema)), method(IdInputSchema, BrokerConnectionDetailsSchema), method(AddBrokerInputSchema, AddBrokerResultSchema, { kind: "mutation" }), method(IdInputSchema, _void(), { kind: "mutation" }), method(IdInputSchema, TestResultSchema$1, { kind: "mutation" }), method(StartEmbeddedInputSchema, StartEmbeddedResultSchema, { kind: "mutation" }), method(IdInputSchema, _void(), { kind: "mutation" }), method(_void(), StatusSchema);
|
|
13222
13241
|
var NetworkEndpointSchema = object({
|
|
13223
13242
|
url: string(),
|
|
13224
13243
|
hostname: string(),
|
|
@@ -13252,29 +13271,210 @@ var NetworkEndpointEntrySchema = NetworkEndpointSchema.extend({
|
|
|
13252
13271
|
sourcePort: number().optional()
|
|
13253
13272
|
});
|
|
13254
13273
|
method(_void(), NetworkEndpointSchema, { kind: "mutation" }), method(_void(), _void(), { kind: "mutation" }), method(_void(), NetworkEndpointSchema.nullable()), method(_void(), NetworkAccessStatusSchema), method(_void(), array(NetworkEndpointEntrySchema).readonly());
|
|
13274
|
+
/**
|
|
13275
|
+
* notification-output — canonical, capability-gated notification delivery.
|
|
13276
|
+
*
|
|
13277
|
+
* Apprise-derived model (see
|
|
13278
|
+
* `docs/superpowers/specs/2026-07-03-notification-output-notifier-matrix.md`):
|
|
13279
|
+
* callers emit ONE canonical `Notification`; each provider declares a
|
|
13280
|
+
* per-kind capability descriptor (`TargetKind`), and the pure degrade
|
|
13281
|
+
* engine (`@camstack/types` `prepareNotification`) transcodes / degrades the
|
|
13282
|
+
* message to what the kind supports — callers never special-case a service.
|
|
13283
|
+
*
|
|
13284
|
+
* DESIGN DECISIONS (locked):
|
|
13285
|
+
* - Target CRUD lives on THIS cap (`upsertTarget` / `deleteTarget` /
|
|
13286
|
+
* `setTargetEnabled`), each provider persisting via the `settings-store`
|
|
13287
|
+
* cap. Rationale: the admin UI needs one uniform surface across the
|
|
13288
|
+
* notifiers addon AND the HA addon; the addon-`globalSettingsSchema`-array
|
|
13289
|
+
* alternative would fork the UI per addon and cannot host the
|
|
13290
|
+
* discovery→adopt flow.
|
|
13291
|
+
* - `listTargetKinds` / `listTargets` / `discoverTargets` return arrays →
|
|
13292
|
+
* the generated cap-mount auto-`concatCollection`-fans them across every
|
|
13293
|
+
* registered provider (notifiers addon + HA addon) so one catalog is
|
|
13294
|
+
* routable. `send` / `testTarget` / CRUD route to ONE provider by the
|
|
13295
|
+
* `addonId` the generated collection router extracts from the call input.
|
|
13296
|
+
* - `Attachment.bytes` is `Uint8Array`. Transport-safe: superjson (the tRPC
|
|
13297
|
+
* transformer) + UDS MsgPack both round-trip typed arrays — already used by
|
|
13298
|
+
* `storage` / `storage-provider` / `recording` caps over the same path. No
|
|
13299
|
+
* base64 fallback needed.
|
|
13300
|
+
*
|
|
13301
|
+
* TODO (deferred, closed-set change — separate decision): add
|
|
13302
|
+
* `providerKind: 'notify'` so notification providers surface on the unified
|
|
13303
|
+
* admin "Integrations" page.
|
|
13304
|
+
*/
|
|
13305
|
+
/**
|
|
13306
|
+
* Zentik-derived typed-media enum — the superset across every kind. Each
|
|
13307
|
+
* adapter picks what it supports and the degrade engine filters the rest.
|
|
13308
|
+
*/
|
|
13309
|
+
var AttachmentMediaTypeSchema = _enum([
|
|
13310
|
+
"image",
|
|
13311
|
+
"video",
|
|
13312
|
+
"gif",
|
|
13313
|
+
"audio",
|
|
13314
|
+
"icon"
|
|
13315
|
+
]);
|
|
13316
|
+
/**
|
|
13317
|
+
* A single attachment. Exactly one of `url` (remote source, most adapters
|
|
13318
|
+
* prefer this) or `bytes` (inline source; required for Pushover-style
|
|
13319
|
+
* bytes-only kinds) MUST be present — the degrade engine expresses a
|
|
13320
|
+
* url→bytes fetch as a `needsFetch` directive the adapter executes.
|
|
13321
|
+
*/
|
|
13322
|
+
var AttachmentSchema = object({
|
|
13323
|
+
mediaType: AttachmentMediaTypeSchema,
|
|
13324
|
+
url: string().optional(),
|
|
13325
|
+
bytes: _instanceof(Uint8Array).optional(),
|
|
13326
|
+
mime: string().optional(),
|
|
13327
|
+
name: string().optional()
|
|
13328
|
+
}).refine((a) => a.url !== void 0 || a.bytes !== void 0, { message: "Attachment requires either `url` or `bytes`" });
|
|
13329
|
+
var NotificationFormatSchema = _enum([
|
|
13330
|
+
"text",
|
|
13331
|
+
"markdown",
|
|
13332
|
+
"html"
|
|
13333
|
+
]);
|
|
13334
|
+
/** A single tap-through action button. */
|
|
13335
|
+
var NotificationActionSchema = object({
|
|
13336
|
+
id: string(),
|
|
13337
|
+
label: string(),
|
|
13338
|
+
url: string().optional()
|
|
13339
|
+
});
|
|
13340
|
+
/**
|
|
13341
|
+
* The canonical notification. `body` is the only hard field (Apprise model).
|
|
13342
|
+
* `priority` is a 5-level ORDINAL (1=lowest … 3=normal(default) … 5=urgent),
|
|
13343
|
+
* NOT a fixed severity enum — each kind declares its own `caps.levels` and
|
|
13344
|
+
* the adapter maps this ordinal onto its native level. `level?` is an
|
|
13345
|
+
* optional kind-native level id (`emergency`, `silent`, …) that overrides
|
|
13346
|
+
* `priority` for that one target.
|
|
13347
|
+
*/
|
|
13348
|
+
var NotificationSchema = object({
|
|
13349
|
+
body: string(),
|
|
13350
|
+
title: string().optional(),
|
|
13351
|
+
format: NotificationFormatSchema.default("text"),
|
|
13352
|
+
priority: number().int().min(1).max(5).default(3),
|
|
13353
|
+
level: string().optional(),
|
|
13354
|
+
attachments: array(AttachmentSchema).optional(),
|
|
13355
|
+
clickUrl: string().optional(),
|
|
13356
|
+
actions: array(NotificationActionSchema).optional(),
|
|
13357
|
+
sound: string().optional(),
|
|
13358
|
+
ttl: number().optional(),
|
|
13359
|
+
tag: string().optional(),
|
|
13360
|
+
deviceId: number().optional(),
|
|
13361
|
+
eventId: string().optional(),
|
|
13362
|
+
metadata: record(string(), unknown()).optional()
|
|
13363
|
+
});
|
|
13364
|
+
/** One declared native severity/priority level for a kind. */
|
|
13365
|
+
var TargetKindLevelSchema = object({
|
|
13366
|
+
id: string(),
|
|
13367
|
+
label: string(),
|
|
13368
|
+
/** Which canonical priority (1..5) this level maps to. `null` = qualitative-only. */
|
|
13369
|
+
ordinal: number().int().min(1).max(5).nullable(),
|
|
13370
|
+
flags: object({
|
|
13371
|
+
critical: boolean().optional(),
|
|
13372
|
+
silent: boolean().optional(),
|
|
13373
|
+
noPush: boolean().optional()
|
|
13374
|
+
}).optional(),
|
|
13375
|
+
/** e.g. Pushover `emergency` requires `retry` / `expire`. */
|
|
13376
|
+
requires: array(string()).optional(),
|
|
13377
|
+
description: string().optional()
|
|
13378
|
+
});
|
|
13379
|
+
/** The full capability block consulted before dispatch. */
|
|
13380
|
+
var TargetKindCapsSchema = object({
|
|
13381
|
+
attachments: object({
|
|
13382
|
+
mediaTypes: array(AttachmentMediaTypeSchema),
|
|
13383
|
+
mode: _enum([
|
|
13384
|
+
"url",
|
|
13385
|
+
"bytes",
|
|
13386
|
+
"both"
|
|
13387
|
+
]),
|
|
13388
|
+
max: number().int().nonnegative(),
|
|
13389
|
+
maxBytes: number().int().positive().optional()
|
|
13390
|
+
}),
|
|
13391
|
+
/** Max action buttons (0 = none). */
|
|
13392
|
+
actions: number().int().nonnegative(),
|
|
13393
|
+
levels: array(TargetKindLevelSchema),
|
|
13394
|
+
format: array(NotificationFormatSchema),
|
|
13395
|
+
clickUrl: boolean(),
|
|
13396
|
+
sound: boolean(),
|
|
13397
|
+
ttl: boolean(),
|
|
13398
|
+
bodyMaxLen: number().int().positive()
|
|
13399
|
+
});
|
|
13400
|
+
/**
|
|
13401
|
+
* `configSchema` is a `ConfigUISchema` tree passed through to the admin
|
|
13402
|
+
* FormBuilder. Stored as `z.unknown()` at the cap seam (mirrors
|
|
13403
|
+
* `device-provider.getChildCreationSchema` `CreationSchemaOutputSchema`) —
|
|
13404
|
+
* the union is large and not meant for runtime validation here; the exported
|
|
13405
|
+
* `TargetKind` type re-tightens `configSchema` to `ConfigUISchema`.
|
|
13406
|
+
*/
|
|
13407
|
+
var ConfigSchemaPassthrough = unknown();
|
|
13408
|
+
var TargetKindSchema = object({
|
|
13409
|
+
kind: string(),
|
|
13410
|
+
label: string(),
|
|
13411
|
+
icon: string(),
|
|
13412
|
+
/** Stamped by each provider so the concat-fanned catalog stays routable. */
|
|
13413
|
+
addonId: string(),
|
|
13414
|
+
configSchema: ConfigSchemaPassthrough,
|
|
13415
|
+
supportsDiscovery: boolean(),
|
|
13416
|
+
caps: TargetKindCapsSchema
|
|
13417
|
+
});
|
|
13418
|
+
/**
|
|
13419
|
+
* A persisted target. `config` holds secrets; providers REDACT secret fields
|
|
13420
|
+
* (return a presence marker only) when serving `listTargets` — never
|
|
13421
|
+
* round-trip a stored secret to the UI.
|
|
13422
|
+
*/
|
|
13423
|
+
var TargetSchema = object({
|
|
13424
|
+
id: string(),
|
|
13425
|
+
name: string(),
|
|
13426
|
+
kind: string(),
|
|
13427
|
+
addonId: string(),
|
|
13428
|
+
enabled: boolean(),
|
|
13429
|
+
config: record(string(), unknown())
|
|
13430
|
+
});
|
|
13431
|
+
/** A discovery-surfaced candidate (config is partial + non-secret). */
|
|
13432
|
+
var DiscoveredTargetSchema = object({
|
|
13433
|
+
kind: string(),
|
|
13434
|
+
suggestedName: string(),
|
|
13435
|
+
config: record(string(), unknown())
|
|
13436
|
+
});
|
|
13437
|
+
/** The degrade engine's report — what was resolved / dropped / degraded. */
|
|
13438
|
+
var RenderedAsSchema = object({
|
|
13439
|
+
level: string(),
|
|
13440
|
+
format: NotificationFormatSchema,
|
|
13441
|
+
attachmentsSent: number().int().nonnegative(),
|
|
13442
|
+
actionsSent: number().int().nonnegative(),
|
|
13443
|
+
truncated: boolean(),
|
|
13444
|
+
dropped: array(string())
|
|
13445
|
+
});
|
|
13446
|
+
var SendResultSchema = object({
|
|
13447
|
+
success: boolean(),
|
|
13448
|
+
error: string().optional(),
|
|
13449
|
+
renderedAs: RenderedAsSchema.optional()
|
|
13450
|
+
});
|
|
13451
|
+
/** Same shape as SendResult — kept as a distinct name for the test panel. */
|
|
13452
|
+
var TestResultSchema = SendResultSchema;
|
|
13255
13453
|
var notificationOutputCapability = {
|
|
13256
13454
|
name: "notification-output",
|
|
13257
13455
|
scope: "system",
|
|
13258
13456
|
mode: "collection",
|
|
13259
13457
|
methods: {
|
|
13458
|
+
listTargetKinds: method(object({}), array(TargetKindSchema)),
|
|
13459
|
+
listTargets: method(object({}), array(TargetSchema)),
|
|
13460
|
+
discoverTargets: method(object({
|
|
13461
|
+
kind: string(),
|
|
13462
|
+
config: record(string(), unknown()).optional()
|
|
13463
|
+
}), array(DiscoveredTargetSchema)),
|
|
13260
13464
|
send: method(object({
|
|
13261
|
-
|
|
13262
|
-
|
|
13263
|
-
|
|
13264
|
-
|
|
13265
|
-
|
|
13266
|
-
|
|
13267
|
-
|
|
13268
|
-
|
|
13269
|
-
|
|
13270
|
-
|
|
13271
|
-
|
|
13272
|
-
|
|
13273
|
-
}), _void(), { kind: "mutation" })
|
|
13274
|
-
sendTest: method(_void(), object({
|
|
13275
|
-
success: boolean(),
|
|
13276
|
-
error: string().optional()
|
|
13277
|
-
}), { kind: "mutation" })
|
|
13465
|
+
targetId: string(),
|
|
13466
|
+
notification: NotificationSchema
|
|
13467
|
+
}), SendResultSchema, { kind: "mutation" }),
|
|
13468
|
+
testTarget: method(object({
|
|
13469
|
+
targetId: string(),
|
|
13470
|
+
sample: NotificationSchema.optional()
|
|
13471
|
+
}), TestResultSchema, { kind: "mutation" }),
|
|
13472
|
+
upsertTarget: method(object({ target: TargetSchema }), TargetSchema, { kind: "mutation" }),
|
|
13473
|
+
deleteTarget: method(object({ targetId: string() }), _void(), { kind: "mutation" }),
|
|
13474
|
+
setTargetEnabled: method(object({
|
|
13475
|
+
targetId: string(),
|
|
13476
|
+
enabled: boolean()
|
|
13477
|
+
}), _void(), { kind: "mutation" })
|
|
13278
13478
|
}
|
|
13279
13479
|
};
|
|
13280
13480
|
/**
|
|
@@ -19271,13 +19471,49 @@ Object.freeze({
|
|
|
19271
19471
|
addonId: null,
|
|
19272
19472
|
access: "create"
|
|
19273
19473
|
},
|
|
19474
|
+
"notificationOutput.deleteTarget": {
|
|
19475
|
+
capName: "notification-output",
|
|
19476
|
+
capScope: "system",
|
|
19477
|
+
addonId: null,
|
|
19478
|
+
access: "delete"
|
|
19479
|
+
},
|
|
19480
|
+
"notificationOutput.discoverTargets": {
|
|
19481
|
+
capName: "notification-output",
|
|
19482
|
+
capScope: "system",
|
|
19483
|
+
addonId: null,
|
|
19484
|
+
access: "view"
|
|
19485
|
+
},
|
|
19486
|
+
"notificationOutput.listTargetKinds": {
|
|
19487
|
+
capName: "notification-output",
|
|
19488
|
+
capScope: "system",
|
|
19489
|
+
addonId: null,
|
|
19490
|
+
access: "view"
|
|
19491
|
+
},
|
|
19492
|
+
"notificationOutput.listTargets": {
|
|
19493
|
+
capName: "notification-output",
|
|
19494
|
+
capScope: "system",
|
|
19495
|
+
addonId: null,
|
|
19496
|
+
access: "view"
|
|
19497
|
+
},
|
|
19274
19498
|
"notificationOutput.send": {
|
|
19275
19499
|
capName: "notification-output",
|
|
19276
19500
|
capScope: "system",
|
|
19277
19501
|
addonId: null,
|
|
19278
19502
|
access: "create"
|
|
19279
19503
|
},
|
|
19280
|
-
"notificationOutput.
|
|
19504
|
+
"notificationOutput.setTargetEnabled": {
|
|
19505
|
+
capName: "notification-output",
|
|
19506
|
+
capScope: "system",
|
|
19507
|
+
addonId: null,
|
|
19508
|
+
access: "create"
|
|
19509
|
+
},
|
|
19510
|
+
"notificationOutput.testTarget": {
|
|
19511
|
+
capName: "notification-output",
|
|
19512
|
+
capScope: "system",
|
|
19513
|
+
addonId: null,
|
|
19514
|
+
access: "create"
|
|
19515
|
+
},
|
|
19516
|
+
"notificationOutput.upsertTarget": {
|
|
19281
19517
|
capName: "notification-output",
|
|
19282
19518
|
capScope: "system",
|
|
19283
19519
|
addonId: null,
|
|
@@ -21405,15 +21641,14 @@ var ConsoleOutput = class {
|
|
|
21405
21641
|
this.logger = logger;
|
|
21406
21642
|
}
|
|
21407
21643
|
async send(notification) {
|
|
21408
|
-
this.logger.info(`[${notification.
|
|
21644
|
+
this.logger.info(`[p${notification.priority}] ${notification.title ?? ""}: ${notification.body}`, notification.deviceId !== void 0 ? { tags: { deviceId: notification.deviceId } } : void 0);
|
|
21409
21645
|
}
|
|
21410
21646
|
async sendTest() {
|
|
21411
21647
|
await this.send({
|
|
21412
21648
|
title: "Test",
|
|
21413
|
-
|
|
21414
|
-
|
|
21415
|
-
|
|
21416
|
-
timestamp: Date.now()
|
|
21649
|
+
body: "Console output working",
|
|
21650
|
+
format: "text",
|
|
21651
|
+
priority: 3
|
|
21417
21652
|
});
|
|
21418
21653
|
return { success: true };
|
|
21419
21654
|
}
|
|
@@ -21681,12 +21916,11 @@ var AdvancedNotifierAddon = class extends BaseAddon {
|
|
|
21681
21916
|
const deviceId = Number.isFinite(deviceIdNum) ? deviceIdNum : void 0;
|
|
21682
21917
|
const notification = {
|
|
21683
21918
|
title,
|
|
21684
|
-
message,
|
|
21685
|
-
|
|
21686
|
-
|
|
21919
|
+
body: message,
|
|
21920
|
+
format: "text",
|
|
21921
|
+
priority: this.priorityToOrdinal(rule.priority),
|
|
21687
21922
|
deviceId,
|
|
21688
|
-
|
|
21689
|
-
timestamp: event.timestamp.getTime()
|
|
21923
|
+
metadata: event.data
|
|
21690
21924
|
};
|
|
21691
21925
|
let success = true;
|
|
21692
21926
|
let dispatchError;
|
|
@@ -21731,10 +21965,18 @@ var AdvancedNotifierAddon = class extends BaseAddon {
|
|
|
21731
21965
|
timestamp: event.timestamp.toISOString()
|
|
21732
21966
|
};
|
|
21733
21967
|
}
|
|
21734
|
-
|
|
21735
|
-
|
|
21736
|
-
|
|
21737
|
-
|
|
21968
|
+
/**
|
|
21969
|
+
* Map a rule's qualitative priority onto the canonical 1..5 ordinal.
|
|
21970
|
+
* Callers now pass ordinal priority; each `notification-output` provider
|
|
21971
|
+
* maps the ordinal onto its declared native level.
|
|
21972
|
+
*/
|
|
21973
|
+
priorityToOrdinal(priority) {
|
|
21974
|
+
switch (priority) {
|
|
21975
|
+
case "critical": return 5;
|
|
21976
|
+
case "high": return 4;
|
|
21977
|
+
case "low": return 2;
|
|
21978
|
+
default: return 3;
|
|
21979
|
+
}
|
|
21738
21980
|
}
|
|
21739
21981
|
};
|
|
21740
21982
|
//#endregion
|
package/dist/index.js
CHANGED
|
@@ -26,6 +26,11 @@ async function fetchWithTimeout(url, init, timeoutMs = DEFAULT_OUTPUT_TIMEOUT_MS
|
|
|
26
26
|
}
|
|
27
27
|
//#endregion
|
|
28
28
|
//#region src/outputs/webhook.ts
|
|
29
|
+
/**
|
|
30
|
+
* @deprecated Superseded by the `addon-notifiers` generic-webhook adapter
|
|
31
|
+
* (the `notification-output` cap collection provider). Kept only for
|
|
32
|
+
* compile-compat; not registered as a live output.
|
|
33
|
+
*/
|
|
29
34
|
var WebhookOutput = class {
|
|
30
35
|
id = "webhook";
|
|
31
36
|
name = "Webhook";
|
|
@@ -45,10 +50,9 @@ var WebhookOutput = class {
|
|
|
45
50
|
try {
|
|
46
51
|
await this.send({
|
|
47
52
|
title: "Test Notification",
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
timestamp: Date.now()
|
|
53
|
+
body: "This is a test from CamStack Advanced Notifier",
|
|
54
|
+
format: "text",
|
|
55
|
+
priority: 3
|
|
52
56
|
});
|
|
53
57
|
return { success: true };
|
|
54
58
|
} catch (err) {
|
|
@@ -61,6 +65,12 @@ var WebhookOutput = class {
|
|
|
61
65
|
};
|
|
62
66
|
//#endregion
|
|
63
67
|
//#region src/outputs/home-assistant.ts
|
|
68
|
+
/**
|
|
69
|
+
* @deprecated Superseded by the `homeassistant` kind in
|
|
70
|
+
* `addon-provider-homeassistant` (the `notification-output` cap collection
|
|
71
|
+
* provider, reusing the HA broker connection). Kept only for compile-compat;
|
|
72
|
+
* not registered as a live output.
|
|
73
|
+
*/
|
|
64
74
|
var HomeAssistantOutput = class {
|
|
65
75
|
id = "home-assistant";
|
|
66
76
|
name = "Home Assistant";
|
|
@@ -80,11 +90,10 @@ var HomeAssistantOutput = class {
|
|
|
80
90
|
},
|
|
81
91
|
body: JSON.stringify({
|
|
82
92
|
title: notification.title,
|
|
83
|
-
message: notification.
|
|
84
|
-
|
|
85
|
-
category: notification.category,
|
|
93
|
+
message: notification.body,
|
|
94
|
+
priority: notification.priority,
|
|
86
95
|
device_id: notification.deviceId,
|
|
87
|
-
data: notification.
|
|
96
|
+
data: notification.metadata
|
|
88
97
|
})
|
|
89
98
|
});
|
|
90
99
|
}
|
|
@@ -92,10 +101,9 @@ var HomeAssistantOutput = class {
|
|
|
92
101
|
try {
|
|
93
102
|
await this.send({
|
|
94
103
|
title: "CamStack Test",
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
timestamp: Date.now()
|
|
104
|
+
body: "Connection verified",
|
|
105
|
+
format: "text",
|
|
106
|
+
priority: 3
|
|
99
107
|
});
|
|
100
108
|
return { success: true };
|
|
101
109
|
} catch (err) {
|
package/dist/index.mjs
CHANGED
|
@@ -25,6 +25,11 @@ async function fetchWithTimeout(url, init, timeoutMs = DEFAULT_OUTPUT_TIMEOUT_MS
|
|
|
25
25
|
}
|
|
26
26
|
//#endregion
|
|
27
27
|
//#region src/outputs/webhook.ts
|
|
28
|
+
/**
|
|
29
|
+
* @deprecated Superseded by the `addon-notifiers` generic-webhook adapter
|
|
30
|
+
* (the `notification-output` cap collection provider). Kept only for
|
|
31
|
+
* compile-compat; not registered as a live output.
|
|
32
|
+
*/
|
|
28
33
|
var WebhookOutput = class {
|
|
29
34
|
id = "webhook";
|
|
30
35
|
name = "Webhook";
|
|
@@ -44,10 +49,9 @@ var WebhookOutput = class {
|
|
|
44
49
|
try {
|
|
45
50
|
await this.send({
|
|
46
51
|
title: "Test Notification",
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
timestamp: Date.now()
|
|
52
|
+
body: "This is a test from CamStack Advanced Notifier",
|
|
53
|
+
format: "text",
|
|
54
|
+
priority: 3
|
|
51
55
|
});
|
|
52
56
|
return { success: true };
|
|
53
57
|
} catch (err) {
|
|
@@ -60,6 +64,12 @@ var WebhookOutput = class {
|
|
|
60
64
|
};
|
|
61
65
|
//#endregion
|
|
62
66
|
//#region src/outputs/home-assistant.ts
|
|
67
|
+
/**
|
|
68
|
+
* @deprecated Superseded by the `homeassistant` kind in
|
|
69
|
+
* `addon-provider-homeassistant` (the `notification-output` cap collection
|
|
70
|
+
* provider, reusing the HA broker connection). Kept only for compile-compat;
|
|
71
|
+
* not registered as a live output.
|
|
72
|
+
*/
|
|
63
73
|
var HomeAssistantOutput = class {
|
|
64
74
|
id = "home-assistant";
|
|
65
75
|
name = "Home Assistant";
|
|
@@ -79,11 +89,10 @@ var HomeAssistantOutput = class {
|
|
|
79
89
|
},
|
|
80
90
|
body: JSON.stringify({
|
|
81
91
|
title: notification.title,
|
|
82
|
-
message: notification.
|
|
83
|
-
|
|
84
|
-
category: notification.category,
|
|
92
|
+
message: notification.body,
|
|
93
|
+
priority: notification.priority,
|
|
85
94
|
device_id: notification.deviceId,
|
|
86
|
-
data: notification.
|
|
95
|
+
data: notification.metadata
|
|
87
96
|
})
|
|
88
97
|
});
|
|
89
98
|
}
|
|
@@ -91,10 +100,9 @@ var HomeAssistantOutput = class {
|
|
|
91
100
|
try {
|
|
92
101
|
await this.send({
|
|
93
102
|
title: "CamStack Test",
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
timestamp: Date.now()
|
|
103
|
+
body: "Connection verified",
|
|
104
|
+
format: "text",
|
|
105
|
+
priority: 3
|
|
98
106
|
});
|
|
99
107
|
return { success: true };
|
|
100
108
|
} catch (err) {
|