@xpoz/xpoz 0.7.0 → 0.8.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.cjs CHANGED
@@ -301,7 +301,7 @@ function coerce(value) {
301
301
  }
302
302
 
303
303
  // src/version.ts
304
- var VERSION = "0.7.0";
304
+ var VERSION = "0.8.0";
305
305
 
306
306
  // src/mcp/transport.ts
307
307
  var USER_AGENT = `xpoz-ts-sdk/${VERSION}`;
@@ -455,6 +455,10 @@ var DEFAULT_API_URL = "https://api.xpoz.ai";
455
455
  var ENV_API_URL = "XPOZ_API_URL";
456
456
  var INSTAGRAM_BASE = "/api/data/instagram";
457
457
  var TWITTER_BASE = "/api/data/twitter";
458
+ var INSTAGRAM_ROUTES = {
459
+ user: (identifier) => `${INSTAGRAM_BASE}/users/${encodeURIComponent(identifier)}`,
460
+ postsByIds: `${INSTAGRAM_BASE}/posts/ids`
461
+ };
458
462
  var INSTAGRAM_LIVE_ROUTES = {
459
463
  posts: `${INSTAGRAM_BASE}/posts/live`,
460
464
  userPosts: (identifier) => `${INSTAGRAM_BASE}/posts/users/${encodeURIComponent(identifier)}/live`,
@@ -465,6 +469,9 @@ var INSTAGRAM_LIVE_ROUTES = {
465
469
  user: (identifier) => `${INSTAGRAM_BASE}/users/${encodeURIComponent(identifier)}/live`,
466
470
  userConnections: (identifier) => `${INSTAGRAM_BASE}/users/${encodeURIComponent(identifier)}/connections/live`
467
471
  };
472
+ var TWITTER_ROUTES = {
473
+ posts: `${TWITTER_BASE}/posts`
474
+ };
468
475
  var TWITTER_LIVE_ROUTES = {
469
476
  posts: `${TWITTER_BASE}/posts/live`,
470
477
  userPosts: (username) => `${TWITTER_BASE}/posts/users/${encodeURIComponent(username)}/live`,
@@ -912,28 +919,36 @@ var BaseNamespace = class {
912
919
  }
913
920
  };
914
921
 
922
+ // src/concurrency.ts
923
+ var DEFAULT_CONCURRENCY = 10;
924
+ async function parallelMap(items, fn, concurrency = DEFAULT_CONCURRENCY) {
925
+ const results = new Array(items.length);
926
+ let nextIndex = 0;
927
+ async function worker() {
928
+ while (nextIndex < items.length) {
929
+ const index = nextIndex++;
930
+ results[index] = await fn(items[index]);
931
+ }
932
+ }
933
+ const workers = Array.from(
934
+ { length: Math.min(concurrency, items.length) },
935
+ () => worker()
936
+ );
937
+ await Promise.all(workers);
938
+ return results;
939
+ }
940
+
915
941
  // src/config/tools.ts
916
- var GET_TWITTER_POSTS_BY_IDS = "getTwitterPostsByIds";
917
942
  var GET_TWITTER_POSTS_BY_AUTHOR = "getTwitterPostsByAuthor";
918
943
  var SEARCH_TWITTER_POSTS = "getTwitterPostsByKeywords";
919
944
  var GET_TWITTER_RETWEETS = "getTwitterPostRetweets";
920
- var GET_TWITTER_QUOTES = "getTwitterPostQuotes";
921
- var GET_TWITTER_COMMENTS = "getTwitterPostComments";
922
- var GET_TWITTER_POST_INTERACTING_USERS = "getTwitterPostInteractingUsers";
923
945
  var COUNT_TWEETS = "countTweets";
924
946
  var GET_TWITTER_USER = "getTwitterUser";
925
947
  var GET_TWITTER_USERS = "getTwitterUsers";
926
- var SEARCH_TWITTER_USERS = "searchTwitterUsers";
927
948
  var GET_TWITTER_USER_CONNECTIONS = "getTwitterUserConnections";
928
949
  var GET_TWITTER_USERS_BY_KEYWORDS = "getTwitterUsersByKeywords";
929
- var GET_INSTAGRAM_POSTS_BY_IDS = "getInstagramPostsByIds";
930
950
  var GET_INSTAGRAM_POSTS_BY_USER = "getInstagramPostsByUser";
931
951
  var SEARCH_INSTAGRAM_POSTS = "getInstagramPostsByKeywords";
932
- var GET_INSTAGRAM_COMMENTS = "getInstagramCommentsByPostId";
933
- var GET_INSTAGRAM_USER = "getInstagramUser";
934
- var SEARCH_INSTAGRAM_USERS = "searchInstagramUsers";
935
- var GET_INSTAGRAM_USER_CONNECTIONS = "getInstagramUserConnections";
936
- var GET_INSTAGRAM_POST_INTERACTING_USERS = "getInstagramPostInteractingUsers";
937
952
  var GET_INSTAGRAM_USERS_BY_KEYWORDS = "getInstagramUsersByKeywords";
938
953
  var SEARCH_REDDIT_POSTS = "getRedditPostsByKeywords";
939
954
  var GET_REDDIT_POST_WITH_COMMENTS = "getRedditPostWithCommentsById";
@@ -970,33 +985,79 @@ function parseUser(item) {
970
985
  return item;
971
986
  }
972
987
  var TwitterNamespace = class extends BaseNamespace {
988
+ rest;
989
+ constructor(callTool, timeoutMs, restTransport) {
990
+ super(callTool, timeoutMs);
991
+ this.rest = restTransport;
992
+ }
993
+ cursorToPaginatedResult(response, fetchNext, pageNumber = 1) {
994
+ const items = response.results ?? [];
995
+ const hasMore = Boolean(response.has_more);
996
+ const nextCursor = response.next_page_cursor ?? null;
997
+ const pagination = {
998
+ tableName: null,
999
+ totalRows: 0,
1000
+ totalPages: hasMore ? pageNumber + 1 : pageNumber,
1001
+ pageNumber,
1002
+ pageSize: items.length,
1003
+ resultsCount: items.length
1004
+ };
1005
+ const fetchPage = async () => {
1006
+ if (!nextCursor) {
1007
+ throw new RangeError("No more pages available");
1008
+ }
1009
+ const nextResponse = await fetchNext(nextCursor);
1010
+ return this.cursorToPaginatedResult(nextResponse, fetchNext, pageNumber + 1);
1011
+ };
1012
+ return new PaginatedResult({
1013
+ data: items,
1014
+ pagination,
1015
+ tableName: null,
1016
+ exportOperationId: null,
1017
+ fetchPage: () => fetchPage(),
1018
+ fetchExport: null
1019
+ });
1020
+ }
973
1021
  async getPostsByIds(postIds, options = {}) {
974
- const args = this.buildArgs({ postIds, ...options });
975
- const result = await this.callAndMaybePoll(
976
- GET_TWITTER_POSTS_BY_IDS,
977
- args
978
- );
979
- return (result["results"] ?? []).map(parseTwitterPost);
1022
+ const fieldsCsv = csvFields(options.fields);
1023
+ const results = await parallelMap(postIds, async (postId) => {
1024
+ const response = await this.rest.get(
1025
+ TWITTER_LIVE_ROUTES.post(postId),
1026
+ { fields: fieldsCsv }
1027
+ );
1028
+ return (response.results ?? [])[0] ?? null;
1029
+ });
1030
+ return results.filter((post) => post !== null);
980
1031
  }
981
1032
  async getPostsByAuthor(identifier, options = {}) {
982
- const args = this.buildArgs({
983
- username: identifier,
984
- fields: options.fields,
985
- startDate: options.startDate,
986
- endDate: options.endDate,
987
- forceLatest: options.forceLatest,
988
- responseType: options.responseType,
989
- limit: options.limit
990
- });
991
- const result = await this.callAndMaybePoll(
992
- GET_TWITTER_POSTS_BY_AUTHOR,
993
- args
1033
+ if (options.responseType === "csv" /* Csv */) {
1034
+ const args = this.buildArgs({
1035
+ username: identifier,
1036
+ fields: options.fields,
1037
+ startDate: options.startDate,
1038
+ endDate: options.endDate,
1039
+ forceLatest: options.forceLatest,
1040
+ responseType: options.responseType,
1041
+ limit: options.limit
1042
+ });
1043
+ const result = await this.callAndMaybePoll(GET_TWITTER_POSTS_BY_AUTHOR, args);
1044
+ return this.buildPaginatedResult(result, parseTwitterPost, GET_TWITTER_POSTS_BY_AUTHOR, args);
1045
+ }
1046
+ const params = {
1047
+ since: options.startDate,
1048
+ until: options.endDate,
1049
+ fields: csvFields(options.fields)
1050
+ };
1051
+ const response = await this.rest.get(
1052
+ TWITTER_LIVE_ROUTES.userPosts(identifier),
1053
+ params
994
1054
  );
995
- return this.buildPaginatedResult(
996
- result,
997
- parseTwitterPost,
998
- GET_TWITTER_POSTS_BY_AUTHOR,
999
- args
1055
+ return this.cursorToPaginatedResult(
1056
+ response,
1057
+ (cursor) => this.rest.get(
1058
+ TWITTER_LIVE_ROUTES.userPosts(identifier),
1059
+ { ...params, cursor }
1060
+ )
1000
1061
  );
1001
1062
  }
1002
1063
  async searchPosts(query, options = {}) {
@@ -1052,39 +1113,48 @@ var TwitterNamespace = class extends BaseNamespace {
1052
1113
  );
1053
1114
  }
1054
1115
  async getQuotes(postId, options = {}) {
1055
- const args = this.buildArgs({ postId, ...options });
1056
- const result = await this.callAndMaybePoll(GET_TWITTER_QUOTES, args);
1057
- return this.buildPaginatedResult(
1058
- result,
1059
- parseTwitterPost,
1060
- GET_TWITTER_QUOTES,
1061
- args
1116
+ const params = { fields: csvFields(options.fields) };
1117
+ const response = await this.rest.get(
1118
+ TWITTER_LIVE_ROUTES.postQuotes(postId),
1119
+ params
1120
+ );
1121
+ return this.cursorToPaginatedResult(
1122
+ response,
1123
+ (cursor) => this.rest.get(
1124
+ TWITTER_LIVE_ROUTES.postQuotes(postId),
1125
+ { ...params, cursor }
1126
+ )
1062
1127
  );
1063
1128
  }
1064
1129
  async getComments(postId, options = {}) {
1065
- const args = this.buildArgs({ postId, ...options });
1066
- const result = await this.callAndMaybePoll(
1067
- GET_TWITTER_COMMENTS,
1068
- args
1130
+ const params = { fields: csvFields(options.fields) };
1131
+ const response = await this.rest.get(
1132
+ TWITTER_LIVE_ROUTES.postComments(postId),
1133
+ params
1069
1134
  );
1070
- return this.buildPaginatedResult(
1071
- result,
1072
- parseTwitterPost,
1073
- GET_TWITTER_COMMENTS,
1074
- args
1135
+ return this.cursorToPaginatedResult(
1136
+ response,
1137
+ (cursor) => this.rest.get(
1138
+ TWITTER_LIVE_ROUTES.postComments(postId),
1139
+ { ...params, cursor }
1140
+ )
1075
1141
  );
1076
1142
  }
1077
1143
  async getPostInteractingUsers(postId, interactionType, options = {}) {
1078
- const args = this.buildArgs({ postId, interactionType, ...options });
1079
- const result = await this.callAndMaybePoll(
1080
- GET_TWITTER_POST_INTERACTING_USERS,
1081
- args
1144
+ const params = {
1145
+ interactionType,
1146
+ fields: csvFields(options.fields)
1147
+ };
1148
+ const response = await this.rest.get(
1149
+ TWITTER_LIVE_ROUTES.postInteractingUsers(postId),
1150
+ params
1082
1151
  );
1083
- return this.buildPaginatedResult(
1084
- result,
1085
- parseUser,
1086
- GET_TWITTER_POST_INTERACTING_USERS,
1087
- args
1152
+ return this.cursorToPaginatedResult(
1153
+ response,
1154
+ (cursor) => this.rest.get(
1155
+ TWITTER_LIVE_ROUTES.postInteractingUsers(postId),
1156
+ { ...params, cursor }
1157
+ )
1088
1158
  );
1089
1159
  }
1090
1160
  async countPosts(phrase, options = {}) {
@@ -1102,48 +1172,81 @@ var TwitterNamespace = class extends BaseNamespace {
1102
1172
  return Number(count);
1103
1173
  }
1104
1174
  async getUsers(identifiers, options = {}) {
1105
- const args = this.buildArgs({
1106
- identifiers,
1107
- identifierType: options.identifierType ?? "username",
1108
- fields: options.fields,
1109
- forceLatest: options.forceLatest
1175
+ if ((options.identifierType ?? "username") === "id") {
1176
+ const args = this.buildArgs({
1177
+ identifiers,
1178
+ identifierType: "id",
1179
+ fields: options.fields,
1180
+ forceLatest: options.forceLatest
1181
+ });
1182
+ const result = await this.callAndMaybePoll(GET_TWITTER_USERS, args);
1183
+ return (result["results"] ?? []).map(parseUser);
1184
+ }
1185
+ const fieldsCsv = csvFields(options.fields);
1186
+ const results = await parallelMap(identifiers, async (username) => {
1187
+ const response = await this.rest.get(
1188
+ TWITTER_LIVE_ROUTES.user(username),
1189
+ { fields: fieldsCsv }
1190
+ );
1191
+ return (response.results ?? [])[0] ?? null;
1110
1192
  });
1111
- const result = await this.callAndMaybePoll(GET_TWITTER_USERS, args);
1112
- return (result["results"] ?? []).map(parseUser);
1193
+ return results.filter((user) => user !== null);
1113
1194
  }
1114
1195
  async getUser(identifier, options = {}) {
1115
- const args = this.buildArgs({
1116
- identifier,
1117
- identifierType: options.identifierType ?? "username",
1118
- fields: options.fields,
1119
- forceLatest: options.forceLatest
1120
- });
1121
- const result = await this.callAndMaybePoll(GET_TWITTER_USER, args);
1122
- const results = result["results"];
1123
- if (Array.isArray(results) && results.length > 0) {
1124
- return results[0];
1196
+ if ((options.identifierType ?? "username") === "id") {
1197
+ const args = this.buildArgs({
1198
+ identifier,
1199
+ identifierType: "id",
1200
+ fields: options.fields,
1201
+ forceLatest: options.forceLatest
1202
+ });
1203
+ const result = await this.callAndMaybePoll(GET_TWITTER_USER, args);
1204
+ const results = result["results"];
1205
+ if (Array.isArray(results) && results.length > 0) {
1206
+ return results[0];
1207
+ }
1208
+ return result;
1125
1209
  }
1126
- return result;
1210
+ const response = await this.rest.get(
1211
+ TWITTER_LIVE_ROUTES.user(identifier),
1212
+ { fields: csvFields(options.fields) }
1213
+ );
1214
+ if (response.results && response.results.length > 0) {
1215
+ return response.results[0];
1216
+ }
1217
+ throw new Error(`User not found: ${identifier}`);
1127
1218
  }
1128
1219
  async searchUsers(name, options = {}) {
1129
- const args = this.buildArgs({ name, ...options });
1130
- const result = await this.callAndMaybePoll(
1131
- SEARCH_TWITTER_USERS,
1132
- args
1220
+ const response = await this.rest.get(
1221
+ TWITTER_LIVE_ROUTES.users,
1222
+ { q: name, fields: csvFields(options.fields) }
1133
1223
  );
1134
- return (result["results"] ?? []).map(parseUser);
1224
+ const users = response.results ?? [];
1225
+ if (options.limit && options.limit > 0) {
1226
+ return users.slice(0, options.limit);
1227
+ }
1228
+ return users;
1135
1229
  }
1136
1230
  async getUserConnections(username, connectionType, options = {}) {
1137
- const args = this.buildArgs({ username, connectionType, ...options });
1138
- const result = await this.callAndMaybePoll(
1139
- GET_TWITTER_USER_CONNECTIONS,
1140
- args
1231
+ if (options.responseType === "csv" /* Csv */) {
1232
+ const args = this.buildArgs({ username, connectionType, ...options });
1233
+ const result = await this.callAndMaybePoll(GET_TWITTER_USER_CONNECTIONS, args);
1234
+ return this.buildPaginatedResult(result, parseUser, GET_TWITTER_USER_CONNECTIONS, args);
1235
+ }
1236
+ const params = {
1237
+ connectionType,
1238
+ fields: csvFields(options.fields)
1239
+ };
1240
+ const response = await this.rest.get(
1241
+ TWITTER_LIVE_ROUTES.userConnections(username),
1242
+ params
1141
1243
  );
1142
- return this.buildPaginatedResult(
1143
- result,
1144
- parseUser,
1145
- GET_TWITTER_USER_CONNECTIONS,
1146
- args
1244
+ return this.cursorToPaginatedResult(
1245
+ response,
1246
+ (cursor) => this.rest.get(
1247
+ TWITTER_LIVE_ROUTES.userConnections(username),
1248
+ { ...params, cursor }
1249
+ )
1147
1250
  );
1148
1251
  }
1149
1252
  async getUsersByKeywords(query, options = {}) {
@@ -1168,92 +1271,187 @@ function parsePost(item) {
1168
1271
  function parseUser2(item) {
1169
1272
  return item;
1170
1273
  }
1171
- function parseComment(item) {
1172
- return item;
1173
- }
1174
1274
  var InstagramNamespace = class extends BaseNamespace {
1275
+ rest;
1276
+ constructor(callTool, timeoutMs, restTransport) {
1277
+ super(callTool, timeoutMs);
1278
+ this.rest = restTransport;
1279
+ }
1280
+ cursorToPaginatedResult(response, fetchNext, pageNumber = 1) {
1281
+ const items = response.results ?? [];
1282
+ const hasMore = Boolean(response.has_more);
1283
+ const nextCursor = response.next_page_cursor ?? null;
1284
+ const pagination = {
1285
+ tableName: null,
1286
+ totalRows: 0,
1287
+ totalPages: hasMore ? pageNumber + 1 : pageNumber,
1288
+ pageNumber,
1289
+ pageSize: items.length,
1290
+ resultsCount: items.length
1291
+ };
1292
+ const fetchPage = async () => {
1293
+ if (!nextCursor) {
1294
+ throw new RangeError("No more pages available");
1295
+ }
1296
+ const nextResponse = await fetchNext(nextCursor);
1297
+ return this.cursorToPaginatedResult(nextResponse, fetchNext, pageNumber + 1);
1298
+ };
1299
+ return new PaginatedResult({
1300
+ data: items,
1301
+ pagination,
1302
+ tableName: null,
1303
+ exportOperationId: null,
1304
+ fetchPage: () => fetchPage(),
1305
+ fetchExport: null
1306
+ });
1307
+ }
1175
1308
  async getPostsByIds(postIds, options = {}) {
1176
- const args = this.buildArgs({ postIds, ...options });
1177
- const result = await this.callAndMaybePoll(GET_INSTAGRAM_POSTS_BY_IDS, args);
1178
- return (result["results"] ?? []).map(parsePost);
1309
+ const fieldsCsv = csvFields(options.fields);
1310
+ const results = await parallelMap(postIds, async (postId) => {
1311
+ const response = await this.rest.get(
1312
+ INSTAGRAM_LIVE_ROUTES.post(postId),
1313
+ { fields: fieldsCsv }
1314
+ );
1315
+ return (response.results ?? [])[0] ?? null;
1316
+ });
1317
+ return results.filter((post) => post !== null);
1179
1318
  }
1180
1319
  async getPostsByUser(identifier, options = {}) {
1181
- const args = this.buildArgs({
1182
- identifier,
1183
- identifierType: options.identifierType ?? "username",
1184
- fields: options.fields,
1185
- startDate: options.startDate,
1186
- endDate: options.endDate,
1187
- forceLatest: options.forceLatest,
1188
- responseType: options.responseType,
1189
- limit: options.limit
1190
- });
1191
- const result = await this.callAndMaybePoll(GET_INSTAGRAM_POSTS_BY_USER, args);
1192
- return this.buildPaginatedResult(
1193
- result,
1194
- parsePost,
1195
- GET_INSTAGRAM_POSTS_BY_USER,
1196
- args
1320
+ if (options.responseType === "csv" /* Csv */) {
1321
+ const args = this.buildArgs({
1322
+ identifier,
1323
+ identifierType: options.identifierType ?? "username",
1324
+ fields: options.fields,
1325
+ startDate: options.startDate,
1326
+ endDate: options.endDate,
1327
+ forceLatest: options.forceLatest,
1328
+ responseType: options.responseType,
1329
+ limit: options.limit
1330
+ });
1331
+ const result = await this.callAndMaybePoll(GET_INSTAGRAM_POSTS_BY_USER, args);
1332
+ return this.buildPaginatedResult(result, parsePost, GET_INSTAGRAM_POSTS_BY_USER, args);
1333
+ }
1334
+ const params = {
1335
+ fields: csvFields(options.fields)
1336
+ };
1337
+ const response = await this.rest.get(
1338
+ INSTAGRAM_LIVE_ROUTES.userPosts(identifier),
1339
+ params
1340
+ );
1341
+ return this.cursorToPaginatedResult(
1342
+ response,
1343
+ (cursor) => this.rest.get(
1344
+ INSTAGRAM_LIVE_ROUTES.userPosts(identifier),
1345
+ { ...params, cursor }
1346
+ )
1197
1347
  );
1198
1348
  }
1199
1349
  async searchPosts(query, options = {}) {
1200
- const args = this.buildArgs({
1201
- query,
1202
- fields: options.fields,
1203
- startDate: options.startDate,
1204
- endDate: options.endDate,
1205
- forceLatest: options.forceLatest,
1206
- responseType: options.responseType,
1207
- limit: options.limit
1208
- });
1209
- const result = await this.callAndMaybePoll(SEARCH_INSTAGRAM_POSTS, args);
1210
- return this.buildPaginatedResult(result, parsePost, SEARCH_INSTAGRAM_POSTS, args);
1350
+ if (options.responseType === "csv" /* Csv */) {
1351
+ const args = this.buildArgs({
1352
+ query,
1353
+ fields: options.fields,
1354
+ startDate: options.startDate,
1355
+ endDate: options.endDate,
1356
+ forceLatest: options.forceLatest,
1357
+ responseType: options.responseType,
1358
+ limit: options.limit
1359
+ });
1360
+ const result = await this.callAndMaybePoll(SEARCH_INSTAGRAM_POSTS, args);
1361
+ return this.buildPaginatedResult(result, parsePost, SEARCH_INSTAGRAM_POSTS, args);
1362
+ }
1363
+ const params = {
1364
+ q: query,
1365
+ fields: csvFields(options.fields)
1366
+ };
1367
+ const response = await this.rest.get(
1368
+ INSTAGRAM_LIVE_ROUTES.posts,
1369
+ params
1370
+ );
1371
+ return this.cursorToPaginatedResult(
1372
+ response,
1373
+ (cursor) => this.rest.get(
1374
+ INSTAGRAM_LIVE_ROUTES.posts,
1375
+ { ...params, cursor }
1376
+ )
1377
+ );
1211
1378
  }
1212
1379
  async getComments(postId, options = {}) {
1213
- const args = this.buildArgs({ postId, ...options });
1214
- const result = await this.callAndMaybePoll(GET_INSTAGRAM_COMMENTS, args);
1215
- return this.buildPaginatedResult(result, parseComment, GET_INSTAGRAM_COMMENTS, args);
1380
+ const params = {
1381
+ fields: csvFields(options.fields)
1382
+ };
1383
+ const response = await this.rest.get(
1384
+ INSTAGRAM_LIVE_ROUTES.postComments(postId),
1385
+ params
1386
+ );
1387
+ return this.cursorToPaginatedResult(
1388
+ response,
1389
+ (cursor) => this.rest.get(
1390
+ INSTAGRAM_LIVE_ROUTES.postComments(postId),
1391
+ { ...params, cursor }
1392
+ )
1393
+ );
1216
1394
  }
1217
1395
  async getUser(identifier, options = {}) {
1218
- const args = this.buildArgs({
1219
- identifier,
1220
- identifierType: options.identifierType ?? "username",
1221
- fields: options.fields,
1222
- forceLatest: options.forceLatest
1223
- });
1224
- const result = await this.callAndMaybePoll(GET_INSTAGRAM_USER, args);
1225
- const results = result["results"];
1226
- if (Array.isArray(results) && results.length > 0) {
1227
- return results[0];
1396
+ const response = await this.rest.get(
1397
+ INSTAGRAM_ROUTES.user(identifier),
1398
+ {
1399
+ identifierType: options.identifierType ?? "username",
1400
+ fields: csvFields(options.fields),
1401
+ forceLatest: true
1402
+ }
1403
+ );
1404
+ if (response.results.length > 0) {
1405
+ return response.results[0];
1228
1406
  }
1229
- return result;
1407
+ throw new Error(`User not found: ${identifier}`);
1230
1408
  }
1231
1409
  async searchUsers(name, options = {}) {
1232
- const args = this.buildArgs({ name, ...options });
1233
- const result = await this.callAndMaybePoll(SEARCH_INSTAGRAM_USERS, args);
1234
- return (result["results"] ?? []).map(parseUser2);
1410
+ const response = await this.rest.get(
1411
+ INSTAGRAM_LIVE_ROUTES.users,
1412
+ {
1413
+ name,
1414
+ fields: csvFields(options.fields)
1415
+ }
1416
+ );
1417
+ const users = response.results ?? [];
1418
+ if (options.limit && options.limit > 0) {
1419
+ return users.slice(0, options.limit);
1420
+ }
1421
+ return users;
1235
1422
  }
1236
1423
  async getUserConnections(username, connectionType, options = {}) {
1237
- const args = this.buildArgs({ username, connectionType, ...options });
1238
- const result = await this.callAndMaybePoll(GET_INSTAGRAM_USER_CONNECTIONS, args);
1239
- return this.buildPaginatedResult(
1240
- result,
1241
- parseUser2,
1242
- GET_INSTAGRAM_USER_CONNECTIONS,
1243
- args
1424
+ const params = {
1425
+ connectionType,
1426
+ fields: csvFields(options.fields)
1427
+ };
1428
+ const response = await this.rest.get(
1429
+ INSTAGRAM_LIVE_ROUTES.userConnections(username),
1430
+ params
1431
+ );
1432
+ return this.cursorToPaginatedResult(
1433
+ response,
1434
+ (cursor) => this.rest.get(
1435
+ INSTAGRAM_LIVE_ROUTES.userConnections(username),
1436
+ { ...params, cursor }
1437
+ )
1244
1438
  );
1245
1439
  }
1246
1440
  async getPostInteractingUsers(postId, interactionType, options = {}) {
1247
- const args = this.buildArgs({ postId, interactionType, ...options });
1248
- const result = await this.callAndMaybePoll(
1249
- GET_INSTAGRAM_POST_INTERACTING_USERS,
1250
- args
1441
+ const params = {
1442
+ interactionType,
1443
+ fields: csvFields(options.fields)
1444
+ };
1445
+ const response = await this.rest.get(
1446
+ INSTAGRAM_LIVE_ROUTES.postInteractingUsers(postId),
1447
+ params
1251
1448
  );
1252
- return this.buildPaginatedResult(
1253
- result,
1254
- parseUser2,
1255
- GET_INSTAGRAM_POST_INTERACTING_USERS,
1256
- args
1449
+ return this.cursorToPaginatedResult(
1450
+ response,
1451
+ (cursor) => this.rest.get(
1452
+ INSTAGRAM_LIVE_ROUTES.postInteractingUsers(postId),
1453
+ { ...params, cursor }
1454
+ )
1257
1455
  );
1258
1456
  }
1259
1457
  async getUsersByKeywords(query, options = {}) {
@@ -1275,7 +1473,7 @@ function parsePost2(item) {
1275
1473
  function parseUser3(item) {
1276
1474
  return item;
1277
1475
  }
1278
- function parseComment2(item) {
1476
+ function parseComment(item) {
1279
1477
  return item;
1280
1478
  }
1281
1479
  function parseSubreddit(item) {
@@ -1295,7 +1493,7 @@ var RedditNamespace = class extends BaseNamespace {
1295
1493
  async searchComments(query, options = {}) {
1296
1494
  const args = this.buildArgs({ query, ...options });
1297
1495
  const result = await this.callAndMaybePoll(SEARCH_REDDIT_COMMENTS, args);
1298
- return this.buildPaginatedResult(result, parseComment2, SEARCH_REDDIT_COMMENTS, args);
1496
+ return this.buildPaginatedResult(result, parseComment, SEARCH_REDDIT_COMMENTS, args);
1299
1497
  }
1300
1498
  async getCommentById(commentId, options = {}) {
1301
1499
  const args = this.buildArgs({ commentId, ...options });
@@ -1360,7 +1558,7 @@ var RedditNamespace = class extends BaseNamespace {
1360
1558
  const pagination = this.extractPagination(raw);
1361
1559
  return {
1362
1560
  post: postData,
1363
- comments: commentsData.map(parseComment2),
1561
+ comments: commentsData.map(parseComment),
1364
1562
  commentsPagination: pagination.totalPages > 0 ? pagination : null,
1365
1563
  commentsTableName: pagination.tableName ?? null
1366
1564
  };
@@ -1389,7 +1587,7 @@ function parsePost3(item) {
1389
1587
  function parseUser4(item) {
1390
1588
  return item;
1391
1589
  }
1392
- function parseComment3(item) {
1590
+ function parseComment2(item) {
1393
1591
  return item;
1394
1592
  }
1395
1593
  function parseSound(item) {
@@ -1436,7 +1634,7 @@ var TiktokNamespace = class extends BaseNamespace {
1436
1634
  async getComments(postId, options = {}) {
1437
1635
  const args = this.buildArgs({ postId, ...options });
1438
1636
  const result = await this.callAndMaybePoll(GET_TIKTOK_COMMENTS, args);
1439
- return this.buildPaginatedResult(result, parseComment3, GET_TIKTOK_COMMENTS, args);
1637
+ return this.buildPaginatedResult(result, parseComment2, GET_TIKTOK_COMMENTS, args);
1440
1638
  }
1441
1639
  async getUser(identifier, options = {}) {
1442
1640
  const args = this.buildArgs({
@@ -1597,8 +1795,8 @@ var XpozClient = class {
1597
1795
  const apiUrl = options.apiUrl ?? process.env[ENV_API_URL] ?? DEFAULT_API_URL;
1598
1796
  this.restTransport = new RestTransport(apiUrl, apiKey);
1599
1797
  const callTool = this.transport.callTool.bind(this.transport);
1600
- this.twitter = new TwitterNamespace(callTool, timeoutMs);
1601
- this.instagram = new InstagramNamespace(callTool, timeoutMs);
1798
+ this.twitter = new TwitterNamespace(callTool, timeoutMs, this.restTransport);
1799
+ this.instagram = new InstagramNamespace(callTool, timeoutMs, this.restTransport);
1602
1800
  this.reddit = new RedditNamespace(callTool, timeoutMs);
1603
1801
  this.tiktok = new TiktokNamespace(callTool, timeoutMs);
1604
1802
  this.tracking = new TrackingNamespace(callTool, timeoutMs);