@rankwrangler/http-client 0.13.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 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
 
@@ -187,15 +187,18 @@ 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 ClerkUser {
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
  }
201
204
  declare const keywordStages: readonly [
@@ -352,10 +355,10 @@ export declare const publicAppRouter: import("@trpc/server").TRPCBuiltRouter<{
352
355
  accessError: import("@merchbaseco/access").ServiceAccessErrorCode | null;
353
356
  request: ContextRequest;
354
357
  } | {
355
- user: ClerkUser;
358
+ user: MerchbaseUser;
356
359
  isAdmin: boolean;
357
360
  authType: "access";
358
- credentialKind: CredentialKind;
361
+ credentialKind: "session" | "api_key" | "service_delegated" | "oauth";
359
362
  authExpiresAtMs: number | null;
360
363
  accessPrincipal: RankWranglerServicePrincipal;
361
364
  accessError: null;
@@ -376,10 +379,10 @@ export declare const publicAppRouter: import("@trpc/server").TRPCBuiltRouter<{
376
379
  accessError: import("@merchbaseco/access").ServiceAccessErrorCode | null;
377
380
  request: ContextRequest;
378
381
  } | {
379
- user: ClerkUser;
382
+ user: MerchbaseUser;
380
383
  isAdmin: boolean;
381
384
  authType: "access";
382
- credentialKind: CredentialKind;
385
+ credentialKind: "session" | "api_key" | "service_delegated" | "oauth";
383
386
  authExpiresAtMs: number | null;
384
387
  accessPrincipal: RankWranglerServicePrincipal;
385
388
  accessError: null;
@@ -400,10 +403,10 @@ export declare const publicAppRouter: import("@trpc/server").TRPCBuiltRouter<{
400
403
  accessError: import("@merchbaseco/access").ServiceAccessErrorCode | null;
401
404
  request: ContextRequest;
402
405
  } | {
403
- user: ClerkUser;
406
+ user: MerchbaseUser;
404
407
  isAdmin: boolean;
405
408
  authType: "access";
406
- credentialKind: CredentialKind;
409
+ credentialKind: "session" | "api_key" | "service_delegated" | "oauth";
407
410
  authExpiresAtMs: number | null;
408
411
  accessPrincipal: RankWranglerServicePrincipal;
409
412
  accessError: null;
@@ -424,10 +427,10 @@ export declare const publicAppRouter: import("@trpc/server").TRPCBuiltRouter<{
424
427
  accessError: import("@merchbaseco/access").ServiceAccessErrorCode | null;
425
428
  request: ContextRequest;
426
429
  } | {
427
- user: ClerkUser;
430
+ user: MerchbaseUser;
428
431
  isAdmin: boolean;
429
432
  authType: "access";
430
- credentialKind: CredentialKind;
433
+ credentialKind: "session" | "api_key" | "service_delegated" | "oauth";
431
434
  authExpiresAtMs: number | null;
432
435
  accessPrincipal: RankWranglerServicePrincipal;
433
436
  accessError: null;
@@ -477,8 +480,8 @@ export declare const publicAppRouter: import("@trpc/server").TRPCBuiltRouter<{
477
480
  text: string;
478
481
  freshness?: "live" | "needsSync" | "syncing" | "all" | undefined;
479
482
  sort?: "work" | "newest" | undefined;
480
- stage?: "trial" | "graduated" | "dropped" | "untracked" | "all" | undefined;
481
483
  limit?: number | undefined;
484
+ stage?: "trial" | "dropped" | "graduated" | "untracked" | "all" | undefined;
482
485
  heat?: "unrated" | "hot" | "warm" | "cold" | "all" | undefined;
483
486
  cursor?: {
484
487
  key: [
@@ -541,10 +544,10 @@ export declare const publicAppRouter: import("@trpc/server").TRPCBuiltRouter<{
541
544
  accessError: import("@merchbaseco/access").ServiceAccessErrorCode | null;
542
545
  request: ContextRequest;
543
546
  } | {
544
- user: ClerkUser;
547
+ user: MerchbaseUser;
545
548
  isAdmin: boolean;
546
549
  authType: "access";
547
- credentialKind: CredentialKind;
550
+ credentialKind: "session" | "api_key" | "service_delegated" | "oauth";
548
551
  authExpiresAtMs: number | null;
549
552
  accessPrincipal: RankWranglerServicePrincipal;
550
553
  accessError: null;
@@ -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 ? { Authorization: `Bearer ${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
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rankwrangler/http-client",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "description": "Typed tRPC client for RankWrangler",
5
5
  "repository": {
6
6
  "type": "git",