@rachelallyson/planning-center-people-ts 2.14.0 → 3.0.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 +93 -7
- package/README.md +42 -4
- package/dist/auth.d.ts +1 -1
- package/dist/auth.js +14 -6
- package/dist/client.d.ts +33 -8
- package/dist/client.js +47 -22
- package/dist/core.d.ts +4 -2
- package/dist/core.js +3 -2
- package/dist/error-handling.d.ts +4 -4
- package/dist/error-handling.js +13 -2
- package/dist/error-scenarios.d.ts +11 -7
- package/dist/error-scenarios.js +26 -10
- package/dist/helpers.d.ts +124 -48
- package/dist/helpers.js +236 -93
- package/dist/index.d.ts +9 -7
- package/dist/index.js +31 -71
- package/dist/matching/matcher.d.ts +8 -4
- package/dist/matching/matcher.js +51 -58
- package/dist/matching/scoring.d.ts +9 -6
- package/dist/matching/scoring.js +18 -14
- package/dist/modules/campus.d.ts +31 -36
- package/dist/modules/campus.js +36 -49
- package/dist/modules/contacts.d.ts +33 -29
- package/dist/modules/contacts.js +36 -12
- package/dist/modules/fields.d.ts +42 -54
- package/dist/modules/fields.js +70 -100
- package/dist/modules/forms.d.ts +35 -24
- package/dist/modules/forms.js +41 -23
- package/dist/modules/households.d.ts +17 -19
- package/dist/modules/households.js +25 -34
- package/dist/modules/lists.d.ts +30 -28
- package/dist/modules/lists.js +55 -42
- package/dist/modules/notes.d.ts +32 -30
- package/dist/modules/notes.js +40 -52
- package/dist/modules/people.d.ts +83 -71
- package/dist/modules/people.js +323 -172
- package/dist/modules/reports.d.ts +18 -32
- package/dist/modules/reports.js +28 -40
- package/dist/modules/service-time.d.ts +19 -24
- package/dist/modules/service-time.js +28 -28
- package/dist/modules/workflows.d.ts +42 -47
- package/dist/modules/workflows.js +50 -53
- package/dist/performance.d.ts +14 -10
- package/dist/performance.js +61 -25
- package/dist/testing/recorder.js +11 -2
- package/dist/testing/simple-builders.d.ts +6 -4
- package/dist/testing/simple-builders.js +36 -49
- package/dist/testing/types.d.ts +4 -0
- package/dist/types/api-options.d.ts +380 -0
- package/dist/types/api-options.js +6 -0
- package/dist/types/client.d.ts +4 -2
- package/dist/types/client.js +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/people.d.ts +47 -9
- package/package.json +7 -7
- package/dist/core/http.d.ts +0 -56
- package/dist/core/http.js +0 -360
- package/dist/core/pagination.d.ts +0 -34
- package/dist/core/pagination.js +0 -178
- package/dist/people/contacts.d.ts +0 -43
- package/dist/people/contacts.js +0 -122
- package/dist/people/core.d.ts +0 -28
- package/dist/people/core.js +0 -69
- package/dist/people/fields.d.ts +0 -62
- package/dist/people/fields.js +0 -294
- package/dist/people/households.d.ts +0 -15
- package/dist/people/households.js +0 -31
- package/dist/people/index.d.ts +0 -8
- package/dist/people/index.js +0 -25
- package/dist/people/lists.d.ts +0 -34
- package/dist/people/lists.js +0 -48
- package/dist/people/notes.d.ts +0 -30
- package/dist/people/notes.js +0 -37
- package/dist/people/organization.d.ts +0 -12
- package/dist/people/organization.js +0 -15
- package/dist/people/workflows.d.ts +0 -37
- package/dist/people/workflows.js +0 -75
package/dist/error-scenarios.js
CHANGED
|
@@ -56,8 +56,12 @@ function isRetryableError(error, retryableStatuses) {
|
|
|
56
56
|
return retryableStatuses.includes(error.status);
|
|
57
57
|
}
|
|
58
58
|
// Network errors are generally retryable
|
|
59
|
-
if (error
|
|
60
|
-
|
|
59
|
+
if (error && typeof error === 'object' && 'name' in error && 'message' in error) {
|
|
60
|
+
const errorName = error.name;
|
|
61
|
+
const errorMessage = error.message;
|
|
62
|
+
if (errorName === 'TypeError' && typeof errorMessage === 'string' && errorMessage.includes('fetch')) {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
61
65
|
}
|
|
62
66
|
return false;
|
|
63
67
|
}
|
|
@@ -198,7 +202,11 @@ function classifyError(error) {
|
|
|
198
202
|
if (error instanceof planning_center_base_ts_1.PcoApiError) {
|
|
199
203
|
return classifyPcoError(error);
|
|
200
204
|
}
|
|
201
|
-
|
|
205
|
+
// Type guard for Error-like objects
|
|
206
|
+
const isErrorLike = (e) => {
|
|
207
|
+
return typeof e === 'object' && e !== null;
|
|
208
|
+
};
|
|
209
|
+
if (isErrorLike(error) && error.name === 'TypeError' && error.message?.includes('fetch')) {
|
|
202
210
|
return {
|
|
203
211
|
category: 'network',
|
|
204
212
|
retryable: true,
|
|
@@ -206,7 +214,7 @@ function classifyError(error) {
|
|
|
206
214
|
userMessage: 'Network connection error. Please check your internet connection.',
|
|
207
215
|
};
|
|
208
216
|
}
|
|
209
|
-
if (error.message
|
|
217
|
+
if (isErrorLike(error) && error.message?.includes('timeout')) {
|
|
210
218
|
return {
|
|
211
219
|
category: 'network',
|
|
212
220
|
retryable: true,
|
|
@@ -282,11 +290,14 @@ function classifyPcoError(error) {
|
|
|
282
290
|
userMessage: 'The requested resource was not found.',
|
|
283
291
|
};
|
|
284
292
|
}
|
|
293
|
+
const isErrorLike = (e) => {
|
|
294
|
+
return typeof e === 'object' && e !== null;
|
|
295
|
+
};
|
|
285
296
|
return {
|
|
286
297
|
category: 'unknown',
|
|
287
298
|
retryable: false,
|
|
288
299
|
severity: 'medium',
|
|
289
|
-
userMessage: error.message || 'An error occurred while processing your request.',
|
|
300
|
+
userMessage: (isErrorLike(error) && error.message) || 'An error occurred while processing your request.',
|
|
290
301
|
};
|
|
291
302
|
}
|
|
292
303
|
// ===== Error Recovery =====
|
|
@@ -329,6 +340,11 @@ async function attemptRecovery(operation, error, context) {
|
|
|
329
340
|
*/
|
|
330
341
|
function createErrorReport(error, context) {
|
|
331
342
|
const classification = classifyError(error);
|
|
343
|
+
// Type guard for error-like objects
|
|
344
|
+
const isErrorLike = (e) => {
|
|
345
|
+
return typeof e === 'object' && e !== null;
|
|
346
|
+
};
|
|
347
|
+
const errorObj = isErrorLike(error) ? error : {};
|
|
332
348
|
return {
|
|
333
349
|
classification,
|
|
334
350
|
context: {
|
|
@@ -340,11 +356,11 @@ function createErrorReport(error, context) {
|
|
|
340
356
|
requestInfo: context.requestInfo,
|
|
341
357
|
},
|
|
342
358
|
error: {
|
|
343
|
-
errors:
|
|
344
|
-
message:
|
|
345
|
-
name:
|
|
346
|
-
stack:
|
|
347
|
-
status:
|
|
359
|
+
errors: errorObj.errors,
|
|
360
|
+
message: errorObj.message || 'Unknown error',
|
|
361
|
+
name: errorObj.name || 'UnknownError',
|
|
362
|
+
stack: errorObj.stack,
|
|
363
|
+
status: errorObj.status,
|
|
348
364
|
},
|
|
349
365
|
operation: context.operation,
|
|
350
366
|
timestamp: new Date().toISOString(),
|
package/dist/helpers.d.ts
CHANGED
|
@@ -1,16 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
* Transform complex params object into flat query params for API calls
|
|
6
|
-
*/
|
|
7
|
-
export declare function buildQueryParams(params?: {
|
|
8
|
-
where?: Record<string, any>;
|
|
9
|
-
include?: string[];
|
|
10
|
-
per_page?: number;
|
|
11
|
-
page?: number;
|
|
12
|
-
filter?: string;
|
|
13
|
-
}): Record<string, any>;
|
|
1
|
+
import type { PcoClient } from './client';
|
|
2
|
+
import type { ResourceObject, ResourceIdentifier } from './types/json-api';
|
|
3
|
+
import { mapIncludedToRelationships as baseMapIncludedToRelationships } from '@rachelallyson/planning-center-base-ts';
|
|
4
|
+
import type { PersonAttributes, PersonResource, EmailAttributes, PhoneNumberAttributes, AddressAttributes, WorkflowCardNoteAttributes, PeopleList, ListsList, ListCategoriesList, EmailResource, PhoneNumberResource, AddressResource, FieldDatumResource, WorkflowCardResource, EmailsList, PhoneNumbersList, AddressesList, OrganizationResource, WorkflowCardNoteResource, Meta, TopLevelLinks, ListResource, HouseholdResource } from './types';
|
|
14
5
|
/**
|
|
15
6
|
* Calculate age from birthdate string
|
|
16
7
|
*/
|
|
@@ -131,7 +122,7 @@ export interface TrustResult {
|
|
|
131
122
|
* @param trustWindow - Trust window in milliseconds (default: 1 hour)
|
|
132
123
|
* @returns Object with trust decision, age, and reason
|
|
133
124
|
*
|
|
134
|
-
* @
|
|
125
|
+
* @gmail.com
|
|
135
126
|
* ```typescript
|
|
136
127
|
* const trust = calculateTrust(pcoInfo.personIdCreatedAt);
|
|
137
128
|
* if (trust.shouldTrust) {
|
|
@@ -166,7 +157,7 @@ export declare function validatePersonData(data: Partial<PersonAttributes>): {
|
|
|
166
157
|
/**
|
|
167
158
|
* Get primary contact information for a person
|
|
168
159
|
*/
|
|
169
|
-
export declare function getPrimaryContact(client:
|
|
160
|
+
export declare function getPrimaryContact(client: PcoClient, personId: string): Promise<{
|
|
170
161
|
email?: string;
|
|
171
162
|
phone?: string;
|
|
172
163
|
address?: string;
|
|
@@ -174,45 +165,61 @@ export declare function getPrimaryContact(client: PcoClientState, personId: stri
|
|
|
174
165
|
/**
|
|
175
166
|
* Create a person with contact information
|
|
176
167
|
*/
|
|
177
|
-
export declare function createPersonWithContact(client:
|
|
168
|
+
export declare function createPersonWithContact(client: PcoClient, personData: Partial<PersonAttributes>, contactData?: {
|
|
178
169
|
email?: Partial<EmailAttributes>;
|
|
179
170
|
phone?: Partial<PhoneNumberAttributes>;
|
|
180
171
|
address?: Partial<AddressAttributes>;
|
|
181
|
-
}
|
|
182
|
-
person:
|
|
183
|
-
email?:
|
|
184
|
-
phone?:
|
|
185
|
-
address?:
|
|
172
|
+
}): Promise<{
|
|
173
|
+
person: PersonResource;
|
|
174
|
+
email?: EmailResource;
|
|
175
|
+
phone?: PhoneNumberResource;
|
|
176
|
+
address?: AddressResource;
|
|
186
177
|
}>;
|
|
187
178
|
/**
|
|
188
179
|
* Search people by multiple criteria
|
|
189
180
|
*/
|
|
190
|
-
export declare function searchPeople(client:
|
|
181
|
+
export declare function searchPeople(client: PcoClient, criteria: {
|
|
191
182
|
status?: string;
|
|
192
183
|
name?: string;
|
|
193
184
|
email?: string;
|
|
194
|
-
|
|
195
|
-
|
|
185
|
+
perPage?: number;
|
|
186
|
+
page?: number;
|
|
187
|
+
}): Promise<PeopleList>;
|
|
196
188
|
/**
|
|
197
189
|
* Get people by household
|
|
198
190
|
*/
|
|
199
|
-
export declare function getPeopleByHousehold(client:
|
|
191
|
+
export declare function getPeopleByHousehold(client: PcoClient, householdId: string): Promise<{
|
|
192
|
+
data: import("@rachelallyson/planning-center-base-ts").FlattenedResource<"Person", PersonAttributes, import("./types").PersonRelationships, import("./types").PersonRelationshipMap>[];
|
|
193
|
+
totalCount: number;
|
|
194
|
+
pagesFetched: number;
|
|
195
|
+
duration: number;
|
|
196
|
+
meta?: Meta;
|
|
197
|
+
links?: TopLevelLinks;
|
|
198
|
+
}>;
|
|
200
199
|
/**
|
|
201
200
|
* Get complete person profile with all related data
|
|
202
201
|
*/
|
|
203
|
-
export declare function getCompletePersonProfile(client:
|
|
204
|
-
person:
|
|
205
|
-
emails:
|
|
206
|
-
phones:
|
|
207
|
-
addresses:
|
|
208
|
-
fieldData:
|
|
209
|
-
|
|
202
|
+
export declare function getCompletePersonProfile(client: PcoClient, personId: string): Promise<{
|
|
203
|
+
person: PersonResource;
|
|
204
|
+
emails: EmailsList;
|
|
205
|
+
phones: PhoneNumbersList;
|
|
206
|
+
addresses: AddressesList;
|
|
207
|
+
fieldData: {
|
|
208
|
+
data: FieldDatumResource[];
|
|
209
|
+
meta?: Meta;
|
|
210
|
+
links?: TopLevelLinks;
|
|
211
|
+
};
|
|
212
|
+
workflowCards: {
|
|
213
|
+
data: WorkflowCardResource[];
|
|
214
|
+
meta?: Meta;
|
|
215
|
+
links?: TopLevelLinks;
|
|
216
|
+
};
|
|
210
217
|
}>;
|
|
211
218
|
/**
|
|
212
219
|
* Get organization info with statistics
|
|
213
220
|
*/
|
|
214
|
-
export declare function getOrganizationInfo(client:
|
|
215
|
-
organization:
|
|
221
|
+
export declare function getOrganizationInfo(client: PcoClient): Promise<{
|
|
222
|
+
organization: OrganizationResource | null;
|
|
216
223
|
stats: {
|
|
217
224
|
totalPeople: number;
|
|
218
225
|
totalHouseholds: number;
|
|
@@ -222,42 +229,111 @@ export declare function getOrganizationInfo(client: PcoClientState, context?: Pa
|
|
|
222
229
|
/**
|
|
223
230
|
* Get lists with their categories
|
|
224
231
|
*/
|
|
225
|
-
export declare function getListsWithCategories(client:
|
|
232
|
+
export declare function getListsWithCategories(client: PcoClient): Promise<{
|
|
226
233
|
lists: ListsList;
|
|
227
234
|
categories: ListCategoriesList;
|
|
228
235
|
}>;
|
|
229
236
|
/**
|
|
230
237
|
* Get workflow cards with notes for a person
|
|
231
238
|
*/
|
|
232
|
-
export declare function getPersonWorkflowCardsWithNotes(client:
|
|
233
|
-
workflowCards:
|
|
239
|
+
export declare function getPersonWorkflowCardsWithNotes(client: PcoClient, personId: string): Promise<{
|
|
240
|
+
workflowCards: {
|
|
241
|
+
data: WorkflowCardResource[];
|
|
242
|
+
meta?: Meta;
|
|
243
|
+
links?: TopLevelLinks;
|
|
244
|
+
};
|
|
234
245
|
notes: {
|
|
235
|
-
[cardId: string]:
|
|
246
|
+
[cardId: string]: {
|
|
247
|
+
data: WorkflowCardNoteResource[];
|
|
248
|
+
meta?: Meta;
|
|
249
|
+
links?: TopLevelLinks;
|
|
250
|
+
};
|
|
236
251
|
};
|
|
237
252
|
}>;
|
|
238
253
|
/**
|
|
239
254
|
* Create a workflow card with a note
|
|
240
255
|
*/
|
|
241
|
-
export declare function createWorkflowCardWithNote(client:
|
|
242
|
-
workflowCard:
|
|
243
|
-
note:
|
|
256
|
+
export declare function createWorkflowCardWithNote(client: PcoClient, workflowId: string, personId: string, noteData: Partial<WorkflowCardNoteAttributes>): Promise<{
|
|
257
|
+
workflowCard: WorkflowCardResource;
|
|
258
|
+
note: WorkflowCardNoteResource;
|
|
244
259
|
}>;
|
|
245
260
|
/**
|
|
246
261
|
* Export all people data in a structured format
|
|
247
262
|
*/
|
|
248
|
-
export declare function exportAllPeopleData(client:
|
|
263
|
+
export declare function exportAllPeopleData(client: PcoClient, options?: {
|
|
249
264
|
includeInactive?: boolean;
|
|
250
265
|
includeFieldData?: boolean;
|
|
251
266
|
includeWorkflowCards?: boolean;
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
organization: any;
|
|
267
|
+
}): Promise<{
|
|
268
|
+
people: PersonResource[];
|
|
269
|
+
households: HouseholdResource[];
|
|
270
|
+
lists: ListResource[];
|
|
271
|
+
organization: OrganizationResource | null;
|
|
258
272
|
exportDate: string;
|
|
259
273
|
totalCount: number;
|
|
260
274
|
}>;
|
|
275
|
+
/**
|
|
276
|
+
* Find an included resource by type and id
|
|
277
|
+
*
|
|
278
|
+
* In JSON:API, relationships contain resource identifiers like { type: 'Email', id: '456' }
|
|
279
|
+
* This helper finds the full resource object from the included array.
|
|
280
|
+
*
|
|
281
|
+
* @param included - Array of included resources from JSON:API response
|
|
282
|
+
* @param type - Resource type to find
|
|
283
|
+
* @param id - Resource id to find
|
|
284
|
+
* @returns The matching resource object, or undefined if not found
|
|
285
|
+
*
|
|
286
|
+
* @example
|
|
287
|
+
* ```typescript
|
|
288
|
+
* const person = await client.people.getPage({ include: ['emails'] });
|
|
289
|
+
* // Data is flattened: person.data[0].emails is the resolved array
|
|
290
|
+
* const email = person.data[0].emails?.[0];
|
|
291
|
+
* console.log(email?.address); // 'john@gmail.com'
|
|
292
|
+
* ```
|
|
293
|
+
*/
|
|
294
|
+
export declare function findIncluded<T extends ResourceObject<string, any, any> = ResourceObject<string, any, any>>(included: ResourceObject<string, any, any>[] | undefined, type: string, id: string): T | undefined;
|
|
295
|
+
/**
|
|
296
|
+
* Resolve all resources from a relationship to their full included objects
|
|
297
|
+
*
|
|
298
|
+
* Takes a relationship's data array (which contains resource identifiers)
|
|
299
|
+
* and resolves them to full resource objects from the included array.
|
|
300
|
+
*
|
|
301
|
+
* @param included - Array of included resources from JSON:API response
|
|
302
|
+
* @param relationshipData - Relationship data array (from relationships.xxx.data)
|
|
303
|
+
* @returns Array of full resource objects, or empty array if none found
|
|
304
|
+
*
|
|
305
|
+
* @example
|
|
306
|
+
* ```typescript
|
|
307
|
+
* const person = await client.people.getPage({ include: ['emails', 'phone_numbers'] });
|
|
308
|
+
* // Data is flattened: person.data[0].emails is the resolved array
|
|
309
|
+
* const emails = person.data[0].emails ?? [];
|
|
310
|
+
* emails.forEach(email => console.log(email.address));
|
|
311
|
+
* ```
|
|
312
|
+
*/
|
|
313
|
+
export declare function resolveIncluded<T extends ResourceObject<string, any, any> = ResourceObject<string, any, any>>(included: ResourceObject<string, any, any>[] | undefined, relationshipData: ResourceIdentifier | ResourceIdentifier[] | null | undefined): T[];
|
|
314
|
+
/**
|
|
315
|
+
* Create a lookup map for included resources by type and id
|
|
316
|
+
*
|
|
317
|
+
* This is more efficient than calling findIncluded() multiple times.
|
|
318
|
+
*
|
|
319
|
+
* @param included - Array of included resources from JSON:API response
|
|
320
|
+
* @returns Map with key format "type:id" -> resource object
|
|
321
|
+
*
|
|
322
|
+
* @gmail.com
|
|
323
|
+
* ```typescript
|
|
324
|
+
* const person = await client.people.getPage({ include: ['emails', 'phone_numbers'] });
|
|
325
|
+
* const lookup = createIncludedLookup(person.included);
|
|
326
|
+
* const email = lookup.get('Email:456'); // Fast lookup
|
|
327
|
+
* ```
|
|
328
|
+
*/
|
|
329
|
+
export declare function createIncludedLookup(included: ResourceObject<string, any, any>[] | undefined): Map<string, ResourceObject<string, any, any>>;
|
|
330
|
+
/**
|
|
331
|
+
* Automatically map included resources to their relationships
|
|
332
|
+
*
|
|
333
|
+
* Re-exported from @rachelallyson/planning-center-base-ts for convenience.
|
|
334
|
+
* The mapping is now automatically applied in getList()/getPage() methods.
|
|
335
|
+
*/
|
|
336
|
+
export declare const mapIncludedToRelationships: typeof baseMapIncludedToRelationships;
|
|
261
337
|
/**
|
|
262
338
|
* Extracts clean URL from HTML markup that contains file links
|
|
263
339
|
* Handles cases like: <a href="https://onark.s3.us-east-1.amazonaws.com/file.pdf" download>View File: https://onark.s3.us-east-1.amazonaws.com/file.pdf</a>
|