"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Capability = exports.commonOptions = void 0; const schema_js_1 = require("../registry/schema.js"); const types_js_1 = require("../registry/types.js"); /** The same as a schema. The friendly names are checked with the instance, by the rules of the interface. */ exports.commonOptions = schema_js_1.s.object({ instance: schema_js_1.s.optional(schema_js_1.s.string()), friendlyNames: schema_js_1.s.optional(schema_js_1.s.array(schema_js_1.s.unknown())), retrievable: schema_js_1.s.optional(schema_js_1.s.boolean()), proactivelyReported: schema_js_1.s.optional(schema_js_1.s.boolean()), nonControllable: schema_js_1.s.optional(schema_js_1.s.boolean()), }); /** One interface as an endpoint declares it: the descriptor, and what the declaration says about this endpoint. */ class Capability { constructor(descriptor, declared) { this.descriptor = descriptor; /** The endpoint the capability is declared on; the device sets it. */ this.endpointId = ""; /** What the bridge logs about the declaration, once, when it answers a discovery. */ this.notes = []; this.handlers = new Map(); this.instance = declared.instance ?? ""; this.friendlyNames = declared.friendlyNames ?? []; this.retrievable = declared.retrievable ?? true; this.proactivelyReported = declared.proactivelyReported ?? false; this.nonControllable = declared.nonControllable; this.options = declared.options; } get namespace() { return this.descriptor.namespace; } on(name, handler) { const names = Object.keys(this.descriptor.directives); // An interface the library only names (tier 3) describes no directive: any name is taken if (name !== "*" && this.descriptor.tier !== 3 && !names.includes(name)) { throw new types_js_1.DeclarationError(this, `${name} is not a directive of the interface, which has ${names.join(", ") || "none"}`); } if (typeof handler !== "function") { throw new types_js_1.DeclarationError(this, `on("${name}") got ${handler === null ? "null" : typeof handler} as the handler: pass a function that takes the context of the directive`); } this.handlers.set(name, handler); return this; } /** The handler on(name) registered, or the one of "*". */ handlerFor(name) { return this.handlers.get(name) ?? this.handlers.get("*"); } /** Mappings of "open", "close", "raise", "lower" and of states, when the declaration has any. */ get semantics() { const { semantics } = this.options; const mapped = (semantics?.actionMappings?.length ?? 0) + (semantics?.stateMappings?.length ?? 0); return mapped > 0 ? semantics : undefined; } /** The capability object for discovery, its fields in the order of the example on alexa-discovery-objects.html. */ toJSON() { const { descriptor, semantics } = this; const extras = descriptor.discovery ? descriptor.discovery(this) : {}; const json = { type: "AlexaInterface", interface: descriptor.namespace, ...(this.instance ? { instance: this.instance } : {}), version: descriptor.version, }; if (extras.properties !== false) { json.properties = { supported: (extras.supported ?? Object.keys(descriptor.properties)).map((name) => ({ name })), proactivelyReported: this.proactivelyReported, retrievable: this.retrievable, }; if (this.nonControllable !== undefined) json.properties.nonControllable = this.nonControllable; } if (this.friendlyNames.length > 0) json.capabilityResources = { friendlyNames: this.friendlyNames }; if (extras.configuration) json.configuration = extras.configuration; if (extras.configurations) json.configurations = extras.configurations; if (semantics) json.semantics = semantics; return { ...json, ...extras.topLevel }; } } exports.Capability = Capability;