@jaaq/jaaq-sdk-js 1.1.1 → 1.2.0-dev-ec79f7e-20260605

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +18 -7
  2. package/dist/embed/embed-collection.html +17 -4
  3. package/dist/embed/embed.html +15 -3
  4. package/dist/index.cjs +57 -11
  5. package/dist/index.cjs.map +1 -1
  6. package/dist/index.d.ts +100 -24
  7. package/dist/index.mjs +56 -12
  8. package/dist/index.mjs.map +1 -1
  9. package/dist/jaaq-sdk.min.js +1 -1
  10. package/dist/jaaq-sdk.min.js.map +1 -1
  11. package/dist/ui/index.cjs +102 -17
  12. package/dist/ui/index.cjs.map +1 -1
  13. package/dist/ui/index.d.ts +89 -10
  14. package/dist/ui/index.mjs +102 -17
  15. package/dist/ui/index.mjs.map +1 -1
  16. package/dist/ui/jaaq-ui-bundled.min.js +2 -2
  17. package/dist/ui/jaaq-ui-bundled.min.js.map +1 -1
  18. package/dist/ui/jaaq-ui.min.js +2 -2
  19. package/dist/ui/jaaq-ui.min.js.map +1 -1
  20. package/dist/ui/react/index.cjs +78 -18
  21. package/dist/ui/react/index.cjs.map +1 -1
  22. package/dist/ui/react/index.d.ts +84 -7
  23. package/dist/ui/react/index.mjs +78 -18
  24. package/dist/ui/react/index.mjs.map +1 -1
  25. package/dist/ui/react/jaaq-ui-react.min.js +2 -2
  26. package/dist/ui/react/jaaq-ui-react.min.js.map +1 -1
  27. package/dist/ui/vanilla/index.cjs +102 -17
  28. package/dist/ui/vanilla/index.cjs.map +1 -1
  29. package/dist/ui/vanilla/index.d.ts +89 -10
  30. package/dist/ui/vanilla/index.mjs +102 -17
  31. package/dist/ui/vanilla/index.mjs.map +1 -1
  32. package/dist/ui/vanilla/jaaq-vanilla-bundled.min.js +2 -2
  33. package/dist/ui/vanilla/jaaq-vanilla-bundled.min.js.map +1 -1
  34. package/dist/ui/vanilla/jaaq-vanilla.min.js +2 -2
  35. package/dist/ui/vanilla/jaaq-vanilla.min.js.map +1 -1
  36. package/dist/ui/webcomponents/index.cjs +74 -14
  37. package/dist/ui/webcomponents/index.cjs.map +1 -1
  38. package/dist/ui/webcomponents/index.d.ts +86 -9
  39. package/dist/ui/webcomponents/index.mjs +74 -14
  40. package/dist/ui/webcomponents/index.mjs.map +1 -1
  41. package/dist/ui/webcomponents/jaaq-webcomponents-bundled.min.js +2 -2
  42. package/dist/ui/webcomponents/jaaq-webcomponents-bundled.min.js.map +1 -1
  43. package/dist/ui/webcomponents/jaaq-webcomponents.min.js +2 -2
  44. package/dist/ui/webcomponents/jaaq-webcomponents.min.js.map +1 -1
  45. package/package.json +38 -35
@@ -28,6 +28,61 @@ type CollectionDTO = {
28
28
  videos: VideoDTO[];
29
29
  };
30
30
 
