@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
@@ -27,10 +27,6 @@ type VideoDTO = {
27
27
  creatorBiography?: string;
28
28
  };
29
29
 
30
- type VideosResource = {
31
- getById(_id: string): Promise<VideoDTO>;
32
- };
33
-
34
30
  type CollectionDTO = {
35
31
  id: string;
36
32
  name: string;
@@ -40,33 +36,111 @@ type CollectionDTO = {
40
36
  videos: VideoDTO[];
41
37
  };
42
38
 
39
+ type CreatorV2DTO = {
40
+ id: string;
41
+ name: string;
42
+ biography: string;
43
+ imageUrl: string;
44
+ type: string;
45
+ };
46
+
47
+ type CtaV2DTO = {
48
+ url?: string;
49
+ label?: string;
50
+ labelColor?: string;
51
+ };
52
+
53
+ type SubtitleV2DTO = {
54
+ code: string;
55
+ url: string;
56
+ default?: boolean;
57
+ };
58
+
59
+ type VideoV2DTO = {
60
+ id: string;
61
+ videoId: string;
62
+ question: string;
63
+ transcription: string;
64
+ subtitles: SubtitleV2DTO[];
65
+ videoUrl: string;
66
+ tags: string[];
67
+ severity: number | null;
68
+ duration: number;
69
+ description: string;
70
+ creator?: CreatorV2DTO;
71
+ cta?: CtaV2DTO;
72
+ allowFeedbackWidget?: boolean;
73
+ };
74
+
75
+ type VideoGroupV2DTO = {
76
+ id: string;
77
+ title: string;
78
+ videos: VideoV2DTO[];
79
+ };
80
+
81
+ type CollectionV2DTO = {
82
+ id: string;
83
+ name: string;
84
+ description: string;
85
+ imageUrl: string;
86
+ idleVideo: {
87
+ id: string;
88
+ duration: number;
89
+ videoUrl: string;
90
+ } | null;
91
+ videoGroups: VideoGroupV2DTO[];
92
+ };
93
+
94
+ type VideosResource = {
95
+ getById(_id: string): Promise<VideoDTO>;
96
+ };
97
+
43
98
  type CollectionsResource = {
44
99
  list(): Promise<CollectionDTO[]>;
45
100
  getById(_id: string): Promise<CollectionDTO>;
46
101
  };
47
102
 
103
+ type VideosResourceV2 = {
104
+ getById(_id: string): Promise<VideoV2DTO>;
105
+ };
106
+
107
+ type CollectionsResourceV2 = {
108
+ list(): Promise<CollectionV2DTO[]>;
109
+ getById(_id: string): Promise<CollectionV2DTO>;
110
+ };
111
+
48
112
  interface SDKConfig {
49
113
  baseUrl?: string;
114
+ apiVersion?: string;
50
115
  apiKey: string;
51
116
  clientId: string;
52
117
  fetch?: FetchLike;
53
118
  timeoutMs?: number;
54
119
  }
55
- declare class JaaqClient {
56
- readonly videos: VideosResource;
57
- readonly collections: CollectionsResource;
120
+ type V1 = {
121
+ videos: VideosResource;
122
+ collections: CollectionsResource;
123
+ };
124
+ type V2 = {
125
+ videos: VideosResourceV2;
126
+ collections: CollectionsResourceV2;
127
+ };
128
+ type ClientVersion = V1 | V2;
129
+ declare class JaaqClient<T extends ClientVersion = V1> {
130
+ readonly videos: T['videos'];
131
+ readonly collections: T['collections'];
58
132
  private constructor();
59
133
  /**
60
134
  * Public "friend" constructor that remains inside the class boundary.
61
135
  * This method is callable from the module-level build function
62
136
  * without exposing `new JaaqClient(...)` to consumers.
63
137
  */
64
- static fromHttp(http: HttpClient): JaaqClient;
138
+ static fromHttp<T extends ClientVersion = V1>(http: HttpClient, apiVersion: string): JaaqClient<T>;
65
139
  /**
66
140
  * OO-friendly static initializer.
67
141
  * Delegates to the single source of truth: `buildClient`.
68
142
  */
69
- static init(config: SDKConfig): JaaqClient;
143
+ static init<T extends ClientVersion = V1>(config: SDKConfig): JaaqClient<T>;
70
144
  }
71
145
 
72
146
  /**
@@ -83,6 +157,8 @@ type PlayerConfig = {
83
157
  client?: JaaqClient;
84
158
  /** Custom API base URL */
85
159
  baseUrl?: string;
160
+ /** Custom API version */
161
+ apiVersion?: string;
86
162
  /** Whether to automatically start playback when video loads */
87
163
  autoplay?: boolean;
88
164
  /** Whether to show player controls */
@@ -161,7 +237,7 @@ type PlayerEventCallback<T> = (_data: T) => void;
161
237
  * Video settings that can be passed to carousel components
162
238
  * Excludes carousel-specific props that are handled separately
163
239
  */
164
- type VideoSettings = Omit<PlayerConfig, 'videoId' | 'apiKey' | 'clientId' | 'baseUrl' | 'client' | 'autoplay'>;
240
+ type VideoSettings = Omit<PlayerConfig, 'videoId' | 'apiKey' | 'clientId' | 'baseUrl' | 'apiVersion' | 'client' | 'autoplay'>;
165
241
 
166
242
  declare class JaaqVideoPlayer {
167
243
  private container;
@@ -252,6 +328,7 @@ type CollectionPlayerConfig = {
252
328
  apiKey?: string;
253
329
  clientId?: string;
254
330
  baseUrl?: string;
331
+ apiVersion?: string;
255
332
  autoplay?: boolean;
256
333
  showArrows?: boolean;
257
334
  showDots?: boolean;
@@ -282,6 +359,7 @@ declare class JaaqCollectionPlayer {
282
359
  private render;
283
360
  private initCarousel;
284
361
  private showLoading;
362
+ private getVideosFromCollection;
285
363
  private renderCarousel;
286
364
  private initSplide;
287
365
  private handleSlideChange;
@@ -350,6 +428,7 @@ declare class JaaqCollectionPlayerElement extends HTMLElement {
350
428
  disconnectedCallback(): void;
351
429
  attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
352
430
  private getBooleanAttr;
431
+ private getVideosFromCollection;
353
432
  private render;
354
433
  private initCarousel;
355
434
  private showLoading;
package/dist/ui/index.mjs CHANGED
@@ -9,16 +9,22 @@ async function parseJson(res) {
9
9
  return undefined;
10
10
  return res.json();
11
11
  }
12
- function joinUrl(baseUrl, clientId, path) {
12
+ function joinUrl(baseUrl, apiVersion, clientId, path) {
13
13
  // return path if it is an absolute URL
14
14
  if (/^https?:\/\//i.test(path))
15
15
  return path;
16
16
  const base = baseUrl.replace(/\/+$/, '');
17
17
  const relative = path.replace(/^\/+/, '');
18
- return `${base}/b2b/v1/subscription/${encodeURIComponent(clientId)}${relative.startsWith('/') ? relative : `/${relative}`}`;
18
+ return `${base}/b2b/${apiVersion}/subscription/${encodeURIComponent(clientId)}${relative.startsWith('/') ? relative : `/${relative}`}`;
19
+ }
20
+ function convertToValidAPIVersion(version) {
21
+ const v = version.toLowerCase();
22
+ if (v === 'v1' || v === 'v2')
23
+ return v;
24
+ return 'v1'; // default to v1 if invalid version provided
19
25
  }
20
26
  function createHttpClient(config) {
21
- const { baseUrl, apiKey, clientId, fetch: fetchImpl } = config;
27
+ const { baseUrl, apiKey, clientId, fetch: fetchImpl, apiVersion } = config;
22
28
  const f = fetchImpl ?? globalThis.fetch;
23
29
  if (!f) {
24
30
  throw new Error('No fetch implementation found. Provide one in SDKConfig.fetch for Node or custom environments.');
@@ -27,7 +33,7 @@ function createHttpClient(config) {
27
33
  'Content-Type': 'application/json',
28
34
  'x-api-key': apiKey,
29
35
  };
30
- const fullUrl = (path) => joinUrl(baseUrl, clientId, path);
36
+ const fullUrl = (path) => joinUrl(baseUrl, convertToValidAPIVersion(apiVersion), clientId, path);
31
37
  const request = async (method, path, init, body) => {
32
38
  const reqInit = {
33
39
  method,
@@ -76,20 +82,51 @@ function createCollectionsResource(http) {
76
82
  };
77
83
  }
78
84
 
85
+ function createVideosResourceV2(http) {
86
+ return {
87
+ async getById(id) {
88
+ const path = `/videos/${encodeURIComponent(id)}`;
89
+ const response = await http.get(path);
90
+ return response.video;
91
+ },
92
+ };
93
+ }
94
+
95
+ function createCollectionsResourceV2(http) {
96
+ return {
97
+ async list() {
98
+ const path = '/collections';
99
+ const response = await http.get(path);
100
+ return response.collections;
101
+ },
102
+ async getById(id) {
103
+ const path = `/collections/${encodeURIComponent(id)}`;
104
+ const response = await http.get(path);
105
+ return response.collection;
106
+ },
107
+ };
108
+ }
109
+
79
110
  const BASE_URL = "https://api.jaaq.app";
80
111
  class JaaqClient {
81
112
  // Keep constructor private to enforce controlled instantiation.
82
- constructor(http) {
83
- this.videos = createVideosResource(http);
84
- this.collections = createCollectionsResource(http);
113
+ constructor(http, apiVersion) {
114
+ if (apiVersion === 'v2') {
115
+ this.videos = createVideosResourceV2(http);
116
+ this.collections = createCollectionsResourceV2(http);
117
+ }
118
+ else {
119
+ this.videos = createVideosResource(http);
120
+ this.collections = createCollectionsResource(http);
121
+ }
85
122
  }
86
123
  /**
87
124
  * Public "friend" constructor that remains inside the class boundary.
88
125
  * This method is callable from the module-level build function
89
126
  * without exposing `new JaaqClient(...)` to consumers.
90
127
  */
91
- static fromHttp(http) {
92
- return new JaaqClient(http);
128
+ static fromHttp(http, apiVersion) {
129
+ return new JaaqClient(http, apiVersion);
93
130
  }
94
131
  /**
95
132
  * OO-friendly static initializer.
@@ -112,14 +149,15 @@ function createJaaqClient(config) {
112
149
  * The constructor stays private; instantiation is funneled via `JaaqClient.fromHttp`.
113
150
  */
114
151
  function buildClient(config) {
115
- const { baseUrl = BASE_URL, apiKey, clientId, fetch: fetchImpl } = config;
152
+ const { baseUrl = BASE_URL, apiKey, clientId, fetch: fetchImpl, apiVersion = 'v1' } = config;
116
153
  const http = createHttpClient({
117
154
  baseUrl,
118
155
  apiKey,
119
156
  clientId,
120
157
  fetch: fetchImpl ?? globalThis.fetch,
158
+ apiVersion,
121
159
  });
122
- return JaaqClient.fromHttp(http);
160
+ return JaaqClient.fromHttp(http, apiVersion);
123
161
  }
124
162
 
125
163
  /**
@@ -4051,6 +4089,7 @@ class JaaqCollectionPlayer {
4051
4089
  apiKey: config.apiKey,
4052
4090
  clientId: config.clientId,
4053
4091
  baseUrl: config.baseUrl || BASE_URL,
4092
+ apiVersion: config.apiVersion,
4054
4093
  });
4055
4094
  }
4056
4095
  else {
@@ -4082,7 +4121,8 @@ class JaaqCollectionPlayer {
4082
4121
  throw new Error('Client is not initialized');
4083
4122
  }
4084
4123
  this.collectionData = await this.client.collections.getById(collectionId);
4085
- if (!this.collectionData.videos || this.collectionData.videos.length === 0) {
4124
+ const videos = this.getVideosFromCollection(this.collectionData);
4125
+ if (videos.length === 0) {
4086
4126
  this.emitError(new Error('No videos found in collection'));
4087
4127
  return;
4088
4128
  }
@@ -4103,6 +4143,21 @@ class JaaqCollectionPlayer {
4103
4143
  </div>
4104
4144
  `;
4105
4145
  }
4146
+ getVideosFromCollection(collection) {
4147
+ if (collection.videos && collection.videos.length > 0) {
4148
+ return collection.videos;
4149
+ }
4150
+ if (collection.videoGroups && collection.videoGroups.length > 0) {
4151
+ const videos = [];
4152
+ collection.videoGroups.forEach((group) => {
4153
+ if (group.videos && group.videos.length > 0) {
4154
+ videos.push(...group.videos);
4155
+ }
4156
+ });
4157
+ return videos;
4158
+ }
4159
+ return [];
4160
+ }
4106
4161
  renderCarousel() {
4107
4162
  if (!this.playerElement || !this.collectionData)
4108
4163
  return;
@@ -4113,7 +4168,8 @@ class JaaqCollectionPlayer {
4113
4168
  track.className = 'splide__track';
4114
4169
  const list = document.createElement('ul');
4115
4170
  list.className = 'splide__list';
4116
- this.collectionData.videos.forEach((video) => {
4171
+ const videos = this.getVideosFromCollection(this.collectionData);
4172
+ videos.forEach((video) => {
4117
4173
  const slide = document.createElement('li');
4118
4174
  slide.className = 'splide__slide';
4119
4175
  const player = document.createElement('jaaq-video-player');
@@ -4124,6 +4180,8 @@ class JaaqCollectionPlayer {
4124
4180
  player.setAttribute('client-id', this.config.clientId);
4125
4181
  if (this.config.baseUrl)
4126
4182
  player.setAttribute('base-url', this.config.baseUrl);
4183
+ if (this.config.apiVersion)
4184
+ player.setAttribute('api-version', this.config.apiVersion);
4127
4185
  player.setAttribute('autoplay', 'false');
4128
4186
  player.setAttribute('width', '100%');
4129
4187
  if (this.config.videoSettings) {
@@ -4193,7 +4251,8 @@ class JaaqCollectionPlayer {
4193
4251
  this.splide.on('moved', (newIndex) => {
4194
4252
  this.handleSlideChange(newIndex);
4195
4253
  if (this.collectionData) {
4196
- this.emit('slidechange', { index: newIndex, video: this.collectionData.videos[newIndex] });
4254
+ const videos = this.getVideosFromCollection(this.collectionData);
4255
+ this.emit('slidechange', { index: newIndex, video: videos[newIndex] });
4197
4256
  }
4198
4257
  });
4199
4258
  this.splide.mount();
@@ -4338,6 +4397,10 @@ function parseDataAttributes(element) {
4338
4397
  if (baseUrl) {
4339
4398
  config.baseUrl = baseUrl;
4340
4399
  }
4400
+ const apiVersion = element.getAttribute('data-api-version');
4401
+ if (apiVersion) {
4402
+ config.apiVersion = apiVersion;
4403
+ }
4341
4404
  const className = element.getAttribute('data-class-name');
4342
4405
  if (className) {
4343
4406
  config.className = className;
@@ -4520,6 +4583,21 @@ class JaaqCollectionPlayerElement extends HTMLElement {
4520
4583
  return defaultValue;
4521
4584
  return v !== 'false';
4522
4585
  }
4586
+ getVideosFromCollection(collection) {
4587
+ if (collection.videos && collection.videos.length > 0) {
4588
+ return collection.videos;
4589
+ }
4590
+ if (collection.videoGroups && collection.videoGroups.length > 0) {
4591
+ const videos = [];
4592
+ collection.videoGroups.forEach((group) => {
4593
+ if (group.videos && group.videos.length > 0) {
4594
+ videos.push(...group.videos);
4595
+ }
4596
+ });
4597
+ return videos;
4598
+ }
4599
+ return [];
4600
+ }
4523
4601
  render() {
4524
4602
  if (!this.shadowRoot)
4525
4603
  return;
@@ -4546,6 +4624,7 @@ class JaaqCollectionPlayerElement extends HTMLElement {
4546
4624
  const apiKey = this.getAttribute('api-key');
4547
4625
  const clientId = this.getAttribute('client-id');
4548
4626
  const baseUrl = this.getAttribute('base-url') || undefined;
4627
+ const apiVersion = this.getAttribute('api-version') || undefined;
4549
4628
  if (!this.clientInstance && !apiKey && !clientId) {
4550
4629
  this.emitError(new Error('Either client property or api-key and client-id attributes are required'));
4551
4630
  return;
@@ -4557,9 +4636,11 @@ class JaaqCollectionPlayerElement extends HTMLElement {
4557
4636
  apiKey: apiKey,
4558
4637
  clientId: clientId,
4559
4638
  baseUrl: baseUrl || BASE_URL,
4639
+ apiVersion: apiVersion,
4560
4640
  });
4561
4641
  this.collectionData = await client.collections.getById(collectionId);
4562
- if (!this.collectionData.videos || this.collectionData.videos.length === 0) {
4642
+ const videos = this.getVideosFromCollection(this.collectionData);
4643
+ if (videos.length === 0) {
4563
4644
  this.emitError(new Error('No videos found in collection'));
4564
4645
  return;
4565
4646
  }
@@ -4607,7 +4688,8 @@ class JaaqCollectionPlayerElement extends HTMLElement {
4607
4688
  console.warn('[CollectionPlayer] Failed to parse video-settings attribute', e);
4608
4689
  }
4609
4690
  }
4610
- this.collectionData.videos.forEach((video) => {
4691
+ const videos = this.getVideosFromCollection(this.collectionData);
4692
+ videos.forEach((video) => {
4611
4693
  const slide = document.createElement('li');
4612
4694
  slide.className = 'splide__slide';
4613
4695
  const player = document.createElement('jaaq-video-player');
@@ -4689,8 +4771,9 @@ class JaaqCollectionPlayerElement extends HTMLElement {
4689
4771
  Components: this.splide?.Components,
4690
4772
  });
4691
4773
  this.handleSlideChange(newIndex);
4774
+ const videos = this.collectionData ? this.getVideosFromCollection(this.collectionData) : [];
4692
4775
  this.dispatchEvent(new CustomEvent('jaaq:collection:slidechange', {
4693
- detail: { index: newIndex, video: this.collectionData?.videos[newIndex] },
4776
+ detail: { index: newIndex, video: videos[newIndex] },
4694
4777
  bubbles: true,
4695
4778
  composed: true,
4696
4779
  }));
@@ -4972,6 +5055,7 @@ class JaaqVideoPlayerElement extends HTMLElement {
4972
5055
  const apiKey = this.getAttribute('api-key');
4973
5056
  const clientId = this.getAttribute('client-id');
4974
5057
  const baseUrl = this.getAttribute('base-url') || undefined;
5058
+ const apiVersion = this.getAttribute('api-version') || undefined;
4975
5059
  const autoplay = this.hasAttribute('autoplay') && this.getAttribute('autoplay') !== 'false';
4976
5060
  const controls = !this.hasAttribute('controls') || this.getAttribute('controls') !== 'false';
4977
5061
  const showLogo = !this.hasAttribute('show-logo') || this.getAttribute('show-logo') !== 'false';
@@ -4991,6 +5075,7 @@ class JaaqVideoPlayerElement extends HTMLElement {
4991
5075
  clientId: clientId ?? undefined,
4992
5076
  client: this.clientInstance || undefined,
4993
5077
  baseUrl,
5078
+ apiVersion,
4994
5079
  autoplay,
4995
5080
  controls,
4996
5081
  showLogo,