@boldvideo/bold-js 0.4.3 → 0.6.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.
@@ -0,0 +1,11 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "npm"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
7
+ open-pull-requests-limit: 10
8
+ groups:
9
+ dependencies:
10
+ patterns:
11
+ - "*"
@@ -0,0 +1,51 @@
1
+ name: Changeset Release
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+
8
+ concurrency: ${{ github.workflow }}-${{ github.ref }}
9
+
10
+ permissions:
11
+ contents: write
12
+ pull-requests: write
13
+ id-token: write # For npm provenance
14
+
15
+ jobs:
16
+ release:
17
+ name: Release
18
+ runs-on: ubuntu-latest
19
+ steps:
20
+ - name: Checkout code
21
+ uses: actions/checkout@v4
22
+ with:
23
+ fetch-depth: 0
24
+
25
+ - name: Install pnpm
26
+ uses: pnpm/action-setup@v2
27
+ with:
28
+ version: 10.12.2
29
+
30
+ - name: Setup Node.js
31
+ uses: actions/setup-node@v4
32
+ with:
33
+ node-version: 20.x
34
+ cache: 'pnpm'
35
+ registry-url: 'https://registry.npmjs.org'
36
+
37
+ - name: Install dependencies
38
+ run: pnpm install --frozen-lockfile
39
+
40
+ - name: Create Release Pull Request or Publish to npm
41
+ id: changesets
42
+ uses: changesets/action@v1
43
+ with:
44
+ title: "chore: release package"
45
+ commit: "chore: release package"
46
+ publish: pnpm changeset publish
47
+ createGithubReleases: true
48
+ env:
49
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
50
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
51
+ NPM_CONFIG_PROVENANCE: true
@@ -0,0 +1,90 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ branches: [ main ]
8
+
9
+ jobs:
10
+ test:
11
+ name: Test on Node ${{ matrix.node-version }}
12
+ runs-on: ubuntu-latest
13
+
14
+ strategy:
15
+ matrix:
16
+ node-version: [20.x, 22.x, 24.x]
17
+
18
+ steps:
19
+ - name: Checkout code
20
+ uses: actions/checkout@v4
21
+
22
+ - name: Install pnpm
23
+ uses: pnpm/action-setup@v2
24
+ with:
25
+ version: 10.12.2
26
+
27
+ - name: Use Node.js ${{ matrix.node-version }}
28
+ uses: actions/setup-node@v4
29
+ with:
30
+ node-version: ${{ matrix.node-version }}
31
+ cache: 'pnpm'
32
+
33
+ - name: Install dependencies
34
+ run: pnpm install --frozen-lockfile
35
+
36
+ - name: Run linter
37
+ run: pnpm run lint
38
+
39
+ - name: Build package
40
+ run: pnpm run build
41
+
42
+ - name: Check package exports
43
+ run: |
44
+ node -e "const pkg = require('./dist/index.cjs'); console.log('CJS import successful');"
45
+ node -e "import('./dist/index.js').then(() => console.log('ESM import successful'));"
46
+
47
+ - name: Check TypeScript declarations
48
+ run: |
49
+ if [ ! -f "dist/index.d.ts" ]; then
50
+ echo "TypeScript declarations not found!"
51
+ exit 1
52
+ fi
53
+
54
+ size-check:
55
+ name: Bundle Size Check
56
+ runs-on: ubuntu-latest
57
+
58
+ steps:
59
+ - name: Checkout code
60
+ uses: actions/checkout@v4
61
+
62
+ - name: Install pnpm
63
+ uses: pnpm/action-setup@v2
64
+ with:
65
+ version: 10.12.2
66
+
67
+ - name: Use Node.js
68
+ uses: actions/setup-node@v4
69
+ with:
70
+ node-version: 22.x
71
+ cache: 'pnpm'
72
+
73
+ - name: Install dependencies
74
+ run: pnpm install --frozen-lockfile
75
+
76
+ - name: Build package
77
+ run: pnpm run build
78
+
79
+ - name: Check bundle size
80
+ run: |
81
+ echo "Bundle sizes:"
82
+ ls -lh dist/
83
+
84
+ # Warn if bundle exceeds 50KB (adjust threshold as needed)
85
+ size=$(node -e "console.log(require('fs').statSync('dist/index.js').size)")
86
+ if [ $size -gt 51200 ]; then
87
+ echo "⚠️ Warning: Bundle size exceeds 50KB (current: ${size} bytes)"
88
+ else
89
+ echo "✅ Bundle size OK: ${size} bytes"
90
+ fi
@@ -0,0 +1,83 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ permissions:
9
+ contents: read
10
+ id-token: write # For npm provenance
11
+
12
+ jobs:
13
+ release:
14
+ name: Release to npm
15
+ runs-on: ubuntu-latest
16
+
17
+ steps:
18
+ - name: Checkout code
19
+ uses: actions/checkout@v4
20
+ with:
21
+ fetch-depth: 0 # Needed for changelog generation
22
+
23
+ - name: Install pnpm
24
+ uses: pnpm/action-setup@v2
25
+ with:
26
+ version: 10.12.2
27
+
28
+ - name: Setup Node.js
29
+ uses: actions/setup-node@v4
30
+ with:
31
+ node-version: 20.x
32
+ cache: 'pnpm'
33
+ registry-url: 'https://registry.npmjs.org'
34
+
35
+ - name: Install dependencies
36
+ run: pnpm install --frozen-lockfile
37
+
38
+ - name: Run CI checks
39
+ run: |
40
+ pnpm run lint
41
+ pnpm run build
42
+
43
+ - name: Verify version matches tag
44
+ run: |
45
+ PACKAGE_VERSION="v$(node -p "require('./package.json').version")"
46
+ if [ "$PACKAGE_VERSION" != "${{ github.ref_name }}" ]; then
47
+ echo "Error: Package version ($PACKAGE_VERSION) doesn't match tag (${{ github.ref_name }})"
48
+ exit 1
49
+ fi
50
+
51
+ - name: Check npm access
52
+ run: npm whoami
53
+ env:
54
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
55
+
56
+ - name: Publish to npm with provenance
57
+ run: pnpm publish --access public --no-git-checks
58
+ env:
59
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
60
+ NPM_CONFIG_PROVENANCE: true
61
+
62
+ - name: Create GitHub Release
63
+ uses: softprops/action-gh-release@v1
64
+ with:
65
+ generate_release_notes: true
66
+ body: |
67
+ ## What's Changed
68
+
69
+ See [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/main/CHANGELOG.md) for details.
70
+
71
+ ## Installation
72
+
73
+ ```bash
74
+ npm install @boldvideo/bold-js@${{ github.ref_name }}
75
+ ```
76
+
77
+ ```bash
78
+ pnpm add @boldvideo/bold-js@${{ github.ref_name }}
79
+ ```
80
+
81
+ ```bash
82
+ yarn add @boldvideo/bold-js@${{ github.ref_name }}
83
+ ```
package/CHANGELOG.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # @boldvideo/bold-js
2
2
 
