@rankwrangler/http-client 0.10.0 → 0.12.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 CHANGED
@@ -2,6 +2,9 @@
2
2
 
3
3
  Typed tRPC client for the RankWrangler public agent API.
4
4
 
5
+ Unified search and `keyword.results` below describe prepared source changes. Database migration,
6
+ package release, and production deployment are pending.
7
+
5
8
  ```bash
6
9
  npm install @rankwrangler/http-client
7
10
  ```
@@ -19,7 +22,11 @@ const product = await client.product.get.mutate({
19
22
  asin: 'B0DV53VS61',
20
23
  });
21
24
 
22
- const search = await client.product.search.mutate({
25
+ const search = await client.product.search.query({
26
+ term: 'retro gardening shirt',
27
+ });
28
+
29
+ const observedResults = await client.keyword.results.mutate({
23
30
  term: 'retro gardening shirt',
24
31
  });
25
32
 
@@ -35,12 +42,13 @@ const keywords = await client.keyword.search.query({
35
42
  });
36
43
  ```
37
44
 
38
- The client is scoped to the public surface (`api.public.*`). It exposes Product
39
- `get/search/history` and keyword `get/search/history`; it does not expose Catalog, Operation,
40
- polling procedures. Product `get` and `history`, plus keyword reads, expose no refresh controls;
41
- Product search retains its separate search contract. Product `get` returns the provider-neutral
42
- current Product shape; Product `history` returns compact rank/price series. `NOT_FOUND` and retryable
43
- `TIMEOUT` errors are preserved from tRPC, with retry hints on temporary unavailability.
45
+ The client is scoped to `api.public.*`. Product `search` reads the stored catalog and returns
46
+ `{ items, nextCursor, coverage }` without provider calls. Its optional term, filters, and sorting
47
+ screen compact Products with market metrics. `keyword.results` preserves dated external search
48
+ evidence and can wait for collection under the existing 24-hour reuse policy.
49
+
50
+ Product `get` returns the current Product. `getMany` returns basic listing data, and `history`
51
+ returns compact rank and price series. Keyword `get` and `search` read the stored keyword directory, separately from observed search results. Retryable `TIMEOUT` errors preserve retry hints.
44
52
 
45
53
  ## Types
46
54
 
@@ -49,7 +57,7 @@ import type { PublicRouterInputs, PublicRouterOutputs } from '@rankwrangler/http
49
57
 
50
58
  type ProductGetInput = PublicRouterInputs['product']['get'];
51
59
  type ProductSearchOutput = PublicRouterOutputs['product']['search'];
52
- type KeywordHistoryOutput = PublicRouterOutputs['keyword']['history'];
60
+ type KeywordSearchOutput = PublicRouterOutputs['keyword']['search'];
53
61
  ```
54
62
 
55
63
  When the public router changes, regenerate and build the declarations:
@@ -198,82 +198,6 @@ export interface ContextRequest {
198
198
  host?: string;
199
199
  };
200
200
  }
201
- declare const TOP_SEARCH_TERMS_REPORT_PERIODS: readonly [
202
- "DAY",
203
- "WEEK"
204
- ];
205
- declare const TOP_SEARCH_TERMS_REFRESH_TRIGGERS: readonly [
206
- "requested",
207
- "automatic"
208
- ];
209
- export type TopSearchTermsReportPeriod = (typeof TOP_SEARCH_TERMS_REPORT_PERIODS)[number];
210
- export type TopSearchTermsRefreshTrigger = (typeof TOP_SEARCH_TERMS_REFRESH_TRIGGERS)[number];
211
- export type SearchTermsTrendDelta = {
212
- rankDelta: number | null;
213
- clickShareDelta: number | null;
214
- conversionShareDelta: number | null;
215
- };
216
- export type SearchTermsTrendDeltas = {
217
- d1: SearchTermsTrendDelta;
218
- d7: SearchTermsTrendDelta;
219
- d30: SearchTermsTrendDelta;
220
- };
221
- export interface KeywordEvidence {
222
- searchFrequencyRank: number;
223
- clickShareTop3: number;
224
- conversionShareTop3: number;
225
- topRowsCount: number;
226
- isMerchRelevant: boolean;
227
- merchReason: string;
228
- }
229
- export interface KeywordCurrent {
230
- keyword: string;
231
- marketplaceId: string;
232
- reportPeriod: TopSearchTermsReportPeriod;
233
- dataStartDate: string;
234
- dataEndDate: string;
235
- observedDate: string;
236
- fetchedAt: string;
237
- trigger: TopSearchTermsRefreshTrigger;
238
- evidence: KeywordEvidence;
239
- }
240
- export interface KeywordSearchItem extends KeywordEvidence {
241
- keyword: string;
242
- observedDate: string;
243
- trigger: TopSearchTermsRefreshTrigger;
244
- }
245
- export interface KeywordSearchSummary {
246
- marketplaceId: string;
247
- reportPeriod: TopSearchTermsReportPeriod;
248
- dataStartDate: string | null;
249
- dataEndDate: string | null;
250
- observedDate: string | null;
251
- fetchedAt: string | null;
252
- totalFiltered: number;
253
- }
254
- export interface KeywordSearchResponse {
255
- status: "ready" | "empty";
256
- items: KeywordSearchItem[];
257
- nextCursor: number | null;
258
- summary: KeywordSearchSummary;
259
- }
260
- export interface KeywordHistoryPoint {
261
- observedDate: string;
262
- searchFrequencyRank: number;
263
- clickShareTop3: number;
264
- conversionShareTop3: number;
265
- trigger: TopSearchTermsRefreshTrigger;
266
- }
267
- export interface KeywordHistoryResponse {
268
- keyword: string;
269
- marketplaceId: string;
270
- reportPeriod: TopSearchTermsReportPeriod;
271
- rangeDays: number;
272
- status: "ready" | "empty";
273
- latestObservedDate: string | null;
274
- points: KeywordHistoryPoint[];
275
- deltas: SearchTermsTrendDeltas;
276
- }
277
201
  export type PublicCutoutThumbnail = {
278
202
  status: "available";
279
203
  url: string;
@@ -324,7 +248,7 @@ export interface Product {
324
248
  };
325
249
  };
326
250
  }
