@rankwrangler/http-client 0.6.0 → 0.9.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
@@ -1,77 +1,63 @@
1
1
  # @rankwrangler/http-client
2
2
 
3
- Typed tRPC client for the RankWrangler public API.
4
-
5
- ## Install
3
+ Typed tRPC client for the RankWrangler public agent API.
6
4
 
7
5
  ```bash
8
6
  npm install @rankwrangler/http-client
9
7
  ```
10
8
 
11
- ## Usage
12
-
13
9
  ```ts
14
10
  import { createRankWranglerClient } from '@rankwrangler/http-client';
15
11
 
16
12
  const client = createRankWranglerClient({
17
- baseUrl: 'https://rankwrangler.merchbase.co',
18
- apiKey: 'rrk_...'
13
+ baseUrl: 'https://rankwrangler.merchbase.co',
14
+ apiKey: process.env.MERCHBASE_API_KEY,
15
+ });
16
+
17
+ const product = await client.product.get.mutate({
18
+ marketplaceId: 'ATVPDKIKX0DER',
19
+ asin: 'B0DV53VS61',
20
+ });
21
+
22
+ const search = await client.product.search.mutate({
23
+ term: 'retro gardening shirt',
19
24
  });
20
25
 
21
- const product = await client.getProductInfo.mutate({
22
- marketplaceId: 'ATVPDKIKX0DER',
23
- asin: 'B0DV53VS61'
26
+ const history = await client.product.history.mutate({
27
+ marketplaceId: 'ATVPDKIKX0DER',
28
+ asin: 'B0DV53VS61',
29
+ metrics: ['salesRank', 'price'],
30
+ bucket: 'week',
31
+ });
32
+
33
+ const keywords = await client.keyword.search.query({
34
+ text: 'retro gardening',
24
35
  });
25
36
  ```
26
37
 
27
- The client is scoped to the public surface (`api.public.*`) so it stays aligned with CLI usage.
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.
28
44
 
29
45
  ## Types
30
46
 
31
47
  ```ts
32
48
  import type { PublicRouterInputs, PublicRouterOutputs } from '@rankwrangler/http-client';
33
49
 
34
- type GetProductInput = PublicRouterInputs['getProductInfo'];
35
- type GetProductOutput = PublicRouterOutputs['getProductInfo'];
50
+ type ProductGetInput = PublicRouterInputs['product']['get'];
51
+ type ProductSearchOutput = PublicRouterOutputs['product']['search'];
52
+ type KeywordHistoryOutput = PublicRouterOutputs['keyword']['history'];
36
53
  ```
37
54
 
38
- ## Maintenance
39
-
40
- When the public router changes, regenerate the bundled router types:
55
+ When the public router changes, regenerate and build the declarations:
41
56
 
42
57
  ```bash
43
58
  bun run http-client:types
44
- ```
45
-
46
- Build the package before publishing:
47
-
48
- ```bash
49
59
  bun run http-client:build
50
60
  ```
51
61
 
52
- ## Publish
53
-
54
- From `packages/http-client`:
55
-
56
- ```bash
57
- node ../../scripts/release/with-npm-token.mjs npm whoami --userconfig ../../.npmrc
58
- node ../../scripts/release/with-npm-token.mjs npm publish --access public --userconfig ../../.npmrc
59
- ```
60
-
61
- On macOS, the helper reads `NPM_TOKEN` from the environment first and otherwise falls back to the
62
- Keychain item `rankwrangler-npm-token` for account `$USER`.
63
-
64
- Before publishing:
65
-
66
- 1. Run `bun run release:bump <patch|minor|major|X.Y.Z>` from repo root.
67
- 2. Run `bun install` from repo root.
68
- 3. Run `bun run release:collect-changelog-context`, then draft `CHANGELOG.md` entry.
69
- 4. Run `bun run release:check`.
70
- 5. Run `bun run http-client:build` from repo root.
71
- 6. Run `npm pack --dry-run` from `packages/http-client`.
72
-
73
- ## Versioning
74
-
75
- - App releases and npm package versions are synchronized to the same `X.Y.Z`.
76
- - `CHANGELOG.md` uses `vX.Y.Z`; package files use `X.Y.Z`.
77
- - Canonical process lives in `docs/release-runbook.md`.
62
+ See the [HTTP client reference](../../docs/reference/http-client.md) for transport options and
63
+ release workflow.
@@ -1,111 +1,421 @@
1
1
  // Generated by dts-bundle-generator v9.5.1
2
2
 
