Skip to content

Commit

Permalink
wrap the sdk in a thicker client (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
atrakh authored Oct 25, 2024
1 parent ec1fa6a commit 357943e
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 28 deletions.
20 changes: 13 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,12 @@ import { LaunchDarkly } from "@convex-dev/launchdarkly";
import { components } from "./_generated/api";
import { query } from "./_generated/server";

const launchdarkly = new LaunchDarkly(components.launchdarkly);

export const myQuery = query({
args: {},
handler: async ({ ctx }) => {
const launchdarkly = new LaunchDarkly(components.launchdarkly, ctx);
const launchdarkly = ld.sdk(ctx);
const isFlagOn = await launchdarkly.boolVariation(
"my-flag",
{ key: "myUser" },
Expand Down Expand Up @@ -202,16 +204,20 @@ Once configured, you may initialize `LaunchDarkly` with the appropriate componen
```typescript
import { LaunchDarkly } from "@convex-dev/launchdarkly";

const ldFirst = new LaunchDarkly(components.first, {
LAUNCHDARKLY_SDK_KEY: process.env.LAUNCHDARKLY_SDK_KEY_FIRST!,
});

const ldSecond = new LaunchDarkly(components.second, {
LAUNCHDARKLY_SDK_KEY: process.env.LAUNCHDARKLY_SDK_KEY_SECOND!,
});

export const myQuery = query({
args: {},
handler: async ({ ctx }) => {
const launchdarklyFirst = new LaunchDarkly(components.first, ctx, {
LAUNCHDARKLY_SDK_KEY: process.env.LAUNCHDARKLY_SDK_KEY_FIRST!
});
const launchdarklyFirst = ldFirst.sdk(ctx);

const launchdarklySecond = new LaunchDarkly(components.second, ctx, {
LAUNCHDARKLY_SDK_KEY: process.env.LAUNCHDARKLY_SDK_KEY_SECOND!
});
const launchdarklySecond = ldSecond.sdk(ctx);

...
},
Expand Down
16 changes: 9 additions & 7 deletions example/convex/example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import { LaunchDarkly } from "@convex-dev/launchdarkly";
import { mutation, query } from "./_generated/server";
import { components } from "./_generated/api";

const launchdarkly = new LaunchDarkly(components.launchdarkly);

export const listFruits = query({
handler: async (ctx) => {
const launchdarkly = new LaunchDarkly(components.launchdarkly, ctx);
const ld= = launchdarkly.sdk(ctx);
const user = { key: "myUserId" };

const showFruits = await launchdarkly.boolVariation(
const showFruits = await ld.boolVariation(
"can-show-fruits",
user,
true
Expand All @@ -21,11 +23,11 @@ export const listFruits = query({

export const buyFruit = mutation({
handler: async (ctx) => {
const launchdarkly = new LaunchDarkly(components.launchdarkly, ctx);
const ld = launchdarkly.sdk(ctx);

const user = { key: "myUserId" };

const showFruits = await launchdarkly.boolVariation(
const showFruits = await ld.boolVariation(
"can-buy-fruits",
user,
false
Expand All @@ -37,7 +39,7 @@ export const buyFruit = mutation({
};
}

launchdarkly.track("buy-fruit", user);
ld.track("buy-fruit", user);
},
});

Expand All @@ -47,9 +49,9 @@ export const initialized = query({
if (!process.env.LAUNCHDARKLY_SDK_KEY) {
return false;
}
const launchdarkly = new LaunchDarkly(components.launchdarkly, ctx);
const ld = launchdarkly.sdk(ctx);
return (
(await launchdarkly.allFlagsState({ key: "any" })).allValues()[
(await ld.allFlagsState({ key: "any" })).allValues()[
"can-buy-fruits"
] !== undefined
);
Expand Down
26 changes: 13 additions & 13 deletions src/sdk/LaunchDarkly.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,29 @@ describe("LaunchDarkly", () => {
new LaunchDarkly(
// @ts-expect-error It's ok
api,
{},
{
LAUNCHDARKLY_SDK_KEY: "test-key",
}
);
// @ts-expect-error It's ok
).sdk({});

expect(setTimeoutSpy).not.toHaveBeenCalled();
expect(setIntervalSpy).not.toHaveBeenCalled();
});

test("should throw an error if LAUNCHDARKLY_SDK_KEY is not provided", async () => {
await expect(
// @ts-expect-error It's ok
() => new LaunchDarkly(api, {}, {})
).toThrow(new Error("LAUNCHDARKLY_SDK_KEY is required"));
// @ts-expect-error It's ok
await expect(() => new LaunchDarkly(api, {}).sdk({})).toThrow(
new Error("LAUNCHDARKLY_SDK_KEY is required")
);
});

test("should not throw an error if the env var is set", () => {
vi.stubEnv("LAUNCHDARKLY_SDK_KEY", "test-key");

expect(() => {
// @ts-expect-error It's ok
new LaunchDarkly(api, {}, {});
new LaunchDarkly(api, {}).sdk({});
}).not.toThrow();

vi.unstubAllEnvs();
Expand All @@ -44,11 +44,11 @@ describe("LaunchDarkly", () => {
const ld = new LaunchDarkly(
// @ts-expect-error It's ok
api,
{},
{
LAUNCHDARKLY_SDK_KEY: "test-key",
}
);
// @ts-expect-error It's ok
).sdk({});

// @ts-expect-error We are testing internal state
expect(ld.eventProcessor).not.toBeInstanceOf(EventProcessor);
Expand All @@ -58,11 +58,11 @@ describe("LaunchDarkly", () => {
const ld = new LaunchDarkly(
// @ts-expect-error It's ok
api,
{ runMutation: () => {} },
{
LAUNCHDARKLY_SDK_KEY: "test-key",
}
);
// @ts-expect-error It's ok
).sdk({ runMutation: () => {} });

// @ts-expect-error We are testing internal state
expect(ld.eventProcessor).toBeInstanceOf(EventProcessor);
Expand All @@ -72,12 +72,12 @@ describe("LaunchDarkly", () => {
const ld = new LaunchDarkly(
// @ts-expect-error It's ok
api,
{ runMutation: () => {} },
{
LAUNCHDARKLY_SDK_KEY: "test-key",
sendEvents: false,
}
);
// @ts-expect-error It's ok
).sdk({ runMutation: () => {} });

// @ts-expect-error We are testing internal state
expect(ld.eventProcessor).not.toBeInstanceOf(EventProcessor);
Expand Down
17 changes: 16 additions & 1 deletion src/sdk/LaunchDarkly.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,22 @@ import {
import { RunMutationCtx, RunQueryCtx } from "../component/types";
import { ComponentApi } from "./useApi";

export class LaunchDarkly extends LDClientImpl {
export class LaunchDarkly {
constructor(
private component: ComponentApi,
private options?: {
application?: LDOptions["application"];
sendEvents?: boolean;
LAUNCHDARKLY_SDK_KEY?: string;
} & EventProcessorOptions
) {}

sdk(ctx: RunQueryCtx | RunMutationCtx) {
return new LDClient(this.component, ctx, this.options);
}
}

class LDClient extends LDClientImpl {
constructor(
component: ComponentApi,
ctx: RunQueryCtx | RunMutationCtx,
Expand Down

0 comments on commit 357943e

Please sign in to comment.