327
- export interface ProductSearchProduct {
251
+ export interface KeywordResultsProduct {
328
252
  marketplaceId: string;
329
253
  asin: string;
330
254
  title: string | null;
@@ -348,12 +272,12 @@ export interface ProductSearchProduct {
348
272
  } | null;
349
273
  boughtInPastMonth: number | null;
350
274
  }
351
- export interface ProductSearch {
275
+ export interface KeywordResults {
352
276
  keyword: string;
353
277
  searchedAt: string;
354
278
  results: Array<{
355
279
  organicSearchPlacement: number;
356
- product: ProductSearchProduct;
280
+ product: KeywordResultsProduct;
357
281
  }>;
358
282
  }
359
283
  export interface BasicProduct {
@@ -505,42 +429,92 @@ export declare const publicAppRouter: import("@trpc/server").TRPCBuiltRouter<{
505
429
  get: import("@trpc/server").TRPCQueryProcedure<{
506
430
  input: {
507
431
  keyword: string;
508
- dataEndDate?: string | undefined;
509
- dataStartDate?: string | undefined;
510
- marketplaceId?: "ATVPDKIKX0DER" | undefined;
511
- reportPeriod?: "DAY" | "WEEK" | undefined;
512
432
  };
513
433
  output: {
514
434
  keyword: string;
515
- status: "ready" | "empty";
516
- current: KeywordCurrent | null;
435
+ data: {
436
+ createdAt: string;
437
+ lastCheckedAt: string | null;
438
+ nextCheckAt: string | null;
439
+ id: string;
440
+ queryId: string | null;
441
+ term: string;
442
+ status: "queued" | "scanning" | "upToDate" | "untracked";
443
+ untrackedReason: "notRelevant" | "noMerchFound" | "notScheduled" | null;
444
+ retryScheduled: boolean;
445
+ heat: string;
446
+ score: number | null;
447
+ sources: string[];
448
+ products: number;
449
+ merch: number;
450
+ intervalDays: number | null;
451
+ };
517
452
  };
518
453
  meta: object;
519
454
  }>;
520
- history: import("@trpc/server").TRPCQueryProcedure<{
455
+ results: import("@trpc/server").TRPCMutationProcedure<{
521
456
  input: {
522
- keyword: string;
523
- marketplaceId?: "ATVPDKIKX0DER" | undefined;
524
- rangeDays?: number | undefined;
525
- reportPeriod?: "DAY" | "WEEK" | undefined;
457
+ term: string;
458
+ refresh?: boolean | undefined;
526
459
  };
527
- output: KeywordHistoryResponse;
460
+ output: KeywordResults;
528
461
  meta: object;
529
462
  }>;
530
463
  search: import("@trpc/server").TRPCQueryProcedure<{
531
464
  input: {
532
465
  text: string;
533
- cursor?: number | undefined;
466
+ state?: "all" | "queued" | "scanning" | "upToDate" | "untracked" | undefined;
467
+ sort?: "work" | "newest" | undefined;
534
468
  limit?: number | undefined;
535
- maxRank?: number | undefined;
536
- merchOnly?: boolean | undefined;
537
- minRank?: number | undefined;
538
- dataEndDate?: string | undefined;
539
- dataStartDate?: string | undefined;
540
- marketplaceId?: "ATVPDKIKX0DER" | undefined;
541
- reportPeriod?: "DAY" | "WEEK" | undefined;
469
+ heat?: "unrated" | "hot" | "warm" | "cold" | "all" | undefined;
470
+ cursor?: {
471
+ key: [
472
+ number,
473
+ number,
474
+ number,
475
+ number,
476
+ number,
477
+ number,
478
+ string
479
+ ];
480
+ asOf: string;
481
+ trialTurn: boolean;
482
+ sort: "work" | "newest";
483
+ } | undefined;
484
+ };
485
+ output: {
486
+ items: {
487
+ createdAt: string;
488
+ lastCheckedAt: string | null;
489
+ nextCheckAt: string | null;
490
+ id: string;
491
+ queryId: string | null;
492
+ term: string;
493
+ status: "queued" | "scanning" | "upToDate" | "untracked";
494
+ untrackedReason: "notRelevant" | "noMerchFound" | "notScheduled" | null;
495
+ retryScheduled: boolean;
496
+ heat: string;
497
+ score: number | null;
498
+ sources: string[];
499
+ products: number;
500
+ merch: number;
501
+ intervalDays: number | null;
502
+ }[];
503
+ nextCursor: {
504
+ key: [
505
+ number,
506
+ number,
507
+ number,
508
+ number,
509
+ number,
510
+ number,
511
+ string
512
+ ];
513
+ asOf: string;
514
+ trialTurn: boolean;
515
+ sort: "work" | "newest";
516
+ } | null;
542
517
  };
543
- output: KeywordSearchResponse;
544
518
  meta: object;
545
519
  }>;
546
520
  }>>;
@@ -601,12 +575,106 @@ export declare const publicAppRouter: import("@trpc/server").TRPCBuiltRouter<{
601
575
  output: PublicProductHistory;
602
576
  meta: object;
603
577
  }>;
604
- search: import("@trpc/server").TRPCMutationProcedure<{
578
+ search: import("@trpc/server").TRPCQueryProcedure<{
605
579
  input: {
606
- term: string;
607
- refresh?: boolean | undefined;
580
+ term?: string | undefined;
581
+ textFields?: "title" | "all" | undefined;
582
+ excludeWords?: string[] | undefined;
583
+ marketplaceIds?: string[] | undefined;
584
+ isMerchListing?: boolean | "unknown" | "all" | undefined;
585
+ amazonListingStatus?: "active" | "deleted" | "all" | undefined;
586
+ brands?: string[] | undefined;
587
+ excludeBrands?: string[] | undefined;
588
+ includeOfficialBrands?: boolean | undefined;
589
+ categoryIds?: number[] | undefined;
590
+ salesRank?: {
591
+ min?: number | undefined;
592
+ max?: number | undefined;
593
+ } | undefined;
594
+ price?: {
595
+ min?: number | undefined;
596
+ max?: number | undefined;
597
+ } | undefined;
598
+ monthlySold?: {
599
+ min?: number | undefined;
600
+ max?: number | undefined;
601
+ } | undefined;
602
+ firstAvailableAt?: {
603
+ after?: string | undefined;
604
+ before?: string | undefined;
605
+ } | undefined;
606
+ discoveredAt?: {
607
+ after?: string | undefined;
608
+ before?: string | undefined;
609
+ } | undefined;
610
+ updatedAt?: {
611
+ after?: string | undefined;
612
+ before?: string | undefined;
613
+ } | undefined;
614
+ facets?: {
615
+ facet: string;
616
+ name: string;
617
+ }[] | undefined;
618
+ sort?: "relevance" | "salesRankAsc" | "salesRankDesc" | "firstAvailableAtDesc" | "firstAvailableAtAsc" | "updatedAtAsc" | "updatedAtDesc" | "discoveredAtDesc" | "priceAsc" | "priceDesc" | "monthlySoldDesc" | undefined;
619
+ cursor?: string | null | undefined;
620
+ limit?: number | undefined;
621
+ };
622
+ output: {
623
+ coverage: {
624
+ keyword: string;
625
+ headCheckedAt: string | null;
626
+ exploration: {
627
+ source: "spapi";
628
+ pages: number;
629
+ observedAt: string | null;
630
+ budgetLimited: boolean;
631
+ } | null;
632
+ } | null;
633
+ items: {
634
+ marketplaceId: string;
635
+ asin: string;
636
+ title: string | null;
637
+ brand: string | null;
638
+ bullet1: string | null;
639
+ bullet2: string | null;
640
+ thumbnail: {
641
+ status: "available";
642
+ url: string;
643
+ } | {
644
+ status: "unavailable";
645
+ url?: undefined;
646
+ };
647
+ isMerchListing: boolean | null;
648
+ amazonListingStatus: AmazonListingStatus;
649
+ categoryId: number | null;
650
+ salesRank: number | null;
651
+ price: {
652
+ amountMinor: number;
653
+ currencyCode: string;
654
+ } | null;
655
+ firstAvailableAt: string | null;
656
+ discoveredAt: string;
657
+ updatedAt: string;
658
+ averages: {
659
+ last30Days: number | null;
660
+ last90Days: number | null;
661
+ };
662
+ demand: {
663
+ boughtInPastMonth: number | null;
664
+ salesRankDrops: {
665
+ last30Days: number | null;
666
+ last90Days: number | null;
667
+ last180Days: number | null;
668
+ last365Days: number | null;
669
+ };
670
+ };
671
+ facets: {
672
+ facet: string;
673
+ name: string;
674
+ }[];
675
+ }[];
676
+ nextCursor: string | null;
608
677
  };
609
- output: ProductSearch;
610
678
  meta: object;
611
679
  }>;
612
680
  }>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rankwrangler/http-client",
3
- "version": "0.10.0",
3
+ "version": "0.12.0",
4
4
  "description": "Typed tRPC client for RankWrangler",
5
5
  "repository": {
6
6
  "type": "git",