Skip to content
This repository has been archived by the owner on Jan 21, 2022. It is now read-only.

Commit

Permalink
feat: provide a singleton Clerk instance as the the default export, a…
Browse files Browse the repository at this point in the history
…llow usage of a sub-api directly, make all options configurable in a consistent manner
  • Loading branch information
yourtallness committed Jan 30, 2021
1 parent 02c68ec commit 82c5354
Show file tree
Hide file tree
Showing 25 changed files with 399 additions and 219 deletions.
232 changes: 176 additions & 56 deletions README.md

Large diffs are not rendered by default.

104 changes: 63 additions & 41 deletions src/Clerk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,18 @@ import { SMSMessage } from './resources/SMSMessage';
import { User } from './resources/User';
import { Verification } from './resources/Verification';

const defaultApiVersion = 'v1';
const defaultServerApiUrl = 'https://api.clerk.dev';
const defaultApiKey = process.env.CLERK_API_KEY || '';
const defaultApiVersion = process.env.CLERK_API_VERSION || 'v1';
const defaultServerApiUrl =
process.env.CLERK_API_URL || 'https://api.clerk.dev';

export default class Clerk {
apiKey: string;
serverApiUrl: string = defaultServerApiUrl;
apiVersion: string = defaultApiVersion;
httpOptions: object = {};
restClient: RestClient;
private _restClient: RestClient;

// singleton instance
static _instance: Clerk;

// TODO we may not need to instantiate these any more if they keep no state
// private api instances
private _clientApi?: ClientApi;
private _emailApi?: EmailApi;
Expand All @@ -48,69 +50,89 @@ export default class Clerk {
public static User = User;
public static Verification = Verification;

constructor(
apiKey: string,
{
serverApiUrl = defaultServerApiUrl,
apiVersion = defaultApiVersion,
httpOptions = {},
}: {
serverApiUrl?: string;
apiVersion?: string;
httpOptions?: object;
} = {}
) {
this.apiKey = apiKey;
this.apiVersion = apiVersion;
this.httpOptions = httpOptions || {};

if (serverApiUrl) {
this.serverApiUrl = serverApiUrl;
constructor({
apiKey = defaultApiKey,
serverApiUrl = defaultServerApiUrl,
apiVersion = defaultApiVersion,
httpOptions = {},
}: {
apiKey?: string;
serverApiUrl?: string;
apiVersion?: string;
httpOptions?: object;
} = {}) {
this._restClient = new RestClient(
apiKey,
serverApiUrl,
apiVersion,
httpOptions
);
}

// For use as singleton, always returns the same instance
static getInstance() {
if (!this._instance) {
this._instance = new Clerk();
}

this.restClient = new RestClient(
this.apiKey,
this.serverApiUrl,
this.apiVersion,
this.httpOptions
);
return this._instance;
}

// Setters for the embedded rest client

set apiKey(value: string) {
this._restClient.apiKey = value;
}

get clientApi(): ClientApi {
set serverApiUrl(value: string) {
this._restClient.serverApiUrl = value;
}

set apiVersion(value: string) {
this._restClient.apiVersion = value;
}

set httpOptions(value: object) {
this._restClient.httpOptions = value;
}

// Lazy sub-api getters

get clients(): ClientApi {
if (!this._clientApi) {
this._clientApi = new ClientApi(this.restClient);
this._clientApi = new ClientApi(this._restClient);
}

return this._clientApi;
}

get emailApi(): EmailApi {
get emails(): EmailApi {
if (!this._emailApi) {
this._emailApi = new EmailApi(this.restClient);
this._emailApi = new EmailApi(this._restClient);
}

return this._emailApi;
}

get sessionApi(): SessionApi {
get sessions(): SessionApi {
if (!this._sessionApi) {
this._sessionApi = new SessionApi(this.restClient);
this._sessionApi = new SessionApi(this._restClient);
}

return this._sessionApi;
}

get smsMessageApi(): SMSMessageApi {
get smsMessages(): SMSMessageApi {
if (!this._smsMessageApi) {
this._smsMessageApi = new SMSMessageApi(this.restClient);
this._smsMessageApi = new SMSMessageApi(this._restClient);
}

return this._smsMessageApi;
}

get userApi(): UserApi {
get users(): UserApi {
if (!this._userApi) {
this._userApi = new UserApi(this.restClient);
this._userApi = new UserApi(this._restClient);
}

return this._userApi;
Expand Down
4 changes: 2 additions & 2 deletions src/apis/AbstractApi.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { RestClient } from '../utils/RestClient';

export abstract class AbstractApi {
restClient: RestClient;
protected _restClient: RestClient;

constructor(restClient: RestClient) {
this.restClient = restClient;
this._restClient = restClient;
}
}
6 changes: 3 additions & 3 deletions src/apis/ClientApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,21 @@ import { Client } from '../resources/Client';

export class ClientApi extends AbstractApi {
public async getClientList(): Promise<Array<Client>> {
return this.restClient.makeRequest({
return this._restClient.makeRequest({
method: 'get',
path: '/clients',
});
}

public async getClient(clientId: string): Promise<Client> {
return this.restClient.makeRequest({
return this._restClient.makeRequest({
method: 'get',
path: `/clients/${clientId}`,
});
}

public verifyClient(token: string): Promise<Client> {
return this.restClient.makeRequest({
return this._restClient.makeRequest({
method: 'post',
path: '/clients/verify',
bodyParams: { token },
Expand Down
2 changes: 1 addition & 1 deletion src/apis/EmailApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type EmailParams = {

export class EmailApi extends AbstractApi {
public async createEmail(params: EmailParams): Promise<Email> {
return this.restClient.makeRequest({
return this._restClient.makeRequest({
method: 'post',
path: '/emails',
bodyParams: params,
Expand Down
2 changes: 1 addition & 1 deletion src/apis/SMSMessageApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ type SMSParams = {

export class SMSMessageApi extends AbstractApi {
public async createSMSMessage(params: SMSParams): Promise<SMSMessage> {
return this.restClient.makeRequest({
return this._restClient.makeRequest({
method: 'post',
path: '/sms_messages',
bodyParams: params,
Expand Down
8 changes: 4 additions & 4 deletions src/apis/SessionApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,22 @@ export class SessionApi extends AbstractApi {
public async getSessionList(
queryParams: QueryParams
): Promise<Array<Session>> {
return this.restClient.makeRequest({
return this._restClient.makeRequest({
method: 'get',
path: '/sessions',
queryParams: queryParams,
});
}

public async getSession(sessionId: string): Promise<Session> {
return this.restClient.makeRequest({
return this._restClient.makeRequest({
method: 'get',
path: `/sessions/${sessionId}`,
});
}

public async revokeSession(sessionId: string): Promise<Session> {
return this.restClient.makeRequest({
return this._restClient.makeRequest({
method: 'post',
path: `/sessions/${sessionId}/revoke`,
});
Expand All @@ -35,7 +35,7 @@ export class SessionApi extends AbstractApi {
sessionId: string,
token: string
): Promise<Session> {
return this.restClient.makeRequest({
return this._restClient.makeRequest({
method: 'post',
path: `/sessions/${sessionId}/verify`,
bodyParams: { token },
Expand Down
8 changes: 4 additions & 4 deletions src/apis/UserApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ interface UserParams {

export class UserApi extends AbstractApi {
public async getUserList(): Promise<Array<User>> {
return this.restClient.makeRequest({
return this._restClient.makeRequest({
method: 'get',
path: '/users',
});
}

public async getUser(userId: string): Promise<User> {
return this.restClient.makeRequest({
return this._restClient.makeRequest({
method: 'get',
path: `/users/${userId}`,
});
Expand All @@ -29,15 +29,15 @@ export class UserApi extends AbstractApi {
userId: string,
params: UserParams = {}
): Promise<User> {
return this.restClient.makeRequest({
return this._restClient.makeRequest({
method: 'patch',
path: `/users/${userId}`,
bodyParams: params,
});
}

public async deleteUser(userId: string): Promise<User> {
return this.restClient.makeRequest({
return this._restClient.makeRequest({
method: 'delete',
path: `/users/${userId}`,
});
Expand Down
13 changes: 7 additions & 6 deletions src/examples/express/server.mjs
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import express from 'express';
import { ExpressAuthMiddleware } from '@clerk/clerk-sdk-node';
import dotenv from 'dotenv';
// Usage:
// node --require dotenv/config server.mjs

dotenv.config();
import express from 'express';
import clerk, { ClerkExpressMiddleware } from '@clerk/clerk-sdk-node';

const apiKey = process.env.CLERK_API_KEY;
const serverApiUrl = process.env.CLERK_API_URL;
const port = process.env.PORT;

function onError(error) {
console.log(error);
}

clerk.serverApiUrl = serverApiUrl;

var app = express();

app.use(ExpressAuthMiddleware(apiKey, { serverApiUrl, onError }));
app.use(ClerkExpressMiddleware({ clerk, onError }));

app.get('/', (req, res) => {
res.json(req.session);
Expand Down
16 changes: 8 additions & 8 deletions src/examples/express/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@
# yarn lockfile v1


"@clerk/clerk-sdk-node@file:../../..":
version "0.0.2"
dependencies:
"@types/cookies" "^0.7.6"
cookies "^0.8.0"
got "^11.8.1"
snakecase-keys "^3.2.1"

"@sindresorhus/is@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.0.0.tgz#2ff674e9611b45b528896d820d3d7a812de2f0e4"
Expand Down Expand Up @@ -172,14 +180,6 @@ cacheable-request@^7.0.1:
normalize-url "^4.1.0"
responselike "^2.0.0"

"clerk-sdk-node@file:../../..":
version "0.0.4"
dependencies:
"@types/cookies" "^0.7.6"
cookies "^0.8.0"
got "^11.8.1"
snakecase-keys "^3.2.1"

clone-response@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b"
Expand Down
4 changes: 2 additions & 2 deletions src/examples/next/pages/api/require-session.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const { requireSession } = require('@clerk/clerk-sdk-node');
import clerk, { requireSession } from '@clerk/clerk-sdk-node';

function handler(req, res) {
console.log('Session required');
res.statusCode = 200;
res.json(req.session || { empty: true });
}

export default requireSession(handler, { serverApiUrl: process.env.CLERK_API_URL, onError: error => console.log(error) });
export default requireSession(handler, { clerk, onError: error => console.log(error) });
4 changes: 2 additions & 2 deletions src/examples/next/pages/api/with-session.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const { withSession } = require('@clerk/clerk-sdk-node');
import clerk, { withSession } from '@clerk/clerk-sdk-node';

function handler(req, res) {
console.log('Session optional');
res.statusCode = 200;
res.json(req.session || { empty: true });
}

export default withSession(handler, { serverApiUrl: process.env.CLERK_API_URL, onError: error => console.log(error) });
export default withSession(handler, { clerk, onError: error => console.log(error) });
19 changes: 9 additions & 10 deletions src/examples/node/client.mjs
Original file line number Diff line number Diff line change
@@ -1,30 +1,29 @@
import Clerk from '@clerk/clerk-sdk-node';
import dotenv from 'dotenv';
// Usage:
// node --require dotenv/config client.mjs

dotenv.config();
import { setClerkServerApiUrl, clients } from '@clerk/clerk-sdk-node';

const serverApiUrl = process.env.CLERK_API_URL;
const apiKey = process.env.CLERK_API_KEY;
const clientId = process.env.CLIENT_ID;
const sessionToken = process.env.SESSION_TOKEN;

const clerk = new Clerk.default(apiKey, { serverApiUrl });
setClerkServerApiUrl(serverApiUrl);

console.log('Get client list');
let clients = await clerk.clientApi.getClientList();
console.log(clients);
let clientList = await clients.getClientList();
console.log(clientList);

console.log('Get single client');
let client = await clerk.clientApi.getClient(clientId);
let client = await clients.getClient(clientId);
console.log(client);

console.log('Verify client');
let verifiedClient = await clerk.clientApi.verifyClient(sessionToken);
let verifiedClient = await clients.verifyClient(sessionToken);
console.log(verifiedClient);

try {
console.log('Get single client for invalid clientId');
let invalidClient = await clerk.clientApi.getClient('foobar');
let invalidClient = await clients.getClient('foobar');
console.log(invalidClient);
} catch (error) {
console.log(error);
Expand Down
Loading

0 comments on commit 82c5354

Please sign in to comment.