yoto-nodejs-client 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.
Files changed (92) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +736 -0
  3. package/bin/auth.d.ts +3 -0
  4. package/bin/auth.d.ts.map +1 -0
  5. package/bin/auth.js +130 -0
  6. package/bin/content.d.ts +3 -0
  7. package/bin/content.d.ts.map +1 -0
  8. package/bin/content.js +117 -0
  9. package/bin/devices.d.ts +3 -0
  10. package/bin/devices.d.ts.map +1 -0
  11. package/bin/devices.js +239 -0
  12. package/bin/groups.d.ts +3 -0
  13. package/bin/groups.d.ts.map +1 -0
  14. package/bin/groups.js +80 -0
  15. package/bin/icons.d.ts +3 -0
  16. package/bin/icons.d.ts.map +1 -0
  17. package/bin/icons.js +100 -0
  18. package/bin/lib/cli-helpers.d.ts +21 -0
  19. package/bin/lib/cli-helpers.d.ts.map +1 -0
  20. package/bin/lib/cli-helpers.js +140 -0
  21. package/bin/lib/token-helpers.d.ts +14 -0
  22. package/bin/lib/token-helpers.d.ts.map +1 -0
  23. package/bin/lib/token-helpers.js +151 -0
  24. package/bin/refresh-token.d.ts +3 -0
  25. package/bin/refresh-token.d.ts.map +1 -0
  26. package/bin/refresh-token.js +168 -0
  27. package/bin/token-info.d.ts +3 -0
  28. package/bin/token-info.d.ts.map +1 -0
  29. package/bin/token-info.js +351 -0
  30. package/index.d.ts +218 -0
  31. package/index.d.ts.map +1 -0
  32. package/index.js +689 -0
  33. package/lib/api-endpoints/auth.d.ts +56 -0
  34. package/lib/api-endpoints/auth.d.ts.map +1 -0
  35. package/lib/api-endpoints/auth.js +209 -0
  36. package/lib/api-endpoints/auth.test.js +27 -0
  37. package/lib/api-endpoints/constants.d.ts +6 -0
  38. package/lib/api-endpoints/constants.d.ts.map +1 -0
  39. package/lib/api-endpoints/constants.js +31 -0
  40. package/lib/api-endpoints/content.d.ts +275 -0
  41. package/lib/api-endpoints/content.d.ts.map +1 -0
  42. package/lib/api-endpoints/content.js +518 -0
  43. package/lib/api-endpoints/content.test.js +250 -0
  44. package/lib/api-endpoints/devices.d.ts +202 -0
  45. package/lib/api-endpoints/devices.d.ts.map +1 -0
  46. package/lib/api-endpoints/devices.js +404 -0
  47. package/lib/api-endpoints/devices.test.js +483 -0
  48. package/lib/api-endpoints/family-library-groups.d.ts +75 -0
  49. package/lib/api-endpoints/family-library-groups.d.ts.map +1 -0
  50. package/lib/api-endpoints/family-library-groups.js +247 -0
  51. package/lib/api-endpoints/family-library-groups.test.js +272 -0
  52. package/lib/api-endpoints/family.d.ts +39 -0
  53. package/lib/api-endpoints/family.d.ts.map +1 -0
  54. package/lib/api-endpoints/family.js +166 -0
  55. package/lib/api-endpoints/family.test.js +184 -0
  56. package/lib/api-endpoints/helpers.d.ts +29 -0
  57. package/lib/api-endpoints/helpers.d.ts.map +1 -0
  58. package/lib/api-endpoints/helpers.js +104 -0
  59. package/lib/api-endpoints/icons.d.ts +62 -0
  60. package/lib/api-endpoints/icons.d.ts.map +1 -0
  61. package/lib/api-endpoints/icons.js +201 -0
  62. package/lib/api-endpoints/icons.test.js +118 -0
  63. package/lib/api-endpoints/media.d.ts +37 -0
  64. package/lib/api-endpoints/media.d.ts.map +1 -0
  65. package/lib/api-endpoints/media.js +155 -0
  66. package/lib/api-endpoints/test-helpers.d.ts +7 -0
  67. package/lib/api-endpoints/test-helpers.d.ts.map +1 -0
  68. package/lib/api-endpoints/test-helpers.js +64 -0
  69. package/lib/mqtt/client.d.ts +124 -0
  70. package/lib/mqtt/client.d.ts.map +1 -0
  71. package/lib/mqtt/client.js +558 -0
  72. package/lib/mqtt/commands.d.ts +69 -0
  73. package/lib/mqtt/commands.d.ts.map +1 -0
  74. package/lib/mqtt/commands.js +238 -0
  75. package/lib/mqtt/factory.d.ts +12 -0
  76. package/lib/mqtt/factory.d.ts.map +1 -0
  77. package/lib/mqtt/factory.js +107 -0
  78. package/lib/mqtt/index.d.ts +5 -0
  79. package/lib/mqtt/index.d.ts.map +1 -0
  80. package/lib/mqtt/index.js +81 -0
  81. package/lib/mqtt/mqtt.test.js +168 -0
  82. package/lib/mqtt/topics.d.ts +34 -0
  83. package/lib/mqtt/topics.d.ts.map +1 -0
  84. package/lib/mqtt/topics.js +295 -0
  85. package/lib/pkg.cjs +3 -0
  86. package/lib/pkg.d.cts +70 -0
  87. package/lib/pkg.d.cts.map +1 -0
  88. package/lib/token.d.ts +29 -0
  89. package/lib/token.d.ts.map +1 -0
  90. package/lib/token.js +240 -0
  91. package/package.json +91 -0
  92. package/yoto.png +0 -0
