@rachelallyson/planning-center-people-ts 2.6.3 โ†’ 2.7.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/CHANGELOG.md CHANGED
@@ -5,6 +5,39 @@ 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.7.0] - 2025-01-11
9
+
10
+ ### ๐Ÿš€ **RATE LIMITING IMPROVEMENTS**
11
+
12
+ This release updates the rate limiting implementation to match Planning Center's actual API specifications and adds enhanced error handling capabilities.
13
+
14
+ ### Added
15
+
16
+ - **๐Ÿ“Š Enhanced Rate Limiting**: Updated default rate limits to match PCO's actual API (100 requests per 20 seconds)
17
+ - **๐Ÿ”„ Dynamic Period Adjustment**: Automatically adapts to server-provided time periods via `X-PCO-API-Request-Rate-Period` header
18
+ - **๐Ÿ” Error Parsing**: New `parseRateLimitError()` method extracts detailed information from 429 error responses
19
+ - **๐Ÿ“ Error Message Parsing**: Handles error messages like `"Rate limit exceeded: 118 of 100 requests per 20 seconds"`
20
+ - **๐Ÿงช Comprehensive Testing**: Added 22 rate limiter tests with new 20-second window and error parsing tests
21
+
22
+ ### Changed
23
+
24
+ - **โšก Rate Limit Defaults**: Changed from 100 requests per 60 seconds to 100 requests per 20 seconds
25
+ - **๐Ÿ“š Documentation**: Updated all documentation to reflect correct rate limiting specifications
26
+ - **๐Ÿ”ง Header Synchronization**: Enhanced parsing of `X-PCO-API-Request-Rate-Period` header for dynamic window adjustment
27
+ - **๐Ÿ“– Configuration Examples**: Updated client configuration examples with proper rate limiting settings
28
+
29
+ ### Fixed
30
+
31
+ - **๐ŸŽฏ API Compliance**: Now correctly follows Planning Center's actual API rate limits
32
+ - **๐Ÿ”„ Server Synchronization**: Better rate limit tracking that stays in sync with PCO's servers
33
+ - **๐Ÿ“Š Debug Information**: Enhanced visibility into rate limit status and remaining requests
34
+
35
+ ### Technical Details
36
+
37
+ - **Backward Compatible**: No breaking changes - existing code continues to work
38
+ - **Future-Proof**: Automatically adapts to PCO rate limit changes via header synchronization
39
+ - **Performance**: More accurate rate limiting reduces 429 errors and improves API efficiency
40
+
8
41
  ## [2.6.3] - 2025-01-10
9
42
 
10
43
  ### ๐Ÿข **CAMPUS ATTRIBUTES ENHANCEMENT**
package/README.md CHANGED
@@ -9,7 +9,7 @@ A modern, type-safe TypeScript library for interacting with the Planning Center
9
9
  - โœ… **Strict TypeScript**: Full type safety with no `any` types
10
10
  - โœ… **JSON:API 1.0 Compliant**: Follows the JSON:API specification exactly
11
11
  - โœ… **Functional Approach**: Clean, composable functions instead of classes
12
- - โœ… **Rate Limiting**: Built-in rate limiting with PCO's 100 req/min policy
12
+ - โœ… **Rate Limiting**: Built-in rate limiting with PCO's 100 req/20s policy
13
13
  - โœ… **Modern HTTP**: Uses native fetch API (no external dependencies)
14
14
  - โœ… **Authentication**: Supports both Personal Access Tokens and OAuth 2.0
15
15
  - โœ… **Enhanced Error Handling**: Comprehensive error handling with categories, severity, and retry logic
@@ -505,7 +505,7 @@ See [TYPE_VALIDATION_SUMMARY.md](./TYPE_VALIDATION_SUMMARY.md) for detailed docu
505
505
 
506
506
  - All test data is automatically cleaned up
507
507
  - Uses descriptive test names (e.g., "TEST_INTEGRATION_2025")
508
- - Respects PCO rate limits (90 requests per 20 seconds)
508
+ - Respects PCO rate limits (100 requests per 20 seconds)
509
509
  - 30-second timeout per test
510
510
  - Comprehensive error handling
511
511
 
package/dist/core/http.js CHANGED
@@ -15,7 +15,7 @@ class PcoHttpClient {
15
15
  this.performanceMetrics = new monitoring_1.PerformanceMetrics();
16
16
  this.rateLimitTracker = new monitoring_1.RateLimitTracker();
17
17
  // Initialize rate limiter
18
- this.rateLimiter = new rate_limiter_1.PcoRateLimiter(100, 60000); // 100 requests per minute
18
+ this.rateLimiter = new rate_limiter_1.PcoRateLimiter(100, 20000); // 100 requests per 20 seconds
19
19
  }
