@camstack/addon-smtp-nodemailer 1.2.152 → 1.2.154
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/CHANGELOG.md +12 -0
- package/dist/smtp.addon.js +612 -614
- package/dist/smtp.addon.mjs +612 -614
- package/package.json +2 -2
package/dist/smtp.addon.js
CHANGED
|
@@ -841,7 +841,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
841
841
|
return EventCategory;
|
|
842
842
|
}({});
|
|
843
843
|
//#endregion
|
|
844
|
-
//#region ../types/dist/device-type-
|
|
844
|
+
//#region ../types/dist/device-type-DxCT0krO.mjs
|
|
845
845
|
/**
|
|
846
846
|
import { errMsg } from '@camstack/types'
|
|
847
847
|
* Extract a human-readable message from an unknown error value.
|
|
@@ -1003,6 +1003,13 @@ var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
|
|
|
1003
1003
|
* filters that want "all devices with on-motion behaviour".
|
|
1004
1004
|
*/
|
|
1005
1005
|
DeviceFeature["MotionTrigger"] = "motion-trigger";
|
|
1006
|
+
/**
|
|
1007
|
+
* Device can be run for a chosen time and then stopped. Mirrors the
|
|
1008
|
+
* `timed-run` wrapper cap — the cap is bound by the core-blocks addon, not by
|
|
1009
|
+
* a driver, so the flag is derived from the device's bindings
|
|
1010
|
+
* (`featuresOfBoundCaps`). Gates the quick-run control in the viewer.
|
|
1011
|
+
*/
|
|
1012
|
+
DeviceFeature["TimedRun"] = "timed-run";
|
|
1006
1013
|
/** Light supports rgb-triplet color via `color` cap. */
|
|
1007
1014
|
DeviceFeature["LightColorRgb"] = "light-color-rgb";
|
|
1008
1015
|
/** Light supports HSV color via `color` cap. */
|
|
@@ -6037,7 +6044,7 @@ var ZodIssueCode = {
|
|
|
6037
6044
|
var ZodFirstPartyTypeKind;
|
|
6038
6045
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
6039
6046
|
//#endregion
|
|
6040
|
-
//#region ../types/dist/sleep-
|
|
6047
|
+
//#region ../types/dist/sleep-CGPZyzB5.mjs
|
|
6041
6048
|
/**
|
|
6042
6049
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
6043
6050
|
* window to float samples (D455).
|
|
@@ -7253,6 +7260,7 @@ var RecordIntegrationInstances = class {
|
|
|
7253
7260
|
this.secretKeys = topLevelSecretKeys(kind.declaration.secretPaths);
|
|
7254
7261
|
this.secretMaps = secretMapKeys(kind.declaration.secretPaths);
|
|
7255
7262
|
this.nameField = kind.declaration.entry?.nameField ?? "name";
|
|
7263
|
+
if (hooks.kindOf === void 0 && hooks.description.kinds.length !== 1) throw new Error(`record kind '${kind.name}': describe().kinds has ${hooks.description.kinds.length} entries, so kindOf is required to say which one an instance is`);
|
|
7256
7264
|
}
|
|
7257
7265
|
/**
|
|
7258
7266
|
* One instance read for the addon's own runtime; null when absent. When the keychain is
|
|
@@ -7294,10 +7302,21 @@ var RecordIntegrationInstances = class {
|
|
|
7294
7302
|
}
|
|
7295
7303
|
return out;
|
|
7296
7304
|
}
|
|
7305
|
+
/** The kind an instance body is of: the provider's `kindOf`, else its one declared kind. */
|
|
7306
|
+
kindOfBody(body) {
|
|
7307
|
+
if (this.hooks.kindOf !== void 0) {
|
|
7308
|
+
const id = this.hooks.kindOf(body);
|
|
7309
|
+
if (!this.hooks.description.kinds.some((declared) => declared.id === id)) throw new Error(`record kind '${this.kind.name}': kindOf returned '${id}', which describe().kinds does not declare (D1013)`);
|
|
7310
|
+
return id;
|
|
7311
|
+
}
|
|
7312
|
+
const only = this.hooks.description.kinds[0];
|
|
7313
|
+
if (only === void 0) throw new Error(`record kind '${this.kind.name}' declares no kinds`);
|
|
7314
|
+
return only.id;
|
|
7315
|
+
}
|
|
7297
7316
|
viewOf(record) {
|
|
7298
7317
|
const shown = secretViewsOf(this.records.owner, this.kind.name, record.id, this.kind.declaration, record.data);
|
|
7299
7318
|
const rawName = record.data[this.nameField];
|
|
7300
|
-
const kind = this.
|
|
7319
|
+
const kind = this.kindOfBody(record.data);
|
|
7301
7320
|
const health = this.hooks.health?.(record.data, record.id);
|
|
7302
7321
|
return {
|
|
7303
7322
|
id: record.id,
|
|
@@ -7305,7 +7324,7 @@ var RecordIntegrationInstances = class {
|
|
|
7305
7324
|
configured: this.hooks.configured(record.data),
|
|
7306
7325
|
enabled: isInstanceEnabled(record.data),
|
|
7307
7326
|
formValues: shown,
|
|
7308
|
-
|
|
7327
|
+
kind,
|
|
7309
7328
|
...health?.status !== void 0 ? { status: health.status } : {},
|
|
7310
7329
|
...health?.lastCheckedAt !== void 0 ? { lastCheckedAt: health.lastCheckedAt } : {}
|
|
7311
7330
|
};
|
|
@@ -8406,7 +8425,7 @@ function boundOf(list) {
|
|
|
8406
8425
|
* Base class for CamStack addons. Eliminates settings boilerplate:
|
|
8407
8426
|
*
|
|
8408
8427
|
* - Typed `config` property with automatic resolution from store + defaults
|
|
8409
|
-
* -
|
|
8428
|
+
* - the scoped settings API (`clusterSettings` / `nodeSettings` / `deviceDefaults`) auto-implemented
|
|
8410
8429
|
* - `getAddonSettings()` / `updateAddonSettings()` auto-implemented
|
|
8411
8430
|
* - `getDeviceSettings()` / `updateDeviceSettings()` auto-implemented
|
|
8412
8431
|
* - `ctx` accessor for the AddonContext (no manual `this.ctxRef` storage)
|
|
@@ -8416,7 +8435,7 @@ function boundOf(list) {
|
|
|
8416
8435
|
* Subclasses override:
|
|
8417
8436
|
* - `onInitialize()` — addon-specific init logic, return ProviderRegistration[]
|
|
8418
8437
|
* - `onShutdown()` — cleanup
|
|
8419
|
-
* - `
|
|
8438
|
+
* - `clusterSettingsSchema()` / `nodeSettingsSchema()` / `deviceSettingsSchema()` — UI schemas
|
|
8420
8439
|
*
|
|
8421
8440
|
* @example
|
|
8422
8441
|
* ```ts
|
|
@@ -8430,7 +8449,7 @@ function boundOf(list) {
|
|
|
8430
8449
|
* super({ maxRetries: 3, endpoint: 'http://localhost' })
|
|
8431
8450
|
* }
|
|
8432
8451
|
*
|
|
8433
|
-
* protected
|
|
8452
|
+
* protected clusterSettingsSchema() {
|
|
8434
8453
|
* return this.schema({
|
|
8435
8454
|
* sections: [{
|
|
8436
8455
|
* id: 'main', title: 'Settings',
|
|
@@ -8473,7 +8492,7 @@ var BaseAddon = class {
|
|
|
8473
8492
|
defaults;
|
|
8474
8493
|
/**
|
|
8475
8494
|
* Hidden-state paths that hold secrets (D787) — values the addon writes
|
|
8476
|
-
* itself (`
|
|
8495
|
+
* itself (`state()`, the scoped writers) that no form field declares.
|
|
8477
8496
|
* Stored in the keychain exactly like a `password` field. Syntax:
|
|
8478
8497
|
* `'snapshotSigningKey'`, `'identity.pincode'`, `'tokens[userId].accessToken'`
|
|
8479
8498
|
* (`key[<id field>]` addresses array items by id, never by index).
|
|
@@ -8483,7 +8502,7 @@ var BaseAddon = class {
|
|
|
8483
8502
|
/**
|
|
8484
8503
|
* D986 M4: the scoped schemas this addon declared, resolved once per capability
|
|
8485
8504
|
* (`loadScopedSchemas`) so the sync readers (`perNodeKeys`, the secret tree, the restart check)
|
|
8486
|
-
* see them. Empty until loaded
|
|
8505
|
+
* see them. Empty until loaded.
|
|
8487
8506
|
*/
|
|
8488
8507
|
_scopedByCap = /* @__PURE__ */ new Map();
|
|
8489
8508
|
_nodeKeysByCap = /* @__PURE__ */ new Map();
|
|
@@ -8669,7 +8688,7 @@ var BaseAddon = class {
|
|
|
8669
8688
|
/** Addon-specific cleanup. Override if needed. */
|
|
8670
8689
|
async onShutdown() {}
|
|
8671
8690
|
/**
|
|
8672
|
-
* Called after config is resolved during
|
|
8691
|
+
* Called after config is resolved during a settings write.
|
|
8673
8692
|
* Override to react to config changes (e.g. restart a sampler, reconnect a service).
|
|
8674
8693
|
* Not called during initialize() — use onInitialize() for initial setup.
|
|
8675
8694
|
*/
|
|
@@ -8698,82 +8717,12 @@ var BaseAddon = class {
|
|
|
8698
8717
|
scopedSettingsCapabilities() {
|
|
8699
8718
|
return [];
|
|
8700
8719
|
}
|
|
8701
|
-
/** Override to provide global-level settings UI schema. */
|
|
8702
|
-
globalSettingsSchema(_cap) {
|
|
8703
|
-
return null;
|
|
8704
|
-
}
|
|
8705
8720
|
/** Override to provide device-level settings UI schema. */
|
|
8706
8721
|
deviceSettingsSchema() {
|
|
8707
8722
|
return null;
|
|
8708
8723
|
}
|
|
8709
8724
|
/**
|
|
8710
|
-
*
|
|
8711
|
-
* ARE the configuration of its integration.
|
|
8712
|
-
*
|
|
8713
|
-
* Return the `ConfigSection.id`s, from {@link globalSettingsSchema}, that an
|
|
8714
|
-
* operator should find on the addon's integration page (System →
|
|
8715
|
-
* Integrations → <name>) rather than only in the cluster-wide list of every
|
|
8716
|
-
* addon. Empty (the default) means the addon has no integration-level
|
|
8717
|
-
* settings and no such surface is offered — this is opt-in, because whether
|
|
8718
|
-
* an addon's configuration IS its integration's configuration depends on the
|
|
8719
|
-
* nature of the integration.
|
|
8720
|
-
*
|
|
8721
|
-
* WHAT THIS IS NOT. It is not a scope. The selected sections keep living in
|
|
8722
|
-
* the ONE global schema, in the ONE addon store, written by the ONE
|
|
8723
|
-
* `updateGlobalSettings` path. There is deliberately no
|
|
8724
|
-
* `updateIntegrationSettings`: a second write path is how a surface acquires
|
|
8725
|
-
* a second store key, and this repo has shipped that twice (`btmPath@hub`,
|
|
8726
|
-
* D266). Selecting sections cannot introduce a key that selecting cannot.
|
|
8727
|
-
*
|
|
8728
|
-
* WHY IT IS A LIST OF SECTION IDS AND NOT A MARKER ON THE SECTION.
|
|
8729
|
-
* `ConfigFieldBase` used to carry `scope?: 'device' | 'global'` and it was
|
|
8730
|
-
* removed with the reason recorded at
|
|
8731
|
-
* `packages/types/src/interfaces/config-ui.ts:249` — *"a field's scope is
|
|
8732
|
-
* determined by WHICH schema it lives in, not by a field-level marker."* A
|
|
8733
|
-
* marker sprinkled across sections also has to borrow a field that already
|
|
8734
|
-
* means something else; borrowing `section.tab` put the literal word
|
|
8735
|
-
* "integration" into an operator-facing tab bar, because `tab` means "how to
|
|
8736
|
-
* GROUP this visually" and cannot also mean "where this lives" (D269
|
|
8737
|
-
* supersedes D268). One declaration, in one place, next to the schema whose
|
|
8738
|
-
* ids it names.
|
|
8739
|
-
*/
|
|
8740
|
-
integrationSettingSections() {
|
|
8741
|
-
return [];
|
|
8742
|
-
}
|
|
8743
|
-
async getGlobalSettings(overlay, cap, nodeId) {
|
|
8744
|
-
await this.loadScopedSchemas(cap);
|
|
8745
|
-
const schema = this.globalSettingsSchema(cap) ?? this.scopedFormSchema(cap);
|
|
8746
|
-
if (!schema) return { sections: [] };
|
|
8747
|
-
const projected = await this.readRawProjectedStore(nodeId, cap);
|
|
8748
|
-
return hydrateSchema(schema, overlay ? await this.overlayKeepingMarkers(projected, overlay) : projected, { inlineSecretsAsViews: true });
|
|
8749
|
-
}
|
|
8750
|
-
/**
|
|
8751
|
-
* The integration-level view of this addon's settings: exactly the sections
|
|
8752
|
-
* named by {@link integrationSettingSections}, hydrated from the SAME store
|
|
8753
|
-
* `getGlobalSettings` reads, and narrowed to cluster-scoped fields.
|
|
8754
|
-
*
|
|
8755
|
-
* Returns `null` when the addon declared nothing — an addon that opts out has
|
|
8756
|
-
* no integration settings surface at all, rather than an empty one that reads
|
|
8757
|
-
* as a failed load.
|
|
8758
|
-
*
|
|
8759
|
-
* Three properties hold BY CONSTRUCTION, which is why they are here in core
|
|
8760
|
-
* and not in whichever UI happens to render this:
|
|
8761
|
-
*
|
|
8762
|
-
* 1. **One key.** The payload is a SUBSET of the global schema, so a field
|
|
8763
|
-
* shown here is the same field, with the same bare key, that the addon's
|
|
8764
|
-
* own page shows. There is no integration-specific writer — callers save
|
|
8765
|
-
* through `updateGlobalSettings` — so a second store key is unreachable,
|
|
8766
|
-
* not merely discouraged.
|
|
8767
|
-
* 2. **No node scope.** `perNode: true` fields are DROPPED. Their store key
|
|
8768
|
-
* is `<key>@<nodeId>` and an integration is not a node; whichever node
|
|
8769
|
-
* such a field silently picked would be a wrong answer for the operator
|
|
8770
|
-
* who opened the page (D266).
|
|
8771
|
-
* 3. **No silent typo.** A declared id that names no section throws. The
|
|
8772
|
-
* alternative — skip it — turns a rename into a surface that quietly
|
|
8773
|
-
* empties, which looks exactly like an addon with nothing to configure.
|
|
8774
|
-
*/
|
|
8775
|
-
/**
|
|
8776
|
-
* The form schema of ONE integration instance, or `null` to use {@link globalSettingsSchema}.
|
|
8725
|
+
* The form schema of ONE integration instance, or `null` to use the scoped form.
|
|
8777
8726
|
*
|
|
8778
8727
|
* Override it only when an `instanceMode: multiple` addon's instances differ: an NVR integration
|
|
8779
8728
|
* needs its connection fields, the default integration the addon's own sections. It is the
|
|
@@ -8946,6 +8895,19 @@ var BaseAddon = class {
|
|
|
8946
8895
|
const overlay = await this.scopedSettingsOverlay(scope, cap, nodeId);
|
|
8947
8896
|
return hydrateSchema(schema, overlay ? await this.overlayKeepingMarkers(stored, overlay) : stored, { inlineSecretsAsViews: true });
|
|
8948
8897
|
}
|
|
8898
|
+
/**
|
|
8899
|
+
* The scoped schemas this addon serves: one entry per loaded (capability, scope), capabilities
|
|
8900
|
+
* in declaration order, scopes in {@link SCOPED_SETTINGS_SCOPES} order. `[]` when it declares
|
|
8901
|
+
* nothing.
|
|
8902
|
+
*/
|
|
8903
|
+
async listScopedSettings() {
|
|
8904
|
+
await this.loadScopedSchemas();
|
|
8905
|
+
return [...this._scopedByCap].flatMap(([cap, entries]) => entries.map((entry) => ({
|
|
8906
|
+
cap,
|
|
8907
|
+
scope: entry.scope,
|
|
8908
|
+
sectionIds: entry.schema.sections.map((section) => section.id)
|
|
8909
|
+
})));
|
|
8910
|
+
}
|
|
8949
8911
|
/** The OPERATOR's write of declared keys of one scope (D787 secret semantics). */
|
|
8950
8912
|
async updateScopedSettings(scope, cap, patch, nodeId) {
|
|
8951
8913
|
this._operatorWriteDepth++;
|
|
@@ -8971,32 +8933,15 @@ var BaseAddon = class {
|
|
|
8971
8933
|
*/
|
|
8972
8934
|
async getIntegrationFormSchema(instance, nodeId) {
|
|
8973
8935
|
const scoped = await this.integrationFormSchema(instance);
|
|
8974
|
-
if (scoped === null) return this.
|
|
8936
|
+
if (scoped === null) return this.scopedForm(nodeId);
|
|
8975
8937
|
return hydrateSchema(scoped, {}, { inlineSecretsAsViews: true });
|
|
8976
8938
|
}
|
|
8977
|
-
|
|
8978
|
-
|
|
8979
|
-
|
|
8980
|
-
const schema = this.
|
|
8981
|
-
if (!schema)
|
|
8982
|
-
|
|
8983
|
-
const sections = [];
|
|
8984
|
-
for (const id of declared) {
|
|
8985
|
-
const section = byId.get(id);
|
|
8986
|
-
if (!section) throw new Error(`${this.constructor.name}: integrationSettingSections() names unknown section "${id}". Known sections: [${[...byId.keys()].join(", ")}].`);
|
|
8987
|
-
const fields = dropPerNodeFields(section.fields);
|
|
8988
|
-
if (fields.length === 0) continue;
|
|
8989
|
-
sections.push({
|
|
8990
|
-
...section,
|
|
8991
|
-
fields
|
|
8992
|
-
});
|
|
8993
|
-
}
|
|
8994
|
-
if (sections.length === 0) return null;
|
|
8995
|
-
const projected = await this.readRawProjectedStore(nodeId);
|
|
8996
|
-
return hydrateSchema({
|
|
8997
|
-
...schema,
|
|
8998
|
-
sections
|
|
8999
|
-
}, projected, { inlineSecretsAsViews: true });
|
|
8939
|
+
/** The form of the scoped schemas this addon declared, hydrated from its store. */
|
|
8940
|
+
async scopedForm(nodeId) {
|
|
8941
|
+
await this.loadScopedSchemas();
|
|
8942
|
+
const schema = this.scopedFormSchema();
|
|
8943
|
+
if (!schema) return { sections: [] };
|
|
8944
|
+
return hydrateSchema(schema, await this.readRawProjectedStore(nodeId), { inlineSecretsAsViews: true });
|
|
9000
8945
|
}
|
|
9001
8946
|
/**
|
|
9002
8947
|
* The raw addon store PROJECTED onto the target node's bare per-node keys:
|
|
@@ -9005,8 +8950,8 @@ var BaseAddon = class {
|
|
|
9005
8950
|
* bare fallback), all `@`-scoped and stray bare per-node keys are dropped.
|
|
9006
8951
|
* A no-op passthrough when the schema declares no `perNode` field.
|
|
9007
8952
|
*
|
|
9008
|
-
* This is the sanctioned way for
|
|
9009
|
-
* the store for custom
|
|
8953
|
+
* This is the sanctioned way for an addon that needs
|
|
8954
|
+
* the store for custom logic (option narrowing, value snapping) to
|
|
9010
8955
|
* read it per-node — never `ctx.settings.readAddonStore()` directly.
|
|
9011
8956
|
* `nodeId` omitted ⇒ the local node (node-blind injection from ctx).
|
|
9012
8957
|
*
|
|
@@ -9058,7 +9003,7 @@ var BaseAddon = class {
|
|
|
9058
9003
|
}
|
|
9059
9004
|
/**
|
|
9060
9005
|
* Whether ONE global key of this addon's store was written, read three-way
|
|
9061
|
-
* (D651). For a question a hydrated view cannot answer:
|
|
9006
|
+
* (D651). For a question a hydrated view cannot answer: a hydrated form
|
|
9062
9007
|
* reports `value ?? default`, so "the operator chose the default" and "nobody
|
|
9063
9008
|
* chose" look the same, and a failed read looks like both. A `perNode` key is
|
|
9064
9009
|
* not supported here: its stored name is scoped.
|
|
@@ -9092,7 +9037,7 @@ var BaseAddon = class {
|
|
|
9092
9037
|
}
|
|
9093
9038
|
/**
|
|
9094
9039
|
* The OPERATOR's write — a settings form or an admin API call, dispatched by
|
|
9095
|
-
* the kernel.
|
|
9040
|
+
* the kernel. The one in-process write of the addon blob that is not a scoped write; a secret
|
|
9096
9041
|
* the operator sends is stored as sent even when it equals a pre-keychain
|
|
9097
9042
|
* inline value: the operator re-entering a password is a change, an addon
|
|
9098
9043
|
* writing back what it read is not (D787).
|
|
@@ -9105,9 +9050,6 @@ var BaseAddon = class {
|
|
|
9105
9050
|
this._operatorWriteDepth--;
|
|
9106
9051
|
}
|
|
9107
9052
|
}
|
|
9108
|
-
async updateGlobalSettings(patch, nodeId) {
|
|
9109
|
-
await this.applyGlobalPatch(patch, nodeId);
|
|
9110
|
-
}
|
|
9111
9053
|
/**
|
|
9112
9054
|
* REMOVE stored secrets — their keychain values and their markers (D787).
|
|
9113
9055
|
*
|
|
@@ -9150,8 +9092,7 @@ var BaseAddon = class {
|
|
|
9150
9092
|
await this.resolveConfig();
|
|
9151
9093
|
await this.onConfigChanged();
|
|
9152
9094
|
this.emitLifecycle(EventCategory.AddonUpdated, { level: "global" });
|
|
9153
|
-
|
|
9154
|
-
this.maybeAutoRestart(Object.keys(barePatch), [...legacy === null ? [] : [legacy], ...this.loadedScopedSchemas().map((entry) => entry.schema)]);
|
|
9095
|
+
this.maybeAutoRestart(Object.keys(barePatch), this.loadedScopedSchemas().map((entry) => entry.schema));
|
|
9155
9096
|
return true;
|
|
9156
9097
|
}
|
|
9157
9098
|
/**
|
|
@@ -9189,10 +9130,7 @@ var BaseAddon = class {
|
|
|
9189
9130
|
this._nodeKeysByCap = /* @__PURE__ */ new Map();
|
|
9190
9131
|
this._addonSecretTree = null;
|
|
9191
9132
|
}
|
|
9192
|
-
/**
|
|
9193
|
-
* The form the settings API serves while an addon declares no {@link globalSettingsSchema}: the
|
|
9194
|
-
* sections of its scoped schemas, so dropping the old hook does not blank the form.
|
|
9195
|
-
*/
|
|
9133
|
+
/** The form of an addon's scoped schemas: their sections, each shown once. */
|
|
9196
9134
|
scopedFormSchema(cap) {
|
|
9197
9135
|
const byId = /* @__PURE__ */ new Map();
|
|
9198
9136
|
for (const entry of this.loadedScopedSchemas(cap)) for (const section of entry.schema.sections) if (!byId.has(section.id)) byId.set(section.id, section);
|
|
@@ -9204,8 +9142,7 @@ var BaseAddon = class {
|
|
|
9204
9142
|
return [...this._scopedByCap.values()].flat();
|
|
9205
9143
|
}
|
|
9206
9144
|
/**
|
|
9207
|
-
* The field keys that are stored per node: every field of a {@link nodeSettingsSchema}
|
|
9208
|
-
* the fields the legacy {@link globalSettingsSchema} still marks `perNode: true`. Derived once
|
|
9145
|
+
* The field keys that are stored per node: every field of a {@link nodeSettingsSchema}. Derived once
|
|
9209
9146
|
* per `cap` argument and memoized (schemas are static declarations). Empty set ⇒ every
|
|
9210
9147
|
* per-node code path is bypassed and the settings API behaves like the node-agnostic one.
|
|
9211
9148
|
* Call {@link loadScopedSchemas} first (the async seams do).
|
|
@@ -9214,8 +9151,7 @@ var BaseAddon = class {
|
|
|
9214
9151
|
const cacheKey = cap ?? "";
|
|
9215
9152
|
const cached = this._nodeKeysByCap.get(cacheKey);
|
|
9216
9153
|
if (cached) return cached;
|
|
9217
|
-
const
|
|
9218
|
-
const keys = new Set(legacy ? legacy.sections.flatMap((section) => collectPerNodeFieldKeys(section.fields)) : []);
|
|
9154
|
+
const keys = /* @__PURE__ */ new Set();
|
|
9219
9155
|
for (const { scope, schema } of this.loadedScopedSchemas(cap)) {
|
|
9220
9156
|
if (scope !== "node") continue;
|
|
9221
9157
|
for (const section of schema.sections) for (const key of collectValueFieldKeys(section.fields)) keys.add(key);
|
|
@@ -9433,8 +9369,6 @@ var BaseAddon = class {
|
|
|
9433
9369
|
}
|
|
9434
9370
|
declaredKeySet() {
|
|
9435
9371
|
const keys = new Set(Object.keys(this.defaults));
|
|
9436
|
-
const schema = this.globalSettingsSchema();
|
|
9437
|
-
if (schema) for (const section of schema.sections) for (const key of collectFieldKeys(section.fields)) keys.add(key);
|
|
9438
9372
|
for (const { schema: scoped } of this.loadedScopedSchemas()) for (const section of scoped.sections) for (const key of collectFieldKeys(section.fields)) keys.add(key);
|
|
9439
9373
|
for (const key of this._declaredStateKeys) keys.add(key);
|
|
9440
9374
|
for (const path of this.secretStatePaths) {
|
|
@@ -9532,7 +9466,7 @@ var BaseAddon = class {
|
|
|
9532
9466
|
/** The addon store's secret tree: schema fields by TYPE, plus `secretStatePaths`. */
|
|
9533
9467
|
addonSecretTree() {
|
|
9534
9468
|
if (this._addonSecretTree === null) {
|
|
9535
|
-
const tree = new Map(
|
|
9469
|
+
const tree = /* @__PURE__ */ new Map();
|
|
9536
9470
|
for (const { schema } of this.loadedScopedSchemas()) for (const [key, node] of secretTreeFromSchema(schema)) tree.set(key, node);
|
|
9537
9471
|
this._addonSecretTree = mergeSecretStatePaths(tree, this.secretStatePaths);
|
|
9538
9472
|
}
|
|
@@ -9744,47 +9678,6 @@ function classifyStoreError(err) {
|
|
|
9744
9678
|
if (TRANSPORT_PHRASES.some((f) => message.includes(f))) return "transport";
|
|
9745
9679
|
return "permanent";
|
|
9746
9680
|
}
|
|
9747
|
-
/**
|
|
9748
|
-
* Collect the keys of every field marked `perNode: true`, recursing into
|
|
9749
|
-
* layout containers (`group` fields and `sub-tabs` tabs) the same way
|
|
9750
|
-
* `hydrateSchema` does. Valueless structural fields (separator/info/…)
|
|
9751
|
-
* don't declare `perNode` and are excluded by the `in` narrowing.
|
|
9752
|
-
*/
|
|
9753
|
-
/**
|
|
9754
|
-
* The same fields with every `perNode: true` one removed, recursing into layout
|
|
9755
|
-
* containers exactly as {@link collectPerNodeFieldKeys} does. A container left
|
|
9756
|
-
* with no child is dropped rather than rendered empty.
|
|
9757
|
-
*
|
|
9758
|
-
* Used by `getIntegrationSettings`: an integration is not a node, so a field
|
|
9759
|
-
* whose store key is `<key>@<nodeId>` has no node to belong to there.
|
|
9760
|
-
*/
|
|
9761
|
-
function dropPerNodeFields(fields) {
|
|
9762
|
-
const kept = [];
|
|
9763
|
-
for (const field of fields) {
|
|
9764
|
-
if (field.type === "group") {
|
|
9765
|
-
const inner = dropPerNodeFields(field.fields);
|
|
9766
|
-
if (inner.length > 0) kept.push({
|
|
9767
|
-
...field,
|
|
9768
|
-
fields: inner
|
|
9769
|
-
});
|
|
9770
|
-
continue;
|
|
9771
|
-
}
|
|
9772
|
-
if (field.type === "sub-tabs") {
|
|
9773
|
-
const tabs = field.tabs.map((tab) => ({
|
|
9774
|
-
...tab,
|
|
9775
|
-
fields: dropPerNodeFields(tab.fields)
|
|
9776
|
-
})).filter((tab) => tab.fields.length > 0);
|
|
9777
|
-
if (tabs.length > 0) kept.push({
|
|
9778
|
-
...field,
|
|
9779
|
-
tabs
|
|
9780
|
-
});
|
|
9781
|
-
continue;
|
|
9782
|
-
}
|
|
9783
|
-
if ("perNode" in field && field.perNode === true) continue;
|
|
9784
|
-
kept.push(field);
|
|
9785
|
-
}
|
|
9786
|
-
return kept;
|
|
9787
|
-
}
|
|
9788
9681
|
/** The keys of the value-holding fields, recursing into layout containers. */
|
|
9789
9682
|
function collectValueFieldKeys(fields) {
|
|
9790
9683
|
const collected = [];
|
|
@@ -9817,21 +9710,6 @@ function collectFieldKeys(fields) {
|
|
|
9817
9710
|
}
|
|
9818
9711
|
return collected;
|
|
9819
9712
|
}
|
|
9820
|
-
function collectPerNodeFieldKeys(fields) {
|
|
9821
|
-
const collected = [];
|
|
9822
|
-
for (const field of fields) {
|
|
9823
|
-
if (field.type === "group") {
|
|
9824
|
-
collected.push(...collectPerNodeFieldKeys(field.fields));
|
|
9825
|
-
continue;
|
|
9826
|
-
}
|
|
9827
|
-
if (field.type === "sub-tabs") {
|
|
9828
|
-
for (const tab of field.tabs) collected.push(...collectPerNodeFieldKeys(tab.fields));
|
|
9829
|
-
continue;
|
|
9830
|
-
}
|
|
9831
|
-
if ("perNode" in field && field.perNode === true) collected.push(field.key);
|
|
9832
|
-
}
|
|
9833
|
-
return collected;
|
|
9834
|
-
}
|
|
9835
9713
|
/**
|
|
9836
9714
|
* Normalize an `ICamstackAddon.initialize()` return value into the
|
|
9837
9715
|
* `AddonInitResult` envelope. Arrays are wrapped into `{ providers }`;
|
|
@@ -12588,13 +12466,25 @@ Object.freeze({
|
|
|
12588
12466
|
"path": "temperature",
|
|
12589
12467
|
"valueType": "number"
|
|
12590
12468
|
}],
|
|
12591
|
-
"timed-run": [
|
|
12592
|
-
|
|
12593
|
-
|
|
12594
|
-
|
|
12595
|
-
|
|
12596
|
-
|
|
12597
|
-
|
|
12469
|
+
"timed-run": [
|
|
12470
|
+
{
|
|
12471
|
+
"path": "activeUntil",
|
|
12472
|
+
"valueType": "number"
|
|
12473
|
+
},
|
|
12474
|
+
{
|
|
12475
|
+
"path": "requestedBy",
|
|
12476
|
+
"valueType": "string"
|
|
12477
|
+
},
|
|
12478
|
+
{
|
|
12479
|
+
"path": "quickRun.duration",
|
|
12480
|
+
"valueType": "number"
|
|
12481
|
+
},
|
|
12482
|
+
{
|
|
12483
|
+
"path": "quickRun.unit",
|
|
12484
|
+
"valueType": "enum",
|
|
12485
|
+
"enumValues": ["s", "min"]
|
|
12486
|
+
}
|
|
12487
|
+
],
|
|
12598
12488
|
"update": [
|
|
12599
12489
|
{
|
|
12600
12490
|
"path": "currentVersion",
|
|
@@ -12832,7 +12722,7 @@ function userError(code, params, englishFallback) {
|
|
|
12832
12722
|
return new CamstackError(code, params, englishFallback);
|
|
12833
12723
|
}
|
|
12834
12724
|
//#endregion
|
|
12835
|
-
//#region ../types/dist/composition-
|
|
12725
|
+
//#region ../types/dist/composition-Bx0JvKUU.mjs
|
|
12836
12726
|
/**
|
|
12837
12727
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
12838
12728
|
*
|
|
@@ -13994,6 +13884,387 @@ var NodeColorIdSchema = _enum([
|
|
|
13994
13884
|
"node-h"
|
|
13995
13885
|
]);
|
|
13996
13886
|
//#endregion
|
|
13887
|
+
//#region ../types/dist/convert-BAzH15HU.mjs
|
|
13888
|
+
/**
|
|
13889
|
+
* Frozen unit → spec table. `•` in the doc marks each dimension's canonical
|
|
13890
|
+
* unit (`factor: 1, offset: 0`). °F derives from `°C = (°F − 32) × 5/9` ⇒
|
|
13891
|
+
* `factor = 5/9`, `offset = -160/9` (kept as exact expressions, not rounded
|
|
13892
|
+
* decimals). K derives from `°C = K − 273.15`.
|
|
13893
|
+
*/
|
|
13894
|
+
var UNIT_TABLE = {
|
|
13895
|
+
"°C": {
|
|
13896
|
+
dimension: "temperature",
|
|
13897
|
+
factor: 1,
|
|
13898
|
+
offset: 0
|
|
13899
|
+
},
|
|
13900
|
+
"°F": {
|
|
13901
|
+
dimension: "temperature",
|
|
13902
|
+
factor: 5 / 9,
|
|
13903
|
+
offset: -160 / 9
|
|
13904
|
+
},
|
|
13905
|
+
K: {
|
|
13906
|
+
dimension: "temperature",
|
|
13907
|
+
factor: 1,
|
|
13908
|
+
offset: -273.15
|
|
13909
|
+
},
|
|
13910
|
+
hPa: {
|
|
13911
|
+
dimension: "pressure",
|
|
13912
|
+
factor: 1,
|
|
13913
|
+
offset: 0
|
|
13914
|
+
},
|
|
13915
|
+
kPa: {
|
|
13916
|
+
dimension: "pressure",
|
|
13917
|
+
factor: 10,
|
|
13918
|
+
offset: 0
|
|
13919
|
+
},
|
|
13920
|
+
Pa: {
|
|
13921
|
+
dimension: "pressure",
|
|
13922
|
+
factor: .01,
|
|
13923
|
+
offset: 0
|
|
13924
|
+
},
|
|
13925
|
+
mbar: {
|
|
13926
|
+
dimension: "pressure",
|
|
13927
|
+
factor: 1,
|
|
13928
|
+
offset: 0
|
|
13929
|
+
},
|
|
13930
|
+
bar: {
|
|
13931
|
+
dimension: "pressure",
|
|
13932
|
+
factor: 1e3,
|
|
13933
|
+
offset: 0
|
|
13934
|
+
},
|
|
13935
|
+
inHg: {
|
|
13936
|
+
dimension: "pressure",
|
|
13937
|
+
factor: 33.8639,
|
|
13938
|
+
offset: 0
|
|
13939
|
+
},
|
|
13940
|
+
mmHg: {
|
|
13941
|
+
dimension: "pressure",
|
|
13942
|
+
factor: 1.33322,
|
|
13943
|
+
offset: 0
|
|
13944
|
+
},
|
|
13945
|
+
psi: {
|
|
13946
|
+
dimension: "pressure",
|
|
13947
|
+
factor: 68.9476,
|
|
13948
|
+
offset: 0
|
|
13949
|
+
},
|
|
13950
|
+
"m/s": {
|
|
13951
|
+
dimension: "speed",
|
|
13952
|
+
factor: 1,
|
|
13953
|
+
offset: 0
|
|
13954
|
+
},
|
|
13955
|
+
"km/h": {
|
|
13956
|
+
dimension: "speed",
|
|
13957
|
+
factor: 1 / 3.6,
|
|
13958
|
+
offset: 0
|
|
13959
|
+
},
|
|
13960
|
+
mph: {
|
|
13961
|
+
dimension: "speed",
|
|
13962
|
+
factor: .44704,
|
|
13963
|
+
offset: 0
|
|
13964
|
+
},
|
|
13965
|
+
kn: {
|
|
13966
|
+
dimension: "speed",
|
|
13967
|
+
factor: .514444,
|
|
13968
|
+
offset: 0
|
|
13969
|
+
},
|
|
13970
|
+
"mm/h": {
|
|
13971
|
+
dimension: "precipitation-rate",
|
|
13972
|
+
factor: 1,
|
|
13973
|
+
offset: 0
|
|
13974
|
+
},
|
|
13975
|
+
"in/h": {
|
|
13976
|
+
dimension: "precipitation-rate",
|
|
13977
|
+
factor: 25.4,
|
|
13978
|
+
offset: 0
|
|
13979
|
+
},
|
|
13980
|
+
m: {
|
|
13981
|
+
dimension: "length",
|
|
13982
|
+
factor: 1,
|
|
13983
|
+
offset: 0
|
|
13984
|
+
},
|
|
13985
|
+
mm: {
|
|
13986
|
+
dimension: "length",
|
|
13987
|
+
factor: .001,
|
|
13988
|
+
offset: 0
|
|
13989
|
+
},
|
|
13990
|
+
cm: {
|
|
13991
|
+
dimension: "length",
|
|
13992
|
+
factor: .01,
|
|
13993
|
+
offset: 0
|
|
13994
|
+
},
|
|
13995
|
+
km: {
|
|
13996
|
+
dimension: "length",
|
|
13997
|
+
factor: 1e3,
|
|
13998
|
+
offset: 0
|
|
13999
|
+
},
|
|
14000
|
+
in: {
|
|
14001
|
+
dimension: "length",
|
|
14002
|
+
factor: .0254,
|
|
14003
|
+
offset: 0
|
|
14004
|
+
},
|
|
14005
|
+
ft: {
|
|
14006
|
+
dimension: "length",
|
|
14007
|
+
factor: .3048,
|
|
14008
|
+
offset: 0
|
|
14009
|
+
},
|
|
14010
|
+
mi: {
|
|
14011
|
+
dimension: "length",
|
|
14012
|
+
factor: 1609.344,
|
|
14013
|
+
offset: 0
|
|
14014
|
+
},
|
|
14015
|
+
"m²": {
|
|
14016
|
+
dimension: "area",
|
|
14017
|
+
factor: 1,
|
|
14018
|
+
offset: 0
|
|
14019
|
+
},
|
|
14020
|
+
lx: {
|
|
14021
|
+
dimension: "illuminance",
|
|
14022
|
+
factor: 1,
|
|
14023
|
+
offset: 0
|
|
14024
|
+
},
|
|
14025
|
+
"W/m²": {
|
|
14026
|
+
dimension: "irradiance",
|
|
14027
|
+
factor: 1,
|
|
14028
|
+
offset: 0
|
|
14029
|
+
},
|
|
14030
|
+
W: {
|
|
14031
|
+
dimension: "power",
|
|
14032
|
+
factor: 1,
|
|
14033
|
+
offset: 0
|
|
14034
|
+
},
|
|
14035
|
+
kW: {
|
|
14036
|
+
dimension: "power",
|
|
14037
|
+
factor: 1e3,
|
|
14038
|
+
offset: 0
|
|
14039
|
+
},
|
|
14040
|
+
VA: {
|
|
14041
|
+
dimension: "apparent-power",
|
|
14042
|
+
factor: 1,
|
|
14043
|
+
offset: 0
|
|
14044
|
+
},
|
|
14045
|
+
Wh: {
|
|
14046
|
+
dimension: "energy",
|
|
14047
|
+
factor: 1,
|
|
14048
|
+
offset: 0
|
|
14049
|
+
},
|
|
14050
|
+
kWh: {
|
|
14051
|
+
dimension: "energy",
|
|
14052
|
+
factor: 1e3,
|
|
14053
|
+
offset: 0
|
|
14054
|
+
},
|
|
14055
|
+
MWh: {
|
|
14056
|
+
dimension: "energy",
|
|
14057
|
+
factor: 1e6,
|
|
14058
|
+
offset: 0
|
|
14059
|
+
},
|
|
14060
|
+
V: {
|
|
14061
|
+
dimension: "voltage",
|
|
14062
|
+
factor: 1,
|
|
14063
|
+
offset: 0
|
|
14064
|
+
},
|
|
14065
|
+
mV: {
|
|
14066
|
+
dimension: "voltage",
|
|
14067
|
+
factor: .001,
|
|
14068
|
+
offset: 0
|
|
14069
|
+
},
|
|
14070
|
+
A: {
|
|
14071
|
+
dimension: "current",
|
|
14072
|
+
factor: 1,
|
|
14073
|
+
offset: 0
|
|
14074
|
+
},
|
|
14075
|
+
mA: {
|
|
14076
|
+
dimension: "current",
|
|
14077
|
+
factor: .001,
|
|
14078
|
+
offset: 0
|
|
14079
|
+
},
|
|
14080
|
+
ppm: {
|
|
14081
|
+
dimension: "concentration-volume",
|
|
14082
|
+
factor: 1,
|
|
14083
|
+
offset: 0
|
|
14084
|
+
},
|
|
14085
|
+
ppb: {
|
|
14086
|
+
dimension: "concentration-volume",
|
|
14087
|
+
factor: .001,
|
|
14088
|
+
offset: 0
|
|
14089
|
+
},
|
|
14090
|
+
"µg/m³": {
|
|
14091
|
+
dimension: "concentration-mass",
|
|
14092
|
+
factor: 1,
|
|
14093
|
+
offset: 0
|
|
14094
|
+
},
|
|
14095
|
+
"mg/m³": {
|
|
14096
|
+
dimension: "concentration-mass",
|
|
14097
|
+
factor: 1e3,
|
|
14098
|
+
offset: 0
|
|
14099
|
+
},
|
|
14100
|
+
kg: {
|
|
14101
|
+
dimension: "mass",
|
|
14102
|
+
factor: 1,
|
|
14103
|
+
offset: 0
|
|
14104
|
+
},
|
|
14105
|
+
g: {
|
|
14106
|
+
dimension: "mass",
|
|
14107
|
+
factor: .001,
|
|
14108
|
+
offset: 0
|
|
14109
|
+
},
|
|
14110
|
+
lb: {
|
|
14111
|
+
dimension: "mass",
|
|
14112
|
+
factor: .453592,
|
|
14113
|
+
offset: 0
|
|
14114
|
+
},
|
|
14115
|
+
oz: {
|
|
14116
|
+
dimension: "mass",
|
|
14117
|
+
factor: .0283495,
|
|
14118
|
+
offset: 0
|
|
14119
|
+
},
|
|
14120
|
+
"%": {
|
|
14121
|
+
dimension: "percentage",
|
|
14122
|
+
factor: 1,
|
|
14123
|
+
offset: 0
|
|
14124
|
+
},
|
|
14125
|
+
L: {
|
|
14126
|
+
dimension: "volume",
|
|
14127
|
+
factor: 1,
|
|
14128
|
+
offset: 0
|
|
14129
|
+
},
|
|
14130
|
+
mL: {
|
|
14131
|
+
dimension: "volume",
|
|
14132
|
+
factor: .001,
|
|
14133
|
+
offset: 0
|
|
14134
|
+
},
|
|
14135
|
+
gal: {
|
|
14136
|
+
dimension: "volume",
|
|
14137
|
+
factor: 3.785411784,
|
|
14138
|
+
offset: 0
|
|
14139
|
+
},
|
|
14140
|
+
s: {
|
|
14141
|
+
dimension: "duration",
|
|
14142
|
+
factor: 1,
|
|
14143
|
+
offset: 0
|
|
14144
|
+
},
|
|
14145
|
+
ms: {
|
|
14146
|
+
dimension: "duration",
|
|
14147
|
+
factor: .001,
|
|
14148
|
+
offset: 0
|
|
14149
|
+
},
|
|
14150
|
+
min: {
|
|
14151
|
+
dimension: "duration",
|
|
14152
|
+
factor: 60,
|
|
14153
|
+
offset: 0
|
|
14154
|
+
},
|
|
14155
|
+
h: {
|
|
14156
|
+
dimension: "duration",
|
|
14157
|
+
factor: 3600,
|
|
14158
|
+
offset: 0
|
|
14159
|
+
},
|
|
14160
|
+
d: {
|
|
14161
|
+
dimension: "duration",
|
|
14162
|
+
factor: 86400,
|
|
14163
|
+
offset: 0
|
|
14164
|
+
},
|
|
14165
|
+
B: {
|
|
14166
|
+
dimension: "information",
|
|
14167
|
+
factor: 1,
|
|
14168
|
+
offset: 0
|
|
14169
|
+
},
|
|
14170
|
+
KiB: {
|
|
14171
|
+
dimension: "information",
|
|
14172
|
+
factor: 1024,
|
|
14173
|
+
offset: 0
|
|
14174
|
+
},
|
|
14175
|
+
MiB: {
|
|
14176
|
+
dimension: "information",
|
|
14177
|
+
factor: 1024 ** 2,
|
|
14178
|
+
offset: 0
|
|
14179
|
+
},
|
|
14180
|
+
GiB: {
|
|
14181
|
+
dimension: "information",
|
|
14182
|
+
factor: 1024 ** 3,
|
|
14183
|
+
offset: 0
|
|
14184
|
+
},
|
|
14185
|
+
TiB: {
|
|
14186
|
+
dimension: "information",
|
|
14187
|
+
factor: 1024 ** 4,
|
|
14188
|
+
offset: 0
|
|
14189
|
+
},
|
|
14190
|
+
kB: {
|
|
14191
|
+
dimension: "information",
|
|
14192
|
+
factor: 1e3,
|
|
14193
|
+
offset: 0
|
|
14194
|
+
},
|
|
14195
|
+
MB: {
|
|
14196
|
+
dimension: "information",
|
|
14197
|
+
factor: 1e6,
|
|
14198
|
+
offset: 0
|
|
14199
|
+
},
|
|
14200
|
+
GB: {
|
|
14201
|
+
dimension: "information",
|
|
14202
|
+
factor: 1e9,
|
|
14203
|
+
offset: 0
|
|
14204
|
+
},
|
|
14205
|
+
"°": {
|
|
14206
|
+
dimension: "angle",
|
|
14207
|
+
factor: 1,
|
|
14208
|
+
offset: 0
|
|
14209
|
+
},
|
|
14210
|
+
dBFS: {
|
|
14211
|
+
dimension: "sound-level",
|
|
14212
|
+
factor: 1,
|
|
14213
|
+
offset: 0
|
|
14214
|
+
},
|
|
14215
|
+
dBm: {
|
|
14216
|
+
dimension: "signal-level",
|
|
14217
|
+
factor: 1,
|
|
14218
|
+
offset: 0
|
|
14219
|
+
},
|
|
14220
|
+
mired: {
|
|
14221
|
+
dimension: "colour-temperature",
|
|
14222
|
+
factor: 1,
|
|
14223
|
+
offset: 0
|
|
14224
|
+
},
|
|
14225
|
+
kbps: {
|
|
14226
|
+
dimension: "bitrate",
|
|
14227
|
+
factor: 1,
|
|
14228
|
+
offset: 0
|
|
14229
|
+
},
|
|
14230
|
+
Mbps: {
|
|
14231
|
+
dimension: "bitrate",
|
|
14232
|
+
factor: 1e3,
|
|
14233
|
+
offset: 0
|
|
14234
|
+
},
|
|
14235
|
+
fps: {
|
|
14236
|
+
dimension: "rate",
|
|
14237
|
+
factor: 1,
|
|
14238
|
+
offset: 0
|
|
14239
|
+
}
|
|
14240
|
+
};
|
|
14241
|
+
/** Resolve a unit's `UnitSpec`, or `undefined` when the spelling is unknown. */
|
|
14242
|
+
function specFor(unit) {
|
|
14243
|
+
return Object.hasOwn(UNIT_TABLE, unit) ? UNIT_TABLE[unit] : void 0;
|
|
14244
|
+
}
|
|
14245
|
+
/** Value in `spec`'s unit → its dimension's canonical unit. */
|
|
14246
|
+
function toCanonical(value, spec) {
|
|
14247
|
+
return value * spec.factor + spec.offset;
|
|
14248
|
+
}
|
|
14249
|
+
/** Canonical-unit value → the unit described by `spec`. */
|
|
14250
|
+
function fromCanonical(canonical, spec) {
|
|
14251
|
+
return (canonical - spec.offset) / spec.factor;
|
|
14252
|
+
}
|
|
14253
|
+
/**
|
|
14254
|
+
* Graceful variant for the render path: returns the converted value, or
|
|
14255
|
+
* `undefined` when the conversion is refused (unknown unit / cross-dimension).
|
|
14256
|
+
* Never throws — a render caller falls back to the raw value + source unit.
|
|
14257
|
+
*/
|
|
14258
|
+
function tryConvertUnit(value, from, to) {
|
|
14259
|
+
if (from === to) return value;
|
|
14260
|
+
const fromSpec = specFor(from);
|
|
14261
|
+
if (!fromSpec) return void 0;
|
|
14262
|
+
const toSpec = specFor(to);
|
|
14263
|
+
if (!toSpec) return void 0;
|
|
14264
|
+
if (fromSpec.dimension !== toSpec.dimension) return void 0;
|
|
14265
|
+
return fromCanonical(toCanonical(value, fromSpec), toSpec);
|
|
14266
|
+
}
|
|
14267
|
+
//#endregion
|
|
13997
14268
|
//#region ../types/dist/index.mjs
|
|
13998
14269
|
/**
|
|
13999
14270
|
* The `smtp-inbound` broker kind (D999): a mailbox a device can send mail to.
|
|
@@ -42976,6 +43247,7 @@ var ExpressionBindingSourceSchema = union([
|
|
|
42976
43247
|
object({
|
|
42977
43248
|
kind: literal("global"),
|
|
42978
43249
|
sourceStableId: string(),
|
|
43250
|
+
addonId: string().optional(),
|
|
42979
43251
|
cap: string(),
|
|
42980
43252
|
fieldPath: string()
|
|
42981
43253
|
})
|
|
@@ -43042,385 +43314,6 @@ var SourceInfoSchema = object({
|
|
|
43042
43314
|
raw: record(string(), unknown()).optional()
|
|
43043
43315
|
});
|
|
43044
43316
|
/**
|
|
43045
|
-
* Frozen unit → spec table. `•` in the doc marks each dimension's canonical
|
|
43046
|
-
* unit (`factor: 1, offset: 0`). °F derives from `°C = (°F − 32) × 5/9` ⇒
|
|
43047
|
-
* `factor = 5/9`, `offset = -160/9` (kept as exact expressions, not rounded
|
|
43048
|
-
* decimals). K derives from `°C = K − 273.15`.
|
|
43049
|
-
*/
|
|
43050
|
-
var UNIT_TABLE = {
|
|
43051
|
-
"°C": {
|
|
43052
|
-
dimension: "temperature",
|
|
43053
|
-
factor: 1,
|
|
43054
|
-
offset: 0
|
|
43055
|
-
},
|
|
43056
|
-
"°F": {
|
|
43057
|
-
dimension: "temperature",
|
|
43058
|
-
factor: 5 / 9,
|
|
43059
|
-
offset: -160 / 9
|
|
43060
|
-
},
|
|
43061
|
-
K: {
|
|
43062
|
-
dimension: "temperature",
|
|
43063
|
-
factor: 1,
|
|
43064
|
-
offset: -273.15
|
|
43065
|
-
},
|
|
43066
|
-
hPa: {
|
|
43067
|
-
dimension: "pressure",
|
|
43068
|
-
factor: 1,
|
|
43069
|
-
offset: 0
|
|
43070
|
-
},
|
|
43071
|
-
kPa: {
|
|
43072
|
-
dimension: "pressure",
|
|
43073
|
-
factor: 10,
|
|
43074
|
-
offset: 0
|
|
43075
|
-
},
|
|
43076
|
-
Pa: {
|
|
43077
|
-
dimension: "pressure",
|
|
43078
|
-
factor: .01,
|
|
43079
|
-
offset: 0
|
|
43080
|
-
},
|
|
43081
|
-
mbar: {
|
|
43082
|
-
dimension: "pressure",
|
|
43083
|
-
factor: 1,
|
|
43084
|
-
offset: 0
|
|
43085
|
-
},
|
|
43086
|
-
bar: {
|
|
43087
|
-
dimension: "pressure",
|
|
43088
|
-
factor: 1e3,
|
|
43089
|
-
offset: 0
|
|
43090
|
-
},
|
|
43091
|
-
inHg: {
|
|
43092
|
-
dimension: "pressure",
|
|
43093
|
-
factor: 33.8639,
|
|
43094
|
-
offset: 0
|
|
43095
|
-
},
|
|
43096
|
-
mmHg: {
|
|
43097
|
-
dimension: "pressure",
|
|
43098
|
-
factor: 1.33322,
|
|
43099
|
-
offset: 0
|
|
43100
|
-
},
|
|
43101
|
-
psi: {
|
|
43102
|
-
dimension: "pressure",
|
|
43103
|
-
factor: 68.9476,
|
|
43104
|
-
offset: 0
|
|
43105
|
-
},
|
|
43106
|
-
"m/s": {
|
|
43107
|
-
dimension: "speed",
|
|
43108
|
-
factor: 1,
|
|
43109
|
-
offset: 0
|
|
43110
|
-
},
|
|
43111
|
-
"km/h": {
|
|
43112
|
-
dimension: "speed",
|
|
43113
|
-
factor: 1 / 3.6,
|
|
43114
|
-
offset: 0
|
|
43115
|
-
},
|
|
43116
|
-
mph: {
|
|
43117
|
-
dimension: "speed",
|
|
43118
|
-
factor: .44704,
|
|
43119
|
-
offset: 0
|
|
43120
|
-
},
|
|
43121
|
-
kn: {
|
|
43122
|
-
dimension: "speed",
|
|
43123
|
-
factor: .514444,
|
|
43124
|
-
offset: 0
|
|
43125
|
-
},
|
|
43126
|
-
"mm/h": {
|
|
43127
|
-
dimension: "precipitation-rate",
|
|
43128
|
-
factor: 1,
|
|
43129
|
-
offset: 0
|
|
43130
|
-
},
|
|
43131
|
-
"in/h": {
|
|
43132
|
-
dimension: "precipitation-rate",
|
|
43133
|
-
factor: 25.4,
|
|
43134
|
-
offset: 0
|
|
43135
|
-
},
|
|
43136
|
-
m: {
|
|
43137
|
-
dimension: "length",
|
|
43138
|
-
factor: 1,
|
|
43139
|
-
offset: 0
|
|
43140
|
-
},
|
|
43141
|
-
mm: {
|
|
43142
|
-
dimension: "length",
|
|
43143
|
-
factor: .001,
|
|
43144
|
-
offset: 0
|
|
43145
|
-
},
|
|
43146
|
-
cm: {
|
|
43147
|
-
dimension: "length",
|
|
43148
|
-
factor: .01,
|
|
43149
|
-
offset: 0
|
|
43150
|
-
},
|
|
43151
|
-
km: {
|
|
43152
|
-
dimension: "length",
|
|
43153
|
-
factor: 1e3,
|
|
43154
|
-
offset: 0
|
|
43155
|
-
},
|
|
43156
|
-
in: {
|
|
43157
|
-
dimension: "length",
|
|
43158
|
-
factor: .0254,
|
|
43159
|
-
offset: 0
|
|
43160
|
-
},
|
|
43161
|
-
ft: {
|
|
43162
|
-
dimension: "length",
|
|
43163
|
-
factor: .3048,
|
|
43164
|
-
offset: 0
|
|
43165
|
-
},
|
|
43166
|
-
mi: {
|
|
43167
|
-
dimension: "length",
|
|
43168
|
-
factor: 1609.344,
|
|
43169
|
-
offset: 0
|
|
43170
|
-
},
|
|
43171
|
-
"m²": {
|
|
43172
|
-
dimension: "area",
|
|
43173
|
-
factor: 1,
|
|
43174
|
-
offset: 0
|
|
43175
|
-
},
|
|
43176
|
-
lx: {
|
|
43177
|
-
dimension: "illuminance",
|
|
43178
|
-
factor: 1,
|
|
43179
|
-
offset: 0
|
|
43180
|
-
},
|
|
43181
|
-
"W/m²": {
|
|
43182
|
-
dimension: "irradiance",
|
|
43183
|
-
factor: 1,
|
|
43184
|
-
offset: 0
|
|
43185
|
-
},
|
|
43186
|
-
W: {
|
|
43187
|
-
dimension: "power",
|
|
43188
|
-
factor: 1,
|
|
43189
|
-
offset: 0
|
|
43190
|
-
},
|
|
43191
|
-
kW: {
|
|
43192
|
-
dimension: "power",
|
|
43193
|
-
factor: 1e3,
|
|
43194
|
-
offset: 0
|
|
43195
|
-
},
|
|
43196
|
-
VA: {
|
|
43197
|
-
dimension: "apparent-power",
|
|
43198
|
-
factor: 1,
|
|
43199
|
-
offset: 0
|
|
43200
|
-
},
|
|
43201
|
-
Wh: {
|
|
43202
|
-
dimension: "energy",
|
|
43203
|
-
factor: 1,
|
|
43204
|
-
offset: 0
|
|
43205
|
-
},
|
|
43206
|
-
kWh: {
|
|
43207
|
-
dimension: "energy",
|
|
43208
|
-
factor: 1e3,
|
|
43209
|
-
offset: 0
|
|
43210
|
-
},
|
|
43211
|
-
MWh: {
|
|
43212
|
-
dimension: "energy",
|
|
43213
|
-
factor: 1e6,
|
|
43214
|
-
offset: 0
|
|
43215
|
-
},
|
|
43216
|
-
V: {
|
|
43217
|
-
dimension: "voltage",
|
|
43218
|
-
factor: 1,
|
|
43219
|
-
offset: 0
|
|
43220
|
-
},
|
|
43221
|
-
mV: {
|
|
43222
|
-
dimension: "voltage",
|
|
43223
|
-
factor: .001,
|
|
43224
|
-
offset: 0
|
|
43225
|
-
},
|
|
43226
|
-
A: {
|
|
43227
|
-
dimension: "current",
|
|
43228
|
-
factor: 1,
|
|
43229
|
-
offset: 0
|
|
43230
|
-
},
|
|
43231
|
-
mA: {
|
|
43232
|
-
dimension: "current",
|
|
43233
|
-
factor: .001,
|
|
43234
|
-
offset: 0
|
|
43235
|
-
},
|
|
43236
|
-
ppm: {
|
|
43237
|
-
dimension: "concentration-volume",
|
|
43238
|
-
factor: 1,
|
|
43239
|
-
offset: 0
|
|
43240
|
-
},
|
|
43241
|
-
ppb: {
|
|
43242
|
-
dimension: "concentration-volume",
|
|
43243
|
-
factor: .001,
|
|
43244
|
-
offset: 0
|
|
43245
|
-
},
|
|
43246
|
-
"µg/m³": {
|
|
43247
|
-
dimension: "concentration-mass",
|
|
43248
|
-
factor: 1,
|
|
43249
|
-
offset: 0
|
|
43250
|
-
},
|
|
43251
|
-
"mg/m³": {
|
|
43252
|
-
dimension: "concentration-mass",
|
|
43253
|
-
factor: 1e3,
|
|
43254
|
-
offset: 0
|
|
43255
|
-
},
|
|
43256
|
-
kg: {
|
|
43257
|
-
dimension: "mass",
|
|
43258
|
-
factor: 1,
|
|
43259
|
-
offset: 0
|
|
43260
|
-
},
|
|
43261
|
-
g: {
|
|
43262
|
-
dimension: "mass",
|
|
43263
|
-
factor: .001,
|
|
43264
|
-
offset: 0
|
|
43265
|
-
},
|
|
43266
|
-
lb: {
|
|
43267
|
-
dimension: "mass",
|
|
43268
|
-
factor: .453592,
|
|
43269
|
-
offset: 0
|
|
43270
|
-
},
|
|
43271
|
-
oz: {
|
|
43272
|
-
dimension: "mass",
|
|
43273
|
-
factor: .0283495,
|
|
43274
|
-
offset: 0
|
|
43275
|
-
},
|
|
43276
|
-
"%": {
|
|
43277
|
-
dimension: "percentage",
|
|
43278
|
-
factor: 1,
|
|
43279
|
-
offset: 0
|
|
43280
|
-
},
|
|
43281
|
-
L: {
|
|
43282
|
-
dimension: "volume",
|
|
43283
|
-
factor: 1,
|
|
43284
|
-
offset: 0
|
|
43285
|
-
},
|
|
43286
|
-
mL: {
|
|
43287
|
-
dimension: "volume",
|
|
43288
|
-
factor: .001,
|
|
43289
|
-
offset: 0
|
|
43290
|
-
},
|
|
43291
|
-
gal: {
|
|
43292
|
-
dimension: "volume",
|
|
43293
|
-
factor: 3.785411784,
|
|
43294
|
-
offset: 0
|
|
43295
|
-
},
|
|
43296
|
-
s: {
|
|
43297
|
-
dimension: "duration",
|
|
43298
|
-
factor: 1,
|
|
43299
|
-
offset: 0
|
|
43300
|
-
},
|
|
43301
|
-
ms: {
|
|
43302
|
-
dimension: "duration",
|
|
43303
|
-
factor: .001,
|
|
43304
|
-
offset: 0
|
|
43305
|
-
},
|
|
43306
|
-
min: {
|
|
43307
|
-
dimension: "duration",
|
|
43308
|
-
factor: 60,
|
|
43309
|
-
offset: 0
|
|
43310
|
-
},
|
|
43311
|
-
h: {
|
|
43312
|
-
dimension: "duration",
|
|
43313
|
-
factor: 3600,
|
|
43314
|
-
offset: 0
|
|
43315
|
-
},
|
|
43316
|
-
d: {
|
|
43317
|
-
dimension: "duration",
|
|
43318
|
-
factor: 86400,
|
|
43319
|
-
offset: 0
|
|
43320
|
-
},
|
|
43321
|
-
B: {
|
|
43322
|
-
dimension: "information",
|
|
43323
|
-
factor: 1,
|
|
43324
|
-
offset: 0
|
|
43325
|
-
},
|
|
43326
|
-
KiB: {
|
|
43327
|
-
dimension: "information",
|
|
43328
|
-
factor: 1024,
|
|
43329
|
-
offset: 0
|
|
43330
|
-
},
|
|
43331
|
-
MiB: {
|
|
43332
|
-
dimension: "information",
|
|
43333
|
-
factor: 1024 ** 2,
|
|
43334
|
-
offset: 0
|
|
43335
|
-
},
|
|
43336
|
-
GiB: {
|
|
43337
|
-
dimension: "information",
|
|
43338
|
-
factor: 1024 ** 3,
|
|
43339
|
-
offset: 0
|
|
43340
|
-
},
|
|
43341
|
-
TiB: {
|
|
43342
|
-
dimension: "information",
|
|
43343
|
-
factor: 1024 ** 4,
|
|
43344
|
-
offset: 0
|
|
43345
|
-
},
|
|
43346
|
-
kB: {
|
|
43347
|
-
dimension: "information",
|
|
43348
|
-
factor: 1e3,
|
|
43349
|
-
offset: 0
|
|
43350
|
-
},
|
|
43351
|
-
MB: {
|
|
43352
|
-
dimension: "information",
|
|
43353
|
-
factor: 1e6,
|
|
43354
|
-
offset: 0
|
|
43355
|
-
},
|
|
43356
|
-
GB: {
|
|
43357
|
-
dimension: "information",
|
|
43358
|
-
factor: 1e9,
|
|
43359
|
-
offset: 0
|
|
43360
|
-
},
|
|
43361
|
-
"°": {
|
|
43362
|
-
dimension: "angle",
|
|
43363
|
-
factor: 1,
|
|
43364
|
-
offset: 0
|
|
43365
|
-
},
|
|
43366
|
-
dBFS: {
|
|
43367
|
-
dimension: "sound-level",
|
|
43368
|
-
factor: 1,
|
|
43369
|
-
offset: 0
|
|
43370
|
-
},
|
|
43371
|
-
dBm: {
|
|
43372
|
-
dimension: "signal-level",
|
|
43373
|
-
factor: 1,
|
|
43374
|
-
offset: 0
|
|
43375
|
-
},
|
|
43376
|
-
mired: {
|
|
43377
|
-
dimension: "colour-temperature",
|
|
43378
|
-
factor: 1,
|
|
43379
|
-
offset: 0
|
|
43380
|
-
},
|
|
43381
|
-
kbps: {
|
|
43382
|
-
dimension: "bitrate",
|
|
43383
|
-
factor: 1,
|
|
43384
|
-
offset: 0
|
|
43385
|
-
},
|
|
43386
|
-
Mbps: {
|
|
43387
|
-
dimension: "bitrate",
|
|
43388
|
-
factor: 1e3,
|
|
43389
|
-
offset: 0
|
|
43390
|
-
},
|
|
43391
|
-
fps: {
|
|
43392
|
-
dimension: "rate",
|
|
43393
|
-
factor: 1,
|
|
43394
|
-
offset: 0
|
|
43395
|
-
}
|
|
43396
|
-
};
|
|
43397
|
-
/** Resolve a unit's `UnitSpec`, or `undefined` when the spelling is unknown. */
|
|
43398
|
-
function specFor(unit) {
|
|
43399
|
-
return Object.hasOwn(UNIT_TABLE, unit) ? UNIT_TABLE[unit] : void 0;
|
|
43400
|
-
}
|
|
43401
|
-
/** Value in `spec`'s unit → its dimension's canonical unit. */
|
|
43402
|
-
function toCanonical(value, spec) {
|
|
43403
|
-
return value * spec.factor + spec.offset;
|
|
43404
|
-
}
|
|
43405
|
-
/** Canonical-unit value → the unit described by `spec`. */
|
|
43406
|
-
function fromCanonical(canonical, spec) {
|
|
43407
|
-
return (canonical - spec.offset) / spec.factor;
|
|
43408
|
-
}
|
|
43409
|
-
/**
|
|
43410
|
-
* Graceful variant for the render path: returns the converted value, or
|
|
43411
|
-
* `undefined` when the conversion is refused (unknown unit / cross-dimension).
|
|
43412
|
-
* Never throws — a render caller falls back to the raw value + source unit.
|
|
43413
|
-
*/
|
|
43414
|
-
function tryConvertUnit(value, from, to) {
|
|
43415
|
-
if (from === to) return value;
|
|
43416
|
-
const fromSpec = specFor(from);
|
|
43417
|
-
if (!fromSpec) return void 0;
|
|
43418
|
-
const toSpec = specFor(to);
|
|
43419
|
-
if (!toSpec) return void 0;
|
|
43420
|
-
if (fromSpec.dimension !== toSpec.dimension) return void 0;
|
|
43421
|
-
return fromCanonical(toCanonical(value, fromSpec), toSpec);
|
|
43422
|
-
}
|
|
43423
|
-
/**
|
|
43424
43317
|
* A number a person types for a physical quantity — the input side of the
|
|
43425
43318
|
* value + unit contract (D972).
|
|
43426
43319
|
*
|
|
@@ -45099,26 +44992,23 @@ var SettingsSchemaWithValuesSchema = object({
|
|
|
45099
44992
|
var SettingsPatchSchema = record(string(), unknown());
|
|
45100
44993
|
/** The scope of a scoped-settings call (D986): where the capability declared the values. */
|
|
45101
44994
|
var ScopedSettingsScopeSchema = _enum(SCOPED_SETTINGS_SCOPES);
|
|
44995
|
+
/** One scoped schema an addon serves: its capability, scope and section ids. */
|
|
44996
|
+
var ScopedSettingsDeclarationSchema = object({
|
|
44997
|
+
cap: string(),
|
|
44998
|
+
scope: ScopedSettingsScopeSchema,
|
|
44999
|
+
sectionIds: array(string())
|
|
45000
|
+
});
|
|
45102
45001
|
/** Standard success response for update operations. */
|
|
45103
45002
|
var SettingsUpdateResultSchema = object({ success: literal(true) });
|
|
45104
45003
|
method(object({
|
|
45105
|
-
addonId: string(),
|
|
45106
|
-
nodeId: string().optional(),
|
|
45107
|
-
overlay: record(string(), unknown()).optional(),
|
|
45108
|
-
cap: string().optional()
|
|
45109
|
-
}), SettingsSchemaWithValuesSchema.nullable()), method(object({
|
|
45110
|
-
addonId: string(),
|
|
45111
|
-
nodeId: string().optional(),
|
|
45112
|
-
patch: SettingsPatchSchema
|
|
45113
|
-
}), SettingsUpdateResultSchema, {
|
|
45114
|
-
kind: "mutation",
|
|
45115
|
-
auth: "admin"
|
|
45116
|
-
}), method(object({
|
|
45117
45004
|
addonId: string(),
|
|
45118
45005
|
cap: string(),
|
|
45119
45006
|
scope: ScopedSettingsScopeSchema,
|
|
45120
45007
|
nodeId: string().optional()
|
|
45121
45008
|
}), SettingsSchemaWithValuesSchema.nullable()), method(object({
|
|
45009
|
+
addonId: string(),
|
|
45010
|
+
nodeId: string().optional()
|
|
45011
|
+
}), array(ScopedSettingsDeclarationSchema).nullable()), method(object({
|
|
45122
45012
|
addonId: string(),
|
|
45123
45013
|
cap: string(),
|
|
45124
45014
|
scope: ScopedSettingsScopeSchema,
|
|
@@ -45133,9 +45023,6 @@ method(object({
|
|
|
45133
45023
|
scope: ScopedSettingsScopeSchema,
|
|
45134
45024
|
nodeId: string().optional()
|
|
45135
45025
|
}), record(string(), unknown()).nullable()), method(object({
|
|
45136
|
-
addonId: string(),
|
|
45137
|
-
nodeId: string().optional()
|
|
45138
|
-
}), SettingsSchemaWithValuesSchema.nullable()), method(object({
|
|
45139
45026
|
addonId: string(),
|
|
45140
45027
|
nodeId: string().optional(),
|
|
45141
45028
|
instance: IntegrationInstanceRefSchema
|
|
@@ -46475,7 +46362,7 @@ var BackupDestinationInfoSchema = object({
|
|
|
46475
46362
|
id: string(),
|
|
46476
46363
|
/**
|
|
46477
46364
|
* Manifest id of the owning addon. The Settings button on the
|
|
46478
|
-
* destination card opens that addon's
|
|
46365
|
+
* destination card opens that addon's scoped settings panel.
|
|
46479
46366
|
*/
|
|
46480
46367
|
addonId: string(),
|
|
46481
46368
|
/** Operator-toggled enable flag from the destination-policy table. */
|
|
@@ -49074,7 +48961,7 @@ DeviceType.MediaPlayer, method(deviceOnly, _void(), {
|
|
|
49074
48961
|
kind: "mutation",
|
|
49075
48962
|
auth: "protected"
|
|
49076
48963
|
});
|
|
49077
|
-
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Heater, DeviceType.Dryer, DeviceType.Gateway, DeviceType.Camera, DeviceType.Fan, DeviceType.Lock, DeviceType.Camera, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Heater, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Heater, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Heater, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Heater, DeviceType.Gateway, DeviceType.Hub, DeviceType.Camera, DeviceType.Sensor, DeviceType.MediaPlayer, DeviceType.Vacuum, DeviceType.Generic, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.PetFountain, DeviceType.Fan, DeviceType.Humidifier, DeviceType.Climate, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder, DeviceType.Heater;
|
|
48964
|
+
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Heater, DeviceType.Dryer, DeviceType.Gateway, DeviceType.Camera, DeviceType.Fan, DeviceType.Lock, DeviceType.Camera, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Heater, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Heater, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Heater, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Heater, DeviceType.Gateway, DeviceType.Hub, DeviceType.Camera, DeviceType.Sensor, DeviceType.MediaPlayer, DeviceType.Vacuum, DeviceType.Generic, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.PetFountain, DeviceType.Fan, DeviceType.Humidifier, DeviceType.Climate, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder, DeviceType.Heater, DeviceType.MediaPlayer;
|
|
49078
48965
|
var NUMBER = {
|
|
49079
48966
|
kind: "fixed",
|
|
49080
48967
|
result: ["number"]
|
|
@@ -50945,6 +50832,7 @@ method(InstancePinSchema, DeviceExportStatusSchema), method(_void(), array(Expor
|
|
|
50945
50832
|
kind: "mutation",
|
|
50946
50833
|
auth: "admin"
|
|
50947
50834
|
});
|
|
50835
|
+
var DeviceAliasSchema = string().max(64).regex(/^[a-z][a-z0-9_]*$/);
|
|
50948
50836
|
/**
|
|
50949
50837
|
* A SITE ZONE — a named part of the property that several locations belong to.
|
|
50950
50838
|
*
|
|
@@ -51338,6 +51226,12 @@ var DeviceInfoSchema = object({
|
|
|
51338
51226
|
addonId: string(),
|
|
51339
51227
|
type: _enum(DeviceType),
|
|
51340
51228
|
name: string(),
|
|
51229
|
+
/** The name a value template uses for this device (`{{ stufa_veranda.temperature }}`),
|
|
51230
|
+
* entity_id style. Generated once from the name at first registration, unique
|
|
51231
|
+
* cluster-wide, editable through `setAlias`, NOT changed by a rename (D1021).
|
|
51232
|
+
* Optional: a record produced by an older build omits it until the boot
|
|
51233
|
+
* backfill has run. */
|
|
51234
|
+
alias: DeviceAliasSchema.optional(),
|
|
51341
51235
|
/** Operator-organisational location label. `null` when unset. */
|
|
51342
51236
|
location: string().nullable(),
|
|
51343
51237
|
/** Soft-disabled flag. */
|
|
@@ -51657,6 +51551,25 @@ method(object({
|
|
|
51657
51551
|
}), _void(), {
|
|
51658
51552
|
kind: "mutation",
|
|
51659
51553
|
auth: "admin"
|
|
51554
|
+
}), method(object({
|
|
51555
|
+
deviceId: number(),
|
|
51556
|
+
alias: string()
|
|
51557
|
+
}), discriminatedUnion("ok", [object({
|
|
51558
|
+
ok: literal(true),
|
|
51559
|
+
alias: DeviceAliasSchema
|
|
51560
|
+
}), object({
|
|
51561
|
+
ok: literal(false),
|
|
51562
|
+
reason: _enum([
|
|
51563
|
+
"empty",
|
|
51564
|
+
"too-long",
|
|
51565
|
+
"grammar",
|
|
51566
|
+
"reserved",
|
|
51567
|
+
"taken"
|
|
51568
|
+
]),
|
|
51569
|
+
takenBy: number().optional()
|
|
51570
|
+
})]), {
|
|
51571
|
+
kind: "mutation",
|
|
51572
|
+
auth: "admin"
|
|
51660
51573
|
}), method(object({
|
|
51661
51574
|
deviceId: number(),
|
|
51662
51575
|
location: string().nullable()
|
|
@@ -54778,10 +54691,11 @@ var IntegrationInstanceDescriptionSchema = object({
|
|
|
54778
54691
|
/** True when `testInstance` really probes the remote. */
|
|
54779
54692
|
canTest: boolean(),
|
|
54780
54693
|
/**
|
|
54781
|
-
* The kinds an instance can be of
|
|
54782
|
-
* Add flow asks which first and sends it as
|
|
54694
|
+
* The kinds an instance can be of (D1013 rule 1), each naming its `functionCap`. One entry:
|
|
54695
|
+
* nothing to choose; more than one: the Add flow asks which first and sends it as
|
|
54696
|
+
* `createInstance.kind`. Never empty: every instance belongs to exactly one kind.
|
|
54783
54697
|
*/
|
|
54784
|
-
kinds: array(IntegrationInstanceKindSchema).
|
|
54698
|
+
kinds: array(IntegrationInstanceKindSchema).min(1),
|
|
54785
54699
|
/**
|
|
54786
54700
|
* The provider accepts `createInstance.id` for an id that once existed (an adopted id, because
|
|
54787
54701
|
* devices carry it). The UI then offers "restore under its old id" on Add. Absent means no.
|
|
@@ -54817,8 +54731,8 @@ var IntegrationInstanceSchema = object({
|
|
|
54817
54731
|
* the body is the one store, `setInstanceEnabled` the one writer (epic #440, step 3).
|
|
54818
54732
|
*/
|
|
54819
54733
|
enabled: boolean().optional(),
|
|
54820
|
-
/** The kind of this instance
|
|
54821
|
-
kind: string().
|
|
54734
|
+
/** The kind of this instance: exactly one of `describe().kinds[].id` (D1013 rule 2). */
|
|
54735
|
+
kind: string().min(1),
|
|
54822
54736
|
/** Values for the instance form; a secret is a `SecretFieldView`, never text. */
|
|
54823
54737
|
formValues: record(string(), unknown()),
|
|
54824
54738
|
status: IntegrationInstanceStatusSchema.optional(),
|
|
@@ -64388,6 +64302,11 @@ var NcScheduleSchema = object({
|
|
|
64388
64302
|
* as a STATE SUMMARY at the end of each window of `schedule`.
|
|
64389
64303
|
*/
|
|
64390
64304
|
var NcSystemEventDeliveryModeSchema = _enum(["instant", "summary"]);
|
|
64305
|
+
_enum([
|
|
64306
|
+
"activation",
|
|
64307
|
+
"deactivation",
|
|
64308
|
+
"schedule"
|
|
64309
|
+
]);
|
|
64391
64310
|
/**
|
|
64392
64311
|
* How a summary window is SENT (D698): `rule` (absent) = ONE notification with
|
|
64393
64312
|
* every section; `section` = one notification per section with something to
|
|
@@ -64404,11 +64323,26 @@ var NcStateSummarySplitSchema = _enum(["rule", "section"]);
|
|
|
64404
64323
|
* midnight crossing); the send time is each window's END. Refused on the
|
|
64405
64324
|
* `alarm` family, which stays instant (`systemEventDeliveryProblems`).
|
|
64406
64325
|
*/
|
|
64407
|
-
var NcSystemEventDeliverySchema = discriminatedUnion("mode", [
|
|
64408
|
-
mode: literal("
|
|
64409
|
-
|
|
64410
|
-
|
|
64411
|
-
|
|
64326
|
+
var NcSystemEventDeliverySchema = discriminatedUnion("mode", [
|
|
64327
|
+
object({ mode: literal("instant") }),
|
|
64328
|
+
object({
|
|
64329
|
+
mode: literal("summary"),
|
|
64330
|
+
schedule: NcScheduleSchema,
|
|
64331
|
+
split: NcStateSummarySplitSchema.optional()
|
|
64332
|
+
}),
|
|
64333
|
+
object({
|
|
64334
|
+
mode: literal("modes"),
|
|
64335
|
+
/** The bad edge, and every kind that has a single edge. */
|
|
64336
|
+
onActivation: boolean(),
|
|
64337
|
+
/** The recovery edges of the classes of the selected kinds (derived, never stored per kind). */
|
|
64338
|
+
onDeactivation: boolean(),
|
|
64339
|
+
/** A state summary at the end of each window; absent = no summary. */
|
|
64340
|
+
onSchedule: object({
|
|
64341
|
+
schedule: NcScheduleSchema,
|
|
64342
|
+
grouping: NcStateSummarySplitSchema
|
|
64343
|
+
}).optional()
|
|
64344
|
+
})
|
|
64345
|
+
]);
|
|
64412
64346
|
/** Fuzzy plate matcher — OCR noise makes exact match useless (spec row 12/13). */
|
|
64413
64347
|
var NcPlateMatcherSchema = object({
|
|
64414
64348
|
/**
|
|
@@ -71735,6 +71669,7 @@ var RemoteLayoutComponentSchema = object({
|
|
|
71735
71669
|
});
|
|
71736
71670
|
});
|
|
71737
71671
|
method(object({}), array(RemoteLayoutComponentSchema), { auth: "protected" });
|
|
71672
|
+
DeviceType.MediaPlayer;
|
|
71738
71673
|
var RunningStateSourceSchema = _enum(["native", "assigned"]);
|
|
71739
71674
|
object({
|
|
71740
71675
|
/** null = unknown — never coerced to false (D393). */
|
|
@@ -74269,6 +74204,11 @@ var TimedRunUnitSchema = _enum(["s", "min"]);
|
|
|
74269
74204
|
_enum(["switch", "pet-fountain"]);
|
|
74270
74205
|
DeviceType.Heater, DeviceType.PetFountain;
|
|
74271
74206
|
DeviceType.Heater, DeviceType.PetFountain;
|
|
74207
|
+
/** One duration, as the one-tap run asks for it. */
|
|
74208
|
+
var TimedRunQuickRunSchema = object({
|
|
74209
|
+
duration: number().positive().finite(),
|
|
74210
|
+
unit: TimedRunUnitSchema
|
|
74211
|
+
});
|
|
74272
74212
|
/** Why a request was not carried out. Typed, so a caller can say it in words. */
|
|
74273
74213
|
var TimedRunRefusalSchema = _enum([
|
|
74274
74214
|
"unsupported-device",
|
|
@@ -74289,9 +74229,30 @@ object({
|
|
|
74289
74229
|
activeUntil: number().nullable(),
|
|
74290
74230
|
/** Who asked for the run (a user id or an addon id); `null` when nothing is armed or it did not say. */
|
|
74291
74231
|
requestedBy: string().nullable(),
|
|
74232
|
+
/**
|
|
74233
|
+
* The one-tap run of THIS device: what a "Run" button on any surface starts. `null` when
|
|
74234
|
+
* the device is gone or its type has no timed run; a status from before this field
|
|
74235
|
+
* existed has none, and a surface falls back to the type's default.
|
|
74236
|
+
*/
|
|
74237
|
+
quickRun: TimedRunQuickRunSchema.nullable(),
|
|
74292
74238
|
lastFetchedAt: number()
|
|
74293
74239
|
});
|
|
74294
|
-
|
|
74240
|
+
/** What the settings form needs: the unit, the bounds and the type's default. */
|
|
74241
|
+
var TimedRunOptionsSchema = object({
|
|
74242
|
+
unit: TimedRunUnitSchema,
|
|
74243
|
+
/** The longest run, in `unit`. */
|
|
74244
|
+
maxDuration: number(),
|
|
74245
|
+
defaultDuration: number()
|
|
74246
|
+
});
|
|
74247
|
+
/** The one-tap run duration, in the type's unit; `null` returns to the type's default. */
|
|
74248
|
+
var TimedRunSettingsPatchSchema = object({ quickRunDuration: number().positive().finite().nullable().optional() });
|
|
74249
|
+
method(object({ deviceId: number().int() }), TimedRunOptionsSchema), method(object({
|
|
74250
|
+
deviceId: number().int(),
|
|
74251
|
+
settings: TimedRunSettingsPatchSchema
|
|
74252
|
+
}), _void(), {
|
|
74253
|
+
kind: "mutation",
|
|
74254
|
+
auth: "admin"
|
|
74255
|
+
}), method(object({
|
|
74295
74256
|
deviceId: number().int(),
|
|
74296
74257
|
duration: number().positive().finite(),
|
|
74297
74258
|
unit: TimedRunUnitSchema
|
|
@@ -76997,13 +76958,6 @@ Object.freeze({
|
|
|
76997
76958
|
access: "view",
|
|
76998
76959
|
role: "admin"
|
|
76999
76960
|
},
|
|
77000
|
-
"addonSettings.getGlobalSettings": {
|
|
77001
|
-
capName: "addon-settings",
|
|
77002
|
-
capScope: "system",
|
|
77003
|
-
addonId: null,
|
|
77004
|
-
access: "view",
|
|
77005
|
-
role: "admin"
|
|
77006
|
-
},
|
|
77007
76961
|
"addonSettings.getIntegrationFormSchema": {
|
|
77008
76962
|
capName: "addon-settings",
|
|
77009
76963
|
capScope: "system",
|
|
@@ -77011,14 +76965,14 @@ Object.freeze({
|
|
|
77011
76965
|
access: "view",
|
|
77012
76966
|
role: "admin"
|
|
77013
76967
|
},
|
|
77014
|
-
"addonSettings.
|
|
76968
|
+
"addonSettings.getScopedSettings": {
|
|
77015
76969
|
capName: "addon-settings",
|
|
77016
76970
|
capScope: "system",
|
|
77017
76971
|
addonId: null,
|
|
77018
76972
|
access: "view",
|
|
77019
76973
|
role: "admin"
|
|
77020
76974
|
},
|
|
77021
|
-
"addonSettings.
|
|
76975
|
+
"addonSettings.listScopedSettings": {
|
|
77022
76976
|
capName: "addon-settings",
|
|
77023
76977
|
capScope: "system",
|
|
77024
76978
|
addonId: null,
|
|
@@ -77046,13 +77000,6 @@ Object.freeze({
|
|
|
77046
77000
|
access: "create",
|
|
77047
77001
|
role: "admin"
|
|
77048
77002
|
},
|
|
77049
|
-
"addonSettings.updateGlobalSettings": {
|
|
77050
|
-
capName: "addon-settings",
|
|
77051
|
-
capScope: "system",
|
|
77052
|
-
addonId: null,
|
|
77053
|
-
access: "create",
|
|
77054
|
-
role: "admin"
|
|
77055
|
-
},
|
|
77056
77003
|
"addonSettings.updateScopedSettings": {
|
|
77057
77004
|
capName: "addon-settings",
|
|
77058
77005
|
capScope: "system",
|
|
@@ -79223,6 +79170,13 @@ Object.freeze({
|
|
|
79223
79170
|
access: "create",
|
|
79224
79171
|
role: "admin"
|
|
79225
79172
|
},
|
|
79173
|
+
"deviceManager.setAlias": {
|
|
79174
|
+
capName: "device-manager",
|
|
79175
|
+
capScope: "system",
|
|
79176
|
+
addonId: null,
|
|
79177
|
+
access: "create",
|
|
79178
|
+
role: "admin"
|
|
79179
|
+
},
|
|
79226
79180
|
"deviceManager.setChildLayout": {
|
|
79227
79181
|
capName: "device-manager",
|
|
79228
79182
|
capScope: "system",
|
|
@@ -86006,6 +85960,13 @@ Object.freeze({
|
|
|
86006
85960
|
access: "create",
|
|
86007
85961
|
role: "viewer"
|
|
86008
85962
|
},
|
|
85963
|
+
"timedRun.getOptions": {
|
|
85964
|
+
capName: "timed-run",
|
|
85965
|
+
capScope: "device",
|
|
85966
|
+
addonId: null,
|
|
85967
|
+
access: "view",
|
|
85968
|
+
role: "viewer"
|
|
85969
|
+
},
|
|
86009
85970
|
"timedRun.getStatus": {
|
|
86010
85971
|
capName: "timed-run",
|
|
86011
85972
|
capScope: "device",
|
|
@@ -86020,6 +85981,13 @@ Object.freeze({
|
|
|
86020
85981
|
access: "create",
|
|
86021
85982
|
role: "viewer"
|
|
86022
85983
|
},
|
|
85984
|
+
"timedRun.setSettings": {
|
|
85985
|
+
capName: "timed-run",
|
|
85986
|
+
capScope: "device",
|
|
85987
|
+
addonId: null,
|
|
85988
|
+
access: "create",
|
|
85989
|
+
role: "admin"
|
|
85990
|
+
},
|
|
86023
85991
|
"toast.onToast": {
|
|
86024
85992
|
capName: "toast",
|
|
86025
85993
|
capScope: "system",
|
|
@@ -86950,6 +86918,7 @@ function offered(received) {
|
|
|
86950
86918
|
};
|
|
86951
86919
|
}
|
|
86952
86920
|
offered(HA_AS), withheld(HOMEKIT_REASON), withheld(ALEXA_REASON), withheld(GOOGLE_REASON), withheld(MATTER_REASON);
|
|
86921
|
+
string().min(1).max(4096);
|
|
86953
86922
|
Object.freeze({
|
|
86954
86923
|
"accessories.getStatus": [{
|
|
86955
86924
|
name: "deviceId",
|
|
@@ -87633,6 +87602,11 @@ Object.freeze({
|
|
|
87633
87602
|
form: "single",
|
|
87634
87603
|
optional: false
|
|
87635
87604
|
}],
|
|
87605
|
+
"deviceManager.setAlias": [{
|
|
87606
|
+
name: "deviceId",
|
|
87607
|
+
form: "single",
|
|
87608
|
+
optional: false
|
|
87609
|
+
}],
|
|
87636
87610
|
"deviceManager.setChildLayout": [{
|
|
87637
87611
|
name: "deviceId",
|
|
87638
87612
|
form: "single",
|
|
@@ -89697,6 +89671,11 @@ Object.freeze({
|
|
|
89697
89671
|
form: "single",
|
|
89698
89672
|
optional: false
|
|
89699
89673
|
}],
|
|
89674
|
+
"timedRun.getOptions": [{
|
|
89675
|
+
name: "deviceId",
|
|
89676
|
+
form: "single",
|
|
89677
|
+
optional: false
|
|
89678
|
+
}],
|
|
89700
89679
|
"timedRun.getStatus": [{
|
|
89701
89680
|
name: "deviceId",
|
|
89702
89681
|
form: "single",
|
|
@@ -89707,6 +89686,11 @@ Object.freeze({
|
|
|
89707
89686
|
form: "single",
|
|
89708
89687
|
optional: false
|
|
89709
89688
|
}],
|
|
89689
|
+
"timedRun.setSettings": [{
|
|
89690
|
+
name: "deviceId",
|
|
89691
|
+
form: "single",
|
|
89692
|
+
optional: false
|
|
89693
|
+
}],
|
|
89710
89694
|
"update.getStatus": [{
|
|
89711
89695
|
name: "deviceId",
|
|
89712
89696
|
form: "single",
|
|
@@ -90569,6 +90553,7 @@ var STATE_SUMMARY_VARS = [
|
|
|
90569
90553
|
[...RULE_TEXT],
|
|
90570
90554
|
[...RULE_TEXT],
|
|
90571
90555
|
[...RULE_TEXT],
|
|
90556
|
+
[...RULE_TEXT],
|
|
90572
90557
|
[...RULE_BODY_ONLY],
|
|
90573
90558
|
[...RULE_TEXT],
|
|
90574
90559
|
([...RULE_TEXT], [...DEVICE_EVENTS]),
|
|
@@ -136224,7 +136209,14 @@ function buildMailboxInstances(records, deps) {
|
|
|
136224
136209
|
role: "services",
|
|
136225
136210
|
instanceMode: "multiple",
|
|
136226
136211
|
kind: "mailbox",
|
|
136227
|
-
canTest: true
|
|
136212
|
+
canTest: true,
|
|
136213
|
+
kinds: [{
|
|
136214
|
+
id: MAILBOX_INSTANCE_KIND,
|
|
136215
|
+
label: "Inbound mailbox (SMTP)",
|
|
136216
|
+
functionCap: "broker",
|
|
136217
|
+
role: "services",
|
|
136218
|
+
brokerKind: SMTP_INBOUND_KIND
|
|
136219
|
+
}]
|
|
136228
136220
|
},
|
|
136229
136221
|
formSchema: () => mailboxSettingsSchema(),
|
|
136230
136222
|
initialBody: (name) => newMailboxBody(name),
|
|
@@ -145960,7 +145952,13 @@ var SmtpNodemailerAddon = class extends BaseAddon {
|
|
|
145960
145952
|
role: "services",
|
|
145961
145953
|
instanceMode: "multiple",
|
|
145962
145954
|
kind: "relays",
|
|
145963
|
-
canTest: true
|
|
145955
|
+
canTest: true,
|
|
145956
|
+
kinds: [{
|
|
145957
|
+
id: "relays",
|
|
145958
|
+
label: "SMTP relay",
|
|
145959
|
+
functionCap: "smtp-provider",
|
|
145960
|
+
role: "services"
|
|
145961
|
+
}]
|
|
145964
145962
|
},
|
|
145965
145963
|
formSchema: () => this.relayForm(),
|
|
145966
145964
|
initialBody: (name) => ({
|