Skip to content

Commit

Permalink
text
Browse files Browse the repository at this point in the history
  • Loading branch information
zoe-codez committed May 25, 2024
1 parent bd67bd4 commit 87026ac
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 70 deletions.
1 change: 1 addition & 0 deletions src/extensions/domains/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ export * from "./scene.extension";
export * from "./select.extension";
export * from "./sensor.extension";
export * from "./switch.extension";
export * from "./text.extension";
121 changes: 121 additions & 0 deletions src/extensions/domains/text.extension.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import { is, TServiceParams } from "@digital-alchemy/core";

import { RemovableCallback, VIRTUAL_ENTITY_BASE_KEYS } from "../../helpers";
import {
SynapseTextParams,
SynapseVirtualText,
TextConfiguration,
} from "../../helpers/domains/text";
import { TRegistry } from "../registry.extension";

export function VirtualText({ context, synapse }: TServiceParams) {
const registry = synapse.registry.create<SynapseVirtualText>({
context,
// @ts-expect-error it's fine
domain: "select",
});

// #MARK: create
return function <
STATE extends string = string,
ATTRIBUTES extends object = object,
>(entity: SynapseTextParams) {
const proxy = new Proxy({} as SynapseVirtualText, {
// #MARK: get
get(_, property: keyof SynapseVirtualText) {
// > common
// * name
if (property === "name") {
return entity.name;
}
// * unique_id
if (property === "unique_id") {
return unique_id;
}
// * onUpdate
if (property === "onUpdate") {
return loader.onUpdate();
}
// * _rawConfiguration
if (property === "_rawConfiguration") {
return loader.configuration;
}
// * _rawAttributes
if (property === "_rawAttributes") {
return loader.attributes;
}
// * attributes
if (property === "attributes") {
return loader.attributesProxy();
}
// * configuration
if (property === "configuration") {
return loader.configurationProxy();
}
// * state
if (property === "state") {
return loader.state;
}
// > domain specific
// * onActivate
if (property === "onSetValue") {
return (callback: RemovableCallback) =>
synapse.registry.removableListener(SET_VALUE, callback);
}
return undefined;
},

ownKeys: () => [...VIRTUAL_ENTITY_BASE_KEYS, "onSetValue"],

// #MARK: set
set(_, property: string, value: unknown) {
// > common
// * state
if (property === "state") {
loader.setState(value as STATE);
return true;
}
// * attributes
if (property === "attributes") {
loader.setAttributes(value as ATTRIBUTES);
return true;
}
return false;
},
});

// - Add to registry
const unique_id = registry.add(proxy, entity);

// - Initialize value storage
const loader = synapse.storage.wrapper<
STATE,
ATTRIBUTES,
TextConfiguration
>({
load_keys: ["mode", "max", "min", "pattern"],
name: entity.name,
registry: registry as TRegistry<unknown>,
unique_id,
});

// - Attach bus events
const SET_VALUE = synapse.registry.busTransfer({
context,
eventName: "set_value",
unique_id,
});

// - Attach static listener
if (is.function(entity.set_value)) {
proxy.onSetValue(entity.set_value);
}

if (entity.managed !== false) {
proxy.onSetValue(({ value }) => (proxy.state = value));
}

// - Done
return proxy;
};
}
12 changes: 4 additions & 8 deletions src/helpers/domains/select.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
RemovableCallback,
} from "../base-domain.helper";
import { EntityConfigCommon } from "../common-config.helper";
import { SensorDeviceClasses } from "./sensor";

export type SynapseSelectParams = BaseEntityParams<string> &
SelectConfiguration & {
Expand All @@ -16,15 +15,12 @@ export type SynapseSelectParams = BaseEntityParams<string> &
managed?: boolean;
};

// supposed to be the same thing
export type SelectDeviceClasses = SensorDeviceClasses;
type SetValueData = { value: string };

export type SelectConfiguration = EntityConfigCommon &
SelectDeviceClasses & {
current_option?: string;
options?: string[];
};
export type SelectConfiguration = EntityConfigCommon & {
current_option?: string;
options?: string[];
};

export type SynapseVirtualSelect = BaseVirtualEntity<
string,
Expand Down
86 changes: 24 additions & 62 deletions src/helpers/domains/text.ts
Original file line number Diff line number Diff line change
@@ -1,72 +1,34 @@
import { TContext } from "@digital-alchemy/core";
import { PICK_ENTITY } from "@digital-alchemy/hass";
import {
BaseEntityParams,
BaseVirtualEntity,
CreateRemovableCallback,
RemovableCallback,
} from "../base-domain.helper";
import { EntityConfigCommon } from "../common-config.helper";
import { SensorDeviceClasses } from "./sensor";

import { BASE_CONFIG_KEYS, EntityConfigCommon } from "../common-config.helper";
import { UpdateCallback } from "../event";
import { TSynapseId } from "../utility.helper";
export type SynapseTextParams = BaseEntityParams<string> &
TextConfiguration & {
set_value: RemovableCallback<SetValueData>;
/**
* default: true
*/
managed?: boolean;
};

export type TText<
STATE extends TextValue,
ATTRIBUTES extends object = object,
> = {
context: TContext;
defaultState?: STATE;
defaultAttributes?: ATTRIBUTES;
name: string;
} & TextConfiguration;
// supposed to be the same thing
export type TextDeviceClasses = SensorDeviceClasses;
type SetValueData = { value: string };

export type TextConfiguration = EntityConfigCommon & {
/**
* Defines how the text should be displayed in the UI.
* It's recommended to use the default `auto`.
* Can be `box` or `slider` to force a display mode.
*/
mode?: "text" | "password";
max?: number;
min?: number;
step?: string;
pattern?: string;
};

export type TextValue = string;

export const TEXT_CONFIGURATION_KEYS = [
...BASE_CONFIG_KEYS,
"mode",
"max",
"min",
"step",
"pattern",
] as (keyof TextConfiguration)[];

export type HassTextEvent = { data: { unique_id: TSynapseId } };

export type TVirtualText<
STATE extends TextValue = TextValue,
ATTRIBUTES extends object = object,
CONFIGURATION extends TextConfiguration = TextConfiguration,
// @ts-expect-error its fine
ENTITY_ID extends PICK_ENTITY<"text"> = PICK_ENTITY<"text">,
> = {
/**
* Do not define attributes that change frequently.
* Create new sensors instead
*/
attributes: ATTRIBUTES;
configuration: CONFIGURATION;
_rawAttributes: ATTRIBUTES;
_rawConfiguration: ATTRIBUTES;
name: string;
/**
* look up the entity id, and
*/
onUpdate: UpdateCallback<ENTITY_ID>;
/**
* the current state
*/
state: STATE;
/**
* Used to uniquely identify this entity in home assistant
*/
unique_id: string;
};
export type SynapseVirtualText = BaseVirtualEntity<
string,
object,
TextConfiguration
> & { onSetValue: CreateRemovableCallback<SetValueData> };
2 changes: 2 additions & 0 deletions src/synapse.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
VirtualSelect,
VirtualSensor,
VirtualSwitch,
VirtualText,
} from "./extensions";
import { HassDeviceMetadata } from "./helpers";

Expand Down Expand Up @@ -122,6 +123,7 @@ export const LIB_SYNAPSE = CreateLibrary({
storage: ValueStorage,

switch: VirtualSwitch,
text: VirtualText,
},
});

Expand Down

0 comments on commit 87026ac

Please sign in to comment.