@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.
- package/.github/dependabot.yml +11 -0
- package/.github/workflows/changeset-release.yml +51 -0
- package/.github/workflows/ci.yml +90 -0
- package/.github/workflows/release.yml +83 -0
- package/CHANGELOG.md +34 -0
- package/CONTRIBUTING.md +103 -0
- package/README.md +23 -0
- package/SECURITY.md +66 -0
- package/package.json +15 -6
- package/src/index.ts +21 -1
- package/src/lib/types.ts +170 -4
- package/.claude/settings.local.json +0 -9
- package/dist/index.cjs +0 -299
- package/dist/index.d.ts +0 -81
- package/dist/index.js +0 -265
|
@@ -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
|
package/CONTRIBUTING.md
ADDED
|
@@ -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
|
+
"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
|
-
"
|
|
10
|
-
"
|
|
11
|
-
|
|
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
|
-
"
|
|
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
|
|
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:
|
|
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
|
};
|
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
|
-
};
|