@xpoz/xpoz 0.1.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/dist/index.js ADDED
@@ -0,0 +1,914 @@
1
+ // src/mcp/transport.ts
2
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
3
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
4
+
5
+ // src/transform/responseParser.ts
6
+ function parseResponseText(text) {
7
+ if (!text.trim()) return {};
8
+ if (text.trimStart().startsWith("{")) {
9
+ try {
10
+ return JSON.parse(text);
11
+ } catch {
12
+ }
13
+ }
14
+ const lines = text.split("\n");
15
+ if (lines[0].startsWith("operationId:")) {
16
+ return parseFlatKv(lines);
17
+ }
18
+ const result = {};
19
+ let i = 0;
20
+ while (i < lines.length) {
21
+ const line = lines[i];
22
+ if (!line.trim()) {
23
+ i++;
24
+ continue;
25
+ }
26
+ const arrayMatch = line.match(/^data\[(\d+)\]\{(.+)\}:/);
27
+ if (arrayMatch) {
28
+ const fields = arrayMatch[2].split(",").map((f) => f.trim());
29
+ i++;
30
+ result["results"] = parseCsvRows(lines, i, 2, fields);
31
+ i += countIndented(lines, i, 2);
32
+ continue;
33
+ }
34
+ const yamlListMatch = line.match(/^data\[(\d+)\]:/);
35
+ if (yamlListMatch) {
36
+ i++;
37
+ result["results"] = parseYamlList(lines, i, 2);
38
+ i += countIndented(lines, i, 2);
39
+ continue;
40
+ }
41
+ if (line === "data:") {
42
+ i++;
43
+ const [data, consumed] = parseDataBlock(lines, i);
44
+ Object.assign(result, data);
45
+ i += consumed;
46
+ continue;
47
+ }
48
+ if (line.startsWith("success:")) {
49
+ i++;
50
+ continue;
51
+ }
52
+ const kvMatch = line.match(/^(\S+?):\s*(.*)/);
53
+ if (kvMatch) {
54
+ result[kvMatch[1]] = coerce(kvMatch[2]);
55
+ }
56
+ i++;
57
+ }
58
+ return result;
59
+ }
60
+ function parseFlatKv(lines) {
61
+ const result = {};
62
+ for (const line of lines) {
63
+ const m = line.match(/^(\S+?):\s*(.*)/);
64
+ if (m) {
65
+ result[m[1]] = coerce(m[2]);
66
+ }
67
+ }
68
+ return result;
69
+ }
70
+ function parseDataBlock(lines, start) {
71
+ return parseBlock(lines, start, 2);
72
+ }
73
+ function parseBlock(lines, start, indent) {
74
+ const result = {};
75
+ const prefix = " ".repeat(indent);
76
+ let i = start;
77
+ while (i < lines.length) {
78
+ const line = lines[i];
79
+ if (!line.startsWith(prefix)) break;
80
+ if (line.length > prefix.length && line[prefix.length] === " ") break;
81
+ const stripped = line.slice(indent);
82
+ const arrayMatch = stripped.match(/^(\w+)\[(\d+)\]\{(.+)\}:/);
83
+ if (arrayMatch) {
84
+ const key = arrayMatch[1];
85
+ const fields = arrayMatch[3].split(",").map((f) => f.trim());
86
+ i++;
87
+ result[key] = parseCsvRows(lines, i, indent + 2, fields);
88
+ i += countIndented(lines, i, indent + 2);
89
+ continue;
90
+ }
91
+ const yamlListMatch = stripped.match(/^(\w+)\[(\d+)\]:/);
92
+ if (yamlListMatch) {
93
+ const key = yamlListMatch[1];
94
+ i++;
95
+ result[key] = parseYamlList(lines, i, indent + 2);
96
+ i += countIndented(lines, i, indent + 2);
97
+ continue;
98
+ }
99
+ const kvMatch = stripped.match(/^(\S+?):\s*(.*)/);
100
+ if (kvMatch) {
101
+ const key = kvMatch[1];
102
+ const val = kvMatch[2];
103
+ if (val) {
104
+ result[key] = coerce(val);
105
+ i++;
106
+ } else {
107
+ const childPrefix = " ".repeat(indent + 2);
108
+ if (i + 1 < lines.length && lines[i + 1].startsWith(childPrefix)) {
109
+ i++;
110
+ const [nested, consumed] = parseBlock(lines, i, indent + 2);
111
+ result[key] = nested;
112
+ i += consumed;
113
+ } else {
114
+ result[key] = null;
115
+ i++;
116
+ }
117
+ }
118
+ continue;
119
+ }
120
+ i++;
121
+ }
122
+ return [result, i - start];
123
+ }
124
+ function parseYamlList(lines, start, indent) {
125
+ const rows = [];
126
+ const prefix = " ".repeat(indent);
127
+ const itemPrefix = prefix + "- ";
128
+ const continuationPrefix = prefix + " ";
129
+ let i = start;
130
+ while (i < lines.length) {
131
+ const line = lines[i];
132
+ if (!line.startsWith(prefix)) break;
133
+ if (!line.trim()) {
134
+ i++;
135
+ continue;
136
+ }
137
+ if (line.startsWith(itemPrefix)) {
138
+ const row = {};
139
+ const firstKv = line.slice(itemPrefix.length);
140
+ const m = firstKv.match(/^(\S+?):\s*(.*)/);
141
+ if (m) {
142
+ row[m[1]] = coerce(m[2]);
143
+ }
144
+ i++;
145
+ while (i < lines.length) {
146
+ const cline = lines[i];
147
+ if (!cline.startsWith(continuationPrefix)) break;
148
+ if (cline.startsWith(itemPrefix)) break;
149
+ const stripped = cline.slice(continuationPrefix.length);
150
+ const cm = stripped.match(/^(\S+?):\s*(.*)/);
151
+ if (cm) {
152
+ row[cm[1]] = coerce(cm[2]);
153
+ }
154
+ i++;
155
+ }
156
+ rows.push(row);
157
+ } else {
158
+ i++;
159
+ }
160
+ }
161
+ return rows;
162
+ }
163
+ function parseCsvRows(lines, start, indent, fields) {
164
+ const rows = [];
165
+ const prefix = " ".repeat(indent);
166
+ let i = start;
167
+ while (i < lines.length) {
168
+ const line = lines[i];
169
+ if (!line.startsWith(prefix)) break;
170
+ const rawRow = line.slice(indent);
171
+ if (!rawRow.trim()) {
172
+ i++;
173
+ continue;
174
+ }
175
+ const values = splitToonRow(rawRow);
176
+ const row = {};
177
+ for (let j = 0; j < fields.length; j++) {
178
+ row[fields[j]] = j < values.length ? coerce(values[j]) : null;
179
+ }
180
+ rows.push(row);
181
+ i++;
182
+ }
183
+ return rows;
184
+ }
185
+ function splitToonRow(line) {
186
+ const values = [];
187
+ let buf = "";
188
+ let inQuotes = false;
189
+ let i = 0;
190
+ while (i < line.length) {
191
+ const ch = line[i];
192
+ if (ch === "\\" && inQuotes && i + 1 < line.length) {
193
+ buf += ch + line[i + 1];
194
+ i += 2;
195
+ continue;
196
+ }
197
+ if (ch === '"') {
198
+ inQuotes = !inQuotes;
199
+ buf += ch;
200
+ i++;
201
+ continue;
202
+ }
203
+ if (ch === "," && !inQuotes) {
204
+ values.push(buf.trim());
205
+ buf = "";
206
+ i++;
207
+ continue;
208
+ }
209
+ buf += ch;
210
+ i++;
211
+ }
212
+ if (buf || values.length) {
213
+ values.push(buf.trim());
214
+ }
215
+ return values;
216
+ }
217
+ function countIndented(lines, start, indent) {
218
+ const prefix = " ".repeat(indent);
219
+ let count = 0;
220
+ let i = start;
221
+ while (i < lines.length) {
222
+ if (!lines[i].startsWith(prefix) && lines[i].trim()) break;
223
+ count++;
224
+ i++;
225
+ }
226
+ return count;
227
+ }
228
+ function coerce(value) {
229
+ if (!value) return null;
230
+ if (value.startsWith('"') && value.endsWith('"')) {
231
+ return value.slice(1, -1);
232
+ }
233
+ if (value === "true") return true;
234
+ if (value === "false") return false;
235
+ if (value === "null" || value === "None") return null;
236
+ const intVal = parseInt(value, 10);
237
+ if (!isNaN(intVal) && String(intVal) === value) {
238
+ if (intVal >= -9007199254740991 && intVal <= 9007199254740991) {
239
+ return intVal;
240
+ }
241
+ return value;
242
+ }
243
+ const floatVal = parseFloat(value);
244
+ if (!isNaN(floatVal) && String(floatVal) === value) {
245
+ return floatVal;
246
+ }
247
+ return value;
248
+ }
249
+
250
+ // src/version.ts
251
+ var VERSION = "0.1.0";
252
+
253
+ // src/mcp/transport.ts
254
+ var USER_AGENT = `xpoz-ts-sdk/${VERSION}`;
255
+ var McpTransport = class {
256
+ serverUrl;
257
+ apiKey;
258
+ client = null;
259
+ transport = null;
260
+ constructor(serverUrl, apiKey) {
261
+ this.serverUrl = serverUrl;
262
+ this.apiKey = apiKey;
263
+ }
264
+ async connect() {
265
+ const headers = {
266
+ "User-Agent": USER_AGENT,
267
+ Authorization: `Bearer ${this.apiKey}`
268
+ };
269
+ this.transport = new StreamableHTTPClientTransport(new URL(this.serverUrl), {
270
+ requestInit: { headers }
271
+ });
272
+ this.client = new Client(
273
+ { name: "xpoz-ts-sdk", version: VERSION },
274
+ { capabilities: {} }
275
+ );
276
+ await this.client.connect(this.transport);
277
+ }
278
+ async close() {
279
+ if (this.client) {
280
+ try {
281
+ await this.client.close();
282
+ } catch {
283
+ }
284
+ this.client = null;
285
+ this.transport = null;
286
+ }
287
+ }
288
+ async callTool(name, args) {
289
+ if (!this.client) {
290
+ throw new Error("Transport not connected. Call connect() first.");
291
+ }
292
+ const result = await this.client.callTool({ name, arguments: args });
293
+ if (result.isError) {
294
+ let errorText = "";
295
+ for (const block of result.content) {
296
+ if (block.text !== void 0) {
297
+ errorText += block.text;
298
+ }
299
+ }
300
+ throw new Error(`MCP tool error (${name}): ${errorText}`);
301
+ }
302
+ let combinedText = "";
303
+ for (const block of result.content) {
304
+ if (block.text !== void 0) {
305
+ combinedText += block.text;
306
+ }
307
+ }
308
+ return parseResponseText(combinedText);
309
+ }
310
+ };
311
+
312
+ // src/errors.ts
313
+ var XpozError = class extends Error {
314
+ constructor(message) {
315
+ super(message);
316
+ this.name = "XpozError";
317
+ }
318
+ };
319
+ var AuthenticationError = class extends XpozError {
320
+ constructor(message) {
321
+ super(message);
322
+ this.name = "AuthenticationError";
323
+ }
324
+ };
325
+ var XpozConnectionError = class extends XpozError {
326
+ constructor(message) {
327
+ super(message);
328
+ this.name = "XpozConnectionError";
329
+ }
330
+ };
331
+ var OperationTimeoutError = class extends XpozError {
332
+ operationId;
333
+ elapsedMs;
334
+ constructor(operationId, elapsedMs) {
335
+ super(`Operation ${operationId} timed out after ${Math.round(elapsedMs / 1e3)}s`);
336
+ this.name = "OperationTimeoutError";
337
+ this.operationId = operationId;
338
+ this.elapsedMs = elapsedMs;
339
+ }
340
+ };
341
+ var OperationFailedError = class extends XpozError {
342
+ operationId;
343
+ operationError;
344
+ constructor(operationId, error) {
345
+ super(`Operation ${operationId} failed: ${error}`);
346
+ this.name = "OperationFailedError";
347
+ this.operationId = operationId;
348
+ this.operationError = error;
349
+ }
350
+ };
351
+ var OperationCancelledError = class extends XpozError {
352
+ operationId;
353
+ constructor(operationId) {
354
+ super(`Operation ${operationId} was cancelled`);
355
+ this.name = "OperationCancelledError";
356
+ this.operationId = operationId;
357
+ }
358
+ };
359
+
360
+ // src/config/constants.ts
361
+ var DEFAULT_SERVER_URL = "https://mcp.xpoz.ai/mcp";
362
+ var ENV_API_KEY = "XPOZ_API_KEY";
363
+ var ENV_SERVER_URL = "XPOZ_SERVER_URL";
364
+ var POLL_INTERVAL_MS = 5e3;
365
+ var DEFAULT_TIMEOUT_MS = 3e5;
366
+
367
+ // src/mcp/polling.ts
368
+ async function waitForResult(callTool, operationId, timeoutMs = DEFAULT_TIMEOUT_MS) {
369
+ const start = Date.now();
370
+ while (true) {
371
+ const result = await callTool("checkOperationStatus", { operationId });
372
+ const status = result["status"];
373
+ if (status === "failed") {
374
+ const error = result["error"] ?? "Unknown error";
375
+ throw new OperationFailedError(operationId, String(error));
376
+ }
377
+ if (status === "cancelled") {
378
+ throw new OperationCancelledError(operationId);
379
+ }
380
+ if (status === "completed" || "results" in result || "downloadUrl" in result) {
381
+ return result;
382
+ }
383
+ const elapsed = Date.now() - start;
384
+ if (elapsed >= timeoutMs) {
385
+ throw new OperationTimeoutError(operationId, elapsed);
386
+ }
387
+ await sleep(POLL_INTERVAL_MS);
388
+ }
389
+ }
390
+ function sleep(ms) {
391
+ return new Promise((resolve) => setTimeout(resolve, ms));
392
+ }
393
+
394
+ // src/pagination.ts
395
+ var PaginatedResult = class {
396
+ data;
397
+ pagination;
398
+ _tableName;
399
+ _exportOperationId;
400
+ _fetchPage;
401
+ _fetchExport;
402
+ constructor(options) {
403
+ this.data = options.data;
404
+ this.pagination = options.pagination;
405
+ this._tableName = options.tableName;
406
+ this._exportOperationId = options.exportOperationId;
407
+ this._fetchPage = options.fetchPage;
408
+ this._fetchExport = options.fetchExport;
409
+ }
410
+ hasNextPage() {
411
+ return this.pagination.pageNumber < this.pagination.totalPages;
412
+ }
413
+ async nextPage() {
414
+ if (!this.hasNextPage()) {
415
+ throw new RangeError("No more pages available");
416
+ }
417
+ return this._fetchPageResult(this.pagination.pageNumber + 1);
418
+ }
419
+ async getPage(pageNumber) {
420
+ if (pageNumber < 1 || pageNumber > this.pagination.totalPages) {
421
+ throw new RangeError(
422
+ `Page ${pageNumber} out of range (1-${this.pagination.totalPages})`
423
+ );
424
+ }
425
+ return this._fetchPageResult(pageNumber);
426
+ }
427
+ async exportCsv() {
428
+ if (!this._fetchExport || !this._exportOperationId) {
429
+ throw new Error("CSV export not available for this result");
430
+ }
431
+ return this._fetchExport(this._exportOperationId);
432
+ }
433
+ _fetchPageResult(pageNumber) {
434
+ return this._fetchPage(pageNumber, this._tableName);
435
+ }
436
+ toString() {
437
+ return `PaginatedResult(items=${this.data.length}, page=${this.pagination.pageNumber}/${this.pagination.totalPages}, total=${this.pagination.totalRows})`;
438
+ }
439
+ };
440
+
441
+ // src/namespaces/base.ts
442
+ function extractPagination(raw) {
443
+ const pag = raw["pagination"] ?? {};
444
+ return {
445
+ tableName: pag["tableName"] ?? null,
446
+ totalRows: pag["totalRows"] ?? 0,
447
+ totalPages: pag["totalPages"] ?? 0,
448
+ pageNumber: pag["pageNumber"] ?? 1,
449
+ pageSize: pag["pageSize"] ?? 100,
450
+ resultsCount: pag["resultsCount"] ?? 0
451
+ };
452
+ }
453
+ function extractResults(raw) {
454
+ return raw["results"] ?? [];
455
+ }
456
+ function extractExportOpId(raw) {
457
+ return raw["dataDumpExportOperationId"] ?? null;
458
+ }
459
+ var BaseNamespace = class {
460
+ callTool;
461
+ timeoutMs;
462
+ constructor(callTool, timeoutMs = DEFAULT_TIMEOUT_MS) {
463
+ this.callTool = callTool;
464
+ this.timeoutMs = timeoutMs;
465
+ }
466
+ async callAndMaybePoll(toolName, args) {
467
+ const result = await this.callTool(toolName, args);
468
+ const operationId = result["operationId"];
469
+ if (operationId) {
470
+ return waitForResult(this.callTool, operationId, this.timeoutMs);
471
+ }
472
+ return result;
473
+ }
474
+ buildPaginatedResult(raw, parseItem, toolName, baseArgs) {
475
+ const items = extractResults(raw).map(parseItem);
476
+ const pagination = extractPagination(raw);
477
+ const tableName = pagination.tableName;
478
+ const exportOpId = extractExportOpId(raw);
479
+ const fetchPage = async (pageNumber, tbl) => {
480
+ const args = { ...baseArgs, pageNumber };
481
+ if (tbl) args["tableName"] = tbl;
482
+ const pageRaw = await this.callAndMaybePoll(toolName, args);
483
+ return this.buildPaginatedResult(pageRaw, parseItem, toolName, baseArgs);
484
+ };
485
+ const fetchExport = async (opId) => {
486
+ const pollResult = await waitForResult(this.callTool, opId, this.timeoutMs);
487
+ return pollResult["downloadUrl"] ?? "";
488
+ };
489
+ return new PaginatedResult({
490
+ data: items,
491
+ pagination,
492
+ tableName,
493
+ exportOperationId: exportOpId,
494
+ fetchPage,
495
+ fetchExport
496
+ });
497
+ }
498
+ buildArgs(args) {
499
+ const result = {};
500
+ for (const [key, value] of Object.entries(args)) {
501
+ if (value !== void 0 && value !== null) {
502
+ result[key] = value;
503
+ }
504
+ }
505
+ return result;
506
+ }
507
+ extractPagination(raw) {
508
+ return extractPagination(raw);
509
+ }
510
+ extractResults(raw) {
511
+ return extractResults(raw);
512
+ }
513
+ };
514
+
515
+ // src/config/tools.ts
516
+ var GET_TWITTER_POSTS_BY_IDS = "getTwitterPostsByIds";
517
+ var GET_TWITTER_POSTS_BY_AUTHOR = "getTwitterPostsByAuthor";
518
+ var SEARCH_TWITTER_POSTS = "getTwitterPostsByKeywords";
519
+ var GET_TWITTER_RETWEETS = "getTwitterPostRetweets";
520
+ var GET_TWITTER_QUOTES = "getTwitterPostQuotes";
521
+ var GET_TWITTER_COMMENTS = "getTwitterPostComments";
522
+ var GET_TWITTER_POST_INTERACTING_USERS = "getTwitterPostInteractingUsers";
523
+ var COUNT_TWEETS = "countTweets";
524
+ var GET_TWITTER_USER = "getTwitterUser";
525
+ var SEARCH_TWITTER_USERS = "searchTwitterUsers";
526
+ var GET_TWITTER_USER_CONNECTIONS = "getTwitterUserConnections";
527
+ var GET_TWITTER_USERS_BY_KEYWORDS = "getTwitterUsersByKeywords";
528
+ var GET_INSTAGRAM_POSTS_BY_IDS = "getInstagramPostsByIds";
529
+ var GET_INSTAGRAM_POSTS_BY_USER = "getInstagramPostsByUser";
530
+ var SEARCH_INSTAGRAM_POSTS = "getInstagramPostsByKeywords";
531
+ var GET_INSTAGRAM_COMMENTS = "getInstagramCommentsByPostId";
532
+ var GET_INSTAGRAM_USER = "getInstagramUser";
533
+ var SEARCH_INSTAGRAM_USERS = "searchInstagramUsers";
534
+ var GET_INSTAGRAM_USER_CONNECTIONS = "getInstagramUserConnections";
535
+ var GET_INSTAGRAM_POST_INTERACTING_USERS = "getInstagramPostInteractingUsers";
536
+ var GET_INSTAGRAM_USERS_BY_KEYWORDS = "getInstagramUsersByKeywords";
537
+ var SEARCH_REDDIT_POSTS = "getRedditPostsByKeywords";
538
+ var GET_REDDIT_POST_WITH_COMMENTS = "getRedditPostWithCommentsById";
539
+ var SEARCH_REDDIT_COMMENTS = "getRedditCommentsByKeywords";
540
+ var GET_REDDIT_USER = "getRedditUser";
541
+ var SEARCH_REDDIT_USERS = "searchRedditUsers";
542
+ var GET_REDDIT_USERS_BY_KEYWORDS = "getRedditUsersByKeywords";
543
+ var SEARCH_REDDIT_SUBREDDITS = "searchRedditSubreddits";
544
+ var GET_REDDIT_SUBREDDIT_WITH_POSTS = "getRedditSubredditWithPostsByName";
545
+ var GET_REDDIT_SUBREDDITS_BY_KEYWORDS = "getRedditSubredditsByKeywords";
546
+
547
+ // src/namespaces/twitter.ts
548
+ function parseTwitterPost(item) {
549
+ return item;
550
+ }
551
+ function parseUser(item) {
552
+ return item;
553
+ }
554
+ var TwitterNamespace = class extends BaseNamespace {
555
+ async getPostsByIds(postIds, options = {}) {
556
+ const args = this.buildArgs({ postIds, ...options });
557
+ const result = await this.callAndMaybePoll(GET_TWITTER_POSTS_BY_IDS, args);
558
+ return (result["results"] ?? []).map(parseTwitterPost);
559
+ }
560
+ async getPostsByAuthor(identifier, options = {}) {
561
+ const args = this.buildArgs({
562
+ identifier,
563
+ identifierType: options.identifierType ?? "username",
564
+ fields: options.fields,
565
+ startDate: options.startDate,
566
+ endDate: options.endDate,
567
+ forceLatest: options.forceLatest
568
+ });
569
+ const result = await this.callAndMaybePoll(GET_TWITTER_POSTS_BY_AUTHOR, args);
570
+ return this.buildPaginatedResult(result, parseTwitterPost, GET_TWITTER_POSTS_BY_AUTHOR, args);
571
+ }
572
+ async searchPosts(query, options = {}) {
573
+ const args = this.buildArgs({
574
+ query,
575
+ fields: options.fields,
576
+ startDate: options.startDate,
577
+ endDate: options.endDate,
578
+ authorUsername: options.authorUsername,
579
+ authorId: options.authorId,
580
+ language: options.language,
581
+ forceLatest: options.forceLatest,
582
+ responseType: options.responseType
583
+ });
584
+ if (options.responseType === "csv") {
585
+ const raw = await this.callTool(SEARCH_TWITTER_POSTS, args);
586
+ const exportOpId = raw["operationId"] ?? raw["dataDumpExportOperationId"] ?? null;
587
+ const csvRaw = { results: [], dataDumpExportOperationId: exportOpId };
588
+ return this.buildPaginatedResult(csvRaw, parseTwitterPost, SEARCH_TWITTER_POSTS, args);
589
+ }
590
+ const result = await this.callAndMaybePoll(SEARCH_TWITTER_POSTS, args);
591
+ return this.buildPaginatedResult(result, parseTwitterPost, SEARCH_TWITTER_POSTS, args);
592
+ }
593
+ async getRetweets(postId, options = {}) {
594
+ const args = this.buildArgs({ postId, ...options });
595
+ const result = await this.callAndMaybePoll(GET_TWITTER_RETWEETS, args);
596
+ return this.buildPaginatedResult(result, parseTwitterPost, GET_TWITTER_RETWEETS, args);
597
+ }
598
+ async getQuotes(postId, options = {}) {
599
+ const args = this.buildArgs({ postId, ...options });
600
+ const result = await this.callAndMaybePoll(GET_TWITTER_QUOTES, args);
601
+ return this.buildPaginatedResult(result, parseTwitterPost, GET_TWITTER_QUOTES, args);
602
+ }
603
+ async getComments(postId, options = {}) {
604
+ const args = this.buildArgs({ postId, ...options });
605
+ const result = await this.callAndMaybePoll(GET_TWITTER_COMMENTS, args);
606
+ return this.buildPaginatedResult(result, parseTwitterPost, GET_TWITTER_COMMENTS, args);
607
+ }
608
+ async getPostInteractingUsers(postId, interactionType, options = {}) {
609
+ const args = this.buildArgs({ postId, interactionType, ...options });
610
+ const result = await this.callAndMaybePoll(GET_TWITTER_POST_INTERACTING_USERS, args);
611
+ return this.buildPaginatedResult(
612
+ result,
613
+ parseUser,
614
+ GET_TWITTER_POST_INTERACTING_USERS,
615
+ args
616
+ );
617
+ }
618
+ async countPosts(phrase, options = {}) {
619
+ const args = this.buildArgs({ phrase, ...options });
620
+ const result = await this.callAndMaybePoll(COUNT_TWEETS, args);
621
+ const count = result["results"] ?? result["count"] ?? 0;
622
+ if (Array.isArray(count)) {
623
+ if (count.length === 0) return 0;
624
+ const first = count[0];
625
+ if (first !== null && typeof first === "object") {
626
+ return Number(Object.values(first)[0]);
627
+ }
628
+ return Number(first);
629
+ }
630
+ return Number(count);
631
+ }
632
+ async getUser(identifier, options = {}) {
633
+ const args = this.buildArgs({
634
+ identifier,
635
+ identifierType: options.identifierType ?? "username",
636
+ fields: options.fields
637
+ });
638
+ const result = await this.callAndMaybePoll(GET_TWITTER_USER, args);
639
+ const results = result["results"];
640
+ if (Array.isArray(results) && results.length > 0) {
641
+ return results[0];
642
+ }
643
+ return result;
644
+ }
645
+ async searchUsers(name, options = {}) {
646
+ const args = this.buildArgs({ name, ...options });
647
+ const result = await this.callAndMaybePoll(SEARCH_TWITTER_USERS, args);
648
+ return (result["results"] ?? []).map(parseUser);
649
+ }
650
+ async getUserConnections(username, connectionType, options = {}) {
651
+ const args = this.buildArgs({ username, connectionType, ...options });
652
+ const result = await this.callAndMaybePoll(GET_TWITTER_USER_CONNECTIONS, args);
653
+ return this.buildPaginatedResult(
654
+ result,
655
+ parseUser,
656
+ GET_TWITTER_USER_CONNECTIONS,
657
+ args
658
+ );
659
+ }
660
+ async getUsersByKeywords(query, options = {}) {
661
+ const args = this.buildArgs({ query, ...options });
662
+ const result = await this.callAndMaybePoll(GET_TWITTER_USERS_BY_KEYWORDS, args);
663
+ return this.buildPaginatedResult(
664
+ result,
665
+ parseUser,
666
+ GET_TWITTER_USERS_BY_KEYWORDS,
667
+ args
668
+ );
669
+ }
670
+ };
671
+
672
+ // src/namespaces/instagram.ts
673
+ function parsePost(item) {
674
+ return item;
675
+ }
676
+ function parseUser2(item) {
677
+ return item;
678
+ }
679
+ function parseComment(item) {
680
+ return item;
681
+ }
682
+ var InstagramNamespace = class extends BaseNamespace {
683
+ async getPostsByIds(postIds, options = {}) {
684
+ const args = this.buildArgs({ postIds, ...options });
685
+ const result = await this.callAndMaybePoll(GET_INSTAGRAM_POSTS_BY_IDS, args);
686
+ return (result["results"] ?? []).map(parsePost);
687
+ }
688
+ async getPostsByUser(identifier, options = {}) {
689
+ const args = this.buildArgs({
690
+ identifier,
691
+ identifierType: options.identifierType ?? "username",
692
+ fields: options.fields,
693
+ startDate: options.startDate,
694
+ endDate: options.endDate,
695
+ forceLatest: options.forceLatest
696
+ });
697
+ const result = await this.callAndMaybePoll(GET_INSTAGRAM_POSTS_BY_USER, args);
698
+ return this.buildPaginatedResult(
699
+ result,
700
+ parsePost,
701
+ GET_INSTAGRAM_POSTS_BY_USER,
702
+ args
703
+ );
704
+ }
705
+ async searchPosts(query, options = {}) {
706
+ const args = this.buildArgs({ query, ...options });
707
+ const result = await this.callAndMaybePoll(SEARCH_INSTAGRAM_POSTS, args);
708
+ return this.buildPaginatedResult(result, parsePost, SEARCH_INSTAGRAM_POSTS, args);
709
+ }
710
+ async getComments(postId, options = {}) {
711
+ const args = this.buildArgs({ postId, ...options });
712
+ const result = await this.callAndMaybePoll(GET_INSTAGRAM_COMMENTS, args);
713
+ return this.buildPaginatedResult(result, parseComment, GET_INSTAGRAM_COMMENTS, args);
714
+ }
715
+ async getUser(identifier, options = {}) {
716
+ const args = this.buildArgs({
717
+ identifier,
718
+ identifierType: options.identifierType ?? "username",
719
+ fields: options.fields
720
+ });
721
+ const result = await this.callAndMaybePoll(GET_INSTAGRAM_USER, args);
722
+ const results = result["results"];
723
+ if (Array.isArray(results) && results.length > 0) {
724
+ return results[0];
725
+ }
726
+ return result;
727
+ }
728
+ async searchUsers(name, options = {}) {
729
+ const args = this.buildArgs({ name, ...options });
730
+ const result = await this.callAndMaybePoll(SEARCH_INSTAGRAM_USERS, args);
731
+ return (result["results"] ?? []).map(parseUser2);
732
+ }
733
+ async getUserConnections(username, connectionType, options = {}) {
734
+ const args = this.buildArgs({ username, connectionType, ...options });
735
+ const result = await this.callAndMaybePoll(GET_INSTAGRAM_USER_CONNECTIONS, args);
736
+ return this.buildPaginatedResult(
737
+ result,
738
+ parseUser2,
739
+ GET_INSTAGRAM_USER_CONNECTIONS,
740
+ args
741
+ );
742
+ }
743
+ async getPostInteractingUsers(postId, interactionType, options = {}) {
744
+ const args = this.buildArgs({ postId, interactionType, ...options });
745
+ const result = await this.callAndMaybePoll(
746
+ GET_INSTAGRAM_POST_INTERACTING_USERS,
747
+ args
748
+ );
749
+ return this.buildPaginatedResult(
750
+ result,
751
+ parseUser2,
752
+ GET_INSTAGRAM_POST_INTERACTING_USERS,
753
+ args
754
+ );
755
+ }
756
+ async getUsersByKeywords(query, options = {}) {
757
+ const args = this.buildArgs({ query, ...options });
758
+ const result = await this.callAndMaybePoll(GET_INSTAGRAM_USERS_BY_KEYWORDS, args);
759
+ return this.buildPaginatedResult(
760
+ result,
761
+ parseUser2,
762
+ GET_INSTAGRAM_USERS_BY_KEYWORDS,
763
+ args
764
+ );
765
+ }
766
+ };
767
+
768
+ // src/namespaces/reddit.ts
769
+ function parsePost2(item) {
770
+ return item;
771
+ }
772
+ function parseUser3(item) {
773
+ return item;
774
+ }
775
+ function parseComment2(item) {
776
+ return item;
777
+ }
778
+ function parseSubreddit(item) {
779
+ return item;
780
+ }
781
+ var RedditNamespace = class extends BaseNamespace {
782
+ async searchPosts(query, options = {}) {
783
+ const args = this.buildArgs({ query, ...options });
784
+ const result = await this.callAndMaybePoll(SEARCH_REDDIT_POSTS, args);
785
+ return this.buildPaginatedResult(result, parsePost2, SEARCH_REDDIT_POSTS, args);
786
+ }
787
+ async getPostWithComments(postId, options = {}) {
788
+ const args = this.buildArgs({ postId, ...options });
789
+ const result = await this.callAndMaybePoll(GET_REDDIT_POST_WITH_COMMENTS, args);
790
+ return this._parsePostWithComments(result);
791
+ }
792
+ async searchComments(query, options = {}) {
793
+ const args = this.buildArgs({ query, ...options });
794
+ const result = await this.callAndMaybePoll(SEARCH_REDDIT_COMMENTS, args);
795
+ return this.buildPaginatedResult(result, parseComment2, SEARCH_REDDIT_COMMENTS, args);
796
+ }
797
+ async getUser(username, options = {}) {
798
+ const args = this.buildArgs({ username, ...options });
799
+ const result = await this.callAndMaybePoll(GET_REDDIT_USER, args);
800
+ const results = result["results"];
801
+ if (Array.isArray(results) && results.length > 0) {
802
+ return results[0];
803
+ }
804
+ return result;
805
+ }
806
+ async searchUsers(name, options = {}) {
807
+ const args = this.buildArgs({ name, ...options });
808
+ const result = await this.callAndMaybePoll(SEARCH_REDDIT_USERS, args);
809
+ return (result["results"] ?? []).map(parseUser3);
810
+ }
811
+ async getUsersByKeywords(query, options = {}) {
812
+ const args = this.buildArgs({ query, ...options });
813
+ const result = await this.callAndMaybePoll(GET_REDDIT_USERS_BY_KEYWORDS, args);
814
+ return this.buildPaginatedResult(
815
+ result,
816
+ parseUser3,
817
+ GET_REDDIT_USERS_BY_KEYWORDS,
818
+ args
819
+ );
820
+ }
821
+ async searchSubreddits(query, options = {}) {
822
+ const args = this.buildArgs({ query, ...options });
823
+ const result = await this.callAndMaybePoll(SEARCH_REDDIT_SUBREDDITS, args);
824
+ return (result["results"] ?? []).map(parseSubreddit);
825
+ }
826
+ async getSubredditWithPosts(subredditName, options = {}) {
827
+ const args = this.buildArgs({ subredditName, ...options });
828
+ const result = await this.callAndMaybePoll(GET_REDDIT_SUBREDDIT_WITH_POSTS, args);
829
+ return this._parseSubredditWithPosts(result);
830
+ }
831
+ async getSubredditsByKeywords(query, options = {}) {
832
+ const args = this.buildArgs({ query, ...options });
833
+ const result = await this.callAndMaybePoll(GET_REDDIT_SUBREDDITS_BY_KEYWORDS, args);
834
+ return this.buildPaginatedResult(
835
+ result,
836
+ parseSubreddit,
837
+ GET_REDDIT_SUBREDDITS_BY_KEYWORDS,
838
+ args
839
+ );
840
+ }
841
+ _parsePostWithComments(raw) {
842
+ let results = raw["results"] ?? {};
843
+ if (Array.isArray(results)) {
844
+ results = results.length > 0 ? results[0] : {};
845
+ }
846
+ const postData = results["post"] ?? results;
847
+ const commentsData = results["comments"] ?? [];
848
+ const pagination = this.extractPagination(raw);
849
+ return {
850
+ post: postData,
851
+ comments: commentsData.map(parseComment2),
852
+ commentsPagination: pagination.totalPages > 0 ? pagination : null,
853
+ commentsTableName: pagination.tableName ?? null
854
+ };
855
+ }
856
+ _parseSubredditWithPosts(raw) {
857
+ let results = raw["results"] ?? {};
858
+ if (Array.isArray(results)) {
859
+ results = results.length > 0 ? results[0] : {};
860
+ }
861
+ const subredditData = results["subreddit"] ?? results;
862
+ const postsData = results["posts"] ?? [];
863
+ const pagination = this.extractPagination(raw);
864
+ return {
865
+ subreddit: subredditData,
866
+ posts: postsData.map(parsePost2),
867
+ postsPagination: pagination.totalPages > 0 ? pagination : null,
868
+ postsTableName: pagination.tableName ?? null
869
+ };
870
+ }
871
+ };
872
+
873
+ // src/client.ts
874
+ var XpozClient = class {
875
+ twitter;
876
+ instagram;
877
+ reddit;
878
+ transport;
879
+ constructor(options = {}) {
880
+ const apiKey = options.apiKey ?? process.env[ENV_API_KEY];
881
+ if (!apiKey) {
882
+ throw new AuthenticationError(
883
+ `API key required. Get your token at http://xpoz.ai/get-token?utm_source=ts_sdk&utm_medium=sdk (login \u2192 copy token), then pass it as apiKey or set the ${ENV_API_KEY} environment variable.`
884
+ );
885
+ }
886
+ const serverUrl = options.serverUrl ?? process.env[ENV_SERVER_URL] ?? DEFAULT_SERVER_URL;
887
+ const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
888
+ this.transport = new McpTransport(serverUrl, apiKey);
889
+ const callTool = this.transport.callTool.bind(this.transport);
890
+ this.twitter = new TwitterNamespace(callTool, timeoutMs);
891
+ this.instagram = new InstagramNamespace(callTool, timeoutMs);
892
+ this.reddit = new RedditNamespace(callTool, timeoutMs);
893
+ }
894
+ async connect() {
895
+ await this.transport.connect();
896
+ }
897
+ async close() {
898
+ await this.transport.close();
899
+ }
900
+ async [Symbol.asyncDispose]() {
901
+ await this.close();
902
+ }
903
+ };
904
+ export {
905
+ AuthenticationError,
906
+ OperationCancelledError,
907
+ OperationFailedError,
908
+ OperationTimeoutError,
909
+ PaginatedResult,
910
+ VERSION,
911
+ XpozClient,
912
+ XpozConnectionError,
913
+ XpozError
914
+ };