@rachelallyson/planning-center-people-ts 2.9.0 โ 2.10.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 +49 -0
- package/dist/client-manager.js +5 -3
- package/dist/core/http.js +7 -3
- package/dist/helpers.d.ts +11 -0
- package/dist/helpers.js +24 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -2
- package/dist/matching/matcher.js +26 -18
- package/dist/matching/scoring.js +4 -11
- package/dist/modules/people.js +6 -6
- package/dist/types/people.d.ts +15 -15
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,55 @@ 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.10.0] - 2025-01-15
|
|
9
|
+
|
|
10
|
+
### โจ **New Features**
|
|
11
|
+
|
|
12
|
+
- **๐ง Email Normalization & Validation**: Added email normalization and format validation to improve search accuracy
|
|
13
|
+
- New `normalizeEmail()` helper function (lowercase and trim)
|
|
14
|
+
- Email is now normalized before search to improve PCO API search results
|
|
15
|
+
- Email format validation prevents wasted API calls on invalid emails
|
|
16
|
+
- **๐ฑ Phone Normalization**: Added phone normalization to improve search accuracy
|
|
17
|
+
- New `normalizePhone()` helper function (normalizes to `+1XXXXXXXXXX` format)
|
|
18
|
+
- Phone numbers are now normalized before search to improve PCO API search results
|
|
19
|
+
- **โ
First Name Validation**: Added firstName validation in person creation
|
|
20
|
+
- Validates firstName is required before attempting person creation
|
|
21
|
+
- Provides clearer error messages: "First name is required to create a person"
|
|
22
|
+
- Fails fast instead of waiting for API error response
|
|
23
|
+
|
|
24
|
+
### ๐ง **Improvements**
|
|
25
|
+
|
|
26
|
+
- **Normalization Consistency**: Refactored normalization logic into reusable helper functions
|
|
27
|
+
- All email/phone normalization now uses consistent helper functions
|
|
28
|
+
- Updated both `matcher.ts` and `scoring.ts` to use shared normalization functions
|
|
29
|
+
- Removed duplicate inline normalization code
|
|
30
|
+
|
|
31
|
+
### ๐ฆ **Exports**
|
|
32
|
+
|
|
33
|
+
- Exported `normalizeEmail` and `normalizePhone` helper functions from main package index for library users
|
|
34
|
+
|
|
35
|
+
## [2.9.1] - 2025-01-14
|
|
36
|
+
|
|
37
|
+
### ๐ **Bug Fixes**
|
|
38
|
+
|
|
39
|
+
- **Type System Accuracy**: Fixed TypeScript type definitions to match actual API responses
|
|
40
|
+
- Updated nullable fields to properly use `string | null` and `number | null` types
|
|
41
|
+
- Fixed `PersonAttributes`: `given_name`, `middle_name`, `nickname`, `anniversary`, `gender`, `grade`, `graduation_year`, `medical_notes`, `remote_id`, `inactivated_at` now correctly typed as `string | null`
|
|
42
|
+
- Fixed `CampusAttributes`: `latitude`, `longitude` now `string | null`; `phone_number`, `website` now `string | null`; `twenty_four_hour_time` now `boolean | null`; `date_format` now `number | null`
|
|
43
|
+
- Fixed `WorkflowCardAttributes`: `calculated_due_at_in_days_ago`, `snooze_until`, `removed_at`, `flagged_for_notification_at`, `moved_to_step_at` now correctly typed as nullable
|
|
44
|
+
- **Test Suite Fixes**: Fixed integration test expectations to match actual API behavior
|
|
45
|
+
- Relaxed relationship validation tests to make `links` optional (not always present in API responses)
|
|
46
|
+
- Fixed batch test data structure access to use `batchResult.data.data` (batch results wrap API responses)
|
|
47
|
+
- Fixed error handling tests to check error `status` property and use correct event name (`request:error`)
|
|
48
|
+
- Updated v2 service-time test to use `getAll()` instead of `getAllPagesPaginated()`
|
|
49
|
+
- Relaxed batch test expectations to handle API validation behavior
|
|
50
|
+
|
|
51
|
+
### ๐งช **Testing Improvements**
|
|
52
|
+
|
|
53
|
+
- Comprehensive integration test suite now passes (655+ tests)
|
|
54
|
+
- All type validation tests align with actual API response structures
|
|
55
|
+
- Error handling tests verify correct error structure and event emission
|
|
56
|
+
|
|
8
57
|
## [2.9.0] - 2025-01-14
|
|
9
58
|
|
|
10
59
|
### ๐ฏ **Matching Logic Improvements**
|
package/dist/client-manager.js
CHANGED
|
@@ -119,9 +119,11 @@ class PcoClientManager {
|
|
|
119
119
|
// Create a hash of the configuration
|
|
120
120
|
const configStr = JSON.stringify({
|
|
121
121
|
authType: config.auth.type,
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
122
|
+
accessToken: config.auth.type === 'oauth' ? config.auth.accessToken : undefined,
|
|
123
|
+
refreshToken: config.auth.type === 'oauth' ? config.auth.refreshToken : undefined,
|
|
124
|
+
personalAccessToken: config.auth.type === 'personal_access_token' ? config.auth.personalAccessToken : undefined,
|
|
125
|
+
appId: config.auth.type === 'basic' ? config.auth.appId : undefined,
|
|
126
|
+
appSecret: config.auth.type === 'basic' ? config.auth.appSecret : undefined,
|
|
125
127
|
baseURL: config.baseURL,
|
|
126
128
|
timeout: config.timeout,
|
|
127
129
|
});
|
package/dist/core/http.js
CHANGED
|
@@ -186,6 +186,10 @@ class PcoHttpClient {
|
|
|
186
186
|
}
|
|
187
187
|
catch (error) {
|
|
188
188
|
clearTimeout(timeoutId);
|
|
189
|
+
// Handle timeout/abort errors
|
|
190
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
191
|
+
throw new Error(`Request timeout after ${timeout}ms`);
|
|
192
|
+
}
|
|
189
193
|
throw error;
|
|
190
194
|
}
|
|
191
195
|
}
|
|
@@ -263,11 +267,11 @@ class PcoHttpClient {
|
|
|
263
267
|
const tokens = await response.json();
|
|
264
268
|
// Update the config with new tokens
|
|
265
269
|
this.config.auth.accessToken = tokens.access_token;
|
|
266
|
-
this.config.auth.refreshToken = tokens.refresh_token;
|
|
267
|
-
// Call the onRefresh callback
|
|
270
|
+
this.config.auth.refreshToken = tokens.refresh_token || this.config.auth.refreshToken;
|
|
271
|
+
// Call the onRefresh callback with the expected format
|
|
268
272
|
await this.config.auth.onRefresh({
|
|
269
273
|
accessToken: tokens.access_token,
|
|
270
|
-
refreshToken: tokens.refresh_token,
|
|
274
|
+
refreshToken: tokens.refresh_token || this.config.auth.refreshToken,
|
|
271
275
|
});
|
|
272
276
|
}
|
|
273
277
|
updateRateLimitTracking(endpoint, headers) {
|
package/dist/helpers.d.ts
CHANGED
|
@@ -44,10 +44,21 @@ export declare function calculateBirthYearFromAge(age: number): number;
|
|
|
44
44
|
* Validate email format
|
|
45
45
|
*/
|
|
46
46
|
export declare function isValidEmail(email: string): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Normalize email address (lowercase and trim)
|
|
49
|
+
*/
|
|
50
|
+
export declare function normalizeEmail(email: string): string;
|
|
47
51
|
/**
|
|
48
52
|
* Validate phone number format (basic validation)
|
|
49
53
|
*/
|
|
50
54
|
export declare function isValidPhone(phone: string): boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Normalize phone number to +1XXXXXXXXXX format
|
|
57
|
+
* - 10 digits: adds +1 prefix
|
|
58
|
+
* - 11 digits starting with 1: adds + prefix
|
|
59
|
+
* - Other lengths: adds + prefix to all digits
|
|
60
|
+
*/
|
|
61
|
+
export declare function normalizePhone(phone: string): string;
|
|
51
62
|
/**
|
|
52
63
|
* Format person name from attributes
|
|
53
64
|
*/
|
package/dist/helpers.js
CHANGED
|
@@ -8,7 +8,9 @@ exports.isChild = isChild;
|
|
|
8
8
|
exports.matchesAgeCriteria = matchesAgeCriteria;
|
|
9
9
|
exports.calculateBirthYearFromAge = calculateBirthYearFromAge;
|
|
10
10
|
exports.isValidEmail = isValidEmail;
|
|
11
|
+
exports.normalizeEmail = normalizeEmail;
|
|
11
12
|
exports.isValidPhone = isValidPhone;
|
|
13
|
+
exports.normalizePhone = normalizePhone;
|
|
12
14
|
exports.formatPersonName = formatPersonName;
|
|
13
15
|
exports.formatDate = formatDate;
|
|
14
16
|
exports.validatePersonData = validatePersonData;
|
|
@@ -137,6 +139,12 @@ function isValidEmail(email) {
|
|
|
137
139
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
138
140
|
return emailRegex.test(email);
|
|
139
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* Normalize email address (lowercase and trim)
|
|
144
|
+
*/
|
|
145
|
+
function normalizeEmail(email) {
|
|
146
|
+
return email.toLowerCase().trim();
|
|
147
|
+
}
|
|
140
148
|
/**
|
|
141
149
|
* Validate phone number format (basic validation)
|
|
142
150
|
*/
|
|
@@ -144,6 +152,22 @@ function isValidPhone(phone) {
|
|
|
144
152
|
const phoneRegex = /^[\+]?[1-9][\d]{6,14}$/;
|
|
145
153
|
return phoneRegex.test(phone.replace(/[\s\-\(\)]/g, ''));
|
|
146
154
|
}
|
|
155
|
+
/**
|
|
156
|
+
* Normalize phone number to +1XXXXXXXXXX format
|
|
157
|
+
* - 10 digits: adds +1 prefix
|
|
158
|
+
* - 11 digits starting with 1: adds + prefix
|
|
159
|
+
* - Other lengths: adds + prefix to all digits
|
|
160
|
+
*/
|
|
161
|
+
function normalizePhone(phone) {
|
|
162
|
+
const digits = phone.replace(/\D/g, '');
|
|
163
|
+
if (digits.length === 10) {
|
|
164
|
+
return `+1${digits}`;
|
|
165
|
+
}
|
|
166
|
+
if (digits.length === 11 && digits.startsWith('1')) {
|
|
167
|
+
return `+${digits}`;
|
|
168
|
+
}
|
|
169
|
+
return `+${digits}`;
|
|
170
|
+
}
|
|
147
171
|
/**
|
|
148
172
|
* Format person name from attributes
|
|
149
173
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ export type { ErrorContext } from '@rachelallyson/planning-center-base-ts';
|
|
|
20
20
|
export { ErrorCategory, ErrorSeverity, handleNetworkError, handleTimeoutError, handleValidationError, PcoError, retryWithBackoff, shouldNotRetry, withErrorBoundary, } from '@rachelallyson/planning-center-base-ts';
|
|
21
21
|
export { createFieldDefinition, createFieldOption, createPerson, createPersonAddress, createPersonEmail, createPersonFieldData, createPersonPhoneNumber, createPersonSocialProfile, createWorkflowCard, createWorkflowCardNote, deleteFieldDefinition, deletePerson, deletePersonFieldData, deleteSocialProfile, getFieldDefinitions, getFieldOptions, getHousehold, getHouseholds, getTabs, getListById, getListCategories, getLists, getNote, getNoteCategories, getNotes, getOrganization, getPeople, getPerson, getPersonAddresses, getPersonEmails, getPersonFieldData, getPersonPhoneNumbers, getPersonSocialProfiles, getWorkflow, getWorkflowCardNotes, getWorkflowCards, getWorkflows, updatePerson, updatePersonAddress, } from './people';
|
|
22
22
|
export { attemptRecovery, CircuitBreaker, classifyError, createErrorReport, DEFAULT_RETRY_CONFIG, executeBulkOperation, retryWithExponentialBackoff, TIMEOUT_CONFIG, withTimeout, } from './error-scenarios';
|
|
23
|
-
export { buildQueryParams, calculateAge, createPersonWithContact, createWorkflowCardWithNote, exportAllPeopleData, extractFileUrl, formatDate, formatPersonName, getCompletePersonProfile, getFileExtension, getFilename, getListsWithCategories, getOrganizationInfo, getPeopleByHousehold, getPersonWorkflowCardsWithNotes, getPrimaryContact, isFileUpload, isFileUrl, isValidEmail, isValidPhone, processFileValue, searchPeople, validatePersonData, } from './helpers';
|
|
23
|
+
export { buildQueryParams, calculateAge, createPersonWithContact, createWorkflowCardWithNote, exportAllPeopleData, extractFileUrl, formatDate, formatPersonName, getCompletePersonProfile, getFileExtension, getFilename, getListsWithCategories, getOrganizationInfo, getPeopleByHousehold, getPersonWorkflowCardsWithNotes, getPrimaryContact, isFileUpload, isFileUrl, isValidEmail, isValidPhone, normalizeEmail, normalizePhone, processFileValue, searchPeople, validatePersonData, } from './helpers';
|
|
24
24
|
export { AdaptiveRateLimiter, ApiCache, batchFetchPersonDetails, fetchAllPages, getCachedPeople, monitorPerformance, PerformanceMonitor, processInBatches, processLargeDataset, streamPeopleData, } from './performance';
|
|
25
25
|
export { MockPcoClient, MockResponseBuilder, RequestRecorder, createMockClient, createRecordingClient, createTestClient, createErrorMockClient, createSlowMockClient, } from './testing';
|
|
26
26
|
export type { MockClientConfig, RecordingConfig } from './testing';
|
package/dist/index.js
CHANGED
|
@@ -16,8 +16,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
};
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.getNotes = exports.getNoteCategories = exports.getNote = exports.getLists = exports.getListCategories = exports.getListById = exports.getTabs = exports.getHouseholds = exports.getHousehold = exports.getFieldOptions = exports.getFieldDefinitions = exports.deleteSocialProfile = exports.deletePersonFieldData = exports.deletePerson = exports.deleteFieldDefinition = exports.createWorkflowCardNote = exports.createWorkflowCard = exports.createPersonSocialProfile = exports.createPersonPhoneNumber = exports.createPersonFieldData = exports.createPersonEmail = exports.createPersonAddress = exports.createPerson = exports.createFieldOption = exports.createFieldDefinition = exports.withErrorBoundary = exports.shouldNotRetry = exports.retryWithBackoff = exports.PcoError = exports.handleValidationError = exports.handleTimeoutError = exports.handleNetworkError = exports.ErrorSeverity = exports.ErrorCategory = exports.PcoRateLimiter = exports.PcoApiError = exports.updateClientTokens = exports.refreshAccessToken = exports.hasRefreshTokenCapability = exports.attemptTokenRefresh = exports.post = exports.patch = exports.getSingle = exports.getRateLimitInfo = exports.getList = exports.getAllPages = exports.del = exports.createPcoClient = exports.PcoClientManager = exports.PcoClient = void 0;
|
|
19
|
-
exports.
|
|
20
|
-
exports.createSlowMockClient = exports.createErrorMockClient = exports.createTestClient = exports.createRecordingClient = exports.createMockClient = exports.RequestRecorder = exports.MockResponseBuilder = exports.MockPcoClient = exports.streamPeopleData = exports.processLargeDataset = exports.processInBatches = exports.PerformanceMonitor = exports.monitorPerformance = exports.getCachedPeople = void 0;
|
|
19
|
+
exports.ApiCache = exports.AdaptiveRateLimiter = exports.validatePersonData = exports.searchPeople = exports.processFileValue = exports.normalizePhone = exports.normalizeEmail = exports.isValidPhone = exports.isValidEmail = exports.isFileUrl = exports.isFileUpload = exports.getPrimaryContact = exports.getPersonWorkflowCardsWithNotes = exports.getPeopleByHousehold = exports.getOrganizationInfo = exports.getListsWithCategories = exports.getFilename = exports.getFileExtension = exports.getCompletePersonProfile = exports.formatPersonName = exports.formatDate = exports.extractFileUrl = exports.exportAllPeopleData = exports.createWorkflowCardWithNote = exports.createPersonWithContact = exports.calculateAge = exports.buildQueryParams = exports.withTimeout = exports.TIMEOUT_CONFIG = exports.retryWithExponentialBackoff = exports.executeBulkOperation = exports.DEFAULT_RETRY_CONFIG = exports.createErrorReport = exports.classifyError = exports.CircuitBreaker = exports.attemptRecovery = exports.updatePersonAddress = exports.updatePerson = exports.getWorkflows = exports.getWorkflowCards = exports.getWorkflowCardNotes = exports.getWorkflow = exports.getPersonSocialProfiles = exports.getPersonPhoneNumbers = exports.getPersonFieldData = exports.getPersonEmails = exports.getPersonAddresses = exports.getPerson = exports.getPeople = exports.getOrganization = void 0;
|
|
20
|
+
exports.createSlowMockClient = exports.createErrorMockClient = exports.createTestClient = exports.createRecordingClient = exports.createMockClient = exports.RequestRecorder = exports.MockResponseBuilder = exports.MockPcoClient = exports.streamPeopleData = exports.processLargeDataset = exports.processInBatches = exports.PerformanceMonitor = exports.monitorPerformance = exports.getCachedPeople = exports.fetchAllPages = exports.batchFetchPersonDetails = void 0;
|
|
21
21
|
// Main client class
|
|
22
22
|
var client_1 = require("./client");
|
|
23
23
|
Object.defineProperty(exports, "PcoClient", { enumerable: true, get: function () { return client_1.PcoClient; } });
|
|
@@ -130,6 +130,8 @@ Object.defineProperty(exports, "isFileUpload", { enumerable: true, get: function
|
|
|
130
130
|
Object.defineProperty(exports, "isFileUrl", { enumerable: true, get: function () { return helpers_1.isFileUrl; } });
|
|
131
131
|
Object.defineProperty(exports, "isValidEmail", { enumerable: true, get: function () { return helpers_1.isValidEmail; } });
|
|
132
132
|
Object.defineProperty(exports, "isValidPhone", { enumerable: true, get: function () { return helpers_1.isValidPhone; } });
|
|
133
|
+
Object.defineProperty(exports, "normalizeEmail", { enumerable: true, get: function () { return helpers_1.normalizeEmail; } });
|
|
134
|
+
Object.defineProperty(exports, "normalizePhone", { enumerable: true, get: function () { return helpers_1.normalizePhone; } });
|
|
133
135
|
Object.defineProperty(exports, "processFileValue", { enumerable: true, get: function () { return helpers_1.processFileValue; } });
|
|
134
136
|
Object.defineProperty(exports, "searchPeople", { enumerable: true, get: function () { return helpers_1.searchPeople; } });
|
|
135
137
|
Object.defineProperty(exports, "validatePersonData", { enumerable: true, get: function () { return helpers_1.validatePersonData; } });
|
package/dist/matching/matcher.js
CHANGED
|
@@ -50,20 +50,30 @@ class PersonMatcher {
|
|
|
50
50
|
// Step 1: Try email/phone search first
|
|
51
51
|
const emailPhoneMatches = [];
|
|
52
52
|
const nameOnlyMatches = [];
|
|
53
|
-
// Search by email
|
|
53
|
+
// Search by email (with normalization and validation)
|
|
54
54
|
if (email) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
// Validate email format to avoid wasted API calls
|
|
56
|
+
if (!(0, helpers_1.isValidEmail)(email)) {
|
|
57
|
+
console.warn('Invalid email format, skipping email search:', email);
|
|
58
58
|
}
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
else {
|
|
60
|
+
try {
|
|
61
|
+
// Normalize email before search to improve PCO search results
|
|
62
|
+
const normalizedEmail = (0, helpers_1.normalizeEmail)(email);
|
|
63
|
+
const emailResults = await this.peopleModule.search({ email: normalizedEmail });
|
|
64
|
+
emailPhoneMatches.push(...emailResults.data);
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
console.warn('Email search failed:', error);
|
|
68
|
+
}
|
|
61
69
|
}
|
|
62
70
|
}
|
|
63
|
-
// Search by phone
|
|
71
|
+
// Search by phone (with normalization)
|
|
64
72
|
if (phone) {
|
|
65
73
|
try {
|
|
66
|
-
|
|
74
|
+
// Normalize phone before search to improve PCO search results
|
|
75
|
+
const normalizedPhone = (0, helpers_1.normalizePhone)(phone);
|
|
76
|
+
const phoneResults = await this.peopleModule.search({ phone: normalizedPhone });
|
|
67
77
|
emailPhoneMatches.push(...phoneResults.data);
|
|
68
78
|
}
|
|
69
79
|
catch (error) {
|
|
@@ -203,8 +213,8 @@ class PersonMatcher {
|
|
|
203
213
|
async verifyEmailMatch(person, email) {
|
|
204
214
|
try {
|
|
205
215
|
const personEmails = await this.peopleModule.getEmails(person.id);
|
|
206
|
-
const normalizedSearchEmail =
|
|
207
|
-
const emails = personEmails.data?.map(e => e.attributes?.address
|
|
216
|
+
const normalizedSearchEmail = (0, helpers_1.normalizeEmail)(email);
|
|
217
|
+
const emails = personEmails.data?.map(e => (0, helpers_1.normalizeEmail)(e.attributes?.address || '')).filter(Boolean) || [];
|
|
208
218
|
return emails.includes(normalizedSearchEmail);
|
|
209
219
|
}
|
|
210
220
|
catch {
|
|
@@ -217,14 +227,8 @@ class PersonMatcher {
|
|
|
217
227
|
async verifyPhoneMatch(person, phone) {
|
|
218
228
|
try {
|
|
219
229
|
const personPhones = await this.peopleModule.getPhoneNumbers(person.id);
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
return digits.length === 10 ? `+1${digits}` :
|
|
223
|
-
digits.length === 11 && digits.startsWith('1') ? `+${digits}` :
|
|
224
|
-
`+${digits}`;
|
|
225
|
-
};
|
|
226
|
-
const normalizedSearchPhone = normalizePhone(phone);
|
|
227
|
-
const phones = personPhones.data?.map(p => normalizePhone(p.attributes?.number || '')).filter(Boolean) || [];
|
|
230
|
+
const normalizedSearchPhone = (0, helpers_1.normalizePhone)(phone);
|
|
231
|
+
const phones = personPhones.data?.map(p => (0, helpers_1.normalizePhone)(p.attributes?.number || '')).filter(Boolean) || [];
|
|
228
232
|
return phones.includes(normalizedSearchPhone);
|
|
229
233
|
}
|
|
230
234
|
catch {
|
|
@@ -294,6 +298,10 @@ class PersonMatcher {
|
|
|
294
298
|
* Create a new person
|
|
295
299
|
*/
|
|
296
300
|
async createPerson(options) {
|
|
301
|
+
// Validate firstName is required for person creation
|
|
302
|
+
if (!options.firstName?.trim()) {
|
|
303
|
+
throw new Error('First name is required to create a person');
|
|
304
|
+
}
|
|
297
305
|
// Create basic person data (only name fields)
|
|
298
306
|
const personData = {};
|
|
299
307
|
if (options.firstName)
|
package/dist/matching/scoring.js
CHANGED
|
@@ -98,9 +98,9 @@ class MatchScorer {
|
|
|
98
98
|
async scoreEmailMatch(person, email) {
|
|
99
99
|
try {
|
|
100
100
|
const personEmails = await this.peopleModule.getEmails(person.id);
|
|
101
|
-
const normalizedSearchEmail =
|
|
101
|
+
const normalizedSearchEmail = (0, helpers_1.normalizeEmail)(email);
|
|
102
102
|
// Check if any of the person's emails match
|
|
103
|
-
const emails = personEmails.data?.map(e => e.attributes?.address
|
|
103
|
+
const emails = personEmails.data?.map(e => (0, helpers_1.normalizeEmail)(e.attributes?.address || '')).filter(Boolean) || [];
|
|
104
104
|
return emails.includes(normalizedSearchEmail) ? 1.0 : 0.0;
|
|
105
105
|
}
|
|
106
106
|
catch (error) {
|
|
@@ -114,15 +114,8 @@ class MatchScorer {
|
|
|
114
114
|
async scorePhoneMatch(person, phone) {
|
|
115
115
|
try {
|
|
116
116
|
const personPhones = await this.peopleModule.getPhoneNumbers(person.id);
|
|
117
|
-
|
|
118
|
-
const
|
|
119
|
-
const digits = num.replace(/\D/g, '');
|
|
120
|
-
return digits.length === 10 ? `+1${digits}` :
|
|
121
|
-
digits.length === 11 && digits.startsWith('1') ? `+${digits}` :
|
|
122
|
-
`+${digits}`;
|
|
123
|
-
};
|
|
124
|
-
const normalizedSearchPhone = normalizePhone(phone);
|
|
125
|
-
const phones = personPhones.data?.map(p => normalizePhone(p.attributes?.number || '')).filter(Boolean) || [];
|
|
117
|
+
const normalizedSearchPhone = (0, helpers_1.normalizePhone)(phone);
|
|
118
|
+
const phones = personPhones.data?.map(p => (0, helpers_1.normalizePhone)(p.attributes?.number || '')).filter(Boolean) || [];
|
|
126
119
|
return phones.includes(normalizedSearchPhone) ? 1.0 : 0.0;
|
|
127
120
|
}
|
|
128
121
|
catch (error) {
|
package/dist/modules/people.js
CHANGED
|
@@ -89,7 +89,7 @@ class PeopleModule extends planning_center_base_ts_1.BaseModule {
|
|
|
89
89
|
return this.httpClient.request({
|
|
90
90
|
method: 'GET',
|
|
91
91
|
endpoint: `/campuses/${campusData.id}`
|
|
92
|
-
}).then(response => response.data);
|
|
92
|
+
}).then(response => response.data.data);
|
|
93
93
|
}
|
|
94
94
|
/**
|
|
95
95
|
* Set a person's primary campus
|
|
@@ -107,7 +107,7 @@ class PeopleModule extends planning_center_base_ts_1.BaseModule {
|
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
|
-
}).then(response => response.data);
|
|
110
|
+
}).then(response => response.data.data);
|
|
111
111
|
}
|
|
112
112
|
/**
|
|
113
113
|
* Remove a person's primary campus
|
|
@@ -125,7 +125,7 @@ class PeopleModule extends planning_center_base_ts_1.BaseModule {
|
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
|
-
}).then(response => response.data);
|
|
128
|
+
}).then(response => response.data.data);
|
|
129
129
|
}
|
|
130
130
|
/**
|
|
131
131
|
* Get a person's household
|
|
@@ -140,7 +140,7 @@ class PeopleModule extends planning_center_base_ts_1.BaseModule {
|
|
|
140
140
|
return this.httpClient.request({
|
|
141
141
|
method: 'GET',
|
|
142
142
|
endpoint: `/households/${householdData.id}`
|
|
143
|
-
}).then(response => response.data);
|
|
143
|
+
}).then(response => response.data.data);
|
|
144
144
|
}
|
|
145
145
|
/**
|
|
146
146
|
* Set a person's household
|
|
@@ -158,7 +158,7 @@ class PeopleModule extends planning_center_base_ts_1.BaseModule {
|
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
|
-
}).then(response => response.data);
|
|
161
|
+
}).then(response => response.data.data);
|
|
162
162
|
}
|
|
163
163
|
/**
|
|
164
164
|
* Remove a person from their household
|
|
@@ -176,7 +176,7 @@ class PeopleModule extends planning_center_base_ts_1.BaseModule {
|
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
|
-
}).then(response => response.data);
|
|
179
|
+
}).then(response => response.data.data);
|
|
180
180
|
}
|
|
181
181
|
/**
|
|
182
182
|
* Get all people in a specific household
|
package/dist/types/people.d.ts
CHANGED
|
@@ -6,16 +6,16 @@ import { Attributes, Paginated, Relationship, ResourceObject, Response } from '.
|
|
|
6
6
|
export interface PersonAttributes extends Attributes {
|
|
7
7
|
first_name?: string;
|
|
8
8
|
last_name?: string;
|
|
9
|
-
given_name?: string;
|
|
10
|
-
middle_name?: string;
|
|
11
|
-
nickname?: string;
|
|
9
|
+
given_name?: string | null;
|
|
10
|
+
middle_name?: string | null;
|
|
11
|
+
nickname?: string | null;
|
|
12
12
|
birthdate?: string;
|
|
13
|
-
anniversary?: string;
|
|
14
|
-
gender?: string;
|
|
15
|
-
grade?: string;
|
|
13
|
+
anniversary?: string | null;
|
|
14
|
+
gender?: string | null;
|
|
15
|
+
grade?: string | null;
|
|
16
16
|
child?: boolean;
|
|
17
17
|
status?: string;
|
|
18
|
-
medical_notes?: string;
|
|
18
|
+
medical_notes?: string | null;
|
|
19
19
|
created_at?: string;
|
|
20
20
|
updated_at?: string;
|
|
21
21
|
name?: string;
|
|
@@ -23,7 +23,7 @@ export interface PersonAttributes extends Attributes {
|
|
|
23
23
|
job_title?: string;
|
|
24
24
|
employer?: string;
|
|
25
25
|
school?: string;
|
|
26
|
-
graduation_year?: string;
|
|
26
|
+
graduation_year?: string | null;
|
|
27
27
|
avatar?: string;
|
|
28
28
|
site_administrator?: boolean;
|
|
29
29
|
accounting_administrator?: boolean;
|
|
@@ -315,7 +315,7 @@ export interface WorkflowCardAttributes extends Attributes {
|
|
|
315
315
|
stage?: string;
|
|
316
316
|
completed_at?: string | null;
|
|
317
317
|
overdue?: boolean;
|
|
318
|
-
calculated_due_at_in_days_ago?: number;
|
|
318
|
+
calculated_due_at_in_days_ago?: number | null;
|
|
319
319
|
flagged_for_notification_at?: string | null;
|
|
320
320
|
moved_to_step_at?: string | null;
|
|
321
321
|
snooze_until?: string | null;
|
|
@@ -385,18 +385,18 @@ export type OrganizationStatisticsList = Paginated<OrganizationStatisticResource
|
|
|
385
385
|
export type OrganizationStatisticSingle = Response<OrganizationStatisticResource>;
|
|
386
386
|
export interface CampusAttributes extends Attributes {
|
|
387
387
|
name: string;
|
|
388
|
-
latitude?:
|
|
389
|
-
longitude?:
|
|
388
|
+
latitude?: string | null;
|
|
389
|
+
longitude?: string | null;
|
|
390
390
|
description?: string;
|
|
391
391
|
street?: string;
|
|
392
392
|
city?: string;
|
|
393
393
|
state?: string;
|
|
394
394
|
zip?: string;
|
|
395
395
|
country?: string;
|
|
396
|
-
phone_number?: string;
|
|
397
|
-
website?: string;
|
|
398
|
-
twenty_four_hour_time?: boolean;
|
|
399
|
-
date_format?: number;
|
|
396
|
+
phone_number?: string | null;
|
|
397
|
+
website?: string | null;
|
|
398
|
+
twenty_four_hour_time?: boolean | null;
|
|
399
|
+
date_format?: number | null;
|
|
400
400
|
church_center_enabled?: boolean;
|
|
401
401
|
created_at?: string;
|
|
402
402
|
updated_at?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rachelallyson/planning-center-people-ts",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.10.0",
|
|
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",
|
|
@@ -69,6 +69,7 @@
|
|
|
69
69
|
"access": "public"
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
|
-
"@rachelallyson/planning-center-base-ts": "^1.0.0"
|
|
72
|
+
"@rachelallyson/planning-center-base-ts": "^1.0.0",
|
|
73
|
+
"form-data": "^4.0.4"
|
|
73
74
|
}
|
|
74
75
|
}
|