@mdjhnson/homebridge-yoto 0.1.5 → 0.1.6

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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  <img src="https://github.com/homebridge/branding/raw/latest/logos/homebridge-wordmark-logo-vertical.png" width="150">
4
4
 
5
- <img src="https://raw.githubusercontent.com/mdjhnson/homebridge-yoto/master/logo.png" width="150">
5
+ <img src="https://raw.githubusercontent.com/mdjhnson/homebridge-yoto/master/homebridge-ui/public/logo.png" width="100">
6
6
 
7
7
  </p>
8
8
 
@@ -8,11 +8,16 @@
8
8
  "schema": {
9
9
  "type": "object",
10
10
  "properties": {
11
+ "name": {
12
+ "title": "Name",
13
+ "type": "string",
14
+ "default": "Yoto",
15
+ "description": "Name used for this plugin in the Homebridge log."
16
+ },
11
17
  "clientId": {
12
18
  "title": "OAuth Client ID",
13
19
  "type": "string",
14
20
  "default": "tpc_ot5BY24FLyZoCX9MnykipB",
15
- "required": false,
16
21
  "description": "OAuth client ID for Yoto API authentication. The default works for most users. Only change if you've created your own OAuth app at yoto.dev.",
17
22
  "x-schema-form": {
18
23
  "hidden": false
@@ -21,7 +26,6 @@
21
26
  "accessToken": {
22
27
  "title": "Access Token",
23
28
  "type": "string",
24
- "required": false,
25
29
  "description": "Automatically managed by the authentication flow. Do not edit manually.",
26
30
  "x-schema-form": {
27
31
  "type": "password"
@@ -30,7 +34,6 @@
30
34
  "refreshToken": {
31
35
  "title": "Refresh Token",
32
36
  "type": "string",
33
- "required": false,
34
37
  "description": "Automatically managed by the authentication flow. Do not edit manually.",
35
38
  "x-schema-form": {
36
39
  "type": "password"
@@ -39,7 +42,6 @@
39
42
  "tokenExpiresAt": {
40
43
  "title": "Token Expiration",
41
44
  "type": "number",
42
- "required": false,
43
45
  "description": "Automatically managed by the authentication flow. Do not edit manually.",
44
46
  "x-schema-form": {
45
47
  "hidden": true
@@ -50,7 +52,6 @@
50
52
  "type": "integer",
51
53
  "default": 60000,
52
54
  "minimum": 10000,
53
- "required": false,
54
55
  "description": "How often to poll the Yoto API for device status and config as a fallback to MQTT updates. Defaults to 60000 (1 minute)."
55
56
  },
56
57
  "services": {
@@ -116,13 +117,11 @@
116
117
  "label": {
117
118
  "title": "Label",
118
119
  "type": "string",
119
- "required": true,
120
120
  "description": "Name shown in HomeKit for this card control."
121
121
  },
122
122
  "cardId": {
123
123
  "title": "Card ID",
124
124
  "type": "string",
125
- "required": true,
126
125
  "description": "The Yoto card ID to play."
127
126
  },
128
127
  "playOnAll": {
@@ -131,7 +130,11 @@
131
130
  "default": false,
132
131
  "description": "Create a separate accessory that plays this card on every Yoto."
133
132
  }
134
- }
133
+ },
134
+ "required": [
135
+ "label",
136
+ "cardId"
137
+ ]
135
138
  }
136
139
  },
137
140
  "shortcuts": {
@@ -250,6 +253,7 @@
250
253
  "expandable": true,
251
254
  "expanded": false,
252
255
  "items": [
256
+ "name",
253
257
  "httpPollIntervalMs",
254
258
  {
255
259
  "type": "help",
@@ -16,6 +16,7 @@ const homebridge = window.homebridge
16
16
  /**
17
17
  * @typedef {Object} YotoConfig
18
18
  * @property {string} [platform] - Platform alias (always "Yoto")
19
+ * @property {string} [name] - Name used in the Homebridge log
19
20
  * @property {string} [clientId] - OAuth client ID (only stored when not the default)
20
21
  * @property {string} [refreshToken] - Stored refresh token
21
22
  * @property {string} [accessToken] - Stored access token
@@ -31,6 +32,8 @@ let authorizeUrl = null
31
32
  let pluginConfig = []
32
33
  /** @type {string | null} */
33
34
  let defaultClientId = null
35
+ /** @type {string | null} */
36
+ let defaultName = null
34
37
  /** @type {string[]} */
35
38
  let legacyClientIds = []
36
39
 
@@ -153,14 +156,13 @@ function getErrorMessage (error, fallback) {
153
156
  async function loadAuthConfig () {
154
157
  try {
155
158
  pluginConfig = await homebridge.getPluginConfig()
156
- if (!pluginConfig.length) {
157
- pluginConfig.push({ platform: 'Yoto' })
158
- }
159
159
 
160
160
  /** @type {AuthConfigResponse} */
161
161
  const config = await homebridge.request('/auth/config')
162
162
  defaultClientId = config.defaultClientId
163
+ defaultName = config.defaultName
163
164
  legacyClientIds = config.legacyClientIds
165
+ getPlatformBlock()
164
166
 
165
167
  const redirectUriDisplay = document.getElementById('redirectUriDisplay')
166
168
  if (redirectUriDisplay) redirectUriDisplay.textContent = config.redirectUri
@@ -178,6 +180,18 @@ async function loadAuthConfig () {
178
180
  }
179
181
  }
180
182
 
183
+ /**
184
+ * The plugin's config block, created if missing. Also fills in the name,
185
+ * which blocks saved by older versions don't have.
186
+ * @returns {YotoConfig}
187
+ */
188
+ function getPlatformBlock () {
189
+ if (!pluginConfig[0]) pluginConfig[0] = { platform: 'Yoto' }
190
+ const config = pluginConfig[0]
191
+ if (!config.name && defaultName) config.name = defaultName
192
+ return config
193
+ }
194
+
181
195
  /**
182
196
  * The client ID saved in config, ignoring retired ones
183
197
  * @returns {string | undefined}
@@ -265,8 +279,7 @@ async function finishAuthorization () {
265
279
  response: pasted,
266
280
  })
267
281
 
268
- if (!pluginConfig[0]) pluginConfig[0] = { platform: 'Yoto' }
269
- const config = pluginConfig[0]
282
+ const config = getPlatformBlock()
270
283
  config.refreshToken = result.refreshToken
271
284
  config.accessToken = result.accessToken
272
285
  config.tokenExpiresAt = result.tokenExpiresAt
@@ -306,11 +319,10 @@ async function logout () {
306
319
  try {
307
320
  homebridge.showSpinner()
308
321
 
309
- if (pluginConfig[0]) {
310
- delete pluginConfig[0].refreshToken
311
- delete pluginConfig[0].accessToken
312
- delete pluginConfig[0].tokenExpiresAt
313
- }
322
+ const config = getPlatformBlock()
323
+ delete config.refreshToken
324
+ delete config.accessToken
325
+ delete config.tokenExpiresAt
314
326
 
315
327
  await homebridge.updatePluginConfig(pluginConfig)
316
328
  await homebridge.savePluginConfig()
@@ -2,6 +2,8 @@
2
2
  <script type="module" src="client.js"></script>
3
3
 
4
4
  <div class="card card-body">
5
+ <img src="logo.png" alt="Homebridge Yoto" width="80" height="80" class="d-block mx-auto mb-3" />
6
+
5
7
  <!-- Authentication Status -->
6
8
  <div id="authStatus">
7
9
  <h4>Authentication Status</h4>
Binary file
@@ -11,6 +11,7 @@ import { HomebridgePluginUiServer, RequestError } from '@homebridge/plugin-ui-ut
11
11
  import { YotoClient } from 'yoto-nodejs-client'
12
12
  import {
13
13
  DEFAULT_CLIENT_ID,
14
+ DEFAULT_NAME,
14
15
  LEGACY_CLIENT_IDS,
15
16
  OAUTH_REDIRECT_URI,
16
17
  OAUTH_SCOPES,
@@ -59,6 +60,7 @@ class YotoUiServer extends HomebridgePluginUiServer {
59
60
  * Response from /auth/config endpoint
60
61
  * @typedef {Object} AuthConfigResponse
61
62
  * @property {string} defaultClientId - The default OAuth client ID
63
+ * @property {string} defaultName - The default plugin name, filled into config blocks that have none
62
64
  * @property {string[]} legacyClientIds - Client IDs that no longer support sign-in
63
65
  * @property {string} redirectUri - Redirect URI to register on a custom Yoto app
64
66
  */
@@ -70,6 +72,7 @@ class YotoUiServer extends HomebridgePluginUiServer {
70
72
  async function getAuthConfig () {
71
73
  return {
72
74
  defaultClientId: DEFAULT_CLIENT_ID,
75
+ defaultName: DEFAULT_NAME,
73
76
  legacyClientIds: LEGACY_CLIENT_IDS,
74
77
  redirectUri: OAUTH_REDIRECT_URI,
75
78
  }
package/lib/settings.js CHANGED
@@ -15,6 +15,11 @@ export const PLUGIN_NAME = '@mdjhnson/homebridge-yoto'
15
15
  */
16
16
  export const DEFAULT_CLIENT_ID = configSchema.schema.properties.clientId.default
17
17
 
18
+ /**
19
+ * Default plugin name (shown in the Homebridge log) from config schema
20
+ */
21
+ export const DEFAULT_NAME = configSchema.schema.properties.name.default
22
+
18
23
  /**
19
24
  * OAuth redirect URI registered on the Yoto developer app. Nothing listens here:
20
25
  * the user copies the resulting address back into the plugin settings.
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@mdjhnson/homebridge-yoto",
3
3
  "displayName": "Homebridge Yoto",
4
4
  "description": "Control your Yoto players through Apple HomeKit with real-time MQTT updates",
5
- "version": "0.1.5",
5
+ "version": "0.1.6",
6
6
  "author": "mdjhnson (https://github.com/mdjhnson)",
7
7
  "contributors": [
8
8
  "Bret Comnes <bcomnes@gmail.com> (https://bret.io)"
@@ -22,6 +22,7 @@
22
22
  "devDependencies": {
23
23
  "@types/node": "^25.9.8",
24
24
  "@voxpelli/tsconfig": "^16.2.1",
25
+ "ajv": "^8.20.0",
25
26
  "auto-changelog": "^2.0.0",
26
27
  "c8": "^10.0.0",
27
28
  "eslint": "^9.39.2",