@basmilius/homey-common 0.0.1

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.
@@ -0,0 +1,41 @@
1
+ import type { Constructor } from './types';
2
+
3
+ export function action(id: string) {
4
+ return <T extends Constructor>(ActionClass: T): T => {
5
+ return class extends ActionClass {
6
+ get actionId(): string {
7
+ return id;
8
+ }
9
+ };
10
+ };
11
+ }
12
+
13
+ export function autocomplete(id: string) {
14
+ return <T extends Constructor>(AutocompleteClass: T): T => {
15
+ return class extends AutocompleteClass {
16
+ get autocompleteId(): string {
17
+ return id;
18
+ }
19
+ };
20
+ };
21
+ }
22
+
23
+ export function condition(id: string) {
24
+ return <T extends Constructor>(ConditionClass: T): T => {
25
+ return class extends ConditionClass {
26
+ get conditionId(): string {
27
+ return id;
28
+ }
29
+ };
30
+ };
31
+ }
32
+
33
+ export function trigger(id: string) {
34
+ return <T extends Constructor>(TriggerClass: T): T => {
35
+ return class extends TriggerClass {
36
+ get triggerId(): string {
37
+ return id;
38
+ }
39
+ };
40
+ };
41
+ }
package/src/flow.ts ADDED
@@ -0,0 +1,91 @@
1
+ import type Homey from 'homey';
2
+ import { type App, Shortcuts } from './app';
3
+ import type { AutocompleteProvider, FlowCardType } from './types';
4
+
5
+ export abstract class FlowEntity<T extends Homey.FlowCard, TArgs = unknown, TState = unknown, TResult = unknown> extends Shortcuts {
6
+ get card(): T {
7
+ return this.#card;
8
+ }
9
+
10
+ get id(): string {
11
+ return this.#card.id;
12
+ }
13
+
14
+ get type(): FlowCardType {
15
+ return this.#card.type;
16
+ }
17
+
18
+ readonly #card: T;
19
+
20
+ constructor(app: App) {
21
+ super(app);
22
+
23
+ this.#card = this.#getCard();
24
+
25
+ this.onInit()
26
+ .then()
27
+ .catch(console.error.bind(console));
28
+ }
29
+
30
+ async onInit(): Promise<void> {
31
+ this.#card.registerRunListener(this.onRun.bind(this));
32
+ this.#card.on('update', this.onUpdate.bind(this));
33
+
34
+ this.log(`onInit() -> Flow card ${this.type}#${this.id} has been registered.`);
35
+ }
36
+
37
+ abstract onRun(args: TArgs, state: TState): Promise<TResult>;
38
+
39
+ async onUpdate(): Promise<void> {
40
+ }
41
+
42
+ registerAutocomplete<T extends FlowAutocompleteProvider>(name: string, autocompleteProvider: AutocompleteProvider<T>): void {
43
+ const provider = this.registry.findAutocompleteProvider(autocompleteProvider);
44
+
45
+ if (!provider) {
46
+ throw new Error(`Unable to register autocomplete for ${this.type}#${this.id}. The provider was not registered.`);
47
+ }
48
+
49
+ this.#card.registerArgumentAutocompleteListener(name, provider.find.bind(provider));
50
+ }
51
+
52
+ #getCard(): T {
53
+ if (this instanceof FlowActionEntity) {
54
+ return this.homey.flow.getActionCard((this as any).actionId) as unknown as T;
55
+ }
56
+
57
+ if (this instanceof FlowConditionEntity) {
58
+ return this.homey.flow.getConditionCard((this as any).conditionId) as unknown as T;
59
+ }
60
+
61
+ if (this instanceof FlowTriggerEntity) {
62
+ return this.homey.flow.getTriggerCard((this as any).triggerId) as unknown as T;
63
+ }
64
+
65
+ throw new Error(`Flow card type ${this.constructor.name} not found.`);
66
+ }
67
+ }
68
+
69
+ export abstract class FlowActionEntity<TArgs = unknown, TState = unknown, TResult = unknown> extends FlowEntity<Homey.FlowCardAction, TArgs, TState, TResult> {
70
+ }
71
+
72
+ export abstract class FlowConditionEntity<TArgs = unknown, TState = unknown> extends FlowEntity<Homey.FlowCardCondition, TArgs, TState, boolean> {
73
+ }
74
+
75
+ export abstract class FlowTriggerEntity<TArgs = unknown, TState = unknown> extends FlowEntity<Homey.FlowCardTrigger, TArgs, TState, boolean> {
76
+ async trigger(state: TState, tokens?: Record<string, unknown>): Promise<any> {
77
+ return this.card.trigger(tokens, state as object);
78
+ }
79
+ }
80
+
81
+ export abstract class FlowAutocompleteProvider extends Shortcuts {
82
+ abstract find(query: string, args: Record<string, unknown>): Promise<Homey.FlowCard.ArgumentAutocompleteResults>;
83
+
84
+ async update(): Promise<void> {
85
+ }
86
+
87
+ async onInit(): Promise<void> {
88
+ this.homey.log(`onInit() -> Autocomplete provider ${(this as any).autocompleteId} has been registered.`);
89
+ await this.update();
90
+ }
91
+ }
package/src/index.ts ADDED
@@ -0,0 +1,33 @@
1
+ export type {
2
+ ApiRequest,
3
+ Color,
4
+ Constructor,
5
+ FlowCardType,
6
+ Icon,
7
+ Language,
8
+ WidgetApiRequest
9
+ } from './types';
10
+
11
+ export {
12
+ action,
13
+ autocomplete,
14
+ condition,
15
+ trigger
16
+ } from './decorator';
17
+
18
+ export {
19
+ FlowEntity,
20
+ FlowActionEntity,
21
+ FlowAutocompleteProvider,
22
+ FlowConditionEntity,
23
+ FlowTriggerEntity
24
+ } from './flow';
25
+
26
+ export {
27
+ Registry
28
+ } from './registry';
29
+
30
+ export {
31
+ colors,
32
+ icons
33
+ } from './data';
@@ -0,0 +1,58 @@
1
+ import { Shortcuts } from './app';
2
+ import type { FlowActionEntity, FlowAutocompleteProvider, FlowConditionEntity, FlowTriggerEntity } from './flow';
3
+ import type { Action, AutocompleteProvider, Condition, Trigger } from './types';
4
+
5
+ export class Registry extends Shortcuts {
6
+ get actions(): FlowActionEntity[] {
7
+ return this.#actions;
8
+ }
9
+
10
+ get autocompleteProviders(): FlowAutocompleteProvider[] {
11
+ return this.#autocompleteProviders;
12
+ }
13
+
14
+ get conditions(): FlowConditionEntity[] {
15
+ return this.#conditions;
16
+ }
17
+
18
+ get triggers(): FlowTriggerEntity[] {
19
+ return this.#triggers;
20
+ }
21
+
22
+ readonly #actions: FlowActionEntity[] = [];
23
+ readonly #autocompleteProviders: FlowAutocompleteProvider[] = [];
24
+ readonly #conditions: FlowConditionEntity[] = [];
25
+ readonly #triggers: FlowTriggerEntity[] = [];
26
+
27
+ action<T extends FlowActionEntity>(action: Action<T>): void {
28
+ this.#actions.push(new action(this.app));
29
+ }
30
+
31
+ autocompleteProvider<T extends FlowAutocompleteProvider>(autocompleteProvider: AutocompleteProvider<T>): void {
32
+ this.#autocompleteProviders.push(new autocompleteProvider(this.app));
33
+ }
34
+
35
+ condition<T extends FlowConditionEntity>(condition: Condition<T>): void {
36
+ this.#conditions.push(new condition(this.app));
37
+ }
38
+
39
+ trigger<T extends FlowTriggerEntity>(trigger: Trigger<T>): void {
40
+ this.#triggers.push(new trigger(this.app));
41
+ }
42
+
43
+ findAction<T extends FlowActionEntity>(action: Action<T>): T | undefined {
44
+ return this.#actions.find(a => a instanceof action) as T;
45
+ }
46
+
47
+ findAutocompleteProvider<T extends FlowAutocompleteProvider>(autocompleteProvider: AutocompleteProvider<T>): T | undefined {
48
+ return this.#autocompleteProviders.find(a => a instanceof autocompleteProvider) as T;
49
+ }
50
+
51
+ findCondition<T extends FlowConditionEntity>(condition: Condition<T>): T | undefined {
52
+ return this.#conditions.find(a => a instanceof condition) as T;
53
+ }
54
+
55
+ findTrigger<T extends FlowTriggerEntity>(trigger: Trigger<T>): T | undefined {
56
+ return this.#triggers.find(a => a instanceof trigger) as T;
57
+ }
58
+ }
package/src/types.ts ADDED
@@ -0,0 +1,52 @@
1
+ import type Homey from 'homey/lib/Homey';
2
+ import type { App } from './app';
3
+ import type { FlowActionEntity, FlowAutocompleteProvider, FlowConditionEntity, FlowTriggerEntity } from './flow';
4
+
5
+ export type Constructor<T = {}> = new (...args: any[]) => T;
6
+
7
+ export type Action<T extends FlowActionEntity> = new (app: App) => T;
8
+ export type AutocompleteProvider<T extends FlowAutocompleteProvider> = new (app: App) => T;
9
+ export type Condition<T extends FlowConditionEntity> = new (app: App) => T;
10
+ export type Trigger<T extends FlowTriggerEntity> = new (app: App) => T;
11
+
12
+ export type FlowCardType =
13
+ | 'action'
14
+ | 'condition'
15
+ | 'trigger';
16
+
17
+ export type Color = {
18
+ readonly hex: string;
19
+ readonly label: string;
20
+ };
21
+
22
+ export type Icon = {
23
+ readonly id: string;
24
+ readonly name: string;
25
+ readonly unicode: string;
26
+ };
27
+
28
+ export type Language =
29
+ | 'en'
30
+ | 'nl'
31
+ | 'de'
32
+ | 'es'
33
+ | 'fr'
34
+ | 'it'
35
+ | 'ko'
36
+ | 'no'
37
+ | 'pl'
38
+ | 'ru'
39
+ | 'sv';
40
+
41
+ export type ApiRequest<TApp> = {
42
+ readonly homey: Homey & {
43
+ readonly app: TApp;
44
+ };
45
+ readonly body: any;
46
+ readonly params: Record<string, unknown>;
47
+ readonly query: Record<string, string>;
48
+ };
49
+
50
+ export type WidgetApiRequest<TApp> = ApiRequest<TApp> & {
51
+ readonly widgetInstanceId: string;
52
+ };
package/tsconfig.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "esnext",
4
+ "lib": [
5
+ "dom",
6
+ "dom.iterable",
7
+ "esnext"
8
+ ],
9
+ "allowJs": true,
10
+ "skipLibCheck": true,
11
+ "strict": false,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "esModuleInterop": true,
14
+ "module": "esnext",
15
+ "moduleResolution": "bundler",
16
+ "resolveJsonModule": true,
17
+ "isolatedModules": true,
18
+ "jsx": "react-jsx",
19
+ "baseUrl": ".",
20
+ "rootDir": "src",
21
+ "outDir": "dist",
22
+ "declaration": true,
23
+ "declarationDir": "dist",
24
+ "declarationMap": true,
25
+ "emitDeclarationOnly": true,
26
+ "experimentalDecorators": true
27
+ },
28
+ "include": [
29
+ "src/**/*.ts",
30
+ "build.ts"
31
+ ],
32
+ "exclude": [
33
+ "dist",
34
+ "node_modules"
35
+ ]
36
+ }