@xpoz/xpoz 0.7.0 → 0.8.1

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.1";
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,50 +985,96 @@ 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 = {}) {
1003
- const args = this.buildArgs({
1004
- query,
1005
- fields: options.fields,
1006
- startDate: options.startDate,
1007
- endDate: options.endDate,
1008
- authorUsername: options.authorUsername,
1009
- authorId: options.authorId,
1010
- language: options.language,
1011
- filterOutRetweets: options.filterOutRetweets,
1012
- forceLatest: options.forceLatest,
1013
- responseType: options.responseType,
1014
- limit: options.limit
1015
- });
1016
1064
  if (options.responseType === "csv" /* Csv */) {
1065
+ const args = this.buildArgs({
1066
+ query,
1067
+ fields: options.fields,
1068
+ startDate: options.startDate,
1069
+ endDate: options.endDate,
1070
+ authorUsername: options.authorUsername,
1071
+ authorId: options.authorId,
1072
+ language: options.language,
1073
+ filterOutRetweets: options.filterOutRetweets,
1074
+ forceLatest: options.forceLatest,
1075
+ responseType: options.responseType,
1076
+ limit: options.limit
1077
+ });
1017
1078
  const raw = await this.callTool(SEARCH_TWITTER_POSTS, args);
1018
1079
  const exportOpId = raw["operationId"] ?? raw["dataDumpExportOperationId"] ?? null;
1019
1080
  const csvRaw = {
@@ -1027,15 +1088,24 @@ var TwitterNamespace = class extends BaseNamespace {
1027
1088
  args
1028
1089
  );
1029
1090
  }
1030
- const result = await this.callAndMaybePoll(
1031
- SEARCH_TWITTER_POSTS,
1032
- args
1091
+ const params = {
1092
+ q: query,
1093
+ since: options.startDate,
1094
+ until: options.endDate,
1095
+ username: options.authorUsername,
1096
+ lang: options.language,
1097
+ fields: csvFields(options.fields)
1098
+ };
1099
+ const response = await this.rest.get(
1100
+ TWITTER_LIVE_ROUTES.posts,
1101
+ params
1033
1102
  );
1034
- return this.buildPaginatedResult(
1035
- result,
1036
- parseTwitterPost,
1037
- SEARCH_TWITTER_POSTS,
1038
- args
1103
+ return this.cursorToPaginatedResult(
1104
+ response,
1105
+ (cursor) => this.rest.get(
1106
+ TWITTER_LIVE_ROUTES.posts,
1107
+ { ...params, cursor }
1108
+ )
1039
1109
  );
1040
1110
  }
1041
1111
  async getRetweets(postId, options = {}) {
@@ -1052,39 +1122,48 @@ var TwitterNamespace = class extends BaseNamespace {
1052
1122
  );
1053
1123
  }
1054
1124
  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
1125
+ const params = { fields: csvFields(options.fields) };
1126
+ const response = await this.rest.get(
1127
+ TWITTER_LIVE_ROUTES.postQuotes(postId),
1128
+ params
1129
+ );
1130
+ return this.cursorToPaginatedResult(
1131
+ response,
1132
+ (cursor) => this.rest.get(
1133
+ TWITTER_LIVE_ROUTES.postQuotes(postId),
1134
+ { ...params, cursor }
1135
+ )
1062
1136
  );
1063
1137
  }
1064
1138
  async getComments(postId, options = {}) {
1065
- const args = this.buildArgs({ postId, ...options });
1066
- const result = await this.callAndMaybePoll(
1067
- GET_TWITTER_COMMENTS,
1068
- args
1139
+ const params = { fields: csvFields(options.fields) };
1140
+ const response = await this.rest.get(
1141
+ TWITTER_LIVE_ROUTES.postComments(postId),
1142
+ params
1069
1143
  );
1070
- return this.buildPaginatedResult(
1071
- result,
1072
- parseTwitterPost,
1073
- GET_TWITTER_COMMENTS,
1074
- args
1144
+ return this.cursorToPaginatedResult(
1145
+ response,
1146
+ (cursor) => this.rest.get(
1147
+ TWITTER_LIVE_ROUTES.postComments(postId),
1148
+ { ...params, cursor }
1149
+ )
1075
1150
  );
1076
1151
  }
1077
1152
  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
1153
+ const params = {
1154
+ interactionType,
1155
+ fields: csvFields(options.fields)
1156
+ };
1157
+ const response = await this.rest.get(
1158
+ TWITTER_LIVE_ROUTES.postInteractingUsers(postId),
1159
+ params
1082
1160
  );
1083
- return this.buildPaginatedResult(
1084
- result,
1085
- parseUser,
1086
- GET_TWITTER_POST_INTERACTING_USERS,
1087
- args
1161
+ return this.cursorToPaginatedResult(
1162
+ response,
1163
+ (cursor) => this.rest.get(
1164
+ TWITTER_LIVE_ROUTES.postInteractingUsers(postId),
1165
+ { ...params, cursor }
1166
+ )
1088
1167
  );
1089
1168
  }
1090
1169
  async countPosts(phrase, options = {}) {
@@ -1102,48 +1181,81 @@ var TwitterNamespace = class extends BaseNamespace {
1102
1181
  return Number(count);
1103
1182
  }
1104
1183
  async getUsers(identifiers, options = {}) {
1105
- const args = this.buildArgs({
1106
- identifiers,
1107
- identifierType: options.identifierType ?? "username",
1108
- fields: options.fields,
1109
- forceLatest: options.forceLatest
1184
+ if ((options.identifierType ?? "username") === "id") {
1185
+ const args = this.buildArgs({
1186
+ identifiers,
1187
+ identifierType: "id",
1188
+ fields: options.fields,
1189
+ forceLatest: options.forceLatest
1190
+ });
1191
+ const result = await this.callAndMaybePoll(GET_TWITTER_USERS, args);
1192
+ return (result["results"] ?? []).map(parseUser);
1193
+ }
1194
+ const fieldsCsv = csvFields(options.fields);
1195
+ const results = await parallelMap(identifiers, async (username) => {
1196
+ const response = await this.rest.get(
1197
+ TWITTER_LIVE_ROUTES.user(username),
1198
+ { fields: fieldsCsv }
1199
+ );
1200
+ return (response.results ?? [])[0] ?? null;
1110
1201
  });
1111
- const result = await this.callAndMaybePoll(GET_TWITTER_USERS, args);
1112
- return (result["results"] ?? []).map(parseUser);
1202
+ return results.filter((user) => user !== null);
1113
1203
  }
1114
1204
  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];
1205
+ if ((options.identifierType ?? "username") === "id") {
1206
+ const args = this.buildArgs({
1207
+ identifier,
1208
+ identifierType: "id",
1209
+ fields: options.fields,
1210
+ forceLatest: options.forceLatest
1211
+ });
1212
+ const result = await this.callAndMaybePoll(GET_TWITTER_USER, args);
1213
+ const results = result["results"];
1214
+ if (Array.isArray(results) && results.length > 0) {
1215
+ return results[0];
1216
+ }
1217
+ return result;
1125
1218
  }
1126
- return result;
1219
+ const response = await this.rest.get(
1220
+ TWITTER_LIVE_ROUTES.user(identifier),
1221
+ { fields: csvFields(options.fields) }
1222
+ );
1223
+ if (response.results && response.results.length > 0) {
1224
+ return response.results[0];
1225
+ }
1226
+ throw new Error(`User not found: ${identifier}`);
1127
1227
  }
1128
1228
  async searchUsers(name, options = {}) {
1129
- const args = this.buildArgs({ name, ...options });
1130
- const result = await this.callAndMaybePoll(
1131
- SEARCH_TWITTER_USERS,
1132
- args
1229
+ const response = await this.rest.get(
1230
+ TWITTER_LIVE_ROUTES.users,
1231
+ { q: name, fields: csvFields(options.fields) }
1133
1232
  );
1134
- return (result["results"] ?? []).map(parseUser);
1233
+ const users = response.results ?? [];
1234
+ if (options.limit && options.limit > 0) {
1235
+ return users.slice(0, options.limit);
1236
+ }
1237
+ return users;
1135
1238
  }
1136
1239
  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
1240
+ if (options.responseType === "csv" /* Csv */) {
1241
+ const args = this.buildArgs({ username, connectionType, ...options });
1242
+ const result = await this.callAndMaybePoll(GET_TWITTER_USER_CONNECTIONS, args);
1243
+ return this.buildPaginatedResult(result, parseUser, GET_TWITTER_USER_CONNECTIONS, args);
1244
+ }
1245
+ const params = {
1246
+ connectionType,
1247
+ fields: csvFields(options.fields)
1248
+ };
1249
+ const response = await this.rest.get(
1250
+ TWITTER_LIVE_ROUTES.userConnections(username),
1251
+ params
1141
1252
  );
1142
- return this.buildPaginatedResult(
1143
- result,
1144
- parseUser,
1145
- GET_TWITTER_USER_CONNECTIONS,
1146
- args
1253
+ return this.cursorToPaginatedResult(
1254
+ response,
1255
+ (cursor) => this.rest.get(
1256
+ TWITTER_LIVE_ROUTES.userConnections(username),
1257
+ { ...params, cursor }
1258
+ )
1147
1259
  );
1148
1260
  }
1149
1261
  async getUsersByKeywords(query, options = {}) {
@@ -1168,92 +1280,187 @@ function parsePost(item) {
1168
1280
  function parseUser2(item) {
1169
1281
  return item;
1170
1282
  }
1171
- function parseComment(item) {
1172
- return item;
1173
- }
1174
1283
  var InstagramNamespace = class extends BaseNamespace {
1284
+ rest;
1285
+ constructor(callTool, timeoutMs, restTransport) {
1286
+ super(callTool, timeoutMs);
1287
+ this.rest = restTransport;
1288
+ }
1289
+ cursorToPaginatedResult(response, fetchNext, pageNumber = 1) {
1290
+ const items = response.results ?? [];
1291
+ const hasMore = Boolean(response.has_more);
1292
+ const nextCursor = response.next_page_cursor ?? null;
1293
+ const pagination = {
1294
+ tableName: null,
1295
+ totalRows: 0,
1296
+ totalPages: hasMore ? pageNumber + 1 : pageNumber,
1297
+ pageNumber,
1298
+ pageSize: items.length,
1299
+ resultsCount: items.length
1300
+ };
1301
+ const fetchPage = async () => {
1302
+ if (!nextCursor) {
1303
+ throw new RangeError("No more pages available");
1304
+ }
1305
+ const nextResponse = await fetchNext(nextCursor);
1306
+ return this.cursorToPaginatedResult(nextResponse, fetchNext, pageNumber + 1);
1307
+ };
1308
+ return new PaginatedResult({
1309
+ data: items,
1310
+ pagination,
1311
+ tableName: null,
1312
+ exportOperationId: null,
1313
+ fetchPage: () => fetchPage(),
1314
+ fetchExport: null
1315
+ });
1316
+ }
1175
1317
  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);
1318
+ const fieldsCsv = csvFields(options.fields);
1319
+ const results = await parallelMap(postIds, async (postId) => {
1320
+ const response = await this.rest.get(
1321
+ INSTAGRAM_LIVE_ROUTES.post(postId),
1322
+ { fields: fieldsCsv }
1323
+ );
1324
+ return (response.results ?? [])[0] ?? null;
1325
+ });
1326
+ return results.filter((post) => post !== null);
1179
1327
  }
1180
1328
  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
1329
+ if (options.responseType === "csv" /* Csv */) {
1330
+ const args = this.buildArgs({
1331
+ identifier,
1332
+ identifierType: options.identifierType ?? "username",
1333
+ fields: options.fields,
1334
+ startDate: options.startDate,
1335
+ endDate: options.endDate,
1336
+ forceLatest: options.forceLatest,
1337
+ responseType: options.responseType,
1338
+ limit: options.limit
1339
+ });
1340
+ const result = await this.callAndMaybePoll(GET_INSTAGRAM_POSTS_BY_USER, args);
1341
+ return this.buildPaginatedResult(result, parsePost, GET_INSTAGRAM_POSTS_BY_USER, args);
1342
+ }
1343
+ const params = {
1344
+ fields: csvFields(options.fields)
1345
+ };
1346
+ const response = await this.rest.get(
1347
+ INSTAGRAM_LIVE_ROUTES.userPosts(identifier),
1348
+ params
1349
+ );
1350
+ return this.cursorToPaginatedResult(
1351
+ response,
1352
+ (cursor) => this.rest.get(
1353
+ INSTAGRAM_LIVE_ROUTES.userPosts(identifier),
1354
+ { ...params, cursor }
1355
+ )
1197
1356
  );
1198
1357
  }
1199
1358
  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);
1359
+ if (options.responseType === "csv" /* Csv */) {
1360
+ const args = this.buildArgs({
1361
+ query,
1362
+ fields: options.fields,
1363
+ startDate: options.startDate,
1364
+ endDate: options.endDate,
1365
+ forceLatest: options.forceLatest,
1366
+ responseType: options.responseType,
1367
+ limit: options.limit
1368
+ });
1369
+ const result = await this.callAndMaybePoll(SEARCH_INSTAGRAM_POSTS, args);
1370
+ return this.buildPaginatedResult(result, parsePost, SEARCH_INSTAGRAM_POSTS, args);
1371
+ }
1372
+ const params = {
1373
+ q: query,
1374
+ fields: csvFields(options.fields)
1375
+ };
1376
+ const response = await this.rest.get(
1377
+ INSTAGRAM_LIVE_ROUTES.posts,
1378
+ params
1379
+ );
1380
+ return this.cursorToPaginatedResult(
1381
+ response,
1382
+ (cursor) => this.rest.get(
1383
+ INSTAGRAM_LIVE_ROUTES.posts,
1384
+ { ...params, cursor }
1385
+ )
1386
+ );
1211
1387
  }
1212
1388
  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);
1389
+ const params = {
1390
+ fields: csvFields(options.fields)
1391
+ };
1392
+ const response = await this.rest.get(
1393
+ INSTAGRAM_LIVE_ROUTES.postComments(postId),
1394
+ params
1395
+ );
1396
+ return this.cursorToPaginatedResult(
1397
+ response,
1398
+ (cursor) => this.rest.get(
1399
+ INSTAGRAM_LIVE_ROUTES.postComments(postId),
1400
+ { ...params, cursor }
1401
+ )
1402
+ );
1216
1403
  }
1217
1404
  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];
1405
+ const response = await this.rest.get(
1406
+ INSTAGRAM_ROUTES.user(identifier),
1407
+ {
1408
+ identifierType: options.identifierType ?? "username",
1409
+ fields: csvFields(options.fields),
1410
+ forceLatest: true
1411
+ }
1412
+ );
1413
+ if (response.results.length > 0) {
1414
+ return response.results[0];
1228
1415
  }
1229
- return result;
1416
+ throw new Error(`User not found: ${identifier}`);
1230
1417
  }
