@simple-login/sdk 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -0
- package/dist/index.cjs +149 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +74 -0
- package/dist/index.d.ts +74 -0
- package/dist/index.js +119 -0
- package/dist/index.js.map +1 -0
- package/package.json +46 -0
package/README.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# @simple-login/sdk
|
|
2
|
+
|
|
3
|
+
Official SDK for Simple Login authentication.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @simple-login/sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { SimpleLogin } from '@simple-login/sdk'
|
|
15
|
+
|
|
16
|
+
const client = new SimpleLogin({
|
|
17
|
+
clientId: 'your-client-id',
|
|
18
|
+
clientSecret: 'your-client-secret',
|
|
19
|
+
redirectUri: 'https://your-app.com/callback',
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
// Generate authorization URL
|
|
23
|
+
const authUrl = client.getAuthorizationUrl({ state: 'random-state' })
|
|
24
|
+
|
|
25
|
+
// Exchange code for tokens
|
|
26
|
+
const tokens = await client.exchangeCode(code)
|
|
27
|
+
|
|
28
|
+
// Get user info
|
|
29
|
+
const user = await client.getUserInfo(tokens.access_token)
|
|
30
|
+
|
|
31
|
+
// Refresh token
|
|
32
|
+
const newTokens = await client.refreshToken(tokens.refresh_token)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## License
|
|
36
|
+
|
|
37
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
AuthorizationError: () => AuthorizationError,
|
|
24
|
+
SimpleLogin: () => SimpleLogin,
|
|
25
|
+
SousaError: () => SousaError,
|
|
26
|
+
TokenError: () => TokenError
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(index_exports);
|
|
29
|
+
|
|
30
|
+
// src/errors.ts
|
|
31
|
+
var SousaError = class extends Error {
|
|
32
|
+
constructor(message, code, statusCode) {
|
|
33
|
+
super(message);
|
|
34
|
+
this.code = code;
|
|
35
|
+
this.statusCode = statusCode;
|
|
36
|
+
this.name = "SousaError";
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
var AuthorizationError = class extends SousaError {
|
|
40
|
+
constructor(message) {
|
|
41
|
+
super(message, "AUTHORIZATION_ERROR", 401);
|
|
42
|
+
this.name = "AuthorizationError";
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
var TokenError = class extends SousaError {
|
|
46
|
+
constructor(message) {
|
|
47
|
+
super(message, "TOKEN_ERROR", 400);
|
|
48
|
+
this.name = "TokenError";
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// src/client.ts
|
|
53
|
+
var BASE_URL = "https://app.simple-login.com";
|
|
54
|
+
var SimpleLogin = class {
|
|
55
|
+
clientId;
|
|
56
|
+
clientSecret;
|
|
57
|
+
redirectUri;
|
|
58
|
+
baseUrl;
|
|
59
|
+
constructor(config) {
|
|
60
|
+
this.clientId = config.clientId;
|
|
61
|
+
this.clientSecret = config.clientSecret;
|
|
62
|
+
this.redirectUri = config.redirectUri;
|
|
63
|
+
this.baseUrl = BASE_URL;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Generate the authorization URL to redirect users for sign-in
|
|
67
|
+
*/
|
|
68
|
+
getAuthorizationUrl(options = {}) {
|
|
69
|
+
const params = new URLSearchParams({
|
|
70
|
+
client_id: this.clientId,
|
|
71
|
+
redirect_uri: this.redirectUri,
|
|
72
|
+
response_type: "code"
|
|
73
|
+
});
|
|
74
|
+
if (options.state) {
|
|
75
|
+
params.set("state", options.state);
|
|
76
|
+
}
|
|
77
|
+
if (options.scopes?.length) {
|
|
78
|
+
params.set("scope", options.scopes.join(" "));
|
|
79
|
+
}
|
|
80
|
+
return `${this.baseUrl}/v1/auth/authorize?${params.toString()}`;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Exchange an authorization code for access and refresh tokens
|
|
84
|
+
*/
|
|
85
|
+
async exchangeCode(code) {
|
|
86
|
+
const response = await fetch(`${this.baseUrl}/v1/auth/token`, {
|
|
87
|
+
method: "POST",
|
|
88
|
+
headers: {
|
|
89
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
90
|
+
},
|
|
91
|
+
body: new URLSearchParams({
|
|
92
|
+
grant_type: "authorization_code",
|
|
93
|
+
client_id: this.clientId,
|
|
94
|
+
client_secret: this.clientSecret,
|
|
95
|
+
redirect_uri: this.redirectUri,
|
|
96
|
+
code
|
|
97
|
+
})
|
|
98
|
+
});
|
|
99
|
+
if (!response.ok) {
|
|
100
|
+
const error = await response.json().catch(() => ({}));
|
|
101
|
+
throw new TokenError(error.error_description || "Failed to exchange authorization code");
|
|
102
|
+
}
|
|
103
|
+
return response.json();
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Refresh an access token using a refresh token
|
|
107
|
+
*/
|
|
108
|
+
async refreshToken(refreshToken) {
|
|
109
|
+
const response = await fetch(`${this.baseUrl}/v1/auth/token`, {
|
|
110
|
+
method: "POST",
|
|
111
|
+
headers: {
|
|
112
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
113
|
+
},
|
|
114
|
+
body: new URLSearchParams({
|
|
115
|
+
grant_type: "refresh_token",
|
|
116
|
+
client_id: this.clientId,
|
|
117
|
+
client_secret: this.clientSecret,
|
|
118
|
+
refresh_token: refreshToken
|
|
119
|
+
})
|
|
120
|
+
});
|
|
121
|
+
if (!response.ok) {
|
|
122
|
+
const error = await response.json().catch(() => ({}));
|
|
123
|
+
throw new TokenError(error.error_description || "Failed to refresh token");
|
|
124
|
+
}
|
|
125
|
+
return response.json();
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Get user information using an access token
|
|
129
|
+
*/
|
|
130
|
+
async getUserInfo(accessToken) {
|
|
131
|
+
const response = await fetch(`${this.baseUrl}/v1/auth/userinfo`, {
|
|
132
|
+
headers: {
|
|
133
|
+
Authorization: `Bearer ${accessToken}`
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
if (!response.ok) {
|
|
137
|
+
throw new AuthorizationError("Failed to fetch user info");
|
|
138
|
+
}
|
|
139
|
+
return response.json();
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
143
|
+
0 && (module.exports = {
|
|
144
|
+
AuthorizationError,
|
|
145
|
+
SimpleLogin,
|
|
146
|
+
SousaError,
|
|
147
|
+
TokenError
|
|
148
|
+
});
|
|
149
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/client.ts"],"sourcesContent":["export { SimpleLogin } from './client'\nexport { AuthorizationError, SousaError, TokenError } from './errors'\nexport type { AuthorizationUrlOptions, SimpleLoginConfig, TokenResponse, UserInfo } from './types'\n","export class SousaError extends Error {\n constructor(\n message: string,\n public code: string,\n public statusCode?: number\n ) {\n super(message);\n this.name = \"SousaError\";\n }\n}\n\nexport class AuthorizationError extends SousaError {\n constructor(message: string) {\n super(message, \"AUTHORIZATION_ERROR\", 401);\n this.name = \"AuthorizationError\";\n }\n}\n\nexport class TokenError extends SousaError {\n constructor(message: string) {\n super(message, \"TOKEN_ERROR\", 400);\n this.name = \"TokenError\";\n }\n}\n","import { AuthorizationError, TokenError } from './errors'\nimport type { AuthorizationUrlOptions, SimpleLoginConfig, TokenResponse, UserInfo } from './types'\n\ndeclare const __SIMPLELOGIN_BASE_URL__: string\n\nconst BASE_URL = __SIMPLELOGIN_BASE_URL__\n\nexport class SimpleLogin {\n private clientId: string\n private clientSecret: string\n private redirectUri: string\n private baseUrl: string\n\n constructor(config: SimpleLoginConfig) {\n this.clientId = config.clientId\n this.clientSecret = config.clientSecret\n this.redirectUri = config.redirectUri\n this.baseUrl = BASE_URL\n }\n\n /**\n * Generate the authorization URL to redirect users for sign-in\n */\n getAuthorizationUrl(options: AuthorizationUrlOptions = {}): string {\n const params = new URLSearchParams({\n client_id: this.clientId,\n redirect_uri: this.redirectUri,\n response_type: 'code',\n })\n\n if (options.state) {\n params.set('state', options.state)\n }\n\n if (options.scopes?.length) {\n params.set('scope', options.scopes.join(' '))\n }\n\n return `${this.baseUrl}/v1/auth/authorize?${params.toString()}`\n }\n\n /**\n * Exchange an authorization code for access and refresh tokens\n */\n async exchangeCode(code: string): Promise<TokenResponse> {\n const response = await fetch(`${this.baseUrl}/v1/auth/token`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n grant_type: 'authorization_code',\n client_id: this.clientId,\n client_secret: this.clientSecret,\n redirect_uri: this.redirectUri,\n code,\n }),\n })\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}))\n throw new TokenError(error.error_description || 'Failed to exchange authorization code')\n }\n\n return response.json()\n }\n\n /**\n * Refresh an access token using a refresh token\n */\n async refreshToken(refreshToken: string): Promise<TokenResponse> {\n const response = await fetch(`${this.baseUrl}/v1/auth/token`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n grant_type: 'refresh_token',\n client_id: this.clientId,\n client_secret: this.clientSecret,\n refresh_token: refreshToken,\n }),\n })\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}))\n throw new TokenError(error.error_description || 'Failed to refresh token')\n }\n\n return response.json()\n }\n\n /**\n * Get user information using an access token\n */\n async getUserInfo(accessToken: string): Promise<UserInfo> {\n const response = await fetch(`${this.baseUrl}/v1/auth/userinfo`, {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n },\n })\n\n if (!response.ok) {\n throw new AuthorizationError('Failed to fetch user info')\n }\n\n return response.json()\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,IAAM,aAAN,cAAyB,MAAM;AAAA,EACpC,YACE,SACO,MACA,YACP;AACA,UAAM,OAAO;AAHN;AACA;AAGP,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,qBAAN,cAAiC,WAAW;AAAA,EACjD,YAAY,SAAiB;AAC3B,UAAM,SAAS,uBAAuB,GAAG;AACzC,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,aAAN,cAAyB,WAAW;AAAA,EACzC,YAAY,SAAiB;AAC3B,UAAM,SAAS,eAAe,GAAG;AACjC,SAAK,OAAO;AAAA,EACd;AACF;;;AClBA,IAAM,WAAW;AAEV,IAAM,cAAN,MAAkB;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,QAA2B;AACrC,SAAK,WAAW,OAAO;AACvB,SAAK,eAAe,OAAO;AAC3B,SAAK,cAAc,OAAO;AAC1B,SAAK,UAAU;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA,EAKA,oBAAoB,UAAmC,CAAC,GAAW;AACjE,UAAM,SAAS,IAAI,gBAAgB;AAAA,MACjC,WAAW,KAAK;AAAA,MAChB,cAAc,KAAK;AAAA,MACnB,eAAe;AAAA,IACjB,CAAC;AAED,QAAI,QAAQ,OAAO;AACjB,aAAO,IAAI,SAAS,QAAQ,KAAK;AAAA,IACnC;AAEA,QAAI,QAAQ,QAAQ,QAAQ;AAC1B,aAAO,IAAI,SAAS,QAAQ,OAAO,KAAK,GAAG,CAAC;AAAA,IAC9C;AAEA,WAAO,GAAG,KAAK,OAAO,sBAAsB,OAAO,SAAS,CAAC;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,MAAsC;AACvD,UAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,kBAAkB;AAAA,MAC5D,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,IAAI,gBAAgB;AAAA,QACxB,YAAY;AAAA,QACZ,WAAW,KAAK;AAAA,QAChB,eAAe,KAAK;AAAA,QACpB,cAAc,KAAK;AAAA,QACnB;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,QAAQ,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AACpD,YAAM,IAAI,WAAW,MAAM,qBAAqB,uCAAuC;AAAA,IACzF;AAEA,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,cAA8C;AAC/D,UAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,kBAAkB;AAAA,MAC5D,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,IAAI,gBAAgB;AAAA,QACxB,YAAY;AAAA,QACZ,WAAW,KAAK;AAAA,QAChB,eAAe,KAAK;AAAA,QACpB,eAAe;AAAA,MACjB,CAAC;AAAA,IACH,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,QAAQ,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AACpD,YAAM,IAAI,WAAW,MAAM,qBAAqB,yBAAyB;AAAA,IAC3E;AAEA,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAY,aAAwC;AACxD,UAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,qBAAqB;AAAA,MAC/D,SAAS;AAAA,QACP,eAAe,UAAU,WAAW;AAAA,MACtC;AAAA,IACF,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,mBAAmB,2BAA2B;AAAA,IAC1D;AAEA,WAAO,SAAS,KAAK;AAAA,EACvB;AACF;","names":[]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
interface SimpleLoginConfig {
|
|
2
|
+
clientId: string;
|
|
3
|
+
clientSecret: string;
|
|
4
|
+
redirectUri: string;
|
|
5
|
+
}
|
|
6
|
+
interface AuthorizationUrlOptions {
|
|
7
|
+
state?: string;
|
|
8
|
+
scopes?: string[];
|
|
9
|
+
}
|
|
10
|
+
interface TokenResponse {
|
|
11
|
+
access_token: string;
|
|
12
|
+
refresh_token: string;
|
|
13
|
+
token_type: string;
|
|
14
|
+
expires_in: number;
|
|
15
|
+
}
|
|
16
|
+
interface UserInfo {
|
|
17
|
+
sub: string;
|
|
18
|
+
id: string;
|
|
19
|
+
email: string;
|
|
20
|
+
email_verified: boolean;
|
|
21
|
+
name: string;
|
|
22
|
+
picture?: string;
|
|
23
|
+
updated_at: number;
|
|
24
|
+
application_id: string;
|
|
25
|
+
application: {
|
|
26
|
+
id: string;
|
|
27
|
+
name: string;
|
|
28
|
+
slug: string;
|
|
29
|
+
logo_url?: string;
|
|
30
|
+
};
|
|
31
|
+
organization?: {
|
|
32
|
+
id: string;
|
|
33
|
+
name: string;
|
|
34
|
+
logo_url?: string;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
declare class SimpleLogin {
|
|
39
|
+
private clientId;
|
|
40
|
+
private clientSecret;
|
|
41
|
+
private redirectUri;
|
|
42
|
+
private baseUrl;
|
|
43
|
+
constructor(config: SimpleLoginConfig);
|
|
44
|
+
/**
|
|
45
|
+
* Generate the authorization URL to redirect users for sign-in
|
|
46
|
+
*/
|
|
47
|
+
getAuthorizationUrl(options?: AuthorizationUrlOptions): string;
|
|
48
|
+
/**
|
|
49
|
+
* Exchange an authorization code for access and refresh tokens
|
|
50
|
+
*/
|
|
51
|
+
exchangeCode(code: string): Promise<TokenResponse>;
|
|
52
|
+
/**
|
|
53
|
+
* Refresh an access token using a refresh token
|
|
54
|
+
*/
|
|
55
|
+
refreshToken(refreshToken: string): Promise<TokenResponse>;
|
|
56
|
+
/**
|
|
57
|
+
* Get user information using an access token
|
|
58
|
+
*/
|
|
59
|
+
getUserInfo(accessToken: string): Promise<UserInfo>;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
declare class SousaError extends Error {
|
|
63
|
+
code: string;
|
|
64
|
+
statusCode?: number | undefined;
|
|
65
|
+
constructor(message: string, code: string, statusCode?: number | undefined);
|
|
66
|
+
}
|
|
67
|
+
declare class AuthorizationError extends SousaError {
|
|
68
|
+
constructor(message: string);
|
|
69
|
+
}
|
|
70
|
+
declare class TokenError extends SousaError {
|
|
71
|
+
constructor(message: string);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export { AuthorizationError, type AuthorizationUrlOptions, SimpleLogin, type SimpleLoginConfig, SousaError, TokenError, type TokenResponse, type UserInfo };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
interface SimpleLoginConfig {
|
|
2
|
+
clientId: string;
|
|
3
|
+
clientSecret: string;
|
|
4
|
+
redirectUri: string;
|
|
5
|
+
}
|
|
6
|
+
interface AuthorizationUrlOptions {
|
|
7
|
+
state?: string;
|
|
8
|
+
scopes?: string[];
|
|
9
|
+
}
|
|
10
|
+
interface TokenResponse {
|
|
11
|
+
access_token: string;
|
|
12
|
+
refresh_token: string;
|
|
13
|
+
token_type: string;
|
|
14
|
+
expires_in: number;
|
|
15
|
+
}
|
|
16
|
+
interface UserInfo {
|
|
17
|
+
sub: string;
|
|
18
|
+
id: string;
|
|
19
|
+
email: string;
|
|
20
|
+
email_verified: boolean;
|
|
21
|
+
name: string;
|
|
22
|
+
picture?: string;
|
|
23
|
+
updated_at: number;
|
|
24
|
+
application_id: string;
|
|
25
|
+
application: {
|
|
26
|
+
id: string;
|
|
27
|
+
name: string;
|
|
28
|
+
slug: string;
|
|
29
|
+
logo_url?: string;
|
|
30
|
+
};
|
|
31
|
+
organization?: {
|
|
32
|
+
id: string;
|
|
33
|
+
name: string;
|
|
34
|
+
logo_url?: string;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
declare class SimpleLogin {
|
|
39
|
+
private clientId;
|
|
40
|
+
private clientSecret;
|
|
41
|
+
private redirectUri;
|
|
42
|
+
private baseUrl;
|
|
43
|
+
constructor(config: SimpleLoginConfig);
|
|
44
|
+
/**
|
|
45
|
+
* Generate the authorization URL to redirect users for sign-in
|
|
46
|
+
*/
|
|
47
|
+
getAuthorizationUrl(options?: AuthorizationUrlOptions): string;
|
|
48
|
+
/**
|
|
49
|
+
* Exchange an authorization code for access and refresh tokens
|
|
50
|
+
*/
|
|
51
|
+
exchangeCode(code: string): Promise<TokenResponse>;
|
|
52
|
+
/**
|
|
53
|
+
* Refresh an access token using a refresh token
|
|
54
|
+
*/
|
|
55
|
+
refreshToken(refreshToken: string): Promise<TokenResponse>;
|
|
56
|
+
/**
|
|
57
|
+
* Get user information using an access token
|
|
58
|
+
*/
|
|
59
|
+
getUserInfo(accessToken: string): Promise<UserInfo>;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
declare class SousaError extends Error {
|
|
63
|
+
code: string;
|
|
64
|
+
statusCode?: number | undefined;
|
|
65
|
+
constructor(message: string, code: string, statusCode?: number | undefined);
|
|
66
|
+
}
|
|
67
|
+
declare class AuthorizationError extends SousaError {
|
|
68
|
+
constructor(message: string);
|
|
69
|
+
}
|
|
70
|
+
declare class TokenError extends SousaError {
|
|
71
|
+
constructor(message: string);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export { AuthorizationError, type AuthorizationUrlOptions, SimpleLogin, type SimpleLoginConfig, SousaError, TokenError, type TokenResponse, type UserInfo };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// src/errors.ts
|
|
2
|
+
var SousaError = class extends Error {
|
|
3
|
+
constructor(message, code, statusCode) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.code = code;
|
|
6
|
+
this.statusCode = statusCode;
|
|
7
|
+
this.name = "SousaError";
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
var AuthorizationError = class extends SousaError {
|
|
11
|
+
constructor(message) {
|
|
12
|
+
super(message, "AUTHORIZATION_ERROR", 401);
|
|
13
|
+
this.name = "AuthorizationError";
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
var TokenError = class extends SousaError {
|
|
17
|
+
constructor(message) {
|
|
18
|
+
super(message, "TOKEN_ERROR", 400);
|
|
19
|
+
this.name = "TokenError";
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// src/client.ts
|
|
24
|
+
var BASE_URL = "https://app.simple-login.com";
|
|
25
|
+
var SimpleLogin = class {
|
|
26
|
+
clientId;
|
|
27
|
+
clientSecret;
|
|
28
|
+
redirectUri;
|
|
29
|
+
baseUrl;
|
|
30
|
+
constructor(config) {
|
|
31
|
+
this.clientId = config.clientId;
|
|
32
|
+
this.clientSecret = config.clientSecret;
|
|
33
|
+
this.redirectUri = config.redirectUri;
|
|
34
|
+
this.baseUrl = BASE_URL;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Generate the authorization URL to redirect users for sign-in
|
|
38
|
+
*/
|
|
39
|
+
getAuthorizationUrl(options = {}) {
|
|
40
|
+
const params = new URLSearchParams({
|
|
41
|
+
client_id: this.clientId,
|
|
42
|
+
redirect_uri: this.redirectUri,
|
|
43
|
+
response_type: "code"
|
|
44
|
+
});
|
|
45
|
+
if (options.state) {
|
|
46
|
+
params.set("state", options.state);
|
|
47
|
+
}
|
|
48
|
+
if (options.scopes?.length) {
|
|
49
|
+
params.set("scope", options.scopes.join(" "));
|
|
50
|
+
}
|
|
51
|
+
return `${this.baseUrl}/v1/auth/authorize?${params.toString()}`;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Exchange an authorization code for access and refresh tokens
|
|
55
|
+
*/
|
|
56
|
+
async exchangeCode(code) {
|
|
57
|
+
const response = await fetch(`${this.baseUrl}/v1/auth/token`, {
|
|
58
|
+
method: "POST",
|
|
59
|
+
headers: {
|
|
60
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
61
|
+
},
|
|
62
|
+
body: new URLSearchParams({
|
|
63
|
+
grant_type: "authorization_code",
|
|
64
|
+
client_id: this.clientId,
|
|
65
|
+
client_secret: this.clientSecret,
|
|
66
|
+
redirect_uri: this.redirectUri,
|
|
67
|
+
code
|
|
68
|
+
})
|
|
69
|
+
});
|
|
70
|
+
if (!response.ok) {
|
|
71
|
+
const error = await response.json().catch(() => ({}));
|
|
72
|
+
throw new TokenError(error.error_description || "Failed to exchange authorization code");
|
|
73
|
+
}
|
|
74
|
+
return response.json();
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Refresh an access token using a refresh token
|
|
78
|
+
*/
|
|
79
|
+
async refreshToken(refreshToken) {
|
|
80
|
+
const response = await fetch(`${this.baseUrl}/v1/auth/token`, {
|
|
81
|
+
method: "POST",
|
|
82
|
+
headers: {
|
|
83
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
84
|
+
},
|
|
85
|
+
body: new URLSearchParams({
|
|
86
|
+
grant_type: "refresh_token",
|
|
87
|
+
client_id: this.clientId,
|
|
88
|
+
client_secret: this.clientSecret,
|
|
89
|
+
refresh_token: refreshToken
|
|
90
|
+
})
|
|
91
|
+
});
|
|
92
|
+
if (!response.ok) {
|
|
93
|
+
const error = await response.json().catch(() => ({}));
|
|
94
|
+
throw new TokenError(error.error_description || "Failed to refresh token");
|
|
95
|
+
}
|
|
96
|
+
return response.json();
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Get user information using an access token
|
|
100
|
+
*/
|
|
101
|
+
async getUserInfo(accessToken) {
|
|
102
|
+
const response = await fetch(`${this.baseUrl}/v1/auth/userinfo`, {
|
|
103
|
+
headers: {
|
|
104
|
+
Authorization: `Bearer ${accessToken}`
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
if (!response.ok) {
|
|
108
|
+
throw new AuthorizationError("Failed to fetch user info");
|
|
109
|
+
}
|
|
110
|
+
return response.json();
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
export {
|
|
114
|
+
AuthorizationError,
|
|
115
|
+
SimpleLogin,
|
|
116
|
+
SousaError,
|
|
117
|
+
TokenError
|
|
118
|
+
};
|
|
119
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/client.ts"],"sourcesContent":["export class SousaError extends Error {\n constructor(\n message: string,\n public code: string,\n public statusCode?: number\n ) {\n super(message);\n this.name = \"SousaError\";\n }\n}\n\nexport class AuthorizationError extends SousaError {\n constructor(message: string) {\n super(message, \"AUTHORIZATION_ERROR\", 401);\n this.name = \"AuthorizationError\";\n }\n}\n\nexport class TokenError extends SousaError {\n constructor(message: string) {\n super(message, \"TOKEN_ERROR\", 400);\n this.name = \"TokenError\";\n }\n}\n","import { AuthorizationError, TokenError } from './errors'\nimport type { AuthorizationUrlOptions, SimpleLoginConfig, TokenResponse, UserInfo } from './types'\n\ndeclare const __SIMPLELOGIN_BASE_URL__: string\n\nconst BASE_URL = __SIMPLELOGIN_BASE_URL__\n\nexport class SimpleLogin {\n private clientId: string\n private clientSecret: string\n private redirectUri: string\n private baseUrl: string\n\n constructor(config: SimpleLoginConfig) {\n this.clientId = config.clientId\n this.clientSecret = config.clientSecret\n this.redirectUri = config.redirectUri\n this.baseUrl = BASE_URL\n }\n\n /**\n * Generate the authorization URL to redirect users for sign-in\n */\n getAuthorizationUrl(options: AuthorizationUrlOptions = {}): string {\n const params = new URLSearchParams({\n client_id: this.clientId,\n redirect_uri: this.redirectUri,\n response_type: 'code',\n })\n\n if (options.state) {\n params.set('state', options.state)\n }\n\n if (options.scopes?.length) {\n params.set('scope', options.scopes.join(' '))\n }\n\n return `${this.baseUrl}/v1/auth/authorize?${params.toString()}`\n }\n\n /**\n * Exchange an authorization code for access and refresh tokens\n */\n async exchangeCode(code: string): Promise<TokenResponse> {\n const response = await fetch(`${this.baseUrl}/v1/auth/token`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n grant_type: 'authorization_code',\n client_id: this.clientId,\n client_secret: this.clientSecret,\n redirect_uri: this.redirectUri,\n code,\n }),\n })\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}))\n throw new TokenError(error.error_description || 'Failed to exchange authorization code')\n }\n\n return response.json()\n }\n\n /**\n * Refresh an access token using a refresh token\n */\n async refreshToken(refreshToken: string): Promise<TokenResponse> {\n const response = await fetch(`${this.baseUrl}/v1/auth/token`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n grant_type: 'refresh_token',\n client_id: this.clientId,\n client_secret: this.clientSecret,\n refresh_token: refreshToken,\n }),\n })\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}))\n throw new TokenError(error.error_description || 'Failed to refresh token')\n }\n\n return response.json()\n }\n\n /**\n * Get user information using an access token\n */\n async getUserInfo(accessToken: string): Promise<UserInfo> {\n const response = await fetch(`${this.baseUrl}/v1/auth/userinfo`, {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n },\n })\n\n if (!response.ok) {\n throw new AuthorizationError('Failed to fetch user info')\n }\n\n return response.json()\n }\n}\n"],"mappings":";AAAO,IAAM,aAAN,cAAyB,MAAM;AAAA,EACpC,YACE,SACO,MACA,YACP;AACA,UAAM,OAAO;AAHN;AACA;AAGP,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,qBAAN,cAAiC,WAAW;AAAA,EACjD,YAAY,SAAiB;AAC3B,UAAM,SAAS,uBAAuB,GAAG;AACzC,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,aAAN,cAAyB,WAAW;AAAA,EACzC,YAAY,SAAiB;AAC3B,UAAM,SAAS,eAAe,GAAG;AACjC,SAAK,OAAO;AAAA,EACd;AACF;;;AClBA,IAAM,WAAW;AAEV,IAAM,cAAN,MAAkB;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,QAA2B;AACrC,SAAK,WAAW,OAAO;AACvB,SAAK,eAAe,OAAO;AAC3B,SAAK,cAAc,OAAO;AAC1B,SAAK,UAAU;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA,EAKA,oBAAoB,UAAmC,CAAC,GAAW;AACjE,UAAM,SAAS,IAAI,gBAAgB;AAAA,MACjC,WAAW,KAAK;AAAA,MAChB,cAAc,KAAK;AAAA,MACnB,eAAe;AAAA,IACjB,CAAC;AAED,QAAI,QAAQ,OAAO;AACjB,aAAO,IAAI,SAAS,QAAQ,KAAK;AAAA,IACnC;AAEA,QAAI,QAAQ,QAAQ,QAAQ;AAC1B,aAAO,IAAI,SAAS,QAAQ,OAAO,KAAK,GAAG,CAAC;AAAA,IAC9C;AAEA,WAAO,GAAG,KAAK,OAAO,sBAAsB,OAAO,SAAS,CAAC;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,MAAsC;AACvD,UAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,kBAAkB;AAAA,MAC5D,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,IAAI,gBAAgB;AAAA,QACxB,YAAY;AAAA,QACZ,WAAW,KAAK;AAAA,QAChB,eAAe,KAAK;AAAA,QACpB,cAAc,KAAK;AAAA,QACnB;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,QAAQ,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AACpD,YAAM,IAAI,WAAW,MAAM,qBAAqB,uCAAuC;AAAA,IACzF;AAEA,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,cAA8C;AAC/D,UAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,kBAAkB;AAAA,MAC5D,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,IAAI,gBAAgB;AAAA,QACxB,YAAY;AAAA,QACZ,WAAW,KAAK;AAAA,QAChB,eAAe,KAAK;AAAA,QACpB,eAAe;AAAA,MACjB,CAAC;AAAA,IACH,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,QAAQ,MAAM,SAAS,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AACpD,YAAM,IAAI,WAAW,MAAM,qBAAqB,yBAAyB;AAAA,IAC3E;AAEA,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAY,aAAwC;AACxD,UAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,qBAAqB;AAAA,MAC/D,SAAS;AAAA,QACP,eAAe,UAAU,WAAW;AAAA,MACtC;AAAA,IACF,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,mBAAmB,2BAA2B;AAAA,IAC1D;AAEA,WAAO,SAAS,KAAK;AAAA,EACvB;AACF;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@simple-login/sdk",
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "Official SDK for Simple Login",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/index.d.cts",
|
|
17
|
+
"default": "./dist/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "NODE_ENV=production tsup",
|
|
26
|
+
"dev": "tsup --watch",
|
|
27
|
+
"typecheck": "tsc --noEmit",
|
|
28
|
+
"prepublishOnly": "npm run build"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"sousa",
|
|
32
|
+
"oauth",
|
|
33
|
+
"authentication",
|
|
34
|
+
"sdk"
|
|
35
|
+
],
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/node": "^25.2.3",
|
|
39
|
+
"dotenv": "^17.2.4",
|
|
40
|
+
"tsup": "^8.0.0",
|
|
41
|
+
"typescript": "^5.3.0"
|
|
42
|
+
},
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=18.0.0"
|
|
45
|
+
}
|
|
46
|
+
}
|