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.
- package/LICENSE +21 -0
- package/README.md +736 -0
- package/bin/auth.d.ts +3 -0
- package/bin/auth.d.ts.map +1 -0
- package/bin/auth.js +130 -0
- package/bin/content.d.ts +3 -0
- package/bin/content.d.ts.map +1 -0
- package/bin/content.js +117 -0
- package/bin/devices.d.ts +3 -0
- package/bin/devices.d.ts.map +1 -0
- package/bin/devices.js +239 -0
- package/bin/groups.d.ts +3 -0
- package/bin/groups.d.ts.map +1 -0
- package/bin/groups.js +80 -0
- package/bin/icons.d.ts +3 -0
- package/bin/icons.d.ts.map +1 -0
- package/bin/icons.js +100 -0
- package/bin/lib/cli-helpers.d.ts +21 -0
- package/bin/lib/cli-helpers.d.ts.map +1 -0
- package/bin/lib/cli-helpers.js +140 -0
- package/bin/lib/token-helpers.d.ts +14 -0
- package/bin/lib/token-helpers.d.ts.map +1 -0
- package/bin/lib/token-helpers.js +151 -0
- package/bin/refresh-token.d.ts +3 -0
- package/bin/refresh-token.d.ts.map +1 -0
- package/bin/refresh-token.js +168 -0
- package/bin/token-info.d.ts +3 -0
- package/bin/token-info.d.ts.map +1 -0
- package/bin/token-info.js +351 -0
- package/index.d.ts +218 -0
- package/index.d.ts.map +1 -0
- package/index.js +689 -0
- package/lib/api-endpoints/auth.d.ts +56 -0
- package/lib/api-endpoints/auth.d.ts.map +1 -0
- package/lib/api-endpoints/auth.js +209 -0
- package/lib/api-endpoints/auth.test.js +27 -0
- package/lib/api-endpoints/constants.d.ts +6 -0
- package/lib/api-endpoints/constants.d.ts.map +1 -0
- package/lib/api-endpoints/constants.js +31 -0
- package/lib/api-endpoints/content.d.ts +275 -0
- package/lib/api-endpoints/content.d.ts.map +1 -0
- package/lib/api-endpoints/content.js +518 -0
- package/lib/api-endpoints/content.test.js +250 -0
- package/lib/api-endpoints/devices.d.ts +202 -0
- package/lib/api-endpoints/devices.d.ts.map +1 -0
- package/lib/api-endpoints/devices.js +404 -0
- package/lib/api-endpoints/devices.test.js +483 -0
- package/lib/api-endpoints/family-library-groups.d.ts +75 -0
- package/lib/api-endpoints/family-library-groups.d.ts.map +1 -0
- package/lib/api-endpoints/family-library-groups.js +247 -0
- package/lib/api-endpoints/family-library-groups.test.js +272 -0
- package/lib/api-endpoints/family.d.ts +39 -0
- package/lib/api-endpoints/family.d.ts.map +1 -0
- package/lib/api-endpoints/family.js +166 -0
- package/lib/api-endpoints/family.test.js +184 -0
- package/lib/api-endpoints/helpers.d.ts +29 -0
- package/lib/api-endpoints/helpers.d.ts.map +1 -0
- package/lib/api-endpoints/helpers.js +104 -0
- package/lib/api-endpoints/icons.d.ts +62 -0
- package/lib/api-endpoints/icons.d.ts.map +1 -0
- package/lib/api-endpoints/icons.js +201 -0
- package/lib/api-endpoints/icons.test.js +118 -0
- package/lib/api-endpoints/media.d.ts +37 -0
- package/lib/api-endpoints/media.d.ts.map +1 -0
- package/lib/api-endpoints/media.js +155 -0
- package/lib/api-endpoints/test-helpers.d.ts +7 -0
- package/lib/api-endpoints/test-helpers.d.ts.map +1 -0
- package/lib/api-endpoints/test-helpers.js +64 -0
- package/lib/mqtt/client.d.ts +124 -0
- package/lib/mqtt/client.d.ts.map +1 -0
- package/lib/mqtt/client.js +558 -0
- package/lib/mqtt/commands.d.ts +69 -0
- package/lib/mqtt/commands.d.ts.map +1 -0
- package/lib/mqtt/commands.js +238 -0
- package/lib/mqtt/factory.d.ts +12 -0
- package/lib/mqtt/factory.d.ts.map +1 -0
- package/lib/mqtt/factory.js +107 -0
- package/lib/mqtt/index.d.ts +5 -0
- package/lib/mqtt/index.d.ts.map +1 -0
- package/lib/mqtt/index.js +81 -0
- package/lib/mqtt/mqtt.test.js +168 -0
- package/lib/mqtt/topics.d.ts +34 -0
- package/lib/mqtt/topics.d.ts.map +1 -0
- package/lib/mqtt/topics.js +295 -0
- package/lib/pkg.cjs +3 -0
- package/lib/pkg.d.cts +70 -0
- package/lib/pkg.d.cts.map +1 -0
- package/lib/token.d.ts +29 -0
- package/lib/token.d.ts.map +1 -0
- package/lib/token.js +240 -0
- package/package.json +91 -0
- package/yoto.png +0 -0
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import { RequestOptions } from './helpers.js'
|
|
3
|
+
*/
|
|
4
|
+
import { request } from 'undici'
|
|
5
|
+
import { defaultAuthHeaders, handleBadResponse, mergeRequestOptions } from './helpers.js'
|
|
6
|
+
import { YOTO_API_URL } from './constants.js'
|
|
7
|
+
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// Content: Content endpoints for managing playlists and cards
|
|
10
|
+
// ============================================================================
|
|
11
|
+
|
|
12
|
+
// Shared types used across multiple content endpoints
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @see https://yoto.dev/reference/card-content-schema/
|
|
16
|
+
* @typedef {'none' | 'stories' | 'music' | 'radio' | 'podcast' | 'sfx' | 'activities' | 'alarms'} YotoCategory
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @see https://yoto.dev/reference/card-content-schema/
|
|
21
|
+
* @typedef {'mp3' | 'aac' | 'opus' | 'ogg'} YotoAudioFormat
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @see https://yoto.dev/reference/card-content-schema/
|
|
26
|
+
* @typedef {'en' | 'en-gb' | 'en-us' | 'fr' | 'fr-fr' | 'es' | 'es-es' | 'es-419' | 'de' | 'it'} YotoLanguage
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @see https://yoto.dev/reference/card-content-schema/
|
|
31
|
+
* @typedef {'new' | 'inprogress' | 'complete' | 'live' | 'archived'} YotoStatusName
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @see https://yoto.dev/reference/card-content-schema/
|
|
36
|
+
* @typedef {'DESC' | 'ASC'} YotoPlaybackDirection
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @see https://yoto.dev/reference/card-content-schema/
|
|
41
|
+
* @typedef {'linear' | 'interactive'} YotoPlaybackType
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @see https://yoto.dev/myo/how-playlists-work/
|
|
46
|
+
* @typedef {Object} YotoTrackDisplay
|
|
47
|
+
* @property {string} icon16x16 - Track icon (16x16px) in format "yoto:#<sha256-hash>"
|
|
48
|
+
*/
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @see https://yoto.dev/myo/how-playlists-work/
|
|
52
|
+
* @typedef {'audio' | 'stream'} YotoTrackType
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @see https://yoto.dev/myo/how-playlists-work/
|
|
57
|
+
* @typedef {'stereo' | 'mono'} YotoChannels
|
|
58
|
+
*/
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* A track represents a single audio file within a chapter.
|
|
62
|
+
* Tracks within a chapter play in sequence.
|
|
63
|
+
* @see https://yoto.dev/myo/how-playlists-work/
|
|
64
|
+
* @see https://yoto.dev/api/getcontent/
|
|
65
|
+
* @see https://yoto.dev/api/getusersmyocontent/
|
|
66
|
+
* @see https://yoto.dev/reference/card-content-schema/
|
|
67
|
+
* @typedef {Object} YotoTrack
|
|
68
|
+
* @property {string} key - Track identifier
|
|
69
|
+
* @property {string} title - Track title
|
|
70
|
+
* @property {string} trackUrl - Track URL in format "yoto:#<sha256-hash>"
|
|
71
|
+
* @property {YotoAudioFormat} format - Audio format
|
|
72
|
+
* @property {YotoTrackType} type - Track type ("audio" or "stream")
|
|
73
|
+
* @property {string} overlayLabel - Display label shown on player
|
|
74
|
+
* @property {number} duration - Track duration in seconds
|
|
75
|
+
* @property {number} fileSize - File size in bytes
|
|
76
|
+
* @property {YotoChannels} channels - Audio channels (stereo or mono)
|
|
77
|
+
* @property {any | null} ambient - Ambient setting for track
|
|
78
|
+
* @property {YotoTrackDisplay} display - Display configuration with icon
|
|
79
|
+
* @property {string | null} [uid] - Optional unique identifier
|
|
80
|
+
* @property {string | null} [overlayLabelOverride] - Optional override for overlay label
|
|
81
|
+
*/
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* @see https://yoto.dev/myo/how-playlists-work/
|
|
85
|
+
* @typedef {Object} YotoChapterDisplay
|
|
86
|
+
* @property {string} icon16x16 - Chapter icon (16x16px) in format "yoto:#<sha256-hash>"
|
|
87
|
+
*/
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* A chapter contains one or more tracks and has its own title and icon.
|
|
91
|
+
* A playlist is made up of one or more chapters.
|
|
92
|
+
* @see https://yoto.dev/myo/how-playlists-work/
|
|
93
|
+
* @see https://yoto.dev/api/getcontent/
|
|
94
|
+
* @see https://yoto.dev/api/getusersmyocontent/
|
|
95
|
+
* @typedef {Object} YotoChapter
|
|
96
|
+
* @property {string} key - Chapter identifier
|
|
97
|
+
* @property {string} title - Chapter title
|
|
98
|
+
* @property {YotoTrack[]} tracks - Array of tracks in this chapter
|
|
99
|
+
* @property {YotoChapterDisplay} display - Display configuration with icon
|
|
100
|
+
* @property {string} overlayLabel - Overlay label shown on player
|
|
101
|
+
* @property {number} duration - Total chapter duration in seconds
|
|
102
|
+
* @property {number} fileSize - Total chapter file size in bytes
|
|
103
|
+
* @property {any | null} availableFrom - Availability date/time
|
|
104
|
+
* @property {any | null} ambient - Ambient setting for chapter
|
|
105
|
+
* @property {string | null} defaultTrackDisplay - Default track display setting
|
|
106
|
+
* @property {string | null} defaultTrackAmbient - Default track ambient setting
|
|
107
|
+
* @property {string | null} [overlayLabelOverride] - Optional override for overlay label
|
|
108
|
+
* @property {number} [startTime] - Chapter start time (for API compatibility)
|
|
109
|
+
*/
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @see https://yoto.dev/api/getcontent/
|
|
113
|
+
* @typedef {Object} YotoEditSettings
|
|
114
|
+
* @property {string} autoOverlayLabels
|
|
115
|
+
* @property {boolean} editKeys
|
|
116
|
+
* @property {boolean} transcodeAudioUploads
|
|
117
|
+
*/
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* @see https://yoto.dev/api/getcontent/
|
|
121
|
+
* @see https://yoto.dev/reference/card-content-schema/
|
|
122
|
+
* @typedef {Object} YotoMetadata
|
|
123
|
+
* @property {YotoCategory} category - Content category
|
|
124
|
+
* @property {Object} cover - Cover image
|
|
125
|
+
* @property {string | null} cover.imageL - Large cover image URL
|
|
126
|
+
* @property {YotoMedia} media - Media information
|
|
127
|
+
* @property {string} [accent] - Accent (e.g., "British")
|
|
128
|
+
* @property {boolean} [addToFamilyLibrary] - Whether to add to family library
|
|
129
|
+
* @property {string} [author] - Author name
|
|
130
|
+
* @property {string} [copyright] - Copyright information
|
|
131
|
+
* @property {string} [description] - Content description
|
|
132
|
+
* @property {string[]} [genre] - Genre tags (e.g., ["Adventure", "Fantasy"])
|
|
133
|
+
* @property {YotoLanguage[]} [languages] - Language codes
|
|
134
|
+
* @property {number} [maxAge] - Maximum recommended age
|
|
135
|
+
* @property {number} [minAge] - Minimum recommended age
|
|
136
|
+
* @property {string[]} [musicType] - Music types (e.g., ["Classical", "Instrumental"])
|
|
137
|
+
* @property {string} [note] - Additional notes
|
|
138
|
+
* @property {string} [order] - Order (e.g., "featured")
|
|
139
|
+
* @property {string} [audioPreviewUrl] - Preview audio URL
|
|
140
|
+
* @property {string} [readBy] - Narrator name
|
|
141
|
+
* @property {boolean} [share] - Whether sharing is enabled
|
|
142
|
+
* @property {YotoStatus} [status] - Content status
|
|
143
|
+
* @property {string[]} [tags] - Content tags
|
|
144
|
+
* @property {string} [feedUrl] - Podcast feed URL
|
|
145
|
+
* @property {number} [numEpisodes] - Number of episodes (for podcasts)
|
|
146
|
+
* @property {YotoPlaybackDirection} [playbackDirection] - Playback direction for podcasts
|
|
147
|
+
*/
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* @see https://yoto.dev/api/getcontent/
|
|
151
|
+
* @see https://yoto.dev/api/getusersmyocontent/
|
|
152
|
+
* @typedef {Object} YotoMedia
|
|
153
|
+
* @property {number} duration
|
|
154
|
+
* @property {number} fileSize
|
|
155
|
+
* @property {boolean} hasStreams
|
|
156
|
+
*/
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* @see https://yoto.dev/api/getusersmyocontent/
|
|
160
|
+
* @see https://yoto.dev/reference/card-content-schema/
|
|
161
|
+
* @typedef {Object} YotoContentConfig
|
|
162
|
+
* @property {string} [autoadvance] - Auto-advance setting
|
|
163
|
+
* @property {boolean} [onlineOnly] - Whether content requires online access
|
|
164
|
+
* @property {YotoShuffle[]} [shuffle] - Shuffle configuration
|
|
165
|
+
* @property {number} [trackNumberOverlayTimeout] - Track number overlay timeout in seconds
|
|
166
|
+
* @property {number} [resumeTimeout] - Resume timeout in seconds
|
|
167
|
+
* @property {boolean} [systemActivity] - System activity setting
|
|
168
|
+
*/
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* @see https://yoto.dev/api/getusersmyocontent/
|
|
172
|
+
* @typedef {Object} YotoShuffle
|
|
173
|
+
* @property {number} end
|
|
174
|
+
* @property {number} limit
|
|
175
|
+
* @property {number} start
|
|
176
|
+
*/
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* @see https://yoto.dev/api/getusersmyocontent/
|
|
180
|
+
* @typedef {Object} YotoContentCover
|
|
181
|
+
* @property {string | null} imageL
|
|
182
|
+
*/
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* @see https://yoto.dev/api/getusersmyocontent/
|
|
186
|
+
* @typedef {Object} YotoMyoEditSettings
|
|
187
|
+
* @property {string} autoOverlayLabels
|
|
188
|
+
* @property {boolean} editKeys
|
|
189
|
+
* @property {YotoPodcastTrackDisplay} [podcastTrackDisplay]
|
|
190
|
+
* @property {string} [podcastType]
|
|
191
|
+
*/
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* @see https://yoto.dev/api/getusersmyocontent/
|
|
195
|
+
* @typedef {Object} YotoPodcastTrackDisplay
|
|
196
|
+
* @property {string} icon16x16
|
|
197
|
+
*/
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* @see https://yoto.dev/api/getusersmyocontent/
|
|
201
|
+
* @see https://yoto.dev/reference/card-content-schema/
|
|
202
|
+
* @typedef {Object} YotoStatus
|
|
203
|
+
* @property {YotoStatusName} name - Status name
|
|
204
|
+
* @property {string} updatedAt - Last update timestamp
|
|
205
|
+
*/
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* @see https://yoto.dev/api/getusersmyocontent/
|
|
209
|
+
* @typedef {Object} YotoSharing
|
|
210
|
+
* @property {string} linkCreatedAt
|
|
211
|
+
* @property {string} linkUrl
|
|
212
|
+
* @property {number} shareCount
|
|
213
|
+
* @property {number} shareLimit
|
|
214
|
+
*/
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* @see https://yoto.dev/api/getusersmyocontent/
|
|
218
|
+
* @typedef {Object} YotoClubAvailability
|
|
219
|
+
* @property {string} store
|
|
220
|
+
*/
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* @see https://yoto.dev/api/getcontent/
|
|
224
|
+
* @typedef {Object} YotoContentResponse
|
|
225
|
+
* @property {YotoCard} card
|
|
226
|
+
*/
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* @see https://yoto.dev/api/getcontent/
|
|
230
|
+
* @see https://yoto.dev/reference/card-content-schema/
|
|
231
|
+
* @typedef {Object} YotoCard
|
|
232
|
+
* @property {string} cardId - Unique card identifier
|
|
233
|
+
* @property {YotoContent} content - Card content and chapters
|
|
234
|
+
* @property {string} createdAt - Creation timestamp
|
|
235
|
+
* @property {string} creatorEmail - Creator email address
|
|
236
|
+
* @property {boolean} deleted - Whether card is deleted
|
|
237
|
+
* @property {YotoMetadata} metadata - Card metadata
|
|
238
|
+
* @property {number} shareLimit - Share limit count
|
|
239
|
+
* @property {string} shareLinkCreatedAt - Share link creation timestamp
|
|
240
|
+
* @property {string} slug - URL-friendly slug
|
|
241
|
+
* @property {string} title - Card title
|
|
242
|
+
* @property {string} updatedAt - Last update timestamp
|
|
243
|
+
* @property {string} userId - Owner user ID
|
|
244
|
+
* @property {string[]} [tags] - Top-level tags
|
|
245
|
+
*/
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* @see https://yoto.dev/api/getcontent/
|
|
249
|
+
* @see https://yoto.dev/reference/card-content-schema/
|
|
250
|
+
* @typedef {Object} YotoContent
|
|
251
|
+
* @property {string} activity - Activity type
|
|
252
|
+
* @property {YotoChapter[]} chapters - Array of chapters
|
|
253
|
+
* @property {YotoContentConfig} config - Content configuration
|
|
254
|
+
* @property {YotoEditSettings} editSettings - Edit settings
|
|
255
|
+
* @property {string} version - Content version
|
|
256
|
+
* @property {YotoPlaybackType} [playbackType] - Playback type (linear or interactive)
|
|
257
|
+
*/
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Returns a piece of content from the Yoto API.
|
|
261
|
+
* @see https://yoto.dev/api/getcontent/
|
|
262
|
+
* @param {object} options
|
|
263
|
+
* @param {string} options.accessToken The API token to request with
|
|
264
|
+
* @param {string} options.cardId The card ID to fetch content for
|
|
265
|
+
* @param {string} [options.timezone] Timezone identifier (e.g., 'Pacific/Auckland'). See https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
|
|
266
|
+
* @param {string} [options.signingType] The type of playable signed URLs returned. Use with `playable`. Example: 's3'
|
|
267
|
+
* @param {boolean} [options.playable] Return playable signed URLs
|
|
268
|
+
* @param {string} [options.userAgent] Optional user agent string
|
|
269
|
+
* @param {RequestOptions} [options.requestOptions] Additional undici request options
|
|
270
|
+
* @return {Promise<YotoContentResponse>} The fetched content
|
|
271
|
+
*/
|
|
272
|
+
export async function getContent ({
|
|
273
|
+
accessToken,
|
|
274
|
+
userAgent,
|
|
275
|
+
requestOptions,
|
|
276
|
+
cardId,
|
|
277
|
+
timezone,
|
|
278
|
+
signingType,
|
|
279
|
+
playable
|
|
280
|
+
}) {
|
|
281
|
+
const requestUrl = new URL(`/content/${cardId}`, YOTO_API_URL)
|
|
282
|
+
|
|
283
|
+
if (timezone) requestUrl.searchParams.set('timezone', timezone)
|
|
284
|
+
if (signingType) requestUrl.searchParams.set('signingType', signingType)
|
|
285
|
+
if (playable) requestUrl.searchParams.set('playable', playable.toString())
|
|
286
|
+
|
|
287
|
+
const response = await request(requestUrl, mergeRequestOptions({
|
|
288
|
+
method: 'GET',
|
|
289
|
+
headers: defaultAuthHeaders({ accessToken, userAgent })
|
|
290
|
+
}, requestOptions))
|
|
291
|
+
|
|
292
|
+
await handleBadResponse(response, { cardId })
|
|
293
|
+
|
|
294
|
+
const responseBody = /** @type {YotoContentResponse} */ (await response.body.json())
|
|
295
|
+
return responseBody
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* @see https://yoto.dev/api/getusersmyocontent/
|
|
300
|
+
* @typedef {Object} YotoMyoContentResponse
|
|
301
|
+
* @property {YotoMyoCard[]} cards
|
|
302
|
+
*/
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* @see https://yoto.dev/api/getusersmyocontent/
|
|
306
|
+
* @typedef {Object} YotoMyoCard
|
|
307
|
+
* @property {string} availability
|
|
308
|
+
* @property {string} cardId
|
|
309
|
+
* @property {YotoClubAvailability[]} [clubAvailability]
|
|
310
|
+
* @property {YotoMyoContent} content
|
|
311
|
+
* @property {string} createdAt
|
|
312
|
+
* @property {boolean} deleted
|
|
313
|
+
* @property {YotoMyoMetadata} metadata
|
|
314
|
+
* @property {string} [shareLinkCreatedAt]
|
|
315
|
+
* @property {string} [shareLinkUrl]
|
|
316
|
+
* @property {YotoSharing} [sharing]
|
|
317
|
+
* @property {string} slug
|
|
318
|
+
* @property {string} [sortkey]
|
|
319
|
+
* @property {string} title
|
|
320
|
+
* @property {string} updatedAt
|
|
321
|
+
* @property {string} userId
|
|
322
|
+
*/
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* @see https://yoto.dev/api/getusersmyocontent/
|
|
326
|
+
* @see https://yoto.dev/reference/card-content-schema/
|
|
327
|
+
* @typedef {Object} YotoMyoContent
|
|
328
|
+
* @property {string} activity - Activity type
|
|
329
|
+
* @property {YotoContentConfig} config - Content configuration
|
|
330
|
+
* @property {YotoContentCover} [cover] - Cover image
|
|
331
|
+
* @property {YotoMyoEditSettings} editSettings - Edit settings
|
|
332
|
+
* @property {boolean} [hidden] - Whether content is hidden
|
|
333
|
+
* @property {boolean} [restricted] - Whether content is restricted
|
|
334
|
+
* @property {string} version - Content version
|
|
335
|
+
* @property {YotoPlaybackType} [playbackType] - Playback type (linear or interactive)
|
|
336
|
+
*/
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* @see https://yoto.dev/api/getusersmyocontent/
|
|
340
|
+
* @see https://yoto.dev/reference/card-content-schema/
|
|
341
|
+
* @typedef {Object} YotoMyoMetadata
|
|
342
|
+
* @property {YotoCategory} category - Content category
|
|
343
|
+
* @property {YotoContentCover} [cover] - Cover image
|
|
344
|
+
* @property {YotoMedia} media - Media information
|
|
345
|
+
* @property {string} [accent] - Accent (e.g., "British")
|
|
346
|
+
* @property {boolean} [addToFamilyLibrary] - Whether to add to family library
|
|
347
|
+
* @property {string} [author] - Author name
|
|
348
|
+
* @property {string} [copyright] - Copyright information
|
|
349
|
+
* @property {string} [description] - Content description
|
|
350
|
+
* @property {string[]} [genre] - Genre tags (e.g., ["Adventure", "Fantasy"])
|
|
351
|
+
* @property {YotoLanguage[]} [languages] - Language codes
|
|
352
|
+
* @property {number} [maxAge] - Maximum recommended age
|
|
353
|
+
* @property {number} [minAge] - Minimum recommended age
|
|
354
|
+
* @property {string[]} [musicType] - Music types (e.g., ["Classical", "Instrumental"])
|
|
355
|
+
* @property {string} [note] - Additional notes
|
|
356
|
+
* @property {any} [order] - Order
|
|
357
|
+
* @property {string} [previewAudio] - Preview audio URL
|
|
358
|
+
* @property {string} [audioPreviewUrl] - Audio preview URL (alternative field name)
|
|
359
|
+
* @property {string} [readBy] - Narrator name
|
|
360
|
+
* @property {boolean} [share] - Whether sharing is enabled
|
|
361
|
+
* @property {YotoStatus} [status] - Content status
|
|
362
|
+
* @property {string[]} [tags] - Content tags
|
|
363
|
+
* @property {string | null} [feedUrl] - Podcast feed URL
|
|
364
|
+
* @property {number} [numEpisodes] - Number of episodes (for podcasts)
|
|
365
|
+
* @property {YotoPlaybackDirection} [playbackDirection] - Playback direction for podcasts
|
|
366
|
+
* @property {boolean} [hidden] - Whether content is hidden
|
|
367
|
+
* @property {any[]} [list] - List data
|
|
368
|
+
*/
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Returns the MYO cards belonging to the authenticated user.
|
|
372
|
+
* @see https://yoto.dev/api/getusersmyocontent/
|
|
373
|
+
* @param {object} options
|
|
374
|
+
* @param {string} options.accessToken The API token to request with
|
|
375
|
+
* @param {boolean} [options.showDeleted=false] Show owned cards that have been deleted
|
|
376
|
+
* @param {string} [options.userAgent] Optional user agent string
|
|
377
|
+
* @param {RequestOptions} [options.requestOptions] Additional undici request options
|
|
378
|
+
* @return {Promise<YotoMyoContentResponse>} The user's MYO content
|
|
379
|
+
*/
|
|
380
|
+
export async function getUserMyoContent ({
|
|
381
|
+
accessToken,
|
|
382
|
+
userAgent,
|
|
383
|
+
requestOptions,
|
|
384
|
+
showDeleted = false
|
|
385
|
+
}) {
|
|
386
|
+
const requestUrl = new URL('/content/mine', YOTO_API_URL)
|
|
387
|
+
|
|
388
|
+
if (showDeleted) requestUrl.searchParams.set('showdeleted', showDeleted.toString())
|
|
389
|
+
|
|
390
|
+
const response = await request(requestUrl, mergeRequestOptions({
|
|
391
|
+
method: 'GET',
|
|
392
|
+
headers: defaultAuthHeaders({ accessToken, userAgent })
|
|
393
|
+
}, requestOptions))
|
|
394
|
+
|
|
395
|
+
await handleBadResponse(response)
|
|
396
|
+
|
|
397
|
+
const responseBody = /** @type {YotoMyoContentResponse} */ (await response.body.json())
|
|
398
|
+
return responseBody
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* @see https://yoto.dev/api/createorupdatecontent/
|
|
403
|
+
* @typedef {Object} YotoCreateOrUpdateContentRequest
|
|
404
|
+
* @property {string} [cardId] - Card ID for updating existing content (omit for creating new)
|
|
405
|
+
* @property {string} title - Card title
|
|
406
|
+
* @property {YotoContentInput} content - Content configuration
|
|
407
|
+
* @property {YotoMetadataInput} [metadata] - Card metadata
|
|
408
|
+
*/
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* @see https://yoto.dev/api/createorupdatecontent/
|
|
412
|
+
* @typedef {Object} YotoContentInput
|
|
413
|
+
* @property {YotoChapter[]} [chapters] - Array of chapters
|
|
414
|
+
* @property {YotoContentConfig} [config] - Content configuration
|
|
415
|
+
* @property {string} [playbackType] - Playback type (e.g., 'linear')
|
|
416
|
+
*/
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* @see https://yoto.dev/api/createorupdatecontent/
|
|
420
|
+
* @typedef {Object} YotoMetadataInput
|
|
421
|
+
* @property {string} [description] - Content description
|
|
422
|
+
* @property {string} [title] - Metadata title
|
|
423
|
+
*/
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* @see https://yoto.dev/api/createorupdatecontent/
|
|
427
|
+
* @typedef {Object} YotoCreateOrUpdateContentResponse
|
|
428
|
+
* @property {YotoCreatedCard} card
|
|
429
|
+
*/
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* @see https://yoto.dev/api/createorupdatecontent/
|
|
433
|
+
* @typedef {Object} YotoCreatedCard
|
|
434
|
+
* @property {string} _id - MongoDB document ID
|
|
435
|
+
* @property {string} cardId - Card ID
|
|
436
|
+
* @property {YotoCreatedContent} content
|
|
437
|
+
* @property {string} createdAt
|
|
438
|
+
* @property {Object} metadata
|
|
439
|
+
* @property {string} title
|
|
440
|
+
* @property {string} updatedAt
|
|
441
|
+
* @property {string} userId
|
|
442
|
+
*/
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* @see https://yoto.dev/api/createorupdatecontent/
|
|
446
|
+
* @typedef {Object} YotoCreatedContent
|
|
447
|
+
* @property {YotoChapter[]} chapters
|
|
448
|
+
* @property {YotoContentConfig} config
|
|
449
|
+
* @property {string} playbackType
|
|
450
|
+
*/
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Create new content or update existing content.
|
|
454
|
+
* @see https://yoto.dev/api/createorupdatecontent/
|
|
455
|
+
* @param {object} options
|
|
456
|
+
* @param {string} options.accessToken The API token to request with
|
|
457
|
+
* @param {YotoCreateOrUpdateContentRequest} options.content The content to create or update
|
|
458
|
+
* @param {string} [options.userAgent] Optional user agent string
|
|
459
|
+
* @param {RequestOptions} [options.requestOptions] Additional undici request options
|
|
460
|
+
* @return {Promise<YotoCreateOrUpdateContentResponse>} The created or updated content
|
|
461
|
+
*/
|
|
462
|
+
export async function createOrUpdateContent ({
|
|
463
|
+
accessToken,
|
|
464
|
+
userAgent,
|
|
465
|
+
requestOptions,
|
|
466
|
+
content
|
|
467
|
+
}) {
|
|
468
|
+
const requestUrl = new URL('/content', YOTO_API_URL)
|
|
469
|
+
|
|
470
|
+
const response = await request(requestUrl, mergeRequestOptions({
|
|
471
|
+
method: 'POST',
|
|
472
|
+
headers: {
|
|
473
|
+
...defaultAuthHeaders({ accessToken, userAgent }),
|
|
474
|
+
'Content-Type': 'application/json'
|
|
475
|
+
},
|
|
476
|
+
body: JSON.stringify(content)
|
|
477
|
+
}, requestOptions))
|
|
478
|
+
|
|
479
|
+
await handleBadResponse(response, { cardId: content.cardId })
|
|
480
|
+
|
|
481
|
+
const responseBody = /** @type {YotoCreateOrUpdateContentResponse} */ (await response.body.json())
|
|
482
|
+
return responseBody
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* @see https://yoto.dev/api/deletecontent/
|
|
487
|
+
* @typedef {Object} YotoDeleteContentResponse
|
|
488
|
+
* @property {string} status - Status of the delete operation (e.g., 'ok')
|
|
489
|
+
*/
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Delete a piece of content.
|
|
493
|
+
* @see https://yoto.dev/api/deletecontent/
|
|
494
|
+
* @param {object} options
|
|
495
|
+
* @param {string} options.accessToken The API token to request with
|
|
496
|
+
* @param {string} options.cardId The card ID to delete
|
|
497
|
+
* @param {string} [options.userAgent] Optional user agent string
|
|
498
|
+
* @param {RequestOptions} [options.requestOptions] Additional undici request options
|
|
499
|
+
* @return {Promise<YotoDeleteContentResponse>} The delete response
|
|
500
|
+
*/
|
|
501
|
+
export async function deleteContent ({
|
|
502
|
+
accessToken,
|
|
503
|
+
userAgent,
|
|
504
|
+
requestOptions,
|
|
505
|
+
cardId
|
|
506
|
+
}) {
|
|
507
|
+
const requestUrl = new URL(`/content/${cardId}`, YOTO_API_URL)
|
|
508
|
+
|
|
509
|
+
const response = await request(requestUrl, mergeRequestOptions({
|
|
510
|
+
method: 'DELETE',
|
|
511
|
+
headers: defaultAuthHeaders({ accessToken, userAgent })
|
|
512
|
+
}, requestOptions))
|
|
513
|
+
|
|
514
|
+
await handleBadResponse(response, { cardId })
|
|
515
|
+
|
|
516
|
+
const responseBody = /** @type {YotoDeleteContentResponse} */ (await response.body.json())
|
|
517
|
+
return responseBody
|
|
518
|
+
}
|