diff --git a/README.md b/README.md index f0ea9f77..eb2c372b 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ async function connect() { if (err === ERR_HASS_HOST_REQUIRED) { const hassUrl = prompt( "What host to connect to?", - "http://localhost:8123" + "http://localhost:8123", ); // Redirect user to log in on their instance auth = await getAuth({ hassUrl }); @@ -137,7 +137,7 @@ connection.suspendReconnectUntil( new Promise((resolve) => { // When you want to try to reconnect again, resolve the promise. resolve(); - }) + }), ); ``` @@ -154,7 +154,7 @@ connection.suspendReconnectUntil( new Promise((resolve) => { // When you want to try to reconnect again, resolve the promise. resolve(); - }) + }), ); connection.suspend(); ``` @@ -166,7 +166,7 @@ connection.suspend( new Promise((resolve) => { // When you want to try to reconnect again, resolve the promise. resolve(); - }) + }), ); ``` @@ -435,7 +435,7 @@ import { (async () => { const auth = createLongLivedTokenAuth( "http://localhost:8123", - "YOUR ACCESS TOKEN" + "YOUR ACCESS TOKEN", ); const connection = await createConnection({ auth }); diff --git a/example.html b/example.html index 9f15f325..3923a226 100644 --- a/example.html +++ b/example.html @@ -1,4 +1,4 @@ - + @@ -41,7 +41,7 @@ if (err === ERR_HASS_HOST_REQUIRED) { authOptions.hassUrl = prompt( "What host to connect to?", - "http://localhost:8123" + "http://localhost:8123", ); if (!authOptions.hassUrl) return; auth = await getAuth(authOptions); @@ -80,7 +80,7 @@ await new Promise((resolve) => setTimeout(resolve, 4000)); } unsubEntities = subscribeEntities(connection, (entities) => - renderEntities(connection, entities) + renderEntities(connection, entities), ); }; @@ -104,7 +104,7 @@ if ( ["switch", "light", "input_boolean"].includes( - entId.split(".", 1)[0] + entId.split(".", 1)[0], ) ) { const button = document.createElement("button"); diff --git a/lib/auth.ts b/lib/auth.ts index 3ab82864..d2b1292d 100644 --- a/lib/auth.ts +++ b/lib/auth.ts @@ -68,10 +68,10 @@ function genAuthorizeUrl( hassUrl: string, clientId: string | null, redirectUrl: string, - state: string + state: string, ) { let authorizeUrl = `${hassUrl}/auth/authorize?response_type=code&redirect_uri=${encodeURIComponent( - redirectUrl + redirectUrl, )}`; if (clientId !== null) { @@ -88,7 +88,7 @@ function redirectAuthorize( hassUrl: string, clientId: string | null, redirectUrl: string, - state: string + state: string, ) { // Add either ?auth_callback=1 or &auth_callback=1 redirectUrl += (redirectUrl.includes("?") ? "&" : "?") + "auth_callback=1"; @@ -97,14 +97,14 @@ function redirectAuthorize( hassUrl, clientId, redirectUrl, - state + state, ); } async function tokenRequest( hassUrl: string, clientId: string | null, - data: AuthorizationCodeRequest | RefreshTokenRequest + data: AuthorizationCodeRequest | RefreshTokenRequest, ) { // Browsers don't allow fetching tokens from https -> http. // Throw an error because it's a pain to debug this. @@ -224,7 +224,7 @@ export class Auth { export function createLongLivedTokenAuth( hassUrl: string, - access_token: string + access_token: string, ) { return new Auth({ hassUrl, @@ -300,7 +300,7 @@ export async function getAuth(options: getAuthOptions = {}): Promise { encodeOAuthState({ hassUrl, clientId, - }) + }), ); // Just don't resolve while we navigate to next page return new Promise(() => {}); diff --git a/lib/collection.ts b/lib/collection.ts index df4b36ae..2124bc08 100644 --- a/lib/collection.ts +++ b/lib/collection.ts @@ -26,9 +26,9 @@ export const getCollection = ( fetchCollection: ((conn: Connection) => Promise) | undefined, subscribeUpdates?: ( conn: Connection, - store: Store + store: Store, ) => Promise, - options: { unsubGrace: boolean } = { unsubGrace: true } + options: { unsubGrace: boolean } = { unsubGrace: true }, ): Collection => { if (conn[key]) { return conn[key]; @@ -170,8 +170,8 @@ export const createCollection = ( | ((conn: Connection, store: Store) => Promise) | undefined, conn: Connection, - onChange: (state: State) => void + onChange: (state: State) => void, ): UnsubscribeFunc => getCollection(conn, key, fetchCollection, subscribeUpdates).subscribe( - onChange + onChange, ); diff --git a/lib/commands.ts b/lib/commands.ts index 43baeec7..c0b47079 100644 --- a/lib/commands.ts +++ b/lib/commands.ts @@ -25,8 +25,8 @@ export const callService = ( domain: string, service: string, serviceData?: object, - target?: HassServiceTarget + target?: HassServiceTarget, ) => connection.sendMessagePromise( - messages.callService(domain, service, serviceData, target) + messages.callService(domain, service, serviceData, target), ); diff --git a/lib/config.ts b/lib/config.ts index 567c3a6f..8b785e07 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -12,7 +12,7 @@ type ComponentLoadedEvent = { function processComponentLoaded( state: HassConfig, - event: ComponentLoadedEvent + event: ComponentLoadedEvent, ): Partial | null { if (state === undefined) return null; @@ -26,11 +26,11 @@ const subscribeUpdates = (conn: Connection, store: Store) => Promise.all([ conn.subscribeEvents( store.action(processComponentLoaded), - "component_loaded" + "component_loaded", ), conn.subscribeEvents( () => fetchConfig(conn).then((config) => store.setState(config, true)), - "core_config_updated" + "core_config_updated", ), ]).then((unsubs) => () => unsubs.forEach((unsub) => unsub())); @@ -39,7 +39,7 @@ export const configColl = (conn: Connection) => export const subscribeConfig = ( conn: Connection, - onChange: (state: HassConfig) => void + onChange: (state: HassConfig) => void, ): UnsubscribeFunc => configColl(conn).subscribe(onChange); export const STATE_NOT_RUNNING = "NOT_RUNNING"; diff --git a/lib/connection.ts b/lib/connection.ts index bf2a71f8..b73bea73 100644 --- a/lib/connection.ts +++ b/lib/connection.ts @@ -18,7 +18,7 @@ export type ConnectionOptions = { export type ConnectionEventListener = ( conn: Connection, - eventData?: any + eventData?: any, ) => void; type Events = "ready" | "disconnected" | "reconnect-error"; @@ -183,7 +183,7 @@ export class Connection { fireEvent(eventType: Events, eventData?: any) { (this.eventListeners.get(eventType) || []).forEach((callback) => - callback(this, eventData) + callback(this, eventData), ); } @@ -234,7 +234,7 @@ export class Connection { */ async subscribeEvents( callback: (ev: EventType) => void, - eventType?: string + eventType?: string, ): Promise { return this.subscribeMessage(callback, messages.subscribeEvents(eventType)); } @@ -301,7 +301,7 @@ export class Connection { async subscribeMessage( callback: (result: Result) => void, subscribeMessage: MessageBase, - options?: { resubscribe?: boolean } + options?: { resubscribe?: boolean }, ): Promise { if (this._queuedMessages) { await new Promise((resolve, reject) => { @@ -329,7 +329,7 @@ export class Connection { // No need to unsubscribe if we're disconnected if (this.connected) { await this.sendMessagePromise( - messages.unsubscribeEvents(commandId) + messages.unsubscribeEvents(commandId), ); } this.commands.delete(commandId); @@ -350,7 +350,7 @@ export class Connection { private _handleMessage = (event: MessageEvent) => { let messageGroup: WebSocketResponse | WebSocketResponse[] = JSON.parse( - event.data + event.data, ); if (!Array.isArray(messageGroup)) { @@ -368,11 +368,11 @@ export class Connection { case "event": if (info) { (info as SubscribeEventCommmandInFlight).callback( - message.event + message.event, ); } else { console.warn( - `Received event for unknown subscription ${message.id}. Unsubscribing.` + `Received event for unknown subscription ${message.id}. Unsubscribing.`, ); this.sendMessagePromise(messages.unsubscribeEvents(message.id)); } @@ -440,33 +440,36 @@ export class Connection { const options = { ...this.options, setupRetry: 0 }; const reconnect = (tries: number) => { - setTimeout(async () => { - if (this.closeRequested) { - return; - } - if (DEBUG) { - console.log("Trying to reconnect"); - } - try { - const socket = await options.createSocket(options); - this._setSocket(socket); - } catch (err) { - if (this._queuedMessages) { - const queuedMessages = this._queuedMessages; - this._queuedMessages = undefined; - for (const msg of queuedMessages) { - if (msg.reject) { - msg.reject(ERR_CONNECTION_LOST); + setTimeout( + async () => { + if (this.closeRequested) { + return; + } + if (DEBUG) { + console.log("Trying to reconnect"); + } + try { + const socket = await options.createSocket(options); + this._setSocket(socket); + } catch (err) { + if (this._queuedMessages) { + const queuedMessages = this._queuedMessages; + this._queuedMessages = undefined; + for (const msg of queuedMessages) { + if (msg.reject) { + msg.reject(ERR_CONNECTION_LOST); + } } } + if (err === ERR_INVALID_AUTH) { + this.fireEvent("reconnect-error", err); + } else { + reconnect(tries + 1); + } } - if (err === ERR_INVALID_AUTH) { - this.fireEvent("reconnect-error", err); - } else { - reconnect(tries + 1); - } - } - }, Math.min(tries, 5) * 1000); + }, + Math.min(tries, 5) * 1000, + ); }; if (this.suspendReconnectPromise) { diff --git a/lib/entities.ts b/lib/entities.ts index 26f872ff..2420e399 100644 --- a/lib/entities.ts +++ b/lib/entities.ts @@ -103,7 +103,7 @@ function processEvent(store: Store, updates: StatesUpdates) { } if (toAdd.lc) { entityState.last_updated = entityState.last_changed = new Date( - toAdd.lc * 1000 + toAdd.lc * 1000, ).toISOString(); } else if (toAdd.lu) { entityState.last_updated = new Date(toAdd.lu * 1000).toISOString(); @@ -134,7 +134,7 @@ const subscribeUpdates = (conn: Connection, store: Store) => function legacyProcessEvent( store: Store, - event: StateChangedEvent + event: StateChangedEvent, ) { const state = store.state; if (state === undefined) return; @@ -162,7 +162,7 @@ async function legacyFetchEntities(conn: Connection): Promise { const legacySubscribeUpdates = (conn: Connection, store: Store) => conn.subscribeEvents( (ev) => legacyProcessEvent(store, ev as StateChangedEvent), - "state_changed" + "state_changed", ); export const entitiesColl = (conn: Connection) => @@ -172,5 +172,5 @@ export const entitiesColl = (conn: Connection) => export const subscribeEntities = ( conn: Connection, - onChange: (state: HassEntities) => void + onChange: (state: HassEntities) => void, ): UnsubscribeFunc => entitiesColl(conn).subscribe(onChange); diff --git a/lib/messages.ts b/lib/messages.ts index 2e6c3d06..e9880572 100644 --- a/lib/messages.ts +++ b/lib/messages.ts @@ -51,7 +51,7 @@ export function callService( domain: string, service: string, serviceData?: object, - target?: HassServiceTarget + target?: HassServiceTarget, ) { const message: ServiceCallMessage = { type: "call_service", diff --git a/lib/services.ts b/lib/services.ts index 24397341..207b38e9 100644 --- a/lib/services.ts +++ b/lib/services.ts @@ -22,7 +22,7 @@ type ServiceRemovedEvent = { function processServiceRegistered( conn: Connection, store: Store, - event: ServiceRegisteredEvent + event: ServiceRegisteredEvent, ) { const state = store.state; if (state === undefined) return; @@ -41,7 +41,7 @@ function processServiceRegistered( function processServiceRemoved( state: HassServices, - event: ServiceRemovedEvent + event: ServiceRemovedEvent, ) { if (state === undefined) return null; @@ -61,7 +61,7 @@ function processServiceRemoved( const debouncedFetchServices = debounce( (conn: Connection, store: Store) => fetchServices(conn).then((services) => store.setState(services, true)), - 5000 + 5000, ); const fetchServices = (conn: Connection) => getServices(conn); @@ -70,11 +70,11 @@ const subscribeUpdates = (conn: Connection, store: Store) => conn.subscribeEvents( (ev) => processServiceRegistered(conn, store, ev as ServiceRegisteredEvent), - "service_registered" + "service_registered", ), conn.subscribeEvents( store.action(processServiceRemoved), - "service_removed" + "service_removed", ), ]).then((unsubs) => () => unsubs.forEach((fn) => fn())); @@ -83,5 +83,5 @@ export const servicesColl = (conn: Connection) => export const subscribeServices = ( conn: Connection, - onChange: (state: HassServices) => void + onChange: (state: HassServices) => void, ): UnsubscribeFunc => servicesColl(conn).subscribe(onChange); diff --git a/lib/socket.ts b/lib/socket.ts index 2839dbb6..1f748f33 100644 --- a/lib/socket.ts +++ b/lib/socket.ts @@ -36,7 +36,7 @@ export function createSocket(options: ConnectionOptions): Promise { }, () => { authRefreshTask = undefined; - } + }, ) : undefined; @@ -50,7 +50,7 @@ export function createSocket(options: ConnectionOptions): Promise { function connect( triesLeft: number, promResolve: (socket: HaWebSocket) => void, - promReject: (err: Error) => void + promReject: (err: Error) => void, ) { if (DEBUG) { console.log("[Auth Phase] New connection", url); @@ -137,6 +137,6 @@ export function createSocket(options: ConnectionOptions): Promise { } return new Promise((resolve, reject) => - connect(options.setupRetry, resolve, reject) + connect(options.setupRetry, resolve, reject), ); } diff --git a/lib/util.ts b/lib/util.ts index f500a6f8..69323cdd 100644 --- a/lib/util.ts +++ b/lib/util.ts @@ -20,7 +20,7 @@ export function parseQuery(queryString: string) { export const debounce = unknown>( func: T, wait: number, - immediate = false + immediate = false, ): T => { let timeout: number | undefined; // @ts-ignore @@ -46,7 +46,7 @@ export const atLeastHaVersion = ( version: string, major: number, minor: number, - patch?: number + patch?: number, ): boolean => { const [haMajor, haMinor, haPatch] = version.split(".", 3); diff --git a/package.json b/package.json index 761c9854..ee492d41 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "husky": "^4.2.5", "lint-staged": "^13.0.0", "mocha": "^8.0.1", - "prettier": "^2.0.5", + "prettier": "^3.0.0", "reify": "^0.20.12", "rollup": "^3.5.0", "ts-node": "^9.0.0", diff --git a/test/util.ts b/test/util.ts index 117b98ba..5ad6698b 100644 --- a/test/util.ts +++ b/test/util.ts @@ -21,7 +21,7 @@ export class MockConnection extends Connection { // hass events async subscribeEvents( eventCallback: (ev: EventType) => void, - eventType?: string + eventType?: string, ) { if (!eventType) { throw new Error("mock all events not implemented"); diff --git a/yarn.lock b/yarn.lock index c8b20b0c..bc02ee7f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1113,10 +1113,10 @@ please-upgrade-node@^3.2.0: dependencies: semver-compare "^1.0.0" -prettier@^2.0.5: - version "2.8.8" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" - integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== +prettier@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.0.0.tgz#e7b19f691245a21d618c68bc54dc06122f6105ae" + integrity sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g== randombytes@^2.1.0: version "2.1.0"