Skip to content

Commit d55e07a

Browse files
add oauth apis and bump to version 0.1.1
1 parent 94d6e12 commit d55e07a

File tree

6 files changed

+212
-5
lines changed

6 files changed

+212
-5
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
## @makeplane/plane-node-sdk@0.1.0
1+
## @makeplane/plane-node-sdk@0.1.1
22

33
This generator creates TypeScript/JavaScript client that utilizes [Fetch API](https://fetch.spec.whatwg.org/). The generated Node module can be used in the following environments:
44

@@ -36,7 +36,7 @@ navigate to the folder of your consuming project and run one of the following co
3636
_published:_
3737

3838
```
39-
npm install @makeplane/[email protected].0 --save
39+
npm install @makeplane/[email protected].1 --save
4040
```
4141

4242
_unPublished (not recommended):_

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@makeplane/plane-node-sdk",
3-
"version": "0.1.0",
3+
"version": "0.1.1",
44
"description": "Node SDK for Plane",
55
"author": "Plane <[email protected]>",
66
"repository": {

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
export * from './runtime';
44
export * from './apis/index';
55
export * from './models/index';
6+
export * from "./oauth/api";

src/oauth/api.ts

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
import * as runtime from "../runtime";
2+
import { PlaneOAuthTokenResponse, PlaneOAuthAppInstallation } from "./models";
3+
4+
/**
5+
* OAuth API helper class
6+
*/
7+
export class OAuthApi extends runtime.BaseAPI {
8+
private clientId: string;
9+
private clientSecret: string;
10+
private redirectUri: string;
11+
private baseUrl: string;
12+
13+
constructor(
14+
configuration: runtime.Configuration,
15+
oauthConfig: {
16+
clientId: string;
17+
clientSecret: string;
18+
redirectUri: string;
19+
}
20+
) {
21+
super(configuration);
22+
this.clientId = oauthConfig.clientId;
23+
this.clientSecret = oauthConfig.clientSecret;
24+
this.redirectUri = oauthConfig.redirectUri;
25+
this.baseUrl = configuration.basePath || "https://api.plane.so";
26+
}
27+
28+
/**
29+
* Get the authorization URL for the OAuth flow
30+
* @param responseType - The response type (default: "code")
31+
* @param state - Optional state parameter for security
32+
* @returns The authorization URL
33+
*/
34+
getAuthorizationUrl(responseType: string = "code", state?: string): string {
35+
const params = new URLSearchParams({
36+
client_id: this.clientId,
37+
response_type: responseType,
38+
redirect_uri: this.redirectUri,
39+
});
40+
41+
if (state) {
42+
params.append("state", state);
43+
}
44+
45+
return `${this.baseUrl}/auth/o/authorize-app/?${params.toString()}`;
46+
}
47+
48+
/**
49+
* Exchange authorization code for access token
50+
* @param code - The authorization code
51+
* @param grantType - The grant type (default: "authorization_code")
52+
* @returns Promise resolving to token response
53+
*/
54+
async exchangeCodeForToken(
55+
code: string,
56+
grantType: string = "authorization_code"
57+
): Promise<PlaneOAuthTokenResponse> {
58+
const data = new URLSearchParams({
59+
grant_type: grantType,
60+
code: code,
61+
client_id: this.clientId,
62+
client_secret: this.clientSecret,
63+
redirect_uri: this.redirectUri,
64+
});
65+
66+
const headers: runtime.HTTPHeaders = {
67+
"Cache-Control": "no-cache",
68+
"Content-Type": "application/x-www-form-urlencoded",
69+
};
70+
71+
const response = await this.request({
72+
path: `/auth/o/token/`,
73+
method: "POST",
74+
headers: headers,
75+
body: data,
76+
});
77+
78+
return await response.json();
79+
}
80+
81+
/**
82+
* Get a new access token using a refresh token
83+
* @param refreshToken - The refresh token
84+
* @returns Promise resolving to token response
85+
*/
86+
async getRefreshToken(
87+
refreshToken: string
88+
): Promise<PlaneOAuthTokenResponse> {
89+
const data = new URLSearchParams({
90+
grant_type: "refresh_token",
91+
refresh_token: refreshToken,
92+
client_id: this.clientId,
93+
client_secret: this.clientSecret,
94+
});
95+
96+
const headers: runtime.HTTPHeaders = {
97+
"Cache-Control": "no-cache",
98+
"Content-Type": "application/x-www-form-urlencoded",
99+
};
100+
101+
const response = await this.request({
102+
path: `/auth/o/token/`,
103+
method: "POST",
104+
headers: headers,
105+
body: data,
106+
});
107+
108+
return await response.json();
109+
}
110+
111+
/**
112+
* Get a new access token using client credentials for bot/app installations
113+
* @param appInstallationId - The app installation ID
114+
* @returns Promise resolving to token response
115+
*/
116+
async getBotToken(
117+
appInstallationId: string
118+
): Promise<PlaneOAuthTokenResponse> {
119+
const data = new URLSearchParams({
120+
grant_type: "client_credentials",
121+
app_installation_id: appInstallationId,
122+
});
123+
124+
const headers: runtime.HTTPHeaders = {
125+
"Cache-Control": "no-cache",
126+
"Content-Type": "application/x-www-form-urlencoded",
127+
Authorization: `Basic ${this.getBasicAuthToken()}`,
128+
};
129+
130+
const response = await this.request({
131+
path: `/auth/o/token/`,
132+
method: "POST",
133+
headers: headers,
134+
body: data,
135+
});
136+
137+
return await response.json();
138+
}
139+
140+
/**
141+
* Get an app installation by ID using the bot token
142+
* @param token - The bot token from getBotToken method
143+
* @param appInstallationId - The app installation ID
144+
* @returns Promise resolving to app installation
145+
*/
146+
async getAppInstallation(
147+
token: string,
148+
appInstallationId: string
149+
): Promise<PlaneOAuthAppInstallation> {
150+
const headers: runtime.HTTPHeaders = {
151+
Authorization: `Bearer ${token}`,
152+
};
153+
154+
const response = await this.request({
155+
path: `/auth/o/app-installation/?id=${appInstallationId}`,
156+
method: "GET",
157+
headers: headers,
158+
});
159+
160+
const data = await response.json();
161+
if (!data || data.length === 0) {
162+
throw new runtime.ResponseError(response, "App installation not found");
163+
}
164+
165+
return data[0];
166+
}
167+
168+
/**
169+
* Generate basic auth token from client_id and client_secret
170+
* @returns Base64 encoded basic auth token
171+
*/
172+
private getBasicAuthToken(): string {
173+
const credentials = `${this.clientId}:${this.clientSecret}`;
174+
return btoa(credentials);
175+
}
176+
}

src/oauth/models.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
export interface PlaneOAuthTokenResponse {
2+
access_token: string;
3+
expires_in?: number;
4+
token_type: string;
5+
scope?: string;
6+
refresh_token?: string;
7+
}
8+
9+
export interface WorkspaceDetail {
10+
name: string;
11+
slug: string;
12+
id: string;
13+
logo_url?: string;
14+
}
15+
16+
export interface PlaneOAuthAppInstallation {
17+
id: string;
18+
workspace_detail: WorkspaceDetail;
19+
created_at: string;
20+
updated_at: string;
21+
deleted_at?: string;
22+
status: string;
23+
created_by?: string;
24+
updated_by?: string;
25+
workspace: string;
26+
application: string;
27+
installed_by: string;
28+
app_bot: string;
29+
webhook?: string;
30+
}

0 commit comments

Comments
 (0)