@goodparty_org/sdk 1.0.0 → 1.2.0
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 +18 -9
- package/dist/index.d.mts +20 -2
- package/dist/index.d.ts +20 -2
- package/dist/index.js +93 -21
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +93 -21
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -28,14 +28,23 @@ const filtered = await client.users.list({
|
|
|
28
28
|
sortOrder: 'desc',
|
|
29
29
|
})
|
|
30
30
|
|
|
31
|
+
const updatedUser = await client.users.update(1, {
|
|
32
|
+
firstName: 'Jane',
|
|
33
|
+
roles: ['candidate'],
|
|
34
|
+
})
|
|
35
|
+
|
|
31
36
|
await client.users.updatePassword(1, {
|
|
32
37
|
oldPassword: 'old',
|
|
33
38
|
newPassword: 'new',
|
|
34
39
|
})
|
|
35
40
|
|
|
36
41
|
await client.users.delete(1)
|
|
42
|
+
|
|
43
|
+
client.destroy()
|
|
37
44
|
```
|
|
38
45
|
|
|
46
|
+
The `destroy()` method cleans up internal token renewal timers. Call it when you are done using the client to prevent leaked timers.
|
|
47
|
+
|
|
39
48
|
All methods throw `SdkError` on failure:
|
|
40
49
|
|
|
41
50
|
```typescript
|
|
@@ -62,15 +71,15 @@ npm install
|
|
|
62
71
|
|
|
63
72
|
### Scripts
|
|
64
73
|
|
|
65
|
-
| Command
|
|
66
|
-
|
|
|
67
|
-
| `npm run dev`
|
|
68
|
-
| `npm run build`
|
|
69
|
-
| `npm run typecheck`
|
|
70
|
-
| `npm run lint`
|
|
71
|
-
| `npm run lint:fix`
|
|
72
|
-
| `npm run format`
|
|
73
|
-
| `npm run format:check` | Check code formatting
|
|
74
|
+
| Command | Description |
|
|
75
|
+
| ---------------------- | --------------------------------- |
|
|
76
|
+
| `npm run dev` | Build in watch mode for local dev |
|
|
77
|
+
| `npm run build` | Build the SDK with tsup |
|
|
78
|
+
| `npm run typecheck` | Run TypeScript type checking |
|
|
79
|
+
| `npm run lint` | Run ESLint |
|
|
80
|
+
| `npm run lint:fix` | Run ESLint with auto-fix |
|
|
81
|
+
| `npm run format` | Format code with Prettier |
|
|
82
|
+
| `npm run format:check` | Check code formatting |
|
|
74
83
|
|
|
75
84
|
### Publishing
|
|
76
85
|
|
package/dist/index.d.mts
CHANGED
|
@@ -34,6 +34,10 @@ declare enum WhyBrowsing {
|
|
|
34
34
|
test = "test",
|
|
35
35
|
else = "else"
|
|
36
36
|
}
|
|
37
|
+
declare enum SIGN_UP_MODE {
|
|
38
|
+
CANDIDATE = "candidate",
|
|
39
|
+
FACILITATED = "facilitated"
|
|
40
|
+
}
|
|
37
41
|
type UserMetaData = {
|
|
38
42
|
customerId?: string;
|
|
39
43
|
checkoutSessionId?: string | null;
|
|
@@ -65,6 +69,17 @@ type ListUsersOptions = PaginationOptions & {
|
|
|
65
69
|
lastName?: string;
|
|
66
70
|
email?: string;
|
|
67
71
|
};
|
|
72
|
+
type UpdateUserInput = {
|
|
73
|
+
firstName?: string;
|
|
74
|
+
lastName?: string;
|
|
75
|
+
email?: string;
|
|
76
|
+
name?: string;
|
|
77
|
+
zip?: string;
|
|
78
|
+
phone?: string;
|
|
79
|
+
roles?: UserRole[];
|
|
80
|
+
signUpMode?: SIGN_UP_MODE;
|
|
81
|
+
allowTexts?: boolean;
|
|
82
|
+
};
|
|
68
83
|
type UpdatePasswordInput = {
|
|
69
84
|
oldPassword?: string;
|
|
70
85
|
newPassword: string;
|
|
@@ -73,8 +88,8 @@ type UpdatePasswordInput = {
|
|
|
73
88
|
type OfetchRequestBody = FetchOptions<'json'>['body'];
|
|
74
89
|
declare class HttpClient {
|
|
75
90
|
private baseUrl;
|
|
76
|
-
private
|
|
77
|
-
constructor(gpApiRootUrl: string,
|
|
91
|
+
private getToken;
|
|
92
|
+
constructor(gpApiRootUrl: string, getToken: () => Promise<string>);
|
|
78
93
|
request: <T>(path: string, init?: FetchOptions<"json">) => Promise<T>;
|
|
79
94
|
}
|
|
80
95
|
|
|
@@ -90,6 +105,7 @@ declare abstract class BaseResource {
|
|
|
90
105
|
declare class UsersResource extends BaseResource {
|
|
91
106
|
list: (options?: ListUsersOptions) => Promise<PaginatedList<User>>;
|
|
92
107
|
get: (id: number) => Promise<User>;
|
|
108
|
+
update: (id: number, input: UpdateUserInput) => Promise<User>;
|
|
93
109
|
delete: (id: number) => Promise<void>;
|
|
94
110
|
updatePassword: (id: number, input: UpdatePasswordInput) => Promise<void>;
|
|
95
111
|
}
|
|
@@ -100,8 +116,10 @@ type GoodPartyClientConfig = {
|
|
|
100
116
|
};
|
|
101
117
|
declare class GoodPartyClient {
|
|
102
118
|
readonly users: UsersResource;
|
|
119
|
+
private clerkService;
|
|
103
120
|
private constructor();
|
|
104
121
|
static create: (config: GoodPartyClientConfig) => Promise<GoodPartyClient>;
|
|
122
|
+
destroy: () => void;
|
|
105
123
|
}
|
|
106
124
|
|
|
107
125
|
export { GoodPartyClient, type GoodPartyClientConfig, type ListUsersOptions, type PaginatedList, type PaginationMeta, type PaginationOptions, SdkError, type UpdatePasswordInput, type User, type UserMetaData, UserRole, WhyBrowsing };
|
package/dist/index.d.ts
CHANGED
|
@@ -34,6 +34,10 @@ declare enum WhyBrowsing {
|
|
|
34
34
|
test = "test",
|
|
35
35
|
else = "else"
|
|
36
36
|
}
|
|
37
|
+
declare enum SIGN_UP_MODE {
|
|
38
|
+
CANDIDATE = "candidate",
|
|
39
|
+
FACILITATED = "facilitated"
|
|
40
|
+
}
|
|
37
41
|
type UserMetaData = {
|
|
38
42
|
customerId?: string;
|
|
39
43
|
checkoutSessionId?: string | null;
|
|
@@ -65,6 +69,17 @@ type ListUsersOptions = PaginationOptions & {
|
|
|
65
69
|
lastName?: string;
|
|
66
70
|
email?: string;
|
|
67
71
|
};
|
|
72
|
+
type UpdateUserInput = {
|
|
73
|
+
firstName?: string;
|
|
74
|
+
lastName?: string;
|
|
75
|
+
email?: string;
|
|
76
|
+
name?: string;
|
|
77
|
+
zip?: string;
|
|
78
|
+
phone?: string;
|
|
79
|
+
roles?: UserRole[];
|
|
80
|
+
signUpMode?: SIGN_UP_MODE;
|
|
81
|
+
allowTexts?: boolean;
|
|
82
|
+
};
|
|
68
83
|
type UpdatePasswordInput = {
|
|
69
84
|
oldPassword?: string;
|
|
70
85
|
newPassword: string;
|
|
@@ -73,8 +88,8 @@ type UpdatePasswordInput = {
|
|
|
73
88
|
type OfetchRequestBody = FetchOptions<'json'>['body'];
|
|
74
89
|
declare class HttpClient {
|
|
75
90
|
private baseUrl;
|
|
76
|
-
private
|
|
77
|
-
constructor(gpApiRootUrl: string,
|
|
91
|
+
private getToken;
|
|
92
|
+
constructor(gpApiRootUrl: string, getToken: () => Promise<string>);
|
|
78
93
|
request: <T>(path: string, init?: FetchOptions<"json">) => Promise<T>;
|
|
79
94
|
}
|
|
80
95
|
|
|
@@ -90,6 +105,7 @@ declare abstract class BaseResource {
|
|
|
90
105
|
declare class UsersResource extends BaseResource {
|
|
91
106
|
list: (options?: ListUsersOptions) => Promise<PaginatedList<User>>;
|
|
92
107
|
get: (id: number) => Promise<User>;
|
|
108
|
+
update: (id: number, input: UpdateUserInput) => Promise<User>;
|
|
93
109
|
delete: (id: number) => Promise<void>;
|
|
94
110
|
updatePassword: (id: number, input: UpdatePasswordInput) => Promise<void>;
|
|
95
111
|
}
|
|
@@ -100,8 +116,10 @@ type GoodPartyClientConfig = {
|
|
|
100
116
|
};
|
|
101
117
|
declare class GoodPartyClient {
|
|
102
118
|
readonly users: UsersResource;
|
|
119
|
+
private clerkService;
|
|
103
120
|
private constructor();
|
|
104
121
|
static create: (config: GoodPartyClientConfig) => Promise<GoodPartyClient>;
|
|
122
|
+
destroy: () => void;
|
|
105
123
|
}
|
|
106
124
|
|
|
107
125
|
export { GoodPartyClient, type GoodPartyClientConfig, type ListUsersOptions, type PaginatedList, type PaginationMeta, type PaginationOptions, SdkError, type UpdatePasswordInput, type User, type UserMetaData, UserRole, WhyBrowsing };
|
package/dist/index.js
CHANGED
|
@@ -27,9 +27,6 @@ __export(index_exports, {
|
|
|
27
27
|
});
|
|
28
28
|
module.exports = __toCommonJS(index_exports);
|
|
29
29
|
|
|
30
|
-
// src/GoodPartyClient.ts
|
|
31
|
-
var import_backend = require("@clerk/backend");
|
|
32
|
-
|
|
33
30
|
// src/http/HttpClient.ts
|
|
34
31
|
var import_ofetch = require("ofetch");
|
|
35
32
|
|
|
@@ -48,17 +45,17 @@ var SdkError = class extends Error {
|
|
|
48
45
|
// src/http/HttpClient.ts
|
|
49
46
|
var HttpClient = class {
|
|
50
47
|
baseUrl;
|
|
51
|
-
|
|
52
|
-
constructor(gpApiRootUrl,
|
|
48
|
+
getToken;
|
|
49
|
+
constructor(gpApiRootUrl, getToken) {
|
|
53
50
|
this.baseUrl = gpApiRootUrl;
|
|
54
|
-
this.
|
|
51
|
+
this.getToken = getToken;
|
|
55
52
|
}
|
|
56
53
|
request = async (path, init) => {
|
|
57
54
|
try {
|
|
58
55
|
return await (0, import_ofetch.ofetch)(path, {
|
|
59
56
|
baseURL: this.baseUrl,
|
|
60
57
|
headers: {
|
|
61
|
-
Authorization: `Bearer ${this.
|
|
58
|
+
Authorization: `Bearer ${await this.getToken()}`,
|
|
62
59
|
...init?.headers ?? {}
|
|
63
60
|
},
|
|
64
61
|
...init
|
|
@@ -89,24 +86,61 @@ var BaseResource = class {
|
|
|
89
86
|
var UsersResource = class extends BaseResource {
|
|
90
87
|
list = (options) => this.getRequest("/users", options);
|
|
91
88
|
get = (id) => this.getRequest(`/users/${id}`);
|
|
89
|
+
update = (id, input) => this.putRequest(`/users/${id}`, input);
|
|
92
90
|
delete = (id) => this.deleteRequest(`/users/${id}`);
|
|
93
91
|
updatePassword = (id, input) => this.putRequest(`/users/${id}/password`, input);
|
|
94
92
|
};
|
|
95
93
|
|
|
96
|
-
// src/
|
|
97
|
-
var
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
94
|
+
// src/vendor/clerk/clerk.service.ts
|
|
95
|
+
var import_backend = require("@clerk/backend");
|
|
96
|
+
var TOKEN_RENEWAL_BUFFER_MS = 3e4;
|
|
97
|
+
var ClerkService = class {
|
|
98
|
+
m2mSecret;
|
|
99
|
+
clerkClient;
|
|
100
|
+
cachedToken = null;
|
|
101
|
+
tokenExpiration = null;
|
|
102
|
+
renewalTimer = null;
|
|
103
|
+
pendingTokenPromise = null;
|
|
104
|
+
destroyed = false;
|
|
105
|
+
constructor(m2mSecret) {
|
|
106
|
+
this.m2mSecret = m2mSecret;
|
|
107
|
+
this.clerkClient = (0, import_backend.createClerkClient)({});
|
|
102
108
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
109
|
+
getToken = async () => {
|
|
110
|
+
if (this.cachedToken && this.isTokenValid()) {
|
|
111
|
+
return this.cachedToken;
|
|
112
|
+
}
|
|
113
|
+
if (this.pendingTokenPromise) {
|
|
114
|
+
return this.pendingTokenPromise;
|
|
115
|
+
}
|
|
116
|
+
const promise = this.createAndCacheToken();
|
|
117
|
+
this.pendingTokenPromise = promise;
|
|
107
118
|
try {
|
|
108
|
-
|
|
109
|
-
|
|
119
|
+
return await promise;
|
|
120
|
+
} finally {
|
|
121
|
+
if (this.pendingTokenPromise === promise) {
|
|
122
|
+
this.pendingTokenPromise = null;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
destroy = () => {
|
|
127
|
+
this.destroyed = true;
|
|
128
|
+
if (this.renewalTimer) {
|
|
129
|
+
clearTimeout(this.renewalTimer);
|
|
130
|
+
this.renewalTimer = null;
|
|
131
|
+
}
|
|
132
|
+
this.cachedToken = null;
|
|
133
|
+
this.tokenExpiration = null;
|
|
134
|
+
this.pendingTokenPromise = null;
|
|
135
|
+
};
|
|
136
|
+
isTokenValid = () => {
|
|
137
|
+
if (!this.tokenExpiration) return true;
|
|
138
|
+
return Date.now() < this.tokenExpiration - TOKEN_RENEWAL_BUFFER_MS;
|
|
139
|
+
};
|
|
140
|
+
createAndCacheToken = async () => {
|
|
141
|
+
try {
|
|
142
|
+
const m2mToken = await this.clerkClient.m2m.createToken({
|
|
143
|
+
machineSecretKey: this.m2mSecret
|
|
110
144
|
});
|
|
111
145
|
if (!m2mToken.token) {
|
|
112
146
|
throw new SdkError(
|
|
@@ -114,7 +148,11 @@ var GoodPartyClient = class _GoodPartyClient {
|
|
|
114
148
|
"Clerk M2M token creation succeeded but returned no token string"
|
|
115
149
|
);
|
|
116
150
|
}
|
|
117
|
-
|
|
151
|
+
if (this.destroyed) return m2mToken.token;
|
|
152
|
+
this.cachedToken = m2mToken.token;
|
|
153
|
+
this.tokenExpiration = m2mToken.expiration;
|
|
154
|
+
this.scheduleRenewal();
|
|
155
|
+
return this.cachedToken;
|
|
118
156
|
} catch (error) {
|
|
119
157
|
if (error instanceof SdkError) {
|
|
120
158
|
throw error;
|
|
@@ -122,7 +160,41 @@ var GoodPartyClient = class _GoodPartyClient {
|
|
|
122
160
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
123
161
|
throw new SdkError(0, `Failed to create Clerk M2M token: ${message}`);
|
|
124
162
|
}
|
|
125
|
-
|
|
163
|
+
};
|
|
164
|
+
scheduleRenewal = () => {
|
|
165
|
+
if (this.renewalTimer) {
|
|
166
|
+
clearTimeout(this.renewalTimer);
|
|
167
|
+
this.renewalTimer = null;
|
|
168
|
+
}
|
|
169
|
+
if (!this.tokenExpiration) return;
|
|
170
|
+
const timeUntilRenewal = this.tokenExpiration - Date.now() - TOKEN_RENEWAL_BUFFER_MS;
|
|
171
|
+
if (timeUntilRenewal <= 0) return;
|
|
172
|
+
this.renewalTimer = setTimeout(() => {
|
|
173
|
+
this.cachedToken = null;
|
|
174
|
+
this.getToken().catch((error) => {
|
|
175
|
+
console.error("Proactive M2M token renewal failed:", error);
|
|
176
|
+
});
|
|
177
|
+
}, timeUntilRenewal);
|
|
178
|
+
};
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
// src/GoodPartyClient.ts
|
|
182
|
+
var GoodPartyClient = class _GoodPartyClient {
|
|
183
|
+
users;
|
|
184
|
+
clerkService;
|
|
185
|
+
constructor(clerkService, gpApiRootUrl) {
|
|
186
|
+
this.clerkService = clerkService;
|
|
187
|
+
const httpClient = new HttpClient(gpApiRootUrl, clerkService.getToken);
|
|
188
|
+
this.users = new UsersResource(httpClient);
|
|
189
|
+
}
|
|
190
|
+
static create = async (config) => {
|
|
191
|
+
const { m2mSecret, gpApiRootUrl } = config;
|
|
192
|
+
const clerkService = new ClerkService(m2mSecret);
|
|
193
|
+
await clerkService.getToken();
|
|
194
|
+
return new _GoodPartyClient(clerkService, gpApiRootUrl);
|
|
195
|
+
};
|
|
196
|
+
destroy = () => {
|
|
197
|
+
this.clerkService.destroy();
|
|
126
198
|
};
|
|
127
199
|
};
|
|
128
200
|
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/GoodPartyClient.ts","../src/http/HttpClient.ts","../src/types/result.ts","../src/resources/BaseResource.ts","../src/resources/UsersResource.ts","../src/types/user.ts"],"sourcesContent":["export { GoodPartyClient } from './GoodPartyClient'\nexport type { GoodPartyClientConfig } from './GoodPartyClient'\n\nexport { SdkError } from './types/result'\nexport type {\n PaginationOptions,\n PaginationMeta,\n PaginatedList,\n} from './types/result'\n\nexport type {\n User,\n UserMetaData,\n ListUsersOptions,\n UpdatePasswordInput,\n} from './types/user'\n\nexport { UserRole, WhyBrowsing } from './types/user'\n","import { createClerkClient } from '@clerk/backend'\nimport { HttpClient } from './http/HttpClient'\nimport { UsersResource } from './resources/UsersResource'\nimport { SdkError } from './types/result'\n\nexport type GoodPartyClientConfig = {\n m2mSecret: string\n gpApiRootUrl: string\n}\n\nexport class GoodPartyClient {\n readonly users: UsersResource\n\n private constructor(gpApiRootUrl: string, m2mToken: string) {\n const httpClient = new HttpClient(gpApiRootUrl, m2mToken)\n this.users = new UsersResource(httpClient)\n }\n\n static create = async (\n config: GoodPartyClientConfig,\n ): Promise<GoodPartyClient> => {\n const { m2mSecret, gpApiRootUrl } = config\n const clerkClient = createClerkClient({})\n\n let token: string\n try {\n const m2mToken = await clerkClient.m2m.createToken({\n machineSecretKey: m2mSecret,\n })\n if (!m2mToken.token) {\n throw new SdkError(\n 0,\n 'Clerk M2M token creation succeeded but returned no token string',\n )\n }\n token = m2mToken.token\n } catch (error: unknown) {\n if (error instanceof SdkError) {\n throw error\n }\n const message = error instanceof Error ? error.message : 'Unknown error'\n throw new SdkError(0, `Failed to create Clerk M2M token: ${message}`)\n }\n\n return new GoodPartyClient(gpApiRootUrl, token)\n }\n}\n","import { ofetch, FetchError, FetchOptions } from 'ofetch'\nimport { SdkError } from '../types/result'\n\nexport type OfetchRequestBody = FetchOptions<'json'>['body']\n\nexport class HttpClient {\n private baseUrl: string\n private m2mToken: string\n\n constructor(gpApiRootUrl: string, m2mToken: string) {\n this.baseUrl = gpApiRootUrl\n this.m2mToken = m2mToken\n }\n\n request = async <T>(\n path: string,\n init?: FetchOptions<'json'>,\n ): Promise<T> => {\n try {\n return await ofetch<T>(path, {\n baseURL: this.baseUrl,\n headers: {\n Authorization: `Bearer ${this.m2mToken}`,\n ...(init?.headers ?? {}),\n },\n ...init,\n })\n } catch (error: unknown) {\n if (error instanceof FetchError) {\n throw new SdkError(error.statusCode ?? 0, error.message, error.response)\n }\n const message = error instanceof Error ? error.message : 'Unknown error'\n throw new SdkError(0, message)\n }\n }\n}\n","export class SdkError extends Error {\n readonly status: number\n readonly response?: Response\n\n constructor(status: number, message: string, response?: Response) {\n super(message)\n this.name = 'SdkError'\n this.status = status\n this.response = response\n }\n}\n\nexport type PaginationOptions = {\n offset?: number\n limit?: number\n sortBy?: string\n sortOrder?: 'asc' | 'desc'\n}\n\nexport type PaginationMeta = {\n total: number\n offset: number\n limit: number\n}\n\nexport type PaginatedList<T> = {\n data: T[]\n meta: PaginationMeta\n}\n","import type { FetchOptions } from 'ofetch'\nimport type { HttpClient, OfetchRequestBody } from '../http/HttpClient'\n\nexport abstract class BaseResource {\n protected httpClient: HttpClient\n\n constructor(httpClient: HttpClient) {\n this.httpClient = httpClient\n }\n\n protected getRequest = <T>(\n path: string,\n query?: FetchOptions<'json'>['query'],\n ): Promise<T> => this.httpClient.request<T>(path, { method: 'GET', query })\n\n protected postRequest = <T>(\n path: string,\n body: OfetchRequestBody,\n ): Promise<T> => this.httpClient.request<T>(path, { method: 'POST', body })\n\n protected putRequest = <T>(\n path: string,\n body: OfetchRequestBody,\n ): Promise<T> => this.httpClient.request<T>(path, { method: 'PUT', body })\n\n protected deleteRequest = <T>(path: string): Promise<T> =>\n this.httpClient.request<T>(path, { method: 'DELETE' })\n}\n","import type { PaginatedList } from '../types/result'\nimport type { ListUsersOptions, UpdatePasswordInput, User } from '../types/user'\nimport { BaseResource } from './BaseResource'\n\nexport class UsersResource extends BaseResource {\n list = (options?: ListUsersOptions): Promise<PaginatedList<User>> =>\n this.getRequest<PaginatedList<User>>('/users', options)\n\n get = (id: number): Promise<User> => this.getRequest<User>(`/users/${id}`)\n\n delete = (id: number): Promise<void> =>\n this.deleteRequest<void>(`/users/${id}`)\n\n updatePassword = (id: number, input: UpdatePasswordInput): Promise<void> =>\n this.putRequest<void>(`/users/${id}/password`, input)\n}\n","import type { PaginationOptions } from './result'\n\nexport enum UserRole {\n admin = 'admin',\n sales = 'sales',\n candidate = 'candidate',\n campaignManager = 'campaignManager',\n demo = 'demo',\n}\n\nexport enum WhyBrowsing {\n considering = 'considering',\n learning = 'learning',\n test = 'test',\n else = 'else',\n}\n\nexport type UserMetaData = {\n customerId?: string\n checkoutSessionId?: string | null\n accountType?: string | null\n lastVisited?: number\n sessionCount?: number\n isDeleted?: boolean\n fsUserId?: string\n whyBrowsing?: WhyBrowsing | null\n hubspotId?: string\n profile_updated_count?: number\n textNotifications?: boolean\n} | null\n\nexport type User = {\n id: number\n firstName: string\n lastName: string\n name?: string | null\n email: string\n phone?: string | null\n zip?: string | null\n avatar?: string | null\n hasPassword: boolean\n roles?: UserRole[]\n metaData?: UserMetaData\n}\n\nexport type ListUsersOptions = PaginationOptions & {\n firstName?: string\n lastName?: string\n email?: string\n}\n\nexport type UpdatePasswordInput = {\n oldPassword?: string\n newPassword: string\n}\n"],"mappings":"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","names":["UserRole","WhyBrowsing"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/http/HttpClient.ts","../src/types/result.ts","../src/resources/BaseResource.ts","../src/resources/UsersResource.ts","../src/vendor/clerk/clerk.service.ts","../src/GoodPartyClient.ts","../src/types/user.ts"],"sourcesContent":["export { GoodPartyClient } from './GoodPartyClient'\nexport type { GoodPartyClientConfig } from './GoodPartyClient'\n\nexport { SdkError } from './types/result'\nexport type {\n PaginationOptions,\n PaginationMeta,\n PaginatedList,\n} from './types/result'\n\nexport type {\n User,\n UserMetaData,\n ListUsersOptions,\n UpdatePasswordInput,\n} from './types/user'\n\nexport { UserRole, WhyBrowsing } from './types/user'\n","import { ofetch, FetchError, FetchOptions } from 'ofetch'\nimport { SdkError } from '../types/result'\n\nexport type OfetchRequestBody = FetchOptions<'json'>['body']\n\nexport class HttpClient {\n private baseUrl: string\n private getToken: () => Promise<string>\n\n constructor(gpApiRootUrl: string, getToken: () => Promise<string>) {\n this.baseUrl = gpApiRootUrl\n this.getToken = getToken\n }\n\n request = async <T>(\n path: string,\n init?: FetchOptions<'json'>,\n ): Promise<T> => {\n try {\n return await ofetch<T>(path, {\n baseURL: this.baseUrl,\n headers: {\n Authorization: `Bearer ${await this.getToken()}`,\n ...(init?.headers ?? {}),\n },\n ...init,\n })\n } catch (error: unknown) {\n if (error instanceof FetchError) {\n throw new SdkError(error.statusCode ?? 0, error.message, error.response)\n }\n const message = error instanceof Error ? error.message : 'Unknown error'\n throw new SdkError(0, message)\n }\n }\n}\n","export class SdkError extends Error {\n readonly status: number\n readonly response?: Response\n\n constructor(status: number, message: string, response?: Response) {\n super(message)\n this.name = 'SdkError'\n this.status = status\n this.response = response\n }\n}\n\nexport type PaginationOptions = {\n offset?: number\n limit?: number\n sortBy?: string\n sortOrder?: 'asc' | 'desc'\n}\n\nexport type PaginationMeta = {\n total: number\n offset: number\n limit: number\n}\n\nexport type PaginatedList<T> = {\n data: T[]\n meta: PaginationMeta\n}\n","import type { FetchOptions } from 'ofetch'\nimport type { HttpClient, OfetchRequestBody } from '../http/HttpClient'\n\nexport abstract class BaseResource {\n protected httpClient: HttpClient\n\n constructor(httpClient: HttpClient) {\n this.httpClient = httpClient\n }\n\n protected getRequest = <T>(\n path: string,\n query?: FetchOptions<'json'>['query'],\n ): Promise<T> => this.httpClient.request<T>(path, { method: 'GET', query })\n\n protected postRequest = <T>(\n path: string,\n body: OfetchRequestBody,\n ): Promise<T> => this.httpClient.request<T>(path, { method: 'POST', body })\n\n protected putRequest = <T>(\n path: string,\n body: OfetchRequestBody,\n ): Promise<T> => this.httpClient.request<T>(path, { method: 'PUT', body })\n\n protected deleteRequest = <T>(path: string): Promise<T> =>\n this.httpClient.request<T>(path, { method: 'DELETE' })\n}\n","import type { PaginatedList } from '../types/result'\nimport type {\n ListUsersOptions,\n UpdatePasswordInput,\n UpdateUserInput,\n User,\n} from '../types/user'\nimport { BaseResource } from './BaseResource'\n\nexport class UsersResource extends BaseResource {\n list = (options?: ListUsersOptions): Promise<PaginatedList<User>> =>\n this.getRequest<PaginatedList<User>>('/users', options)\n\n get = (id: number): Promise<User> => this.getRequest<User>(`/users/${id}`)\n\n update = (id: number, input: UpdateUserInput): Promise<User> =>\n this.putRequest<User>(`/users/${id}`, input)\n\n delete = (id: number): Promise<void> =>\n this.deleteRequest<void>(`/users/${id}`)\n\n updatePassword = (id: number, input: UpdatePasswordInput): Promise<void> =>\n this.putRequest<void>(`/users/${id}/password`, input)\n}\n","import { createClerkClient } from '@clerk/backend'\nimport { SdkError } from '../../types/result'\n\nconst TOKEN_RENEWAL_BUFFER_MS = 30_000\n\nexport class ClerkService {\n private readonly m2mSecret: string\n private readonly clerkClient: ReturnType<typeof createClerkClient>\n private cachedToken: string | null = null\n private tokenExpiration: number | null = null\n private renewalTimer: ReturnType<typeof setTimeout> | null = null\n private pendingTokenPromise: Promise<string> | null = null\n private destroyed = false\n\n constructor(m2mSecret: string) {\n this.m2mSecret = m2mSecret\n this.clerkClient = createClerkClient({})\n }\n\n getToken = async (): Promise<string> => {\n if (this.cachedToken && this.isTokenValid()) {\n return this.cachedToken\n }\n\n if (this.pendingTokenPromise) {\n return this.pendingTokenPromise\n }\n\n const promise = this.createAndCacheToken()\n this.pendingTokenPromise = promise\n\n try {\n return await promise\n } finally {\n if (this.pendingTokenPromise === promise) {\n this.pendingTokenPromise = null\n }\n }\n }\n\n destroy = (): void => {\n this.destroyed = true\n if (this.renewalTimer) {\n clearTimeout(this.renewalTimer)\n this.renewalTimer = null\n }\n this.cachedToken = null\n this.tokenExpiration = null\n this.pendingTokenPromise = null\n }\n\n private isTokenValid = (): boolean => {\n if (!this.tokenExpiration) return true\n return Date.now() < this.tokenExpiration - TOKEN_RENEWAL_BUFFER_MS\n }\n\n private createAndCacheToken = async (): Promise<string> => {\n try {\n const m2mToken = await this.clerkClient.m2m.createToken({\n machineSecretKey: this.m2mSecret,\n })\n\n if (!m2mToken.token) {\n throw new SdkError(\n 0,\n 'Clerk M2M token creation succeeded but returned no token string',\n )\n }\n\n if (this.destroyed) return m2mToken.token\n\n this.cachedToken = m2mToken.token\n this.tokenExpiration = m2mToken.expiration\n this.scheduleRenewal()\n\n return this.cachedToken\n } catch (error: unknown) {\n if (error instanceof SdkError) {\n throw error\n }\n const message = error instanceof Error ? error.message : 'Unknown error'\n throw new SdkError(0, `Failed to create Clerk M2M token: ${message}`)\n }\n }\n\n private scheduleRenewal = (): void => {\n if (this.renewalTimer) {\n clearTimeout(this.renewalTimer)\n this.renewalTimer = null\n }\n\n if (!this.tokenExpiration) return\n\n const timeUntilRenewal =\n this.tokenExpiration - Date.now() - TOKEN_RENEWAL_BUFFER_MS\n\n if (timeUntilRenewal <= 0) return\n\n this.renewalTimer = setTimeout(() => {\n this.cachedToken = null\n this.getToken().catch((error: unknown) => {\n console.error('Proactive M2M token renewal failed:', error)\n })\n }, timeUntilRenewal)\n }\n}\n","import { HttpClient } from './http/HttpClient'\nimport { UsersResource } from './resources/UsersResource'\nimport { ClerkService } from './vendor/clerk/clerk.service'\n\nexport type GoodPartyClientConfig = {\n m2mSecret: string\n gpApiRootUrl: string\n}\n\nexport class GoodPartyClient {\n readonly users: UsersResource\n private clerkService: ClerkService\n\n private constructor(clerkService: ClerkService, gpApiRootUrl: string) {\n this.clerkService = clerkService\n const httpClient = new HttpClient(gpApiRootUrl, clerkService.getToken)\n this.users = new UsersResource(httpClient)\n }\n\n static create = async (\n config: GoodPartyClientConfig,\n ): Promise<GoodPartyClient> => {\n const { m2mSecret, gpApiRootUrl } = config\n const clerkService = new ClerkService(m2mSecret)\n await clerkService.getToken()\n return new GoodPartyClient(clerkService, gpApiRootUrl)\n }\n\n destroy = (): void => {\n this.clerkService.destroy()\n }\n}\n","import type { PaginationOptions } from './result'\n\nexport enum UserRole {\n admin = 'admin',\n sales = 'sales',\n candidate = 'candidate',\n campaignManager = 'campaignManager',\n demo = 'demo',\n}\n\nexport enum WhyBrowsing {\n considering = 'considering',\n learning = 'learning',\n test = 'test',\n else = 'else',\n}\n\nexport enum SIGN_UP_MODE {\n CANDIDATE = 'candidate',\n FACILITATED = 'facilitated',\n}\n\nexport type UserMetaData = {\n customerId?: string\n checkoutSessionId?: string | null\n accountType?: string | null\n lastVisited?: number\n sessionCount?: number\n isDeleted?: boolean\n fsUserId?: string\n whyBrowsing?: WhyBrowsing | null\n hubspotId?: string\n profile_updated_count?: number\n textNotifications?: boolean\n} | null\n\nexport type User = {\n id: number\n firstName: string\n lastName: string\n name?: string | null\n email: string\n phone?: string | null\n zip?: string | null\n avatar?: string | null\n hasPassword: boolean\n roles?: UserRole[]\n metaData?: UserMetaData\n}\n\nexport type ListUsersOptions = PaginationOptions & {\n firstName?: string\n lastName?: string\n email?: string\n}\n\nexport type UpdateUserInput = {\n firstName?: string\n lastName?: string\n email?: string\n name?: string\n zip?: string\n phone?: string\n roles?: UserRole[]\n signUpMode?: SIGN_UP_MODE\n allowTexts?: boolean\n}\n\nexport type UpdatePasswordInput = {\n oldPassword?: string\n newPassword: string\n}\n"],"mappings":"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","names":["UserRole","WhyBrowsing"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
// src/GoodPartyClient.ts
|
|
2
|
-
import { createClerkClient } from "@clerk/backend";
|
|
3
|
-
|
|
4
1
|
// src/http/HttpClient.ts
|
|
5
2
|
import { ofetch, FetchError } from "ofetch";
|
|
6
3
|
|
|
@@ -19,17 +16,17 @@ var SdkError = class extends Error {
|
|
|
19
16
|
// src/http/HttpClient.ts
|
|
20
17
|
var HttpClient = class {
|
|
21
18
|
baseUrl;
|
|
22
|
-
|
|
23
|
-
constructor(gpApiRootUrl,
|
|
19
|
+
getToken;
|
|
20
|
+
constructor(gpApiRootUrl, getToken) {
|
|
24
21
|
this.baseUrl = gpApiRootUrl;
|
|
25
|
-
this.
|
|
22
|
+
this.getToken = getToken;
|
|
26
23
|
}
|
|
27
24
|
request = async (path, init) => {
|
|
28
25
|
try {
|
|
29
26
|
return await ofetch(path, {
|
|
30
27
|
baseURL: this.baseUrl,
|
|
31
28
|
headers: {
|
|
32
|
-
Authorization: `Bearer ${this.
|
|
29
|
+
Authorization: `Bearer ${await this.getToken()}`,
|
|
33
30
|
...init?.headers ?? {}
|
|
34
31
|
},
|
|
35
32
|
...init
|
|
@@ -60,24 +57,61 @@ var BaseResource = class {
|
|
|
60
57
|
var UsersResource = class extends BaseResource {
|
|
61
58
|
list = (options) => this.getRequest("/users", options);
|
|
62
59
|
get = (id) => this.getRequest(`/users/${id}`);
|
|
60
|
+
update = (id, input) => this.putRequest(`/users/${id}`, input);
|
|
63
61
|
delete = (id) => this.deleteRequest(`/users/${id}`);
|
|
64
62
|
updatePassword = (id, input) => this.putRequest(`/users/${id}/password`, input);
|
|
65
63
|
};
|
|
66
64
|
|
|
67
|
-
// src/
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
65
|
+
// src/vendor/clerk/clerk.service.ts
|
|
66
|
+
import { createClerkClient } from "@clerk/backend";
|
|
67
|
+
var TOKEN_RENEWAL_BUFFER_MS = 3e4;
|
|
68
|
+
var ClerkService = class {
|
|
69
|
+
m2mSecret;
|
|
70
|
+
clerkClient;
|
|
71
|
+
cachedToken = null;
|
|
72
|
+
tokenExpiration = null;
|
|
73
|
+
renewalTimer = null;
|
|
74
|
+
pendingTokenPromise = null;
|
|
75
|
+
destroyed = false;
|
|
76
|
+
constructor(m2mSecret) {
|
|
77
|
+
this.m2mSecret = m2mSecret;
|
|
78
|
+
this.clerkClient = createClerkClient({});
|
|
73
79
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
80
|
+
getToken = async () => {
|
|
81
|
+
if (this.cachedToken && this.isTokenValid()) {
|
|
82
|
+
return this.cachedToken;
|
|
83
|
+
}
|
|
84
|
+
if (this.pendingTokenPromise) {
|
|
85
|
+
return this.pendingTokenPromise;
|
|
86
|
+
}
|
|
87
|
+
const promise = this.createAndCacheToken();
|
|
88
|
+
this.pendingTokenPromise = promise;
|
|
78
89
|
try {
|
|
79
|
-
|
|
80
|
-
|
|
90
|
+
return await promise;
|
|
91
|
+
} finally {
|
|
92
|
+
if (this.pendingTokenPromise === promise) {
|
|
93
|
+
this.pendingTokenPromise = null;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
destroy = () => {
|
|
98
|
+
this.destroyed = true;
|
|
99
|
+
if (this.renewalTimer) {
|
|
100
|
+
clearTimeout(this.renewalTimer);
|
|
101
|
+
this.renewalTimer = null;
|
|
102
|
+
}
|
|
103
|
+
this.cachedToken = null;
|
|
104
|
+
this.tokenExpiration = null;
|
|
105
|
+
this.pendingTokenPromise = null;
|
|
106
|
+
};
|
|
107
|
+
isTokenValid = () => {
|
|
108
|
+
if (!this.tokenExpiration) return true;
|
|
109
|
+
return Date.now() < this.tokenExpiration - TOKEN_RENEWAL_BUFFER_MS;
|
|
110
|
+
};
|
|
111
|
+
createAndCacheToken = async () => {
|
|
112
|
+
try {
|
|
113
|
+
const m2mToken = await this.clerkClient.m2m.createToken({
|
|
114
|
+
machineSecretKey: this.m2mSecret
|
|
81
115
|
});
|
|
82
116
|
if (!m2mToken.token) {
|
|
83
117
|
throw new SdkError(
|
|
@@ -85,7 +119,11 @@ var GoodPartyClient = class _GoodPartyClient {
|
|
|
85
119
|
"Clerk M2M token creation succeeded but returned no token string"
|
|
86
120
|
);
|
|
87
121
|
}
|
|
88
|
-
|
|
122
|
+
if (this.destroyed) return m2mToken.token;
|
|
123
|
+
this.cachedToken = m2mToken.token;
|
|
124
|
+
this.tokenExpiration = m2mToken.expiration;
|
|
125
|
+
this.scheduleRenewal();
|
|
126
|
+
return this.cachedToken;
|
|
89
127
|
} catch (error) {
|
|
90
128
|
if (error instanceof SdkError) {
|
|
91
129
|
throw error;
|
|
@@ -93,7 +131,41 @@ var GoodPartyClient = class _GoodPartyClient {
|
|
|
93
131
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
94
132
|
throw new SdkError(0, `Failed to create Clerk M2M token: ${message}`);
|
|
95
133
|
}
|
|
96
|
-
|
|
134
|
+
};
|
|
135
|
+
scheduleRenewal = () => {
|
|
136
|
+
if (this.renewalTimer) {
|
|
137
|
+
clearTimeout(this.renewalTimer);
|
|
138
|
+
this.renewalTimer = null;
|
|
139
|
+
}
|
|
140
|
+
if (!this.tokenExpiration) return;
|
|
141
|
+
const timeUntilRenewal = this.tokenExpiration - Date.now() - TOKEN_RENEWAL_BUFFER_MS;
|
|
142
|
+
if (timeUntilRenewal <= 0) return;
|
|
143
|
+
this.renewalTimer = setTimeout(() => {
|
|
144
|
+
this.cachedToken = null;
|
|
145
|
+
this.getToken().catch((error) => {
|
|
146
|
+
console.error("Proactive M2M token renewal failed:", error);
|
|
147
|
+
});
|
|
148
|
+
}, timeUntilRenewal);
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
// src/GoodPartyClient.ts
|
|
153
|
+
var GoodPartyClient = class _GoodPartyClient {
|
|
154
|
+
users;
|
|
155
|
+
clerkService;
|
|
156
|
+
constructor(clerkService, gpApiRootUrl) {
|
|
157
|
+
this.clerkService = clerkService;
|
|
158
|
+
const httpClient = new HttpClient(gpApiRootUrl, clerkService.getToken);
|
|
159
|
+
this.users = new UsersResource(httpClient);
|
|
160
|
+
}
|
|
161
|
+
static create = async (config) => {
|
|
162
|
+
const { m2mSecret, gpApiRootUrl } = config;
|
|
163
|
+
const clerkService = new ClerkService(m2mSecret);
|
|
164
|
+
await clerkService.getToken();
|
|
165
|
+
return new _GoodPartyClient(clerkService, gpApiRootUrl);
|
|
166
|
+
};
|
|
167
|
+
destroy = () => {
|
|
168
|
+
this.clerkService.destroy();
|
|
97
169
|
};
|
|
98
170
|
};
|
|
99
171
|
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/GoodPartyClient.ts","../src/http/HttpClient.ts","../src/types/result.ts","../src/resources/BaseResource.ts","../src/resources/UsersResource.ts","../src/types/user.ts"],"sourcesContent":["import { createClerkClient } from '@clerk/backend'\nimport { HttpClient } from './http/HttpClient'\nimport { UsersResource } from './resources/UsersResource'\nimport { SdkError } from './types/result'\n\nexport type GoodPartyClientConfig = {\n m2mSecret: string\n gpApiRootUrl: string\n}\n\nexport class GoodPartyClient {\n readonly users: UsersResource\n\n private constructor(gpApiRootUrl: string, m2mToken: string) {\n const httpClient = new HttpClient(gpApiRootUrl, m2mToken)\n this.users = new UsersResource(httpClient)\n }\n\n static create = async (\n config: GoodPartyClientConfig,\n ): Promise<GoodPartyClient> => {\n const { m2mSecret, gpApiRootUrl } = config\n const clerkClient = createClerkClient({})\n\n let token: string\n try {\n const m2mToken = await clerkClient.m2m.createToken({\n machineSecretKey: m2mSecret,\n })\n if (!m2mToken.token) {\n throw new SdkError(\n 0,\n 'Clerk M2M token creation succeeded but returned no token string',\n )\n }\n token = m2mToken.token\n } catch (error: unknown) {\n if (error instanceof SdkError) {\n throw error\n }\n const message = error instanceof Error ? error.message : 'Unknown error'\n throw new SdkError(0, `Failed to create Clerk M2M token: ${message}`)\n }\n\n return new GoodPartyClient(gpApiRootUrl, token)\n }\n}\n","import { ofetch, FetchError, FetchOptions } from 'ofetch'\nimport { SdkError } from '../types/result'\n\nexport type OfetchRequestBody = FetchOptions<'json'>['body']\n\nexport class HttpClient {\n private baseUrl: string\n private m2mToken: string\n\n constructor(gpApiRootUrl: string, m2mToken: string) {\n this.baseUrl = gpApiRootUrl\n this.m2mToken = m2mToken\n }\n\n request = async <T>(\n path: string,\n init?: FetchOptions<'json'>,\n ): Promise<T> => {\n try {\n return await ofetch<T>(path, {\n baseURL: this.baseUrl,\n headers: {\n Authorization: `Bearer ${this.m2mToken}`,\n ...(init?.headers ?? {}),\n },\n ...init,\n })\n } catch (error: unknown) {\n if (error instanceof FetchError) {\n throw new SdkError(error.statusCode ?? 0, error.message, error.response)\n }\n const message = error instanceof Error ? error.message : 'Unknown error'\n throw new SdkError(0, message)\n }\n }\n}\n","export class SdkError extends Error {\n readonly status: number\n readonly response?: Response\n\n constructor(status: number, message: string, response?: Response) {\n super(message)\n this.name = 'SdkError'\n this.status = status\n this.response = response\n }\n}\n\nexport type PaginationOptions = {\n offset?: number\n limit?: number\n sortBy?: string\n sortOrder?: 'asc' | 'desc'\n}\n\nexport type PaginationMeta = {\n total: number\n offset: number\n limit: number\n}\n\nexport type PaginatedList<T> = {\n data: T[]\n meta: PaginationMeta\n}\n","import type { FetchOptions } from 'ofetch'\nimport type { HttpClient, OfetchRequestBody } from '../http/HttpClient'\n\nexport abstract class BaseResource {\n protected httpClient: HttpClient\n\n constructor(httpClient: HttpClient) {\n this.httpClient = httpClient\n }\n\n protected getRequest = <T>(\n path: string,\n query?: FetchOptions<'json'>['query'],\n ): Promise<T> => this.httpClient.request<T>(path, { method: 'GET', query })\n\n protected postRequest = <T>(\n path: string,\n body: OfetchRequestBody,\n ): Promise<T> => this.httpClient.request<T>(path, { method: 'POST', body })\n\n protected putRequest = <T>(\n path: string,\n body: OfetchRequestBody,\n ): Promise<T> => this.httpClient.request<T>(path, { method: 'PUT', body })\n\n protected deleteRequest = <T>(path: string): Promise<T> =>\n this.httpClient.request<T>(path, { method: 'DELETE' })\n}\n","import type { PaginatedList } from '../types/result'\nimport type { ListUsersOptions, UpdatePasswordInput, User } from '../types/user'\nimport { BaseResource } from './BaseResource'\n\nexport class UsersResource extends BaseResource {\n list = (options?: ListUsersOptions): Promise<PaginatedList<User>> =>\n this.getRequest<PaginatedList<User>>('/users', options)\n\n get = (id: number): Promise<User> => this.getRequest<User>(`/users/${id}`)\n\n delete = (id: number): Promise<void> =>\n this.deleteRequest<void>(`/users/${id}`)\n\n updatePassword = (id: number, input: UpdatePasswordInput): Promise<void> =>\n this.putRequest<void>(`/users/${id}/password`, input)\n}\n","import type { PaginationOptions } from './result'\n\nexport enum UserRole {\n admin = 'admin',\n sales = 'sales',\n candidate = 'candidate',\n campaignManager = 'campaignManager',\n demo = 'demo',\n}\n\nexport enum WhyBrowsing {\n considering = 'considering',\n learning = 'learning',\n test = 'test',\n else = 'else',\n}\n\nexport type UserMetaData = {\n customerId?: string\n checkoutSessionId?: string | null\n accountType?: string | null\n lastVisited?: number\n sessionCount?: number\n isDeleted?: boolean\n fsUserId?: string\n whyBrowsing?: WhyBrowsing | null\n hubspotId?: string\n profile_updated_count?: number\n textNotifications?: boolean\n} | null\n\nexport type User = {\n id: number\n firstName: string\n lastName: string\n name?: string | null\n email: string\n phone?: string | null\n zip?: string | null\n avatar?: string | null\n hasPassword: boolean\n roles?: UserRole[]\n metaData?: UserMetaData\n}\n\nexport type ListUsersOptions = PaginationOptions & {\n firstName?: string\n lastName?: string\n email?: string\n}\n\nexport type UpdatePasswordInput = {\n oldPassword?: string\n newPassword: string\n}\n"],"mappings":"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","names":["UserRole","WhyBrowsing"]}
|
|
1
|
+
{"version":3,"sources":["../src/http/HttpClient.ts","../src/types/result.ts","../src/resources/BaseResource.ts","../src/resources/UsersResource.ts","../src/vendor/clerk/clerk.service.ts","../src/GoodPartyClient.ts","../src/types/user.ts"],"sourcesContent":["import { ofetch, FetchError, FetchOptions } from 'ofetch'\nimport { SdkError } from '../types/result'\n\nexport type OfetchRequestBody = FetchOptions<'json'>['body']\n\nexport class HttpClient {\n private baseUrl: string\n private getToken: () => Promise<string>\n\n constructor(gpApiRootUrl: string, getToken: () => Promise<string>) {\n this.baseUrl = gpApiRootUrl\n this.getToken = getToken\n }\n\n request = async <T>(\n path: string,\n init?: FetchOptions<'json'>,\n ): Promise<T> => {\n try {\n return await ofetch<T>(path, {\n baseURL: this.baseUrl,\n headers: {\n Authorization: `Bearer ${await this.getToken()}`,\n ...(init?.headers ?? {}),\n },\n ...init,\n })\n } catch (error: unknown) {\n if (error instanceof FetchError) {\n throw new SdkError(error.statusCode ?? 0, error.message, error.response)\n }\n const message = error instanceof Error ? error.message : 'Unknown error'\n throw new SdkError(0, message)\n }\n }\n}\n","export class SdkError extends Error {\n readonly status: number\n readonly response?: Response\n\n constructor(status: number, message: string, response?: Response) {\n super(message)\n this.name = 'SdkError'\n this.status = status\n this.response = response\n }\n}\n\nexport type PaginationOptions = {\n offset?: number\n limit?: number\n sortBy?: string\n sortOrder?: 'asc' | 'desc'\n}\n\nexport type PaginationMeta = {\n total: number\n offset: number\n limit: number\n}\n\nexport type PaginatedList<T> = {\n data: T[]\n meta: PaginationMeta\n}\n","import type { FetchOptions } from 'ofetch'\nimport type { HttpClient, OfetchRequestBody } from '../http/HttpClient'\n\nexport abstract class BaseResource {\n protected httpClient: HttpClient\n\n constructor(httpClient: HttpClient) {\n this.httpClient = httpClient\n }\n\n protected getRequest = <T>(\n path: string,\n query?: FetchOptions<'json'>['query'],\n ): Promise<T> => this.httpClient.request<T>(path, { method: 'GET', query })\n\n protected postRequest = <T>(\n path: string,\n body: OfetchRequestBody,\n ): Promise<T> => this.httpClient.request<T>(path, { method: 'POST', body })\n\n protected putRequest = <T>(\n path: string,\n body: OfetchRequestBody,\n ): Promise<T> => this.httpClient.request<T>(path, { method: 'PUT', body })\n\n protected deleteRequest = <T>(path: string): Promise<T> =>\n this.httpClient.request<T>(path, { method: 'DELETE' })\n}\n","import type { PaginatedList } from '../types/result'\nimport type {\n ListUsersOptions,\n UpdatePasswordInput,\n UpdateUserInput,\n User,\n} from '../types/user'\nimport { BaseResource } from './BaseResource'\n\nexport class UsersResource extends BaseResource {\n list = (options?: ListUsersOptions): Promise<PaginatedList<User>> =>\n this.getRequest<PaginatedList<User>>('/users', options)\n\n get = (id: number): Promise<User> => this.getRequest<User>(`/users/${id}`)\n\n update = (id: number, input: UpdateUserInput): Promise<User> =>\n this.putRequest<User>(`/users/${id}`, input)\n\n delete = (id: number): Promise<void> =>\n this.deleteRequest<void>(`/users/${id}`)\n\n updatePassword = (id: number, input: UpdatePasswordInput): Promise<void> =>\n this.putRequest<void>(`/users/${id}/password`, input)\n}\n","import { createClerkClient } from '@clerk/backend'\nimport { SdkError } from '../../types/result'\n\nconst TOKEN_RENEWAL_BUFFER_MS = 30_000\n\nexport class ClerkService {\n private readonly m2mSecret: string\n private readonly clerkClient: ReturnType<typeof createClerkClient>\n private cachedToken: string | null = null\n private tokenExpiration: number | null = null\n private renewalTimer: ReturnType<typeof setTimeout> | null = null\n private pendingTokenPromise: Promise<string> | null = null\n private destroyed = false\n\n constructor(m2mSecret: string) {\n this.m2mSecret = m2mSecret\n this.clerkClient = createClerkClient({})\n }\n\n getToken = async (): Promise<string> => {\n if (this.cachedToken && this.isTokenValid()) {\n return this.cachedToken\n }\n\n if (this.pendingTokenPromise) {\n return this.pendingTokenPromise\n }\n\n const promise = this.createAndCacheToken()\n this.pendingTokenPromise = promise\n\n try {\n return await promise\n } finally {\n if (this.pendingTokenPromise === promise) {\n this.pendingTokenPromise = null\n }\n }\n }\n\n destroy = (): void => {\n this.destroyed = true\n if (this.renewalTimer) {\n clearTimeout(this.renewalTimer)\n this.renewalTimer = null\n }\n this.cachedToken = null\n this.tokenExpiration = null\n this.pendingTokenPromise = null\n }\n\n private isTokenValid = (): boolean => {\n if (!this.tokenExpiration) return true\n return Date.now() < this.tokenExpiration - TOKEN_RENEWAL_BUFFER_MS\n }\n\n private createAndCacheToken = async (): Promise<string> => {\n try {\n const m2mToken = await this.clerkClient.m2m.createToken({\n machineSecretKey: this.m2mSecret,\n })\n\n if (!m2mToken.token) {\n throw new SdkError(\n 0,\n 'Clerk M2M token creation succeeded but returned no token string',\n )\n }\n\n if (this.destroyed) return m2mToken.token\n\n this.cachedToken = m2mToken.token\n this.tokenExpiration = m2mToken.expiration\n this.scheduleRenewal()\n\n return this.cachedToken\n } catch (error: unknown) {\n if (error instanceof SdkError) {\n throw error\n }\n const message = error instanceof Error ? error.message : 'Unknown error'\n throw new SdkError(0, `Failed to create Clerk M2M token: ${message}`)\n }\n }\n\n private scheduleRenewal = (): void => {\n if (this.renewalTimer) {\n clearTimeout(this.renewalTimer)\n this.renewalTimer = null\n }\n\n if (!this.tokenExpiration) return\n\n const timeUntilRenewal =\n this.tokenExpiration - Date.now() - TOKEN_RENEWAL_BUFFER_MS\n\n if (timeUntilRenewal <= 0) return\n\n this.renewalTimer = setTimeout(() => {\n this.cachedToken = null\n this.getToken().catch((error: unknown) => {\n console.error('Proactive M2M token renewal failed:', error)\n })\n }, timeUntilRenewal)\n }\n}\n","import { HttpClient } from './http/HttpClient'\nimport { UsersResource } from './resources/UsersResource'\nimport { ClerkService } from './vendor/clerk/clerk.service'\n\nexport type GoodPartyClientConfig = {\n m2mSecret: string\n gpApiRootUrl: string\n}\n\nexport class GoodPartyClient {\n readonly users: UsersResource\n private clerkService: ClerkService\n\n private constructor(clerkService: ClerkService, gpApiRootUrl: string) {\n this.clerkService = clerkService\n const httpClient = new HttpClient(gpApiRootUrl, clerkService.getToken)\n this.users = new UsersResource(httpClient)\n }\n\n static create = async (\n config: GoodPartyClientConfig,\n ): Promise<GoodPartyClient> => {\n const { m2mSecret, gpApiRootUrl } = config\n const clerkService = new ClerkService(m2mSecret)\n await clerkService.getToken()\n return new GoodPartyClient(clerkService, gpApiRootUrl)\n }\n\n destroy = (): void => {\n this.clerkService.destroy()\n }\n}\n","import type { PaginationOptions } from './result'\n\nexport enum UserRole {\n admin = 'admin',\n sales = 'sales',\n candidate = 'candidate',\n campaignManager = 'campaignManager',\n demo = 'demo',\n}\n\nexport enum WhyBrowsing {\n considering = 'considering',\n learning = 'learning',\n test = 'test',\n else = 'else',\n}\n\nexport enum SIGN_UP_MODE {\n CANDIDATE = 'candidate',\n FACILITATED = 'facilitated',\n}\n\nexport type UserMetaData = {\n customerId?: string\n checkoutSessionId?: string | null\n accountType?: string | null\n lastVisited?: number\n sessionCount?: number\n isDeleted?: boolean\n fsUserId?: string\n whyBrowsing?: WhyBrowsing | null\n hubspotId?: string\n profile_updated_count?: number\n textNotifications?: boolean\n} | null\n\nexport type User = {\n id: number\n firstName: string\n lastName: string\n name?: string | null\n email: string\n phone?: string | null\n zip?: string | null\n avatar?: string | null\n hasPassword: boolean\n roles?: UserRole[]\n metaData?: UserMetaData\n}\n\nexport type ListUsersOptions = PaginationOptions & {\n firstName?: string\n lastName?: string\n email?: string\n}\n\nexport type UpdateUserInput = {\n firstName?: string\n lastName?: string\n email?: string\n name?: string\n zip?: string\n phone?: string\n roles?: UserRole[]\n signUpMode?: SIGN_UP_MODE\n allowTexts?: boolean\n}\n\nexport type UpdatePasswordInput = {\n oldPassword?: string\n newPassword: string\n}\n"],"mappings":"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","names":["UserRole","WhyBrowsing"]}
|