31
+ type CreatorV2DTO = {
32
+ id: string;
33
+ name: string;
34
+ biography: string;
35
+ imageUrl: string;
36
+ type: string;
37
+ };
38
+
39
+ type CtaV2DTO = {
40
+ url?: string;
41
+ label?: string;
42
+ labelColor?: string;
43
+ };
44
+
45
+ type SubtitleV2DTO = {
46
+ code: string;
47
+ url: string;
48
+ default?: boolean;
49
+ };
50
+
51
+ type VideoV2DTO = {
52
+ id: string;
53
+ videoId: string;
54
+ question: string;
55
+ transcription: string;
56
+ subtitles: SubtitleV2DTO[];
57
+ videoUrl: string;
58
+ tags: string[];
59
+ severity: number | null;
60
+ duration: number;
61
+ description: string;
62
+ creator?: CreatorV2DTO;
63
+ cta?: CtaV2DTO;
64
+ allowFeedbackWidget?: boolean;
65
+ };
66
+
67
+ type VideoGroupV2DTO = {
68
+ id: string;
69
+ title: string;
70
+ videos: VideoV2DTO[];
71
+ };
72
+
73
+ type CollectionV2DTO = {
74
+ id: string;
75
+ name: string;
76
+ description: string;
77
+ imageUrl: string;
78
+ idleVideo: {
79
+ id: string;
80
+ duration: number;
81
+ videoUrl: string;
82
+ } | null;
83
+ videoGroups: VideoGroupV2DTO[];
84
+ };
85
+
31
86
  type FetchLike = typeof globalThis.fetch;
32
87
  type RequestOptions = Parameters<typeof globalThis.fetch>[1];
