@camstack/addon-smtp-nodemailer 1.2.26 → 1.2.27
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/smtp.addon.js +184 -34
- package/dist/smtp.addon.mjs +184 -34
- package/package.json +1 -1
package/dist/smtp.addon.js
CHANGED
|
@@ -5838,6 +5838,13 @@ var BaseAddon = class {
|
|
|
5838
5838
|
_readinessGeneration = typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).slice(2, 14);
|
|
5839
5839
|
/** Capability names this addon registered at init — used to emit matching `down` events on shutdown. */
|
|
5840
5840
|
_registeredCapNames = [];
|
|
5841
|
+
/**
|
|
5842
|
+
* True only after `readAddonStore` actually answered. Constructor
|
|
5843
|
+
* defaults look like stored config when the store is down — a forked
|
|
5844
|
+
* addon that auto-starts from those defaults (cloudflare-tunnel quick
|
|
5845
|
+
* mode, 2026-08-25) is not "the operator chose this".
|
|
5846
|
+
*/
|
|
5847
|
+
settingsStoreReady = false;
|
|
5841
5848
|
/** Default config values. Provided via constructor. */
|
|
5842
5849
|
defaults;
|
|
5843
5850
|
constructor(defaults) {
|
|
@@ -6238,7 +6245,9 @@ var BaseAddon = class {
|
|
|
6238
6245
|
];
|
|
6239
6246
|
let lastErr;
|
|
6240
6247
|
for (let attempt = 0; attempt <= delaysMs.length; attempt++) try {
|
|
6241
|
-
|
|
6248
|
+
const stored = await settings.readAddonStore() ?? {};
|
|
6249
|
+
this.settingsStoreReady = true;
|
|
6250
|
+
return stored;
|
|
6242
6251
|
} catch (err) {
|
|
6243
6252
|
lastErr = err;
|
|
6244
6253
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -6246,6 +6255,7 @@ var BaseAddon = class {
|
|
|
6246
6255
|
if (attempt === delaysMs.length) break;
|
|
6247
6256
|
await new Promise((r) => setTimeout(r, delaysMs[attempt]));
|
|
6248
6257
|
}
|
|
6258
|
+
this.settingsStoreReady = false;
|
|
6249
6259
|
this._ctx?.logger?.warn?.("readAddonStore: settings-store unavailable after retries — using defaults", { meta: { error: lastErr instanceof Error ? lastErr.message : String(lastErr) } });
|
|
6250
6260
|
return {};
|
|
6251
6261
|
}
|
|
@@ -8133,6 +8143,12 @@ var ModelVariantGroupSchema = object({
|
|
|
8133
8143
|
*/
|
|
8134
8144
|
resolution: number().int().positive().optional()
|
|
8135
8145
|
});
|
|
8146
|
+
var ModelProviderIdSchema = _enum([
|
|
8147
|
+
"camstack",
|
|
8148
|
+
"frigate",
|
|
8149
|
+
"scrypted",
|
|
8150
|
+
"custom"
|
|
8151
|
+
]);
|
|
8136
8152
|
var ModelCatalogEntrySchema = object({
|
|
8137
8153
|
id: string(),
|
|
8138
8154
|
name: string(),
|
|
@@ -8230,6 +8246,12 @@ var ModelCatalogEntrySchema = object({
|
|
|
8230
8246
|
*/
|
|
8231
8247
|
group: ModelVariantGroupSchema.optional(),
|
|
8232
8248
|
/**
|
|
8249
|
+
* Catalog source for the pipeline stepper's provider-first picker. Absent on
|
|
8250
|
+
* built-in CamStack entries (treated as `camstack`) and on registry rows
|
|
8251
|
+
* persisted before this field existed (`inferModelProvider` fills those).
|
|
8252
|
+
*/
|
|
8253
|
+
provider: ModelProviderIdSchema.optional(),
|
|
8254
|
+
/**
|
|
8233
8255
|
* Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
|
|
8234
8256
|
* applies (Frigate / COCO public catalog). Set on a custom model whose raw
|
|
8235
8257
|
* labels already ARE the CamStack macros (Scrypted identity map).
|
|
@@ -11757,6 +11779,27 @@ var LinkedDeviceSchema = object({
|
|
|
11757
11779
|
features: array(string()),
|
|
11758
11780
|
producesTrackedEvents: boolean().optional()
|
|
11759
11781
|
});
|
|
11782
|
+
/** One camera's resolved linked set, tagged with the camera it belongs to.
|
|
11783
|
+
* The batch answer needs the tag; the single-device answer already has it
|
|
11784
|
+
* from the input, which is why `getLinkedDevices` keeps the untagged shape. */
|
|
11785
|
+
var LinkedDevicesForDeviceSchema = object({
|
|
11786
|
+
deviceId: number(),
|
|
11787
|
+
mode: LinkedDevicesModeSchema,
|
|
11788
|
+
devices: array(LinkedDeviceSchema)
|
|
11789
|
+
});
|
|
11790
|
+
/** One device's binding map — the shape `getBindings`, `getBindingsBatch` and
|
|
11791
|
+
* `getAllBindings` all answer in. Declared once: three copies of the same
|
|
11792
|
+
* object literal is exactly how the three drift apart. */
|
|
11793
|
+
var DeviceBindingsForDeviceSchema = object({
|
|
11794
|
+
deviceId: number(),
|
|
11795
|
+
entries: array(object({
|
|
11796
|
+
capName: string(),
|
|
11797
|
+
kind: _enum(["native", "wrapped"]),
|
|
11798
|
+
providerAddonId: string(),
|
|
11799
|
+
providerNodeId: string(),
|
|
11800
|
+
nativeAddonId: string()
|
|
11801
|
+
}))
|
|
11802
|
+
});
|
|
11760
11803
|
var SavedDeviceRowSchema = object({
|
|
11761
11804
|
/** Numeric id reserved at allocateDeviceId time. */
|
|
11762
11805
|
id: number(),
|
|
@@ -11982,11 +12025,25 @@ method(object({
|
|
|
11982
12025
|
projection: _enum(["full", "slim"]).optional(),
|
|
11983
12026
|
/** Return only camera devices. Filtering server-side instead of
|
|
11984
12027
|
* shipping 293 rows to find 12. */
|
|
11985
|
-
isCamera: boolean().optional()
|
|
12028
|
+
isCamera: boolean().optional(),
|
|
12029
|
+
/**
|
|
12030
|
+
* Return only these device ids. For the caller that already KNOWS the
|
|
12031
|
+
* handful it wants and needs a field the id-bearing answer does not
|
|
12032
|
+
* carry — the viewer's linked-devices panel joins `type` and `online`
|
|
12033
|
+
* onto ~8 linked ids and, unfiltered, dragged the fleet across to do
|
|
12034
|
+
* it: 433 KB slim / 958 KB full for 967 devices, on a query that
|
|
12035
|
+
* refetches on the reconcile interval, on a phone.
|
|
12036
|
+
*
|
|
12037
|
+
* Safe to send at a hub that predates it: Zod STRIPS unknown input
|
|
12038
|
+
* keys rather than rejecting them (verified against the live hub
|
|
12039
|
+
* 2026-08-25 — 967 rows came back), so an old hub answers exactly what
|
|
12040
|
+
* it answers today and the caller filters as it already does.
|
|
12041
|
+
*/
|
|
12042
|
+
deviceIds: array(number()).optional()
|
|
11986
12043
|
}), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), object({
|
|
11987
12044
|
mode: LinkedDevicesModeSchema,
|
|
11988
12045
|
devices: array(LinkedDeviceSchema)
|
|
11989
|
-
})), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
12046
|
+
})), method(object({ deviceIds: array(number()) }), array(LinkedDevicesForDeviceSchema)), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
11990
12047
|
deviceId: number(),
|
|
11991
12048
|
values: record(string(), unknown())
|
|
11992
12049
|
}), object({ success: literal(true) }), {
|
|
@@ -12013,25 +12070,7 @@ method(object({
|
|
|
12013
12070
|
}), method(object({ deviceId: number() }), array(StreamProbeResultSchema), {
|
|
12014
12071
|
kind: "mutation",
|
|
12015
12072
|
auth: "admin"
|
|
12016
|
-
}), method(object({ deviceId: number() }), object({
|
|
12017
|
-
deviceId: number(),
|
|
12018
|
-
entries: array(object({
|
|
12019
|
-
capName: string(),
|
|
12020
|
-
kind: _enum(["native", "wrapped"]),
|
|
12021
|
-
providerAddonId: string(),
|
|
12022
|
-
providerNodeId: string(),
|
|
12023
|
-
nativeAddonId: string()
|
|
12024
|
-
}))
|
|
12025
|
-
})), method(object({}), array(object({
|
|
12026
|
-
deviceId: number(),
|
|
12027
|
-
entries: array(object({
|
|
12028
|
-
capName: string(),
|
|
12029
|
-
kind: _enum(["native", "wrapped"]),
|
|
12030
|
-
providerAddonId: string(),
|
|
12031
|
-
providerNodeId: string(),
|
|
12032
|
-
nativeAddonId: string()
|
|
12033
|
-
}))
|
|
12034
|
-
}))), method(object({
|
|
12073
|
+
}), method(object({ deviceId: number() }), DeviceBindingsForDeviceSchema), method(object({ deviceIds: array(number()) }), array(DeviceBindingsForDeviceSchema)), method(object({}), array(DeviceBindingsForDeviceSchema)), method(object({
|
|
12035
12074
|
deviceId: number(),
|
|
12036
12075
|
capName: string(),
|
|
12037
12076
|
wrapperAddonId: string(),
|
|
@@ -14403,12 +14442,15 @@ var NcOccupancyConditionSchema = object({
|
|
|
14403
14442
|
* there is no second switch that can disagree with the first and every rule
|
|
14404
14443
|
* authored before the decision migrates for free (`audioModeOf`):
|
|
14405
14444
|
*
|
|
14406
|
-
* - **LABEL mode — `labels` present.** The rule fires
|
|
14407
|
-
*
|
|
14408
|
-
* `hitPercent` and `samplingSeconds` are ignored
|
|
14409
|
-
*
|
|
14410
|
-
*
|
|
14411
|
-
*
|
|
14445
|
+
* - **LABEL mode — `labels` present.** The rule fires when `confirmHits`
|
|
14446
|
+
* labelled frames land inside `confirmWindowSec` (default 2 in 5 s).
|
|
14447
|
+
* `hitPercent` and `samplingSeconds` are still ignored — a percentage of
|
|
14448
|
+
* frames is the wrong question for a classifier that labels 1–3 frames
|
|
14449
|
+
* per episode. The count window is the brake that drops a single-frame
|
|
14450
|
+
* false positive; the rule's own `throttle` cooldown is the other. The
|
|
14451
|
+
* per-label confidence floor is the analyzer's (`classificationMinScore`,
|
|
14452
|
+
* per device) — a label only reaches this condition if the classifier was
|
|
14453
|
+
* already confident enough. `confirmHits: 1` restores first-frame fire.
|
|
14412
14454
|
* - **LEVEL mode — `dbThreshold` present, no labels.** The sampling window IS
|
|
14413
14455
|
* the condition: at least `hitPercent`% of the samples over
|
|
14414
14456
|
* `samplingSeconds` must be at or above `dbThreshold` dBFS (see
|
|
@@ -14435,14 +14477,22 @@ var NcOccupancyConditionSchema = object({
|
|
|
14435
14477
|
* an operator who typed `dog` mean the same thing.
|
|
14436
14478
|
*/
|
|
14437
14479
|
var NcAudioConditionSchema = object({
|
|
14438
|
-
/** LABEL MODE: audio macro labels. Present ⇒
|
|
14480
|
+
/** LABEL MODE: audio macro labels. Present ⇒ count-in-window confirm. */
|
|
14439
14481
|
labels: array(string().min(1)).min(1).optional(),
|
|
14440
14482
|
/** LEVEL MODE: floor in dBFS (negative-going, `0` = full scale). */
|
|
14441
14483
|
dbThreshold: number().min(-96).max(0).optional(),
|
|
14442
14484
|
/** LEVEL MODE ONLY: percentage of the window's samples that must be hits (1–100). */
|
|
14443
14485
|
hitPercent: number().int().min(1).max(100).default(60),
|
|
14444
14486
|
/** LEVEL MODE ONLY: length of the sampling window in seconds. */
|
|
14445
|
-
samplingSeconds: number().int().min(1).max(300).default(10)
|
|
14487
|
+
samplingSeconds: number().int().min(1).max(300).default(10),
|
|
14488
|
+
/**
|
|
14489
|
+
* LABEL MODE: how many labelled frames must land inside
|
|
14490
|
+
* {@link NcAudioConditionSchema.shape.confirmWindowSec} before dispatch.
|
|
14491
|
+
* Absent ⇒ 2 (the matcher default). `1` is first-frame fire.
|
|
14492
|
+
*/
|
|
14493
|
+
confirmHits: number().int().min(1).max(20).optional(),
|
|
14494
|
+
/** LABEL MODE: the window those frames must share, in seconds. Absent ⇒ 5. */
|
|
14495
|
+
confirmWindowSec: number().int().min(1).max(60).optional()
|
|
14446
14496
|
});
|
|
14447
14497
|
/**
|
|
14448
14498
|
* Which zone-crossing DIRECTION a rule accepts (`ObjectEvent.zoneCrossing`).
|
|
@@ -16816,6 +16866,46 @@ var RecentTracksPageSchema = object({
|
|
|
16816
16866
|
/** Cursor for the next page, or null when this page is the last. */
|
|
16817
16867
|
nextCursor: string().nullable()
|
|
16818
16868
|
});
|
|
16869
|
+
var LIST_GROUPS_DEFAULT_LIMIT = 40;
|
|
16870
|
+
var LIST_GROUPS_MAX_LIMIT = 100;
|
|
16871
|
+
var AnalyticsGroupRecordSchema = object({
|
|
16872
|
+
id: string(),
|
|
16873
|
+
deviceId: number().int(),
|
|
16874
|
+
openedAt: number().int(),
|
|
16875
|
+
closedAt: number().int(),
|
|
16876
|
+
timestamp: number().int(),
|
|
16877
|
+
memberCount: number().int(),
|
|
16878
|
+
memberTrackIds: array(string()).readonly(),
|
|
16879
|
+
className: string(),
|
|
16880
|
+
classes: array(string()).readonly(),
|
|
16881
|
+
/** Relative event-media path, or null when the group has no picture yet. */
|
|
16882
|
+
mediaUrl: string().nullable(),
|
|
16883
|
+
singleton: boolean()
|
|
16884
|
+
});
|
|
16885
|
+
var AnalyticsGroupMemberSchema = object({
|
|
16886
|
+
trackId: string(),
|
|
16887
|
+
deviceId: number().int(),
|
|
16888
|
+
className: string(),
|
|
16889
|
+
firstSeen: number().int(),
|
|
16890
|
+
lastSeen: number().int(),
|
|
16891
|
+
mediaUrl: string().nullable()
|
|
16892
|
+
});
|
|
16893
|
+
var AnalyticsGroupDetailSchema = AnalyticsGroupRecordSchema.extend({ members: array(AnalyticsGroupMemberSchema).readonly() });
|
|
16894
|
+
var ListGroupsQueryInput = object({
|
|
16895
|
+
/** Devices to merge. An empty array yields `{ groups: [], nextCursor: null }`. */
|
|
16896
|
+
deviceIds: array(number()),
|
|
16897
|
+
/** Window lower bound on `closedAt` (inclusive). */
|
|
16898
|
+
since: number().optional(),
|
|
16899
|
+
/** Window upper bound on `openedAt` (inclusive). */
|
|
16900
|
+
until: number().optional(),
|
|
16901
|
+
limit: number().int().min(1).max(LIST_GROUPS_MAX_LIMIT).default(LIST_GROUPS_DEFAULT_LIMIT),
|
|
16902
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`. */
|
|
16903
|
+
cursor: string().optional()
|
|
16904
|
+
});
|
|
16905
|
+
var ListGroupsPageSchema = object({
|
|
16906
|
+
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
16907
|
+
nextCursor: string().nullable()
|
|
16908
|
+
});
|
|
16819
16909
|
var KeyEventQueryInput = object({
|
|
16820
16910
|
deviceId: number(),
|
|
16821
16911
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
@@ -16891,7 +16981,9 @@ var TrackCascadeCountsSchema = object({
|
|
|
16891
16981
|
/** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
|
|
16892
16982
|
plates: number().int(),
|
|
16893
16983
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
16894
|
-
embeddings: number().int()
|
|
16984
|
+
embeddings: number().int(),
|
|
16985
|
+
/** Group membership + group rows removed with their last member (best-effort). */
|
|
16986
|
+
groups: number().int()
|
|
16895
16987
|
});
|
|
16896
16988
|
/** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
|
|
16897
16989
|
var DiskReconcileCountsSchema = object({
|
|
@@ -17037,7 +17129,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
17037
17129
|
* stationary registry). Default false: the timeline lists passages,
|
|
17038
17130
|
* not parking records (operator decision, 2026-08-15). */
|
|
17039
17131
|
includeStationary: boolean().optional()
|
|
17040
|
-
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(
|
|
17132
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(ListGroupsQueryInput, ListGroupsPageSchema), method(object({
|
|
17133
|
+
deviceId: number(),
|
|
17134
|
+
groupId: string().min(1)
|
|
17135
|
+
}), AnalyticsGroupDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
17041
17136
|
kind: "mutation",
|
|
17042
17137
|
auth: "admin"
|
|
17043
17138
|
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(EventKindsForDeviceSchema).readonly()), method(object({
|
|
@@ -17347,7 +17442,8 @@ var PipelineModelOptionSchema = object({
|
|
|
17347
17442
|
sizeMB: number()
|
|
17348
17443
|
})),
|
|
17349
17444
|
group: ModelVariantGroupSchema.optional(),
|
|
17350
|
-
legacy: boolean().optional()
|
|
17445
|
+
legacy: boolean().optional(),
|
|
17446
|
+
provider: ModelProviderIdSchema.optional()
|
|
17351
17447
|
});
|
|
17352
17448
|
var ConfigFieldBridge = custom();
|
|
17353
17449
|
var PipelineAddonSchemaSchema = object({
|
|
@@ -23944,7 +24040,12 @@ var PlateInfoSchema = object({
|
|
|
23944
24040
|
plateBbox: BoundingBoxSchema.optional(),
|
|
23945
24041
|
/** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
|
|
23946
24042
|
keyFrameMediaKey: string().optional(),
|
|
23947
|
-
base64: string().optional()
|
|
24043
|
+
base64: string().optional(),
|
|
24044
|
+
/**
|
|
24045
|
+
* Same crop as a data-plane URL. `getPlateByTrack` returns this and
|
|
24046
|
+
* never inlines JPEG; `listPlates` still inlines for the admin-ui.
|
|
24047
|
+
*/
|
|
24048
|
+
cropUrl: string().optional()
|
|
23948
24049
|
});
|
|
23949
24050
|
var MediaFileLiteSchema = object({
|
|
23950
24051
|
key: string(),
|
|
@@ -27584,6 +27685,12 @@ Object.freeze({
|
|
|
27584
27685
|
addonId: null,
|
|
27585
27686
|
access: "view"
|
|
27586
27687
|
},
|
|
27688
|
+
"deviceManager.getBindingsBatch": {
|
|
27689
|
+
capName: "device-manager",
|
|
27690
|
+
capScope: "system",
|
|
27691
|
+
addonId: null,
|
|
27692
|
+
access: "view"
|
|
27693
|
+
},
|
|
27587
27694
|
"deviceManager.getChildren": {
|
|
27588
27695
|
capName: "device-manager",
|
|
27589
27696
|
capScope: "system",
|
|
@@ -27644,6 +27751,12 @@ Object.freeze({
|
|
|
27644
27751
|
addonId: null,
|
|
27645
27752
|
access: "view"
|
|
27646
27753
|
},
|
|
27754
|
+
"deviceManager.getLinkedDevicesBatch": {
|
|
27755
|
+
capName: "device-manager",
|
|
27756
|
+
capScope: "system",
|
|
27757
|
+
addonId: null,
|
|
27758
|
+
access: "view"
|
|
27759
|
+
},
|
|
27647
27760
|
"deviceManager.getRoleDisplayDefaults": {
|
|
27648
27761
|
capName: "device-manager",
|
|
27649
27762
|
capScope: "system",
|
|
@@ -29414,6 +29527,12 @@ Object.freeze({
|
|
|
29414
29527
|
addonId: null,
|
|
29415
29528
|
access: "view"
|
|
29416
29529
|
},
|
|
29530
|
+
"pipelineAnalytics.getGroup": {
|
|
29531
|
+
capName: "pipeline-analytics",
|
|
29532
|
+
capScope: "device",
|
|
29533
|
+
addonId: null,
|
|
29534
|
+
access: "view"
|
|
29535
|
+
},
|
|
29417
29536
|
"pipelineAnalytics.getKeyEvents": {
|
|
29418
29537
|
capName: "pipeline-analytics",
|
|
29419
29538
|
capScope: "device",
|
|
@@ -29498,6 +29617,12 @@ Object.freeze({
|
|
|
29498
29617
|
addonId: null,
|
|
29499
29618
|
access: "view"
|
|
29500
29619
|
},
|
|
29620
|
+
"pipelineAnalytics.listGroups": {
|
|
29621
|
+
capName: "pipeline-analytics",
|
|
29622
|
+
capScope: "device",
|
|
29623
|
+
addonId: null,
|
|
29624
|
+
access: "view"
|
|
29625
|
+
},
|
|
29501
29626
|
"pipelineAnalytics.listOpsLog": {
|
|
29502
29627
|
capName: "pipeline-analytics",
|
|
29503
29628
|
capScope: "device",
|
|
@@ -32279,6 +32404,11 @@ Object.freeze({
|
|
|
32279
32404
|
form: "single",
|
|
32280
32405
|
optional: false
|
|
32281
32406
|
}],
|
|
32407
|
+
"deviceManager.getBindingsBatch": [{
|
|
32408
|
+
name: "deviceIds",
|
|
32409
|
+
form: "array",
|
|
32410
|
+
optional: false
|
|
32411
|
+
}],
|
|
32282
32412
|
"deviceManager.getChildren": [{
|
|
32283
32413
|
name: "parentDeviceId",
|
|
32284
32414
|
form: "single",
|
|
@@ -32324,6 +32454,11 @@ Object.freeze({
|
|
|
32324
32454
|
form: "single",
|
|
32325
32455
|
optional: false
|
|
32326
32456
|
}],
|
|
32457
|
+
"deviceManager.getLinkedDevicesBatch": [{
|
|
32458
|
+
name: "deviceIds",
|
|
32459
|
+
form: "array",
|
|
32460
|
+
optional: false
|
|
32461
|
+
}],
|
|
32327
32462
|
"deviceManager.getSettingsSchema": [{
|
|
32328
32463
|
name: "deviceId",
|
|
32329
32464
|
form: "single",
|
|
@@ -32344,6 +32479,11 @@ Object.freeze({
|
|
|
32344
32479
|
form: "single",
|
|
32345
32480
|
optional: false
|
|
32346
32481
|
}],
|
|
32482
|
+
"deviceManager.listAll": [{
|
|
32483
|
+
name: "deviceIds",
|
|
32484
|
+
form: "array",
|
|
32485
|
+
optional: true
|
|
32486
|
+
}],
|
|
32347
32487
|
"deviceManager.loadConfig": [{
|
|
32348
32488
|
name: "deviceId",
|
|
32349
32489
|
form: "single",
|
|
@@ -32917,6 +33057,11 @@ Object.freeze({
|
|
|
32917
33057
|
form: "single",
|
|
32918
33058
|
optional: false
|
|
32919
33059
|
}],
|
|
33060
|
+
"pipelineAnalytics.getGroup": [{
|
|
33061
|
+
name: "deviceId",
|
|
33062
|
+
form: "single",
|
|
33063
|
+
optional: false
|
|
33064
|
+
}],
|
|
32920
33065
|
"pipelineAnalytics.getKeyEvents": [{
|
|
32921
33066
|
name: "deviceId",
|
|
32922
33067
|
form: "single",
|
|
@@ -32972,6 +33117,11 @@ Object.freeze({
|
|
|
32972
33117
|
form: "array",
|
|
32973
33118
|
optional: false
|
|
32974
33119
|
}],
|
|
33120
|
+
"pipelineAnalytics.listGroups": [{
|
|
33121
|
+
name: "deviceIds",
|
|
33122
|
+
form: "array",
|
|
33123
|
+
optional: false
|
|
33124
|
+
}],
|
|
32975
33125
|
"pipelineAnalytics.listOpsLog": [{
|
|
32976
33126
|
name: "deviceId",
|
|
32977
33127
|
form: "single",
|
package/dist/smtp.addon.mjs
CHANGED
|
@@ -5836,6 +5836,13 @@ var BaseAddon = class {
|
|
|
5836
5836
|
_readinessGeneration = typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).slice(2, 14);
|
|
5837
5837
|
/** Capability names this addon registered at init — used to emit matching `down` events on shutdown. */
|
|
5838
5838
|
_registeredCapNames = [];
|
|
5839
|
+
/**
|
|
5840
|
+
* True only after `readAddonStore` actually answered. Constructor
|
|
5841
|
+
* defaults look like stored config when the store is down — a forked
|
|
5842
|
+
* addon that auto-starts from those defaults (cloudflare-tunnel quick
|
|
5843
|
+
* mode, 2026-08-25) is not "the operator chose this".
|
|
5844
|
+
*/
|
|
5845
|
+
settingsStoreReady = false;
|
|
5839
5846
|
/** Default config values. Provided via constructor. */
|
|
5840
5847
|
defaults;
|
|
5841
5848
|
constructor(defaults) {
|
|
@@ -6236,7 +6243,9 @@ var BaseAddon = class {
|
|
|
6236
6243
|
];
|
|
6237
6244
|
let lastErr;
|
|
6238
6245
|
for (let attempt = 0; attempt <= delaysMs.length; attempt++) try {
|
|
6239
|
-
|
|
6246
|
+
const stored = await settings.readAddonStore() ?? {};
|
|
6247
|
+
this.settingsStoreReady = true;
|
|
6248
|
+
return stored;
|
|
6240
6249
|
} catch (err) {
|
|
6241
6250
|
lastErr = err;
|
|
6242
6251
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -6244,6 +6253,7 @@ var BaseAddon = class {
|
|
|
6244
6253
|
if (attempt === delaysMs.length) break;
|
|
6245
6254
|
await new Promise((r) => setTimeout(r, delaysMs[attempt]));
|
|
6246
6255
|
}
|
|
6256
|
+
this.settingsStoreReady = false;
|
|
6247
6257
|
this._ctx?.logger?.warn?.("readAddonStore: settings-store unavailable after retries — using defaults", { meta: { error: lastErr instanceof Error ? lastErr.message : String(lastErr) } });
|
|
6248
6258
|
return {};
|
|
6249
6259
|
}
|
|
@@ -8131,6 +8141,12 @@ var ModelVariantGroupSchema = object({
|
|
|
8131
8141
|
*/
|
|
8132
8142
|
resolution: number().int().positive().optional()
|
|
8133
8143
|
});
|
|
8144
|
+
var ModelProviderIdSchema = _enum([
|
|
8145
|
+
"camstack",
|
|
8146
|
+
"frigate",
|
|
8147
|
+
"scrypted",
|
|
8148
|
+
"custom"
|
|
8149
|
+
]);
|
|
8134
8150
|
var ModelCatalogEntrySchema = object({
|
|
8135
8151
|
id: string(),
|
|
8136
8152
|
name: string(),
|
|
@@ -8228,6 +8244,12 @@ var ModelCatalogEntrySchema = object({
|
|
|
8228
8244
|
*/
|
|
8229
8245
|
group: ModelVariantGroupSchema.optional(),
|
|
8230
8246
|
/**
|
|
8247
|
+
* Catalog source for the pipeline stepper's provider-first picker. Absent on
|
|
8248
|
+
* built-in CamStack entries (treated as `camstack`) and on registry rows
|
|
8249
|
+
* persisted before this field existed (`inferModelProvider` fills those).
|
|
8250
|
+
*/
|
|
8251
|
+
provider: ModelProviderIdSchema.optional(),
|
|
8252
|
+
/**
|
|
8231
8253
|
* Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
|
|
8232
8254
|
* applies (Frigate / COCO public catalog). Set on a custom model whose raw
|
|
8233
8255
|
* labels already ARE the CamStack macros (Scrypted identity map).
|
|
@@ -11755,6 +11777,27 @@ var LinkedDeviceSchema = object({
|
|
|
11755
11777
|
features: array(string()),
|
|
11756
11778
|
producesTrackedEvents: boolean().optional()
|
|
11757
11779
|
});
|
|
11780
|
+
/** One camera's resolved linked set, tagged with the camera it belongs to.
|
|
11781
|
+
* The batch answer needs the tag; the single-device answer already has it
|
|
11782
|
+
* from the input, which is why `getLinkedDevices` keeps the untagged shape. */
|
|
11783
|
+
var LinkedDevicesForDeviceSchema = object({
|
|
11784
|
+
deviceId: number(),
|
|
11785
|
+
mode: LinkedDevicesModeSchema,
|
|
11786
|
+
devices: array(LinkedDeviceSchema)
|
|
11787
|
+
});
|
|
11788
|
+
/** One device's binding map — the shape `getBindings`, `getBindingsBatch` and
|
|
11789
|
+
* `getAllBindings` all answer in. Declared once: three copies of the same
|
|
11790
|
+
* object literal is exactly how the three drift apart. */
|
|
11791
|
+
var DeviceBindingsForDeviceSchema = object({
|
|
11792
|
+
deviceId: number(),
|
|
11793
|
+
entries: array(object({
|
|
11794
|
+
capName: string(),
|
|
11795
|
+
kind: _enum(["native", "wrapped"]),
|
|
11796
|
+
providerAddonId: string(),
|
|
11797
|
+
providerNodeId: string(),
|
|
11798
|
+
nativeAddonId: string()
|
|
11799
|
+
}))
|
|
11800
|
+
});
|
|
11758
11801
|
var SavedDeviceRowSchema = object({
|
|
11759
11802
|
/** Numeric id reserved at allocateDeviceId time. */
|
|
11760
11803
|
id: number(),
|
|
@@ -11980,11 +12023,25 @@ method(object({
|
|
|
11980
12023
|
projection: _enum(["full", "slim"]).optional(),
|
|
11981
12024
|
/** Return only camera devices. Filtering server-side instead of
|
|
11982
12025
|
* shipping 293 rows to find 12. */
|
|
11983
|
-
isCamera: boolean().optional()
|
|
12026
|
+
isCamera: boolean().optional(),
|
|
12027
|
+
/**
|
|
12028
|
+
* Return only these device ids. For the caller that already KNOWS the
|
|
12029
|
+
* handful it wants and needs a field the id-bearing answer does not
|
|
12030
|
+
* carry — the viewer's linked-devices panel joins `type` and `online`
|
|
12031
|
+
* onto ~8 linked ids and, unfiltered, dragged the fleet across to do
|
|
12032
|
+
* it: 433 KB slim / 958 KB full for 967 devices, on a query that
|
|
12033
|
+
* refetches on the reconcile interval, on a phone.
|
|
12034
|
+
*
|
|
12035
|
+
* Safe to send at a hub that predates it: Zod STRIPS unknown input
|
|
12036
|
+
* keys rather than rejecting them (verified against the live hub
|
|
12037
|
+
* 2026-08-25 — 967 rows came back), so an old hub answers exactly what
|
|
12038
|
+
* it answers today and the caller filters as it already does.
|
|
12039
|
+
*/
|
|
12040
|
+
deviceIds: array(number()).optional()
|
|
11984
12041
|
}), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), object({
|
|
11985
12042
|
mode: LinkedDevicesModeSchema,
|
|
11986
12043
|
devices: array(LinkedDeviceSchema)
|
|
11987
|
-
})), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
12044
|
+
})), method(object({ deviceIds: array(number()) }), array(LinkedDevicesForDeviceSchema)), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
11988
12045
|
deviceId: number(),
|
|
11989
12046
|
values: record(string(), unknown())
|
|
11990
12047
|
}), object({ success: literal(true) }), {
|
|
@@ -12011,25 +12068,7 @@ method(object({
|
|
|
12011
12068
|
}), method(object({ deviceId: number() }), array(StreamProbeResultSchema), {
|
|
12012
12069
|
kind: "mutation",
|
|
12013
12070
|
auth: "admin"
|
|
12014
|
-
}), method(object({ deviceId: number() }), object({
|
|
12015
|
-
deviceId: number(),
|
|
12016
|
-
entries: array(object({
|
|
12017
|
-
capName: string(),
|
|
12018
|
-
kind: _enum(["native", "wrapped"]),
|
|
12019
|
-
providerAddonId: string(),
|
|
12020
|
-
providerNodeId: string(),
|
|
12021
|
-
nativeAddonId: string()
|
|
12022
|
-
}))
|
|
12023
|
-
})), method(object({}), array(object({
|
|
12024
|
-
deviceId: number(),
|
|
12025
|
-
entries: array(object({
|
|
12026
|
-
capName: string(),
|
|
12027
|
-
kind: _enum(["native", "wrapped"]),
|
|
12028
|
-
providerAddonId: string(),
|
|
12029
|
-
providerNodeId: string(),
|
|
12030
|
-
nativeAddonId: string()
|
|
12031
|
-
}))
|
|
12032
|
-
}))), method(object({
|
|
12071
|
+
}), method(object({ deviceId: number() }), DeviceBindingsForDeviceSchema), method(object({ deviceIds: array(number()) }), array(DeviceBindingsForDeviceSchema)), method(object({}), array(DeviceBindingsForDeviceSchema)), method(object({
|
|
12033
12072
|
deviceId: number(),
|
|
12034
12073
|
capName: string(),
|
|
12035
12074
|
wrapperAddonId: string(),
|
|
@@ -14401,12 +14440,15 @@ var NcOccupancyConditionSchema = object({
|
|
|
14401
14440
|
* there is no second switch that can disagree with the first and every rule
|
|
14402
14441
|
* authored before the decision migrates for free (`audioModeOf`):
|
|
14403
14442
|
*
|
|
14404
|
-
* - **LABEL mode — `labels` present.** The rule fires
|
|
14405
|
-
*
|
|
14406
|
-
* `hitPercent` and `samplingSeconds` are ignored
|
|
14407
|
-
*
|
|
14408
|
-
*
|
|
14409
|
-
*
|
|
14443
|
+
* - **LABEL mode — `labels` present.** The rule fires when `confirmHits`
|
|
14444
|
+
* labelled frames land inside `confirmWindowSec` (default 2 in 5 s).
|
|
14445
|
+
* `hitPercent` and `samplingSeconds` are still ignored — a percentage of
|
|
14446
|
+
* frames is the wrong question for a classifier that labels 1–3 frames
|
|
14447
|
+
* per episode. The count window is the brake that drops a single-frame
|
|
14448
|
+
* false positive; the rule's own `throttle` cooldown is the other. The
|
|
14449
|
+
* per-label confidence floor is the analyzer's (`classificationMinScore`,
|
|
14450
|
+
* per device) — a label only reaches this condition if the classifier was
|
|
14451
|
+
* already confident enough. `confirmHits: 1` restores first-frame fire.
|
|
14410
14452
|
* - **LEVEL mode — `dbThreshold` present, no labels.** The sampling window IS
|
|
14411
14453
|
* the condition: at least `hitPercent`% of the samples over
|
|
14412
14454
|
* `samplingSeconds` must be at or above `dbThreshold` dBFS (see
|
|
@@ -14433,14 +14475,22 @@ var NcOccupancyConditionSchema = object({
|
|
|
14433
14475
|
* an operator who typed `dog` mean the same thing.
|
|
14434
14476
|
*/
|
|
14435
14477
|
var NcAudioConditionSchema = object({
|
|
14436
|
-
/** LABEL MODE: audio macro labels. Present ⇒
|
|
14478
|
+
/** LABEL MODE: audio macro labels. Present ⇒ count-in-window confirm. */
|
|
14437
14479
|
labels: array(string().min(1)).min(1).optional(),
|
|
14438
14480
|
/** LEVEL MODE: floor in dBFS (negative-going, `0` = full scale). */
|
|
14439
14481
|
dbThreshold: number().min(-96).max(0).optional(),
|
|
14440
14482
|
/** LEVEL MODE ONLY: percentage of the window's samples that must be hits (1–100). */
|
|
14441
14483
|
hitPercent: number().int().min(1).max(100).default(60),
|
|
14442
14484
|
/** LEVEL MODE ONLY: length of the sampling window in seconds. */
|
|
14443
|
-
samplingSeconds: number().int().min(1).max(300).default(10)
|
|
14485
|
+
samplingSeconds: number().int().min(1).max(300).default(10),
|
|
14486
|
+
/**
|
|
14487
|
+
* LABEL MODE: how many labelled frames must land inside
|
|
14488
|
+
* {@link NcAudioConditionSchema.shape.confirmWindowSec} before dispatch.
|
|
14489
|
+
* Absent ⇒ 2 (the matcher default). `1` is first-frame fire.
|
|
14490
|
+
*/
|
|
14491
|
+
confirmHits: number().int().min(1).max(20).optional(),
|
|
14492
|
+
/** LABEL MODE: the window those frames must share, in seconds. Absent ⇒ 5. */
|
|
14493
|
+
confirmWindowSec: number().int().min(1).max(60).optional()
|
|
14444
14494
|
});
|
|
14445
14495
|
/**
|
|
14446
14496
|
* Which zone-crossing DIRECTION a rule accepts (`ObjectEvent.zoneCrossing`).
|
|
@@ -16814,6 +16864,46 @@ var RecentTracksPageSchema = object({
|
|
|
16814
16864
|
/** Cursor for the next page, or null when this page is the last. */
|
|
16815
16865
|
nextCursor: string().nullable()
|
|
16816
16866
|
});
|
|
16867
|
+
var LIST_GROUPS_DEFAULT_LIMIT = 40;
|
|
16868
|
+
var LIST_GROUPS_MAX_LIMIT = 100;
|
|
16869
|
+
var AnalyticsGroupRecordSchema = object({
|
|
16870
|
+
id: string(),
|
|
16871
|
+
deviceId: number().int(),
|
|
16872
|
+
openedAt: number().int(),
|
|
16873
|
+
closedAt: number().int(),
|
|
16874
|
+
timestamp: number().int(),
|
|
16875
|
+
memberCount: number().int(),
|
|
16876
|
+
memberTrackIds: array(string()).readonly(),
|
|
16877
|
+
className: string(),
|
|
16878
|
+
classes: array(string()).readonly(),
|
|
16879
|
+
/** Relative event-media path, or null when the group has no picture yet. */
|
|
16880
|
+
mediaUrl: string().nullable(),
|
|
16881
|
+
singleton: boolean()
|
|
16882
|
+
});
|
|
16883
|
+
var AnalyticsGroupMemberSchema = object({
|
|
16884
|
+
trackId: string(),
|
|
16885
|
+
deviceId: number().int(),
|
|
16886
|
+
className: string(),
|
|
16887
|
+
firstSeen: number().int(),
|
|
16888
|
+
lastSeen: number().int(),
|
|
16889
|
+
mediaUrl: string().nullable()
|
|
16890
|
+
});
|
|
16891
|
+
var AnalyticsGroupDetailSchema = AnalyticsGroupRecordSchema.extend({ members: array(AnalyticsGroupMemberSchema).readonly() });
|
|
16892
|
+
var ListGroupsQueryInput = object({
|
|
16893
|
+
/** Devices to merge. An empty array yields `{ groups: [], nextCursor: null }`. */
|
|
16894
|
+
deviceIds: array(number()),
|
|
16895
|
+
/** Window lower bound on `closedAt` (inclusive). */
|
|
16896
|
+
since: number().optional(),
|
|
16897
|
+
/** Window upper bound on `openedAt` (inclusive). */
|
|
16898
|
+
until: number().optional(),
|
|
16899
|
+
limit: number().int().min(1).max(LIST_GROUPS_MAX_LIMIT).default(LIST_GROUPS_DEFAULT_LIMIT),
|
|
16900
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`. */
|
|
16901
|
+
cursor: string().optional()
|
|
16902
|
+
});
|
|
16903
|
+
var ListGroupsPageSchema = object({
|
|
16904
|
+
groups: array(AnalyticsGroupRecordSchema).readonly(),
|
|
16905
|
+
nextCursor: string().nullable()
|
|
16906
|
+
});
|
|
16817
16907
|
var KeyEventQueryInput = object({
|
|
16818
16908
|
deviceId: number(),
|
|
16819
16909
|
/** Window lower bound (track firstSeen ≥ since). */
|
|
@@ -16889,7 +16979,9 @@ var TrackCascadeCountsSchema = object({
|
|
|
16889
16979
|
/** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
|
|
16890
16980
|
plates: number().int(),
|
|
16891
16981
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
16892
|
-
embeddings: number().int()
|
|
16982
|
+
embeddings: number().int(),
|
|
16983
|
+
/** Group membership + group rows removed with their last member (best-effort). */
|
|
16984
|
+
groups: number().int()
|
|
16893
16985
|
});
|
|
16894
16986
|
/** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
|
|
16895
16987
|
var DiskReconcileCountsSchema = object({
|
|
@@ -17035,7 +17127,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
17035
17127
|
* stationary registry). Default false: the timeline lists passages,
|
|
17036
17128
|
* not parking records (operator decision, 2026-08-15). */
|
|
17037
17129
|
includeStationary: boolean().optional()
|
|
17038
|
-
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(
|
|
17130
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(ListGroupsQueryInput, ListGroupsPageSchema), method(object({
|
|
17131
|
+
deviceId: number(),
|
|
17132
|
+
groupId: string().min(1)
|
|
17133
|
+
}), AnalyticsGroupDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
17039
17134
|
kind: "mutation",
|
|
17040
17135
|
auth: "admin"
|
|
17041
17136
|
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(EventKindsForDeviceSchema).readonly()), method(object({
|
|
@@ -17345,7 +17440,8 @@ var PipelineModelOptionSchema = object({
|
|
|
17345
17440
|
sizeMB: number()
|
|
17346
17441
|
})),
|
|
17347
17442
|
group: ModelVariantGroupSchema.optional(),
|
|
17348
|
-
legacy: boolean().optional()
|
|
17443
|
+
legacy: boolean().optional(),
|
|
17444
|
+
provider: ModelProviderIdSchema.optional()
|
|
17349
17445
|
});
|
|
17350
17446
|
var ConfigFieldBridge = custom();
|
|
17351
17447
|
var PipelineAddonSchemaSchema = object({
|
|
@@ -23942,7 +24038,12 @@ var PlateInfoSchema = object({
|
|
|
23942
24038
|
plateBbox: BoundingBoxSchema.optional(),
|
|
23943
24039
|
/** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
|
|
23944
24040
|
keyFrameMediaKey: string().optional(),
|
|
23945
|
-
base64: string().optional()
|
|
24041
|
+
base64: string().optional(),
|
|
24042
|
+
/**
|
|
24043
|
+
* Same crop as a data-plane URL. `getPlateByTrack` returns this and
|
|
24044
|
+
* never inlines JPEG; `listPlates` still inlines for the admin-ui.
|
|
24045
|
+
*/
|
|
24046
|
+
cropUrl: string().optional()
|
|
23946
24047
|
});
|
|
23947
24048
|
var MediaFileLiteSchema = object({
|
|
23948
24049
|
key: string(),
|
|
@@ -27582,6 +27683,12 @@ Object.freeze({
|
|
|
27582
27683
|
addonId: null,
|
|
27583
27684
|
access: "view"
|
|
27584
27685
|
},
|
|
27686
|
+
"deviceManager.getBindingsBatch": {
|
|
27687
|
+
capName: "device-manager",
|
|
27688
|
+
capScope: "system",
|
|
27689
|
+
addonId: null,
|
|
27690
|
+
access: "view"
|
|
27691
|
+
},
|
|
27585
27692
|
"deviceManager.getChildren": {
|
|
27586
27693
|
capName: "device-manager",
|
|
27587
27694
|
capScope: "system",
|
|
@@ -27642,6 +27749,12 @@ Object.freeze({
|
|
|
27642
27749
|
addonId: null,
|
|
27643
27750
|
access: "view"
|
|
27644
27751
|
},
|
|
27752
|
+
"deviceManager.getLinkedDevicesBatch": {
|
|
27753
|
+
capName: "device-manager",
|
|
27754
|
+
capScope: "system",
|
|
27755
|
+
addonId: null,
|
|
27756
|
+
access: "view"
|
|
27757
|
+
},
|
|
27645
27758
|
"deviceManager.getRoleDisplayDefaults": {
|
|
27646
27759
|
capName: "device-manager",
|
|
27647
27760
|
capScope: "system",
|
|
@@ -29412,6 +29525,12 @@ Object.freeze({
|
|
|
29412
29525
|
addonId: null,
|
|
29413
29526
|
access: "view"
|
|
29414
29527
|
},
|
|
29528
|
+
"pipelineAnalytics.getGroup": {
|
|
29529
|
+
capName: "pipeline-analytics",
|
|
29530
|
+
capScope: "device",
|
|
29531
|
+
addonId: null,
|
|
29532
|
+
access: "view"
|
|
29533
|
+
},
|
|
29415
29534
|
"pipelineAnalytics.getKeyEvents": {
|
|
29416
29535
|
capName: "pipeline-analytics",
|
|
29417
29536
|
capScope: "device",
|
|
@@ -29496,6 +29615,12 @@ Object.freeze({
|
|
|
29496
29615
|
addonId: null,
|
|
29497
29616
|
access: "view"
|
|
29498
29617
|
},
|
|
29618
|
+
"pipelineAnalytics.listGroups": {
|
|
29619
|
+
capName: "pipeline-analytics",
|
|
29620
|
+
capScope: "device",
|
|
29621
|
+
addonId: null,
|
|
29622
|
+
access: "view"
|
|
29623
|
+
},
|
|
29499
29624
|
"pipelineAnalytics.listOpsLog": {
|
|
29500
29625
|
capName: "pipeline-analytics",
|
|
29501
29626
|
capScope: "device",
|
|
@@ -32277,6 +32402,11 @@ Object.freeze({
|
|
|
32277
32402
|
form: "single",
|
|
32278
32403
|
optional: false
|
|
32279
32404
|
}],
|
|
32405
|
+
"deviceManager.getBindingsBatch": [{
|
|
32406
|
+
name: "deviceIds",
|
|
32407
|
+
form: "array",
|
|
32408
|
+
optional: false
|
|
32409
|
+
}],
|
|
32280
32410
|
"deviceManager.getChildren": [{
|
|
32281
32411
|
name: "parentDeviceId",
|
|
32282
32412
|
form: "single",
|
|
@@ -32322,6 +32452,11 @@ Object.freeze({
|
|
|
32322
32452
|
form: "single",
|
|
32323
32453
|
optional: false
|
|
32324
32454
|
}],
|
|
32455
|
+
"deviceManager.getLinkedDevicesBatch": [{
|
|
32456
|
+
name: "deviceIds",
|
|
32457
|
+
form: "array",
|
|
32458
|
+
optional: false
|
|
32459
|
+
}],
|
|
32325
32460
|
"deviceManager.getSettingsSchema": [{
|
|
32326
32461
|
name: "deviceId",
|
|
32327
32462
|
form: "single",
|
|
@@ -32342,6 +32477,11 @@ Object.freeze({
|
|
|
32342
32477
|
form: "single",
|
|
32343
32478
|
optional: false
|
|
32344
32479
|
}],
|
|
32480
|
+
"deviceManager.listAll": [{
|
|
32481
|
+
name: "deviceIds",
|
|
32482
|
+
form: "array",
|
|
32483
|
+
optional: true
|
|
32484
|
+
}],
|
|
32345
32485
|
"deviceManager.loadConfig": [{
|
|
32346
32486
|
name: "deviceId",
|
|
32347
32487
|
form: "single",
|
|
@@ -32915,6 +33055,11 @@ Object.freeze({
|
|
|
32915
33055
|
form: "single",
|
|
32916
33056
|
optional: false
|
|
32917
33057
|
}],
|
|
33058
|
+
"pipelineAnalytics.getGroup": [{
|
|
33059
|
+
name: "deviceId",
|
|
33060
|
+
form: "single",
|
|
33061
|
+
optional: false
|
|
33062
|
+
}],
|
|
32918
33063
|
"pipelineAnalytics.getKeyEvents": [{
|
|
32919
33064
|
name: "deviceId",
|
|
32920
33065
|
form: "single",
|
|
@@ -32970,6 +33115,11 @@ Object.freeze({
|
|
|
32970
33115
|
form: "array",
|
|
32971
33116
|
optional: false
|
|
32972
33117
|
}],
|
|
33118
|
+
"pipelineAnalytics.listGroups": [{
|
|
33119
|
+
name: "deviceIds",
|
|
33120
|
+
form: "array",
|
|
33121
|
+
optional: false
|
|
33122
|
+
}],
|
|
32973
33123
|
"pipelineAnalytics.listOpsLog": [{
|
|
32974
33124
|
name: "deviceId",
|
|
32975
33125
|
form: "single",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-smtp-nodemailer",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.27",
|
|
4
4
|
"description": "SMTP email provider addon for CamStack — wraps `nodemailer` and registers a `smtp-provider` cap collection entry. Used by magic-link login + notifier addons.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|