@@ -0,0 +1,351 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * @import {ArgscloptsParseArgsOptionsConfig} from 'argsclopts'
5
+ */
6
+
7
+ import { printHelpText } from 'argsclopts'
8
+ import { parseArgs } from 'node:util'
9
+ import { YotoClient } from '../index.js'
10
+ import { pkg } from '../lib/pkg.cjs'
11
+ import { DEFAULT_CLIENT_ID } from '../lib/api-endpoints/constants.js'
12
+ import { decodeJwt, formatTimestamp, checkExpiration, saveTokensToEnv } from './lib/token-helpers.js'
13
+ import {
14
+ getCommonOptions,
15
+ loadEnvFile,
16
+ printHeader
17
+ } from './lib/cli-helpers.js'
18
+
19
+ /** @type {ArgscloptsParseArgsOptionsConfig} */
20
+ const options = {
21
+ ...getCommonOptions(),
22
+ 'access-token': {
23
+ type: 'string',
24
+ short: 'a',
25
+ help: 'Access token to inspect (or set YOTO_ACCESS_TOKEN env var)'
26
+ },
27
+ 'refresh-token': {
28
+ type: 'string',
29
+ short: 'r',
30
+ help: 'Refresh token to inspect (or set YOTO_REFRESH_TOKEN env var)'
31
+ },
32
+ introspect: {
33
+ type: 'boolean',
34
+ short: 'i',
35
+ help: 'Attempt to introspect token with authorization server'
36
+ }
37
+ }
38
+
39
+ const args = parseArgs({ options, strict: false })
40
+
41
+ if (args.values['help']) {
42
+ await printHelpText({
43
+ options,
44
+ name: 'yoto-token-info',
45
+ version: pkg.version,
46
+ exampleFn: ({ name }) => ` Display information about Yoto OAuth tokens\n\n Examples:\n ${name}\n ${name} --access-token eyJhbGc...\n ${name} --env-file .env.local\n`
47
+ })
48
+ process.exit(0)
49
+ }
50
+
51
+ // Load .env file if specified or use default
52
+ const envFile = loadEnvFile(args.values['env-file'] ? String(args.values['env-file']) : undefined)
53
+ const outputFile = envFile // Use same file for output
54
+
55
+ // Get tokens from args or env
56
+ const accessToken = String(args.values['access-token'] || process.env['YOTO_ACCESS_TOKEN'] || '')
57
+ const refreshToken = String(args.values['refresh-token'] || process.env['YOTO_REFRESH_TOKEN'] || '')
58
+ const clientId = String(args.values['client-id'] || process.env['YOTO_CLIENT_ID'] || DEFAULT_CLIENT_ID)
59
+ const shouldIntrospect = Boolean(args.values['introspect'])
60
+
61
+ if (!accessToken || !refreshToken) {
62
+ console.error('❌ Both access token and refresh token are required')
63
+ console.error('Provide tokens via:')
64
+ console.error(' - Command line flags: --access-token and --refresh-token')
65
+ console.error(' - Environment variables: YOTO_ACCESS_TOKEN and YOTO_REFRESH_TOKEN')
66
+ console.error(' - .env file (loaded automatically or specify with --env-file)')
67
+ console.error('\n💡 Tip: Run yoto-auth to get both tokens')
68
+ process.exit(1)
69
+ }
70
+
71
+ /**
72
+ * Introspect token with authorization server
73
+ * @param {string} token
74
+ * @param {string} clientId
75
+ * @returns {Promise<any>}
76
+ */
77
+ async function introspectToken (token, clientId) {
78
+ const introspectionUrl = 'https://login.yotoplay.com/oauth/introspect'
79
+
80
+ try {
81
+ const response = await fetch(introspectionUrl, {
82
+ method: 'POST',
83
+ headers: {
84
+ 'Content-Type': 'application/x-www-form-urlencoded'
85
+ },
86
+ body: new URLSearchParams({
87
+ token,
88
+ client_id: clientId
89
+ })
90
+ })
91
+
92
+ if (response.status === 404) {
93
+ return { error: 'not_supported', message: 'Token introspection endpoint not found (404)' }
94
+ }
95
+
96
+ if (response.status === 401) {
97
+ return {
98
+ error: 'authentication_required',
99
+ message: 'Endpoint requires client authentication. This is typical for introspection endpoints - they require confidential clients with credentials (client secret or private key). Public clients cannot use this endpoint.'
100
+ }
101
+ }
102
+
103
+ if (!response.ok) {
104
+ const errorText = await response.text()
105
+ return { error: 'request_failed', message: `Request failed: ${response.status} ${errorText}` }
106
+ }
107
+
108
+ return await response.json()
109
+ } catch (err) {
110
+ const error = /** @type {any} */ (err)
111
+ return { error: 'network_error', message: error.message }
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Display token information
117
+ * @param {string} tokenType
118
+ * @param {string} token
119
+ * @param {string} clientId
120
+ * @param {boolean} shouldIntrospect
121
+ */
122
+ async function displayTokenInfo (tokenType, token, clientId, shouldIntrospect) {
123
+ console.log(`\n${'='.repeat(60)}`)
124
+ console.log(`${tokenType.toUpperCase()} TOKEN`)
125
+ console.log('='.repeat(60))
126
+
127
+ // Check if token is a JWT (has three parts separated by dots)
128
+ const parts = token.split('.')
129
+ if (parts.length !== 3) {
130
+ // Not a JWT - probably an opaque token (like refresh tokens)
131
+ console.log('\n🔤 Token Type: Opaque Token (not a JWT)')
132
+ console.log('\n📝 Information:')
133
+ console.log(' This token is not a JWT and cannot be decoded.')
134
+ console.log(' It is likely an opaque refresh token that can only')
135
+ console.log(' be validated by the authorization server.')
136
+ console.log('\n🔤 Token Preview:')
137
+ if (token.length > 40) {
138
+ console.log(` ${token.substring(0, 20)}...${token.substring(token.length - 20)}`)
139
+ } else {
140
+ console.log(` ${token}`)
141
+ }
142
+ console.log(` Length: ${token.length} characters`)
143
+ return
144
+ }
145
+
146
+ try {
147
+ const decoded = decodeJwt(token)
148
+
149
+ console.log('\n📋 Token Type: JWT')
150
+
151
+ // Expiration
152
+ if (decoded.exp) {
153
+ console.log('\n⏰ Expiration:')
154
+ console.log(` Expires: ${formatTimestamp(decoded.exp)}`)
155
+ const expCheck = checkExpiration(decoded.exp)
156
+ const statusIcon = expCheck.expired ? '❌' : '✅'
157
+ console.log(` Status: ${statusIcon} ${expCheck.message}`)
158
+ }
159
+
160
+ // Issued at
161
+ if (decoded.iat) {
162
+ console.log(` Issued: ${formatTimestamp(decoded.iat)}`)
163
+ const age = Math.floor(Date.now() / 1000) - decoded.iat
164
+ const ageMinutes = Math.floor(age / 60)
165
+ const ageHours = Math.floor(ageMinutes / 60)
166
+ if (ageHours > 0) {
167
+ console.log(` Age: ${ageHours} hour(s) ${ageMinutes % 60} minute(s)`)
168
+ } else {
169
+ console.log(` Age: ${ageMinutes} minute(s)`)
170
+ }
171
+ }
172
+
173
+ // Subject and audience
174
+ console.log('\n👤 Claims:')
175
+ if (decoded.sub) console.log(` Subject: ${decoded.sub}`)
176
+ if (decoded.aud) {
177
+ if (Array.isArray(decoded.aud)) {
178
+ console.log(' Audience:')
179
+ decoded.aud.forEach((/** @type {any} */ aud) => console.log(` - ${aud}`))
180
+ } else {
181
+ console.log(` Audience: ${decoded.aud}`)
182
+ }
183
+ }
184
+ if (decoded.iss) console.log(` Issuer: ${decoded.iss}`)
185
+
186
+ // Client ID verification
187
+ if (decoded.azp || decoded.client_id) {
188
+ const tokenClientId = decoded.azp || decoded.client_id
189
+ console.log(` Client ID: ${tokenClientId}`)
190
+ if (clientId) {
191
+ if (tokenClientId === clientId) {
192
+ console.log(' ✅ Matches provided client ID')
193
+ } else {
194
+ console.log(` ⚠️ Does NOT match provided client ID (${clientId})`)
195
+ }
196
+ }
197
+ }
198
+
199
+ // Scopes
200
+ if (decoded.scope) {
201
+ console.log('\n🔐 Scopes:')
202
+ const scopes = typeof decoded.scope === 'string' ? decoded.scope.split(' ') : decoded.scope
203
+ if (Array.isArray(scopes)) {
204
+ scopes.forEach(scope => console.log(` - ${scope}`))
205
+ } else {
206
+ console.log(` ${scopes}`)
207
+ }
208
+ }
209
+
210
+ // Permissions
211
+ if (decoded.permissions && Array.isArray(decoded.permissions)) {
212
+ console.log('\n🔑 Permissions:')
213
+ decoded.permissions.forEach((/** @type {any} */ perm) => console.log(` - ${perm}`))
214
+ }
215
+
216
+ // Other claims
217
+ const standardClaims = new Set(['exp', 'iat', 'nbf', 'sub', 'aud', 'iss', 'azp', 'client_id', 'scope', 'permissions', 'alg', 'typ', 'kid'])
218
+ const otherClaims = Object.keys(decoded).filter(key => !standardClaims.has(key))
219
+
220
+ if (otherClaims.length > 0) {
221
+ console.log('\n📦 Other Claims:')
222
+ otherClaims.forEach(key => {
223
+ const value = decoded[key]
224
+ if (typeof value === 'object') {
225
+ console.log(` ${key}: ${JSON.stringify(value)}`)
226
+ } else {
227
+ console.log(` ${key}: ${value}`)
228
+ }
229
+ })
230
+ }
231
+
232
+ // Raw token (first/last 20 chars)
233
+ console.log('\n🔤 Token Preview:')
234
+ if (token.length > 40) {
235
+ console.log(` ${token.substring(0, 20)}...${token.substring(token.length - 20)}`)
236
+ } else {
237
+ console.log(` ${token}`)
238
+ }
239
+ console.log(` Length: ${token.length} characters`)
240
+ } catch (err) {
241
+ const error = /** @type {any} */ (err)
242
+ console.error(`\n❌ Error decoding ${tokenType} token:`)
243
+ console.error(` ${error.message}`)
244
+ console.error('\n💡 Tip: If this is a refresh token, it may be an opaque token')
245
+ console.error(' that cannot be decoded. This is normal for some OAuth2 implementations.')
246
+ }
247
+
248
+ // Introspection
249
+ if (shouldIntrospect) {
250
+ console.log('\n🔍 Token Introspection:')
251
+ console.log(' Querying authorization server...')
252
+
253
+ const introspectionResult = await introspectToken(token, clientId)
254
+
255
+ if (introspectionResult.error) {
256
+ if (introspectionResult.error === 'authentication_required') {
257
+ console.log(` ⚠️ ${introspectionResult.message}`)
258
+ } else {
259
+ console.log(` ❌ ${introspectionResult.message}`)
260
+ }
261
+ } else if (introspectionResult.active === false) {
262
+ console.log(' ❌ Token is INACTIVE')
263
+ } else if (introspectionResult.active === true) {
264
+ console.log(' ✅ Token is ACTIVE')
265
+ if (introspectionResult.scope) {
266
+ console.log(` Scope: ${introspectionResult.scope}`)
267
+ }
268
+ if (introspectionResult.client_id) {
269
+ console.log(` Client ID: ${introspectionResult.client_id}`)
270
+ }
271
+ if (introspectionResult.username) {
272
+ console.log(` Username: ${introspectionResult.username}`)
273
+ }
274
+ if (introspectionResult.exp) {
275
+ console.log(` Expires: ${formatTimestamp(introspectionResult.exp)}`)
276
+ }
277
+ if (introspectionResult.iat) {
278
+ console.log(` Issued: ${formatTimestamp(introspectionResult.iat)}`)
279
+ }
280
+ } else {
281
+ console.log(' ⚠️ Unexpected response:')
282
+ console.log(` ${JSON.stringify(introspectionResult, null, 2)}`)
283
+ }
284
+ }
285
+ }
286
+
287
+ printHeader('Yoto Token Information')
288
+
289
+ // Create YotoClient to show token status
290
+ let client
291
+ try {
292
+ console.log('\n📊 Creating YotoClient instance...')
293
+ client = new YotoClient({
294
+ clientId,
295
+ refreshToken,
296
+ accessToken,
297
+ onTokenRefresh: async (tokens) => {
298
+ // Save tokens if they refresh during inspection
299
+ console.log('\n⚠️ Token was refreshed during inspection! Saving...')
300
+ await saveTokensToEnv(outputFile, {
301
+ access_token: tokens.accessToken,
302
+ refresh_token: tokens.refreshToken,
303
+ token_type: 'Bearer',
304
+ expires_in: tokens.expiresAt - Math.floor(Date.now() / 1000)
305
+ }, tokens.clientId)
306
+ console.log(`✅ Updated tokens saved to ${outputFile}`)
307
+ },
308
+ onRefreshStart: () => {
309
+ console.log('\n🔄 Token refresh triggered during inspection...')
310
+ },
311
+ onRefreshError: (error) => {
312
+ console.warn('\n⚠️ Token refresh failed:', error.message)
313
+ },
314
+ onInvalid: (error) => {
315
+ console.error('\n❌ Refresh token is invalid:', error.message)
316
+ }
317
+ })
318
+
319
+ console.log('✅ YotoClient created successfully')
320
+ console.log('\n🔍 Token Status from RefreshableToken:')
321
+ console.log(` Valid: ${client.token.isValid() ? '✅ Yes' : '❌ No'}`)
322
+ console.log(` Expires At: ${formatTimestamp(client.token.getExpiresAt())}`)
323
+
324
+ const timeRemaining = client.token.getTimeRemaining()
325
+ if (timeRemaining > 0) {
326
+ const minutes = Math.floor(timeRemaining / 60)
327
+ const hours = Math.floor(minutes / 60)
328
+ if (hours > 0) {
329
+ console.log(` Time Remaining: ${hours} hour(s) ${minutes % 60} minute(s)`)
330
+ } else {
331
+ console.log(` Time Remaining: ${minutes} minute(s)`)
332
+ }
333
+ } else {
334
+ console.log(` Time Remaining: Expired ${Math.abs(timeRemaining)} seconds ago`)
335
+ }
336
+ } catch (err) {
337
+ const error = /** @type {Error} */ (err)
338
+ console.log(`⚠️ Could not create YotoClient: ${error.message}`)
339
+ }
340
+
341
+ // Display access token info
342
+ if (accessToken) {
343
+ await displayTokenInfo('access', accessToken, clientId, shouldIntrospect)
344
+ }
345
+
346
+ // Display refresh token info
347
+ await displayTokenInfo('refresh', refreshToken, clientId, shouldIntrospect)
348
+
349
+ console.log('\n' + '='.repeat(60))
350
+ console.log('✨ Token inspection complete')
351
+ console.log('='.repeat(60) + '\n')
package/index.d.ts ADDED
@@ -0,0 +1,218 @@
1
+ export class YotoClient {
2
+ static getAuthorizeUrl(params: {
3
+ clientId: string;
4
+ redirectUri: string;
5
+ responseType: "code" | "token" | "id_token" | "code token" | "code id_token" | "token id_token" | "code token id_token";
6
+ state: string;
7
+ audience?: string | undefined;
8
+ scope?: string | undefined;
9
+ nonce?: string | undefined;
10
+ prompt?: "none" | "login" | "consent" | "select_account" | undefined;
11
+ maxAge?: number | undefined;
12
+ codeChallenge?: string | undefined;
13
+ codeChallengeMethod?: "S256" | "plain" | undefined;
14
+ }): string;
15
+ static exchangeToken(params: {
16
+ grantType: "authorization_code" | "refresh_token" | "client_credentials" | "urn:ietf:params:oauth:grant-type:device_code";
17
+ code?: string | undefined;
18
+ redirectUri?: string | undefined;
19
+ refreshToken?: string | undefined;
20
+ clientId?: string | undefined;
21
+ clientSecret?: string | undefined;
22
+ scope?: string | undefined;
23
+ codeVerifier?: string | undefined;
24
+ deviceCode?: string | undefined;
25
+ audience?: string | undefined;
26
+ }): Promise<Auth.YotoTokenResponse>;
27
+ static requestDeviceCode(params: {
28
+ clientId: string;
29
+ scope?: string | undefined;
30
+ audience?: string | undefined;
31
+ }): Promise<Auth.YotoDeviceCodeResponse>;
32
+ constructor({ clientId, refreshToken, accessToken, onTokenRefresh, bufferSeconds, onRefreshStart, onRefreshError, onInvalid, userAgent, defaultRequestOptions }: YotoClientConstructorOptions);
33
+ get token(): RefreshableToken;
34
+ getContent({ cardId, timezone, signingType, playable, requestOptions }: {
35
+ cardId: string;
36
+ timezone?: string | undefined;
37
+ signingType?: "full" | "pre" | undefined;
38
+ playable?: boolean | undefined;
39
+ requestOptions?: ({
40
+ dispatcher?: import("undici").Dispatcher;
41
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
42
+ }): Promise<Content.YotoContentResponse>;
43
+ getUserMyoContent({ showDeleted, requestOptions }?: {
44
+ showDeleted?: boolean | undefined;
45
+ requestOptions?: ({
46
+ dispatcher?: import("undici").Dispatcher;
47
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
48
+ }): Promise<Content.YotoMyoContentResponse>;
49
+ createOrUpdateContent({ content, requestOptions }: {
50
+ content: Content.YotoCreateOrUpdateContentRequest;
51
+ requestOptions?: ({
52
+ dispatcher?: import("undici").Dispatcher;
53
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
54
+ }): Promise<Content.YotoCreateOrUpdateContentResponse>;
55
+ deleteContent({ cardId, requestOptions }: {
56
+ cardId: string;
57
+ requestOptions?: ({
58
+ dispatcher?: import("undici").Dispatcher;
59
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
60
+ }): Promise<Content.YotoDeleteContentResponse>;
61
+ getDevices({ requestOptions }?: {
62
+ requestOptions?: ({
63
+ dispatcher?: import("undici").Dispatcher;
64
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
65
+ }): Promise<Devices.YotoDevicesResponse>;
66
+ getDeviceStatus({ deviceId, requestOptions }: {
67
+ deviceId: string;
68
+ requestOptions?: ({
69
+ dispatcher?: import("undici").Dispatcher;
70
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
71
+ }): Promise<Devices.YotoDeviceStatusResponse>;
72
+ getDeviceConfig({ deviceId, requestOptions }: {
73
+ deviceId: string;
74
+ requestOptions?: ({
75
+ dispatcher?: import("undici").Dispatcher;
76
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
77
+ }): Promise<Devices.YotoDeviceConfigResponse>;
78
+ updateDeviceConfig({ deviceId, configUpdate, requestOptions }: {
79
+ deviceId: string;
80
+ configUpdate: Devices.YotoUpdateDeviceConfigRequest;
81
+ requestOptions?: ({
82
+ dispatcher?: import("undici").Dispatcher;
83
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
84
+ }): Promise<Devices.YotoUpdateDeviceConfigResponse>;
85
+ updateDeviceShortcuts({ deviceId, shortcutsUpdate, requestOptions }: {
86
+ deviceId: string;
87
+ shortcutsUpdate: Devices.YotoUpdateShortcutsRequest;
88
+ requestOptions?: ({
89
+ dispatcher?: import("undici").Dispatcher;
90
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
91
+ }): Promise<Devices.YotoUpdateShortcutsResponse>;
92
+ sendDeviceCommand({ deviceId, command, requestOptions }: {
93
+ deviceId: string;
94
+ command: Devices.YotoDeviceCommand;
95
+ requestOptions?: ({
96
+ dispatcher?: import("undici").Dispatcher;
97
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
98
+ }): Promise<Devices.YotoDeviceCommandResponse>;
99
+ getGroups({ requestOptions }?: {
100
+ requestOptions?: ({
101
+ dispatcher?: import("undici").Dispatcher;
102
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
103
+ }): Promise<FamilyLibraryGroups.YotoGroup[]>;
104
+ createGroup({ group, requestOptions }: {
105
+ group: FamilyLibraryGroups.YotoCreateGroupRequest;
106
+ requestOptions?: ({
107
+ dispatcher?: import("undici").Dispatcher;
108
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
109
+ }): Promise<FamilyLibraryGroups.YotoGroup>;
110
+ getGroup({ groupId, requestOptions }: {
111
+ groupId: string;
112
+ requestOptions?: ({
113
+ dispatcher?: import("undici").Dispatcher;
114
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
115
+ }): Promise<FamilyLibraryGroups.YotoGroup>;
116
+ updateGroup({ groupId, group, requestOptions }: {
117
+ groupId: string;
118
+ group: FamilyLibraryGroups.YotoUpdateGroupRequest;
119
+ requestOptions?: ({
120
+ dispatcher?: import("undici").Dispatcher;
121
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
122
+ }): Promise<FamilyLibraryGroups.YotoGroup>;
123
+ deleteGroup({ groupId, requestOptions }: {
124
+ groupId: string;
125
+ requestOptions?: ({
126
+ dispatcher?: import("undici").Dispatcher;
127
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
128
+ }): Promise<FamilyLibraryGroups.YotoDeleteGroupResponse>;
129
+ getFamilyImages({ requestOptions }?: {
130
+ requestOptions?: ({
131
+ dispatcher?: import("undici").Dispatcher;
132
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
133
+ }): Promise<Family.YotoFamilyImagesResponse>;
134
+ getAFamilyImage({ imageId, size, requestOptions }: {
135
+ imageId: string;
136
+ size: "640x480" | "320x320";
137
+ requestOptions?: ({
138
+ dispatcher?: import("undici").Dispatcher;
139
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
140
+ }): Promise<Family.YotoFamilyImageResponse>;
141
+ uploadAFamilyImage({ imageData, requestOptions }: {
142
+ imageData: Buffer;
143
+ requestOptions?: ({
144
+ dispatcher?: import("undici").Dispatcher;
145
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
146
+ }): Promise<Family.YotoUploadFamilyImageResponse>;
147
+ getPublicIcons({ requestOptions }?: {
148
+ requestOptions?: ({
149
+ dispatcher?: import("undici").Dispatcher;
150
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
151
+ }): Promise<Icons.YotoPublicIconsResponse>;
152
+ getUserIcons({ requestOptions }?: {
153
+ requestOptions?: ({
154
+ dispatcher?: import("undici").Dispatcher;
155
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
156
+ }): Promise<Icons.YotoUserIconsResponse>;
157
+ uploadIcon({ imageData, autoConvert, filename, requestOptions }: {
158
+ imageData: Buffer;
159
+ autoConvert?: boolean | undefined;
160
+ filename?: string | undefined;
161
+ requestOptions?: ({
162
+ dispatcher?: import("undici").Dispatcher;
163
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
164
+ }): Promise<Icons.YotoUploadIconResponse>;
165
+ getAudioUploadUrl({ sha256, filename, requestOptions }: {
166
+ sha256: string;
167
+ filename?: string | undefined;
168
+ requestOptions?: ({
169
+ dispatcher?: import("undici").Dispatcher;
170
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
171
+ }): Promise<Media.YotoAudioUploadUrlResponse>;
172
+ uploadCoverImage({ imageData, imageUrl, autoConvert, coverType, filename, requestOptions }: {
173
+ imageData?: Buffer<ArrayBufferLike> | undefined;
174
+ imageUrl?: string | undefined;
175
+ autoConvert?: boolean | undefined;
176
+ coverType?: Media.YotoCoverType | undefined;
177
+ filename?: string | undefined;
178
+ requestOptions?: ({
179
+ dispatcher?: import("undici").Dispatcher;
180
+ } & Omit<import("undici").Dispatcher.RequestOptions<unknown>, "origin" | "path" | "method"> & Partial<Pick<import("undici").Dispatcher.RequestOptions<null>, "method">>) | undefined;
181
+ }): Promise<Media.YotoUploadCoverImageResponse>;
182
+ createMqttClient({ deviceId, options }: {
183
+ deviceId: string;
184
+ options?: {
185
+ autoSubscribe?: boolean | undefined;
186
+ } | undefined;
187
+ }): Promise<YotoMqttClient>;
188
+ #private;
189
+ }
190
+ export type RefreshSuccessEvent = {
191
+ clientId: string;
192
+ accessToken: string;
193
+ refreshToken: string;
194
+ expiresAt: number;
195
+ };
196
+ export type YotoClientConstructorOptions = {
197
+ clientId: string;
198
+ refreshToken: string;
199
+ accessToken: string;
200
+ onTokenRefresh: (event: RefreshSuccessEvent) => void | Promise<void>;
201
+ bufferSeconds?: number;
202
+ onRefreshStart?: () => void | Promise<void>;
203
+ onRefreshError?: (error: Error) => void | Promise<void>;
204
+ onInvalid?: (error: Error) => void | Promise<void>;
205
+ userAgent?: string;
206
+ defaultRequestOptions?: RequestOptions;
207
+ };
208
+ import { RefreshableToken } from './lib/token.js';
209
+ import * as Content from './lib/api-endpoints/content.js';
210
+ import * as Devices from './lib/api-endpoints/devices.js';
211
+ import * as FamilyLibraryGroups from './lib/api-endpoints/family-library-groups.js';
212
+ import * as Family from './lib/api-endpoints/family.js';
213
+ import * as Icons from './lib/api-endpoints/icons.js';
214
+ import * as Media from './lib/api-endpoints/media.js';
215
+ import type { YotoMqttClient } from './lib/mqtt/client.js';
216
+ import * as Auth from './lib/api-endpoints/auth.js';
217
+ import type { RequestOptions } from './lib/api-endpoints/helpers.js';
218
+ //# sourceMappingURL=index.d.ts.map
package/index.d.ts.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.js"],"names":[],"mappings":"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"}