3
- export interface LicenseUsageData {
4
- id: string;
5
- email: string;
6
- usage: number;
7
- usageLimit: number;
8
- }
3
+ declare const rankwranglerServiceAccounts: import("drizzle-orm/pg-core").PgTableWithColumns<{
4
+ name: "rankwrangler_service_accounts";
5
+ schema: undefined;
6
+ columns: {
7
+ id: import("drizzle-orm/pg-core").PgColumn<{
8
+ name: "id";
9
+ tableName: "rankwrangler_service_accounts";
10
+ dataType: "string";
11
+ columnType: "PgUUID";
12
+ data: string;
13
+ driverParam: string;
14
+ notNull: true;
15
+ hasDefault: true;
16
+ isPrimaryKey: true;
17
+ isAutoincrement: false;
18
+ hasRuntimeDefault: false;
19
+ enumValues: undefined;
20
+ baseColumn: never;
21
+ identity: undefined;
22
+ generated: undefined;
23
+ }, {}, {}>;
24
+ service: import("drizzle-orm/pg-core").PgColumn<{
25
+ name: "service";
26
+ tableName: "rankwrangler_service_accounts";
27
+ dataType: "string";
28
+ columnType: "PgText";
29
+ data: string;
30
+ driverParam: string;
31
+ notNull: true;
32
+ hasDefault: true;
33
+ isPrimaryKey: false;
34
+ isAutoincrement: false;
35
+ hasRuntimeDefault: false;
36
+ enumValues: [
37
+ string,
38
+ ...string[]
39
+ ];
40
+ baseColumn: never;
41
+ identity: undefined;
42
+ generated: undefined;
43
+ }, {}, {}>;
44
+ merchbaseUserId: import("drizzle-orm/pg-core").PgColumn<{
45
+ name: "merchbase_user_id";
46
+ tableName: "rankwrangler_service_accounts";
47
+ dataType: "string";
48
+ columnType: "PgText";
49
+ data: string;
50
+ driverParam: string;
51
+ notNull: false;
52
+ hasDefault: false;
53
+ isPrimaryKey: false;
54
+ isAutoincrement: false;
55
+ hasRuntimeDefault: false;
56
+ enumValues: [
57
+ string,
58
+ ...string[]
59
+ ];
60
+ baseColumn: never;
61
+ identity: undefined;
62
+ generated: undefined;
63
+ }, {}, {}>;
64
+ createdAt: import("drizzle-orm/pg-core").PgColumn<{
65
+ name: "created_at";
66
+ tableName: "rankwrangler_service_accounts";
67
+ dataType: "date";
68
+ columnType: "PgTimestamp";
69
+ data: Date;
70
+ driverParam: string;
71
+ notNull: true;
72
+ hasDefault: true;
73
+ isPrimaryKey: false;
74
+ isAutoincrement: false;
75
+ hasRuntimeDefault: false;
76
+ enumValues: undefined;
77
+ baseColumn: never;
78
+ identity: undefined;
79
+ generated: undefined;
80
+ }, {}, {}>;
81
+ updatedAt: import("drizzle-orm/pg-core").PgColumn<{
82
+ name: "updated_at";
83
+ tableName: "rankwrangler_service_accounts";
84
+ dataType: "date";
85
+ columnType: "PgTimestamp";
86
+ data: Date;
87
+ driverParam: string;
88
+ notNull: true;
89
+ hasDefault: true;
90
+ isPrimaryKey: false;
91
+ isAutoincrement: false;
92
+ hasRuntimeDefault: false;
93
+ enumValues: undefined;
94
+ baseColumn: never;
95
+ identity: undefined;
96
+ generated: undefined;
97
+ }, {}, {}>;
98
+ lastUsedAt: import("drizzle-orm/pg-core").PgColumn<{
99
+ name: "last_used_at";
100
+ tableName: "rankwrangler_service_accounts";
101
+ dataType: "date";
102
+ columnType: "PgTimestamp";
103
+ data: Date;
104
+ driverParam: string;
105
+ notNull: false;
106
+ hasDefault: false;
107
+ isPrimaryKey: false;
108
+ isAutoincrement: false;
109
+ hasRuntimeDefault: false;
110
+ enumValues: undefined;
111
+ baseColumn: never;
112
+ identity: undefined;
113
+ generated: undefined;
114
+ }, {}, {}>;
115
+ usageToday: import("drizzle-orm/pg-core").PgColumn<{
116
+ name: "usage_today";
117
+ tableName: "rankwrangler_service_accounts";
118
+ dataType: "number";
119
+ columnType: "PgInteger";
120
+ data: number;
121
+ driverParam: string | number;
122
+ notNull: true;
123
+ hasDefault: true;
124
+ isPrimaryKey: false;
125
+ isAutoincrement: false;
126
+ hasRuntimeDefault: false;
127
+ enumValues: undefined;
128
+ baseColumn: never;
129
+ identity: undefined;
130
+ generated: undefined;
131
+ }, {}, {}>;
132
+ usageCount: import("drizzle-orm/pg-core").PgColumn<{
133
+ name: "usage_count";
134
+ tableName: "rankwrangler_service_accounts";
135
+ dataType: "number";
136
+ columnType: "PgInteger";
137
+ data: number;
138
+ driverParam: string | number;
139
+ notNull: true;
140
+ hasDefault: true;
141
+ isPrimaryKey: false;
142
+ isAutoincrement: false;
143
+ hasRuntimeDefault: false;
144
+ enumValues: undefined;
145
+ baseColumn: never;
146
+ identity: undefined;
147
+ generated: undefined;
148
+ }, {}, {}>;
149
+ usageLimit: import("drizzle-orm/pg-core").PgColumn<{
150
+ name: "usage_limit";
151
+ tableName: "rankwrangler_service_accounts";
152
+ dataType: "number";
153
+ columnType: "PgInteger";
154
+ data: number;
155
+ driverParam: string | number;
156
+ notNull: true;
157
+ hasDefault: true;
158
+ isPrimaryKey: false;
159
+ isAutoincrement: false;
160
+ hasRuntimeDefault: false;
161
+ enumValues: undefined;
162
+ baseColumn: never;
163
+ identity: undefined;
164
+ generated: undefined;
165
+ }, {}, {}>;
166
+ lastResetAt: import("drizzle-orm/pg-core").PgColumn<{
167
+ name: "last_reset_at";
168
+ tableName: "rankwrangler_service_accounts";
169
+ dataType: "date";
170
+ columnType: "PgTimestamp";
171
+ data: Date;
172
+ driverParam: string;
173
+ notNull: true;
174
+ hasDefault: true;
175
+ isPrimaryKey: false;
176
+ isAutoincrement: false;
177
+ hasRuntimeDefault: false;
178
+ enumValues: undefined;
179
+ baseColumn: never;
180
+ identity: undefined;
181
+ generated: undefined;
182
+ }, {}, {}>;
183
+ };
184
+ dialect: "pg";
185
+ }>;
186
+ export type RankWranglerServicePrincipal = Omit<typeof rankwranglerServiceAccounts.$inferSelect, "merchbaseUserId"> & {
187
+ merchbaseUserId: string;
188
+ };
9
189
  export interface ClerkUser {
10
190
  sub: string;
11
191
  email?: string;
12
192
  }