33
88
  interface HttpClient {
@@ -47,28 +102,47 @@ type CollectionsResource = {
47
102
  getById(_id: string): Promise<CollectionDTO>;
48
103
  };
49
104
 
105
+ type VideosResourceV2 = {
106
+ getById(_id: string): Promise<VideoV2DTO>;
107
+ };
108
+
109
+ type CollectionsResourceV2 = {
110
+ list(): Promise<CollectionV2DTO[]>;
111
+ getById(_id: string): Promise<CollectionV2DTO>;
112
+ };
113
+
50
114
  interface SDKConfig {
51
115
  baseUrl?: string;
116
+ apiVersion?: string;
52
117
  apiKey: string;
53
118
  clientId: string;
54
119
  fetch?: FetchLike;
55
120
  timeoutMs?: number;
56
121
  }
57
- declare class JaaqClient {
58
- readonly videos: VideosResource;
59
- readonly collections: CollectionsResource;
122
+ type V1 = {
123
+ videos: VideosResource;
124
+ collections: CollectionsResource;
125
+ };
126
+ type V2 = {
127
+ videos: VideosResourceV2;
128
+ collections: CollectionsResourceV2;
129
+ };
130
+ type ClientVersion = V1 | V2;
131
+ declare class JaaqClient<T extends ClientVersion = V1> {
132
+ readonly videos: T['videos'];
133
+ readonly collections: T['collections'];
60
134
  private constructor();
61
135
  /**
62
136
  * Public "friend" constructor that remains inside the class boundary.
63
137
  * This method is callable from the module-level build function
64
138
  * without exposing `new JaaqClient(...)` to consumers.
65
139
  */
66
- static fromHttp(http: HttpClient): JaaqClient;
140
+ static fromHttp<T extends ClientVersion = V1>(http: HttpClient, apiVersion: string): JaaqClient<T>;
67
141
  /**
68
142
  * OO-friendly static initializer.
69
143
  * Delegates to the single source of truth: `buildClient`.
70
144
  */
71
- static init(config: SDKConfig): JaaqClient;
145
+ static init<T extends ClientVersion = V1>(config: SDKConfig): JaaqClient<T>;
72
146
  }
73
147
 
74
148
  /**
@@ -85,6 +159,8 @@ type PlayerConfig = {
85
159
  client?: JaaqClient;
86
160
  /** Custom API base URL */
87
161
  baseUrl?: string;
162
+ /** Custom API version */
163
+ apiVersion?: string;
88
164
  /** Whether to automatically start playback when video loads */
89
165
  autoplay?: boolean;
90
166
  /** Whether to show player controls */
@@ -137,7 +213,7 @@ type PlayerState = {
137
213
  * Video settings that can be passed to carousel components
138
214
  * Excludes carousel-specific props that are handled separately
139
215
  */
140
- type VideoSettings = Omit<PlayerConfig, 'videoId' | 'apiKey' | 'clientId' | 'baseUrl' | 'client' | 'autoplay'>;
216
+ type VideoSettings = Omit<PlayerConfig, 'videoId' | 'apiKey' | 'clientId' | 'baseUrl' | 'apiVersion' | 'client' | 'autoplay'>;
141
217
 
142
218
  type VideoPlayerHandle = {
143
219
  play: () => void;
@@ -167,6 +243,7 @@ type CollectionPlayerProps = {
167
243
  subscriptionId?: string;
168
244
  client?: JaaqClient;
169
245
  baseUrl?: string;
246
+ apiVersion?: string;
170
247
  autoplay?: boolean;
171
248
  showArrows?: boolean;
172
249
  showDots?: boolean;
@@ -176,7 +253,7 @@ type CollectionPlayerProps = {
176
253
  onError?: (_error: Error) => void;
177
254
  onSlideChange?: (_data: {
178
255
  index: number;
179
- video: CollectionDTO['videos'][0];
256
+ video: CollectionDTO['videos'][0] | CollectionV2DTO['videoGroups'][0]['videos'][0];
180
257
  }) => void;
181
258
  };
182
259
  type CollectionPlayerHandle = {
@@ -11,16 +11,22 @@ async function parseJson(res) {
11
11
  return undefined;
12
12
  return res.json();
13
13
  }
14
- function joinUrl(baseUrl, clientId, path) {
14
+ function joinUrl(baseUrl, apiVersion, clientId, path) {
15
15
  // return path if it is an absolute URL
16
16
  if (/^https?:\/\//i.test(path))
17
17
  return path;
18
18
  const base = baseUrl.replace(/\/+$/, '');
19
19
  const relative = path.replace(/^\/+/, '');
20
- return `${base}/b2b/v1/subscription/${encodeURIComponent(clientId)}${relative.startsWith('/') ? relative : `/${relative}`}`;
20
+ return `${base}/b2b/${apiVersion}/subscription/${encodeURIComponent(clientId)}${relative.startsWith('/') ? relative : `/${relative}`}`;
21
+ }
22
+ function convertToValidAPIVersion(version) {
23
+ const v = version.toLowerCase();
24
+ if (v === 'v1' || v === 'v2')
25
+ return v;
26
+ return 'v1'; // default to v1 if invalid version provided
21
27
  }
22
28
  function createHttpClient(config) {
23
- const { baseUrl, apiKey, clientId, fetch: fetchImpl } = config;
29
+ const { baseUrl, apiKey, clientId, fetch: fetchImpl, apiVersion } = config;
24
30
  const f = fetchImpl ?? globalThis.fetch;
25
31
  if (!f) {
26
32
  throw new Error('No fetch implementation found. Provide one in SDKConfig.fetch for Node or custom environments.');
@@ -29,7 +35,7 @@ function createHttpClient(config) {
29
35
  'Content-Type': 'application/json',
30
36
  'x-api-key': apiKey,
31
37
  };
32
- const fullUrl = (path) => joinUrl(baseUrl, clientId, path);
38
+ const fullUrl = (path) => joinUrl(baseUrl, convertToValidAPIVersion(apiVersion), clientId, path);
33
39
  const request = async (method, path, init, body) => {
34
40
  const reqInit = {
35
41
  method,
@@ -78,20 +84,51 @@ function createCollectionsResource(http) {
78
84
  };
79
85
  }
80
86
 
87
+ function createVideosResourceV2(http) {
88
+ return {
89
+ async getById(id) {
90
+ const path = `/videos/${encodeURIComponent(id)}`;
91
+ const response = await http.get(path);
92
+ return response.video;
93
+ },
94
+ };
95
+ }
96
+
97
+ function createCollectionsResourceV2(http) {
98
+ return {
99
+ async list() {
100
+ const path = '/collections';
101
+ const response = await http.get(path);
102
+ return response.collections;
103
+ },
104
+ async getById(id) {
105
+ const path = `/collections/${encodeURIComponent(id)}`;
106
+ const response = await http.get(path);
107
+ return response.collection;
108
+ },
109
+ };
110
+ }
111
+
81
112
  const BASE_URL = "https://api.jaaq.app";
82
113
  class JaaqClient {
83
114
  // Keep constructor private to enforce controlled instantiation.
84
- constructor(http) {
85
- this.videos = createVideosResource(http);
86
- this.collections = createCollectionsResource(http);
115
+ constructor(http, apiVersion) {
116
+ if (apiVersion === 'v2') {
117
+ this.videos = createVideosResourceV2(http);
118
+ this.collections = createCollectionsResourceV2(http);
119
+ }
120
+ else {
121
+ this.videos = createVideosResource(http);
122
+ this.collections = createCollectionsResource(http);
123
+ }
87
124
  }
88
125
  /**
89
126
  * Public "friend" constructor that remains inside the class boundary.
90
127
  * This method is callable from the module-level build function
91
128
  * without exposing `new JaaqClient(...)` to consumers.
92
129
  */
93
- static fromHttp(http) {
94
- return new JaaqClient(http);
130
+ static fromHttp(http, apiVersion) {
131
+ return new JaaqClient(http, apiVersion);
95
132
  }
96
133
  /**
97
134
  * OO-friendly static initializer.
@@ -114,14 +151,15 @@ function createJaaqClient(config) {
114
151
  * The constructor stays private; instantiation is funneled via `JaaqClient.fromHttp`.
115
152
  */
116
153
  function buildClient(config) {
117
- const { baseUrl = BASE_URL, apiKey, clientId, fetch: fetchImpl } = config;
154
+ const { baseUrl = BASE_URL, apiKey, clientId, fetch: fetchImpl, apiVersion = 'v1' } = config;
118
155
  const http = createHttpClient({
119
156
  baseUrl,
120
157
  apiKey,
121
158
  clientId,
122
159
  fetch: fetchImpl ?? globalThis.fetch,
160
+ apiVersion,
123
161
  });
124
- return JaaqClient.fromHttp(http);
162
+ return JaaqClient.fromHttp(http, apiVersion);
125
163
  }
126
164
 
127
165
  /**
@@ -992,6 +1030,7 @@ class JaaqVideoPlayerElement extends HTMLElement {
992
1030
  const apiKey = this.getAttribute('api-key');
993
1031
  const clientId = this.getAttribute('client-id');
994
1032
  const baseUrl = this.getAttribute('base-url') || undefined;
1033
+ const apiVersion = this.getAttribute('api-version') || undefined;
995
1034
  const autoplay = this.hasAttribute('autoplay') && this.getAttribute('autoplay') !== 'false';
996
1035
  const controls = !this.hasAttribute('controls') || this.getAttribute('controls') !== 'false';
997
1036
  const showLogo = !this.hasAttribute('show-logo') || this.getAttribute('show-logo') !== 'false';
@@ -1011,6 +1050,7 @@ class JaaqVideoPlayerElement extends HTMLElement {
1011
1050
  clientId: clientId ?? undefined,
1012
1051
  client: this.clientInstance || undefined,
1013
1052
  baseUrl,
1053
+ apiVersion,
1014
1054
  autoplay,
1015
1055
  controls,
1016
1056
  showLogo,
@@ -4388,6 +4428,21 @@ class JaaqCollectionPlayerElement extends HTMLElement {
4388
4428
  return defaultValue;
4389
4429
  return v !== 'false';
4390
4430
  }
4431
+ getVideosFromCollection(collection) {
4432
+ if (collection.videos && collection.videos.length > 0) {
4433
+ return collection.videos;
4434
+ }
4435
+ if (collection.videoGroups && collection.videoGroups.length > 0) {
4436
+ const videos = [];
4437
+ collection.videoGroups.forEach((group) => {
4438
+ if (group.videos && group.videos.length > 0) {
4439
+ videos.push(...group.videos);
4440
+ }
4441
+ });
4442
+ return videos;
4443
+ }
4444
+ return [];
4445
+ }
4391
4446
  render() {
4392
4447
  if (!this.shadowRoot)
4393
4448
  return;
@@ -4414,6 +4469,7 @@ class JaaqCollectionPlayerElement extends HTMLElement {
4414
4469
  const apiKey = this.getAttribute('api-key');
4415
4470
  const clientId = this.getAttribute('client-id');
4416
4471
  const baseUrl = this.getAttribute('base-url') || undefined;
4472
+ const apiVersion = this.getAttribute('api-version') || undefined;
4417
4473
  if (!this.clientInstance && !apiKey && !clientId) {
4418
4474
  this.emitError(new Error('Either client property or api-key and client-id attributes are required'));
4419
4475
  return;
@@ -4425,9 +4481,11 @@ class JaaqCollectionPlayerElement extends HTMLElement {
4425
4481
  apiKey: apiKey,
4426
4482
  clientId: clientId,
4427
4483
  baseUrl: baseUrl || BASE_URL,
4484
+ apiVersion: apiVersion,
4428
4485
  });
4429
4486
  this.collectionData = await client.collections.getById(collectionId);
4430
- if (!this.collectionData.videos || this.collectionData.videos.length === 0) {
4487
+ const videos = this.getVideosFromCollection(this.collectionData);
4488
+ if (videos.length === 0) {
4431
4489
  this.emitError(new Error('No videos found in collection'));
4432
4490
  return;
4433
4491
  }
@@ -4475,7 +4533,8 @@ class JaaqCollectionPlayerElement extends HTMLElement {
4475
4533
  console.warn('[CollectionPlayer] Failed to parse video-settings attribute', e);
4476
4534
  }
4477
4535
  }
4478
- this.collectionData.videos.forEach((video) => {
4536
+ const videos = this.getVideosFromCollection(this.collectionData);
4537
+ videos.forEach((video) => {
4479
4538
  const slide = document.createElement('li');
4480
4539
  slide.className = 'splide__slide';
4481
4540
  const player = document.createElement('jaaq-video-player');
@@ -4557,8 +4616,9 @@ class JaaqCollectionPlayerElement extends HTMLElement {
4557
4616
  Components: this.splide?.Components,
4558
4617
  });
4559
4618
  this.handleSlideChange(newIndex);
4619
+ const videos = this.collectionData ? this.getVideosFromCollection(this.collectionData) : [];
4560
4620
  this.dispatchEvent(new CustomEvent('jaaq:collection:slidechange', {
4561
- detail: { index: newIndex, video: this.collectionData?.videos[newIndex] },
4621
+ detail: { index: newIndex, video: videos[newIndex] },
4562
4622
  bubbles: true,
4563
4623
  composed: true,
4564
4624
  }));
@@ -4734,7 +4794,7 @@ if (typeof window !== 'undefined' && typeof document !== 'undefined') {
4734
4794
  if (typeof window !== 'undefined') {
4735
4795
  registerJaaqComponents();
4736
4796
  }
4737
- function VideoPlayerComponent({ videoId, apiKey, clientId, client, baseUrl, autoplay = false, controls = true, width = '100%', height = 'auto', className = '', showLogo = true, showTitle = true, showAuthor = true, showDescription = true, showCaptions = true, startMuted = false, onPlay, onPause, onError, onLoaded, onTimeUpdate, onVolumeChange, onEnded, onFullscreenChange, showInfo = false, }, ref) {
4797
+ function VideoPlayerComponent({ videoId, apiKey, clientId, client, baseUrl, apiVersion, autoplay = false, controls = true, width = '100%', height = 'auto', className = '', showLogo = true, showTitle = true, showAuthor = true, showDescription = true, showCaptions = true, startMuted = false, onPlay, onPause, onError, onLoaded, onTimeUpdate, onVolumeChange, onEnded, onFullscreenChange, showInfo = false, }, ref) {
4738
4798
  const playerRef = useRef(null);
4739
4799
  const videoDataRef = useRef(null);
4740
4800
  useImperativeHandle(ref, () => ({
@@ -4803,7 +4863,7 @@ function VideoPlayerComponent({ videoId, apiKey, clientId, client, baseUrl, auto
4803
4863
  player.setAttribute('start-muted', startMuted ? 'true' : 'false');
4804
4864
  }, [startMuted]);
4805
4865
  return (React.createElement("div", { style: { width, height }, className: className },
4806
- React.createElement("jaaq-video-player", { ref: playerRef, "video-id": videoId, "api-key": apiKey, "client-id": clientId, "base-url": baseUrl, autoplay: autoplay ? 'true' : 'false', controls: controls ? 'true' : 'false', "show-logo": showLogo ? 'true' : 'false', "show-title": showTitle ? 'true' : 'false', "show-author": showAuthor ? 'true' : 'false', "show-description": showDescription ? 'true' : 'false', "show-captions": showCaptions ? 'true' : 'false', "start-muted": startMuted ? 'true' : 'false', width: "100%", height: "auto" }),
4866
+ React.createElement("jaaq-video-player", { ref: playerRef, "video-id": videoId, "api-key": apiKey, "client-id": clientId, "base-url": baseUrl, "api-version": apiVersion, autoplay: autoplay ? 'true' : 'false', controls: controls ? 'true' : 'false', "show-logo": showLogo ? 'true' : 'false', "show-title": showTitle ? 'true' : 'false', "show-author": showAuthor ? 'true' : 'false', "show-description": showDescription ? 'true' : 'false', "show-captions": showCaptions ? 'true' : 'false', "start-muted": startMuted ? 'true' : 'false', width: "100%", height: "auto" }),
4807
4867
  showInfo && videoDataRef.current && (React.createElement("div", { className: "jaaq-video-info", style: { marginTop: '16px', padding: '16px', background: '#f8f9fa', borderRadius: '8px' } },
4808
4868
  React.createElement("h3", { style: { margin: '0 0 12px 0', fontSize: '18px' } }, videoDataRef.current.question || videoDataRef.current.description || 'Untitled Video'),
4809
4869
  React.createElement("p", { style: { margin: '0 0 8px 0' } },
@@ -4822,7 +4882,7 @@ const VideoPlayer = forwardRef(VideoPlayerComponent);
4822
4882
  if (typeof window !== 'undefined') {
4823
4883
  registerJaaqComponents();
4824
4884
  }
4825
- function CollectionPlayerComponent({ collectionId, apiKey, clientId, subscriptionId, client, baseUrl, autoplay = false, showArrows = true, showDots = true, className = '', videoSettings, onLoaded, onError, onSlideChange, }, ref) {
4885
+ function CollectionPlayerComponent({ collectionId, apiKey, clientId, subscriptionId, client, baseUrl, apiVersion, autoplay = false, showArrows = true, showDots = true, className = '', videoSettings, onLoaded, onError, onSlideChange, }, ref) {
4826
4886
  const playerRef = useRef(null);
4827
4887
  useImperativeHandle(ref, () => ({
4828
4888
  refresh: () => playerRef.current?.refresh(),
@@ -4867,7 +4927,7 @@ function CollectionPlayerComponent({ collectionId, apiKey, clientId, subscriptio
4867
4927
  };
4868
4928
  }, [client, videoSettings, onLoaded, onError, onSlideChange]);
4869
4929
  return (React.createElement("div", { className: className },
4870
- React.createElement("jaaq-collection-player", { ref: playerRef, "collection-id": collectionId, "api-key": apiKey, "client-id": clientId, "subscription-id": subscriptionId, "base-url": baseUrl, autoplay: autoplay ? 'true' : 'false', "show-arrows": showArrows ? 'true' : 'false', "show-dots": showDots ? 'true' : 'false' })));
4930
+ React.createElement("jaaq-collection-player", { ref: playerRef, "collection-id": collectionId, "api-key": apiKey, "client-id": clientId, "subscription-id": subscriptionId, "base-url": baseUrl, "api-version": apiVersion, autoplay: autoplay ? 'true' : 'false', "show-arrows": showArrows ? 'true' : 'false', "show-dots": showDots ? 'true' : 'false' })));
4871
4931
  }
4872
4932
  CollectionPlayerComponent.displayName = 'CollectionPlayer';
4873
4933
  const CollectionPlayer = forwardRef(CollectionPlayerComponent);