@rachelallyson/planning-center-people-ts 2.12.1 → 2.12.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/CHANGELOG.md +7 -0
- package/dist/client-manager.js +4 -0
- package/dist/client.d.ts +0 -1
- package/dist/client.js +0 -19
- package/dist/core/http.d.ts +4 -0
- package/dist/core/http.js +67 -11
- package/dist/core.d.ts +3 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.12.2] - 2026-01-20
|
|
9
|
+
|
|
10
|
+
### ✨ **New Features**
|
|
11
|
+
|
|
12
|
+
- **Direct Personal Access Token Configuration**: Added support for passing `personalAccessTokenSecret` directly in config (alternative to environment variables)
|
|
13
|
+
- **Flexible Authentication**: Choose between environment variables or direct config based on your needs
|
|
14
|
+
|
|
8
15
|
## [2.12.1] - 2026-01-20
|
|
9
16
|
|
|
10
17
|
### ✨ **New Features**
|
package/dist/client-manager.js
CHANGED
|
@@ -151,6 +151,10 @@ class PcoClientManager {
|
|
|
151
151
|
if (oldConfig.auth.type === 'personal_access_token' && newConfig.auth.type === 'personal_access_token') {
|
|
152
152
|
return oldConfig.auth.personalAccessToken !== newConfig.auth.personalAccessToken;
|
|
153
153
|
}
|
|
154
|
+
if (oldConfig.auth.type === 'basic' && newConfig.auth.type === 'basic') {
|
|
155
|
+
return (oldConfig.auth.appId !== newConfig.auth.appId ||
|
|
156
|
+
oldConfig.auth.appSecret !== newConfig.auth.appSecret);
|
|
157
|
+
}
|
|
154
158
|
return (oldConfig.baseURL !== newConfig.baseURL ||
|
|
155
159
|
oldConfig.timeout !== newConfig.timeout);
|
|
156
160
|
}
|
package/dist/client.d.ts
CHANGED
package/dist/client.js
CHANGED
|
@@ -36,7 +36,6 @@ class PcoClient {
|
|
|
36
36
|
this.reports = new reports_1.ReportsModule(this.httpClient, this.paginationHelper, this.eventEmitter);
|
|
37
37
|
this.batch = new planning_center_base_ts_1.BatchExecutor(this, this.eventEmitter);
|
|
38
38
|
// Set up event handlers from config
|
|
39
|
-
this.setupEventHandlers();
|
|
40
39
|
}
|
|
41
40
|
// EventEmitter implementation
|
|
42
41
|
on(eventType, handler) {
|
|
@@ -95,24 +94,6 @@ class PcoClient {
|
|
|
95
94
|
eventTypes() {
|
|
96
95
|
return this.eventEmitter.eventTypes();
|
|
97
96
|
}
|
|
98
|
-
setupEventHandlers() {
|
|
99
|
-
// Set up config event handlers
|
|
100
|
-
if (this.config.events?.onError) {
|
|
101
|
-
this.on('error', this.config.events.onError);
|
|
102
|
-
}
|
|
103
|
-
if (this.config.events?.onAuthFailure) {
|
|
104
|
-
this.on('auth:failure', this.config.events.onAuthFailure);
|
|
105
|
-
}
|
|
106
|
-
if (this.config.events?.onRequestStart) {
|
|
107
|
-
this.on('request:start', this.config.events.onRequestStart);
|
|
108
|
-
}
|
|
109
|
-
if (this.config.events?.onRequestComplete) {
|
|
110
|
-
this.on('request:complete', this.config.events.onRequestComplete);
|
|
111
|
-
}
|
|
112
|
-
if (this.config.events?.onRateLimit) {
|
|
113
|
-
this.on('rate:limit', this.config.events.onRateLimit);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
97
|
updateModules() {
|
|
117
98
|
// Recreate modules with new HTTP client
|
|
118
99
|
this.people = new people_1.PeopleModule(this.httpClient, this.paginationHelper, this.eventEmitter);
|
package/dist/core/http.d.ts
CHANGED
|
@@ -49,4 +49,8 @@ export declare class PcoHttpClient {
|
|
|
49
49
|
* Get authentication header for external services (like file uploads)
|
|
50
50
|
*/
|
|
51
51
|
getAuthHeader(): string;
|
|
52
|
+
/**
|
|
53
|
+
* Make HTTPS request using Node.js HTTPS module (fallback when fetch is unavailable)
|
|
54
|
+
*/
|
|
55
|
+
private makeHttpsRequest;
|
|
52
56
|
}
|
package/dist/core/http.js
CHANGED
|
@@ -152,7 +152,7 @@ class PcoHttpClient {
|
|
|
152
152
|
catch (refreshError) {
|
|
153
153
|
console.warn('Token refresh failed:', refreshError);
|
|
154
154
|
// Call the onRefreshFailure callback
|
|
155
|
-
await this.config.auth.onRefreshFailure(refreshError);
|
|
155
|
+
await this.config.auth.onRefreshFailure?.(refreshError);
|
|
156
156
|
throw refreshError;
|
|
157
157
|
}
|
|
158
158
|
}
|
|
@@ -195,9 +195,20 @@ class PcoHttpClient {
|
|
|
195
195
|
}
|
|
196
196
|
addAuthentication(headers) {
|
|
197
197
|
if (this.config.auth.type === 'personal_access_token') {
|
|
198
|
-
// Personal Access Tokens use HTTP Basic Auth
|
|
199
|
-
//
|
|
200
|
-
|
|
198
|
+
// Personal Access Tokens use client_id:secret format with HTTP Basic Auth
|
|
199
|
+
// Get client ID from config (required)
|
|
200
|
+
const clientId = this.config.auth.personalAccessToken;
|
|
201
|
+
// Get client secret from config or environment (with config taking precedence)
|
|
202
|
+
const clientSecret = this.config.auth.personalAccessTokenSecret ||
|
|
203
|
+
process.env.PCO_PERSONAL_ACCESS_SECRET;
|
|
204
|
+
if (!clientId) {
|
|
205
|
+
throw new Error('personalAccessToken is required for personal access token authentication');
|
|
206
|
+
}
|
|
207
|
+
if (!clientSecret) {
|
|
208
|
+
throw new Error('personalAccessTokenSecret (in config) or PCO_PERSONAL_ACCESS_SECRET environment variable is required for personal access token authentication');
|
|
209
|
+
}
|
|
210
|
+
const credentials = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');
|
|
211
|
+
headers.Authorization = `Basic ${credentials}`;
|
|
201
212
|
}
|
|
202
213
|
else if (this.config.auth.type === 'oauth') {
|
|
203
214
|
headers.Authorization = `Bearer ${this.config.auth.accessToken}`;
|
|
@@ -243,11 +254,11 @@ class PcoHttpClient {
|
|
|
243
254
|
// Prepare the request body for token refresh
|
|
244
255
|
const body = new URLSearchParams({
|
|
245
256
|
grant_type: 'refresh_token',
|
|
246
|
-
refresh_token: this.config.auth.refreshToken,
|
|
257
|
+
refresh_token: this.config.auth.refreshToken || '',
|
|
247
258
|
});
|
|
248
259
|
// Add client credentials if available from the config or environment
|
|
249
|
-
const clientId = this.config.auth.
|
|
250
|
-
const clientSecret = this.config.auth.
|
|
260
|
+
const clientId = this.config.auth.appId || process.env.PCO_APP_ID;
|
|
261
|
+
const clientSecret = this.config.auth.appSecret || process.env.PCO_APP_SECRET;
|
|
251
262
|
if (clientId && clientSecret) {
|
|
252
263
|
body.append('client_id', clientId);
|
|
253
264
|
body.append('client_secret', clientSecret);
|
|
@@ -268,10 +279,10 @@ class PcoHttpClient {
|
|
|
268
279
|
// Update the config with new tokens
|
|
269
280
|
this.config.auth.accessToken = tokens.access_token;
|
|
270
281
|
this.config.auth.refreshToken = tokens.refresh_token || this.config.auth.refreshToken;
|
|
271
|
-
// Call the onRefresh callback
|
|
272
|
-
await this.config.auth.onRefresh({
|
|
282
|
+
// Call the onRefresh callback
|
|
283
|
+
await this.config.auth.onRefresh?.({
|
|
273
284
|
accessToken: tokens.access_token,
|
|
274
|
-
refreshToken: tokens.refresh_token || this.config.auth.refreshToken
|
|
285
|
+
refreshToken: tokens.refresh_token || this.config.auth.refreshToken
|
|
275
286
|
});
|
|
276
287
|
}
|
|
277
288
|
updateRateLimitTracking(endpoint, headers) {
|
|
@@ -292,13 +303,58 @@ class PcoHttpClient {
|
|
|
292
303
|
* Get authentication header for external services (like file uploads)
|
|
293
304
|
*/
|
|
294
305
|
getAuthHeader() {
|
|
306
|
+
// The base package's PcoHttpClient handles authentication, so this method should delegate
|
|
307
|
+
// But for backward compatibility, we'll implement it
|
|
295
308
|
if (this.config.auth.type === 'personal_access_token') {
|
|
296
|
-
|
|
309
|
+
const clientSecret = this.config.auth.personalAccessTokenSecret || process.env.PCO_PERSONAL_ACCESS_SECRET;
|
|
310
|
+
return `Basic ${Buffer.from(`${this.config.auth.personalAccessToken}:${clientSecret}`).toString('base64')}`;
|
|
297
311
|
}
|
|
298
312
|
else if (this.config.auth.type === 'oauth') {
|
|
299
313
|
return `Bearer ${this.config.auth.accessToken}`;
|
|
300
314
|
}
|
|
315
|
+
else if (this.config.auth.type === 'basic') {
|
|
316
|
+
return `Basic ${Buffer.from(`${this.config.auth.appId}:${this.config.auth.appSecret}`).toString('base64')}`;
|
|
317
|
+
}
|
|
301
318
|
return '';
|
|
302
319
|
}
|
|
320
|
+
/**
|
|
321
|
+
* Make HTTPS request using Node.js HTTPS module (fallback when fetch is unavailable)
|
|
322
|
+
*/
|
|
323
|
+
async makeHttpsRequest(url, options) {
|
|
324
|
+
const https = require('https');
|
|
325
|
+
const urlObj = new URL(url);
|
|
326
|
+
const requestOptions = {
|
|
327
|
+
hostname: urlObj.hostname,
|
|
328
|
+
port: urlObj.port || 443,
|
|
329
|
+
path: urlObj.pathname + urlObj.search,
|
|
330
|
+
method: options.method || 'GET',
|
|
331
|
+
headers: options.headers,
|
|
332
|
+
};
|
|
333
|
+
return new Promise((resolve, reject) => {
|
|
334
|
+
const req = https.request(requestOptions, (res) => {
|
|
335
|
+
let data = '';
|
|
336
|
+
res.on('data', (chunk) => {
|
|
337
|
+
data += chunk;
|
|
338
|
+
});
|
|
339
|
+
res.on('end', () => {
|
|
340
|
+
// Create a response-like object
|
|
341
|
+
const response = {
|
|
342
|
+
ok: res.statusCode >= 200 && res.statusCode < 300,
|
|
343
|
+
status: res.statusCode,
|
|
344
|
+
statusText: res.statusMessage,
|
|
345
|
+
headers: res.headers,
|
|
346
|
+
text: () => Promise.resolve(data),
|
|
347
|
+
json: () => Promise.resolve(JSON.parse(data)),
|
|
348
|
+
};
|
|
349
|
+
resolve(response);
|
|
350
|
+
});
|
|
351
|
+
});
|
|
352
|
+
req.on('error', reject);
|
|
353
|
+
if (options.body) {
|
|
354
|
+
req.write(options.body);
|
|
355
|
+
}
|
|
356
|
+
req.end();
|
|
357
|
+
});
|
|
358
|
+
}
|
|
303
359
|
}
|
|
304
360
|
exports.PcoHttpClient = PcoHttpClient;
|
package/dist/core.d.ts
CHANGED
|
@@ -3,8 +3,10 @@ import { PcoRateLimiter } from '@rachelallyson/planning-center-base-ts';
|
|
|
3
3
|
import { Paginated, ResourceObject, Response as JsonApiResponse } from './types';
|
|
4
4
|
import { type TokenRefreshCallback, type TokenRefreshFailureCallback } from './auth';
|
|
5
5
|
export interface PcoClientConfig {
|
|
6
|
-
/** Personal Access Token (for single-user apps) */
|
|
6
|
+
/** Personal Access Token Client ID (for single-user apps) */
|
|
7
7
|
personalAccessToken?: string;
|
|
8
|
+
/** Personal Access Token Client Secret (alternative to PCO_PERSONAL_ACCESS_SECRET env var) */
|
|
9
|
+
personalAccessTokenSecret?: string;
|
|
8
10
|
/** OAuth 2.0 Access Token (for multi-user apps) */
|
|
9
11
|
accessToken?: string;
|
|
10
12
|
/** OAuth 2.0 Refresh Token (for multi-user apps) */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rachelallyson/planning-center-people-ts",
|
|
3
|
-
"version": "2.12.
|
|
3
|
+
"version": "2.12.2",
|
|
4
4
|
"description": "A strictly typed TypeScript client for Planning Center Online People API with comprehensive functionality and enhanced developer experience",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|