@rachelallyson/planning-center-people-ts 2.0.0 → 2.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/CHANGELOG.md +146 -0
- package/dist/client-manager.js +14 -8
- package/dist/client.d.ts +2 -0
- package/dist/client.js +2 -0
- package/dist/core/http.d.ts +1 -0
- package/dist/core/http.js +35 -12
- package/dist/index.d.ts +2 -2
- package/dist/modules/campus.d.ts +63 -0
- package/dist/modules/campus.js +77 -0
- package/dist/testing/simple-factories.js +9 -0
- package/dist/types/client.d.ts +19 -11
- package/dist/types/people.d.ts +25 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,148 @@ 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.2.0] - 2025-01-17
|
|
9
|
+
|
|
10
|
+
### 🏢 **NEW FEATURE - Campus Management Support**
|
|
11
|
+
|
|
12
|
+
This release adds comprehensive Campus management functionality to the Planning Center People API client.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
#### **🏢 Campus Module**
|
|
17
|
+
|
|
18
|
+
- **Complete Campus CRUD Operations**: Create, read, update, and delete campuses
|
|
19
|
+
- **Campus-Specific Operations**: Get campus lists and service times
|
|
20
|
+
- **Type-Safe Campus Resource**: Full TypeScript support for campus attributes and relationships
|
|
21
|
+
- **Pagination Support**: Automatic pagination for campus listings
|
|
22
|
+
|
|
23
|
+
#### **📋 Campus Operations**
|
|
24
|
+
|
|
25
|
+
- `client.campus.getAll()` - Get all campuses with filtering and pagination
|
|
26
|
+
- `client.campus.getById(id, include?)` - Get specific campus by ID
|
|
27
|
+
- `client.campus.create(data)` - Create new campus
|
|
28
|
+
- `client.campus.update(id, data)` - Update existing campus
|
|
29
|
+
- `client.campus.delete(id)` - Delete campus
|
|
30
|
+
- `client.campus.getLists(campusId)` - Get lists for a specific campus
|
|
31
|
+
- `client.campus.getServiceTimes(campusId)` - Get service times for a specific campus
|
|
32
|
+
- `client.campus.getAllPagesPaginated()` - Get all campuses with automatic pagination
|
|
33
|
+
|
|
34
|
+
#### **🏗️ Campus Resource Structure**
|
|
35
|
+
|
|
36
|
+
- **Location Data**: `latitude`, `longitude`, `street`, `city`, `state`, `zip`, `country`
|
|
37
|
+
- **Contact Information**: `phone_number`, `website`
|
|
38
|
+
- **Settings**: `twenty_four_hour_time`, `date_format`, `church_center_enabled`
|
|
39
|
+
- **Metadata**: `description`, `created_at`, `updated_at`
|
|
40
|
+
|
|
41
|
+
### Documentation
|
|
42
|
+
|
|
43
|
+
- **Updated README.md** with Campus Management examples
|
|
44
|
+
- **Updated EXAMPLES.md** with comprehensive Campus usage patterns
|
|
45
|
+
- **Updated API_REFERENCE.md** with complete Campus Module documentation
|
|
46
|
+
- **Added Campus types** to resource types documentation
|
|
47
|
+
|
|
48
|
+
### Testing
|
|
49
|
+
|
|
50
|
+
- **Integration Tests**: Complete test suite for Campus operations
|
|
51
|
+
- **Type Safety**: Full TypeScript coverage for Campus resources
|
|
52
|
+
- **Error Handling**: Comprehensive error handling for Campus operations
|
|
53
|
+
|
|
54
|
+
### Example Usage
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { PcoClient } from '@rachelallyson/planning-center-people-ts';
|
|
58
|
+
|
|
59
|
+
const client = new PcoClient({
|
|
60
|
+
auth: {
|
|
61
|
+
type: 'personal_access_token',
|
|
62
|
+
personalAccessToken: 'your-token'
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Get all campuses
|
|
67
|
+
const campuses = await client.campus.getAll();
|
|
68
|
+
|
|
69
|
+
// Create new campus
|
|
70
|
+
const newCampus = await client.campus.create({
|
|
71
|
+
description: 'Main Campus',
|
|
72
|
+
street: '123 Church Street',
|
|
73
|
+
city: 'Anytown',
|
|
74
|
+
state: 'CA',
|
|
75
|
+
zip: '12345',
|
|
76
|
+
country: 'US',
|
|
77
|
+
phone_number: '555-123-4567',
|
|
78
|
+
website: 'https://maincampus.example.com',
|
|
79
|
+
twenty_four_hour_time: false,
|
|
80
|
+
date_format: 1,
|
|
81
|
+
church_center_enabled: true
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Get campus-specific data
|
|
85
|
+
const campusLists = await client.campus.getLists('campus-id');
|
|
86
|
+
const serviceTimes = await client.campus.getServiceTimes('campus-id');
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## [2.1.0] - 2025-01-17
|
|
90
|
+
|
|
91
|
+
### 🔒 **SECURITY RELEASE - Required Refresh Token Handling**
|
|
92
|
+
|
|
93
|
+
This release addresses a critical security issue where OAuth 2.0 clients could lose access when tokens expire without proper refresh handling.
|
|
94
|
+
|
|
95
|
+
### Breaking Changes
|
|
96
|
+
|
|
97
|
+
- **OAuth 2.0 Authentication**: `onRefresh` and `onRefreshFailure` callbacks are now **required** for OAuth configurations
|
|
98
|
+
- **Type Safety**: Enhanced type-safe authentication configuration prevents invalid configurations at compile time
|
|
99
|
+
|
|
100
|
+
### Security
|
|
101
|
+
|
|
102
|
+
- **CRITICAL**: OAuth 2.0 authentication now requires refresh token handling to prevent token loss
|
|
103
|
+
- **BREAKING**: Type-safe authentication configuration enforces required fields
|
|
104
|
+
- Enhanced token refresh implementation with proper error handling
|
|
105
|
+
- Improved authentication type safety with union types
|
|
106
|
+
|
|
107
|
+
### Fixed
|
|
108
|
+
|
|
109
|
+
- Fixed person matching to properly handle default fuzzy strategy
|
|
110
|
+
- Fixed mock client to support createWithContacts method
|
|
111
|
+
- Fixed event system tests to work with mock client
|
|
112
|
+
- Fixed phone number builder in mock response builder
|
|
113
|
+
|
|
114
|
+
### Migration from v2.0.0
|
|
115
|
+
|
|
116
|
+
**Before (v2.0.0):**
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
const client = new PcoClient({
|
|
120
|
+
auth: {
|
|
121
|
+
type: 'oauth',
|
|
122
|
+
accessToken: 'access-token',
|
|
123
|
+
refreshToken: 'refresh-token'
|
|
124
|
+
// Missing required callbacks - this will now cause TypeScript errors
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**After (v2.1.0):**
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
const client = new PcoClient({
|
|
133
|
+
auth: {
|
|
134
|
+
type: 'oauth',
|
|
135
|
+
accessToken: 'access-token',
|
|
136
|
+
refreshToken: 'refresh-token',
|
|
137
|
+
// REQUIRED: Handle token refresh to prevent token loss
|
|
138
|
+
onRefresh: async (tokens) => {
|
|
139
|
+
await saveTokensToDatabase(userId, tokens);
|
|
140
|
+
},
|
|
141
|
+
// REQUIRED: Handle refresh failures
|
|
142
|
+
onRefreshFailure: async (error) => {
|
|
143
|
+
console.error('Token refresh failed:', error.message);
|
|
144
|
+
await clearUserTokens(userId);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
```
|
|
149
|
+
|
|
8
150
|
## [2.0.0] - 2025-01-17
|
|
9
151
|
|
|
10
152
|
### 🚀 **MAJOR RELEASE - Complete API Redesign**
|
|
@@ -120,6 +262,10 @@ const person = await client.people.create({ first_name: 'John', last_name: 'Doe'
|
|
|
120
262
|
- **Error Handling**: Improved error handling and retry logic
|
|
121
263
|
- **Rate Limiting**: Fixed rate limiting edge cases
|
|
122
264
|
- **Authentication**: Resolved token refresh and persistence issues
|
|
265
|
+
- Fixed person matching to properly handle default fuzzy strategy
|
|
266
|
+
- Fixed mock client to support createWithContacts method
|
|
267
|
+
- Fixed event system tests to work with mock client
|
|
268
|
+
- Fixed phone number builder in mock response builder
|
|
123
269
|
|
|
124
270
|
## [1.1.0] - 2025-10-08
|
|
125
271
|
|
package/dist/client-manager.js
CHANGED
|
@@ -119,9 +119,9 @@ class PcoClientManager {
|
|
|
119
119
|
// Create a hash of the configuration
|
|
120
120
|
const configStr = JSON.stringify({
|
|
121
121
|
authType: config.auth.type,
|
|
122
|
-
hasAccessToken: !!config.auth.accessToken,
|
|
123
|
-
hasRefreshToken: !!config.auth.refreshToken,
|
|
124
|
-
hasPersonalAccessToken: !!config.auth.personalAccessToken,
|
|
122
|
+
hasAccessToken: config.auth.type === 'oauth' ? !!config.auth.accessToken : false,
|
|
123
|
+
hasRefreshToken: config.auth.type === 'oauth' ? !!config.auth.refreshToken : false,
|
|
124
|
+
hasPersonalAccessToken: config.auth.type === 'personal_access_token' ? !!config.auth.personalAccessToken : false,
|
|
125
125
|
baseURL: config.baseURL,
|
|
126
126
|
timeout: config.timeout,
|
|
127
127
|
});
|
|
@@ -139,11 +139,17 @@ class PcoClientManager {
|
|
|
139
139
|
*/
|
|
140
140
|
hasConfigChanged(oldConfig, newConfig) {
|
|
141
141
|
// Compare key configuration properties
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
oldConfig.
|
|
142
|
+
if (oldConfig.auth.type !== newConfig.auth.type) {
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
if (oldConfig.auth.type === 'oauth' && newConfig.auth.type === 'oauth') {
|
|
146
|
+
return (oldConfig.auth.accessToken !== newConfig.auth.accessToken ||
|
|
147
|
+
oldConfig.auth.refreshToken !== newConfig.auth.refreshToken);
|
|
148
|
+
}
|
|
149
|
+
if (oldConfig.auth.type === 'personal_access_token' && newConfig.auth.type === 'personal_access_token') {
|
|
150
|
+
return oldConfig.auth.personalAccessToken !== newConfig.auth.personalAccessToken;
|
|
151
|
+
}
|
|
152
|
+
return (oldConfig.baseURL !== newConfig.baseURL ||
|
|
147
153
|
oldConfig.timeout !== newConfig.timeout);
|
|
148
154
|
}
|
|
149
155
|
}
|
package/dist/client.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { ContactsModule } from './modules/contacts';
|
|
|
10
10
|
import { HouseholdsModule } from './modules/households';
|
|
11
11
|
import { NotesModule } from './modules/notes';
|
|
12
12
|
import { ListsModule } from './modules/lists';
|
|
13
|
+
import { CampusModule } from './modules/campus';
|
|
13
14
|
import { BatchExecutor } from './batch';
|
|
14
15
|
export declare class PcoClient implements EventEmitter {
|
|
15
16
|
people: PeopleModule;
|
|
@@ -19,6 +20,7 @@ export declare class PcoClient implements EventEmitter {
|
|
|
19
20
|
households: HouseholdsModule;
|
|
20
21
|
notes: NotesModule;
|
|
21
22
|
lists: ListsModule;
|
|
23
|
+
campus: CampusModule;
|
|
22
24
|
batch: BatchExecutor;
|
|
23
25
|
private httpClient;
|
|
24
26
|
private paginationHelper;
|
package/dist/client.js
CHANGED
|
@@ -14,6 +14,7 @@ const contacts_1 = require("./modules/contacts");
|
|
|
14
14
|
const households_1 = require("./modules/households");
|
|
15
15
|
const notes_1 = require("./modules/notes");
|
|
16
16
|
const lists_1 = require("./modules/lists");
|
|
17
|
+
const campus_1 = require("./modules/campus");
|
|
17
18
|
const batch_1 = require("./batch");
|
|
18
19
|
class PcoClient {
|
|
19
20
|
constructor(config) {
|
|
@@ -29,6 +30,7 @@ class PcoClient {
|
|
|
29
30
|
this.households = new households_1.HouseholdsModule(this.httpClient, this.paginationHelper, this.eventEmitter);
|
|
30
31
|
this.notes = new notes_1.NotesModule(this.httpClient, this.paginationHelper, this.eventEmitter);
|
|
31
32
|
this.lists = new lists_1.ListsModule(this.httpClient, this.paginationHelper, this.eventEmitter);
|
|
33
|
+
this.campus = new campus_1.CampusModule(this.httpClient, this.paginationHelper, this.eventEmitter);
|
|
32
34
|
this.batch = new batch_1.BatchExecutor(this, this.eventEmitter);
|
|
33
35
|
// Set up event handlers from config
|
|
34
36
|
this.setupEventHandlers();
|
package/dist/core/http.d.ts
CHANGED
|
@@ -31,6 +31,7 @@ export declare class PcoHttpClient {
|
|
|
31
31
|
private addAuthentication;
|
|
32
32
|
private getResourceTypeFromEndpoint;
|
|
33
33
|
private extractHeaders;
|
|
34
|
+
private attemptTokenRefresh;
|
|
34
35
|
private updateRateLimitTracking;
|
|
35
36
|
getPerformanceMetrics(): Record<string, {
|
|
36
37
|
count: number;
|
package/dist/core/http.js
CHANGED
|
@@ -7,7 +7,6 @@ exports.PcoHttpClient = void 0;
|
|
|
7
7
|
const monitoring_1 = require("../monitoring");
|
|
8
8
|
const rate_limiter_1 = require("../rate-limiter");
|
|
9
9
|
const api_error_1 = require("../api-error");
|
|
10
|
-
const auth_1 = require("../auth");
|
|
11
10
|
class PcoHttpClient {
|
|
12
11
|
constructor(config, eventEmitter) {
|
|
13
12
|
this.config = config;
|
|
@@ -139,20 +138,15 @@ class PcoHttpClient {
|
|
|
139
138
|
// Handle other errors
|
|
140
139
|
if (!response.ok) {
|
|
141
140
|
// Handle 401 errors with token refresh if available
|
|
142
|
-
|
|
143
|
-
const v1Config = {
|
|
144
|
-
refreshToken: this.config.auth.refreshToken,
|
|
145
|
-
onTokenRefresh: this.config.auth.onRefresh,
|
|
146
|
-
onTokenRefreshFailure: this.config.auth.onRefreshFailure,
|
|
147
|
-
};
|
|
148
|
-
const clientState = { config: v1Config, rateLimiter: this.rateLimiter };
|
|
149
|
-
if (response.status === 401 && (0, auth_1.hasRefreshTokenCapability)(clientState)) {
|
|
141
|
+
if (response.status === 401 && this.config.auth.type === 'oauth') {
|
|
150
142
|
try {
|
|
151
|
-
await
|
|
143
|
+
await this.attemptTokenRefresh();
|
|
152
144
|
return this.makeRequest(options, requestId);
|
|
153
145
|
}
|
|
154
146
|
catch (refreshError) {
|
|
155
147
|
console.warn('Token refresh failed:', refreshError);
|
|
148
|
+
// Call the onRefreshFailure callback
|
|
149
|
+
await this.config.auth.onRefreshFailure(refreshError);
|
|
156
150
|
}
|
|
157
151
|
}
|
|
158
152
|
let errorData;
|
|
@@ -189,12 +183,12 @@ class PcoHttpClient {
|
|
|
189
183
|
}
|
|
190
184
|
}
|
|
191
185
|
addAuthentication(headers) {
|
|
192
|
-
if (this.config.auth.
|
|
186
|
+
if (this.config.auth.type === 'personal_access_token') {
|
|
193
187
|
// Personal Access Tokens use HTTP Basic Auth format: app_id:secret
|
|
194
188
|
// The personalAccessToken should be in the format "app_id:secret"
|
|
195
189
|
headers.Authorization = `Basic ${Buffer.from(this.config.auth.personalAccessToken).toString('base64')}`;
|
|
196
190
|
}
|
|
197
|
-
else if (this.config.auth.
|
|
191
|
+
else if (this.config.auth.type === 'oauth') {
|
|
198
192
|
headers.Authorization = `Bearer ${this.config.auth.accessToken}`;
|
|
199
193
|
}
|
|
200
194
|
}
|
|
@@ -224,6 +218,35 @@ class PcoHttpClient {
|
|
|
224
218
|
});
|
|
225
219
|
return headers;
|
|
226
220
|
}
|
|
221
|
+
async attemptTokenRefresh() {
|
|
222
|
+
if (this.config.auth.type !== 'oauth') {
|
|
223
|
+
throw new Error('Token refresh is only available for OAuth authentication');
|
|
224
|
+
}
|
|
225
|
+
const baseURL = this.config.baseURL || 'https://api.planningcenteronline.com/people/v2';
|
|
226
|
+
const tokenUrl = baseURL.replace('/people/v2', '/oauth/token');
|
|
227
|
+
const response = await fetch(tokenUrl, {
|
|
228
|
+
method: 'POST',
|
|
229
|
+
headers: {
|
|
230
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
231
|
+
},
|
|
232
|
+
body: new URLSearchParams({
|
|
233
|
+
grant_type: 'refresh_token',
|
|
234
|
+
refresh_token: this.config.auth.refreshToken,
|
|
235
|
+
}),
|
|
236
|
+
});
|
|
237
|
+
if (!response.ok) {
|
|
238
|
+
throw new Error(`Token refresh failed: ${response.status} ${response.statusText}`);
|
|
239
|
+
}
|
|
240
|
+
const tokens = await response.json();
|
|
241
|
+
// Update the config with new tokens
|
|
242
|
+
this.config.auth.accessToken = tokens.access_token;
|
|
243
|
+
this.config.auth.refreshToken = tokens.refresh_token;
|
|
244
|
+
// Call the onRefresh callback
|
|
245
|
+
await this.config.auth.onRefresh({
|
|
246
|
+
accessToken: tokens.access_token,
|
|
247
|
+
refreshToken: tokens.refresh_token,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
227
250
|
updateRateLimitTracking(endpoint, headers) {
|
|
228
251
|
const limit = headers['x-pco-api-request-rate-limit'];
|
|
229
252
|
const remaining = headers['x-pco-api-request-rate-count'];
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
export { PcoClient } from './client';
|
|
2
2
|
export { PcoClientManager } from './client-manager';
|
|
3
|
-
export type { PcoClientConfig } from './types/client';
|
|
3
|
+
export type { PcoClientConfig, PcoAuthConfig, PersonalAccessTokenAuth, OAuthAuth } from './types/client';
|
|
4
4
|
export type { PcoEvent, EventHandler, EventType } from './types/events';
|
|
5
5
|
export type { BatchOperation, BatchResult, BatchOptions, BatchSummary } from './types/batch';
|
|
6
6
|
export type { Paginated, Relationship, ResourceIdentifier, ResourceObject, } from './types';
|
|
7
7
|
export type { PersonResource, PersonAttributes, PersonSingle, PeopleList, EmailResource, EmailAttributes, PhoneNumberResource, PhoneNumberAttributes, AddressResource, AddressAttributes, SocialProfileResource, SocialProfileAttributes, } from './types';
|
|
8
8
|
export type { FieldDefinitionResource, FieldDefinitionAttributes, FieldDatumResource, FieldDatumAttributes, FieldOptionResource, FieldOptionAttributes, TabResource, TabAttributes, } from './types';
|
|
9
9
|
export type { WorkflowResource, WorkflowAttributes, WorkflowCardResource, WorkflowCardAttributes, WorkflowCardNoteResource, WorkflowCardNoteAttributes, } from './types';
|
|
10
|
-
export type { HouseholdResource, HouseholdAttributes, NoteResource, NoteAttributes, ListResource, ListAttributes, OrganizationResource, OrganizationAttributes, } from './types';
|
|
10
|
+
export type { HouseholdResource, HouseholdAttributes, NoteResource, NoteAttributes, ListResource, ListAttributes, OrganizationResource, OrganizationAttributes, CampusResource, CampusAttributes, CampusesList, } from './types';
|
|
11
11
|
export * from './types';
|
|
12
12
|
export type { PcoClientConfig as PcoClientConfigV1, PcoClientState } from './core';
|
|
13
13
|
export { createPcoClient, del, getAllPages, getList, getRateLimitInfo, getSingle, patch, post, } from './core';
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { BaseModule } from './base';
|
|
2
|
+
import type { PcoHttpClient } from '../core/http';
|
|
3
|
+
import type { PaginationHelper } from '../core/pagination';
|
|
4
|
+
import type { PcoEventEmitter } from '../monitoring';
|
|
5
|
+
import type { PaginationOptions, PaginationResult } from '../core/pagination';
|
|
6
|
+
import type { CampusResource, CampusAttributes, CampusesList } from '../types';
|
|
7
|
+
/**
|
|
8
|
+
* Campus module for managing campus-related operations
|
|
9
|
+
*/
|
|
10
|
+
export declare class CampusModule extends BaseModule {
|
|
11
|
+
constructor(httpClient: PcoHttpClient, paginationHelper: PaginationHelper, eventEmitter: PcoEventEmitter);
|
|
12
|
+
/**
|
|
13
|
+
* Get all campuses
|
|
14
|
+
*/
|
|
15
|
+
getAll(params?: {
|
|
16
|
+
where?: Record<string, any>;
|
|
17
|
+
include?: string[];
|
|
18
|
+
per_page?: number;
|
|
19
|
+
page?: number;
|
|
20
|
+
}): Promise<CampusesList>;
|
|
21
|
+
/**
|
|
22
|
+
* Get a specific campus by ID
|
|
23
|
+
*/
|
|
24
|
+
getById(id: string, include?: string[]): Promise<CampusResource>;
|
|
25
|
+
/**
|
|
26
|
+
* Create a new campus
|
|
27
|
+
*/
|
|
28
|
+
create(data: CampusAttributes): Promise<CampusResource>;
|
|
29
|
+
/**
|
|
30
|
+
* Update an existing campus
|
|
31
|
+
*/
|
|
32
|
+
update(id: string, data: Partial<CampusAttributes>): Promise<CampusResource>;
|
|
33
|
+
/**
|
|
34
|
+
* Delete a campus
|
|
35
|
+
*/
|
|
36
|
+
delete(id: string): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Get lists for a specific campus
|
|
39
|
+
*/
|
|
40
|
+
getLists(campusId: string, params?: {
|
|
41
|
+
where?: Record<string, any>;
|
|
42
|
+
include?: string[];
|
|
43
|
+
per_page?: number;
|
|
44
|
+
page?: number;
|
|
45
|
+
}): Promise<any>;
|
|
46
|
+
/**
|
|
47
|
+
* Get service times for a specific campus
|
|
48
|
+
*/
|
|
49
|
+
getServiceTimes(campusId: string, params?: {
|
|
50
|
+
where?: Record<string, any>;
|
|
51
|
+
include?: string[];
|
|
52
|
+
per_page?: number;
|
|
53
|
+
page?: number;
|
|
54
|
+
}): Promise<any>;
|
|
55
|
+
/**
|
|
56
|
+
* Get all campuses with pagination support
|
|
57
|
+
*/
|
|
58
|
+
getAllPagesPaginated(params?: {
|
|
59
|
+
where?: Record<string, any>;
|
|
60
|
+
include?: string[];
|
|
61
|
+
per_page?: number;
|
|
62
|
+
}, paginationOptions?: PaginationOptions): Promise<PaginationResult<CampusResource>>;
|
|
63
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CampusModule = void 0;
|
|
4
|
+
const base_1 = require("./base");
|
|
5
|
+
/**
|
|
6
|
+
* Campus module for managing campus-related operations
|
|
7
|
+
*/
|
|
8
|
+
class CampusModule extends base_1.BaseModule {
|
|
9
|
+
constructor(httpClient, paginationHelper, eventEmitter) {
|
|
10
|
+
super(httpClient, paginationHelper, eventEmitter);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Get all campuses
|
|
14
|
+
*/
|
|
15
|
+
async getAll(params) {
|
|
16
|
+
return this.getList('/campuses', params);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Get a specific campus by ID
|
|
20
|
+
*/
|
|
21
|
+
async getById(id, include) {
|
|
22
|
+
const params = {};
|
|
23
|
+
if (include) {
|
|
24
|
+
params.include = include.join(',');
|
|
25
|
+
}
|
|
26
|
+
return this.getSingle(`/campuses/${id}`, params);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Create a new campus
|
|
30
|
+
*/
|
|
31
|
+
async create(data) {
|
|
32
|
+
return this.createResource('/campuses', data);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Update an existing campus
|
|
36
|
+
*/
|
|
37
|
+
async update(id, data) {
|
|
38
|
+
return this.updateResource(`/campuses/${id}`, data);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Delete a campus
|
|
42
|
+
*/
|
|
43
|
+
async delete(id) {
|
|
44
|
+
return this.deleteResource(`/campuses/${id}`);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Get lists for a specific campus
|
|
48
|
+
*/
|
|
49
|
+
async getLists(campusId, params) {
|
|
50
|
+
return this.getList(`/campuses/${campusId}/lists`, params);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Get service times for a specific campus
|
|
54
|
+
*/
|
|
55
|
+
async getServiceTimes(campusId, params) {
|
|
56
|
+
return this.getList(`/campuses/${campusId}/service_times`, params);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get all campuses with pagination support
|
|
60
|
+
*/
|
|
61
|
+
async getAllPagesPaginated(params, paginationOptions) {
|
|
62
|
+
const queryParams = {};
|
|
63
|
+
if (params?.where) {
|
|
64
|
+
Object.entries(params.where).forEach(([key, value]) => {
|
|
65
|
+
queryParams[`where[${key}]`] = value;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
if (params?.include) {
|
|
69
|
+
queryParams.include = params.include.join(',');
|
|
70
|
+
}
|
|
71
|
+
if (params?.per_page) {
|
|
72
|
+
queryParams.per_page = params.per_page;
|
|
73
|
+
}
|
|
74
|
+
return this.getAllPages('/campuses', queryParams, paginationOptions);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.CampusModule = CampusModule;
|
|
@@ -181,6 +181,9 @@ function createTestClient(overrides = {}) {
|
|
|
181
181
|
auth: {
|
|
182
182
|
type: 'oauth',
|
|
183
183
|
accessToken: 'test-token',
|
|
184
|
+
refreshToken: 'test-refresh-token',
|
|
185
|
+
onRefresh: async () => { },
|
|
186
|
+
onRefreshFailure: async () => { },
|
|
184
187
|
},
|
|
185
188
|
};
|
|
186
189
|
const defaultMockConfig = {
|
|
@@ -239,6 +242,9 @@ function createErrorMockClient(errorType = 'network') {
|
|
|
239
242
|
auth: {
|
|
240
243
|
type: 'oauth',
|
|
241
244
|
accessToken: 'test-token',
|
|
245
|
+
refreshToken: 'test-refresh-token',
|
|
246
|
+
onRefresh: async () => { },
|
|
247
|
+
onRefreshFailure: async () => { },
|
|
242
248
|
},
|
|
243
249
|
};
|
|
244
250
|
const errorMockConfig = {
|
|
@@ -260,6 +266,9 @@ function createSlowMockClient(delayMs = 1000) {
|
|
|
260
266
|
auth: {
|
|
261
267
|
type: 'oauth',
|
|
262
268
|
accessToken: 'test-token',
|
|
269
|
+
refreshToken: 'test-refresh-token',
|
|
270
|
+
onRefresh: async () => { },
|
|
271
|
+
onRefreshFailure: async () => { },
|
|
263
272
|
},
|
|
264
273
|
};
|
|
265
274
|
const slowMockConfig = {
|
package/dist/types/client.d.ts
CHANGED
|
@@ -1,19 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* v2.0.0 Client Configuration Types
|
|
3
3
|
*/
|
|
4
|
+
/** Authentication configuration for Personal Access Token */
|
|
5
|
+
export interface PersonalAccessTokenAuth {
|
|
6
|
+
type: 'personal_access_token';
|
|
7
|
+
personalAccessToken: string;
|
|
8
|
+
}
|
|
9
|
+
/** Authentication configuration for OAuth 2.0 with required refresh handling */
|
|
10
|
+
export interface OAuthAuth {
|
|
11
|
+
type: 'oauth';
|
|
12
|
+
accessToken: string;
|
|
13
|
+
refreshToken: string;
|
|
14
|
+
onRefresh: (tokens: {
|
|
15
|
+
accessToken: string;
|
|
16
|
+
refreshToken: string;
|
|
17
|
+
}) => void | Promise<void>;
|
|
18
|
+
onRefreshFailure: (error: Error) => void | Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
/** Union type for authentication configurations */
|
|
21
|
+
export type PcoAuthConfig = PersonalAccessTokenAuth | OAuthAuth;
|
|
4
22
|
export interface PcoClientConfig {
|
|
5
23
|
/** Authentication configuration */
|
|
6
|
-
auth:
|
|
7
|
-
type: 'oauth' | 'personal_access_token';
|
|
8
|
-
accessToken?: string;
|
|
9
|
-
refreshToken?: string;
|
|
10
|
-
personalAccessToken?: string;
|
|
11
|
-
onRefresh?: (tokens: {
|
|
12
|
-
accessToken: string;
|
|
13
|
-
refreshToken?: string;
|
|
14
|
-
}) => void | Promise<void>;
|
|
15
|
-
onRefreshFailure?: (error: Error) => void | Promise<void>;
|
|
16
|
-
};
|
|
24
|
+
auth: PcoAuthConfig;
|
|
17
25
|
/** Caching configuration */
|
|
18
26
|
caching?: {
|
|
19
27
|
fieldDefinitions?: boolean;
|
package/dist/types/people.d.ts
CHANGED
|
@@ -376,4 +376,28 @@ export interface OrganizationStatisticResource extends ResourceObject<'Organizat
|
|
|
376
376
|
}
|
|
377
377
|
export type OrganizationStatisticsList = Paginated<OrganizationStatisticResource>;
|
|
378
378
|
export type OrganizationStatisticSingle = Response<OrganizationStatisticResource>;
|
|
379
|
-
export
|
|
379
|
+
export interface CampusAttributes extends Attributes {
|
|
380
|
+
latitude?: number;
|
|
381
|
+
longitude?: number;
|
|
382
|
+
description?: string;
|
|
383
|
+
street?: string;
|
|
384
|
+
city?: string;
|
|
385
|
+
state?: string;
|
|
386
|
+
zip?: string;
|
|
387
|
+
country?: string;
|
|
388
|
+
phone_number?: string;
|
|
389
|
+
website?: string;
|
|
390
|
+
twenty_four_hour_time?: boolean;
|
|
391
|
+
date_format?: number;
|
|
392
|
+
church_center_enabled?: boolean;
|
|
393
|
+
created_at?: string;
|
|
394
|
+
updated_at?: string;
|
|
395
|
+
}
|
|
396
|
+
export interface CampusRelationships {
|
|
397
|
+
organization?: Relationship;
|
|
398
|
+
}
|
|
399
|
+
export interface CampusResource extends ResourceObject<'Campus', CampusAttributes, CampusRelationships> {
|
|
400
|
+
}
|
|
401
|
+
export type CampusesList = Paginated<CampusResource>;
|
|
402
|
+
export type CampusSingle = Response<CampusResource>;
|
|
403
|
+
export type PeopleIncluded = EmailResource | AddressResource | PhoneNumberResource | HouseholdResource | SocialProfileResource | FieldDatumResource | TabResource | CampusResource;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rachelallyson/planning-center-people-ts",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.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",
|