Skip to content

Commit 571abb1

Browse files
authored
feat(KNO-9338): add branch configuration options (#696)
1 parent bac8ced commit 571abb1

File tree

15 files changed

+150
-1
lines changed

15 files changed

+150
-1
lines changed

.changeset/cuddly-moments-fly.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
"@knocklabs/react-core": patch
3+
---
4+
5+
Add `branch` option to `useAuthenticatedKnockClient` hook
6+
7+
The `useAuthenticatedKnockClient` hook now accepts a `branch` option. To use
8+
`useAuthenticatedKnockClient` with a branch, set the `apiKey` param to your
9+
development environment's API key and set the `branch` option to the slug of an
10+
existing branch.
11+
12+
```tsx
13+
import { useAuthenticatedKnockClient } from "@knocklabs/react-core";
14+
15+
const knock = useAuthenticatedKnockClient(
16+
process.env.KNOCK_PUBLIC_API_KEY,
17+
{ id: user.id },
18+
undefined, // userToken when needed
19+
{ branch: "my-branch-slug" },
20+
);
21+
```

.changeset/four-dodos-enter.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"nextjs-example": patch
3+
---
4+
5+
Add NEXT_PUBLIC_KNOCK_BRANCH env var for specifying branch

.changeset/tidy-days-make.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
"@knocklabs/client": patch
3+
---
4+
5+
Add `branch` option to `Knock` client
6+
7+
The `Knock` client now accepts a `branch` option. To use `Knock` with a branch,
8+
set the `apiKey` param to your development environment's API key and set the
9+
`branch` option to the slug of an existing branch.
10+
11+
```js
12+
import Knock from "@knocklabs/client";
13+
14+
const knock = new Knock(process.env.KNOCK_PUBLIC_API_KEY, {
15+
branch: "my-branch-slug",
16+
});
17+
```

.changeset/yellow-insects-knock.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
"@knocklabs/react-core": patch
3+
---
4+
5+
Add `branch` prop to `<KnockProvider>`
6+
7+
The `<KnockProvider>` context provider now accepts an optional `branch` prop.
8+
To use `<KnockProvider>` with a branch, set the `apiKey` prop to your
9+
development environment's API key and set `branch` to the slug of an existing
10+
branch.
11+
12+
```tsx
13+
import { KnockProvider } from "@knocklabs/react";
14+
15+
const YourAppLayout = () => {
16+
return (
17+
<KnockProvider
18+
apiKey={process.env.KNOCK_PUBLIC_API_KEY}
19+
user={{ id: user.id }}
20+
branch="my-branch-slug"
21+
>
22+
{/** the rest of your app */}
23+
</KnockProvider>
24+
);
25+
};
26+
```

examples/nextjs-example/.env.sample

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ NEXT_PUBLIC_KNOCK_PUBLIC_API_KEY=<Knock public API key>
66
NEXT_PUBLIC_KNOCK_FEED_CHANNEL_ID=<Knock in-app feed channel ID for loading the feed>
77
NEXT_PUBLIC_WORKFLOW_KEY=<Knock workflow key that has the in-app channel, for sending notifications to this feed>
88

9-
NEXT_PUBLIC_KNOCK_HOST=<Optional>
9+
NEXT_PUBLIC_KNOCK_HOST=<Optional>
10+
NEXT_PUBLIC_KNOCK_BRANCH=<Optional>

examples/nextjs-example/pages/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export default function Home() {
4545
userToken={userToken}
4646
apiKey={process.env.NEXT_PUBLIC_KNOCK_PUBLIC_API_KEY!}
4747
host={process.env.NEXT_PUBLIC_KNOCK_HOST}
48+
branch={process.env.NEXT_PUBLIC_KNOCK_BRANCH}
4849
onUserTokenExpiring={tokenRefreshHandler}
4950
timeBeforeExpirationInMs={5000}
5051
logLevel="debug"

packages/client/src/api.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ type ApiClientOptions = {
66
host: string;
77
apiKey: string;
88
userToken: string | undefined;
9+
branch?: string;
910
};
1011

1112
export interface ApiResponse {
@@ -21,6 +22,7 @@ class ApiClient {
2122
private host: string;
2223
private apiKey: string;
2324
private userToken: string | null;
25+
private branch: string | null;
2426
private axiosClient: AxiosInstance;
2527

2628
public socket: Socket | undefined;
@@ -29,6 +31,7 @@ class ApiClient {
2931
this.host = options.host;
3032
this.apiKey = options.apiKey;
3133
this.userToken = options.userToken || null;
34+
this.branch = options.branch || null;
3235

3336
// Create a retryable axios client
3437
this.axiosClient = axios.create({
@@ -39,6 +42,7 @@ class ApiClient {
3942
Authorization: `Bearer ${this.apiKey}`,
4043
"X-Knock-User-Token": this.userToken,
4144
"X-Knock-Client": this.getKnockClientHeader(),
45+
"X-Knock-Branch": this.branch,
4246
},
4347
});
4448

@@ -47,6 +51,7 @@ class ApiClient {
4751
params: {
4852
user_token: this.userToken,
4953
api_key: this.apiKey,
54+
branch_slug: this.branch,
5055
},
5156
});
5257
}

packages/client/src/interfaces.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export type LogLevel = "debug";
88
export interface KnockOptions {
99
host?: string;
1010
logLevel?: LogLevel;
11+
branch?: string;
1112
}
1213

1314
export interface KnockObject<T = GenericData> {

packages/client/src/knock.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class Knock {
2525
public userId: string | undefined | null;
2626
public userToken?: string;
2727
public logLevel?: LogLevel;
28+
public readonly branch?: string;
2829
private tokenExpirationTimer: ReturnType<typeof setTimeout> | null = null;
2930
readonly feeds = new FeedClient(this);
3031
readonly objects = new ObjectClient(this);
@@ -40,6 +41,7 @@ class Knock {
4041
) {
4142
this.host = options.host || DEFAULT_HOST;
4243
this.logLevel = options.logLevel;
44+
this.branch = options.branch || undefined;
4345

4446
this.log("Initialized Knock instance");
4547

@@ -187,6 +189,7 @@ class Knock {
187189
apiKey: this.apiKey,
188190
host: this.host,
189191
userToken: this.userToken,
192+
branch: this.branch,
190193
});
191194
}
192195

packages/client/test/api.test.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import ApiClient from "../src/api";
55

66
import { createAxiosMock, mockAxios } from "./test-utils/mocks";
77

8+
const TEST_BRANCH_SLUG = "lorem-ipsum-dolor-branch";
9+
810
// Type for accessing global properties
911
type GlobalWithWindow = Record<string, unknown>;
1012

@@ -74,6 +76,7 @@ describe("API Client", () => {
7476
host: "https://api.knock.app",
7577
apiKey: "pk_test_12345",
7678
userToken: undefined,
79+
branch: TEST_BRANCH_SLUG,
7780
});
7881

7982
expect(apiClient).toBeInstanceOf(ApiClient);
@@ -515,6 +518,22 @@ describe("API Client", () => {
515518
);
516519
});
517520

521+
test("sets correct x-knock-branch header", () => {
522+
const apiClient = new ApiClient({
523+
host: "https://api.knock.app",
524+
apiKey: "pk_test_12345",
525+
userToken: undefined,
526+
branch: TEST_BRANCH_SLUG,
527+
});
528+
529+
const axiosClient = (apiClient as unknown as Record<string, unknown>)
530+
.axiosClient as { defaults: { headers: Record<string, string> } };
531+
532+
expect(axiosClient.defaults.headers["X-Knock-Branch"]).toBe(
533+
TEST_BRANCH_SLUG,
534+
);
535+
});
536+
518537
test("supports various HTTP methods", async () => {
519538
const mockHttp = createAxiosMock();
520539
const apiClient = new ApiClient({

0 commit comments

Comments
 (0)