@camstack/addon-advanced-notifier 1.1.13 → 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 +259 -35
- package/dist/addon.mjs +259 -35
- 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"
|
|
@@ -13217,7 +13218,7 @@ var AddBrokerInputSchema = object({
|
|
|
13217
13218
|
});
|
|
13218
13219
|
var AddBrokerResultSchema = object({ id: string() });
|
|
13219
13220
|
var IdInputSchema = object({ id: string() });
|
|
13220
|
-
var TestResultSchema = discriminatedUnion("ok", [object({
|
|
13221
|
+
var TestResultSchema$1 = discriminatedUnion("ok", [object({
|
|
13221
13222
|
ok: literal(true),
|
|
13222
13223
|
latencyMs: number()
|
|
13223
13224
|
}), object({
|
|
@@ -13240,7 +13241,7 @@ var StatusSchema = object({
|
|
|
13240
13241
|
brokerCount: number(),
|
|
13241
13242
|
embeddedRunning: boolean()
|
|
13242
13243
|
});
|
|
13243
|
-
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);
|
|
13244
13245
|
var NetworkEndpointSchema = object({
|
|
13245
13246
|
url: string(),
|
|
13246
13247
|
hostname: string(),
|
|
@@ -13274,29 +13275,210 @@ var NetworkEndpointEntrySchema = NetworkEndpointSchema.extend({
|
|
|
13274
13275
|
sourcePort: number().optional()
|
|
13275
13276
|
});
|
|
13276
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;
|
|
13277
13457
|
var notificationOutputCapability = {
|
|
13278
13458
|
name: "notification-output",
|
|
13279
13459
|
scope: "system",
|
|
13280
13460
|
mode: "collection",
|
|
13281
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)),
|
|
13282
13468
|
send: method(object({
|
|
13283
|
-
|
|
13284
|
-
|
|
13285
|
-
|
|
13286
|
-
|
|
13287
|
-
|
|
13288
|
-
|
|
13289
|
-
|
|
13290
|
-
|
|
13291
|
-
|
|
13292
|
-
|
|
13293
|
-
|
|
13294
|
-
|
|
13295
|
-
}), _void(), { kind: "mutation" })
|
|
13296
|
-
sendTest: method(_void(), object({
|
|
13297
|
-
success: boolean(),
|
|
13298
|
-
error: string().optional()
|
|
13299
|
-
}), { 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" })
|
|
13300
13482
|
}
|
|
13301
13483
|
};
|
|
13302
13484
|
/**
|
|
@@ -19293,13 +19475,49 @@ Object.freeze({
|
|
|
19293
19475
|
addonId: null,
|
|
19294
19476
|
access: "create"
|
|
19295
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
|
+
},
|
|
19296
19502
|
"notificationOutput.send": {
|
|
19297
19503
|
capName: "notification-output",
|
|
19298
19504
|
capScope: "system",
|
|
19299
19505
|
addonId: null,
|
|
19300
19506
|
access: "create"
|
|
19301
19507
|
},
|
|
19302
|
-
"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": {
|
|
19303
19521
|
capName: "notification-output",
|
|
19304
19522
|
capScope: "system",
|
|
19305
19523
|
addonId: null,
|
|
@@ -21427,15 +21645,14 @@ var ConsoleOutput = class {
|
|
|
21427
21645
|
this.logger = logger;
|
|
21428
21646
|
}
|
|
21429
21647
|
async send(notification) {
|
|
21430
|
-
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);
|
|
21431
21649
|
}
|
|
21432
21650
|
async sendTest() {
|
|
21433
21651
|
await this.send({
|
|
21434
21652
|
title: "Test",
|
|
21435
|
-
|
|
21436
|
-
|
|
21437
|
-
|
|
21438
|
-
timestamp: Date.now()
|
|
21653
|
+
body: "Console output working",
|
|
21654
|
+
format: "text",
|
|
21655
|
+
priority: 3
|
|
21439
21656
|
});
|
|
21440
21657
|
return { success: true };
|
|
21441
21658
|
}
|
|
@@ -21703,12 +21920,11 @@ var AdvancedNotifierAddon = class extends BaseAddon {
|
|
|
21703
21920
|
const deviceId = Number.isFinite(deviceIdNum) ? deviceIdNum : void 0;
|
|
21704
21921
|
const notification = {
|
|
21705
21922
|
title,
|
|
21706
|
-
message,
|
|
21707
|
-
|
|
21708
|
-
|
|
21923
|
+
body: message,
|
|
21924
|
+
format: "text",
|
|
21925
|
+
priority: this.priorityToOrdinal(rule.priority),
|
|
21709
21926
|
deviceId,
|
|
21710
|
-
|
|
21711
|
-
timestamp: event.timestamp.getTime()
|
|
21927
|
+
metadata: event.data
|
|
21712
21928
|
};
|
|
21713
21929
|
let success = true;
|
|
21714
21930
|
let dispatchError;
|
|
@@ -21753,10 +21969,18 @@ var AdvancedNotifierAddon = class extends BaseAddon {
|
|
|
21753
21969
|
timestamp: event.timestamp.toISOString()
|
|
21754
21970
|
};
|
|
21755
21971
|
}
|
|
21756
|
-
|
|
21757
|
-
|
|
21758
|
-
|
|
21759
|
-
|
|
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
|
+
}
|
|
21760
21984
|
}
|
|
21761
21985
|
};
|
|
21762
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"
|
|
@@ -13213,7 +13214,7 @@ var AddBrokerInputSchema = object({
|
|
|
13213
13214
|
});
|
|
13214
13215
|
var AddBrokerResultSchema = object({ id: string() });
|
|
13215
13216
|
var IdInputSchema = object({ id: string() });
|
|
13216
|
-
var TestResultSchema = discriminatedUnion("ok", [object({
|
|
13217
|
+
var TestResultSchema$1 = discriminatedUnion("ok", [object({
|
|
13217
13218
|
ok: literal(true),
|
|
13218
13219
|
latencyMs: number()
|
|
13219
13220
|
}), object({
|
|
@@ -13236,7 +13237,7 @@ var StatusSchema = object({
|
|
|
13236
13237
|
brokerCount: number(),
|
|
13237
13238
|
embeddedRunning: boolean()
|
|
13238
13239
|
});
|
|
13239
|
-
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);
|
|
13240
13241
|
var NetworkEndpointSchema = object({
|
|
13241
13242
|
url: string(),
|
|
13242
13243
|
hostname: string(),
|
|
@@ -13270,29 +13271,210 @@ var NetworkEndpointEntrySchema = NetworkEndpointSchema.extend({
|
|
|
13270
13271
|
sourcePort: number().optional()
|
|
13271
13272
|
});
|
|
13272
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;
|
|
13273
13453
|
var notificationOutputCapability = {
|
|
13274
13454
|
name: "notification-output",
|
|
13275
13455
|
scope: "system",
|
|
13276
13456
|
mode: "collection",
|
|
13277
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)),
|
|
13278
13464
|
send: method(object({
|
|
13279
|
-
|
|
13280
|
-
|
|
13281
|
-
|
|
13282
|
-
|
|
13283
|
-
|
|
13284
|
-
|
|
13285
|
-
|
|
13286
|
-
|
|
13287
|
-
|
|
13288
|
-
|
|
13289
|
-
|
|
13290
|
-
|
|
13291
|
-
}), _void(), { kind: "mutation" })
|
|
13292
|
-
sendTest: method(_void(), object({
|
|
13293
|
-
success: boolean(),
|
|
13294
|
-
error: string().optional()
|
|
13295
|
-
}), { 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" })
|
|
13296
13478
|
}
|
|
13297
13479
|
};
|
|
13298
13480
|
/**
|
|
@@ -19289,13 +19471,49 @@ Object.freeze({
|
|
|
19289
19471
|
addonId: null,
|
|
19290
19472
|
access: "create"
|
|
19291
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
|
+
},
|
|
19292
19498
|
"notificationOutput.send": {
|
|
19293
19499
|
capName: "notification-output",
|
|
19294
19500
|
capScope: "system",
|
|
19295
19501
|
addonId: null,
|
|
19296
19502
|
access: "create"
|
|
19297
19503
|
},
|
|
19298
|
-
"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": {
|
|
19299
19517
|
capName: "notification-output",
|
|
19300
19518
|
capScope: "system",
|
|
19301
19519
|
addonId: null,
|
|
@@ -21423,15 +21641,14 @@ var ConsoleOutput = class {
|
|
|
21423
21641
|
this.logger = logger;
|
|
21424
21642
|
}
|
|
21425
21643
|
async send(notification) {
|
|
21426
|
-
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);
|
|
21427
21645
|
}
|
|
21428
21646
|
async sendTest() {
|
|
21429
21647
|
await this.send({
|
|
21430
21648
|
title: "Test",
|
|
21431
|
-
|
|
21432
|
-
|
|
21433
|
-
|
|
21434
|
-
timestamp: Date.now()
|
|
21649
|
+
body: "Console output working",
|
|
21650
|
+
format: "text",
|
|
21651
|
+
priority: 3
|
|
21435
21652
|
});
|
|
21436
21653
|
return { success: true };
|
|
21437
21654
|
}
|
|
@@ -21699,12 +21916,11 @@ var AdvancedNotifierAddon = class extends BaseAddon {
|
|
|
21699
21916
|
const deviceId = Number.isFinite(deviceIdNum) ? deviceIdNum : void 0;
|
|
21700
21917
|
const notification = {
|
|
21701
21918
|
title,
|
|
21702
|
-
message,
|
|
21703
|
-
|
|
21704
|
-
|
|
21919
|
+
body: message,
|
|
21920
|
+
format: "text",
|
|
21921
|
+
priority: this.priorityToOrdinal(rule.priority),
|
|
21705
21922
|
deviceId,
|
|
21706
|
-
|
|
21707
|
-
timestamp: event.timestamp.getTime()
|
|
21923
|
+
metadata: event.data
|
|
21708
21924
|
};
|
|
21709
21925
|
let success = true;
|
|
21710
21926
|
let dispatchError;
|
|
@@ -21749,10 +21965,18 @@ var AdvancedNotifierAddon = class extends BaseAddon {
|
|
|
21749
21965
|
timestamp: event.timestamp.toISOString()
|
|
21750
21966
|
};
|
|
21751
21967
|
}
|
|
21752
|
-
|
|
21753
|
-
|
|
21754
|
-
|
|
21755
|
-
|
|
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
|
+
}
|
|
21756
21980
|
}
|
|
21757
21981
|
};
|
|
21758
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) {
|