Skip to content

Commit

Permalink
feat: initial checkpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
himanshu-dixit committed Aug 15, 2024
1 parent 590abcc commit f0baecf
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 58 deletions.
3 changes: 2 additions & 1 deletion js/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ node_modules/
dist/
/types/*
lib/
*.log
*.log
ks/test-results/*
16 changes: 14 additions & 2 deletions js/config/getTestConfig.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
export const env = process.env.TEST_ENV || "prod"
const CURRENT_FILE_DIR = __dirname;
export const getTestConfig = (): Record<string, string> => {

type config = {
COMPOSIO_API_KEY: string;
BACKEND_HERMES_URL: string;
}

export const getTestConfig = (): config => {
const path = `${CURRENT_FILE_DIR}/test.config.${env}.json`;
return JSON.parse(JSON.stringify(require(path)));
try {
return JSON.parse(JSON.stringify(require(path))) as unknown as config;
} catch (error) {
console.error("Error loading test config file:", error);

throw new Error("Error loading test config file. You can create test.{{env}}.json file in the config folder.");
}
}
5 changes: 3 additions & 2 deletions js/src/sdk/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ describe("Basic SDK spec suite", () => {
it("create basic client", () => {
new Composio(COMPOSIO_API_KEY)
});

it("without apiKey, error should be thrown", () => {
expect(() => {
new Composio();
}).toThrow('API key is missing');
});

it("get entity",async()=>{
it("get entity and then fetch connection",async()=>{
const app = "github"
const composio = new Composio(COMPOSIO_API_KEY, BACKEND_HERMES_URL);
const entity = composio.getEntity("default")
Expand All @@ -27,4 +27,5 @@ describe("Basic SDK spec suite", () => {
const connection = await entity.getConnection(app);
expect(connection.appUniqueId).toBe(app);
})

});
49 changes: 20 additions & 29 deletions js/src/sdk/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,41 +6,32 @@ import { Integrations } from './models/integrations';
import { ActiveTriggers } from './models/activeTriggers';
import { getEnvVariable } from '../utils/shared';
import { COMPOSIO_BASE_URL } from './client/core/OpenAPI';
import { client as axiosClient } from "./client/services.gen"
import { User } from './models/user';
import { BackendClient } from './models/backendClient';
import { Entity } from './models/Entity';

export class Composio {
connectedAccounts: typeof ConnectedAccounts;
apps: typeof Apps;
actions: typeof Actions;
triggers: typeof Triggers;
integrations: typeof Integrations;
activeTriggers: typeof ActiveTriggers;
connectedAccounts: ConnectedAccounts;
apps: Apps;
actions: Actions;
triggers: Triggers;
integrations: Integrations;
activeTriggers: ActiveTriggers;

constructor(apiKey?: string, baseUrl?: string, runtime?: string) {
User.baseUrl = baseUrl || getEnvVariable("COMPOSIO_BASE_URL", COMPOSIO_BASE_URL) || "";
User.apiKey = apiKey || getEnvVariable("COMPOSIO_API_KEY") || '';

if (!User.apiKey) {
throw new Error('API key is missing');
}
backendClient: BackendClient;

axiosClient.setConfig({
baseURL: baseUrl,
headers: {
'X-API-KEY': `${User.apiKey}`,
'X-SOURCE': 'js_sdk',
'X-RUNTIME': runtime
}
})
constructor(apiKey?: string, baseUrl?: string, runtime?: string) {
const baseURLParsed = baseUrl || getEnvVariable("COMPOSIO_BASE_URL", COMPOSIO_BASE_URL) || "https://backend.composio.dev";
const apiKeyParsed = apiKey || getEnvVariable("COMPOSIO_API_KEY") || '';

this.backendClient = new BackendClient(apiKeyParsed, baseURLParsed, runtime);
this.connectedAccounts = new ConnectedAccounts(this.backendClient);
this.triggers = new Triggers(this.backendClient);

this.connectedAccounts = ConnectedAccounts;
this.apps = Apps;
this.actions = Actions;
this.triggers = Triggers;
this.integrations = Integrations;
this.activeTriggers = ActiveTriggers;
this.apps = new Apps();
this.actions = new Actions();

this.integrations = new Integrations();
this.activeTriggers = new ActiveTriggers();

}

Expand Down
69 changes: 69 additions & 0 deletions js/src/sdk/models/backendClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import apiClient from "../client/client"
import { client as axiosClient } from "../client/services.gen"

/**
* Class representing the details required to initialize and configure the API client.
*/
export class BackendClient {
/**
* The API key used for authenticating requests.
*/
public apiKey: string;

/**
* The base URL of the API against which requests will be made.
*/
public baseUrl: string;

/**
* The runtime environment where the client is being used.
*/
public runtime: string;

/**
* Creates an instance of apiClientDetails.
* @param {string} apiKey - The API key for client initialization.
* @param {string} baseUrl - The base URL for the API client.
* @param {string} runtime - The runtime environment identifier.
* @throws Will throw an error if the API key is not provided.
*/
constructor(apiKey: string, baseUrl: string, runtime?: string) {
this.runtime = runtime || '';
this.apiKey = apiKey;
this.baseUrl = baseUrl;

if (!apiKey) {
throw new Error(`API Key is required for initializing the client`);
}

this.initializeApiClient();
}

/**
* Retrieves the client ID from the user's information.
* @returns {Promise<string>} A promise that resolves to the client ID.
* @throws Will throw an error if the HTTP request fails.
*/
public async getClientId(): Promise<string> {
const response = await apiClient.clientAuthService.getUserInfo();
if (response.status !== 200) {
throw new Error(`HTTP Error: ${response.status}`);
}
return (response.data as unknown as Record<string, Record<string, string>>).client.id;
}

/**
* Initializes the API client with the provided configuration.
* @private
*/
private initializeApiClient() {
axiosClient.setConfig({
baseURL: this.baseUrl,
headers: {
'X-API-KEY': `${this.apiKey}`,
'X-SOURCE': 'js_sdk',
'X-RUNTIME': this.runtime
}
});
}
}
7 changes: 5 additions & 2 deletions js/src/sdk/models/connectedAccounts.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@