3
+ ## 0.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Add complete type definitions for Settings and Video API responses
8
+
9
+ **Settings updates:**
10
+
11
+ - Add `portal` object with display, layout, navigation, and theme settings
12
+ - Add `portal.navigation.show_header` field (BOLD-687)
13
+ - Add `account` object with nested AI configuration
14
+ - Add top-level fields: `favicon_url`, `logo_dark_url`, `logo_url`, `version`
15
+ - Add `theme_config` with dark/light theme definitions
16
+ - Expand `meta_data` to include `social_graph_image_url`
17
+ - Maintain backward compatibility with flat AI fields
18
+
19
+ **Video updates:**
20
+
21
+ - Add missing fields: `chapters`, `attachments`, `download_urls`, `transcript`
22
+ - Add `internal_id`, `playback_speed`, `subtitles`, `tags`, `cta`
23
+ - Fix `meta_data` type from array to object
24
+ - Replace incorrect `transcription` field with correct `transcript` field
25
+ - Mark optional fields appropriately
26
+
27
+ ## 0.5.0
28
+
29
+ ### Minor Changes
30
+
31
+ - 111cb8f: feat: add ai_greeting property to Settings type
32
+
33
+ Added optional ai_greeting property to the Settings type to allow customization of the AI assistant's greeting message. This maintains backward compatibility while enabling users to override the default greeting.
34
+
35
+ Resolves #2
36
+
3
37
  ## 0.4.3
4
38
 
5
39
  ### Patch Changes