1231
1418
  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);
1419
+ const response = await this.rest.get(
1420
+ INSTAGRAM_LIVE_ROUTES.users,
1421
+ {
1422
+ name,
1423
+ fields: csvFields(options.fields)
1424
+ }
1425
+ );
1426
+ const users = response.results ?? [];
1427
+ if (options.limit && options.limit > 0) {
1428
+ return users.slice(0, options.limit);
1429
+ }
1430
+ return users;
1235
1431
  }
1236
1432
  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
1433
+ const params = {
1434
+ connectionType,
1435
+ fields: csvFields(options.fields)
1436
+ };
1437
+ const response = await this.rest.get(
1438
+ INSTAGRAM_LIVE_ROUTES.userConnections(username),
1439
+ params
1440
+ );
1441
+ return this.cursorToPaginatedResult(
1442
+ response,
1443
+ (cursor) => this.rest.get(
1444
+ INSTAGRAM_LIVE_ROUTES.userConnections(username),
1445
+ { ...params, cursor }
1446
+ )
1244
1447
  );
1245
1448
  }
1246
1449
  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
1450
+ const params = {
1451
+ interactionType,
1452
+ fields: csvFields(options.fields)
1453
+ };
1454
+ const response = await this.rest.get(
1455
+ INSTAGRAM_LIVE_ROUTES.postInteractingUsers(postId),
1456
+ params
1251
1457
  );
