@socialrouter/sdk 0.2.0 → 0.3.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/README.md +56 -16
- package/dist/client.d.ts +12 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +56 -7
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/types.d.ts +62 -8
- package/dist/types.d.ts.map +1 -1
- package/package.json +18 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# SocialRouter SDK
|
|
2
2
|
|
|
3
|
-
A unified API to extract data from social media platforms. SocialRouter acts as an abstraction layer over multiple data providers (
|
|
3
|
+
A unified API to extract data from social media platforms. SocialRouter acts as an abstraction layer over multiple data providers (Apify, BrightData, etc.), offering a single interface, normalized data format, and automatic failover.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -30,7 +30,7 @@ for (const person of result.data) {
|
|
|
30
30
|
|
|
31
31
|
## Provider slugs
|
|
32
32
|
|
|
33
|
-
The `provider` field is a slug of the form `<provider>/<platform>/<type
|
|
33
|
+
The `provider` field is a slug of the form `<provider>/<platform>/<type>[:<tag>]` — for example `apify/linkedin/profile.info`, `apify/linkedin/profile.posts:apimaestro`, or `apify/googlemaps/place.search`. It fully specifies the routing target: which provider, which platform, which extraction or search type, and (optionally) which actor variant.
|
|
34
34
|
|
|
35
35
|
Browse the full catalogue (with pricing and copy buttons) at [socialrouter.io/providers](https://www.socialrouter.io/providers).
|
|
36
36
|
|
|
@@ -43,12 +43,10 @@ const client = new SocialRouter({
|
|
|
43
43
|
});
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
## Extracting Data
|
|
46
|
+
## Extracting Data (URL-driven)
|
|
47
47
|
|
|
48
48
|
### Extract and wait (recommended)
|
|
49
49
|
|
|
50
|
-
The simplest approach. Launches the extraction and polls automatically until the result is ready:
|
|
51
|
-
|
|
52
50
|
```typescript
|
|
53
51
|
const result = await client.extractAndWait({
|
|
54
52
|
url: "https://www.linkedin.com/posts/johndoe_ai-sales-1234567890",
|
|
@@ -71,19 +69,37 @@ const result = await client.extractAndWait(
|
|
|
71
69
|
);
|
|
72
70
|
```
|
|
73
71
|
|
|
74
|
-
###
|
|
72
|
+
### Batch URLs
|
|
73
|
+
|
|
74
|
+
When the target actor accepts batches, pass `urls` instead of `url`:
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
const result = await client.extractAndWait({
|
|
78
|
+
urls: [
|
|
79
|
+
"https://linkedin.com/in/alice",
|
|
80
|
+
"https://linkedin.com/in/bob",
|
|
81
|
+
"https://linkedin.com/in/carol",
|
|
82
|
+
],
|
|
83
|
+
provider: "apify/linkedin/profile.info",
|
|
84
|
+
limit: 50,
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Disable fallback
|
|
89
|
+
|
|
90
|
+
By default, the router walks the provider chain when the requested one fails. Pass `fallback: false` to attempt only the requested provider and surface its error directly:
|
|
75
91
|
|
|
76
92
|
```typescript
|
|
77
93
|
await client.extract({
|
|
78
|
-
url: "https://linkedin.com/in/johndoe",
|
|
79
|
-
provider: "apify/linkedin/profile.info",
|
|
80
|
-
|
|
94
|
+
url: "https://linkedin.com/in/johndoe",
|
|
95
|
+
provider: "apify/linkedin/profile.info",
|
|
96
|
+
fallback: false,
|
|
81
97
|
});
|
|
82
98
|
```
|
|
83
99
|
|
|
84
|
-
|
|
100
|
+
When a fallback was used, the response includes `fallback_from` (the initially-requested provider).
|
|
85
101
|
|
|
86
|
-
|
|
102
|
+
### Manual polling
|
|
87
103
|
|
|
88
104
|
```typescript
|
|
89
105
|
const extraction = await client.extract({
|
|
@@ -93,7 +109,6 @@ const extraction = await client.extract({
|
|
|
93
109
|
|
|
94
110
|
console.log(extraction.id); // "ext_abc123"
|
|
95
111
|
|
|
96
|
-
// Check the result later
|
|
97
112
|
const result = await client.getExtraction(extraction.id);
|
|
98
113
|
|
|
99
114
|
if (result.status === "completed") {
|
|
@@ -103,6 +118,24 @@ if (result.status === "completed") {
|
|
|
103
118
|
}
|
|
104
119
|
```
|
|
105
120
|
|
|
121
|
+
## Searching (query-driven)
|
|
122
|
+
|
|
123
|
+
For services where the input is a query rather than a URL (e.g. Google Maps place search), use `search` / `searchAndWait`:
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
const result = await client.searchAndWait({
|
|
127
|
+
queries: ["coffee shops in Brooklyn", "bakeries in Brooklyn"],
|
|
128
|
+
provider: "apify/googlemaps/place.search",
|
|
129
|
+
limit: 100,
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
console.log(result.kind); // "search"
|
|
133
|
+
console.log(result.queries); // ["coffee shops in Brooklyn", ...]
|
|
134
|
+
console.log(result.data); // ExtractionRecord[]
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Search and extract share the same response shape; only `kind`, `queries`, and the supported `type` differ.
|
|
138
|
+
|
|
106
139
|
## Providers
|
|
107
140
|
|
|
108
141
|
```typescript
|
|
@@ -111,11 +144,15 @@ const providers = await client.listProviders();
|
|
|
111
144
|
|
|
112
145
|
for (const p of providers) {
|
|
113
146
|
console.log(`${p.name} [${p.status}] - ${p.supported_platforms.join(", ")}`);
|
|
147
|
+
if (p.supported_search_types?.length) {
|
|
148
|
+
console.log(` search: ${p.supported_search_types.join(", ")}`);
|
|
149
|
+
}
|
|
114
150
|
}
|
|
115
151
|
|
|
116
152
|
// Get provider details including pricing
|
|
117
|
-
const detail = await client.getProvider("
|
|
118
|
-
console.log(detail.pricing);
|
|
153
|
+
const detail = await client.getProvider("apify");
|
|
154
|
+
console.log(detail.pricing); // per-extraction pricing
|
|
155
|
+
console.log(detail.search_pricing); // per-search pricing (if any)
|
|
119
156
|
```
|
|
120
157
|
|
|
121
158
|
## Account
|
|
@@ -134,8 +171,6 @@ console.log(`Credits used: $${usage.total_credits}`);
|
|
|
134
171
|
|
|
135
172
|
## Error Handling
|
|
136
173
|
|
|
137
|
-
The SDK exposes specific error classes for each failure case:
|
|
138
|
-
|
|
139
174
|
```typescript
|
|
140
175
|
import {
|
|
141
176
|
SocialRouter,
|
|
@@ -170,13 +205,18 @@ All types are exported for direct use:
|
|
|
170
205
|
import type {
|
|
171
206
|
SocialRouterConfig,
|
|
172
207
|
ExtractOptions,
|
|
208
|
+
SearchOptions,
|
|
173
209
|
Extraction,
|
|
174
210
|
ExtractionRecord,
|
|
175
211
|
ExtractionType,
|
|
176
212
|
ExtractionStatus,
|
|
213
|
+
ExtractionKind,
|
|
214
|
+
SearchType,
|
|
215
|
+
ServiceType,
|
|
177
216
|
Platform,
|
|
178
217
|
ProviderInfo,
|
|
179
218
|
ProviderDetail,
|
|
219
|
+
ProviderStatus,
|
|
180
220
|
AccountBalance,
|
|
181
221
|
UsageSummary,
|
|
182
222
|
ApiErrorDetail,
|
package/dist/client.d.ts
CHANGED
|
@@ -1,14 +1,24 @@
|
|
|
1
|
-
import type { SocialRouterConfig, ExtractOptions, Extraction, ProviderInfo, ProviderDetail, AccountBalance, UsageSummary } from "./types.js";
|
|
1
|
+
import type { SocialRouterConfig, ExtractOptions, SearchOptions, Extraction, ProviderInfo, ProviderDetail, AccountBalance, UsageSummary } from "./types.js";
|
|
2
2
|
export declare class SocialRouter {
|
|
3
3
|
private apiKey;
|
|
4
4
|
private baseUrl;
|
|
5
5
|
constructor(config: SocialRouterConfig);
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* Run a URL-driven data extraction. Pass either `url` (single) or `urls`
|
|
8
|
+
* (batch — only meaningful when the target provider/actor accepts batches).
|
|
9
|
+
*/
|
|
7
10
|
extract(options: ExtractOptions): Promise<Extraction>;
|
|
11
|
+
/**
|
|
12
|
+
* Run a query-driven search. The slug grammar matches `extract`, but the
|
|
13
|
+
* `type` segment must belong to the SearchType union (e.g. `place.search`).
|
|
14
|
+
*/
|
|
15
|
+
search(options: SearchOptions): Promise<Extraction>;
|
|
8
16
|
/** Get extraction by ID (for polling async results) */
|
|
9
17
|
getExtraction(id: string): Promise<Extraction>;
|
|
10
18
|
/** Extract and poll until completed (convenience method) */
|
|
11
19
|
extractAndWait(options: ExtractOptions, pollIntervalMs?: number, timeoutMs?: number): Promise<Extraction>;
|
|
20
|
+
/** Run a search and poll until completed (convenience method) */
|
|
21
|
+
searchAndWait(options: SearchOptions, pollIntervalMs?: number, timeoutMs?: number): Promise<Extraction>;
|
|
12
22
|
/** List all providers */
|
|
13
23
|
listProviders(): Promise<ProviderInfo[]>;
|
|
14
24
|
/** Get provider detail */
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,cAAc,EACd,UAAU,EACV,YAAY,EACZ,cAAc,EACd,cAAc,EACd,YAAY,EACb,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,UAAU,EACV,YAAY,EACZ,cAAc,EACd,cAAc,EACd,YAAY,EACb,MAAM,YAAY,CAAC;AAWpB,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,kBAAkB;IAOtC;;;OAGG;IACG,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC;IAiB3D;;;OAGG;IACG,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC;IAWzD,uDAAuD;IACjD,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAIpD,4DAA4D;IACtD,cAAc,CAClB,OAAO,EAAE,cAAc,EACvB,cAAc,GAAE,MAAa,EAC7B,SAAS,GAAE,MAAe,GACzB,OAAO,CAAC,UAAU,CAAC;IAiBtB,iEAAiE;IAC3D,aAAa,CACjB,OAAO,EAAE,aAAa,EACtB,cAAc,GAAE,MAAa,EAC7B,SAAS,GAAE,MAAe,GACzB,OAAO,CAAC,UAAU,CAAC;IAmBtB,yBAAyB;IACnB,aAAa,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IAK9C,0BAA0B;IACpB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAMtD,yBAAyB;IACnB,UAAU,IAAI,OAAO,CAAC,cAAc,CAAC;IAI3C,wBAAwB;IAClB,QAAQ,CAAC,IAAI,GAAE,MAAW,GAAG,OAAO,CAAC,YAAY,CAAC;YAM1C,GAAG;YAIH,IAAI;YAIJ,OAAO;CAoCtB"}
|
package/dist/client.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SocialRouterError, AuthenticationError, InsufficientCreditsError, RateLimitError, } from "./errors.js";
|
|
2
2
|
const DEFAULT_BASE_URL = "https://api.socialrouter.io";
|
|
3
|
+
const SDK_VERSION = "0.3.0";
|
|
3
4
|
export class SocialRouter {
|
|
4
5
|
apiKey;
|
|
5
6
|
baseUrl;
|
|
@@ -8,13 +9,47 @@ export class SocialRouter {
|
|
|
8
9
|
this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
|
|
9
10
|
}
|
|
10
11
|
// ─── Extract ─────────────────────────────────────────
|
|
11
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* Run a URL-driven data extraction. Pass either `url` (single) or `urls`
|
|
14
|
+
* (batch — only meaningful when the target provider/actor accepts batches).
|
|
15
|
+
*/
|
|
12
16
|
async extract(options) {
|
|
13
|
-
|
|
14
|
-
url: options.url,
|
|
17
|
+
const body = {
|
|
15
18
|
provider: options.provider,
|
|
16
|
-
|
|
17
|
-
|
|
19
|
+
};
|
|
20
|
+
if (options.urls !== undefined) {
|
|
21
|
+
body.urls = options.urls;
|
|
22
|
+
}
|
|
23
|
+
else if (options.url !== undefined) {
|
|
24
|
+
body.url = options.url;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
throw new Error("extract() requires either 'url' or 'urls'.");
|
|
28
|
+
}
|
|
29
|
+
if (options.limit !== undefined)
|
|
30
|
+
body.limit = options.limit;
|
|
31
|
+
if (options.fallback !== undefined)
|
|
32
|
+
body.fallback = options.fallback;
|
|
33
|
+
if (options.options !== undefined)
|
|
34
|
+
body.options = options.options;
|
|
35
|
+
return this.post("/v1/extract", body);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Run a query-driven search. The slug grammar matches `extract`, but the
|
|
39
|
+
* `type` segment must belong to the SearchType union (e.g. `place.search`).
|
|
40
|
+
*/
|
|
41
|
+
async search(options) {
|
|
42
|
+
const body = {
|
|
43
|
+
queries: options.queries,
|
|
44
|
+
provider: options.provider,
|
|
45
|
+
};
|
|
46
|
+
if (options.limit !== undefined)
|
|
47
|
+
body.limit = options.limit;
|
|
48
|
+
if (options.fallback !== undefined)
|
|
49
|
+
body.fallback = options.fallback;
|
|
50
|
+
if (options.options !== undefined)
|
|
51
|
+
body.options = options.options;
|
|
52
|
+
return this.post("/v1/search", body);
|
|
18
53
|
}
|
|
19
54
|
/** Get extraction by ID (for polling async results) */
|
|
20
55
|
async getExtraction(id) {
|
|
@@ -26,7 +61,6 @@ export class SocialRouter {
|
|
|
26
61
|
if (extraction.status === "completed" || extraction.status === "failed") {
|
|
27
62
|
return extraction;
|
|
28
63
|
}
|
|
29
|
-
// Poll
|
|
30
64
|
const start = Date.now();
|
|
31
65
|
while (Date.now() - start < timeoutMs) {
|
|
32
66
|
await new Promise((r) => setTimeout(r, pollIntervalMs));
|
|
@@ -36,6 +70,21 @@ export class SocialRouter {
|
|
|
36
70
|
}
|
|
37
71
|
throw new Error(`Extraction ${extraction.id} timed out after ${timeoutMs}ms`);
|
|
38
72
|
}
|
|
73
|
+
/** Run a search and poll until completed (convenience method) */
|
|
74
|
+
async searchAndWait(options, pollIntervalMs = 3000, timeoutMs = 120000) {
|
|
75
|
+
const extraction = await this.search(options);
|
|
76
|
+
if (extraction.status === "completed" || extraction.status === "failed") {
|
|
77
|
+
return extraction;
|
|
78
|
+
}
|
|
79
|
+
const start = Date.now();
|
|
80
|
+
while (Date.now() - start < timeoutMs) {
|
|
81
|
+
await new Promise((r) => setTimeout(r, pollIntervalMs));
|
|
82
|
+
const result = await this.getExtraction(extraction.id);
|
|
83
|
+
if (result.status !== "pending")
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
throw new Error(`Search ${extraction.id} timed out after ${timeoutMs}ms`);
|
|
87
|
+
}
|
|
39
88
|
// ─── Providers ───────────────────────────────────────
|
|
40
89
|
/** List all providers */
|
|
41
90
|
async listProviders() {
|
|
@@ -69,7 +118,7 @@ export class SocialRouter {
|
|
|
69
118
|
headers: {
|
|
70
119
|
Authorization: `Bearer ${this.apiKey}`,
|
|
71
120
|
"Content-Type": "application/json",
|
|
72
|
-
"User-Agent":
|
|
121
|
+
"User-Agent": `socialrouter-sdk/${SDK_VERSION}`,
|
|
73
122
|
},
|
|
74
123
|
...(body ? { body: JSON.stringify(body) } : {}),
|
|
75
124
|
});
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { SocialRouter } from "./client.js";
|
|
2
2
|
export { SocialRouterError, AuthenticationError, InsufficientCreditsError, RateLimitError, } from "./errors.js";
|
|
3
|
-
export type { SocialRouterConfig, ExtractOptions, Extraction, ExtractionRecord, ExtractionType, ExtractionStatus, Platform, ProviderInfo, ProviderDetail, AccountBalance, UsageSummary, ApiErrorDetail, } from "./types.js";
|
|
3
|
+
export type { SocialRouterConfig, ExtractOptions, SearchOptions, Extraction, ExtractionRecord, ExtractionType, ExtractionStatus, ExtractionKind, SearchType, ServiceType, Platform, ProviderInfo, ProviderDetail, ProviderStatus, AccountBalance, UsageSummary, ApiErrorDetail, } from "./types.js";
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,wBAAwB,EACxB,cAAc,GACf,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,kBAAkB,EAClB,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,cAAc,EACd,YAAY,EACZ,cAAc,GACf,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,wBAAwB,EACxB,cAAc,GACf,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,UAAU,EACV,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,cAAc,EACd,cAAc,EACd,YAAY,EACZ,cAAc,GACf,MAAM,YAAY,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,15 +1,53 @@
|
|
|
1
|
-
export type
|
|
2
|
-
export type
|
|
1
|
+
export type Platform = "linkedin" | "instagram" | "x" | "reddit" | "facebook" | "tiktok" | "youtube" | "pinterest" | "bluesky" | "snapchat" | "googlemaps";
|
|
2
|
+
export type ExtractionType = "post.likes" | "post.comments" | "post.info" | "profile.info" | "profile.posts" | "profile.reels" | "profile.shorts" | "profile.followers" | "company.info" | "company.reviews" | "group.posts" | "job.listings" | "event.info" | "marketplace.listings" | "video.info" | "video.transcript" | "channel.info" | "playlist.posts" | "hashtag.posts" | "place.info" | "place.reviews";
|
|
3
|
+
export type SearchType = "place.search" | "video.search";
|
|
4
|
+
export type ServiceType = ExtractionType | SearchType;
|
|
3
5
|
export type ExtractionStatus = "pending" | "completed" | "failed";
|
|
6
|
+
export type ExtractionKind = "extract" | "search";
|
|
7
|
+
export type ProviderStatus = "active" | "degraded" | "down" | "coming_soon";
|
|
4
8
|
export interface ExtractOptions {
|
|
5
|
-
url: string;
|
|
6
9
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
|
|
10
|
+
* Single URL to extract from. Use `urls` for batch-capable providers when
|
|
11
|
+
* sending more than one URL in a single request.
|
|
12
|
+
*/
|
|
13
|
+
url?: string;
|
|
14
|
+
/** Batch form — non-empty array of URLs. Mutually exclusive with `url`. */
|
|
15
|
+
urls?: string[];
|
|
16
|
+
/**
|
|
17
|
+
* Service slug of the form `<provider>/<platform>/<type>[:<tag>]`
|
|
18
|
+
* (e.g. `apify/linkedin/profile.info` or
|
|
19
|
+
* `apify/linkedin/profile.posts:apimaestro`). The `:tag` suffix is optional
|
|
20
|
+
* and selects a specific actor/dataset variant.
|
|
10
21
|
*/
|
|
11
22
|
provider: string;
|
|
12
23
|
limit?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Whether to fall over to alternative providers if the requested one fails.
|
|
26
|
+
* Defaults to `true`. Set to `false` to attempt only the requested provider
|
|
27
|
+
* and surface its error directly.
|
|
28
|
+
*/
|
|
29
|
+
fallback?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Per-actor input overrides. Plain JSON object — each actor decides which
|
|
32
|
+
* keys it honors via its `buildInput` allowlist (unknown keys are dropped
|
|
33
|
+
* server-side). Use this for actor-specific knobs that don't have a
|
|
34
|
+
* first-class slot in the request body (e.g. `proxyCountry`, `language`).
|
|
35
|
+
*/
|
|
36
|
+
options?: Record<string, unknown>;
|
|
37
|
+
}
|
|
38
|
+
export interface SearchOptions {
|
|
39
|
+
/** Non-empty list of search queries (terms or context-pinning URLs). */
|
|
40
|
+
queries: string[];
|
|
41
|
+
/**
|
|
42
|
+
* Service slug `<provider>/<platform>/<type>[:<tag>]` whose `type` belongs
|
|
43
|
+
* to the SearchType union (e.g. `apify/googlemaps/place.search:compass`).
|
|
44
|
+
*/
|
|
45
|
+
provider: string;
|
|
46
|
+
limit?: number;
|
|
47
|
+
/** Defaults to `true`. See `ExtractOptions.fallback`. */
|
|
48
|
+
fallback?: boolean;
|
|
49
|
+
/** Per-actor input overrides. See `ExtractOptions.options`. */
|
|
50
|
+
options?: Record<string, unknown>;
|
|
13
51
|
}
|
|
14
52
|
export interface ExtractionRecord {
|
|
15
53
|
name: string;
|
|
@@ -23,11 +61,19 @@ export interface ExtractionRecord {
|
|
|
23
61
|
}
|
|
24
62
|
export interface Extraction {
|
|
25
63
|
id: string;
|
|
64
|
+
kind: ExtractionKind;
|
|
26
65
|
status: ExtractionStatus;
|
|
27
66
|
source: Platform;
|
|
28
|
-
type: ExtractionType;
|
|
67
|
+
type: ExtractionType | SearchType;
|
|
29
68
|
url: string;
|
|
69
|
+
/** Populated when `kind === "search"` — the original list of queries. */
|
|
70
|
+
queries?: string[];
|
|
30
71
|
provider: string;
|
|
72
|
+
/**
|
|
73
|
+
* Present only when a fallback was used. Holds the provider that was
|
|
74
|
+
* initially selected by the router before the chain rolled over.
|
|
75
|
+
*/
|
|
76
|
+
fallback_from?: string;
|
|
31
77
|
credits_used: number;
|
|
32
78
|
data: ExtractionRecord[];
|
|
33
79
|
pagination: {
|
|
@@ -43,9 +89,11 @@ export interface ProviderInfo {
|
|
|
43
89
|
id: string;
|
|
44
90
|
name: string;
|
|
45
91
|
description: string;
|
|
46
|
-
status:
|
|
92
|
+
status: ProviderStatus;
|
|
47
93
|
supported_platforms: Platform[];
|
|
48
94
|
supported_types: ExtractionType[];
|
|
95
|
+
/** Search-style services supported by this provider, if any. */
|
|
96
|
+
supported_search_types?: SearchType[];
|
|
49
97
|
}
|
|
50
98
|
export interface ProviderDetail extends ProviderInfo {
|
|
51
99
|
pricing: {
|
|
@@ -53,6 +101,12 @@ export interface ProviderDetail extends ProviderInfo {
|
|
|
53
101
|
platforms: Platform[];
|
|
54
102
|
price_per_record: number;
|
|
55
103
|
}[];
|
|
104
|
+
/** Pricing for search-style services, keyed by SearchType. */
|
|
105
|
+
search_pricing?: {
|
|
106
|
+
type: SearchType;
|
|
107
|
+
platforms: Platform[];
|
|
108
|
+
price_per_record: number;
|
|
109
|
+
}[];
|
|
56
110
|
}
|
|
57
111
|
export interface AccountBalance {
|
|
58
112
|
balance: number;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GACtB,YAAY,GACZ,eAAe,GACf,cAAc,GACd,eAAe,GACf,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@socialrouter/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Official TypeScript SDK for the SocialRouter API",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -11,13 +11,28 @@
|
|
|
11
11
|
"import": "./dist/index.js"
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
|
-
"files": [
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"README.md",
|
|
17
|
+
"LICENSE"
|
|
18
|
+
],
|
|
15
19
|
"scripts": {
|
|
16
20
|
"build": "tsc",
|
|
17
21
|
"dev": "tsc --watch",
|
|
18
22
|
"prepublishOnly": "npm run build"
|
|
19
23
|
},
|
|
20
|
-
"keywords": [
|
|
24
|
+
"keywords": [
|
|
25
|
+
"socialrouter",
|
|
26
|
+
"social-media",
|
|
27
|
+
"scraping",
|
|
28
|
+
"api",
|
|
29
|
+
"sdk",
|
|
30
|
+
"linkedin",
|
|
31
|
+
"instagram",
|
|
32
|
+
"twitter",
|
|
33
|
+
"x",
|
|
34
|
+
"reddit"
|
|
35
|
+
],
|
|
21
36
|
"author": "SocialRouter",
|
|
22
37
|
"license": "MIT",
|
|
23
38
|
"homepage": "https://www.socialrouter.io",
|