@@ -0,0 +1,103 @@
1
+ # Contributing to @boldvideo/bold-js
2
+
3
+ First off, thank you for considering contributing to Bold JS! It's people like you that make Bold JS such a great tool.
4
+
5
+ ## Code of Conduct
6
+
7
+ By participating in this project, you are expected to uphold our Code of Conduct:
8
+ - Be respectful and inclusive
9
+ - Welcome newcomers and help them get started
10
+ - Focus on what is best for the community
11
+ - Show empathy towards other community members
12
+
13
+ ## How Can I Contribute?
14
+
15
+ ### Reporting Bugs
16
+
17
+ Before creating bug reports, please check existing issues to avoid duplicates. When you create a bug report, include as many details as possible:
18
+
19
+ - Use a clear and descriptive title
20
+ - Describe the exact steps to reproduce the problem
21
+ - Provide specific examples to demonstrate the steps
22
+ - Describe the behavior you observed and what behavior you expected
23
+ - Include your environment details (Node.js version, OS, etc.)
24
+
25
+ ### Suggesting Enhancements
26
+
27
+ Enhancement suggestions are tracked as GitHub issues. When creating an enhancement suggestion:
28
+
29
+ - Use a clear and descriptive title
30
+ - Provide a step-by-step description of the suggested enhancement
31
+ - Provide specific examples to demonstrate the use case
32
+ - Explain why this enhancement would be useful to most users
33
+
34
+ ### Pull Requests
35
+
36
+ 1. Fork the repo and create your branch from `main`
37
+ 2. If you've added code that should be tested, add tests
38
+ 3. Ensure the test suite passes (`pnpm run lint && pnpm run build`)
39
+ 4. Make sure your code follows the existing code style
40
+ 5. Create a changeset for your changes:
41
+ ```bash
42
+ pnpm changeset
43
+ ```
44
+ 6. Push your branch and submit a pull request
45
+
46
+ ## Development Setup
47
+
48
+ 1. Fork and clone the repo:
49
+ ```bash
50
+ git clone https://github.com/YOUR_USERNAME/bold-js.git
51
+ cd bold-js
52
+ ```
53
+
54
+ 2. Install dependencies:
55
+ ```bash
56
+ pnpm install
57
+ ```
58
+
59
+ 3. Make your changes and run the build:
60
+ ```bash
61
+ pnpm run build
62
+ pnpm run lint
63
+ ```
64
+
65
+ ## Changesets
66
+
67
+ We use [changesets](https://github.com/changesets/changesets) to manage versions and changelogs. When you make a change:
68
+
69
+ 1. Run `pnpm changeset`
70
+ 2. Select the type of change (patch/minor/major)
71
+ 3. Describe your changes for the changelog
72
+ 4. Commit the generated changeset file along with your changes
73
+
74
+ ## Style Guide
75
+
76
+ - Use TypeScript for all new code
77
+ - Follow the existing code style (enforced by TypeScript compiler)
78
+ - Write clear, self-documenting code
79
+ - Add comments only when necessary to explain "why" not "what"
80
+ - Keep functions small and focused
81
+ - Use meaningful variable and function names
82
+
83
+ ## Commit Messages
84
+
85
+ - Use the present tense ("Add feature" not "Added feature")
86
+ - Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
87
+ - Limit the first line to 72 characters or less
88
+ - Reference issues and pull requests liberally after the first line
89
+
90
+ ## Release Process (Maintainers Only)
91
+
92
+ Releases are automated through GitHub Actions:
93
+
94
+ 1. When PRs with changesets are merged to main, a "Version Packages" PR is created
95
+ 2. Review and merge the version PR to trigger a release
96
+ 3. The workflow will automatically:
97
+ - Publish to npm
98
+ - Create a GitHub release
99
+ - Update the changelog
100
+
101
+ ## Questions?
102
+
103
+ Feel free to open an issue with your question or reach out to the maintainers directly.
package/README.md CHANGED
@@ -58,6 +58,29 @@ const playlists = await bold.playlists.list();
58
58
 
59
59
  - **[Bold API Documentation](https://docs.boldvideo.io/docs/api)**
60
60
 
61
+ ## Contributing
62
+
63
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to this project.
64
+
65
+ ## Security
66
+
67
+ ### For Maintainers
68
+
69
+ The automated release process is secure by default:
70
+ - NPM_TOKEN is only accessible to workflows on the main branch
71
+ - External contributors' PRs cannot access secrets
72
+ - Only maintainers with write access can merge to main
73
+ - The changeset-release workflow only runs after merge to main
74
+
75
+ ### Recommended Branch Protection
76
+
77
+ For additional security, enable these branch protection rules for `main`:
78
+ - Require pull request reviews before merging
79
+ - Dismiss stale pull request approvals when new commits are pushed
80
+ - Require status checks to pass (CI workflow)
81
+ - Require branches to be up to date before merging
82
+ - Include administrators in these restrictions
83
+
61
84
  ## More Resources
62
85
 
63
86
  ### Support
package/SECURITY.md ADDED
@@ -0,0 +1,66 @@
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ We release patches for security vulnerabilities for the following versions:
6
+
7
+ | Version | Supported |
8
+ | ------- | ------------------ |
9
+ | 0.x.x | :white_check_mark: |
10
+
11
+ ## Reporting a Vulnerability
12
+
13
+ If you discover a security vulnerability within Bold JS, please send an email to security@boldvideo.com. All security vulnerabilities will be promptly addressed.
14
+
15
+ Please do not report security vulnerabilities through public GitHub issues.
16
+
17
+ When reporting a vulnerability, please include:
18
+
19
+ - The version of @boldvideo/bold-js you're using
20
+ - A description of the vulnerability
21
+ - Steps to reproduce the issue
22
+ - Potential impact of the vulnerability
23
+ - Any suggested fixes (if applicable)
24
+
25
+ ## Security Measures
26
+
27
+ ### NPM Publishing
28
+
29
+ - Releases are automated through GitHub Actions
30
+ - NPM tokens are stored as encrypted GitHub secrets
31
+ - Only maintainers with write access can trigger releases
32
+ - All releases include npm provenance for supply chain security
33
+
34
+ ### Dependencies
35
+
36
+ - Dependencies are regularly updated via Dependabot
37
+ - Security advisories are monitored through GitHub's security features
38
+ - Minimal dependencies to reduce attack surface (only axios as runtime dependency)
39
+
40
+ ### Code Review
41
+
42
+ - All changes require pull request reviews
43
+ - CI checks must pass before merging
44
+ - Type safety enforced through TypeScript
45
+
46
+ ## Best Practices for Users
47
+
48
+ When using @boldvideo/bold-js:
49
+
50
+ 1. **Keep your API keys secure**
51
+ - Never commit API keys to version control
52
+ - Use environment variables for API keys
53
+ - Rotate keys regularly
54
+
55
+ 2. **Stay updated**
56
+ - Regularly update to the latest version
57
+ - Monitor security advisories
58
+ - Review the changelog for security updates
59
+
60
+ 3. **Validate input**
61
+ - Always validate and sanitize user input before passing to the SDK
62
+ - Be cautious with data from external sources
63
+
64
+ ## Acknowledgments
65
+
66
+ We appreciate responsible disclosure of security vulnerabilities and will acknowledge researchers who report issues (with their permission).
package/package.json CHANGED
@@ -1,14 +1,20 @@
1
1
  {
2
2
  "name": "@boldvideo/bold-js",
3
3
  "license": "MIT",
4
- "version": "0.4.3",
4
+ "version": "0.6.0",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
8
  "type": "module",
9
- "scripts": {
10
- "build": "tsup src/index.ts --format cjs,esm --dts",
11
- "lint": "tsc"
9
+ "engines": {
10
+ "node": ">=20.0.0"
11
+ },
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/boldvideo/bold-js"
15
+ },
16
+ "publishConfig": {
17
+ "access": "public"
12
18
  },
13
19
  "devDependencies": {
14
20
  "@changesets/cli": "^2.26.0",
@@ -18,5 +24,8 @@
18
24
  "dependencies": {
19
25
  "axios": "^1.3.6"
20
26
  },
21
- "packageManager": "pnpm@10.12.2+sha512.a32540185b964ee30bb4e979e405adc6af59226b438ee4cc19f9e8773667a66d302f5bfee60a39d3cac69e35e4b96e708a71dd002b7e9359c4112a1722ac323f"
22
- }
27
+ "scripts": {
28
+ "build": "tsup src/index.ts --format cjs,esm --dts",
29
+ "lint": "tsc"
30
+ }
31
+ }
package/src/index.ts CHANGED
@@ -1,2 +1,22 @@
1
1
  export { createClient } from "lib/client";
2
- export * from "lib/types";
2
+ export type {
3
+ Video,
4
+ VideoAttachment,
5
+ VideoDownloadUrls,
6
+ VideoSubtitles,
7
+ VideoTranscript,
8
+ VideoMetadata,
9
+ Playlist,
10
+ MenuItem,
11
+ Settings,
12
+ Portal,
13
+ PortalDisplay,
14
+ PortalLayout,
15
+ PortalNavigation,
16
+ PortalTheme,
17
+ AssistantConfig,
18
+ ThemeConfig,
19
+ ThemeColors,
20
+ Account,
21
+ AccountAI,
22
+ } from "./lib/types";
package/src/lib/types.ts CHANGED
@@ -1,4 +1,37 @@
1
+ export type VideoAttachment = {
2
+ id: string;
3
+ title: string;
4
+ file_url: string;
5
+ file_size?: number;
6
+ file_type?: string;
7
+ };
8
+
9
+ export type VideoDownloadUrls = {
10
+ mp4?: string;
11
+ audio?: string;
12
+ legacy_mp4?: string;
13
+ };
14
+
15
+ export type VideoSubtitles = {
16
+ label: string;
17
+ url: string;
18
+ engine?: string;
19
+ language: string;
20
+ };
21
+
22
+ export type VideoTranscript = {
23
+ text: string;
24
+ json: any;
25
+ };
26
+
27
+ export type VideoMetadata = {
28
+ description: string;
29
+ title: string;
30
+ image: string | null;
31
+ };
32
+
1
33
  export type Video = {
34
+ // Existing fields (kept as-is)
2
35
  captions: string;
3
36
  captions_label: string;
4
37
  captions_lang: string;
@@ -6,16 +39,44 @@ export type Video = {
6
39
  duration: number;
7
40
  id: string;
8
41
  imported_from: string | null;
9
- legacy_video_url: null | null;
10
- meta_data: [];
42
+ legacy_video_url: string | null;
11
43
  playback_id: string;
12
44
  published_at: string;
13
45
  stream_url: string;
14
46
  teaser: string | null;
15
47
  thumbnail: string;
16
48
  title: string;
17
- transcription: string;
18
49
  type: string;
50
+
51
+ // Fixed: meta_data should be an object, not array
52
+ meta_data: VideoMetadata;
53
+
54
+ // New: Chapters in WEBVTT format
55
+ chapters?: string;
56
+
57
+ // New: Attachments array
58
+ attachments?: VideoAttachment[];
59
+
60
+ // New: Call-to-action (can be null)
61
+ cta?: any | null;
62
+
63
+ // New: Download URLs object
64
+ download_urls?: VideoDownloadUrls;
65
+
66
+ // New: Internal ID
67
+ internal_id?: string;
68
+
69
+ // New: Playback speed
70
+ playback_speed?: number;
71
+
72
+ // New: Subtitles object
73
+ subtitles?: VideoSubtitles;
74
+
75
+ // New: Tags array
76
+ tags?: string[];
77
+
78
+ // New: Transcript object (replaces transcription)
79
+ transcript?: VideoTranscript;
19
80
  };
20
81
 
21
82
  export type Playlist = {
@@ -34,18 +95,123 @@ export type MenuItem = {
34
95
  url: string;
35
96
  };
36
97
 
98
+ export type PortalDisplay = {
99
+ show_chapters: boolean;
100
+ show_transcripts: boolean;
101
+ };
102
+
103
+ export type AssistantConfig = {
104
+ headline: string;
105
+ subheadline: string;
106
+ suggestions: string[];
107
+ };
108
+
109
+ export type PortalLayout = {
110
+ assistant_config: AssistantConfig | null;
111
+ show_playlists: boolean;
112
+ type: string;
113
+ videos_limit: number;
114
+ };
115
+
116
+ export type PortalNavigation = {
117
+ show_ai_search: boolean;
118
+ show_header: boolean;
119
+ show_search: boolean;
120
+ };
121
+
122
+ export type PortalTheme = {
123
+ background: string;
124
+ font_body: string;
125
+ font_header: string;
126
+ foreground: string;
127
+ logo_height: number;
128
+ logo_url: string;
129
+ logo_width: number;
130
+ primary: string;
131
+ };
132
+
133
+ export type Portal = {
134
+ display: PortalDisplay;
135
+ layout: PortalLayout;
136
+ navigation: PortalNavigation;
137
+ theme: PortalTheme;
138
+ };
139
+
140
+ export type ThemeColors = {
141
+ background: string;
142
+ border: string;
143
+ card: string;
144
+ "card-foreground": string;
145
+ destructive: string;
146
+ "destructive-foreground": string;
147
+ foreground: string;
148
+ input: string;
149
+ muted: string;
150
+ "muted-foreground": string;
151
+ popover: string;
152
+ "popover-foreground": string;
153
+ primary: string;
154
+ "primary-foreground": string;
155
+ ring: string;
156
+ secondary: string;
157
+ "secondary-foreground": string;
158
+ };
159
+
160
+ export type ThemeConfig = {
161
+ dark: ThemeColors;
162
+ light: ThemeColors;
163
+ radius: string;
164
+ };
165
+
166
+ export type AccountAI = {
167
+ avatar_url: string;
168
+ enabled: boolean;
169
+ greeting: string;
170
+ name: string;
171
+ };
172
+
173
+ export type Account = {
174
+ ai: AccountAI;
175
+ name: string;
176
+ slug: string;
177
+ };
178
+
37
179
  export type Settings = {
180
+ // Existing top-level arrays
38
181
  featured_playlists: Playlist[];
39
182
  menu_items: MenuItem[];
183
+
184
+ // Existing flat AI fields (kept for backward compatibility)
40
185
  ai_avatar: string;
41
186
  ai_name: string;
187
+ ai_greeting?: string;
42
188
  has_ai: boolean;
189
+
190
+ // New: Account object with nested AI config
191
+ account: Account;
192
+
193
+ // New: Top-level URL fields
194
+ favicon_url?: string;
195
+ logo_dark_url?: string;
196
+ logo_url?: string;
197
+
198
+ // Updated: meta_data with additional fields
43
199
  meta_data: {
44
200
  channel_name: string;
45
201
  description: string;
46
- image: string;
202
+ image: string | null;
47
203
  no_seo: boolean;
204
+ social_graph_image_url?: string;
48
205
  title: string;
49
206
  title_suffix: string;
50
207
  };
208
+
209
+ // New: Portal object with all nested structures
210
+ portal: Portal;
211
+
212
+ // New: Theme configuration
213
+ theme_config: ThemeConfig;
214
+
215
+ // New: API version
216
+ version: string;
51
217
  };
@@ -1,9 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Bash(pnpm run lint:*)",
5
- "Bash(ls:*)"
6
- ]
7
- },
8
- "enableAllProjectMcpServers": false
9
- }
package/dist/index.cjs DELETED
@@ -1,299 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __defProps = Object.defineProperties;
5
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
7
- var __getOwnPropNames = Object.getOwnPropertyNames;
8
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
9
- var __getProtoOf = Object.getPrototypeOf;
10
- var __hasOwnProp = Object.prototype.hasOwnProperty;
11
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
12
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
13
- var __spreadValues = (a, b) => {
14
- for (var prop in b || (b = {}))
15
- if (__hasOwnProp.call(b, prop))
16
- __defNormalProp(a, prop, b[prop]);
17
- if (__getOwnPropSymbols)
18
- for (var prop of __getOwnPropSymbols(b)) {
19
- if (__propIsEnum.call(b, prop))
20
- __defNormalProp(a, prop, b[prop]);
21
- }
22
- return a;
23
- };
24
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
25
- var __export = (target, all) => {
26
- for (var name in all)
27
- __defProp(target, name, { get: all[name], enumerable: true });
28
- };
29
- var __copyProps = (to, from, except, desc) => {
30
- if (from && typeof from === "object" || typeof from === "function") {
31
- for (let key of __getOwnPropNames(from))
32
- if (!__hasOwnProp.call(to, key) && key !== except)
33
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
34
- }
35
- return to;
36
- };
37
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
38
- // If the importer is in node compatibility mode or this is not an ESM
39
- // file that has been converted to a CommonJS file using a Babel-
40
- // compatible transform (i.e. "__esModule" has not been set), then set
41
- // "default" to the CommonJS "module.exports" for node compatibility.
42
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
43
- mod
44
- ));
45
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
46
- var __async = (__this, __arguments, generator) => {
47
- return new Promise((resolve, reject) => {
48
- var fulfilled = (value) => {
49
- try {
50
- step(generator.next(value));
51
- } catch (e) {
52
- reject(e);
53
- }
54
- };
55
- var rejected = (value) => {
56
- try {
57
- step(generator.throw(value));
58
- } catch (e) {
59
- reject(e);
60
- }
61
- };
62
- var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
63
- step((generator = generator.apply(__this, __arguments)).next());
64
- });
65
- };
66
-
67
- // src/index.ts
68
- var src_exports = {};
69
- __export(src_exports, {
70
- createClient: () => createClient
71
- });
72
- module.exports = __toCommonJS(src_exports);
73
-
74
- // src/lib/client.ts
75
- var import_axios = __toESM(require("axios"), 1);
76
-
77
- // src/lib/fetchers.ts
78
- function get(client, url) {
79
- return __async(this, null, function* () {
80
- try {
81
- const res = yield client.get(url);
82
- if (res.status !== 200) {
83
- throw new Error(`Unexpected response status: ${res.status}`);
84
- }
85
- return res.data;
86
- } catch (error) {
87
- console.error(`Error fetching data from URL: ${url}`, error);
88
- throw error;
89
- }
90
- });
91
- }
92
- function fetchSettings(client) {
93
- return (videoLimit = 12) => __async(this, null, function* () {
94
- try {
95
- return yield get(
96
- client,
97
- `settings?limit=${videoLimit}`
98
- );
99
- } catch (error) {
100
- console.error(`Error fetching settings with limit: ${videoLimit}`, error);
101
- throw error;
102
- }
103
- });
104
- }
105
- function fetchVideos(client) {
106
- return (videoLimit = 12) => __async(this, null, function* () {
107
- try {
108
- return yield get(
109
- client,
110
- `videos/latest?limit=${videoLimit}`
111
- );
112
- } catch (error) {
113
- console.error(`Error fetching videos with limit: ${videoLimit}`, error);
114
- throw error;
115
- }
116
- });
117
- }
118
- function searchVideos(client) {
119
- return (term) => __async(this, null, function* () {
120
- try {
121
- return yield get(client, `videos?query=${term}`);
122
- } catch (error) {
123
- console.error(`Error searching for videos with term: ${term}`, error);
124
- throw error;
125
- }
126
- });
127
- }
128
- function fetchVideo(client) {
129
- return (id) => __async(this, null, function* () {
130
- try {
131
- return yield get(client, `videos/${id}`);
132
- } catch (error) {
133
- console.error(`Error fetching video with ID: ${id}`, error);
134
- throw error;
135
- }
136
- });
137
- }
138
- function fetchPlaylists(client) {
139
- return () => __async(this, null, function* () {
140
- try {
141
- return yield get(client, "playlists");
142
- } catch (error) {
143
- console.error("Error fetching playlists", error);
144
- throw error;
145
- }
146
- });
147
- }
148
- function fetchPlaylist(client) {
149
- return (id) => __async(this, null, function* () {
150
- try {
151
- return yield get(client, `playlists/${id}`);
152
- } catch (error) {
153
- console.error(`Error fetching playlist with ID: ${id}`, error);
154
- throw error;
155
- }
156
- });
157
- }
158
-
159
- // src/util/throttle.ts
160
- var throttle = (fn, delay) => {
161
- let wait = false;
162
- let timeout;
163
- let cancelled = false;
164
- return [
165
- (...args) => {
166
- if (cancelled)
167
- return void 0;
168
- if (wait)
169
- return void 0;
170
- const val = fn(...args);
171
- wait = true;
172
- timeout = window.setTimeout(() => {
173
- wait = false;
174
- }, delay);
175
- return val;
176
- },
177
- () => {
178
- cancelled = true;
179
- clearTimeout(timeout);
180
- }
181
- ];
182
- };
183
-
184
- // src/lib/tracking.ts
185
- function sendEvent(client, eventName, data, debug) {
186
- const payload = {
187
- n: eventName,
188
- u: data.url,
189
- usr: data.userId,
190
- d: data.domain,
191
- ua: data.userAgent,
192
- w: data.deviceWidth,
193
- vid: (data == null ? void 0 : data.videoId) || void 0,
194
- vt: data.title,
195
- vdur: (data == null ? void 0 : data.videoDuration) || void 0,
196
- time: (data == null ? void 0 : data.currentTime) || void 0
197
- };
198
- if (debug)
199
- console.log(`Bold SDK - Logging event '${eventName}'`, payload);
200
- client.post("/event", payload);
201
- }
202
- var [throttledSendEvent] = throttle(sendEvent, 5e3);
203
- function trackEvent(client, userId, options) {
204
- return (video, event) => {
205
- var _a;
206
- const eventDetails = __spreadProps(__spreadValues({}, basicInfos()), {
207
- userId,
208
- videoId: video.id,
209
- title: video.title,
210
- videoDuration: video.duration,
211
- currentTime: ((_a = event.target) == null ? void 0 : _a.currentTime) || 0
212
- });
213
- if (event.type == "timeupdate" || event.type == "time-update") {
214
- throttledSendEvent(
215
- client,
216
- getEventName(event),
217
- eventDetails,
218
- options.debug
219
- );
220
- } else {
221
- sendEvent(client, getEventName(event), eventDetails, options.debug);
222
- }
223
- };
224
- }
225
- function trackPageView(client, userId, options) {
226
- return (title) => {
227
- const eventDetails = __spreadProps(__spreadValues({}, basicInfos()), {
228
- userId,
229
- title
230
- });
231
- sendEvent(client, "page_view", eventDetails, options.debug);
232
- };
233
- }
234
- function getEventName(event) {
235
- switch (event.type) {
236
- case "pause":
237
- return "video_pause";
238
- case "play":
239
- return "video_resume";
240
- case "loadedmetadata":
241
- case "loaded-metadata":
242
- return "video_load";
243
- case "time-update":
244
- case "timeupdate":
245
- return "video_progress";
246
- default:
247
- return "unknown_event";
248
- }
249
- }
250
- function basicInfos() {
251
- return {
252
- url: location.href,
253
- domain: location.hostname,
254
- referrer: document.referrer || null,
255
- deviceWidth: window.innerWidth,
256
- userAgent: navigator.userAgent
257
- };
258
- }
259
-
260
- // src/lib/client.ts
261
- function createClient(apiKey, options = { debug: false }) {
262
- var _a;
263
- if (!apiKey || typeof apiKey !== "string") {
264
- throw new Error("API key is missing or invalid");
265
- }
266
- const { debug } = options;
267
- const apiClientOptions = {
268
- baseURL: (_a = options.baseURL) != null ? _a : "https://app.boldvideo.io/api/v1/",
269
- headers: {
270
- Authorization: apiKey
271
- }
272
- };
273
- let apiClient;
274
- try {
275
- apiClient = import_axios.default.create(apiClientOptions);
276
- } catch (error) {
277
- console.error("Error creating API client", error);
278
- throw error;
279
- }
280
- const userId = [...Array(30)].map(() => Math.random().toString(36)[2]).join("");
281
- return {
282
- settings: fetchSettings(apiClient),
283
- videos: {
284
- list: fetchVideos(apiClient),
285
- get: fetchVideo(apiClient),
286
- search: searchVideos(apiClient)
287
- },
288
- playlists: {
289
- list: fetchPlaylists(apiClient),
290
- get: fetchPlaylist(apiClient)
291
- },
292
- trackEvent: trackEvent(apiClient, userId, { debug }),
293
- trackPageView: trackPageView(apiClient, userId, { debug })
294
- };
295
- }
296
- // Annotate the CommonJS export names for ESM import in node:
297
- 0 && (module.exports = {
298
- createClient
299
- });
package/dist/index.d.ts DELETED
@@ -1,81 +0,0 @@
1
- type Video = {
2
- captions: string;
3
- captions_label: string;
4
- captions_lang: string;
5
- description: string | null;
6
- duration: number;
7
- id: string;
8
- imported_from: string | null;
9
- legacy_video_url: null | null;
10
- meta_data: [];
11
- playback_id: string;
12
- published_at: string;
13
- stream_url: string;
14
- teaser: string | null;
15
- thumbnail: string;
16
- title: string;
17
- transcription: string;
18
- type: string;
19
- };
20
- type Playlist = {
21
- description?: string;
22
- id: string;
23
- is_private: boolean;
24
- title: string;
25
- type: string;
26
- videos: Video[];
27
- };
28
- type MenuItem = {
29
- icon: string;
30
- is_ext: boolean;
31
- label: string;
32
- url: string;
33
- };
34
- type Settings = {
35
- featured_playlists: Playlist[];
36
- menu_items: MenuItem[];
37
- ai_avatar: string;
38
- ai_name: string;
39
- has_ai: boolean;
40
- meta_data: {
41
- channel_name: string;
42
- description: string;
43
- image: string;
44
- no_seo: boolean;
45
- title: string;
46
- title_suffix: string;
47
- };
48
- };
49
-
50
- type ClientOptions = {
51
- baseURL?: string;
52
- debug: boolean;
53
- };
54
- declare function createClient(apiKey: string, options?: ClientOptions): {
55
- settings: (videoLimit?: number) => Promise<{
56
- data: Settings;
57
- }>;
58
- videos: {
59
- list: (videoLimit?: number) => Promise<{
60
- data: Video[];
61
- }>;
62
- get: (id: string) => Promise<{
63
- data: Video;
64
- }>;
65
- search: (term: string) => Promise<{
66
- data: Video[];
67
- }>;
68
- };
69
- playlists: {
70
- list: () => Promise<{
71
- data: Playlist[];
72
- }>;
73
- get: (id: string) => Promise<{
74
- data: Playlist;
75
- }>;
76
- };
77
- trackEvent: (video: any, event: Event) => void;
78
- trackPageView: (title: string) => void;
79
- };
80
-
81
- export { MenuItem, Playlist, Settings, Video, createClient };
package/dist/index.js DELETED
@@ -1,265 +0,0 @@
1
- var __defProp = Object.defineProperty;
2
- var __defProps = Object.defineProperties;
3
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
- var __spreadValues = (a, b) => {
9
- for (var prop in b || (b = {}))
10
- if (__hasOwnProp.call(b, prop))
11
- __defNormalProp(a, prop, b[prop]);
12
- if (__getOwnPropSymbols)
13
- for (var prop of __getOwnPropSymbols(b)) {
14
- if (__propIsEnum.call(b, prop))
15
- __defNormalProp(a, prop, b[prop]);
16
- }
17
- return a;
18
- };
19
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
- var __async = (__this, __arguments, generator) => {
21
- return new Promise((resolve, reject) => {
22
- var fulfilled = (value) => {
23
- try {
24
- step(generator.next(value));
25
- } catch (e) {
26
- reject(e);
27
- }
28
- };
29
- var rejected = (value) => {
30
- try {
31
- step(generator.throw(value));
32
- } catch (e) {
33
- reject(e);
34
- }
35
- };
36
- var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
37
- step((generator = generator.apply(__this, __arguments)).next());
38
- });
39
- };
40
-
41
- // src/lib/client.ts
42
- import axios from "axios";
43
-
44
- // src/lib/fetchers.ts
45
- function get(client, url) {
46
- return __async(this, null, function* () {
47
- try {
48
- const res = yield client.get(url);
49
- if (res.status !== 200) {
50
- throw new Error(`Unexpected response status: ${res.status}`);
51
- }
52
- return res.data;
53
- } catch (error) {
54
- console.error(`Error fetching data from URL: ${url}`, error);
55
- throw error;
56
- }
57
- });
58
- }
59
- function fetchSettings(client) {
60
- return (videoLimit = 12) => __async(this, null, function* () {
61
- try {
62
- return yield get(
63
- client,
64
- `settings?limit=${videoLimit}`
65
- );
66
- } catch (error) {
67
- console.error(`Error fetching settings with limit: ${videoLimit}`, error);
68
- throw error;
69
- }
70
- });
71
- }
72
- function fetchVideos(client) {
73
- return (videoLimit = 12) => __async(this, null, function* () {
74
- try {
75
- return yield get(
76
- client,
77
- `videos/latest?limit=${videoLimit}`
78
- );
79
- } catch (error) {
80
- console.error(`Error fetching videos with limit: ${videoLimit}`, error);
81
- throw error;
82
- }
83
- });
84
- }
85
- function searchVideos(client) {
86
- return (term) => __async(this, null, function* () {
87
- try {
88
- return yield get(client, `videos?query=${term}`);
89
- } catch (error) {
90
- console.error(`Error searching for videos with term: ${term}`, error);
91
- throw error;
92
- }
93
- });
94
- }
95
- function fetchVideo(client) {
96
- return (id) => __async(this, null, function* () {
97
- try {
98
- return yield get(client, `videos/${id}`);
99
- } catch (error) {
100
- console.error(`Error fetching video with ID: ${id}`, error);
101
- throw error;
102
- }
103
- });
104
- }
105
- function fetchPlaylists(client) {
106
- return () => __async(this, null, function* () {
107
- try {
108
- return yield get(client, "playlists");
109
- } catch (error) {
110
- console.error("Error fetching playlists", error);
111
- throw error;
112
- }
113
- });
114
- }
115
- function fetchPlaylist(client) {
116
- return (id) => __async(this, null, function* () {
117
- try {
118
- return yield get(client, `playlists/${id}`);
119
- } catch (error) {
120
- console.error(`Error fetching playlist with ID: ${id}`, error);
121
- throw error;
122
- }
123
- });
124
- }
125
-
126
- // src/util/throttle.ts
127
- var throttle = (fn, delay) => {
128
- let wait = false;
129
- let timeout;
130
- let cancelled = false;
131
- return [
132
- (...args) => {
133
- if (cancelled)
134
- return void 0;
135
- if (wait)
136
- return void 0;
137
- const val = fn(...args);
138
- wait = true;
139
- timeout = window.setTimeout(() => {
140
- wait = false;
141
- }, delay);
142
- return val;
143
- },
144
- () => {
145
- cancelled = true;
146
- clearTimeout(timeout);
147
- }
148
- ];
149
- };
150
-
151
- // src/lib/tracking.ts
152
- function sendEvent(client, eventName, data, debug) {
153
- const payload = {
154
- n: eventName,
155
- u: data.url,
156
- usr: data.userId,
157
- d: data.domain,
158
- ua: data.userAgent,
159
- w: data.deviceWidth,
160
- vid: (data == null ? void 0 : data.videoId) || void 0,
161
- vt: data.title,
162
- vdur: (data == null ? void 0 : data.videoDuration) || void 0,
163
- time: (data == null ? void 0 : data.currentTime) || void 0
164
- };
165
- if (debug)
166
- console.log(`Bold SDK - Logging event '${eventName}'`, payload);
167
- client.post("/event", payload);
168
- }
169
- var [throttledSendEvent] = throttle(sendEvent, 5e3);
170
- function trackEvent(client, userId, options) {
171
- return (video, event) => {
172
- var _a;
173
- const eventDetails = __spreadProps(__spreadValues({}, basicInfos()), {
174
- userId,
175
- videoId: video.id,
176
- title: video.title,
177
- videoDuration: video.duration,
178
- currentTime: ((_a = event.target) == null ? void 0 : _a.currentTime) || 0
179
- });
180
- if (event.type == "timeupdate" || event.type == "time-update") {
181
- throttledSendEvent(
182
- client,
183
- getEventName(event),
184
- eventDetails,
185
- options.debug
186
- );
187
- } else {
188
- sendEvent(client, getEventName(event), eventDetails, options.debug);
189
- }
190
- };
191
- }
192
- function trackPageView(client, userId, options) {
193
- return (title) => {
194
- const eventDetails = __spreadProps(__spreadValues({}, basicInfos()), {
195
- userId,
196
- title
197
- });
198
- sendEvent(client, "page_view", eventDetails, options.debug);
199
- };
200
- }
201
- function getEventName(event) {
202
- switch (event.type) {
203
- case "pause":
204
- return "video_pause";
205
- case "play":
206
- return "video_resume";
207
- case "loadedmetadata":
208
- case "loaded-metadata":
209
- return "video_load";
210
- case "time-update":
211
- case "timeupdate":
212
- return "video_progress";
213
- default:
214
- return "unknown_event";
215
- }
216
- }
217
- function basicInfos() {
218
- return {
219
- url: location.href,
220
- domain: location.hostname,
221
- referrer: document.referrer || null,
222
- deviceWidth: window.innerWidth,
223
- userAgent: navigator.userAgent
224
- };
225
- }
226
-
227
- // src/lib/client.ts
228
- function createClient(apiKey, options = { debug: false }) {
229
- var _a;
230
- if (!apiKey || typeof apiKey !== "string") {
231
- throw new Error("API key is missing or invalid");
232
- }
233
- const { debug } = options;
234
- const apiClientOptions = {
235
- baseURL: (_a = options.baseURL) != null ? _a : "https://app.boldvideo.io/api/v1/",
236
- headers: {
237
- Authorization: apiKey
238
- }
239
- };
240
- let apiClient;
241
- try {
242
- apiClient = axios.create(apiClientOptions);
243
- } catch (error) {
244
- console.error("Error creating API client", error);
245
- throw error;
246
- }
247
- const userId = [...Array(30)].map(() => Math.random().toString(36)[2]).join("");
248
- return {
249
- settings: fetchSettings(apiClient),
250
- videos: {
251
- list: fetchVideos(apiClient),
252
- get: fetchVideo(apiClient),
253
- search: searchVideos(apiClient)
254
- },
255
- playlists: {
256
- list: fetchPlaylists(apiClient),
257
- get: fetchPlaylist(apiClient)
258
- },
259
- trackEvent: trackEvent(apiClient, userId, { debug }),
260
- trackPageView: trackPageView(apiClient, userId, { debug })
261
- };
262
- }
263
- export {
264
- createClient
265
- };