@rankwrangler/http-client 0.12.0 → 0.14.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 +1 -1
- package/dist/app-router.d.ts +39 -24
- package/dist/credential-headers.d.ts +1 -0
- package/dist/credential-headers.js +23 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +5 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ npm install @rankwrangler/http-client
|
|
|
13
13
|
import { createRankWranglerClient } from '@rankwrangler/http-client';
|
|
14
14
|
|
|
15
15
|
const client = createRankWranglerClient({
|
|
16
|
-
baseUrl: 'https://rankwrangler.merchbase.co',
|
|
16
|
+
baseUrl: 'https://rankwrangler-api.merchbase.co',
|
|
17
17
|
apiKey: process.env.MERCHBASE_API_KEY,
|
|
18
18
|
});
|
|
19
19
|
|
package/dist/app-router.d.ts
CHANGED
|
@@ -187,17 +187,31 @@ declare const rankwranglerServiceAccounts: import("drizzle-orm/pg-core").PgTable
|
|
|
187
187
|
export type RankWranglerServicePrincipal = Omit<typeof rankwranglerServiceAccounts.$inferSelect, "merchbaseUserId"> & {
|
|
188
188
|
merchbaseUserId: string;
|
|
189
189
|
};
|
|
190
|
-
export interface
|
|
190
|
+
export interface MerchbaseUser {
|
|
191
191
|
sub: string;
|
|
192
192
|
email?: string;
|
|
193
193
|
}
|
|
194
|
-
export type CredentialKind = "api_key" | "oauth" | "session";
|
|
195
194
|
export interface ContextRequest {
|
|
195
|
+
method?: string;
|
|
196
|
+
url?: string;
|
|
196
197
|
headers: {
|
|
197
198
|
authorization?: string;
|
|
198
199
|
host?: string;
|
|
200
|
+
"cf-access-jwt-assertion"?: string;
|
|
201
|
+
"x-merchbase-user-id"?: string | string[];
|
|
199
202
|
};
|
|
200
203
|
}
|
|
204
|
+
declare const keywordStages: readonly [
|
|
205
|
+
"graduated",
|
|
206
|
+
"trial",
|
|
207
|
+
"dropped",
|
|
208
|
+
"untracked"
|
|
209
|
+
];
|
|
210
|
+
declare const keywordFreshness: readonly [
|
|
211
|
+
"live",
|
|
212
|
+
"needsSync",
|
|
213
|
+
"syncing"
|
|
214
|
+
];
|
|
201
215
|
export type PublicCutoutThumbnail = {
|
|
202
216
|
status: "available";
|
|
203
217
|
url: string;
|
|
@@ -341,10 +355,10 @@ export declare const publicAppRouter: import("@trpc/server").TRPCBuiltRouter<{
|
|
|
341
355
|
accessError: import("@merchbaseco/access").ServiceAccessErrorCode | null;
|
|
342
356
|
request: ContextRequest;
|
|
343
357
|
} | {
|
|
344
|
-
user:
|
|
358
|
+
user: MerchbaseUser;
|
|
345
359
|
isAdmin: boolean;
|
|
346
360
|
authType: "access";
|
|
347
|
-
credentialKind:
|
|
361
|
+
credentialKind: "session" | "api_key" | "service_delegated" | "oauth";
|
|
348
362
|
authExpiresAtMs: number | null;
|
|
349
363
|
accessPrincipal: RankWranglerServicePrincipal;
|
|
350
364
|
accessError: null;
|
|
@@ -365,10 +379,10 @@ export declare const publicAppRouter: import("@trpc/server").TRPCBuiltRouter<{
|
|
|
365
379
|
accessError: import("@merchbaseco/access").ServiceAccessErrorCode | null;
|
|
366
380
|
request: ContextRequest;
|
|
367
381
|
} | {
|
|
368
|
-
user:
|
|
382
|
+
user: MerchbaseUser;
|
|
369
383
|
isAdmin: boolean;
|
|
370
384
|
authType: "access";
|
|
371
|
-
credentialKind:
|
|
385
|
+
credentialKind: "session" | "api_key" | "service_delegated" | "oauth";
|
|
372
386
|
authExpiresAtMs: number | null;
|
|
373
387
|
accessPrincipal: RankWranglerServicePrincipal;
|
|
374
388
|
accessError: null;
|
|
@@ -389,10 +403,10 @@ export declare const publicAppRouter: import("@trpc/server").TRPCBuiltRouter<{
|
|
|
389
403
|
accessError: import("@merchbaseco/access").ServiceAccessErrorCode | null;
|
|
390
404
|
request: ContextRequest;
|
|
391
405
|
} | {
|
|
392
|
-
user:
|
|
406
|
+
user: MerchbaseUser;
|
|
393
407
|
isAdmin: boolean;
|
|
394
408
|
authType: "access";
|
|
395
|
-
credentialKind:
|
|
409
|
+
credentialKind: "session" | "api_key" | "service_delegated" | "oauth";
|
|
396
410
|
authExpiresAtMs: number | null;
|
|
397
411
|
accessPrincipal: RankWranglerServicePrincipal;
|
|
398
412
|
accessError: null;
|
|
@@ -413,10 +427,10 @@ export declare const publicAppRouter: import("@trpc/server").TRPCBuiltRouter<{
|
|
|
413
427
|
accessError: import("@merchbaseco/access").ServiceAccessErrorCode | null;
|
|
414
428
|
request: ContextRequest;
|
|
415
429
|
} | {
|
|
416
|
-
user:
|
|
430
|
+
user: MerchbaseUser;
|
|
417
431
|
isAdmin: boolean;
|
|
418
432
|
authType: "access";
|
|
419
|
-
credentialKind:
|
|
433
|
+
credentialKind: "session" | "api_key" | "service_delegated" | "oauth";
|
|
420
434
|
authExpiresAtMs: number | null;
|
|
421
435
|
accessPrincipal: RankWranglerServicePrincipal;
|
|
422
436
|
accessError: null;
|
|
@@ -437,13 +451,14 @@ export declare const publicAppRouter: import("@trpc/server").TRPCBuiltRouter<{
|
|
|
437
451
|
lastCheckedAt: string | null;
|
|
438
452
|
nextCheckAt: string | null;
|
|
439
453
|
id: string;
|
|
440
|
-
queryId: string
|
|
454
|
+
queryId: string;
|
|
441
455
|
term: string;
|
|
442
|
-
|
|
443
|
-
|
|
456
|
+
stage: (typeof keywordStages)[number];
|
|
457
|
+
freshness: (typeof keywordFreshness)[number] | null;
|
|
444
458
|
retryScheduled: boolean;
|
|
445
459
|
heat: string;
|
|
446
460
|
score: number | null;
|
|
461
|
+
searchFrequencyRank: number | null;
|
|
447
462
|
sources: string[];
|
|
448
463
|
products: number;
|
|
449
464
|
merch: number;
|
|
@@ -463,9 +478,10 @@ export declare const publicAppRouter: import("@trpc/server").TRPCBuiltRouter<{
|
|
|
463
478
|
search: import("@trpc/server").TRPCQueryProcedure<{
|
|
464
479
|
input: {
|
|
465
480
|
text: string;
|
|
466
|
-
|
|
481
|
+
freshness?: "live" | "needsSync" | "syncing" | "all" | undefined;
|
|
467
482
|
sort?: "work" | "newest" | undefined;
|
|
468
483
|
limit?: number | undefined;
|
|
484
|
+
stage?: "trial" | "dropped" | "graduated" | "untracked" | "all" | undefined;
|
|
469
485
|
heat?: "unrated" | "hot" | "warm" | "cold" | "all" | undefined;
|
|
470
486
|
cursor?: {
|
|
471
487
|
key: [
|
|
@@ -478,7 +494,6 @@ export declare const publicAppRouter: import("@trpc/server").TRPCBuiltRouter<{
|
|
|
478
494
|
string
|
|
479
495
|
];
|
|
480
496
|
asOf: string;
|
|
481
|
-
trialTurn: boolean;
|
|
482
497
|
sort: "work" | "newest";
|
|
483
498
|
} | undefined;
|
|
484
499
|
};
|
|
@@ -488,19 +503,22 @@ export declare const publicAppRouter: import("@trpc/server").TRPCBuiltRouter<{
|
|
|
488
503
|
lastCheckedAt: string | null;
|
|
489
504
|
nextCheckAt: string | null;
|
|
490
505
|
id: string;
|
|
491
|
-
queryId: string
|
|
506
|
+
queryId: string;
|
|
492
507
|
term: string;
|
|
493
|
-
|
|
494
|
-
|
|
508
|
+
stage: (typeof keywordStages)[number];
|
|
509
|
+
freshness: (typeof keywordFreshness)[number] | null;
|
|
495
510
|
retryScheduled: boolean;
|
|
496
511
|
heat: string;
|
|
497
512
|
score: number | null;
|
|
513
|
+
searchFrequencyRank: number | null;
|
|
498
514
|
sources: string[];
|
|
499
515
|
products: number;
|
|
500
516
|
merch: number;
|
|
501
517
|
intervalDays: number | null;
|
|
502
518
|
}[];
|
|
503
519
|
nextCursor: {
|
|
520
|
+
sort: "fresh" | "work" | "newest" | "score" | "medianBsr" | "merch";
|
|
521
|
+
asOf: string;
|
|
504
522
|
key: [
|
|
505
523
|
number,
|
|
506
524
|
number,
|
|
@@ -510,9 +528,6 @@ export declare const publicAppRouter: import("@trpc/server").TRPCBuiltRouter<{
|
|
|
510
528
|
number,
|
|
511
529
|
string
|
|
512
530
|
];
|
|
513
|
-
asOf: string;
|
|
514
|
-
trialTurn: boolean;
|
|
515
|
-
sort: "work" | "newest";
|
|
516
531
|
} | null;
|
|
517
532
|
};
|
|
518
533
|
meta: object;
|
|
@@ -529,10 +544,10 @@ export declare const publicAppRouter: import("@trpc/server").TRPCBuiltRouter<{
|
|
|
529
544
|
accessError: import("@merchbaseco/access").ServiceAccessErrorCode | null;
|
|
530
545
|
request: ContextRequest;
|
|
531
546
|
} | {
|
|
532
|
-
user:
|
|
547
|
+
user: MerchbaseUser;
|
|
533
548
|
isAdmin: boolean;
|
|
534
549
|
authType: "access";
|
|
535
|
-
credentialKind:
|
|
550
|
+
credentialKind: "session" | "api_key" | "service_delegated" | "oauth";
|
|
536
551
|
authExpiresAtMs: number | null;
|
|
537
552
|
accessPrincipal: RankWranglerServicePrincipal;
|
|
538
553
|
accessError: null;
|
|
@@ -565,7 +580,7 @@ export declare const publicAppRouter: import("@trpc/server").TRPCBuiltRouter<{
|
|
|
565
580
|
input: {
|
|
566
581
|
marketplaceId: string;
|
|
567
582
|
asin: string;
|
|
568
|
-
bucket?: "
|
|
583
|
+
bucket?: "week" | "day" | "auto" | "month" | undefined;
|
|
569
584
|
days?: unknown;
|
|
570
585
|
endAt?: unknown;
|
|
571
586
|
limit?: unknown;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const credentialHeaders: (credential: string) => Record<string, string>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export const credentialHeaders = (credential) => {
|
|
2
|
+
if (!credential.startsWith('mbk_v1.'))
|
|
3
|
+
return { Authorization: `Bearer ${credential}` };
|
|
4
|
+
try {
|
|
5
|
+
if (credential.length > 2048)
|
|
6
|
+
throw new Error();
|
|
7
|
+
const encoded = credential.slice(7);
|
|
8
|
+
if (!/^[A-Za-z0-9_-]+$/.test(encoded))
|
|
9
|
+
throw new Error();
|
|
10
|
+
const decoded = atob(encoded.replace(/-/g, '+').replace(/_/g, '/'));
|
|
11
|
+
if (btoa(decoded).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '') !== encoded)
|
|
12
|
+
throw new Error();
|
|
13
|
+
const parsed = JSON.parse(decoded);
|
|
14
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed) || Object.keys(parsed).length !== 2 || !('clientId' in parsed) || !('clientSecret' in parsed) ||
|
|
15
|
+
typeof parsed.clientId !== 'string' || !/^[A-Za-z0-9._-]{1,256}$/.test(parsed.clientId) ||
|
|
16
|
+
typeof parsed.clientSecret !== 'string' || !/^[A-Za-z0-9_-]{32,512}$/.test(parsed.clientSecret))
|
|
17
|
+
throw new Error();
|
|
18
|
+
return { 'CF-Access-Client-Id': parsed.clientId, 'CF-Access-Client-Secret': parsed.clientSecret };
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
throw new Error('Invalid Merchbase machine credential.');
|
|
22
|
+
}
|
|
23
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createTRPCProxyClient } from '@trpc/client';
|
|
2
2
|
import type { inferRouterInputs, inferRouterOutputs } from '@trpc/server';
|
|
3
3
|
import type { PublicAppRouter } from './app-router';
|
|
4
|
-
export declare const DEFAULT_API_BASE_URL = "https://rankwrangler.merchbase.co";
|
|
4
|
+
export declare const DEFAULT_API_BASE_URL = "https://rankwrangler-api.merchbase.co";
|
|
5
5
|
export type AppRouter = PublicAppRouter;
|
|
6
6
|
export type RouterInputs = inferRouterInputs<PublicAppRouter>;
|
|
7
7
|
export type RouterOutputs = inferRouterOutputs<PublicAppRouter>;
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { credentialHeaders } from './credential-headers.js';
|
|
1
2
|
import { createTRPCProxyClient, httpBatchLink, httpLink } from '@trpc/client';
|
|
2
3
|
const TRAILING_SLASHES_REGEX = /\/+$/;
|
|
3
|
-
export const DEFAULT_API_BASE_URL = 'https://rankwrangler.merchbase.co';
|
|
4
|
+
export const DEFAULT_API_BASE_URL = 'https://rankwrangler-api.merchbase.co';
|
|
4
5
|
export const createRankWranglerClient = ({ baseUrl, apiKey, headers, batch = true, }) => {
|
|
5
6
|
const url = `${normalizeBaseUrl(baseUrl)}/api`;
|
|
6
7
|
const resolveHeaders = () => ({
|
|
7
|
-
...(apiKey ?
|
|
8
|
+
...(apiKey ? credentialHeaders(apiKey) : {}),
|
|
8
9
|
...(headers ?? {}),
|
|
9
10
|
});
|
|
10
11
|
if (batch) {
|
|
@@ -12,6 +13,7 @@ export const createRankWranglerClient = ({ baseUrl, apiKey, headers, batch = tru
|
|
|
12
13
|
links: [
|
|
13
14
|
httpBatchLink({
|
|
14
15
|
url,
|
|
16
|
+
fetch: (input, init) => fetch(input, { ...init, redirect: 'manual' }),
|
|
15
17
|
headers: resolveHeaders,
|
|
16
18
|
}),
|
|
17
19
|
],
|
|
@@ -22,6 +24,7 @@ export const createRankWranglerClient = ({ baseUrl, apiKey, headers, batch = tru
|
|
|
22
24
|
links: [
|
|
23
25
|
httpLink({
|
|
24
26
|
url,
|
|
27
|
+
fetch: (input, init) => fetch(input, { ...init, redirect: 'manual' }),
|
|
25
28
|
headers: resolveHeaders,
|
|
26
29
|
}),
|
|
27
30
|
],
|