stophy 1.0.1 → 1.0.3
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 +13 -17
- package/dist/index.cjs +45 -162
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8346 -19607
- package/dist/index.d.ts +8346 -19607
- package/dist/index.js +45 -162
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ const result = await new Stophy().web.search({ query: "bun runtime" });
|
|
|
17
17
|
console.log(result.data.results);
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
Web search, YouTube search, and
|
|
20
|
+
Web search, YouTube search, and transcripts work without a key, with a small free allowance. Every other method throws a `StophyError` with the code `unauthorized`.
|
|
21
21
|
|
|
22
22
|
## Use an API key
|
|
23
23
|
|
|
@@ -32,42 +32,38 @@ console.log(videos.data.results);
|
|
|
32
32
|
|
|
33
33
|
`new Stophy("st_...")` works too.
|
|
34
34
|
|
|
35
|
-
Methods follow the source and the command: `stophy.maps.search(...)`, `stophy.reddit.subreddit(...)`, `stophy.
|
|
35
|
+
Methods follow the source and the command: `stophy.maps.search(...)`, `stophy.reddit.subreddit(...)`, `stophy.ads.search({ network: "meta", ... })`. Endpoints with a single name are methods on the client: `stophy.transcript(...)`, `stophy.suggest(...)`.
|
|
36
|
+
|
|
37
|
+
Every response is `{ success, data, creditsUsed, requestId }`. `data` is one flat object. Lists are in `data.results`.
|
|
36
38
|
|
|
37
39
|
## More sources
|
|
38
40
|
|
|
39
|
-
A
|
|
41
|
+
A transcript, Reddit posts, Google Maps reviews, an Amazon product and Meta ads:
|
|
40
42
|
|
|
41
43
|
```ts
|
|
42
44
|
const stophy = new Stophy({ apiKey: "st_..." });
|
|
43
45
|
|
|
44
|
-
const transcript = await stophy.
|
|
46
|
+
const transcript = await stophy.transcript({ video: "https://youtu.be/dQw4w9WgXcQ", includeTimestamps: true });
|
|
45
47
|
console.log(transcript.data.text, transcript.data.segments);
|
|
46
48
|
|
|
47
49
|
const posts = await stophy.reddit.search({ query: "bun runtime", sort: "top", within: "month" });
|
|
48
50
|
console.log(posts.data.results);
|
|
49
51
|
|
|
50
|
-
const places = await stophy.maps.search({ query: "coffee",
|
|
51
|
-
const placeId = places.data.
|
|
52
|
+
const places = await stophy.maps.search({ query: "coffee", location: "Austin, TX", limit: 5 });
|
|
53
|
+
const placeId = places.data.results[0]?.placeId;
|
|
52
54
|
if (placeId) {
|
|
53
55
|
const reviews = await stophy.maps.reviews({ place: placeId, limit: 20 });
|
|
54
|
-
console.log(reviews.data.
|
|
56
|
+
console.log(reviews.data.results);
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
const product = await stophy.amazon.product({ product: "B08N5WRWNW", country: "us" });
|
|
58
|
-
console.log(product.data.
|
|
59
|
-
```
|
|
60
|
+
console.log(product.data.title, product.data.price);
|
|
60
61
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
```ts
|
|
64
|
-
const markdown = await stophy.youtube.search(
|
|
65
|
-
{ query: "bun runtime", limit: 5 },
|
|
66
|
-
{ format: "markdown" },
|
|
67
|
-
);
|
|
62
|
+
const ads = await stophy.ads.search({ network: "meta", query: "running shoes" });
|
|
63
|
+
console.log(ads.data.results);
|
|
68
64
|
```
|
|
69
65
|
|
|
70
|
-
|
|
66
|
+
Some endpoints cover several sources. Pick one with a field: `network` for `ads.*`, `source` for `suggest`, `by` for `google.trends`. The types follow the choice.
|
|
71
67
|
|
|
72
68
|
## Get the next page
|
|
73
69
|
|
package/dist/index.cjs
CHANGED
|
@@ -106,29 +106,18 @@ function isRecord(value) {
|
|
|
106
106
|
|
|
107
107
|
// src/bind.ts
|
|
108
108
|
function post(path, call) {
|
|
109
|
-
|
|
110
|
-
return call({ method: "POST", path, body, options });
|
|
111
|
-
}
|
|
112
|
-
return run;
|
|
109
|
+
return (body, options) => call({ method: "POST", path, body, options });
|
|
113
110
|
}
|
|
114
111
|
function postOptional(path, call) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
}
|
|
121
|
-
return run;
|
|
112
|
+
return (body, options) => call({
|
|
113
|
+
method: "POST",
|
|
114
|
+
path,
|
|
115
|
+
body: body ?? {},
|
|
116
|
+
options
|
|
117
|
+
});
|
|
122
118
|
}
|
|
123
119
|
function get(path, call) {
|
|
124
|
-
|
|
125
|
-
return call({ method: "GET", path, options });
|
|
126
|
-
}
|
|
127
|
-
return run;
|
|
128
|
-
}
|
|
129
|
-
function isMarkdownOptions(value) {
|
|
130
|
-
if (typeof value !== "object" || value === null) return false;
|
|
131
|
-
return "format" in value && value.format === "markdown";
|
|
120
|
+
return (options) => call({ method: "GET", path, options });
|
|
132
121
|
}
|
|
133
122
|
|
|
134
123
|
// src/generated/surface.gen.ts
|
|
@@ -137,26 +126,19 @@ function bindSurface(call) {
|
|
|
137
126
|
endpoints: get("/v1/endpoints", call),
|
|
138
127
|
web: {
|
|
139
128
|
search: post("/v1/web/search", call),
|
|
140
|
-
news: postOptional("/v1/web/news", call)
|
|
141
|
-
contacts: post("/v1/web/contacts", call)
|
|
129
|
+
news: postOptional("/v1/web/news", call)
|
|
142
130
|
},
|
|
143
131
|
youtube: {
|
|
144
132
|
search: post("/v1/youtube/search", call),
|
|
145
133
|
video: post("/v1/youtube/video", call),
|
|
146
|
-
|
|
147
|
-
comments: Object.assign(post("/v1/youtube/comments", call), {
|
|
148
|
-
replies: post("/v1/youtube/comments/replies", call)
|
|
149
|
-
}),
|
|
134
|
+
comments: post("/v1/youtube/comments", call),
|
|
150
135
|
channel: post("/v1/youtube/channel", call),
|
|
151
|
-
playlist: post("/v1/youtube/playlist", call)
|
|
152
|
-
suggest: post("/v1/youtube/suggest", call)
|
|
136
|
+
playlist: post("/v1/youtube/playlist", call)
|
|
153
137
|
},
|
|
138
|
+
transcript: post("/v1/transcript", call),
|
|
154
139
|
reddit: {
|
|
155
140
|
search: post("/v1/reddit/search", call),
|
|
156
141
|
post: post("/v1/reddit/post", call),
|
|
157
|
-
comments: {
|
|
158
|
-
more: post("/v1/reddit/comments/more", call)
|
|
159
|
-
},
|
|
160
142
|
subreddit: post("/v1/reddit/subreddit", call),
|
|
161
143
|
user: post("/v1/reddit/user", call),
|
|
162
144
|
domain: post("/v1/reddit/domain", call)
|
|
@@ -168,59 +150,34 @@ function bindSurface(call) {
|
|
|
168
150
|
},
|
|
169
151
|
instagram: {
|
|
170
152
|
profile: post("/v1/instagram/profile", call),
|
|
171
|
-
posts: post("/v1/instagram/posts", call),
|
|
172
153
|
post: post("/v1/instagram/post", call),
|
|
173
|
-
url: post("/v1/instagram/url", call),
|
|
174
154
|
search: post("/v1/instagram/search", call),
|
|
175
|
-
|
|
176
|
-
comments: Object.assign(post("/v1/instagram/comments", call), {
|
|
177
|
-
replies: post("/v1/instagram/comments/replies", call)
|
|
178
|
-
})
|
|
155
|
+
comments: post("/v1/instagram/comments", call)
|
|
179
156
|
},
|
|
180
157
|
tiktok: {
|
|
181
158
|
profile: post("/v1/tiktok/profile", call),
|
|
182
159
|
video: post("/v1/tiktok/video", call),
|
|
183
|
-
url: post("/v1/tiktok/url", call),
|
|
184
|
-
transcript: post("/v1/tiktok/transcript", call),
|
|
185
|
-
posts: post("/v1/tiktok/posts", call),
|
|
186
160
|
hashtag: post("/v1/tiktok/hashtag", call),
|
|
187
|
-
comments:
|
|
188
|
-
|
|
189
|
-
}),
|
|
190
|
-
search: post("/v1/tiktok/search", call),
|
|
191
|
-
ads: {
|
|
192
|
-
search: postOptional("/v1/tiktok/ads/search", call),
|
|
193
|
-
ad: post("/v1/tiktok/ads/ad", call)
|
|
194
|
-
}
|
|
161
|
+
comments: post("/v1/tiktok/comments", call),
|
|
162
|
+
search: post("/v1/tiktok/search", call)
|
|
195
163
|
},
|
|
196
164
|
bluesky: {
|
|
197
165
|
profile: post("/v1/bluesky/profile", call),
|
|
198
|
-
posts: post("/v1/bluesky/posts", call),
|
|
199
166
|
post: post("/v1/bluesky/post", call),
|
|
200
167
|
followers: post("/v1/bluesky/followers", call)
|
|
201
168
|
},
|
|
202
|
-
mastodon: {
|
|
203
|
-
profile: post("/v1/mastodon/profile", call),
|
|
204
|
-
posts: post("/v1/mastodon/posts", call),
|
|
205
|
-
post: post("/v1/mastodon/post", call),
|
|
206
|
-
hashtag: post("/v1/mastodon/hashtag", call)
|
|
207
|
-
},
|
|
208
169
|
threads: {
|
|
209
170
|
profile: post("/v1/threads/profile", call),
|
|
210
|
-
posts: post("/v1/threads/posts", call),
|
|
211
171
|
post: post("/v1/threads/post", call),
|
|
212
172
|
search: post("/v1/threads/search", call)
|
|
213
173
|
},
|
|
214
174
|
telegram: {
|
|
215
|
-
channel: post("/v1/telegram/channel", call),
|
|
216
175
|
posts: post("/v1/telegram/posts", call),
|
|
217
176
|
post: post("/v1/telegram/post", call)
|
|
218
177
|
},
|
|
219
178
|
meta: {
|
|
220
179
|
ads: {
|
|
221
|
-
|
|
222
|
-
page: post("/v1/meta/ads/page", call),
|
|
223
|
-
ad: post("/v1/meta/ads/ad", call)
|
|
180
|
+
page: post("/v1/meta/ads/page", call)
|
|
224
181
|
}
|
|
225
182
|
},
|
|
226
183
|
linkedin: {
|
|
@@ -228,82 +185,40 @@ function bindSurface(call) {
|
|
|
228
185
|
search: postOptional("/v1/linkedin/jobs/search", call),
|
|
229
186
|
job: post("/v1/linkedin/jobs/job", call)
|
|
230
187
|
},
|
|
231
|
-
|
|
232
|
-
search: postOptional("/v1/linkedin/ads/search", call),
|
|
233
|
-
ad: post("/v1/linkedin/ads/ad", call)
|
|
234
|
-
},
|
|
235
|
-
company: Object.assign(post("/v1/linkedin/company", call), {
|
|
236
|
-
posts: post("/v1/linkedin/company/posts", call)
|
|
237
|
-
}),
|
|
188
|
+
company: post("/v1/linkedin/company", call),
|
|
238
189
|
profile: post("/v1/linkedin/profile", call),
|
|
239
190
|
posts: postOptional("/v1/linkedin/posts", call)
|
|
240
191
|
},
|
|
241
192
|
zillow: {
|
|
242
|
-
search:
|
|
193
|
+
search: post("/v1/zillow/search", call),
|
|
243
194
|
property: post("/v1/zillow/property", call)
|
|
244
195
|
},
|
|
245
|
-
google: {
|
|
246
|
-
ads: {
|
|
247
|
-
advertisers: post("/v1/google/ads/advertisers", call),
|
|
248
|
-
search: postOptional("/v1/google/ads/search", call),
|
|
249
|
-
ad: post("/v1/google/ads/ad", call)
|
|
250
|
-
},
|
|
251
|
-
suggest: post("/v1/google/suggest", call),
|
|
252
|
-
trends: {
|
|
253
|
-
interest: post("/v1/google/trends/interest", call),
|
|
254
|
-
regions: post("/v1/google/trends/regions", call),
|
|
255
|
-
related: post("/v1/google/trends/related", call),
|
|
256
|
-
trending: postOptional("/v1/google/trends/trending", call)
|
|
257
|
-
}
|
|
258
|
-
},
|
|
259
196
|
upwork: {
|
|
260
197
|
search: postOptional("/v1/upwork/search", call),
|
|
261
198
|
job: post("/v1/upwork/job", call)
|
|
262
199
|
},
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
200
|
+
google: {
|
|
201
|
+
trends: Object.assign(post("/v1/google/trends", call), {
|
|
202
|
+
related: post("/v1/google/trends/related", call),
|
|
203
|
+
trending: postOptional("/v1/google/trends/trending", call)
|
|
204
|
+
})
|
|
268
205
|
},
|
|
269
206
|
site: {
|
|
270
|
-
map: post("/v1/site/map", call),
|
|
271
207
|
seo: post("/v1/site/seo", call)
|
|
272
208
|
},
|
|
273
|
-
domain: {
|
|
274
|
-
whois: post("/v1/domain/whois", call),
|
|
275
|
-
dns: post("/v1/domain/dns", call),
|
|
276
|
-
tech: post("/v1/domain/tech", call)
|
|
277
|
-
},
|
|
278
209
|
email: {
|
|
279
|
-
|
|
210
|
+
verify: post("/v1/email/verify", call),
|
|
211
|
+
find: post("/v1/email/find", call)
|
|
280
212
|
},
|
|
281
213
|
crypto: {
|
|
282
214
|
coins: postOptional("/v1/crypto/coins", call),
|
|
283
215
|
coin: post("/v1/crypto/coin", call),
|
|
284
216
|
history: post("/v1/crypto/history", call),
|
|
285
|
-
trending: postOptional("/v1/crypto/trending", call),
|
|
286
|
-
categories: postOptional("/v1/crypto/categories", call),
|
|
287
|
-
movers: postOptional("/v1/crypto/movers", call),
|
|
288
|
-
new: postOptional("/v1/crypto/new", call),
|
|
289
217
|
dex: {
|
|
290
218
|
search: post("/v1/crypto/dex/search", call),
|
|
291
|
-
|
|
292
|
-
token: post("/v1/crypto/dex/token", call),
|
|
293
|
-
new: postOptional("/v1/crypto/dex/new", call)
|
|
294
|
-
},
|
|
295
|
-
pump: {
|
|
296
|
-
coins: postOptional("/v1/crypto/pump/coins", call),
|
|
297
|
-
coin: post("/v1/crypto/pump/coin", call),
|
|
298
|
-
trades: post("/v1/crypto/pump/trades", call)
|
|
219
|
+
token: post("/v1/crypto/dex/token", call)
|
|
299
220
|
},
|
|
300
|
-
wallet: post("/v1/crypto/wallet", call)
|
|
301
|
-
token: {
|
|
302
|
-
holders: post("/v1/crypto/token/holders", call)
|
|
303
|
-
},
|
|
304
|
-
binance: {
|
|
305
|
-
announcements: postOptional("/v1/crypto/binance/announcements", call)
|
|
306
|
-
}
|
|
221
|
+
wallet: post("/v1/crypto/wallet", call)
|
|
307
222
|
},
|
|
308
223
|
indeed: {
|
|
309
224
|
search: postOptional("/v1/indeed/search", call),
|
|
@@ -317,6 +232,11 @@ function bindSurface(call) {
|
|
|
317
232
|
googletravel: {
|
|
318
233
|
flights: post("/v1/googletravel/flights", call)
|
|
319
234
|
},
|
|
235
|
+
amazon: {
|
|
236
|
+
search: postOptional("/v1/amazon/search", call),
|
|
237
|
+
product: post("/v1/amazon/product", call),
|
|
238
|
+
bestsellers: post("/v1/amazon/bestsellers", call)
|
|
239
|
+
},
|
|
320
240
|
shopify: {
|
|
321
241
|
products: post("/v1/shopify/products", call),
|
|
322
242
|
collections: post("/v1/shopify/collections", call),
|
|
@@ -347,14 +267,6 @@ function bindSurface(call) {
|
|
|
347
267
|
calendar: post("/v1/airbnb/calendar", call),
|
|
348
268
|
reviews: post("/v1/airbnb/reviews", call)
|
|
349
269
|
},
|
|
350
|
-
redfin: {
|
|
351
|
-
search: post("/v1/redfin/search", call),
|
|
352
|
-
property: post("/v1/redfin/property", call)
|
|
353
|
-
},
|
|
354
|
-
realtor: {
|
|
355
|
-
search: post("/v1/realtor/search", call),
|
|
356
|
-
property: post("/v1/realtor/property", call)
|
|
357
|
-
},
|
|
358
270
|
rightmove: {
|
|
359
271
|
search: post("/v1/rightmove/search", call),
|
|
360
272
|
property: post("/v1/rightmove/property", call)
|
|
@@ -367,54 +279,28 @@ function bindSurface(call) {
|
|
|
367
279
|
search: post("/v1/pinterest/search", call),
|
|
368
280
|
pin: post("/v1/pinterest/pin", call),
|
|
369
281
|
board: post("/v1/pinterest/board", call),
|
|
370
|
-
user: post("/v1/pinterest/user", call)
|
|
371
|
-
ads: {
|
|
372
|
-
search: post("/v1/pinterest/ads/search", call),
|
|
373
|
-
ad: post("/v1/pinterest/ads/ad", call)
|
|
374
|
-
}
|
|
282
|
+
user: post("/v1/pinterest/user", call)
|
|
375
283
|
},
|
|
376
284
|
x: {
|
|
377
|
-
|
|
378
|
-
},
|
|
379
|
-
kick: {
|
|
380
|
-
channel: post("/v1/kick/channel", call),
|
|
381
|
-
videos: post("/v1/kick/videos", call),
|
|
382
|
-
clips: post("/v1/kick/clips", call)
|
|
285
|
+
post: post("/v1/x/post", call)
|
|
383
286
|
},
|
|
384
287
|
finance: {
|
|
385
288
|
quote: post("/v1/finance/quote", call),
|
|
386
289
|
history: post("/v1/finance/history", call),
|
|
387
290
|
search: post("/v1/finance/search", call),
|
|
388
|
-
|
|
291
|
+
stock: post("/v1/finance/stock", call)
|
|
389
292
|
},
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
advertisers: post("/v1/microsoft/ads/advertisers", call)
|
|
395
|
-
}
|
|
396
|
-
},
|
|
397
|
-
snapchat: {
|
|
398
|
-
profile: post("/v1/snapchat/profile", call),
|
|
399
|
-
ads: {
|
|
400
|
-
search: post("/v1/snapchat/ads/search", call),
|
|
401
|
-
ad: post("/v1/snapchat/ads/ad", call)
|
|
402
|
-
}
|
|
403
|
-
},
|
|
404
|
-
tumblr: {
|
|
405
|
-
blog: post("/v1/tumblr/blog", call),
|
|
406
|
-
posts: post("/v1/tumblr/posts", call),
|
|
407
|
-
post: post("/v1/tumblr/post", call),
|
|
408
|
-
search: post("/v1/tumblr/search", call)
|
|
293
|
+
ads: {
|
|
294
|
+
search: post("/v1/ads/search", call),
|
|
295
|
+
ad: post("/v1/ads/ad", call),
|
|
296
|
+
advertisers: post("/v1/ads/advertisers", call)
|
|
409
297
|
},
|
|
410
|
-
|
|
411
|
-
question: post("/v1/quora/question", call)
|
|
412
|
-
}
|
|
298
|
+
suggest: post("/v1/suggest", call)
|
|
413
299
|
};
|
|
414
300
|
}
|
|
415
301
|
|
|
416
302
|
// package.json
|
|
417
|
-
var version = "1.0.
|
|
303
|
+
var version = "1.0.3";
|
|
418
304
|
|
|
419
305
|
// src/transport.ts
|
|
420
306
|
var DEFAULT_BASE_URL = "https://api.stophy.dev";
|
|
@@ -431,7 +317,6 @@ function createCaller(options) {
|
|
|
431
317
|
timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS
|
|
432
318
|
};
|
|
433
319
|
return async (spec) => {
|
|
434
|
-
const markdown = spec.options?.format === "markdown";
|
|
435
320
|
const headers = new Headers(options.headers);
|
|
436
321
|
if (typeof document === "undefined" && !headers.has("user-agent")) {
|
|
437
322
|
headers.set("user-agent", USER_AGENT);
|
|
@@ -439,7 +324,7 @@ function createCaller(options) {
|
|
|
439
324
|
if (options.apiKey) {
|
|
440
325
|
headers.set("authorization", `Bearer ${options.apiKey}`);
|
|
441
326
|
}
|
|
442
|
-
headers.set("accept",
|
|
327
|
+
headers.set("accept", "application/json");
|
|
443
328
|
if (spec.body !== void 0)
|
|
444
329
|
headers.set("content-type", "application/json");
|
|
445
330
|
const url = withQuery(`${baseUrl}${spec.path}`, spec.query);
|
|
@@ -452,13 +337,12 @@ function createCaller(options) {
|
|
|
452
337
|
body: spec.body === void 0 ? void 0 : JSON.stringify(spec.body),
|
|
453
338
|
signal
|
|
454
339
|
}),
|
|
455
|
-
markdown,
|
|
456
340
|
spec.options?.signal,
|
|
457
341
|
retry
|
|
458
342
|
);
|
|
459
343
|
};
|
|
460
344
|
}
|
|
461
|
-
async function send(baseFetch, url, init,
|
|
345
|
+
async function send(baseFetch, url, init, signal, retry) {
|
|
462
346
|
for (let n = 0; ; n += 1) {
|
|
463
347
|
const deadline = withDeadline(signal, retry.timeoutMs);
|
|
464
348
|
let waitMs;
|
|
@@ -479,7 +363,7 @@ async function send(baseFetch, url, init, markdown, signal, retry) {
|
|
|
479
363
|
}
|
|
480
364
|
waitMs = seconds === void 0 ? backoffMs(n, retry.initialDelayMs) : seconds * 1e3;
|
|
481
365
|
} else {
|
|
482
|
-
return await readBody(response
|
|
366
|
+
return await readBody(response);
|
|
483
367
|
}
|
|
484
368
|
} finally {
|
|
485
369
|
deadline.clear();
|
|
@@ -509,10 +393,9 @@ function withDeadline(signal, timeoutMs) {
|
|
|
509
393
|
}
|
|
510
394
|
};
|
|
511
395
|
}
|
|
512
|
-
async function readBody(response
|
|
396
|
+
async function readBody(response) {
|
|
513
397
|
if (!response.ok) throw await errorFrom(response);
|
|
514
398
|
const text = await response.text();
|
|
515
|
-
if (markdown) return text;
|
|
516
399
|
if (!text) {
|
|
517
400
|
throw failed(response, "Stophy returned an empty response", {});
|
|
518
401
|
}
|