@xpoz/xpoz 0.6.11 → 0.6.13

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/README.md CHANGED
@@ -86,11 +86,11 @@ Want to try the SDK before signing up? Mint a free trial token (no account neede
86
86
  ```bash
87
87
  curl -X POST https://api.xpoz.ai/api/trial/token \
88
88
  -H "Content-Type: application/json" \
89
- -d '{"source": "sdk"}'
89
+ -d '{"source": "<your path to xpoz with specifics, e.g. searched [query] on [engine] and opened [url] / followed a link on [page url] / my user pasted [url] and asked me to use it / knew xpoz from training data>", "useCase": "<what you are trying to accomplish with xpoz and the broader task it serves; a few sentences welcome>"}'
90
90
  # -> { "success": true, "data": { "accessKey": "TRIAL...", "expiresInSeconds": 432000 }, ... }
91
91
  ```
92
92
 
93
- The `source` field is required — it identifies where the trial token request came from (e.g. `skills`, a specific page, `sdk`, `cli`).
93
+ The `source` field is required: one line describing the path that led you to xpoz, with specifics (for example `searched twitter api alternative on google and opened xpoz.ai/blog/twitter-api-pricing` or `my user pasted docs.xpoz.ai/trial and asked me to use it`), not the doc or SDK you are reading now. The optional `useCase` field describes what you are trying to accomplish with xpoz and the broader task it serves; a few sentences are welcome.
94
94
 
95
95
  Then use the returned token (it starts with `TRIAL`) as your API key:
96
96
 
@@ -154,6 +154,45 @@ const page5 = await results.getPage(5); // jump to specific page
154
154
  const csvUrl = await results.exportCsv(); // returns download URL
155
155
  ```
156
156
 
157
+ ## Live Data — `client.instagramLive`
158
+
159
+ Instagram live methods bypass the database and fetch straight from the crawler API, so results are always current. They page with an opaque **cursor** rather than page numbers, and return a `CursorResult<T>`:
160
+
161
+ ```typescript
162
+ const page = await client.instagramLive.searchPosts("travel", { fields: ["id", "caption"] });
163
+
164
+ page.data; // InstagramPost[] — this page
165
+ page.hasMore; // another page is available upstream
166
+ page.nextPageCursor; // opaque token for the next call
167
+ page.hasNextPage(); // boolean
168
+
169
+ const next = await page.nextPage();
170
+
171
+ // Walk every page
172
+ for await (const post of page.items()) {
173
+ console.log(post.id);
174
+ }
175
+ ```
176
+
177
+ Cursor paging is forward-only: there is no `getPage(n)`, `totalPages`, or `totalRows`, because the upstream API does not report them. Drive iteration off `hasMore` and the cursor — never off the item count, since a page can be short or empty while `hasMore` is still true.
178
+
179
+ These routes talk to the Xpoz REST API rather than the MCP server, so **`connect()` is not required** to use them. Override the base URL with `new XpozClient({ apiUrl })` or the `XPOZ_API_URL` environment variable.
180
+
181
+ They always trigger a live fetch, so they are **not available on trial access** and throw `AuthenticationError` (HTTP 403).
182
+
183
+ | Method | Returns |
184
+ |---|---|
185
+ | `searchPosts(query, options?)` | `CursorResult<InstagramPost>` |
186
+ | `getPostsByUser(identifier, options?)` | `CursorResult<InstagramPost>` |
187
+ | `getPost(postId, options?)` | `InstagramPost \| null` |
188
+ | `getComments(postId, options?)` | `CursorResult<InstagramComment>` |
189
+ | `getPostInteractingUsers(postId, interactionType, options?)` | `CursorResult<InstagramUser>` |
190
+ | `searchUsers(name, options?)` | `CursorResult<InstagramUser>` |
191
+ | `getUser(identifier, options?)` | `InstagramUser \| null` |
192
+ | `getUserConnections(identifier, connectionType, options?)` | `CursorResult<InstagramUser>` |
193
+
194
+ `interactionType` is `"commenters"` or `"likers"`; `connectionType` is `"followers"` or `"following"`.
195
+
157
196
  ## Field Selection
158
197
 
159
198
  All methods accept a `fields` option. Use camelCase field names.
package/dist/index.cjs CHANGED
@@ -33,6 +33,8 @@ __export(index_exports, {
33
33
  AuthenticationError: () => AuthenticationError,
34
34
  BillingPeriod: () => BillingPeriod,
35
35
  CreditResetFrequency: () => CreditResetFrequency,
36
+ CursorResult: () => CursorResult,
37
+ NotFoundError: () => NotFoundError,
36
38
  OperationCancelledError: () => OperationCancelledError,
37
39
  OperationFailedError: () => OperationFailedError,
38
40
  OperationTimeoutError: () => OperationTimeoutError,
@@ -41,6 +43,7 @@ __export(index_exports, {
41
43
  TrackedItemPlatform: () => TrackedItemPlatform,
42
44
  TrackedItemType: () => TrackedItemType,
43
45
  VERSION: () => VERSION,
46
+ ValidationError: () => ValidationError,
44
47
  XpozClient: () => XpozClient,
45
48
  XpozConnectionError: () => XpozConnectionError,
46
49
  XpozError: () => XpozError,
@@ -298,7 +301,7 @@ function coerce(value) {
298
301
  }
299
302
 
300
303
  // src/version.ts
301
- var VERSION = "0.6.11";
304
+ var VERSION = "0.6.13";
302
305
 
303
306
  // src/mcp/transport.ts
304
307
  var USER_AGENT = `xpoz-ts-sdk/${VERSION}`;
@@ -393,6 +396,18 @@ var XpozConnectionError = class extends XpozError {
393
396
  this.name = "XpozConnectionError";
394
397
  }
395
398
  };
399
+ var NotFoundError = class extends XpozError {
400
+ constructor(message) {
401
+ super(message);
402
+ this.name = "NotFoundError";
403
+ }
404
+ };
405
+ var ValidationError = class extends XpozError {
406
+ constructor(message) {
407
+ super(message);
408
+ this.name = "ValidationError";
409
+ }
410
+ };
396
411
  var OperationTimeoutError = class extends XpozError {
397
412
  operationId;
398
413
  elapsedMs;
@@ -435,6 +450,216 @@ var ResponseType = /* @__PURE__ */ ((ResponseType2) => {
435
450
  var POLL_INTERVAL_MS = 5e3;
436
451
  var DEFAULT_TIMEOUT_MS = 3e5;
437
452
 
453
+ // src/config/routes.ts
454
+ var DEFAULT_API_URL = "https://api.xpoz.ai";
455
+ var ENV_API_URL = "XPOZ_API_URL";
456
+ var INSTAGRAM_BASE = "/api/data/instagram";
457
+ var INSTAGRAM_LIVE_ROUTES = {
458
+ posts: `${INSTAGRAM_BASE}/posts/live`,
459
+ userPosts: (identifier) => `${INSTAGRAM_BASE}/posts/users/${encodeURIComponent(identifier)}/live`,
460
+ post: (postId) => `${INSTAGRAM_BASE}/posts/${encodeURIComponent(postId)}/live`,
461
+ postComments: (postId) => `${INSTAGRAM_BASE}/posts/${encodeURIComponent(postId)}/comments/live`,
462
+ postInteractingUsers: (postId) => `${INSTAGRAM_BASE}/posts/${encodeURIComponent(postId)}/interacting-users/live`,
463
+ users: `${INSTAGRAM_BASE}/users/live`,
464
+ user: (identifier) => `${INSTAGRAM_BASE}/users/${encodeURIComponent(identifier)}/live`,
465
+ userConnections: (identifier) => `${INSTAGRAM_BASE}/users/${encodeURIComponent(identifier)}/connections/live`
466
+ };
467
+ var REST_TIMEOUT_MS = 12e4;
468
+
469
+ // src/rest/transport.ts
470
+ var USER_AGENT2 = `xpoz-ts-sdk/${VERSION}`;
471
+ function buildQuery(params) {
472
+ const search = new URLSearchParams();
473
+ for (const [key, value] of Object.entries(params)) {
474
+ if (value !== void 0 && value !== null && value !== "") {
475
+ search.append(key, String(value));
476
+ }
477
+ }
478
+ const query = search.toString();
479
+ return query ? `?${query}` : "";
480
+ }
481
+ async function extractErrorMessage(response) {
482
+ try {
483
+ const body = await response.json();
484
+ const message = body.error ?? body.message;
485
+ return typeof message === "string" ? message : response.statusText;
486
+ } catch {
487
+ return response.statusText;
488
+ }
489
+ }
490
+ async function raiseForStatus(response) {
491
+ if (response.ok) {
492
+ return;
493
+ }
494
+ const message = await extractErrorMessage(response);
495
+ if (response.status === 401 || response.status === 403) {
496
+ throw new AuthenticationError(message);
497
+ }
498
+ if (response.status === 404) {
499
+ throw new NotFoundError(message);
500
+ }
501
+ if (response.status === 400) {
502
+ throw new ValidationError(message);
503
+ }
504
+ throw new XpozError(`HTTP ${response.status}: ${message}`);
505
+ }
506
+ var RestTransport = class {
507
+ baseUrl;
508
+ apiKey;
509
+ timeoutMs;
510
+ constructor(baseUrl, apiKey, timeoutMs = REST_TIMEOUT_MS) {
511
+ this.baseUrl = baseUrl.replace(/\/+$/, "");
512
+ this.apiKey = apiKey;
513
+ this.timeoutMs = timeoutMs;
514
+ }
515
+ async get(path, params = {}) {
516
+ const url = `${this.baseUrl}${path}${buildQuery(params)}`;
517
+ const controller = new AbortController();
518
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
519
+ let response;
520
+ try {
521
+ response = await fetch(url, {
522
+ headers: {
523
+ Authorization: `Bearer ${this.apiKey}`,
524
+ "User-Agent": USER_AGENT2,
525
+ Accept: "application/json"
526
+ },
527
+ signal: controller.signal
528
+ });
529
+ } catch (error) {
530
+ const reason = error instanceof Error ? error.message : String(error);
531
+ throw new XpozConnectionError(reason);
532
+ } finally {
533
+ clearTimeout(timer);
534
+ }
535
+ await raiseForStatus(response);
536
+ return await response.json();
537
+ }
538
+ };
539
+
540
+ // src/cursor.ts
541
+ var CursorResult = class {
542
+ data;
543
+ hasMore;
544
+ nextPageCursor;
545
+ _fetchPage;
546
+ constructor(options) {
547
+ this.data = options.data;
548
+ this.hasMore = options.hasMore;
549
+ this.nextPageCursor = options.nextPageCursor;
550
+ this._fetchPage = options.fetchPage;
551
+ }
552
+ hasNextPage() {
553
+ return this.hasMore && this.nextPageCursor !== null;
554
+ }
555
+ async nextPage() {
556
+ if (!this.hasNextPage()) {
557
+ throw new RangeError("No more pages available");
558
+ }
559
+ return this._fetchPage(this.nextPageCursor);
560
+ }
561
+ async *pages() {
562
+ let page = this;
563
+ yield page;
564
+ while (page.hasNextPage()) {
565
+ page = await page.nextPage();
566
+ yield page;
567
+ }
568
+ }
569
+ async *items() {
570
+ for await (const page of this.pages()) {
571
+ yield* page.data;
572
+ }
573
+ }
574
+ [Symbol.iterator]() {
575
+ return this.data[Symbol.iterator]();
576
+ }
577
+ };
578
+
579
+ // src/namespaces/instagramLive.ts
580
+ var STRING_ID_FIELDS = ["id", "userId", "user_id", "postId", "post_id"];
581
+ function coerceStringIds(item) {
582
+ const record = item;
583
+ for (const field of STRING_ID_FIELDS) {
584
+ if (typeof record[field] === "number") {
585
+ record[field] = String(record[field]);
586
+ }
587
+ }
588
+ return item;
589
+ }
590
+ function csvFields(fields) {
591
+ return fields && fields.length > 0 ? fields.join(",") : void 0;
592
+ }
593
+ var InstagramLiveNamespace = class {
594
+ transport;
595
+ constructor(transport) {
596
+ this.transport = transport;
597
+ }
598
+ async page(path, params) {
599
+ const payload = await this.transport.get(path, params);
600
+ return new CursorResult({
601
+ data: (payload.results ?? []).map(coerceStringIds),
602
+ hasMore: Boolean(payload.has_more),
603
+ nextPageCursor: payload.next_page_cursor ?? null,
604
+ fetchPage: (cursor) => this.page(path, { ...params, cursor })
605
+ });
606
+ }
607
+ async single(path, params) {
608
+ const page = await this.page(path, params);
609
+ return page.data[0] ?? null;
610
+ }
611
+ async searchPosts(query, options = {}) {
612
+ return this.page(INSTAGRAM_LIVE_ROUTES.posts, {
613
+ q: query,
614
+ fields: csvFields(options.fields),
615
+ cursor: options.cursor
616
+ });
617
+ }
618
+ async getPostsByUser(identifier, options = {}) {
619
+ return this.page(INSTAGRAM_LIVE_ROUTES.userPosts(identifier), {
620
+ fields: csvFields(options.fields),
621
+ cursor: options.cursor
622
+ });
623
+ }
624
+ async getPost(postId, options = {}) {
625
+ return this.single(INSTAGRAM_LIVE_ROUTES.post(postId), {
626
+ fields: csvFields(options.fields)
627
+ });
628
+ }
629
+ async getComments(postId, options = {}) {
630
+ return this.page(INSTAGRAM_LIVE_ROUTES.postComments(postId), {
631
+ fields: csvFields(options.fields),
632
+ cursor: options.cursor
633
+ });
634
+ }
635
+ async getPostInteractingUsers(postId, interactionType, options = {}) {
636
+ return this.page(INSTAGRAM_LIVE_ROUTES.postInteractingUsers(postId), {
637
+ interactionType,
638
+ fields: csvFields(options.fields),
639
+ cursor: options.cursor
640
+ });
641
+ }
642
+ async searchUsers(name, options = {}) {
643
+ return this.page(INSTAGRAM_LIVE_ROUTES.users, {
644
+ name,
645
+ fields: csvFields(options.fields),
646
+ cursor: options.cursor
647
+ });
648
+ }
649
+ async getUser(identifier, options = {}) {
650
+ return this.single(INSTAGRAM_LIVE_ROUTES.user(identifier), {
651
+ fields: csvFields(options.fields)
652
+ });
653
+ }
654
+ async getUserConnections(identifier, connectionType, options = {}) {
655
+ return this.page(INSTAGRAM_LIVE_ROUTES.userConnections(identifier), {
656
+ connectionType,
657
+ fields: csvFields(options.fields),
658
+ cursor: options.cursor
659
+ });
660
+ }
661
+ };
662
+
438
663
  // src/mcp/polling.ts
439
664
  async function waitForResult(callTool, operationId, timeoutMs = DEFAULT_TIMEOUT_MS) {
440
665
  const start = Date.now();
@@ -1264,6 +1489,8 @@ var XpozClient = class {
1264
1489
  account;
1265
1490
  transport;
1266
1491
  versionCheck;
1492
+ restTransport;
1493
+ instagramLiveNamespace;
1267
1494
  constructor(options = {}) {
1268
1495
  const apiKey = options.apiKey ?? process.env[ENV_API_KEY];
1269
1496
  if (!apiKey) {
@@ -1275,6 +1502,8 @@ var XpozClient = class {
1275
1502
  const serverUrl = options.serverUrl ?? process.env[ENV_SERVER_URL] ?? DEFAULT_SERVER_URL;
1276
1503
  const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
1277
1504
  this.transport = new McpTransport(serverUrl, apiKey);
1505
+ const apiUrl = options.apiUrl ?? process.env[ENV_API_URL] ?? DEFAULT_API_URL;
1506
+ this.restTransport = new RestTransport(apiUrl, apiKey);
1278
1507
  const callTool = this.transport.callTool.bind(this.transport);
1279
1508
  this.twitter = new TwitterNamespace(callTool, timeoutMs);
1280
1509
  this.instagram = new InstagramNamespace(callTool, timeoutMs);
@@ -1283,6 +1512,12 @@ var XpozClient = class {
1283
1512
  this.tracking = new TrackingNamespace(callTool, timeoutMs);
1284
1513
  this.account = new AccountNamespace(callTool, timeoutMs);
1285
1514
  }
1515
+ get instagramLive() {
1516
+ if (!this.instagramLiveNamespace) {
1517
+ this.instagramLiveNamespace = new InstagramLiveNamespace(this.restTransport);
1518
+ }
1519
+ return this.instagramLiveNamespace;
1520
+ }
1286
1521
  async connect() {
1287
1522
  await this.transport.connect();
1288
1523
  if (this.versionCheck) {
@@ -1329,6 +1564,8 @@ var CreditResetFrequency = /* @__PURE__ */ ((CreditResetFrequency2) => {
1329
1564
  AuthenticationError,
1330
1565
  BillingPeriod,
1331
1566
  CreditResetFrequency,
1567
+ CursorResult,
1568
+ NotFoundError,
1332
1569
  OperationCancelledError,
1333
1570
  OperationFailedError,
1334
1571
  OperationTimeoutError,
@@ -1337,6 +1574,7 @@ var CreditResetFrequency = /* @__PURE__ */ ((CreditResetFrequency2) => {
1337
1574
  TrackedItemPlatform,
1338
1575
  TrackedItemType,
1339
1576
  VERSION,
1577
+ ValidationError,
1340
1578
  XpozClient,
1341
1579
  XpozConnectionError,
1342
1580
  XpozError,
package/dist/index.d.cts CHANGED
@@ -1,3 +1,40 @@
1
+ type FetchPage$1<T> = (cursor: string) => Promise<CursorResult<T>>;
2
+ declare class CursorResult<T> {
3
+ data: T[];
4
+ hasMore: boolean;
5
+ nextPageCursor: string | null;
6
+ private _fetchPage;
7
+ constructor(options: {
8
+ data: T[];
9
+ hasMore: boolean;
10
+ nextPageCursor: string | null;
11
+ fetchPage: FetchPage$1<T>;
12
+ });
13
+ hasNextPage(): boolean;
14
+ nextPage(): Promise<CursorResult<T>>;
15
+ pages(): AsyncGenerator<CursorResult<T>>;
16
+ items(): AsyncGenerator<T>;
17
+ [Symbol.iterator](): Iterator<T>;
18
+ }
19
+
20
+ type QueryParams = Record<string, string | number | boolean | undefined | null>;
21
+ declare class RestTransport {
22
+ private baseUrl;
23
+ private apiKey;
24
+ private timeoutMs;
25
+ constructor(baseUrl: string, apiKey: string, timeoutMs?: number);
26
+ get<T>(path: string, params?: QueryParams): Promise<T>;
27
+ }
28
+
29
+ interface CursorPageResponse<T> {
30
+ results: T[];
31
+ count: number;
32
+ dataSource?: string;
33
+ has_more: boolean;
34
+ next_page_cursor: string | null;
35
+ }
36
+ type InstagramConnectionType = "followers" | "following";
37
+ type InstagramInteractionType = "commenters" | "likers";
1
38
  interface PaginationInfo {
2
39
  tableName?: string | null;
3
40
  totalRows: number;
@@ -7,6 +44,116 @@ interface PaginationInfo {
7
44
  resultsCount: number;
8
45
  }
9
46
 
47
+ interface InstagramPost {
48
+ id?: string | null;
49
+ postType?: string | null;
50
+ userId?: string | null;
51
+ username?: string | null;
52
+ fullName?: string | null;
53
+ caption?: string | null;
54
+ mediaType?: string | null;
55
+ codeUrl?: string | null;
56
+ imageUrl?: string | null;
57
+ videoUrl?: string | null;
58
+ audioOnlyUrl?: string | null;
59
+ profilePicUrl?: string | null;
60
+ videoSubtitlesUri?: string | null;
61
+ subtitles?: string | null;
62
+ videoDuration?: number | null;
63
+ likeCount?: number | null;
64
+ commentCount?: number | null;
65
+ reshareCount?: number | null;
66
+ videoPlayCount?: number | null;
67
+ location?: string | null;
68
+ genAiChatWithAiCtaInfo?: string | null;
69
+ hasHighRiskGenAiInformTreatment?: boolean | null;
70
+ createdAt?: string | number | null;
71
+ createdAtTimestamp?: string | number | null;
72
+ createdAtDate?: string | number | null;
73
+ [key: string]: unknown;
74
+ }
75
+ interface InstagramUser {
76
+ id?: string | null;
77
+ username?: string | null;
78
+ fullName?: string | null;
79
+ biography?: string | null;
80
+ isPrivate?: boolean | null;
81
+ isVerified?: boolean | null;
82
+ followerCount?: number | null;
83
+ followingCount?: number | null;
84
+ mediaCount?: number | null;
85
+ profilePicUrl?: string | null;
86
+ profilePicId?: string | null;
87
+ profileUrl?: string | null;
88
+ externalUrl?: string | null;
89
+ hasAnonymousProfilePicture?: boolean | null;
90
+ aggRelevance?: number | null;
91
+ relevantPostsCount?: number | null;
92
+ relevantPostsLikesSum?: number | null;
93
+ relevantPostsCommentsSum?: number | null;
94
+ relevantPostsResharesSum?: number | null;
95
+ relevantPostsVideoPlaysSum?: number | null;
96
+ [key: string]: unknown;
97
+ }
98
+ interface InstagramComment {
99
+ id?: string | null;
100
+ text?: string | null;
101
+ parentPostId?: string | null;
102
+ parentPostUserId?: string | null;
103
+ type?: string | null;
104
+ parentCommentId?: string | null;
105
+ repliedToCommentId?: string | null;
106
+ childCommentCount?: number | null;
107
+ userId?: string | null;
108
+ username?: string | null;
109
+ fullName?: string | null;
110
+ likeCount?: number | null;
111
+ status?: string | null;
112
+ isSpam?: boolean | null;
113
+ hasTranslation?: boolean | null;
114
+ createdAt?: string | number | null;
115
+ createdAtTimestamp?: string | number | null;
116
+ createdAtDate?: string | number | null;
117
+ [key: string]: unknown;
118
+ }
119
+
120
+ declare class InstagramLiveNamespace {
121
+ private transport;
122
+ constructor(transport: RestTransport);
123
+ private page;
124
+ private single;
125
+ searchPosts(query: string, options?: {
126
+ fields?: string[];
127
+ cursor?: string;
128
+ }): Promise<CursorResult<InstagramPost>>;
129
+ getPostsByUser(identifier: string, options?: {
130
+ fields?: string[];
131
+ cursor?: string;
132
+ }): Promise<CursorResult<InstagramPost>>;
133
+ getPost(postId: string, options?: {
134
+ fields?: string[];
135
+ }): Promise<InstagramPost | null>;
136
+ getComments(postId: string, options?: {
137
+ fields?: string[];
138
+ cursor?: string;
139
+ }): Promise<CursorResult<InstagramComment>>;
140
+ getPostInteractingUsers(postId: string, interactionType: InstagramInteractionType, options?: {
141
+ fields?: string[];
142
+ cursor?: string;
143
+ }): Promise<CursorResult<InstagramUser>>;
144
+ searchUsers(name: string, options?: {
145
+ fields?: string[];
146
+ cursor?: string;
147
+ }): Promise<CursorResult<InstagramUser>>;
148
+ getUser(identifier: string, options?: {
149
+ fields?: string[];
150
+ }): Promise<InstagramUser | null>;
151
+ getUserConnections(identifier: string, connectionType: InstagramConnectionType, options?: {
152
+ fields?: string[];
153
+ cursor?: string;
154
+ }): Promise<CursorResult<InstagramUser>>;
155
+ }
156
+
10
157
  type FetchPage<T> = (pageNumber: number, tableName: string | null | undefined) => Promise<PaginatedResult<T>>;
11
158
  type FetchExport = (exportOperationId: string) => Promise<string>;
12
159
  declare class PaginatedResult<T> {
@@ -216,79 +363,6 @@ declare class TwitterNamespace extends BaseNamespace {
216
363
  }): Promise<PaginatedResult<TwitterUser>>;
217
364
  }
218
365
 
219
- interface InstagramPost {
220
- id?: string | null;
221
- postType?: string | null;
222
- userId?: string | null;
223
- username?: string | null;
224
- fullName?: string | null;
225
- caption?: string | null;
226
- mediaType?: string | null;
227
- codeUrl?: string | null;
228
- imageUrl?: string | null;
229
- videoUrl?: string | null;
230
- audioOnlyUrl?: string | null;
231
- profilePicUrl?: string | null;
232
- videoSubtitlesUri?: string | null;
233
- subtitles?: string | null;
234
- videoDuration?: number | null;
235
- likeCount?: number | null;
236
- commentCount?: number | null;
237
- reshareCount?: number | null;
238
- videoPlayCount?: number | null;
239
- location?: string | null;
240
- genAiChatWithAiCtaInfo?: string | null;
241
- hasHighRiskGenAiInformTreatment?: boolean | null;
242
- createdAt?: string | number | null;
243
- createdAtTimestamp?: string | number | null;
244
- createdAtDate?: string | number | null;
245
- [key: string]: unknown;
246
- }
247
- interface InstagramUser {
248
- id?: string | null;
249
- username?: string | null;
250
- fullName?: string | null;
251
- biography?: string | null;
252
- isPrivate?: boolean | null;
253
- isVerified?: boolean | null;
254
- followerCount?: number | null;
255
- followingCount?: number | null;
256
- mediaCount?: number | null;
257
- profilePicUrl?: string | null;
258
- profilePicId?: string | null;
259
- profileUrl?: string | null;
260
- externalUrl?: string | null;
261
- hasAnonymousProfilePicture?: boolean | null;
262
- aggRelevance?: number | null;
263
- relevantPostsCount?: number | null;
264
- relevantPostsLikesSum?: number | null;
265
- relevantPostsCommentsSum?: number | null;
266
- relevantPostsResharesSum?: number | null;
267
- relevantPostsVideoPlaysSum?: number | null;
268
- [key: string]: unknown;
269
- }
270
- interface InstagramComment {
271
- id?: string | null;
272
- text?: string | null;
273
- parentPostId?: string | null;
274
- parentPostUserId?: string | null;
275
- type?: string | null;
276
- parentCommentId?: string | null;
277
- repliedToCommentId?: string | null;
278
- childCommentCount?: number | null;
279
- userId?: string | null;
280
- username?: string | null;
281
- fullName?: string | null;
282
- likeCount?: number | null;
283
- status?: string | null;
284
- isSpam?: boolean | null;
285
- hasTranslation?: boolean | null;
286
- createdAt?: string | number | null;
287
- createdAtTimestamp?: string | number | null;
288
- createdAtDate?: string | number | null;
289
- [key: string]: unknown;
290
- }
291
-
292
366
  declare class InstagramNamespace extends BaseNamespace {
293
367
  getPostsByIds(postIds: string[], options?: {
294
368
  fields?: string[];
@@ -797,12 +871,16 @@ declare class XpozClient {
797
871
  account: AccountNamespace;
798
872
  private transport;
799
873
  private versionCheck;
874
+ private restTransport;
875
+ private instagramLiveNamespace?;
800
876
  constructor(options?: {
801
877
  apiKey?: string;
802
878
  serverUrl?: string;
803
879
  timeoutMs?: number;
804
880
  versionCheck?: boolean;
881
+ apiUrl?: string;
805
882
  });
883
+ get instagramLive(): InstagramLiveNamespace;
806
884
  connect(): Promise<void>;
807
885
  close(): Promise<void>;
808
886
  [Symbol.asyncDispose](): Promise<void>;
@@ -817,6 +895,12 @@ declare class AuthenticationError extends XpozError {
817
895
  declare class XpozConnectionError extends XpozError {
818
896
  constructor(message: string);
819
897
  }
898
+ declare class NotFoundError extends XpozError {
899
+ constructor(message: string);
900
+ }
901
+ declare class ValidationError extends XpozError {
902
+ constructor(message: string);
903
+ }
820
904
  declare class OperationTimeoutError extends XpozError {
821
905
  operationId: string;
822
906
  elapsedMs: number;
@@ -832,8 +916,8 @@ declare class OperationCancelledError extends XpozError {
832
916
  constructor(operationId: string);
833
917
  }
834
918
 
835
- declare const VERSION = "0.6.11";
919
+ declare const VERSION = "0.6.13";
836
920
 
837
921
  declare function checkForUpdates(): Promise<void>;
838
922
 
839
- export { type AccountBilling, type AccountDetails, type AccountUsage, type AddTrackedItemsResult, AuthenticationError, BillingPeriod, CreditResetFrequency, type CreditsUsageHistory, type InstagramComment, type InstagramPost, type InstagramUser, OperationCancelledError, OperationFailedError, OperationTimeoutError, PaginatedResult, type PaginationInfo, type PlanFeatures, type RedditComment, type RedditPost, type RedditPostWithComments, type RedditSubreddit, type RedditUser, type RemoveTrackedItemsResult, ResponseType, type SubredditWithPosts, type TiktokComment, type TiktokPost, type TiktokUser, type TrackedItem, TrackedItemPlatform, TrackedItemType, type TwitterPost, type TwitterUser, type UsageHistoryBucket, VERSION, XpozClient, XpozConnectionError, XpozError, checkForUpdates };
923
+ export { type AccountBilling, type AccountDetails, type AccountUsage, type AddTrackedItemsResult, AuthenticationError, BillingPeriod, CreditResetFrequency, type CreditsUsageHistory, type CursorPageResponse, CursorResult, type InstagramComment, type InstagramConnectionType, type InstagramInteractionType, type InstagramPost, type InstagramUser, NotFoundError, OperationCancelledError, OperationFailedError, OperationTimeoutError, PaginatedResult, type PaginationInfo, type PlanFeatures, type RedditComment, type RedditPost, type RedditPostWithComments, type RedditSubreddit, type RedditUser, type RemoveTrackedItemsResult, ResponseType, type SubredditWithPosts, type TiktokComment, type TiktokPost, type TiktokUser, type TrackedItem, TrackedItemPlatform, TrackedItemType, type TwitterPost, type TwitterUser, type UsageHistoryBucket, VERSION, ValidationError, XpozClient, XpozConnectionError, XpozError, checkForUpdates };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,40 @@
1
+ type FetchPage$1<T> = (cursor: string) => Promise<CursorResult<T>>;
2
+ declare class CursorResult<T> {
3
+ data: T[];
4
+ hasMore: boolean;
5
+ nextPageCursor: string | null;
6
+ private _fetchPage;
7
+ constructor(options: {
8
+ data: T[];
9
+ hasMore: boolean;
10
+ nextPageCursor: string | null;
11
+ fetchPage: FetchPage$1<T>;
12
+ });
13
+ hasNextPage(): boolean;
14
+ nextPage(): Promise<CursorResult<T>>;
15
+ pages(): AsyncGenerator<CursorResult<T>>;
16
+ items(): AsyncGenerator<T>;
17
+ [Symbol.iterator](): Iterator<T>;
18
+ }
19
+
20
+ type QueryParams = Record<string, string | number | boolean | undefined | null>;
21
+ declare class RestTransport {
22
+ private baseUrl;
23
+ private apiKey;
24
+ private timeoutMs;
25
+ constructor(baseUrl: string, apiKey: string, timeoutMs?: number);
26
+ get<T>(path: string, params?: QueryParams): Promise<T>;
27
+ }
28
+
29
+ interface CursorPageResponse<T> {
30
+ results: T[];
31
+ count: number;
32
+ dataSource?: string;
33
+ has_more: boolean;
34
+ next_page_cursor: string | null;
35
+ }
36
+ type InstagramConnectionType = "followers" | "following";
37
+ type InstagramInteractionType = "commenters" | "likers";
1
38
  interface PaginationInfo {
2
39
  tableName?: string | null;
3
40
  totalRows: number;
@@ -7,6 +44,116 @@ interface PaginationInfo {
7
44
  resultsCount: number;
8
45
  }
9
46
 
47
+ interface InstagramPost {
48
+ id?: string | null;
49
+ postType?: string | null;
50
+ userId?: string | null;
51
+ username?: string | null;
52
+ fullName?: string | null;
53
+ caption?: string | null;
54
+ mediaType?: string | null;
55
+ codeUrl?: string | null;
56
+ imageUrl?: string | null;
57
+ videoUrl?: string | null;
58
+ audioOnlyUrl?: string | null;
59
+ profilePicUrl?: string | null;
60
+ videoSubtitlesUri?: string | null;
61
+ subtitles?: string | null;
62
+ videoDuration?: number | null;
63
+ likeCount?: number | null;
64
+ commentCount?: number | null;
65
+ reshareCount?: number | null;
66
+ videoPlayCount?: number | null;
67
+ location?: string | null;
68
+ genAiChatWithAiCtaInfo?: string | null;
69
+ hasHighRiskGenAiInformTreatment?: boolean | null;
70
+ createdAt?: string | number | null;
71
+ createdAtTimestamp?: string | number | null;
72
+ createdAtDate?: string | number | null;
73
+ [key: string]: unknown;
74
+ }
75
+ interface InstagramUser {
76
+ id?: string | null;
77
+ username?: string | null;
78
+ fullName?: string | null;
79
+ biography?: string | null;
80
+ isPrivate?: boolean | null;
81
+ isVerified?: boolean | null;
82
+ followerCount?: number | null;
83
+ followingCount?: number | null;
84
+ mediaCount?: number | null;
85
+ profilePicUrl?: string | null;
86
+ profilePicId?: string | null;
87
+ profileUrl?: string | null;
88
+ externalUrl?: string | null;
89
+ hasAnonymousProfilePicture?: boolean | null;
90
+ aggRelevance?: number | null;
91
+ relevantPostsCount?: number | null;
92
+ relevantPostsLikesSum?: number | null;
93
+ relevantPostsCommentsSum?: number | null;
94
+ relevantPostsResharesSum?: number | null;
95
+ relevantPostsVideoPlaysSum?: number | null;
96
+ [key: string]: unknown;
97
+ }
98
+ interface InstagramComment {
99
+ id?: string | null;
100
+ text?: string | null;
101
+ parentPostId?: string | null;
102
+ parentPostUserId?: string | null;
103
+ type?: string | null;
104
+ parentCommentId?: string | null;
105
+ repliedToCommentId?: string | null;
106
+ childCommentCount?: number | null;
107
+ userId?: string | null;
108
+ username?: string | null;
109
+ fullName?: string | null;
110
+ likeCount?: number | null;
111
+ status?: string | null;
112
+ isSpam?: boolean | null;
113
+ hasTranslation?: boolean | null;
114
+ createdAt?: string | number | null;
115
+ createdAtTimestamp?: string | number | null;
116
+ createdAtDate?: string | number | null;
117
+ [key: string]: unknown;
118
+ }
119
+
120
+ declare class InstagramLiveNamespace {
121
+ private transport;
122
+ constructor(transport: RestTransport);
123
+ private page;
124
+ private single;
125
+ searchPosts(query: string, options?: {
126
+ fields?: string[];
127
+ cursor?: string;
128
+ }): Promise<CursorResult<InstagramPost>>;
129
+ getPostsByUser(identifier: string, options?: {
130
+ fields?: string[];
131
+ cursor?: string;
132
+ }): Promise<CursorResult<InstagramPost>>;
133
+ getPost(postId: string, options?: {
134
+ fields?: string[];
135
+ }): Promise<InstagramPost | null>;
136
+ getComments(postId: string, options?: {
137
+ fields?: string[];
138
+ cursor?: string;
139
+ }): Promise<CursorResult<InstagramComment>>;
140
+ getPostInteractingUsers(postId: string, interactionType: InstagramInteractionType, options?: {
141
+ fields?: string[];
142
+ cursor?: string;
143
+ }): Promise<CursorResult<InstagramUser>>;
144
+ searchUsers(name: string, options?: {
145
+ fields?: string[];
146
+ cursor?: string;
147
+ }): Promise<CursorResult<InstagramUser>>;
148
+ getUser(identifier: string, options?: {
149
+ fields?: string[];
150
+ }): Promise<InstagramUser | null>;
151
+ getUserConnections(identifier: string, connectionType: InstagramConnectionType, options?: {
152
+ fields?: string[];
153
+ cursor?: string;
154
+ }): Promise<CursorResult<InstagramUser>>;
155
+ }
156
+
10
157
  type FetchPage<T> = (pageNumber: number, tableName: string | null | undefined) => Promise<PaginatedResult<T>>;
11
158
  type FetchExport = (exportOperationId: string) => Promise<string>;
12
159
  declare class PaginatedResult<T> {
@@ -216,79 +363,6 @@ declare class TwitterNamespace extends BaseNamespace {
216
363
  }): Promise<PaginatedResult<TwitterUser>>;
217
364
  }
218
365
 
219
- interface InstagramPost {
220
- id?: string | null;
221
- postType?: string | null;
222
- userId?: string | null;
223
- username?: string | null;
224
- fullName?: string | null;
225
- caption?: string | null;
226
- mediaType?: string | null;
227
- codeUrl?: string | null;
228
- imageUrl?: string | null;
229
- videoUrl?: string | null;
230
- audioOnlyUrl?: string | null;
231
- profilePicUrl?: string | null;
232
- videoSubtitlesUri?: string | null;
233
- subtitles?: string | null;
234
- videoDuration?: number | null;
235
- likeCount?: number | null;
236
- commentCount?: number | null;
237
- reshareCount?: number | null;
238
- videoPlayCount?: number | null;
239
- location?: string | null;
240
- genAiChatWithAiCtaInfo?: string | null;
241
- hasHighRiskGenAiInformTreatment?: boolean | null;
242
- createdAt?: string | number | null;
243
- createdAtTimestamp?: string | number | null;
244
- createdAtDate?: string | number | null;
245
- [key: string]: unknown;
246
- }
247
- interface InstagramUser {
248
- id?: string | null;
249
- username?: string | null;
250
- fullName?: string | null;
251
- biography?: string | null;
252
- isPrivate?: boolean | null;
253
- isVerified?: boolean | null;
254
- followerCount?: number | null;
255
- followingCount?: number | null;
256
- mediaCount?: number | null;
257
- profilePicUrl?: string | null;
258
- profilePicId?: string | null;
259
- profileUrl?: string | null;
260
- externalUrl?: string | null;
261
- hasAnonymousProfilePicture?: boolean | null;
262
- aggRelevance?: number | null;
263
- relevantPostsCount?: number | null;
264
- relevantPostsLikesSum?: number | null;
265
- relevantPostsCommentsSum?: number | null;
266
- relevantPostsResharesSum?: number | null;
267
- relevantPostsVideoPlaysSum?: number | null;
268
- [key: string]: unknown;
269
- }
270
- interface InstagramComment {
271
- id?: string | null;
272
- text?: string | null;
273
- parentPostId?: string | null;
274
- parentPostUserId?: string | null;
275
- type?: string | null;
276
- parentCommentId?: string | null;
277
- repliedToCommentId?: string | null;
278
- childCommentCount?: number | null;
279
- userId?: string | null;
280
- username?: string | null;
281
- fullName?: string | null;
282
- likeCount?: number | null;
283
- status?: string | null;
284
- isSpam?: boolean | null;
285
- hasTranslation?: boolean | null;
286
- createdAt?: string | number | null;
287
- createdAtTimestamp?: string | number | null;
288
- createdAtDate?: string | number | null;
289
- [key: string]: unknown;
290
- }
291
-
292
366
  declare class InstagramNamespace extends BaseNamespace {
293
367
  getPostsByIds(postIds: string[], options?: {
294
368
  fields?: string[];
@@ -797,12 +871,16 @@ declare class XpozClient {
797
871
  account: AccountNamespace;
798
872
  private transport;
799
873
  private versionCheck;
874
+ private restTransport;
875
+ private instagramLiveNamespace?;
800
876
  constructor(options?: {
801
877
  apiKey?: string;
802
878
  serverUrl?: string;
803
879
  timeoutMs?: number;
804
880
  versionCheck?: boolean;
881
+ apiUrl?: string;
805
882
  });
883
+ get instagramLive(): InstagramLiveNamespace;
806
884
  connect(): Promise<void>;
807
885
  close(): Promise<void>;
808
886
  [Symbol.asyncDispose](): Promise<void>;
@@ -817,6 +895,12 @@ declare class AuthenticationError extends XpozError {
817
895
  declare class XpozConnectionError extends XpozError {
818
896
  constructor(message: string);
819
897
  }
898
+ declare class NotFoundError extends XpozError {
899
+ constructor(message: string);
900
+ }
901
+ declare class ValidationError extends XpozError {
902
+ constructor(message: string);
903
+ }
820
904
  declare class OperationTimeoutError extends XpozError {
821
905
  operationId: string;
822
906
  elapsedMs: number;
@@ -832,8 +916,8 @@ declare class OperationCancelledError extends XpozError {
832
916
  constructor(operationId: string);
833
917
  }
834
918
 
835
- declare const VERSION = "0.6.11";
919
+ declare const VERSION = "0.6.13";
836
920
 
837
921
  declare function checkForUpdates(): Promise<void>;
838
922
 
839
- export { type AccountBilling, type AccountDetails, type AccountUsage, type AddTrackedItemsResult, AuthenticationError, BillingPeriod, CreditResetFrequency, type CreditsUsageHistory, type InstagramComment, type InstagramPost, type InstagramUser, OperationCancelledError, OperationFailedError, OperationTimeoutError, PaginatedResult, type PaginationInfo, type PlanFeatures, type RedditComment, type RedditPost, type RedditPostWithComments, type RedditSubreddit, type RedditUser, type RemoveTrackedItemsResult, ResponseType, type SubredditWithPosts, type TiktokComment, type TiktokPost, type TiktokUser, type TrackedItem, TrackedItemPlatform, TrackedItemType, type TwitterPost, type TwitterUser, type UsageHistoryBucket, VERSION, XpozClient, XpozConnectionError, XpozError, checkForUpdates };
923
+ export { type AccountBilling, type AccountDetails, type AccountUsage, type AddTrackedItemsResult, AuthenticationError, BillingPeriod, CreditResetFrequency, type CreditsUsageHistory, type CursorPageResponse, CursorResult, type InstagramComment, type InstagramConnectionType, type InstagramInteractionType, type InstagramPost, type InstagramUser, NotFoundError, OperationCancelledError, OperationFailedError, OperationTimeoutError, PaginatedResult, type PaginationInfo, type PlanFeatures, type RedditComment, type RedditPost, type RedditPostWithComments, type RedditSubreddit, type RedditUser, type RemoveTrackedItemsResult, ResponseType, type SubredditWithPosts, type TiktokComment, type TiktokPost, type TiktokUser, type TrackedItem, TrackedItemPlatform, TrackedItemType, type TwitterPost, type TwitterUser, type UsageHistoryBucket, VERSION, ValidationError, XpozClient, XpozConnectionError, XpozError, checkForUpdates };
package/dist/index.js CHANGED
@@ -248,7 +248,7 @@ function coerce(value) {
248
248
  }
249
249
 
250
250
  // src/version.ts
251
- var VERSION = "0.6.11";
251
+ var VERSION = "0.6.13";
252
252
 
253
253
  // src/mcp/transport.ts
254
254
  var USER_AGENT = `xpoz-ts-sdk/${VERSION}`;
@@ -343,6 +343,18 @@ var XpozConnectionError = class extends XpozError {
343
343
  this.name = "XpozConnectionError";
344
344
  }
345
345
  };
346
+ var NotFoundError = class extends XpozError {
347
+ constructor(message) {
348
+ super(message);
349
+ this.name = "NotFoundError";
350
+ }
351
+ };
352
+ var ValidationError = class extends XpozError {
353
+ constructor(message) {
354
+ super(message);
355
+ this.name = "ValidationError";
356
+ }
357
+ };
346
358
  var OperationTimeoutError = class extends XpozError {
347
359
  operationId;
348
360
  elapsedMs;
@@ -385,6 +397,216 @@ var ResponseType = /* @__PURE__ */ ((ResponseType2) => {
385
397
  var POLL_INTERVAL_MS = 5e3;
386
398
  var DEFAULT_TIMEOUT_MS = 3e5;
387
399
 
400
+ // src/config/routes.ts
401
+ var DEFAULT_API_URL = "https://api.xpoz.ai";
402
+ var ENV_API_URL = "XPOZ_API_URL";
403
+ var INSTAGRAM_BASE = "/api/data/instagram";
404
+ var INSTAGRAM_LIVE_ROUTES = {
405
+ posts: `${INSTAGRAM_BASE}/posts/live`,
406
+ userPosts: (identifier) => `${INSTAGRAM_BASE}/posts/users/${encodeURIComponent(identifier)}/live`,
407
+ post: (postId) => `${INSTAGRAM_BASE}/posts/${encodeURIComponent(postId)}/live`,
408
+ postComments: (postId) => `${INSTAGRAM_BASE}/posts/${encodeURIComponent(postId)}/comments/live`,
409
+ postInteractingUsers: (postId) => `${INSTAGRAM_BASE}/posts/${encodeURIComponent(postId)}/interacting-users/live`,
410
+ users: `${INSTAGRAM_BASE}/users/live`,
411
+ user: (identifier) => `${INSTAGRAM_BASE}/users/${encodeURIComponent(identifier)}/live`,
412
+ userConnections: (identifier) => `${INSTAGRAM_BASE}/users/${encodeURIComponent(identifier)}/connections/live`
413
+ };
414
+ var REST_TIMEOUT_MS = 12e4;
415
+
416
+ // src/rest/transport.ts
417
+ var USER_AGENT2 = `xpoz-ts-sdk/${VERSION}`;
418
+ function buildQuery(params) {
419
+ const search = new URLSearchParams();
420
+ for (const [key, value] of Object.entries(params)) {
421
+ if (value !== void 0 && value !== null && value !== "") {
422
+ search.append(key, String(value));
423
+ }
424
+ }
425
+ const query = search.toString();
426
+ return query ? `?${query}` : "";
427
+ }
428
+ async function extractErrorMessage(response) {
429
+ try {
430
+ const body = await response.json();
431
+ const message = body.error ?? body.message;
432
+ return typeof message === "string" ? message : response.statusText;
433
+ } catch {
434
+ return response.statusText;
435
+ }
436
+ }
437
+ async function raiseForStatus(response) {
438
+ if (response.ok) {
439
+ return;
440
+ }
441
+ const message = await extractErrorMessage(response);
442
+ if (response.status === 401 || response.status === 403) {
443
+ throw new AuthenticationError(message);
444
+ }
445
+ if (response.status === 404) {
446
+ throw new NotFoundError(message);
447
+ }
448
+ if (response.status === 400) {
449
+ throw new ValidationError(message);
450
+ }
451
+ throw new XpozError(`HTTP ${response.status}: ${message}`);
452
+ }
453
+ var RestTransport = class {
454
+ baseUrl;
455
+ apiKey;
456
+ timeoutMs;
457
+ constructor(baseUrl, apiKey, timeoutMs = REST_TIMEOUT_MS) {
458
+ this.baseUrl = baseUrl.replace(/\/+$/, "");
459
+ this.apiKey = apiKey;
460
+ this.timeoutMs = timeoutMs;
461
+ }
462
+ async get(path, params = {}) {
463
+ const url = `${this.baseUrl}${path}${buildQuery(params)}`;
464
+ const controller = new AbortController();
465
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
466
+ let response;
467
+ try {
468
+ response = await fetch(url, {
469
+ headers: {
470
+ Authorization: `Bearer ${this.apiKey}`,
471
+ "User-Agent": USER_AGENT2,
472
+ Accept: "application/json"
473
+ },
474
+ signal: controller.signal
475
+ });
476
+ } catch (error) {
477
+ const reason = error instanceof Error ? error.message : String(error);
478
+ throw new XpozConnectionError(reason);
479
+ } finally {
480
+ clearTimeout(timer);
481
+ }
482
+ await raiseForStatus(response);
483
+ return await response.json();
484
+ }
485
+ };
486
+
487
+ // src/cursor.ts
488
+ var CursorResult = class {
489
+ data;
490
+ hasMore;
491
+ nextPageCursor;
492
+ _fetchPage;
493
+ constructor(options) {
494
+ this.data = options.data;
495
+ this.hasMore = options.hasMore;
496
+ this.nextPageCursor = options.nextPageCursor;
497
+ this._fetchPage = options.fetchPage;
498
+ }
499
+ hasNextPage() {
500
+ return this.hasMore && this.nextPageCursor !== null;
501
+ }
502
+ async nextPage() {
503
+ if (!this.hasNextPage()) {
504
+ throw new RangeError("No more pages available");
505
+ }
506
+ return this._fetchPage(this.nextPageCursor);
507
+ }
508
+ async *pages() {
509
+ let page = this;
510
+ yield page;
511
+ while (page.hasNextPage()) {
512
+ page = await page.nextPage();
513
+ yield page;
514
+ }
515
+ }
516
+ async *items() {
517
+ for await (const page of this.pages()) {
518
+ yield* page.data;
519
+ }
520
+ }
521
+ [Symbol.iterator]() {
522
+ return this.data[Symbol.iterator]();
523
+ }
524
+ };
525
+
526
+ // src/namespaces/instagramLive.ts
527
+ var STRING_ID_FIELDS = ["id", "userId", "user_id", "postId", "post_id"];
528
+ function coerceStringIds(item) {
529
+ const record = item;
530
+ for (const field of STRING_ID_FIELDS) {
531
+ if (typeof record[field] === "number") {
532
+ record[field] = String(record[field]);
533
+ }
534
+ }
535
+ return item;
536
+ }
537
+ function csvFields(fields) {
538
+ return fields && fields.length > 0 ? fields.join(",") : void 0;
539
+ }
540
+ var InstagramLiveNamespace = class {
541
+ transport;
542
+ constructor(transport) {
543
+ this.transport = transport;
544
+ }
545
+ async page(path, params) {
546
+ const payload = await this.transport.get(path, params);
547
+ return new CursorResult({
548
+ data: (payload.results ?? []).map(coerceStringIds),
549
+ hasMore: Boolean(payload.has_more),
550
+ nextPageCursor: payload.next_page_cursor ?? null,
551
+ fetchPage: (cursor) => this.page(path, { ...params, cursor })
552
+ });
553
+ }
554
+ async single(path, params) {
555
+ const page = await this.page(path, params);
556
+ return page.data[0] ?? null;
557
+ }
558
+ async searchPosts(query, options = {}) {
559
+ return this.page(INSTAGRAM_LIVE_ROUTES.posts, {
560
+ q: query,
561
+ fields: csvFields(options.fields),
562
+ cursor: options.cursor
563
+ });
564
+ }
565
+ async getPostsByUser(identifier, options = {}) {
566
+ return this.page(INSTAGRAM_LIVE_ROUTES.userPosts(identifier), {
567
+ fields: csvFields(options.fields),
568
+ cursor: options.cursor
569
+ });
570
+ }
571
+ async getPost(postId, options = {}) {
572
+ return this.single(INSTAGRAM_LIVE_ROUTES.post(postId), {
573
+ fields: csvFields(options.fields)
574
+ });
575
+ }
576
+ async getComments(postId, options = {}) {
577
+ return this.page(INSTAGRAM_LIVE_ROUTES.postComments(postId), {
578
+ fields: csvFields(options.fields),
579
+ cursor: options.cursor
580
+ });
581
+ }
582
+ async getPostInteractingUsers(postId, interactionType, options = {}) {
583
+ return this.page(INSTAGRAM_LIVE_ROUTES.postInteractingUsers(postId), {
584
+ interactionType,
585
+ fields: csvFields(options.fields),
586
+ cursor: options.cursor
587
+ });
588
+ }
589
+ async searchUsers(name, options = {}) {
590
+ return this.page(INSTAGRAM_LIVE_ROUTES.users, {
591
+ name,
592
+ fields: csvFields(options.fields),
593
+ cursor: options.cursor
594
+ });
595
+ }
596
+ async getUser(identifier, options = {}) {
597
+ return this.single(INSTAGRAM_LIVE_ROUTES.user(identifier), {
598
+ fields: csvFields(options.fields)
599
+ });
600
+ }
601
+ async getUserConnections(identifier, connectionType, options = {}) {
602
+ return this.page(INSTAGRAM_LIVE_ROUTES.userConnections(identifier), {
603
+ connectionType,
604
+ fields: csvFields(options.fields),
605
+ cursor: options.cursor
606
+ });
607
+ }
608
+ };
609
+
388
610
  // src/mcp/polling.ts
389
611
  async function waitForResult(callTool, operationId, timeoutMs = DEFAULT_TIMEOUT_MS) {
390
612
  const start = Date.now();
@@ -1214,6 +1436,8 @@ var XpozClient = class {
1214
1436
  account;
1215
1437
  transport;
1216
1438
  versionCheck;
1439
+ restTransport;
1440
+ instagramLiveNamespace;
1217
1441
  constructor(options = {}) {
1218
1442
  const apiKey = options.apiKey ?? process.env[ENV_API_KEY];
1219
1443
  if (!apiKey) {
@@ -1225,6 +1449,8 @@ var XpozClient = class {
1225
1449
  const serverUrl = options.serverUrl ?? process.env[ENV_SERVER_URL] ?? DEFAULT_SERVER_URL;
1226
1450
  const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
1227
1451
  this.transport = new McpTransport(serverUrl, apiKey);
1452
+ const apiUrl = options.apiUrl ?? process.env[ENV_API_URL] ?? DEFAULT_API_URL;
1453
+ this.restTransport = new RestTransport(apiUrl, apiKey);
1228
1454
  const callTool = this.transport.callTool.bind(this.transport);
1229
1455
  this.twitter = new TwitterNamespace(callTool, timeoutMs);
1230
1456
  this.instagram = new InstagramNamespace(callTool, timeoutMs);
@@ -1233,6 +1459,12 @@ var XpozClient = class {
1233
1459
  this.tracking = new TrackingNamespace(callTool, timeoutMs);
1234
1460
  this.account = new AccountNamespace(callTool, timeoutMs);
1235
1461
  }
1462
+ get instagramLive() {
1463
+ if (!this.instagramLiveNamespace) {
1464
+ this.instagramLiveNamespace = new InstagramLiveNamespace(this.restTransport);
1465
+ }
1466
+ return this.instagramLiveNamespace;
1467
+ }
1236
1468
  async connect() {
1237
1469
  await this.transport.connect();
1238
1470
  if (this.versionCheck) {
@@ -1278,6 +1510,8 @@ export {
1278
1510
  AuthenticationError,
1279
1511
  BillingPeriod,
1280
1512
  CreditResetFrequency,
1513
+ CursorResult,
1514
+ NotFoundError,
1281
1515
  OperationCancelledError,
1282
1516
  OperationFailedError,
1283
1517
  OperationTimeoutError,
@@ -1286,6 +1520,7 @@ export {
1286
1520
  TrackedItemPlatform,
1287
1521
  TrackedItemType,
1288
1522
  VERSION,
1523
+ ValidationError,
1289
1524
  XpozClient,
1290
1525
  XpozConnectionError,
1291
1526
  XpozError,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xpoz/xpoz",
3
- "version": "0.6.11",
3
+ "version": "0.6.13",
4
4
  "description": "TypeScript SDK for the Xpoz social media intelligence platform",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",