import client from "../client/client";
import apiClient from "../client/client"
import { BackendClient } from "./backendClient";

export class ConnectedAccounts {
constructor() {
}
backendClient: BackendClient;

constructor(backendClient: BackendClient) {
this.backendClient = backendClient;
}

static list(data: any): any{
return apiClient.connections.getConnections({
Expand Down
21 changes: 13 additions & 8 deletions js/src/sdk/models/triggers.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@

import { TriggerData, PusherUtils } from "../utils/pusher";
import logger from "../../utils/logger";
import {User} from "./user"
import {BackendClient} from "./backendClient"

import apiClient from "../client/client"
import { TriggersControllerListTriggersData, TriggersControllerListTriggersResponse } from "../client";
export class Triggers {
trigger_to_client_event = "trigger_to_client";

backendClient: BackendClient;
constructor(backendClient: BackendClient) {
this.backendClient = backendClient;
}

/**
* Retrieves a list of all triggers in the Composio platform.
*
Expand All @@ -18,7 +23,7 @@ export class Triggers {
* @throws {ApiError} If the request fails.
*/
//@ts-ignore
static list(data: TriggersControllerListTriggersData = {}): Promise<TriggersControllerListTriggersResponse> {
list(data: TriggersControllerListTriggersData = {}): Promise<TriggersControllerListTriggersResponse> {
//@ts-ignore
return apiClient.triggers.listTriggers({
query: data
Expand All @@ -33,12 +38,12 @@ export class Triggers {
* @throws {ApiError} If the request fails.
*/
//@ts-ignore
static setup(data: any):{status:"string"}{
setup(data: any):{status:"string"}{
//@ts-ignore
return apiClient.triggers.enableTrigger(data).then(res=>res.data);
}

static async subscribe(fn: (data: TriggerData) => void, filters:{
async subscribe(fn: (data: TriggerData) => void, filters:{
appName?: string,
triggerId? : string;
connectionId?: string;
Expand All @@ -50,9 +55,9 @@ export class Triggers {

if(!fn) throw new Error("Function is required for trigger subscription");
//@ts-ignore
const clientId = await User.getClientId();
const clientId = await this.backendClient.getClientId();
//@ts-ignore
await PusherUtils.getPusherClient(User.baseUrl, User.apiKey);
await PusherUtils.getPusherClient(this.backendClient.baseUrl, this.backendClient.apiKey);

const shouldSendTrigger = (data: TriggerData) => {
if(Object.keys(filters).length === 0) return true;
Expand All @@ -76,9 +81,9 @@ export class Triggers {
});
}

static async unsubscribe() {
async unsubscribe() {
//@ts-ignore
const clientId = await User.getClientId();
const clientId = await this.backendClient.getClientId();
PusherUtils.triggerUnsubscribe(clientId);
}
}
Expand Down
14 changes: 0 additions & 14 deletions js/src/sdk/models/user.ts

This file was deleted.

17 changes: 17 additions & 0 deletions js/src/sdk/testUtils/getBackendInstance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { get } from "http";
import { BackendClient } from "../models/backendClient";
import { getTestConfig } from "../../../config/getTestConfig";


export const getBackendInstance = (): BackendClient => {
const testConfig = getTestConfig();
if (testConfig["COMPOSIO_API_KEY"] === undefined) {
throw new Error("COMPOSIO_API_KEY is not set in the test config");
}
if (testConfig["BACKEND_HERMES_URL"] === undefined) {
throw new Error("BACKEND_HERMES_URL is not set in the test config.");
}
const COMPOSIO_API_KEY = testConfig["COMPOSIO_API_KEY"];
const BACKEND_HERMES_URL = testConfig["BACKEND_HERMES_URL"];
return new BackendClient(COMPOSIO_API_KEY, BACKEND_HERMES_URL);
}

0 comments on commit f0baecf

Please sign in to comment.