@rackbops/docket-types 0.11.1 → 0.13.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/README.md +21 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/want-ebay.d.ts +61 -0
- package/dist/want-ebay.d.ts.map +1 -0
- package/dist/want-ebay.js +177 -0
- package/dist/want-ebay.js.map +1 -0
- package/dist/want-shopify.d.ts +70 -0
- package/dist/want-shopify.d.ts.map +1 -0
- package/dist/want-shopify.js +221 -0
- package/dist/want-shopify.js.map +1 -0
- package/dist/want-sources.d.ts +16 -5
- package/dist/want-sources.d.ts.map +1 -1
- package/dist/want-sources.js +1 -1
- package/dist/want-sources.js.map +1 -1
- package/dist/wantjudge.d.ts +1 -1
- package/dist/wantjudge.d.ts.map +1 -1
- package/dist/wantjudge.js +33 -17
- package/dist/wantjudge.js.map +1 -1
- package/dist/wantlist.d.ts +10 -1
- package/dist/wantlist.d.ts.map +1 -1
- package/dist/wantlist.js +45 -12
- package/dist/wantlist.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -201,7 +201,11 @@ The tracker's task types, built on `@rackbops/docket-core`'s contract. Shipped s
|
|
|
201
201
|
Fetch port, never eBay), `bggSource` (BGG's XML API, with the host's token) and `inboxSource`
|
|
202
202
|
(listings the host stored for the watch's inbox key: alert emails, or searches someone ran in
|
|
203
203
|
their own browser and sent in; `submittedListing` cleans each one, and the judge opens no
|
|
204
|
-
page for such a watch)
|
|
204
|
+
page for such a watch) and `shopifySource` (new copies in stock at Shopify stores, from
|
|
205
|
+
Shopify's catalog search through Firecrawl's Alexandria, 5 credits a look; a product counts only
|
|
206
|
+
when every word of the search is in its title, and the judge opens no store for it) and
|
|
207
|
+
`ebaySource` (eBay listings from eBay's own Browse API, with the host's eBay app token; the
|
|
208
|
+
judge opens no eBay page for it).
|
|
205
209
|
- `wantjudge` (category 2, plan 5.4, item 63): the same watch on the execute lane. New listings
|
|
206
210
|
are read in plain code (no charge), then one Job has the model judge each one and its seller
|
|
207
211
|
(WebFetch only on the watch's own host, never WebSearch or the runner's files; 12 turns,
|
|
@@ -216,6 +220,21 @@ host:
|
|
|
216
220
|
|
|
217
221
|
- its Fetch port refuses any hop to eBay when a read carries the `NEVER_EBAY` header, and does
|
|
218
222
|
not send that header on;
|
|
223
|
+
- `shopifySource(scrape)` gets a `scrape(request)` that sends `request` as the `alexandria` field
|
|
224
|
+
of Firecrawl's `POST https://api.firecrawl.dev/v2/scrape` with the host's own key, and hands back
|
|
225
|
+
the HTTP status and the parsed JSON body (bounded in time and size). The watch's `target` is
|
|
226
|
+
the words to search for; its top price and currency narrow the search itself. Each look is
|
|
227
|
+
paid for (5 credits), and the type sets no floor on how often a `poll` runs, so the host keeps
|
|
228
|
+
a Shopify watch's interval long (the tracker's floor is a day);
|
|
229
|
+
- `ebaySource(browse)` gets a `browse(request)` that sends `GET https://api.ebay.com` +
|
|
230
|
+
`request.path` with `request.params` as the query, `X-EBAY-C-MARKETPLACE-ID: request.marketplace`
|
|
231
|
+
and an application token (client credentials, scope `https://api.ebay.com/oauth/api_scope`) from
|
|
232
|
+
the host's own eBay keys, and hands back the HTTP status and the parsed JSON body (bounded in
|
|
233
|
+
time and size). The watch's `target` is the words to search for. eBay's API License wants
|
|
234
|
+
listing data shown no more than six hours old: a plain watch DMs what it read at once, and a
|
|
235
|
+
judged one once the model has looked. An eBay watch stores no findings (`keepsFindings`), so a
|
|
236
|
+
host that keeps no eBay data also clears the run's recorded DM after a while, and does not judge
|
|
237
|
+
one whose Job a queue would keep;
|
|
219
238
|
- its Fetch port reaches only public addresses, checked after the name lookup: the judge grants
|
|
220
239
|
the runner WebFetch on the watch's own host only because the host's reads already reach it;
|
|
221
240
|
- `bggSource` gets a Fetch that hands back the body as sent and follows no redirect, so BGG's
|
|
@@ -230,7 +249,7 @@ host:
|
|
|
230
249
|
|
|
231
250
|
```ts
|
|
232
251
|
import { TASK_TYPES, reminder, renewal, price, research, scout, TYPE_IDS, isTypeId } from "@rackbops/docket-types"
|
|
233
|
-
import { bggSource, inboxSource, pageSource, wantjudgeType, wantlistType } from "@rackbops/docket-types"
|
|
252
|
+
import { bggSource, ebaySource, inboxSource, pageSource, shopifySource, wantjudgeType, wantlistType } from "@rackbops/docket-types"
|
|
234
253
|
```
|
|
235
254
|
|
|
236
255
|
`TASK_TYPES` is every shipped type keyed by id, ready for the dispatcher. Every type is declared
|
package/dist/index.d.ts
CHANGED
|
@@ -21,9 +21,11 @@ export { BARRED_SITES, blockedKey, type GatheredPage, gatheredPages, MAX_GATHERE
|
|
|
21
21
|
export { BGG_CATEGORIES, bggCategoryUrl, FIRECRAWL_TOOLS, WEB_ALLOWED_TOOLS, } from "./research-web.js";
|
|
22
22
|
export { itemKey, LENS_TEXT, LENSES, type Lens, lensOf, MAX_FOR_CHARS, MAX_INTEREST_CHARS, MAX_INTERESTS, MAX_ITEMS, MAX_SCOUT_NOTES, MAX_SHOWN, MIN_ITEMS, PROMPT_SHOWN, parseScout, renderScout, SCOUT_MAX_BUDGET_USD, SCOUT_MAX_TURNS, SCOUT_SCHEMA, SCOUT_TIMEOUT_MS, type ScoutConfig, type ScoutItem, type ScoutState, type ShownItem, scout, scoutJob, scoutState, } from "./scout.js";
|
|
23
23
|
export { BGG_ATTRIBUTION, BGG_HOST, BGG_SPACING_MS, type BggOptions, bggSource, bggThingUrl, MAX_SCANNED, parseBggThingId, parseMarketplace, } from "./want-bgg.js";
|
|
24
|
-
export {
|
|
24
|
+
export { EBAY_ATTRIBUTION, EBAY_CURRENCY, EBAY_LIMIT, EBAY_MARKETPLACE, EBAY_SEARCH_PATH, type EbayBrowse, type EbayRequest, type EbaySearch, ebayRequest, ebaySource, parseEbayAnswer, } from "./want-ebay.js";
|
|
25
|
+
export { matchesWords, minorUnits, parseShopifyAnswer, SHOPIFY_ATTRIBUTION, SHOPIFY_CAPABILITY, SHOPIFY_COUNTRY, SHOPIFY_CREDITS, SHOPIFY_CURRENCY, SHOPIFY_LIMIT, SHOPIFY_PROVIDER, type ShopifyRequest, type ShopifyScrape, type ShopifySearch, searchWords, shopifyQuery, shopifyRequest, shopifySource, } from "./want-shopify.js";
|
|
26
|
+
export { inboxSource, isEbayHost, type Listing, listingKey, listingsFromJsonLd, MAX_LISTINGS, NEVER_EBAY, pageSource, type ReadInbox, readListings, type SearchLimits, SOURCE_IDS, type Source, type SourceId, SourceMiss, SourceUnavailableError, type Submitted, submittedListing, } from "./want-sources.js";
|
|
25
27
|
export { FITS, type Fit, JUDGE_MAX_BUDGET_USD, JUDGE_MAX_TURNS, JUDGE_SCHEMA, JUDGE_TIMEOUT_MS, type JudgeOptions, type JudgeState, type JudgeVerdict, judgeHosts, judgeJob, judgeState, parseVerdicts, RETRY_GRACE_MS, renderJudged, renderUnchecked, wantjudgeType, } from "./wantjudge.js";
|
|
26
|
-
export { clip, inert, listingFinding, listingLine, MAX_DM_CHARS, MAX_NEW_PER_RUN, MAX_REPORTED, miss, type Polled, pollWant, priceText, renderWant, SHOWN_IN_DM, type WantConfig, type WantState, wantlistType, wantState, withinLimits, } from "./wantlist.js";
|
|
28
|
+
export { clip, inert, keepsFindings, listingFinding, listingLine, MAX_DM_CHARS, MAX_NEW_PER_RUN, MAX_REPORTED, miss, moreLine, type Polled, pollWant, priceText, renderWant, SHOWN_IN_DM, type WantConfig, type WantState, wantlistType, wantState, withinLimits, } from "./wantlist.js";
|
|
27
29
|
/**
|
|
28
30
|
* The six task categories the tracker starts with (plan section 1.2), as type identifiers, then
|
|
29
31
|
* `wantjudge`: category 2's watch with the model's look first (plan 5.4), a type of its own.
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAUrD,YAAY,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAA;AACjD,OAAO,EACL,KAAK,cAAc,EACnB,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,aAAa,EACb,aAAa,EACb,gBAAgB,GACjB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EACL,cAAc,EACd,KAAK,YAAY,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EACrB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,EACL,SAAS,GACV,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,iBAAiB,EAAE,KAAK,cAAc,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC7F,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,OAAO,GACR,MAAM,cAAc,CAAA;AAErB,OAAO,EACL,aAAa,EACb,UAAU,EACV,SAAS,EACT,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,EACT,mBAAmB,EACnB,uBAAuB,EACvB,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,QAAQ,EACR,WAAW,EACX,aAAa,EACb,YAAY,EACZ,SAAS,EACT,eAAe,GAChB,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,aAAa,EACb,KAAK,WAAW,EAChB,KAAK,EACL,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,YAAY,EACZ,WAAW,EACX,aAAa,EACb,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,MAAM,EACX,YAAY,EACZ,YAAY,EACZ,OAAO,EACP,QAAQ,EACR,KAAK,OAAO,EACZ,IAAI,GACL,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACL,YAAY,EACZ,UAAU,EACV,KAAK,YAAY,EACjB,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACd,oBAAoB,EACpB,cAAc,EACd,cAAc,EACd,UAAU,EACV,SAAS,EACT,KAAK,WAAW,EAChB,qBAAqB,EACrB,+BAA+B,EAC/B,0BAA0B,EAC1B,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,aAAa,EACb,oBAAoB,EACpB,eAAe,GAChB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,cAAc,EACd,cAAc,EACd,eAAe,EACf,iBAAiB,GAClB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACL,OAAO,EACP,SAAS,EACT,MAAM,EACN,KAAK,IAAI,EACT,MAAM,EACN,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,SAAS,EACT,eAAe,EACf,SAAS,EACT,SAAS,EACT,YAAY,EACZ,UAAU,EACV,WAAW,EACX,oBAAoB,EACpB,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,EACL,QAAQ,EACR,UAAU,GACX,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,eAAe,EACf,QAAQ,EACR,cAAc,EACd,KAAK,UAAU,EACf,SAAS,EACT,WAAW,EACX,WAAW,EACX,eAAe,EACf,gBAAgB,GACjB,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,gBAAgB,EAChB,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,WAAW,EACX,UAAU,EACV,eAAe,GAChB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,YAAY,EACZ,UAAU,EACV,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,WAAW,EACX,YAAY,EACZ,cAAc,EACd,aAAa,GACd,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACL,WAAW,EACX,UAAU,EACV,KAAK,OAAO,EACZ,UAAU,EACV,kBAAkB,EAClB,YAAY,EACZ,UAAU,EACV,UAAU,EACV,KAAK,SAAS,EACd,YAAY,EACZ,KAAK,YAAY,EACjB,UAAU,EACV,KAAK,MAAM,EACX,KAAK,QAAQ,EACb,UAAU,EACV,sBAAsB,EACtB,KAAK,SAAS,EACd,gBAAgB,GACjB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACL,IAAI,EACJ,KAAK,GAAG,EACR,oBAAoB,EACpB,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,UAAU,EACV,QAAQ,EACR,UAAU,EACV,aAAa,EACb,cAAc,EACd,YAAY,EACZ,eAAe,EACf,aAAa,GACd,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,IAAI,EACJ,KAAK,EACL,aAAa,EACb,cAAc,EACd,WAAW,EACX,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,IAAI,EACJ,QAAQ,EACR,KAAK,MAAM,EACX,QAAQ,EACR,SAAS,EACT,UAAU,EACV,WAAW,EACX,KAAK,UAAU,EACf,KAAK,SAAS,EACd,YAAY,EACZ,SAAS,EACT,YAAY,GACb,MAAM,eAAe,CAAA;AAEtB;;;GAGG;AACH,eAAO,MAAM,QAAQ,YACnB,UAAU,EACV,SAAS,EACT,OAAO,EACP,UAAU,EACV,OAAO,EACP,UAAU,EACV,WAAW,CACH,CAAA;AAEV,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAA;AAE9C,2FAA2F;AAC3F,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,MAAM,CAEvD;AAED,2EAA2E;AAC3E,eAAO,MAAM,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CASjE,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -27,9 +27,11 @@ export { BARRED_SITES, blockedKey, gatheredPages, MAX_GATHERED_CHARS, MAX_GATHER
|
|
|
27
27
|
export { BGG_CATEGORIES, bggCategoryUrl, FIRECRAWL_TOOLS, WEB_ALLOWED_TOOLS, } from "./research-web.js";
|
|
28
28
|
export { itemKey, LENS_TEXT, LENSES, lensOf, MAX_FOR_CHARS, MAX_INTEREST_CHARS, MAX_INTERESTS, MAX_ITEMS, MAX_SCOUT_NOTES, MAX_SHOWN, MIN_ITEMS, PROMPT_SHOWN, parseScout, renderScout, SCOUT_MAX_BUDGET_USD, SCOUT_MAX_TURNS, SCOUT_SCHEMA, SCOUT_TIMEOUT_MS, scout, scoutJob, scoutState, } from "./scout.js";
|
|
29
29
|
export { BGG_ATTRIBUTION, BGG_HOST, BGG_SPACING_MS, bggSource, bggThingUrl, MAX_SCANNED, parseBggThingId, parseMarketplace, } from "./want-bgg.js";
|
|
30
|
+
export { EBAY_ATTRIBUTION, EBAY_CURRENCY, EBAY_LIMIT, EBAY_MARKETPLACE, EBAY_SEARCH_PATH, ebayRequest, ebaySource, parseEbayAnswer, } from "./want-ebay.js";
|
|
31
|
+
export { matchesWords, minorUnits, parseShopifyAnswer, SHOPIFY_ATTRIBUTION, SHOPIFY_CAPABILITY, SHOPIFY_COUNTRY, SHOPIFY_CREDITS, SHOPIFY_CURRENCY, SHOPIFY_LIMIT, SHOPIFY_PROVIDER, searchWords, shopifyQuery, shopifyRequest, shopifySource, } from "./want-shopify.js";
|
|
30
32
|
export { inboxSource, isEbayHost, listingKey, listingsFromJsonLd, MAX_LISTINGS, NEVER_EBAY, pageSource, readListings, SOURCE_IDS, SourceMiss, SourceUnavailableError, submittedListing, } from "./want-sources.js";
|
|
31
33
|
export { FITS, JUDGE_MAX_BUDGET_USD, JUDGE_MAX_TURNS, JUDGE_SCHEMA, JUDGE_TIMEOUT_MS, judgeHosts, judgeJob, judgeState, parseVerdicts, RETRY_GRACE_MS, renderJudged, renderUnchecked, wantjudgeType, } from "./wantjudge.js";
|
|
32
|
-
export { clip, inert, listingFinding, listingLine, MAX_DM_CHARS, MAX_NEW_PER_RUN, MAX_REPORTED, miss, pollWant, priceText, renderWant, SHOWN_IN_DM, wantlistType, wantState, withinLimits, } from "./wantlist.js";
|
|
34
|
+
export { clip, inert, keepsFindings, listingFinding, listingLine, MAX_DM_CHARS, MAX_NEW_PER_RUN, MAX_REPORTED, miss, moreLine, pollWant, priceText, renderWant, SHOWN_IN_DM, wantlistType, wantState, withinLimits, } from "./wantlist.js";
|
|
33
35
|
/**
|
|
34
36
|
* The six task categories the tracker starts with (plan section 1.2), as type identifiers, then
|
|
35
37
|
* `wantjudge`: category 2's watch with the model's look first (plan 5.4), a type of its own.
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAG5C,OAAO,EAEL,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,aAAa,EACb,aAAa,EACb,gBAAgB,GACjB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EACL,cAAc,EAEd,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EAGrB,KAAK,EACL,SAAS,GACV,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,iBAAiB,EAAuB,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC7F,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EAIjB,OAAO,GACR,MAAM,cAAc,CAAA;AAErB,OAAO,EACL,aAAa,EACb,UAAU,EACV,SAAS,EACT,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,EACT,mBAAmB,EACnB,uBAAuB,EACvB,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EAMjB,QAAQ,EACR,WAAW,EACX,aAAa,EACb,YAAY,EACZ,SAAS,EACT,eAAe,GAChB,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,aAAa,EAEb,KAAK,EACL,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,YAAY,EACZ,WAAW,EACX,aAAa,EAIb,YAAY,EACZ,YAAY,EACZ,OAAO,EACP,QAAQ,EAER,IAAI,GACL,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACL,YAAY,EACZ,UAAU,EAEV,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACd,oBAAoB,EACpB,cAAc,EACd,cAAc,EACd,UAAU,EACV,SAAS,EAET,qBAAqB,EACrB,+BAA+B,EAC/B,0BAA0B,EAC1B,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,aAAa,EACb,oBAAoB,EACpB,eAAe,GAChB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,cAAc,EACd,cAAc,EACd,eAAe,EACf,iBAAiB,GAClB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACL,OAAO,EACP,SAAS,EACT,MAAM,EAEN,MAAM,EACN,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,SAAS,EACT,eAAe,EACf,SAAS,EACT,SAAS,EACT,YAAY,EACZ,UAAU,EACV,WAAW,EACX,oBAAoB,EACpB,eAAe,EACf,YAAY,EACZ,gBAAgB,EAKhB,KAAK,EACL,QAAQ,EACR,UAAU,GACX,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,eAAe,EACf,QAAQ,EACR,cAAc,EAEd,SAAS,EACT,WAAW,EACX,WAAW,EACX,eAAe,EACf,gBAAgB,GACjB,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,WAAW,EACX,UAAU,EAEV,UAAU,EACV,kBAAkB,EAClB,YAAY,EACZ,UAAU,EACV,UAAU,EAEV,YAAY,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type Listing, type Source } from "./want-sources.js";
|
|
2
|
+
/**
|
|
3
|
+
* The eBay source (Rod, 2026-10-20, "Build it" on the eBay Browse API card): listings from eBay's
|
|
4
|
+
* own Browse API, `GET /buy/browse/v1/item_summary/search` (developer.ebay.com, read 2026-10-20),
|
|
5
|
+
* with an application token from the owner's eBay developer keyset. Using eBay's API under its API
|
|
6
|
+
* License Agreement is eBay's own permission, where reading its pages is barred (User Agreement
|
|
7
|
+
* s.3); the tracker still never opens an eBay page, and a judged eBay watch opens none either.
|
|
8
|
+
*
|
|
9
|
+
* A host registers the source only with eBay keys, and runs the request itself (`EbayBrowse`,
|
|
10
|
+
* which adds api.ebay.com, the token and the marketplace header): this library opens nothing.
|
|
11
|
+
*
|
|
12
|
+
* One search a look, the newest `EBAY_LIMIT` listings, fixed-price and auction alike, narrowed by
|
|
13
|
+
* the watch's top price (eBay's own `price` and `priceCurrency` filters). eBay matches the words
|
|
14
|
+
* itself; a listing is still kept only when every word is in its title (`matchesWords`), as for
|
|
15
|
+
* Shopify, so a description-only match is not DMed. An auction's price is its current bid, or its
|
|
16
|
+
* Buy It Now price when it has one. The
|
|
17
|
+
* seller line carries what eBay's answer shows: the seller's name, feedback percentage and score.
|
|
18
|
+
*
|
|
19
|
+
* The answer is untrusted text: every field is capped and cleaned, and an address is kept only as
|
|
20
|
+
* an eBay item's own `https://<eBay host>/itm/<number>`.
|
|
21
|
+
*/
|
|
22
|
+
export declare const EBAY_SEARCH_PATH = "/buy/browse/v1/item_summary/search";
|
|
23
|
+
export declare const EBAY_MARKETPLACE = "EBAY_US";
|
|
24
|
+
export declare const EBAY_CURRENCY = "USD";
|
|
25
|
+
export declare const EBAY_LIMIT = 50;
|
|
26
|
+
export declare const EBAY_ATTRIBUTION = "via eBay";
|
|
27
|
+
/** One Browse API search: the path, its query parameters, and the marketplace to send as `X-EBAY-C-MARKETPLACE-ID`. */
|
|
28
|
+
export interface EbayRequest {
|
|
29
|
+
path: typeof EBAY_SEARCH_PATH;
|
|
30
|
+
params: Record<string, string>;
|
|
31
|
+
marketplace: typeof EBAY_MARKETPLACE;
|
|
32
|
+
}
|
|
33
|
+
/** The host's run of one request on api.ebay.com with its application token: the HTTP status and the parsed JSON body (null when it was not JSON). */
|
|
34
|
+
export type EbayBrowse = (request: EbayRequest) => Promise<{
|
|
35
|
+
status: number;
|
|
36
|
+
body: unknown;
|
|
37
|
+
}>;
|
|
38
|
+
export interface EbaySearch {
|
|
39
|
+
query: string;
|
|
40
|
+
maxPrice?: number;
|
|
41
|
+
currency?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The request for a search: the words as sent (cut at a word, like Shopify's), newest first, at
|
|
45
|
+
* most `EBAY_LIMIT`, and at or under the top price. eBay US prices in USD, so the price filter is
|
|
46
|
+
* sent only for a watch in USD (or naming no currency); a watch in another currency gets no filter,
|
|
47
|
+
* and the type's own limits drop what is not in its currency. The filter is in whole units with
|
|
48
|
+
* decimals. Pure.
|
|
49
|
+
*/
|
|
50
|
+
export declare function ebayRequest(s: EbaySearch): EbayRequest;
|
|
51
|
+
/**
|
|
52
|
+
* The listings in one search answer: each item summary whose title holds every word of `query`,
|
|
53
|
+
* with an eBay item address, priced (an auction at its current bid), with its condition, "auction"
|
|
54
|
+
* when it is one, and its seller. At most `MAX_LISTINGS`. An answer with no `itemSummaries` is a
|
|
55
|
+
* search with no results (eBay leaves the field out then); one that is not a search answer at all
|
|
56
|
+
* throws `SourceMiss`. Pure.
|
|
57
|
+
*/
|
|
58
|
+
export declare function parseEbayAnswer(body: unknown, query: string): Listing[];
|
|
59
|
+
/** The `ebay` source over the host's `browse`: `target` is the words to search for, `limits` the watch's top price and currency. */
|
|
60
|
+
export declare function ebaySource(browse: EbayBrowse): Source;
|
|
61
|
+
//# sourceMappingURL=want-ebay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"want-ebay.d.ts","sourceRoot":"","sources":["../src/want-ebay.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,OAAO,EAEZ,KAAK,MAAM,EAGZ,MAAM,mBAAmB,CAAA;AAE1B;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,eAAO,MAAM,gBAAgB,uCAAuC,CAAA;AACpE,eAAO,MAAM,gBAAgB,YAAY,CAAA;AACzC,eAAO,MAAM,aAAa,QAAQ,CAAA;AAClC,eAAO,MAAM,UAAU,KAAK,CAAA;AAC5B,eAAO,MAAM,gBAAgB,aAAa,CAAA;AAK1C,uHAAuH;AACvH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,OAAO,gBAAgB,CAAA;IAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9B,WAAW,EAAE,OAAO,gBAAgB,CAAA;CACrC;AAED,sJAAsJ;AACtJ,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC,CAAA;AAE7F,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,UAAU,GAAG,WAAW,CAkBtD;AAyCD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,EAAE,CAsCvE;AAED,oIAAoI;AACpI,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAuBrD"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { clean } from "@rackbops/docket-core";
|
|
2
|
+
import { safeUrl } from "./research-answer.js";
|
|
3
|
+
import { matchesWords, minorUnits, searchWords, shopifyQuery } from "./want-shopify.js";
|
|
4
|
+
import { isEbayHost, MAX_LISTINGS, SourceMiss, SourceUnavailableError, } from "./want-sources.js";
|
|
5
|
+
/**
|
|
6
|
+
* The eBay source (Rod, 2026-10-20, "Build it" on the eBay Browse API card): listings from eBay's
|
|
7
|
+
* own Browse API, `GET /buy/browse/v1/item_summary/search` (developer.ebay.com, read 2026-10-20),
|
|
8
|
+
* with an application token from the owner's eBay developer keyset. Using eBay's API under its API
|
|
9
|
+
* License Agreement is eBay's own permission, where reading its pages is barred (User Agreement
|
|
10
|
+
* s.3); the tracker still never opens an eBay page, and a judged eBay watch opens none either.
|
|
11
|
+
*
|
|
12
|
+
* A host registers the source only with eBay keys, and runs the request itself (`EbayBrowse`,
|
|
13
|
+
* which adds api.ebay.com, the token and the marketplace header): this library opens nothing.
|
|
14
|
+
*
|
|
15
|
+
* One search a look, the newest `EBAY_LIMIT` listings, fixed-price and auction alike, narrowed by
|
|
16
|
+
* the watch's top price (eBay's own `price` and `priceCurrency` filters). eBay matches the words
|
|
17
|
+
* itself; a listing is still kept only when every word is in its title (`matchesWords`), as for
|
|
18
|
+
* Shopify, so a description-only match is not DMed. An auction's price is its current bid, or its
|
|
19
|
+
* Buy It Now price when it has one. The
|
|
20
|
+
* seller line carries what eBay's answer shows: the seller's name, feedback percentage and score.
|
|
21
|
+
*
|
|
22
|
+
* The answer is untrusted text: every field is capped and cleaned, and an address is kept only as
|
|
23
|
+
* an eBay item's own `https://<eBay host>/itm/<number>`.
|
|
24
|
+
*/
|
|
25
|
+
export const EBAY_SEARCH_PATH = "/buy/browse/v1/item_summary/search";
|
|
26
|
+
export const EBAY_MARKETPLACE = "EBAY_US";
|
|
27
|
+
export const EBAY_CURRENCY = "USD";
|
|
28
|
+
export const EBAY_LIMIT = 50;
|
|
29
|
+
export const EBAY_ATTRIBUTION = "via eBay";
|
|
30
|
+
const TITLE_CHARS = 150;
|
|
31
|
+
const CONDITION_CHARS = 40;
|
|
32
|
+
const SELLER_CHARS = 80;
|
|
33
|
+
/**
|
|
34
|
+
* The request for a search: the words as sent (cut at a word, like Shopify's), newest first, at
|
|
35
|
+
* most `EBAY_LIMIT`, and at or under the top price. eBay US prices in USD, so the price filter is
|
|
36
|
+
* sent only for a watch in USD (or naming no currency); a watch in another currency gets no filter,
|
|
37
|
+
* and the type's own limits drop what is not in its currency. The filter is in whole units with
|
|
38
|
+
* decimals. Pure.
|
|
39
|
+
*/
|
|
40
|
+
export function ebayRequest(s) {
|
|
41
|
+
const asked = (s.currency ?? "").trim().toUpperCase();
|
|
42
|
+
const currency = asked === "" ? EBAY_CURRENCY : asked;
|
|
43
|
+
const params = {
|
|
44
|
+
q: shopifyQuery(s.query),
|
|
45
|
+
limit: String(EBAY_LIMIT),
|
|
46
|
+
sort: "newlyListed",
|
|
47
|
+
};
|
|
48
|
+
if (currency === EBAY_CURRENCY &&
|
|
49
|
+
s.maxPrice !== undefined &&
|
|
50
|
+
Number.isFinite(s.maxPrice) &&
|
|
51
|
+
s.maxPrice >= 0) {
|
|
52
|
+
const digits = Math.round(Math.log10(minorUnits(currency)));
|
|
53
|
+
params.filter = `price:[..${s.maxPrice.toFixed(digits)}],priceCurrency:${currency}`;
|
|
54
|
+
}
|
|
55
|
+
return { path: EBAY_SEARCH_PATH, params, marketplace: EBAY_MARKETPLACE };
|
|
56
|
+
}
|
|
57
|
+
const isObj = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
58
|
+
/** eBay's `{ value, currency }`, value a decimal string: as a number and a code; null without both. */
|
|
59
|
+
function amountOf(v) {
|
|
60
|
+
if (!isObj(v))
|
|
61
|
+
return null;
|
|
62
|
+
const raw = typeof v.value === "string" || typeof v.value === "number" ? String(v.value) : "";
|
|
63
|
+
const currency = typeof v.currency === "string" ? v.currency.trim().toUpperCase() : "";
|
|
64
|
+
if (!/^[0-9]{1,12}(\.[0-9]{1,4})?$/.test(raw.trim()) || !/^[A-Z]{3}$/.test(currency))
|
|
65
|
+
return null;
|
|
66
|
+
return { value: Number(raw), currency };
|
|
67
|
+
}
|
|
68
|
+
/** An eBay item's own address, `https://<eBay host>/itm/<number>`, or null for anything else. */
|
|
69
|
+
function itemUrl(raw) {
|
|
70
|
+
if (typeof raw !== "string")
|
|
71
|
+
return null;
|
|
72
|
+
let u;
|
|
73
|
+
try {
|
|
74
|
+
u = new URL(raw.trim());
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
if (u.protocol !== "https:" || !isEbayHost(u.hostname))
|
|
80
|
+
return null;
|
|
81
|
+
const item = /^\/itm\/(?:[^/]+\/)?([0-9]{6,20})\/?$/.exec(u.pathname);
|
|
82
|
+
return item ? safeUrl(`https://${u.hostname.toLowerCase()}/itm/${item[1]}`) : null;
|
|
83
|
+
}
|
|
84
|
+
/** "name, 99.8% positive, 1234 feedback": what eBay shows of the seller, or "" with no name. */
|
|
85
|
+
function sellerOf(v) {
|
|
86
|
+
if (!isObj(v) || typeof v.username !== "string")
|
|
87
|
+
return "";
|
|
88
|
+
const name = clean(v.username, 40, true);
|
|
89
|
+
if (!name)
|
|
90
|
+
return "";
|
|
91
|
+
const parts = [name];
|
|
92
|
+
const pct = typeof v.feedbackPercentage === "string" ? v.feedbackPercentage.trim() : "";
|
|
93
|
+
if (/^[0-9]{1,3}(\.[0-9]{1,2})?$/.test(pct))
|
|
94
|
+
parts.push(`${pct}% positive`);
|
|
95
|
+
if (typeof v.feedbackScore === "number" && Number.isInteger(v.feedbackScore))
|
|
96
|
+
parts.push(`${v.feedbackScore} feedback`);
|
|
97
|
+
return clean(parts.join(", "), SELLER_CHARS, true);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* The listings in one search answer: each item summary whose title holds every word of `query`,
|
|
101
|
+
* with an eBay item address, priced (an auction at its current bid), with its condition, "auction"
|
|
102
|
+
* when it is one, and its seller. At most `MAX_LISTINGS`. An answer with no `itemSummaries` is a
|
|
103
|
+
* search with no results (eBay leaves the field out then); one that is not a search answer at all
|
|
104
|
+
* throws `SourceMiss`. Pure.
|
|
105
|
+
*/
|
|
106
|
+
export function parseEbayAnswer(body, query) {
|
|
107
|
+
if (!isObj(body) || (body.itemSummaries === undefined && typeof body.total !== "number"))
|
|
108
|
+
throw new SourceMiss("eBay's answer was not a search result");
|
|
109
|
+
const items = Array.isArray(body.itemSummaries) ? body.itemSummaries : [];
|
|
110
|
+
const words = searchWords(query);
|
|
111
|
+
const out = [];
|
|
112
|
+
const seen = new Set();
|
|
113
|
+
for (const item of items.slice(0, EBAY_LIMIT * 4)) {
|
|
114
|
+
if (out.length >= MAX_LISTINGS)
|
|
115
|
+
break;
|
|
116
|
+
if (!isObj(item) || typeof item.title !== "string" || typeof item.itemId !== "string")
|
|
117
|
+
continue;
|
|
118
|
+
if (!matchesWords(item.title.slice(0, 2_000), words))
|
|
119
|
+
continue;
|
|
120
|
+
const title = clean(item.title, TITLE_CHARS, true);
|
|
121
|
+
const url = itemUrl(item.itemWebUrl);
|
|
122
|
+
if (!title || !url || item.itemId.length > 120)
|
|
123
|
+
continue;
|
|
124
|
+
// Keyed by the listing's `/itm/<number>`, which its variations share: one listing is told once,
|
|
125
|
+
// whichever variation eBay puts first on a later look.
|
|
126
|
+
const number = /\/itm\/([0-9]+)$/.exec(url)?.[1];
|
|
127
|
+
if (!number || seen.has(number))
|
|
128
|
+
continue;
|
|
129
|
+
seen.add(number);
|
|
130
|
+
const options = Array.isArray(item.buyingOptions) ? item.buyingOptions : [];
|
|
131
|
+
const auction = options.includes("AUCTION");
|
|
132
|
+
const buyNow = options.includes("FIXED_PRICE");
|
|
133
|
+
// A plain auction at its current bid; one with Buy It Now at that price, which buys it outright.
|
|
134
|
+
const price = amountOf(auction && !buyNow ? (item.currentBidPrice ?? item.price) : item.price);
|
|
135
|
+
const state = typeof item.condition === "string" ? clean(item.condition, 30, true) : "";
|
|
136
|
+
const kind = auction ? [buyNow ? "auction, Buy It Now" : "auction"] : [];
|
|
137
|
+
const condition = clean([state, ...kind].filter(Boolean).join(", "), CONDITION_CHARS, true);
|
|
138
|
+
const seller = sellerOf(item.seller);
|
|
139
|
+
out.push({
|
|
140
|
+
id: `ebay:${number}`,
|
|
141
|
+
title,
|
|
142
|
+
url,
|
|
143
|
+
...(price ? { price: price.value, currency: price.currency } : {}),
|
|
144
|
+
...(condition ? { condition } : {}),
|
|
145
|
+
...(seller ? { seller } : {}),
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
return out;
|
|
149
|
+
}
|
|
150
|
+
/** The `ebay` source over the host's `browse`: `target` is the words to search for, `limits` the watch's top price and currency. */
|
|
151
|
+
export function ebaySource(browse) {
|
|
152
|
+
return {
|
|
153
|
+
id: "ebay",
|
|
154
|
+
async search(target, _fetch, limits) {
|
|
155
|
+
if (searchWords(target).length === 0)
|
|
156
|
+
throw new SourceMiss("there are no words to search for");
|
|
157
|
+
let status;
|
|
158
|
+
let body;
|
|
159
|
+
try {
|
|
160
|
+
;
|
|
161
|
+
({ status, body } = await browse(ebayRequest({ query: target, ...limits })));
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
throw new SourceMiss(`eBay could not be searched: ${clean(err instanceof Error ? err.message : String(err), 200, true)}`, { cause: err });
|
|
165
|
+
}
|
|
166
|
+
// Keys eBay refuses, or an app without Browse access: no later look succeeds until someone acts.
|
|
167
|
+
if (status === 401 || status === 403)
|
|
168
|
+
throw new SourceUnavailableError("eBay refused the app's keys");
|
|
169
|
+
if (status === 429 || status >= 500)
|
|
170
|
+
throw new SourceMiss(`eBay is busy (HTTP ${status})`);
|
|
171
|
+
if (status !== 200)
|
|
172
|
+
throw new SourceMiss(`eBay answered HTTP ${status}`);
|
|
173
|
+
return parseEbayAnswer(body, target);
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=want-ebay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"want-ebay.js","sourceRoot":"","sources":["../src/want-ebay.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { type Listing, type SearchLimits, type Source } from "./want-sources.js";
|
|
2
|
+
/**
|
|
3
|
+
* The Shopify source (Rod, 2026-10-19: "add Shopify to watches, daily"): new copies in stock at
|
|
4
|
+
* Shopify stores, from Shopify's catalog search as Firecrawl's Alexandria runs it -- provider
|
|
5
|
+
* `shopify`, capability `catalog/search_catalog`, 5 Firecrawl credits a search (its contract, read
|
|
6
|
+
* 2026-10-19). A host registers the source only with a Firecrawl key, and runs the request itself
|
|
7
|
+
* (`ShopifyScrape`): this library opens nothing.
|
|
8
|
+
*
|
|
9
|
+
* One search a look, one page of at most `SHOPIFY_LIMIT` products, in stock only and under the top
|
|
10
|
+
* price when one is set (Shopify's own `filters`, in minor units). Shopify's search is loose -- it
|
|
11
|
+
* returns related products too -- so a product is kept only when every word of the watch's search
|
|
12
|
+
* is in its title (`matchesWords`). Only a variant that is available, and new or unmarked, is a
|
|
13
|
+
* listing (a variant whose condition is unmarked is taken as new): the catalog sells new copies. The
|
|
14
|
+
* country filter is Shopify's, and leaky (stores abroad still appear, priced in the asked currency).
|
|
15
|
+
*
|
|
16
|
+
* The answer is untrusted shop text: every field is capped and cleaned, an address is kept only as
|
|
17
|
+
* an absolute http(s) one with no fragment and no query parameter but `variant`, and the walk is bounded.
|
|
18
|
+
*/
|
|
19
|
+
export declare const SHOPIFY_PROVIDER = "shopify";
|
|
20
|
+
export declare const SHOPIFY_CAPABILITY = "catalog/search_catalog";
|
|
21
|
+
/** Firecrawl's listed price for one search (its contract, 2026-10-19). */
|
|
22
|
+
export declare const SHOPIFY_CREDITS = 5;
|
|
23
|
+
export declare const SHOPIFY_LIMIT = 50;
|
|
24
|
+
export declare const SHOPIFY_COUNTRY = "US";
|
|
25
|
+
export declare const SHOPIFY_CURRENCY = "USD";
|
|
26
|
+
export declare const SHOPIFY_ATTRIBUTION = "via Shopify";
|
|
27
|
+
/** The Alexandria call for one look: `{ provider, capability, options }`, sent as the `alexandria` field of Firecrawl's `POST /v2/scrape`. */
|
|
28
|
+
export interface ShopifyRequest {
|
|
29
|
+
provider: typeof SHOPIFY_PROVIDER;
|
|
30
|
+
capability: typeof SHOPIFY_CAPABILITY;
|
|
31
|
+
options: {
|
|
32
|
+
query: string;
|
|
33
|
+
country: string;
|
|
34
|
+
currency: string;
|
|
35
|
+
limit: number;
|
|
36
|
+
filters: {
|
|
37
|
+
available: true;
|
|
38
|
+
price?: {
|
|
39
|
+
max: number;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/** The host's run of one request: Firecrawl's HTTP status and its parsed JSON body (null when it was not JSON). */
|
|
45
|
+
export type ShopifyScrape = (request: ShopifyRequest) => Promise<{
|
|
46
|
+
status: number;
|
|
47
|
+
body: unknown;
|
|
48
|
+
}>;
|
|
49
|
+
export interface ShopifySearch extends SearchLimits {
|
|
50
|
+
query: string;
|
|
51
|
+
}
|
|
52
|
+
/** The request for a search: in stock, at or under the top price (minor units, rounded down), in USD unless the watch names a valid three-letter code. Pure. */
|
|
53
|
+
export declare function shopifyRequest(s: ShopifySearch): ShopifyRequest;
|
|
54
|
+
export declare function shopifyQuery(query: string): string;
|
|
55
|
+
/** The words a title must hold: those of the query as sent, in any order. */
|
|
56
|
+
export declare function searchWords(query: string): string[];
|
|
57
|
+
/** Whether `title` holds every one of `words` as a whole word. Pure. */
|
|
58
|
+
export declare function matchesWords(title: string, words: readonly string[]): boolean;
|
|
59
|
+
/** How many minor units make one of `currency` (100 for USD, 1 for JPY, 1000 for KWD). */
|
|
60
|
+
export declare function minorUnits(currency: string): number;
|
|
61
|
+
/**
|
|
62
|
+
* The listings in one search answer (Firecrawl's body): each product whose title holds every word
|
|
63
|
+
* of `query`, and in it each variant that is available, new or unmarked, with an address -- titled
|
|
64
|
+
* by the product (and the variant, when it names one of its own), priced, and sold by its store. At
|
|
65
|
+
* most `MAX_LISTINGS`. Throws `SourceMiss` when the answer is not a search result. Pure.
|
|
66
|
+
*/
|
|
67
|
+
export declare function parseShopifyAnswer(body: unknown, query: string): Listing[];
|
|
68
|
+
/** The `shopify` source over the host's `scrape`: `target` is the words to search for, `limits` the watch's top price and currency. */
|
|
69
|
+
export declare function shopifySource(scrape: ShopifyScrape): Source;
|
|
70
|
+
//# sourceMappingURL=want-shopify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"want-shopify.d.ts","sourceRoot":"","sources":["../src/want-shopify.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,OAAO,EAEZ,KAAK,YAAY,EACjB,KAAK,MAAM,EAGZ,MAAM,mBAAmB,CAAA;AAE1B;;;;;;;;;;;;;;;;GAgBG;AAEH,eAAO,MAAM,gBAAgB,YAAY,CAAA;AACzC,eAAO,MAAM,kBAAkB,2BAA2B,CAAA;AAC1D,0EAA0E;AAC1E,eAAO,MAAM,eAAe,IAAI,CAAA;AAChC,eAAO,MAAM,aAAa,KAAK,CAAA;AAC/B,eAAO,MAAM,eAAe,OAAO,CAAA;AACnC,eAAO,MAAM,gBAAgB,QAAQ,CAAA;AACrC,eAAO,MAAM,mBAAmB,gBAAgB,CAAA;AAKhD,8IAA8I;AAC9I,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,OAAO,gBAAgB,CAAA;IACjC,UAAU,EAAE,OAAO,kBAAkB,CAAA;IACrC,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAA;QACb,OAAO,EAAE,MAAM,CAAA;QACf,QAAQ,EAAE,MAAM,CAAA;QAChB,KAAK,EAAE,MAAM,CAAA;QACb,OAAO,EAAE;YAAE,SAAS,EAAE,IAAI,CAAC;YAAC,KAAK,CAAC,EAAE;gBAAE,GAAG,EAAE,MAAM,CAAA;aAAE,CAAA;SAAE,CAAA;KACtD,CAAA;CACF;AAED,mHAAmH;AACnH,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC,CAAA;AAEnG,MAAM,WAAW,aAAc,SAAQ,YAAY;IACjD,KAAK,EAAE,MAAM,CAAA;CACd;AAED,gKAAgK;AAChK,wBAAgB,cAAc,CAAC,CAAC,EAAE,aAAa,GAAG,cAAc,CAiB/D;AAOD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMlD;AAaD,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAEnD;AAED,wEAAwE;AACxE,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAG7E;AAuBD,0FAA0F;AAC1F,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGnD;AAoBD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,EAAE,CAqD1E;AAED,uIAAuI;AACvI,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CA0B3D"}
|