Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/vercel-flags-core/src/index.default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const {
*/
resetDefaultFlagsClient,
/**
* Create a flags client based on an SDK Key
* Create a flags client using an SDK key, connection string, or Vercel OIDC.
*/
createClient,
} = make(createCreateRawClient(fns));
18 changes: 18 additions & 0 deletions packages/vercel-flags-core/src/index.make.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,24 @@ describe('make', () => {
expect(client).toBeDefined();
});

it('should create an OIDC-authenticated client with options as the first argument', () => {
const createRawClient = createMockCreateRawClient();
const { createClient } = make(createRawClient);

const client = createClient({ stream: false, polling: false });

expect(Controller).toHaveBeenCalledWith({
auth: expect.objectContaining({ sdkKey: undefined }),
stream: false,
polling: false,
});
expect(createRawClient).toHaveBeenCalledWith({
controller: expect.any(Object),
origin: { provider: 'vercel', sdkKey: undefined },
});
expect(client).toBeDefined();
});

it('should throw for empty SDK key', () => {
const createRawClient = createMockCreateRawClient();
const { createClient } = make(createRawClient);
Expand Down
33 changes: 28 additions & 5 deletions packages/vercel-flags-core/src/index.make.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,52 @@ import type { FlagsClient } from './types';
*/
export type CreateClientOptions = Omit<ControllerOptions, 'auth'>;

type CreateClient = {
<Entities = Record<string, unknown>>(
options: CreateClientOptions,
): FlagsClient<Entities>;
<Entities = Record<string, unknown>>(
sdkKeyOrConnectionString?: string,
options?: CreateClientOptions,
): FlagsClient<Entities>;
};

export function make(
createRawClient: ReturnType<typeof createCreateRawClient>,
): {
flagsClient: FlagsClient;
resetDefaultFlagsClient: () => void;
createClient: <Entities = Record<string, unknown>>(
sdkKeyOrConnectionString?: string,
options?: CreateClientOptions,
) => FlagsClient<Entities>;
createClient: CreateClient;
} {
let _defaultFlagsClient: FlagsClient | null = null;

// Insights
// - data source must specify the environment & projectId as sdkKey has that info
// - "reuse" functionality relies on the data source having the data for all envs
function createClient<Entities = Record<string, unknown>>(
options: CreateClientOptions,
): FlagsClient<Entities>;
function createClient<Entities = Record<string, unknown>>(
sdkKeyOrConnectionString?: string,
options?: CreateClientOptions,
): FlagsClient<Entities>;
function createClient<Entities = Record<string, unknown>>(
sdkKeyOrConnectionStringOrOptions?: string | CreateClientOptions,
options?: CreateClientOptions,
): FlagsClient<Entities> {
const optionsOnly =
typeof sdkKeyOrConnectionStringOrOptions === 'object' &&
sdkKeyOrConnectionStringOrOptions !== null;
const sdkKeyOrConnectionString = optionsOnly
? undefined
: sdkKeyOrConnectionStringOrOptions;
const createClientOptions = optionsOnly
? sdkKeyOrConnectionStringOrOptions
: options;
const auth = new Authentication(sdkKeyOrConnectionString);

// sdk key contains the environment
const controller = new Controller({ auth, ...options });
const controller = new Controller({ auth, ...createClientOptions });
return createRawClient<Entities>({
controller,
origin: { provider: 'vercel', sdkKey: auth.sdkKey },
Expand Down
Loading