13
- declare const productHistoryBuckets: readonly [
14
- "auto",
15
- "day",
16
- "week",
17
- "month"
193
+ export type CredentialKind = "api_key" | "oauth" | "session";
194
+ export interface ContextRequest {
195
+ headers: {
196
+ authorization?: string;
197
+ host?: string;
198
+ };
199
+ }
200
+ declare const TOP_SEARCH_TERMS_REPORT_PERIODS: readonly [
201
+ "DAY",
202
+ "WEEK"
18
203
  ];
19
- export type ProductHistoryBucket = (typeof productHistoryBuckets)[number];
20
- export type ResolvedHistoryBucket = Exclude<ProductHistoryBucket, "auto">;
21
- export type HistoryBucketTuple = [
22
- string,
23
- number | null
204
+ declare const TOP_SEARCH_TERMS_REFRESH_TRIGGERS: readonly [
205
+ "requested",
206
+ "automatic"
24
207
  ];
25
- export type HistoryBucketSummary = {
208
+ export type TopSearchTermsReportPeriod = (typeof TOP_SEARCH_TERMS_REPORT_PERIODS)[number];
209
+ export type TopSearchTermsRefreshTrigger = (typeof TOP_SEARCH_TERMS_REFRESH_TRIGGERS)[number];
210
+ export type SearchTermsTrendDelta = {
211
+ rankDelta: number | null;
212
+ clickShareDelta: number | null;
213
+ conversionShareDelta: number | null;
214
+ };
215
+ export type SearchTermsTrendDeltas = {
216
+ d1: SearchTermsTrendDelta;
217
+ d7: SearchTermsTrendDelta;
218
+ d30: SearchTermsTrendDelta;
219
+ };
220
+ export interface KeywordEvidence {
221
+ searchFrequencyRank: number;
222
+ clickShareTop3: number;
223
+ conversionShareTop3: number;
224
+ topRowsCount: number;
225
+ isMerchRelevant: boolean;
226
+ merchReason: string;
227
+ }
228
+ export interface KeywordCurrent {
229
+ keyword: string;
230
+ marketplaceId: string;
231
+ reportPeriod: TopSearchTermsReportPeriod;
232
+ dataStartDate: string;
233
+ dataEndDate: string;
234
+ observedDate: string;
235
+ fetchedAt: string;
236
+ trigger: TopSearchTermsRefreshTrigger;
237
+ evidence: KeywordEvidence;
238
+ }
239
+ export interface KeywordSearchItem extends KeywordEvidence {
240
+ keyword: string;
241
+ observedDate: string;
242
+ trigger: TopSearchTermsRefreshTrigger;
243
+ }
244
+ export interface KeywordSearchSummary {
245
+ marketplaceId: string;
246
+ reportPeriod: TopSearchTermsReportPeriod;
247
+ dataStartDate: string | null;
248
+ dataEndDate: string | null;
249
+ observedDate: string | null;
250
+ fetchedAt: string | null;
251
+ totalFiltered: number;
252
+ }
253
+ export interface KeywordSearchResponse {
254
+ status: "ready" | "empty";
255
+ items: KeywordSearchItem[];
256
+ nextCursor: number | null;
257
+ summary: KeywordSearchSummary;
258
+ }
259
+ export interface KeywordHistoryPoint {
260
+ observedDate: string;
261
+ searchFrequencyRank: number;
262
+ clickShareTop3: number;
263
+ conversionShareTop3: number;
264
+ trigger: TopSearchTermsRefreshTrigger;
265
+ }
266
+ export interface KeywordHistoryResponse {
267
+ keyword: string;
268
+ marketplaceId: string;
269
+ reportPeriod: TopSearchTermsReportPeriod;
270
+ rangeDays: number;
271
+ status: "ready" | "empty";
272
+ latestObservedDate: string | null;
273
+ points: KeywordHistoryPoint[];
274
+ deltas: SearchTermsTrendDeltas;
275
+ }
276
+ export interface Product {
277
+ marketplaceId: string;
278
+ asin: string;
279
+ listing: {
280
+ title: string | null;
281
+ brand: string | null;
282
+ firstAvailableAt: string | null;
283
+ bulletPoints: string[];
284
+ thumbnail: {
285
+ status: "available";
286
+ url: string;
287
+ } | {
288
+ status: "unavailable";
289
+ };
290
+ isMerchListing: boolean | null;
291
+ isUnavailable: boolean;
292
+ };
293
+ category: {
294
+ id: number;
295
+ name: string | null;
296
+ } | null;
297
+ salesRank: {
298
+ current: number | null;
299
+ averages: {
300
+ last30Days: number | null;
301
+ last90Days: number | null;
302
+ };
303
+ };
304
+ price: {
305
+ amountMinor: number;
306
+ currencyCode: string;
307
+ } | null;
308
+ demand: {
309
+ boughtInPastMonth: number | null;
310
+ salesRankDrops: {
311
+ last30Days: number | null;
312
+ last90Days: number | null;
313
+ last180Days: number | null;
314
+ last365Days: number | null;
315
+ };
316
+ };
317
+ }
318
+ export interface ProductSearchProduct {
319
+ marketplaceId: string;
320
+ asin: string;
321
+ title: string | null;
322
+ brand: string | null;
323
+ thumbnail: {
324
+ status: "available";
325
+ url: string;
326
+ } | {
327
+ status: "unavailable";
328
+ };
329
+ isMerchListing: boolean | null;
330
+ isUnavailable: boolean;
331
+ category: {
332
+ id: number;
333
+ name: string | null;
334
+ } | null;
335
+ salesRank: number | null;
336
+ price: {
337
+ amountMinor: number;
338
+ currencyCode: string;
339
+ } | null;
340
+ boughtInPastMonth: number | null;
341
+ }
342
+ export interface ProductSearch {
343
+ keyword: string;
344
+ searchedAt: string;
345
+ results: Array<{
346
+ organicSearchPlacement: number;
347
+ product: ProductSearchProduct;
348
+ }>;
349
+ }
350
+ export interface BasicProduct {
351
+ marketplaceId: string;
352
+ asin: string;
353
+ title: string | null;
354
+ thumbnail: {
355
+ status: "available";
356
+ url: string;
357
+ } | {
358
+ status: "unavailable";
359
+ };
360
+ isUnavailable: boolean;
361
+ }
362
+ export interface ProductHistorySummary {
26
363
  first: number | null;
27
364
  latest: number | null;
28
365
  min: number | null;
29
366
  max: number | null;
30
- count: number;
31
- firstBucketAt: string | null;
32
- latestBucketAt: string | null;
33
- };
34
- export type AgentHistorySeries = {
35
- bsr?: {
36
- unit: "rank";
37
- category: {
38
- id: number;
39
- name: string | null;
40
- } | null;
41
- buckets: HistoryBucketTuple[];
42
- summary: HistoryBucketSummary;
43
- };
44
- price?: {
45
- unit: "minorCurrency";
46
- currencyCode: "USD";
47
- valueScale: 100;
48
- buckets: HistoryBucketTuple[];
49
- summary: HistoryBucketSummary;
50
- };
51
- };
52
- export type AgentHistoryResponse = {
53
- schemaVersion: 2;
367
+ }
368
+ export interface PublicProductHistory {
54
369
  marketplaceId: string;
55
370
  asin: string;
56
- status: "collecting" | "ready" | "empty";
57
- latestImportAt: string | null;
58
- syncTriggered: boolean;
59
371
  range: {
60
372
  startAt: string;
61
373
  endAt: string;
62
- bucket: ResolvedHistoryBucket;
374
+ interval: "day" | "week" | "month";
63
375
  };
64
- series: AgentHistorySeries;
65
- };
66
- export type ProductInfo = {
67
- asin: string;
68
- marketplaceId: string;
69
- dateFirstAvailable: string | null;
70
- title: string | null;
71
- brand: string | null;
72
- isMerchListing: boolean;
73
- bullet1: string | null;
74
- bullet2: string | null;
75
- rootCategoryId: number | null;
76
- rootCategoryBsr: number | null;
77
- rootCategoryDisplayName: string | null;
78
- thumbnailUrl?: string;
79
- metadata: {
80
- lastFetched: string;
81
- cached: boolean;
376
+ series: {
377
+ salesRank?: {
378
+ unit: "rank";
379
+ category: {
380
+ id: number;
381
+ name: string | null;
382
+ } | null;
383
+ points: [
384
+ periodStart: string,
385
+ valueAtPeriodEnd: number | null
386
+ ][];
387
+ summary: ProductHistorySummary;
388
+ };
389
+ price?: {
390
+ unit: "minorCurrency";
391
+ currencyCode: string;
392
+ points: [
393
+ periodStart: string,
394
+ valueAtPeriodEnd: number | null
395
+ ][];
396
+ summary: ProductHistorySummary;
397
+ };
82
398
  };
83
- };
399
+ }
84
400
  export declare const publicAppRouter: import("@trpc/server").TRPCBuiltRouter<{
85
401
  ctx: {
86
- user: ClerkUser;
87
- isAdmin: boolean;
88
- authType: "license" | "clerk" | "none";
89
- license: {
90
- key: string;
91
- data: LicenseUsageData | undefined;
92
- };
93
- licenseError: undefined;
94
- request: import("fastify").FastifyRequest<import("fastify").RouteGenericInterface, import("fastify").RawServerDefault, import("http").IncomingMessage, import("fastify").FastifySchema, import("fastify").FastifyTypeProviderDefault, unknown, import("fastify").FastifyBaseLogger, import("fastify/types/type-provider.js").ResolveFastifyRequestType<import("fastify").FastifyTypeProviderDefault, import("fastify").FastifySchema, import("fastify").RouteGenericInterface>>;
95
- } | {
96
402
  user: null;
97
403
  isAdmin: boolean;
98
- authType: "license" | "clerk" | "none";
99
- license: null;
100
- licenseError: string | undefined;
101
- request: import("fastify").FastifyRequest<import("fastify").RouteGenericInterface, import("fastify").RawServerDefault, import("http").IncomingMessage, import("fastify").FastifySchema, import("fastify").FastifyTypeProviderDefault, unknown, import("fastify").FastifyBaseLogger, import("fastify/types/type-provider.js").ResolveFastifyRequestType<import("fastify").FastifyTypeProviderDefault, import("fastify").FastifySchema, import("fastify").RouteGenericInterface>>;
404
+ authType: "none";
405
+ credentialKind: null;
406
+ authExpiresAtMs: null;
407
+ accessPrincipal: null;
408
+ accessError: import("@merchbaseco/access").ServiceAccessErrorCode | null;
409
+ request: ContextRequest;
102
410
  } | {
103
411
  user: ClerkUser;
104
412
  isAdmin: boolean;
105
- authType: "license" | "clerk" | "none";
106
- license: null;
107
- licenseError: undefined;
108
- request: import("fastify").FastifyRequest<import("fastify").RouteGenericInterface, import("fastify").RawServerDefault, import("http").IncomingMessage, import("fastify").FastifySchema, import("fastify").FastifyTypeProviderDefault, unknown, import("fastify").FastifyBaseLogger, import("fastify/types/type-provider.js").ResolveFastifyRequestType<import("fastify").FastifyTypeProviderDefault, import("fastify").FastifySchema, import("fastify").RouteGenericInterface>>;
413
+ authType: "access";
414
+ credentialKind: CredentialKind;
415
+ authExpiresAtMs: number | null;
416
+ accessPrincipal: RankWranglerServicePrincipal;
417
+ accessError: null;
418
+ request: ContextRequest;
109
419
  };
110
420
  meta: object;
111
421
  errorShape: import("@trpc/server").TRPCDefaultErrorShape;
@@ -113,29 +423,23 @@ export declare const publicAppRouter: import("@trpc/server").TRPCBuiltRouter<{
113
423
  }, import("@trpc/server").TRPCDecorateCreateRouterOptions<{
114
424
  api: import("@trpc/server").TRPCBuiltRouter<{
115
425
  ctx: {
116
- user: ClerkUser;
117
- isAdmin: boolean;
118
- authType: "license" | "clerk" | "none";
119
- license: {
120
- key: string;
121
- data: LicenseUsageData | undefined;
122
- };
123
- licenseError: undefined;
124
- request: import("fastify").FastifyRequest<import("fastify").RouteGenericInterface, import("fastify").RawServerDefault, import("http").IncomingMessage, import("fastify").FastifySchema, import("fastify").FastifyTypeProviderDefault, unknown, import("fastify").FastifyBaseLogger, import("fastify/types/type-provider.js").ResolveFastifyRequestType<import("fastify").FastifyTypeProviderDefault, import("fastify").FastifySchema, import("fastify").RouteGenericInterface>>;
125
- } | {
126
426
  user: null;
127
427
  isAdmin: boolean;
128
- authType: "license" | "clerk" | "none";
129
- license: null;
130
- licenseError: string | undefined;
131
- request: import("fastify").FastifyRequest<import("fastify").RouteGenericInterface, import("fastify").RawServerDefault, import("http").IncomingMessage, import("fastify").FastifySchema, import("fastify").FastifyTypeProviderDefault, unknown, import("fastify").FastifyBaseLogger, import("fastify/types/type-provider.js").ResolveFastifyRequestType<import("fastify").FastifyTypeProviderDefault, import("fastify").FastifySchema, import("fastify").RouteGenericInterface>>;
428
+ authType: "none";
429
+ credentialKind: null;
430
+ authExpiresAtMs: null;
431
+ accessPrincipal: null;
432
+ accessError: import("@merchbaseco/access").ServiceAccessErrorCode | null;
433
+ request: ContextRequest;
132
434
  } | {
133
435
  user: ClerkUser;
134
436
  isAdmin: boolean;
135
- authType: "license" | "clerk" | "none";
136
- license: null;
137
- licenseError: undefined;
138
- request: import("fastify").FastifyRequest<import("fastify").RouteGenericInterface, import("fastify").RawServerDefault, import("http").IncomingMessage, import("fastify").FastifySchema, import("fastify").FastifyTypeProviderDefault, unknown, import("fastify").FastifyBaseLogger, import("fastify/types/type-provider.js").ResolveFastifyRequestType<import("fastify").FastifyTypeProviderDefault, import("fastify").FastifySchema, import("fastify").RouteGenericInterface>>;
437
+ authType: "access";
438
+ credentialKind: CredentialKind;
439
+ authExpiresAtMs: number | null;
440
+ accessPrincipal: RankWranglerServicePrincipal;
441
+ accessError: null;
442
+ request: ContextRequest;
139
443
  };
140
444
  meta: object;
141
445
  errorShape: import("@trpc/server").TRPCDefaultErrorShape;
@@ -143,200 +447,156 @@ export declare const publicAppRouter: import("@trpc/server").TRPCBuiltRouter<{
143
447
  }, import("@trpc/server").TRPCDecorateCreateRouterOptions<{
144
448
  public: import("@trpc/server").TRPCBuiltRouter<{
145
449
  ctx: {
146
- user: ClerkUser;
147
- isAdmin: boolean;
148
- authType: "license" | "clerk" | "none";
149
- license: {
150
- key: string;
151
- data: LicenseUsageData | undefined;
152
- };
153
- licenseError: undefined;
154
- request: import("fastify").FastifyRequest<import("fastify").RouteGenericInterface, import("fastify").RawServerDefault, import("http").IncomingMessage, import("fastify").FastifySchema, import("fastify").FastifyTypeProviderDefault, unknown, import("fastify").FastifyBaseLogger, import("fastify/types/type-provider.js").ResolveFastifyRequestType<import("fastify").FastifyTypeProviderDefault, import("fastify").FastifySchema, import("fastify").RouteGenericInterface>>;
155
- } | {
156
450
  user: null;
157
451
  isAdmin: boolean;
158
- authType: "license" | "clerk" | "none";
159
- license: null;
160
- licenseError: string | undefined;
161
- request: import("fastify").FastifyRequest<import("fastify").RouteGenericInterface, import("fastify").RawServerDefault, import("http").IncomingMessage, import("fastify").FastifySchema, import("fastify").FastifyTypeProviderDefault, unknown, import("fastify").FastifyBaseLogger, import("fastify/types/type-provider.js").ResolveFastifyRequestType<import("fastify").FastifyTypeProviderDefault, import("fastify").FastifySchema, import("fastify").RouteGenericInterface>>;
452
+ authType: "none";
453
+ credentialKind: null;
454
+ authExpiresAtMs: null;
455
+ accessPrincipal: null;
456
+ accessError: import("@merchbaseco/access").ServiceAccessErrorCode | null;
457
+ request: ContextRequest;
162
458
  } | {
163
459
  user: ClerkUser;
164
460
  isAdmin: boolean;
165
- authType: "license" | "clerk" | "none";
166
- license: null;
167
- licenseError: undefined;
168
- request: import("fastify").FastifyRequest<import("fastify").RouteGenericInterface, import("fastify").RawServerDefault, import("http").IncomingMessage, import("fastify").FastifySchema, import("fastify").FastifyTypeProviderDefault, unknown, import("fastify").FastifyBaseLogger, import("fastify/types/type-provider.js").ResolveFastifyRequestType<import("fastify").FastifyTypeProviderDefault, import("fastify").FastifySchema, import("fastify").RouteGenericInterface>>;
461
+ authType: "access";
462
+ credentialKind: CredentialKind;
463
+ authExpiresAtMs: number | null;
464
+ accessPrincipal: RankWranglerServicePrincipal;
465
+ accessError: null;
466
+ request: ContextRequest;
169
467
  };
170
468
  meta: object;
171
469
  errorShape: import("@trpc/server").TRPCDefaultErrorShape;
172
470
  transformer: false;
173
471
  }, import("@trpc/server").TRPCDecorateCreateRouterOptions<{
174
- getProductHistory: import("@trpc/server").TRPCMutationProcedure<{
175
- input: {
176
- marketplaceId: string;
177
- asin: string;
178
- startAt?: unknown;
179
- endAt?: unknown;
180
- limit?: unknown;
181
- days?: unknown;
182
- metrics?: ("bsr" | "price")[] | undefined;
183
- format?: "legacy" | "agent" | undefined;
184
- bucket?: "auto" | "day" | "week" | "month" | undefined;
185
- };
186
- output: AgentHistoryResponse | {
187
- syncTriggered: boolean;
188
- marketplaceId: string;
189
- asin: string;
190
- metric: "bsrMain" | "bsrCategory" | "priceAmazon" | "priceNew" | "priceNewFba";
191
- latestImportAt: string | null;
192
- categoryNames: {
193
- [x: string]: string;
194
- };
195
- points: {
196
- categoryId: number;
197
- categoryName: string;
198
- observedAt: string;
199
- keepaMinutes: number;
200
- value: number | null;
201
- isMissing: boolean;
202
- }[];
203
- } | {
204
- marketplaceId: string;
205
- asin: string;
206
- metric: "bsrMain";
207
- latestImportAt: string | null;
208
- categoryNames: Record<string, string>;
209
- points: {
210
- categoryId: number;
211
- categoryName: string | null;
212
- observedAt: string;
213
- keepaMinutes: number;
214
- value: number | null;
215
- isMissing: boolean;
216
- }[];
217
- collecting: boolean;
218
- syncTriggered: boolean;
219
- };
220
- meta: object;
221
- }>;
222
- getProductInfoBatch: import("@trpc/server").TRPCMutationProcedure<{
223
- input: {
224
- marketplaceId: string;
225
- asins: string[];
226
- };
227
- output: {
228
- marketplaceId: string;
229
- items: ({
230
- asin: string;
231
- success: true;
232
- data: ProductInfo;
233
- } | {
234
- asin: string;
235
- success: false;
236
- error: string;
237
- code: "UNAUTHORIZED" | "PARSE_ERROR" | "BAD_REQUEST" | "INTERNAL_SERVER_ERROR" | "NOT_IMPLEMENTED" | "BAD_GATEWAY" | "SERVICE_UNAVAILABLE" | "GATEWAY_TIMEOUT" | "PAYMENT_REQUIRED" | "FORBIDDEN" | "NOT_FOUND" | "METHOD_NOT_SUPPORTED" | "TIMEOUT" | "CONFLICT" | "PRECONDITION_FAILED" | "PAYLOAD_TOO_LARGE" | "UNSUPPORTED_MEDIA_TYPE" | "UNPROCESSABLE_CONTENT" | "PRECONDITION_REQUIRED" | "TOO_MANY_REQUESTS" | "CLIENT_CLOSED_REQUEST";
238
- })[];
239
- meta: {
240
- requestedCount: number;
241
- successCount: number;
242
- errorCount: number;
243
- };
244
- };
245
- meta: object;
246
- }>;
247
- getProductInfo: import("@trpc/server").TRPCMutationProcedure<{
248
- input: {
249
- marketplaceId: string;
250
- asin: string;
251
- };
252
- output: ProductInfo;
253
- meta: object;
254
- }>;
255
- dev: import("@trpc/server").TRPCBuiltRouter<{
472
+ keyword: import("@trpc/server").TRPCBuiltRouter<{
256
473
  ctx: {
257
- user: ClerkUser;
258
- isAdmin: boolean;
259
- authType: "license" | "clerk" | "none";
260
- license: {
261
- key: string;
262
- data: LicenseUsageData | undefined;
263
- };
264
- licenseError: undefined;
265
- request: import("fastify").FastifyRequest<import("fastify").RouteGenericInterface, import("fastify").RawServerDefault, import("http").IncomingMessage, import("fastify").FastifySchema, import("fastify").FastifyTypeProviderDefault, unknown, import("fastify").FastifyBaseLogger, import("fastify/types/type-provider.js").ResolveFastifyRequestType<import("fastify").FastifyTypeProviderDefault, import("fastify").FastifySchema, import("fastify").RouteGenericInterface>>;
266
- } | {
267
474
  user: null;
268
475
  isAdmin: boolean;
269
- authType: "license" | "clerk" | "none";
270
- license: null;
271
- licenseError: string | undefined;
272
- request: import("fastify").FastifyRequest<import("fastify").RouteGenericInterface, import("fastify").RawServerDefault, import("http").IncomingMessage, import("fastify").FastifySchema, import("fastify").FastifyTypeProviderDefault, unknown, import("fastify").FastifyBaseLogger, import("fastify/types/type-provider.js").ResolveFastifyRequestType<import("fastify").FastifyTypeProviderDefault, import("fastify").FastifySchema, import("fastify").RouteGenericInterface>>;
476
+ authType: "none";
477
+ credentialKind: null;
478
+ authExpiresAtMs: null;
479
+ accessPrincipal: null;
480
+ accessError: import("@merchbaseco/access").ServiceAccessErrorCode | null;
481
+ request: ContextRequest;
273
482
  } | {
274
483
  user: ClerkUser;
275
484
  isAdmin: boolean;
276
- authType: "license" | "clerk" | "none";
277
- license: null;
278
- licenseError: undefined;
279
- request: import("fastify").FastifyRequest<import("fastify").RouteGenericInterface, import("fastify").RawServerDefault, import("http").IncomingMessage, import("fastify").FastifySchema, import("fastify").FastifyTypeProviderDefault, unknown, import("fastify").FastifyBaseLogger, import("fastify/types/type-provider.js").ResolveFastifyRequestType<import("fastify").FastifyTypeProviderDefault, import("fastify").FastifySchema, import("fastify").RouteGenericInterface>>;
485
+ authType: "access";
486
+ credentialKind: CredentialKind;
487
+ authExpiresAtMs: number | null;
488
+ accessPrincipal: RankWranglerServicePrincipal;
489
+ accessError: null;
490
+ request: ContextRequest;
280
491
  };
281
492
  meta: object;
282
493
  errorShape: import("@trpc/server").TRPCDefaultErrorShape;
283
494
  transformer: false;
284
495
  }, import("@trpc/server").TRPCDecorateCreateRouterOptions<{
285
- createClerkSignInToken: import("@trpc/server").TRPCMutationProcedure<{
286
- input: void;
496
+ get: import("@trpc/server").TRPCQueryProcedure<{
497
+ input: {
498
+ keyword: string;
499
+ dataEndDate?: string | undefined;
500
+ dataStartDate?: string | undefined;
501
+ marketplaceId?: "ATVPDKIKX0DER" | undefined;
502
+ reportPeriod?: "DAY" | "WEEK" | undefined;
503
+ };
287
504
  output: {
288
- ticket: string;
289
- expiresInSeconds: number;
505
+ keyword: string;
506
+ status: "ready" | "empty";
507
+ current: KeywordCurrent | null;
290
508
  };
291
509
  meta: object;
292
510
  }>;
511
+ history: import("@trpc/server").TRPCQueryProcedure<{
512
+ input: {
513
+ keyword: string;
514
+ marketplaceId?: "ATVPDKIKX0DER" | undefined;
515
+ rangeDays?: number | undefined;
516
+ reportPeriod?: "DAY" | "WEEK" | undefined;
517
+ };
518
+ output: KeywordHistoryResponse;
519
+ meta: object;
520
+ }>;
521
+ search: import("@trpc/server").TRPCQueryProcedure<{
522
+ input: {
523
+ text: string;
524
+ cursor?: number | undefined;
525
+ limit?: number | undefined;
526
+ maxRank?: number | undefined;
527
+ merchOnly?: boolean | undefined;
528
+ minRank?: number | undefined;
529
+ dataEndDate?: string | undefined;
530
+ dataStartDate?: string | undefined;
531
+ marketplaceId?: "ATVPDKIKX0DER" | undefined;
532
+ reportPeriod?: "DAY" | "WEEK" | undefined;
533
+ };
534
+ output: KeywordSearchResponse;
535
+ meta: object;
536
+ }>;
293
537
  }>>;
294
- license: import("@trpc/server").TRPCBuiltRouter<{
538
+ product: import("@trpc/server").TRPCBuiltRouter<{
295
539
  ctx: {
296
- user: ClerkUser;
297
- isAdmin: boolean;
298
- authType: "license" | "clerk" | "none";
299
- license: {
300
- key: string;
301
- data: LicenseUsageData | undefined;
302
- };
303
- licenseError: undefined;
304
- request: import("fastify").FastifyRequest<import("fastify").RouteGenericInterface, import("fastify").RawServerDefault, import("http").IncomingMessage, import("fastify").FastifySchema, import("fastify").FastifyTypeProviderDefault, unknown, import("fastify").FastifyBaseLogger, import("fastify/types/type-provider.js").ResolveFastifyRequestType<import("fastify").FastifyTypeProviderDefault, import("fastify").FastifySchema, import("fastify").RouteGenericInterface>>;
305
- } | {
306
540
  user: null;
307
541
  isAdmin: boolean;
308
- authType: "license" | "clerk" | "none";
309
- license: null;
310
- licenseError: string | undefined;
311
- request: import("fastify").FastifyRequest<import("fastify").RouteGenericInterface, import("fastify").RawServerDefault, import("http").IncomingMessage, import("fastify").FastifySchema, import("fastify").FastifyTypeProviderDefault, unknown, import("fastify").FastifyBaseLogger, import("fastify/types/type-provider.js").ResolveFastifyRequestType<import("fastify").FastifyTypeProviderDefault, import("fastify").FastifySchema, import("fastify").RouteGenericInterface>>;
542
+ authType: "none";
543
+ credentialKind: null;
544
+ authExpiresAtMs: null;
545
+ accessPrincipal: null;
546
+ accessError: import("@merchbaseco/access").ServiceAccessErrorCode | null;
547
+ request: ContextRequest;
312
548
  } | {
313
549
  user: ClerkUser;
314
550
  isAdmin: boolean;
315
- authType: "license" | "clerk" | "none";
316
- license: null;
317
- licenseError: undefined;
318
- request: import("fastify").FastifyRequest<import("fastify").RouteGenericInterface, import("fastify").RawServerDefault, import("http").IncomingMessage, import("fastify").FastifySchema, import("fastify").FastifyTypeProviderDefault, unknown, import("fastify").FastifyBaseLogger, import("fastify/types/type-provider.js").ResolveFastifyRequestType<import("fastify").FastifyTypeProviderDefault, import("fastify").FastifySchema, import("fastify").RouteGenericInterface>>;
551
+ authType: "access";
552
+ credentialKind: CredentialKind;
553
+ authExpiresAtMs: number | null;
554
+ accessPrincipal: RankWranglerServicePrincipal;
555
+ accessError: null;
556
+ request: ContextRequest;
319
557
  };
320
558
  meta: object;
321
559
  errorShape: import("@trpc/server").TRPCDefaultErrorShape;
322
560
  transformer: false;
323
561
  }, import("@trpc/server").TRPCDecorateCreateRouterOptions<{
324
- validate: import("@trpc/server").TRPCMutationProcedure<{
325
- input: void;
326
- output: {
327
- email: string;
328
- usage: number;
329
- usageLimit: number;
562
+ get: import("@trpc/server").TRPCMutationProcedure<{
563
+ input: {
564
+ marketplaceId: string;
565
+ asin: string;
330
566
  };
567
+ output: Product;
331
568
  meta: object;
332
569
  }>;
333
- status: import("@trpc/server").TRPCMutationProcedure<{
334
- input: void;
335
- output: {
336
- email: string;
337
- usage: number;
338
- usageLimit: number;
570
+ getMany: import("@trpc/server").TRPCMutationProcedure<{
571
+ input: {
572
+ products: {
573
+ marketplaceId: string;
574
+ asin: string;
575
+ }[];
576
+ };
577
+ output: BasicProduct[];
578
+ meta: object;
579
+ }>;
580
+ history: import("@trpc/server").TRPCMutationProcedure<{
581
+ input: {
582
+ marketplaceId: string;
583
+ asin: string;
584
+ bucket?: "auto" | "day" | "week" | "month" | undefined;
585
+ days?: unknown;
586
+ endAt?: unknown;
587
+ limit?: unknown;
588
+ metrics?: ("price" | "salesRank")[] | undefined;
589
+ startAt?: unknown;
590
+ };
591
+ output: PublicProductHistory;
592
+ meta: object;
593
+ }>;
594
+ search: import("@trpc/server").TRPCMutationProcedure<{
595
+ input: {
596
+ term: string;
597
+ refresh?: boolean | undefined;
339
598
  };
599
+ output: ProductSearch;
340
600
  meta: object;
341
601
  }>;
342
602
  }>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rankwrangler/http-client",
3
- "version": "0.6.0",
3
+ "version": "0.9.0",
4
4
  "description": "Typed tRPC client for RankWrangler",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -15,6 +15,9 @@
15
15
  "dist",
16
16
  "README.md"
17
17
  ],
18
+ "scripts": {
19
+ "test": "tsc -p tsconfig.test.json && bun test test/*.test.ts"
20
+ },
18
21
  "publishConfig": {
19
22
  "access": "public",
20
23
  "provenance": true