@boldvideo/bold-js 1.16.0 → 1.17.0
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/CHANGELOG.md +27 -0
- package/README.md +23 -2
- package/dist/index.cjs +42 -3
- package/dist/index.d.ts +40 -2
- package/dist/index.js +42 -3
- package/llms.txt +25 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# @boldvideo/bold-js
|
|
2
2
|
|
|
3
|
+
## 1.17.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 563730d: Add full options support to `videos.list()` for tag, collectionId, viewerId, and page filtering
|
|
8
|
+
|
|
9
|
+
**New features:**
|
|
10
|
+
|
|
11
|
+
- Filter videos by `tag` and `collectionId` on both endpoints
|
|
12
|
+
- Include watch progress with `viewerId` parameter
|
|
13
|
+
- Access paginated `/videos` endpoint using `page` parameter
|
|
14
|
+
|
|
15
|
+
**Usage:**
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
// Latest videos with filters
|
|
19
|
+
await bold.videos.list({ limit: 20, tag: "sales", collectionId: "col_123" });
|
|
20
|
+
|
|
21
|
+
// Include viewer watch progress
|
|
22
|
+
await bold.videos.list({ limit: 20, viewerId: "viewer_123" });
|
|
23
|
+
|
|
24
|
+
// Paginated index (uses /videos endpoint)
|
|
25
|
+
await bold.videos.list({ page: 2, tag: "sales" });
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Breaking:** None. Existing `bold.videos.list()` and `bold.videos.list(12)` calls work unchanged.
|
|
29
|
+
|
|
3
30
|
## 1.16.0
|
|
4
31
|
|
|
5
32
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -59,9 +59,27 @@ console.log(recs.guidance);
|
|
|
59
59
|
### Videos
|
|
60
60
|
|
|
61
61
|
```typescript
|
|
62
|
-
// List latest videos
|
|
62
|
+
// List latest videos (default: 12)
|
|
63
63
|
const videos = await bold.videos.list();
|
|
64
64
|
|
|
65
|
+
// With limit (backwards compatible)
|
|
66
|
+
const videos = await bold.videos.list(20);
|
|
67
|
+
|
|
68
|
+
// With filters
|
|
69
|
+
const videos = await bold.videos.list({
|
|
70
|
+
limit: 20,
|
|
71
|
+
tag: 'sales',
|
|
72
|
+
collectionId: 'col_123',
|
|
73
|
+
viewerId: 'viewer_123' // Include watch progress
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Paginated index (uses /videos endpoint)
|
|
77
|
+
const videos = await bold.videos.list({
|
|
78
|
+
page: 2,
|
|
79
|
+
tag: 'sales',
|
|
80
|
+
collectionId: 'col_123'
|
|
81
|
+
});
|
|
82
|
+
|
|
65
83
|
// Get a single video by ID or slug
|
|
66
84
|
const video = await bold.videos.get('video-id');
|
|
67
85
|
const videoBySlug = await bold.videos.get('my-video-slug');
|
|
@@ -357,7 +375,10 @@ import type {
|
|
|
357
375
|
Viewer,
|
|
358
376
|
ViewerProgress,
|
|
359
377
|
ViewerLookupParams,
|
|
360
|
-
ListProgressOptions
|
|
378
|
+
ListProgressOptions,
|
|
379
|
+
ListVideosOptions,
|
|
380
|
+
ListVideosLatestOptions,
|
|
381
|
+
ListVideosIndexOptions
|
|
361
382
|
} from '@boldvideo/bold-js';
|
|
362
383
|
```
|
|
363
384
|
|
package/dist/index.cjs
CHANGED
|
@@ -64,6 +64,15 @@ function camelizeKeys(input, options = {}) {
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
// src/lib/fetchers.ts
|
|
67
|
+
function toQuery(params) {
|
|
68
|
+
const qs = new URLSearchParams();
|
|
69
|
+
for (const [k, v] of Object.entries(params)) {
|
|
70
|
+
if (v !== void 0 && v !== null)
|
|
71
|
+
qs.set(k, String(v));
|
|
72
|
+
}
|
|
73
|
+
const s = qs.toString();
|
|
74
|
+
return s ? `?${s}` : "";
|
|
75
|
+
}
|
|
67
76
|
async function get(client, url) {
|
|
68
77
|
try {
|
|
69
78
|
const res = await client.get(url);
|
|
@@ -90,14 +99,44 @@ function fetchSettings(client) {
|
|
|
90
99
|
};
|
|
91
100
|
}
|
|
92
101
|
function fetchVideos(client) {
|
|
93
|
-
return async (
|
|
102
|
+
return async (arg = 12) => {
|
|
94
103
|
try {
|
|
104
|
+
if (typeof arg === "number") {
|
|
105
|
+
return await get(
|
|
106
|
+
client,
|
|
107
|
+
`videos/latest${toQuery({ limit: arg })}`
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
const opts = arg;
|
|
111
|
+
const hasPage = "page" in opts && opts.page !== void 0;
|
|
112
|
+
if (hasPage && ("limit" in opts || "viewerId" in opts)) {
|
|
113
|
+
throw new Error(
|
|
114
|
+
"videos.list(): cannot use `page` with `limit` or `viewerId` (these belong to different endpoints)"
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
if (hasPage) {
|
|
118
|
+
const { page, tag: tag2, collectionId: collectionId2 } = opts;
|
|
119
|
+
return await get(
|
|
120
|
+
client,
|
|
121
|
+
`videos${toQuery({
|
|
122
|
+
page,
|
|
123
|
+
tag: tag2,
|
|
124
|
+
collection_id: collectionId2
|
|
125
|
+
})}`
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
const { limit, tag, collectionId, viewerId } = opts;
|
|
95
129
|
return await get(
|
|
96
130
|
client,
|
|
97
|
-
`videos/latest
|
|
131
|
+
`videos/latest${toQuery({
|
|
132
|
+
limit: limit ?? 12,
|
|
133
|
+
tag,
|
|
134
|
+
collection_id: collectionId,
|
|
135
|
+
viewer_id: viewerId
|
|
136
|
+
})}`
|
|
98
137
|
);
|
|
99
138
|
} catch (error) {
|
|
100
|
-
console.error(`Error fetching videos
|
|
139
|
+
console.error(`Error fetching videos`, error);
|
|
101
140
|
throw error;
|
|
102
141
|
}
|
|
103
142
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -473,6 +473,44 @@ type ProgressListMeta = {
|
|
|
473
473
|
/** Number of in-progress videos */
|
|
474
474
|
inProgress: number;
|
|
475
475
|
};
|
|
476
|
+
/**
|
|
477
|
+
* Options for listing videos from /videos/latest endpoint
|
|
478
|
+
*/
|
|
479
|
+
type ListVideosLatestOptions = {
|
|
480
|
+
/** Max videos to return (default: 12) */
|
|
481
|
+
limit?: number;
|
|
482
|
+
/** Filter by tag */
|
|
483
|
+
tag?: string;
|
|
484
|
+
/** Filter to videos in a specific collection */
|
|
485
|
+
collectionId?: string;
|
|
486
|
+
/** Viewer UUID for watch progress */
|
|
487
|
+
viewerId?: string;
|
|
488
|
+
};
|
|
489
|
+
/**
|
|
490
|
+
* Options for listing videos from /videos (index) endpoint with pagination
|
|
491
|
+
*/
|
|
492
|
+
type ListVideosIndexOptions = {
|
|
493
|
+
/** Page number for pagination */
|
|
494
|
+
page?: number;
|
|
495
|
+
/** Filter by tag */
|
|
496
|
+
tag?: string;
|
|
497
|
+
/** Filter to videos in a specific collection */
|
|
498
|
+
collectionId?: string;
|
|
499
|
+
};
|
|
500
|
+
/**
|
|
501
|
+
* Combined options for bold.videos.list()
|
|
502
|
+
*
|
|
503
|
+
* If `page` is provided, uses /videos (index) endpoint.
|
|
504
|
+
* Otherwise, uses /videos/latest endpoint.
|
|
505
|
+
*
|
|
506
|
+
* Note: `page` and `limit`/`viewerId` are mutually exclusive.
|
|
507
|
+
*/
|
|
508
|
+
type ListVideosOptions = (ListVideosLatestOptions & {
|
|
509
|
+
page?: never;
|
|
510
|
+
}) | (ListVideosIndexOptions & {
|
|
511
|
+
limit?: never;
|
|
512
|
+
viewerId?: never;
|
|
513
|
+
});
|
|
476
514
|
|
|
477
515
|
/**
|
|
478
516
|
* AI client interface for type-safe method overloading
|
|
@@ -609,7 +647,7 @@ declare function createClient(apiKey: string, options?: ClientOptions): {
|
|
|
609
647
|
data: Settings;
|
|
610
648
|
}>;
|
|
611
649
|
videos: {
|
|
612
|
-
list: (
|
|
650
|
+
list: (arg?: number | ListVideosOptions) => Promise<{
|
|
613
651
|
data: Video[];
|
|
614
652
|
}>;
|
|
615
653
|
get: (id: string) => Promise<{
|
|
@@ -668,4 +706,4 @@ declare const DEFAULT_API_BASE_URL = "https://app.boldvideo.io/api/v1/";
|
|
|
668
706
|
*/
|
|
669
707
|
declare const DEFAULT_INTERNAL_API_BASE_URL = "https://app.boldvideo.io/i/v1/";
|
|
670
708
|
|
|
671
|
-
export { AIContextMessage, AIEvent, AIResponse, AIUsage, Account, AccountAI, AnalyticsProvider, AskOptions, AssistantConfig, ChatOptions, Citation, ClientOptions, Conversation, ConversationMessage, ConversationMetadata, CreateViewerData, CustomRedirect, DEFAULT_API_BASE_URL, DEFAULT_INTERNAL_API_BASE_URL, ListProgressOptions, MenuItem, Playlist, Portal, PortalDisplay, PortalHero, PortalLayout, PortalNavigation, PortalTheme, ProgressListMeta, RecommendOptions, RecommendResponse, Recommendation, RecommendationVideo, RecommendationsOptions, RecommendationsResponse, SaveProgressData, SearchOptions, Segment, Settings, Source, ThemeColors, ThemeConfig, UpdateViewerData, Video, VideoAttachment, VideoDownloadUrls, VideoMetadata, VideoSubtitles, VideoTranscript, Viewer, ViewerAPIError, ViewerLookupParams, ViewerProgress, createClient };
|
|
709
|
+
export { AIContextMessage, AIEvent, AIResponse, AIUsage, Account, AccountAI, AnalyticsProvider, AskOptions, AssistantConfig, ChatOptions, Citation, ClientOptions, Conversation, ConversationMessage, ConversationMetadata, CreateViewerData, CustomRedirect, DEFAULT_API_BASE_URL, DEFAULT_INTERNAL_API_BASE_URL, ListProgressOptions, ListVideosIndexOptions, ListVideosLatestOptions, ListVideosOptions, MenuItem, Playlist, Portal, PortalDisplay, PortalHero, PortalLayout, PortalNavigation, PortalTheme, ProgressListMeta, RecommendOptions, RecommendResponse, Recommendation, RecommendationVideo, RecommendationsOptions, RecommendationsResponse, SaveProgressData, SearchOptions, Segment, Settings, Source, ThemeColors, ThemeConfig, UpdateViewerData, Video, VideoAttachment, VideoDownloadUrls, VideoMetadata, VideoSubtitles, VideoTranscript, Viewer, ViewerAPIError, ViewerLookupParams, ViewerProgress, createClient };
|
package/dist/index.js
CHANGED
|
@@ -25,6 +25,15 @@ function camelizeKeys(input, options = {}) {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
// src/lib/fetchers.ts
|
|
28
|
+
function toQuery(params) {
|
|
29
|
+
const qs = new URLSearchParams();
|
|
30
|
+
for (const [k, v] of Object.entries(params)) {
|
|
31
|
+
if (v !== void 0 && v !== null)
|
|
32
|
+
qs.set(k, String(v));
|
|
33
|
+
}
|
|
34
|
+
const s = qs.toString();
|
|
35
|
+
return s ? `?${s}` : "";
|
|
36
|
+
}
|
|
28
37
|
async function get(client, url) {
|
|
29
38
|
try {
|
|
30
39
|
const res = await client.get(url);
|
|
@@ -51,14 +60,44 @@ function fetchSettings(client) {
|
|
|
51
60
|
};
|
|
52
61
|
}
|
|
53
62
|
function fetchVideos(client) {
|
|
54
|
-
return async (
|
|
63
|
+
return async (arg = 12) => {
|
|
55
64
|
try {
|
|
65
|
+
if (typeof arg === "number") {
|
|
66
|
+
return await get(
|
|
67
|
+
client,
|
|
68
|
+
`videos/latest${toQuery({ limit: arg })}`
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
const opts = arg;
|
|
72
|
+
const hasPage = "page" in opts && opts.page !== void 0;
|
|
73
|
+
if (hasPage && ("limit" in opts || "viewerId" in opts)) {
|
|
74
|
+
throw new Error(
|
|
75
|
+
"videos.list(): cannot use `page` with `limit` or `viewerId` (these belong to different endpoints)"
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
if (hasPage) {
|
|
79
|
+
const { page, tag: tag2, collectionId: collectionId2 } = opts;
|
|
80
|
+
return await get(
|
|
81
|
+
client,
|
|
82
|
+
`videos${toQuery({
|
|
83
|
+
page,
|
|
84
|
+
tag: tag2,
|
|
85
|
+
collection_id: collectionId2
|
|
86
|
+
})}`
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
const { limit, tag, collectionId, viewerId } = opts;
|
|
56
90
|
return await get(
|
|
57
91
|
client,
|
|
58
|
-
`videos/latest
|
|
92
|
+
`videos/latest${toQuery({
|
|
93
|
+
limit: limit ?? 12,
|
|
94
|
+
tag,
|
|
95
|
+
collection_id: collectionId,
|
|
96
|
+
viewer_id: viewerId
|
|
97
|
+
})}`
|
|
59
98
|
);
|
|
60
99
|
} catch (error) {
|
|
61
|
-
console.error(`Error fetching videos
|
|
100
|
+
console.error(`Error fetching videos`, error);
|
|
62
101
|
throw error;
|
|
63
102
|
}
|
|
64
103
|
};
|
package/llms.txt
CHANGED
|
@@ -55,12 +55,35 @@ interface ClientOptions {
|
|
|
55
55
|
All content methods return `Promise<{ data: T }>`.
|
|
56
56
|
|
|
57
57
|
- `bold.settings(videoLimit?)` - Channel settings, menus, featured playlists
|
|
58
|
-
- `bold.videos.list(
|
|
58
|
+
- `bold.videos.list()` - List latest videos (default limit: 12)
|
|
59
|
+
- `bold.videos.list(limit)` - List with numeric limit (backwards compatible)
|
|
60
|
+
- `bold.videos.list(options)` - List with full options (see ListVideosOptions)
|
|
59
61
|
- `bold.videos.get(id)` - Get video by ID or slug
|
|
60
62
|
- `bold.videos.search(query)` - Search videos
|
|
61
63
|
- `bold.playlists.list()` - List playlists
|
|
62
64
|
- `bold.playlists.get(id)` - Get playlist with videos
|
|
63
65
|
|
|
66
|
+
### ListVideosOptions
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
// For /videos/latest endpoint (default)
|
|
70
|
+
{
|
|
71
|
+
limit?: number; // Max videos (default: 12)
|
|
72
|
+
tag?: string; // Filter by tag
|
|
73
|
+
collectionId?: string; // Filter to collection
|
|
74
|
+
viewerId?: string; // Include watch progress
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// For /videos (index) endpoint - use when you need pagination
|
|
78
|
+
{
|
|
79
|
+
page?: number; // Page number
|
|
80
|
+
tag?: string;
|
|
81
|
+
collectionId?: string;
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Note: If `page` is provided, SDK uses `/videos` (index); otherwise uses `/videos/latest`.
|
|
86
|
+
|
|
64
87
|
## Viewers API
|
|
65
88
|
|
|
66
89
|
Manage external users and track video progress. Returns `Promise<{ data: T }>` (consistent with other SDK methods).
|
|
@@ -254,7 +277,7 @@ type AIEvent =
|
|
|
254
277
|
|
|
255
278
|
### Other types exported
|
|
256
279
|
|
|
257
|
-
`Playlist`, `Settings`, `Portal`, `MenuItem`, `AIResponse`, `AIUsage`, `AIContextMessage`, `Conversation`, `ConversationMessage`, `RecommendationsResponse`, `Viewer`, `ViewerProgress`, `ViewerLookupParams`, `ListProgressOptions`
|
|
280
|
+
`Playlist`, `Settings`, `Portal`, `MenuItem`, `AIResponse`, `AIUsage`, `AIContextMessage`, `Conversation`, `ConversationMessage`, `RecommendationsResponse`, `Viewer`, `ViewerProgress`, `ViewerLookupParams`, `ListProgressOptions`, `ListVideosOptions`, `ListVideosLatestOptions`, `ListVideosIndexOptions`
|
|
258
281
|
|
|
259
282
|
## Error Handling
|
|
260
283
|
|