20
20
  async request(options) {
21
21
  const requestId = this.requestIdGenerator.generate();
package/dist/core.js CHANGED
@@ -23,7 +23,7 @@ function createPcoClient(config) {
23
23
  // Initialize rate limiter
24
24
  const rateLimitConfig = config.rateLimit ?? {
25
25
  maxRequests: 100,
26
- perMilliseconds: 60000,
26
+ perMilliseconds: 20000, // 20 seconds
27
27
  };
28
28
  const rateLimiter = new rate_limiter_1.PcoRateLimiter(rateLimitConfig.maxRequests, rateLimitConfig.perMilliseconds);
29
29
  return {
@@ -2,9 +2,10 @@
2
2
  * PCO Rate Limiter
3
3
  *
4
4
  * Planning Center Online has the following rate limits:
5
- * - 100 requests per minute (60 seconds)
5
+ * - 100 requests per 20 seconds (subject to change)
6
6
  * - Rate limit headers are returned on every response
7
7
  * - 429 responses include Retry-After header
8
+ * - Limits and time periods can change dynamically
8
9
  *
9
10
  * This rate limiter tracks requests and enforces these limits.
10
11
  */
@@ -56,6 +57,14 @@ export declare class PcoRateLimiter {
56
57
  * Update the sliding window
57
58
  */
58
59
  private updateWindow;
60
+ /**
61
+ * Parse rate limit error details from 429 response
62
+ */
63
+ static parseRateLimitError(errorDetail: string): {
64
+ current: number;
65
+ limit: number;
66
+ period: number;
67
+ } | null;
59
68
  /**
60
69
  * Get debug information
61
70
  */
@@ -3,9 +3,10 @@
3
3
  * PCO Rate Limiter
4
4
  *
5
5
  * Planning Center Online has the following rate limits:
6
- * - 100 requests per minute (60 seconds)
6
+ * - 100 requests per 20 seconds (subject to change)
7
7
  * - Rate limit headers are returned on every response
8
8
  * - 429 responses include Retry-After header
9
+ * - Limits and time periods can change dynamically
9
10
  *
10
11
  * This rate limiter tracks requests and enforces these limits.
11
12
  */
@@ -15,8 +16,8 @@ class PcoRateLimiter {
15
16
  constructor(limit, windowMs) {
16
17
  this.requestCount = 0;
17
18
  this.windowStart = Date.now();
18
- this.defaultLimit = 100; // requests per minute
19
- this.defaultWindow = 60000; // 60 seconds in milliseconds
19
+ this.defaultLimit = 100; // requests per 20 seconds
20
+ this.defaultWindow = 20000; // 20 seconds in milliseconds
20
21
  this.limit = limit || this.defaultLimit;
21
22
  this.windowMs = windowMs || this.defaultWindow;
22
23
  }
@@ -60,6 +61,13 @@ class PcoRateLimiter {
60
61
  if (headers['X-PCO-API-Request-Rate-Limit']) {
61
62
  this.limit = parseInt(headers['X-PCO-API-Request-Rate-Limit'], 10);
62
63
  }
64
+ if (headers['X-PCO-API-Request-Rate-Period']) {
65
+ // Update window period from server (in seconds, convert to milliseconds)
66
+ const periodSeconds = parseInt(headers['X-PCO-API-Request-Rate-Period'], 10);
67
+ if (!isNaN(periodSeconds)) {
68
+ this.windowMs = periodSeconds * 1000;
69
+ }
70
+ }
63
71
  if (headers['X-PCO-API-Request-Rate-Count']) {
64
72
  this.requestCount = parseInt(headers['X-PCO-API-Request-Rate-Count'], 10);
65
73
  }
@@ -97,6 +105,21 @@ class PcoRateLimiter {
97
105
  this.requestCount = 0;
98
106
  }
99
107
  }
108
+ /**
109
+ * Parse rate limit error details from 429 response
110
+ */
111
+ static parseRateLimitError(errorDetail) {
112
+ // Parse error like "Rate limit exceeded: 118 of 100 requests per 20 seconds"
113
+ const match = errorDetail.match(/Rate limit exceeded: (\d+) of (\d+) requests per (\d+) seconds/);
114
+ if (match) {
115
+ return {
116
+ current: parseInt(match[1], 10),
117
+ limit: parseInt(match[2], 10),
118
+ period: parseInt(match[3], 10)
119
+ };
120
+ }
121
+ return null;
122
+ }
100
123
  /**
101
124
  * Get debug information
102
125
  */
@@ -384,6 +384,7 @@ export interface OrganizationStatisticResource extends ResourceObject<'Organizat
384
384
  export type OrganizationStatisticsList = Paginated<OrganizationStatisticResource>;
385
385
  export type OrganizationStatisticSingle = Response<OrganizationStatisticResource>;
386
386
  export interface CampusAttributes extends Attributes {
387
+ name: string;
387
388
  latitude?: number;
388
389
  longitude?: number;
389
390
  description?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rachelallyson/planning-center-people-ts",
3
- "version": "2.6.3",
3
+ "version": "2.7.0",
4
4
  "description": "A strictly typed TypeScript client for Planning Center Online People API with smart matching, batch operations, and enhanced developer experience",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",