1252
- return this.buildPaginatedResult(
1253
- result,
1254
- parseUser2,
1255
- GET_INSTAGRAM_POST_INTERACTING_USERS,
1256
- args
1458
+ return this.cursorToPaginatedResult(
1459
+ response,
1460
+ (cursor) => this.rest.get(
1461
+ INSTAGRAM_LIVE_ROUTES.postInteractingUsers(postId),
1462
+ { ...params, cursor }
1463
+ )
1257
1464
  );
1258
1465
  }
1259
1466
  async getUsersByKeywords(query, options = {}) {
@@ -1275,7 +1482,7 @@ function parsePost2(item) {
1275
1482
  function parseUser3(item) {
1276
1483
  return item;
1277
1484
  }
1278
- function parseComment2(item) {
1485
+ function parseComment(item) {
1279
1486
  return item;
1280
1487
  }
1281
1488
  function parseSubreddit(item) {
@@ -1295,7 +1502,7 @@ var RedditNamespace = class extends BaseNamespace {
1295
1502
  async searchComments(query, options = {}) {
1296
1503
  const args = this.buildArgs({ query, ...options });
1297
1504
  const result = await this.callAndMaybePoll(SEARCH_REDDIT_COMMENTS, args);
1298
- return this.buildPaginatedResult(result, parseComment2, SEARCH_REDDIT_COMMENTS, args);
1505
+ return this.buildPaginatedResult(result, parseComment, SEARCH_REDDIT_COMMENTS, args);
1299
1506
  }
1300
1507
  async getCommentById(commentId, options = {}) {
1301
1508
  const args = this.buildArgs({ commentId, ...options });
@@ -1360,7 +1567,7 @@ var RedditNamespace = class extends BaseNamespace {
1360
1567
  const pagination = this.extractPagination(raw);
1361
1568
  return {
1362
1569
  post: postData,
1363
- comments: commentsData.map(parseComment2),
1570
+ comments: commentsData.map(parseComment),
1364
1571
  commentsPagination: pagination.totalPages > 0 ? pagination : null,
1365
1572
  commentsTableName: pagination.tableName ?? null
1366
1573
  };
@@ -1389,7 +1596,7 @@ function parsePost3(item) {
1389
1596
  function parseUser4(item) {
1390
1597
  return item;
1391
1598
  }
1392
- function parseComment3(item) {
1599
+ function parseComment2(item) {
1393
1600
  return item;
1394
1601
  }
1395
1602
  function parseSound(item) {
@@ -1436,7 +1643,7 @@ var TiktokNamespace = class extends BaseNamespace {
1436
1643
  async getComments(postId, options = {}) {
1437
1644
  const args = this.buildArgs({ postId, ...options });
1438
1645
  const result = await this.callAndMaybePoll(GET_TIKTOK_COMMENTS, args);
1439
- return this.buildPaginatedResult(result, parseComment3, GET_TIKTOK_COMMENTS, args);
1646
+ return this.buildPaginatedResult(result, parseComment2, GET_TIKTOK_COMMENTS, args);
1440
1647
  }
1441
1648
  async getUser(identifier, options = {}) {
1442
1649
  const args = this.buildArgs({
@@ -1597,8 +1804,8 @@ var XpozClient = class {
1597
1804
  const apiUrl = options.apiUrl ?? process.env[ENV_API_URL] ?? DEFAULT_API_URL;
1598
1805
  this.restTransport = new RestTransport(apiUrl, apiKey);
1599
1806
  const callTool = this.transport.callTool.bind(this.transport);
1600
- this.twitter = new TwitterNamespace(callTool, timeoutMs);
1601
- this.instagram = new InstagramNamespace(callTool, timeoutMs);
1807
+ this.twitter = new TwitterNamespace(callTool, timeoutMs, this.restTransport);
1808
+ this.instagram = new InstagramNamespace(callTool, timeoutMs, this.restTransport);
1602
1809
  this.reddit = new RedditNamespace(callTool, timeoutMs);
1603
1810
  this.tiktok = new TiktokNamespace(callTool, timeoutMs);
1604
1811
  this.tracking = new TrackingNamespace(callTool, timeoutMs);