@rachelallyson/planning-center-people-ts 1.0.0 → 2.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 +248 -1
- package/README.md +28 -0
- package/dist/auth.d.ts +64 -0
- package/dist/auth.js +98 -0
- package/dist/batch.d.ts +47 -0
- package/dist/batch.js +376 -0
- package/dist/client-manager.d.ts +66 -0
- package/dist/client-manager.js +150 -0
- package/dist/client.d.ts +71 -0
- package/dist/client.js +123 -0
- package/dist/core/http.d.ts +47 -0
- package/dist/core/http.js +242 -0
- package/dist/core/pagination.d.ts +34 -0
- package/dist/core/pagination.js +164 -0
- package/dist/core.d.ts +5 -0
- package/dist/core.js +12 -0
- package/dist/helpers.d.ts +125 -100
- package/dist/helpers.js +315 -275
- package/dist/index.d.ts +17 -5
- package/dist/index.js +39 -5
- package/dist/matching/matcher.d.ts +41 -0
- package/dist/matching/matcher.js +161 -0
- package/dist/matching/scoring.d.ts +35 -0
- package/dist/matching/scoring.js +141 -0
- package/dist/matching/strategies.d.ts +35 -0
- package/dist/matching/strategies.js +79 -0
- package/dist/modules/base.d.ts +46 -0
- package/dist/modules/base.js +82 -0
- package/dist/modules/contacts.d.ts +103 -0
- package/dist/modules/contacts.js +130 -0
- package/dist/modules/fields.d.ts +157 -0
- package/dist/modules/fields.js +294 -0
- package/dist/modules/households.d.ts +42 -0
- package/dist/modules/households.js +74 -0
- package/dist/modules/lists.d.ts +62 -0
- package/dist/modules/lists.js +92 -0
- package/dist/modules/notes.d.ts +74 -0
- package/dist/modules/notes.js +125 -0
- package/dist/modules/people.d.ts +196 -0
- package/dist/modules/people.js +221 -0
- package/dist/modules/workflows.d.ts +131 -0
- package/dist/modules/workflows.js +221 -0
- package/dist/monitoring.d.ts +53 -0
- package/dist/monitoring.js +142 -0
- package/dist/people/contacts.d.ts +43 -0
- package/dist/people/contacts.js +122 -0
- package/dist/people/core.d.ts +28 -0
- package/dist/people/core.js +69 -0
- package/dist/people/fields.d.ts +62 -0
- package/dist/people/fields.js +293 -0
- package/dist/people/households.d.ts +15 -0
- package/dist/people/households.js +31 -0
- package/dist/people/index.d.ts +8 -0
- package/dist/people/index.js +25 -0
- package/dist/people/lists.d.ts +30 -0
- package/dist/people/lists.js +37 -0
- package/dist/people/notes.d.ts +30 -0
- package/dist/people/notes.js +37 -0
- package/dist/people/organization.d.ts +12 -0
- package/dist/people/organization.js +15 -0
- package/dist/people/workflows.d.ts +37 -0
- package/dist/people/workflows.js +75 -0
- package/dist/testing/index.d.ts +9 -0
- package/dist/testing/index.js +24 -0
- package/dist/testing/recorder.d.ts +58 -0
- package/dist/testing/recorder.js +195 -0
- package/dist/testing/simple-builders.d.ts +33 -0
- package/dist/testing/simple-builders.js +124 -0
- package/dist/testing/simple-factories.d.ts +91 -0
- package/dist/testing/simple-factories.js +279 -0
- package/dist/testing/types.d.ts +160 -0
- package/dist/testing/types.js +5 -0
- package/dist/types/batch.d.ts +50 -0
- package/dist/types/batch.js +5 -0
- package/dist/types/client.d.ts +81 -0
- package/dist/types/client.js +5 -0
- package/dist/types/events.d.ts +85 -0
- package/dist/types/events.js +5 -0
- package/dist/types/people.d.ts +73 -79
- package/package.json +14 -3
- package/dist/people.d.ts +0 -205
- package/dist/people.js +0 -598
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,26 @@
|
|
|
1
|
+
export { PcoClient } from './client';
|
|
2
|
+
export { PcoClientManager } from './client-manager';
|
|
3
|
+
export type { PcoClientConfig } from './types/client';
|
|
4
|
+
export type { PcoEvent, EventHandler, EventType } from './types/events';
|
|
5
|
+
export type { BatchOperation, BatchResult, BatchOptions, BatchSummary } from './types/batch';
|
|
6
|
+
export type { Paginated, Relationship, ResourceIdentifier, ResourceObject, } from './types';
|
|
7
|
+
export type { PersonResource, PersonAttributes, PersonSingle, PeopleList, EmailResource, EmailAttributes, PhoneNumberResource, PhoneNumberAttributes, AddressResource, AddressAttributes, SocialProfileResource, SocialProfileAttributes, } from './types';
|
|
8
|
+
export type { FieldDefinitionResource, FieldDefinitionAttributes, FieldDatumResource, FieldDatumAttributes, FieldOptionResource, FieldOptionAttributes, TabResource, TabAttributes, } from './types';
|
|
9
|
+
export type { WorkflowResource, WorkflowAttributes, WorkflowCardResource, WorkflowCardAttributes, WorkflowCardNoteResource, WorkflowCardNoteAttributes, } from './types';
|
|
10
|
+
export type { HouseholdResource, HouseholdAttributes, NoteResource, NoteAttributes, ListResource, ListAttributes, OrganizationResource, OrganizationAttributes, } from './types';
|
|
1
11
|
export * from './types';
|
|
2
|
-
export type { PcoClientConfig, PcoClientState } from './core';
|
|
12
|
+
export type { PcoClientConfig as PcoClientConfigV1, PcoClientState } from './core';
|
|
3
13
|
export { createPcoClient, del, getAllPages, getList, getRateLimitInfo, getSingle, patch, post, } from './core';
|
|
14
|
+
export type { TokenResponse, TokenRefreshCallback, TokenRefreshFailureCallback } from './auth';
|
|
15
|
+
export { attemptTokenRefresh, hasRefreshTokenCapability, refreshAccessToken, updateClientTokens, } from './auth';
|
|
4
16
|
export { PcoApiError } from './api-error';
|
|
5
17
|
export type { RateLimitHeaders, RateLimitInfo } from './rate-limiter';
|
|
6
18
|
export { PcoRateLimiter } from './rate-limiter';
|
|
7
19
|
export type { ErrorContext } from './error-handling';
|
|
8
20
|
export { ErrorCategory, ErrorSeverity, handleNetworkError, handleTimeoutError, handleValidationError, PcoError, retryWithBackoff, shouldNotRetry, withErrorBoundary, } from './error-handling';
|
|
9
|
-
export { createFieldOption, createPerson, createPersonAddress, createPersonEmail, createPersonFieldData,
|
|
10
|
-
export type { Paginated, Relationship, ResourceIdentifier, ResourceObject, } from './types';
|
|
11
|
-
export type { AddressAttributes, AddressesList, AddressResource, AddressSingle, EmailAttributes, EmailResource, EmailSingle, EmailsList, FieldDataList, FieldDataSingle, FieldDatumAttributes, FieldDatumRelationships, FieldDatumResource, FieldDefinitionAttributes, FieldDefinitionResource, FieldDefinitionSingle, FieldDefinitionsList, FieldOptionAttributes, FieldOptionResource, FieldOptionSingle, FieldOptionsList, HouseholdAttributes, HouseholdResource, HouseholdSingle, HouseholdsList, ListAttributes, ListCategoriesList, ListCategoryAttributes, ListCategoryResource, ListCategorySingle, ListResource, ListSingle, ListsList, NoteAttributes, NoteCategoriesList, NoteCategoryAttributes, NoteCategoryResource, NoteCategorySingle, NoteResource, NoteSingle, NotesList, OrganizationAttributes, OrganizationResource, OrganizationSingle, PeopleList, PersonAttributes, PersonRelationships, PersonResource, PersonSingle, PhoneNumberAttributes, PhoneNumberResource, PhoneNumberSingle, PhoneNumbersList, SocialProfileAttributes, SocialProfileResource, SocialProfileSingle, SocialProfilesList, WorkflowAttributes, WorkflowCardAttributes, WorkflowCardNoteAttributes, WorkflowCardNoteRelationships, WorkflowCardNoteResource, WorkflowCardNoteSingle, WorkflowCardNotesList, WorkflowCardRelationships, WorkflowCardResource, WorkflowCardSingle, WorkflowCardsList, WorkflowResource, WorkflowSingle, WorkflowsList, } from './types';
|
|
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';
|
|
12
22
|
export { attemptRecovery, CircuitBreaker, classifyError, createErrorReport, DEFAULT_RETRY_CONFIG, executeBulkOperation, retryWithExponentialBackoff, TIMEOUT_CONFIG, withTimeout, } from './error-scenarios';
|
|
13
|
-
export { calculateAge, createPersonWithContact, createWorkflowCardWithNote, exportAllPeopleData, formatDate, formatPersonName, getCompletePersonProfile, getListsWithCategories, getOrganizationInfo, getPeopleByHousehold, getPersonWorkflowCardsWithNotes, getPrimaryContact, isValidEmail, isValidPhone, 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, processFileValue, searchPeople, validatePersonData, } from './helpers';
|
|
14
24
|
export { AdaptiveRateLimiter, ApiCache, batchFetchPersonDetails, fetchAllPages, getCachedPeople, monitorPerformance, PerformanceMonitor, processInBatches, processLargeDataset, streamPeopleData, } from './performance';
|
|
25
|
+
export { MockPcoClient, MockResponseBuilder, RequestRecorder, createMockClient, createRecordingClient, createTestClient, createErrorMockClient, createSlowMockClient, } from './testing';
|
|
26
|
+
export type { MockClientConfig, RecordingConfig } from './testing';
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
// ===== v2.0.0 Main Exports =====
|
|
2
3
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
4
|
if (k2 === undefined) k2 = k;
|
|
4
5
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -14,9 +15,17 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
15
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
16
|
};
|
|
16
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.
|
|
18
|
-
exports.
|
|
19
|
-
|
|
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.fetchAllPages = exports.batchFetchPersonDetails = exports.ApiCache = exports.AdaptiveRateLimiter = exports.validatePersonData = exports.searchPeople = exports.processFileValue = 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 = void 0;
|
|
21
|
+
// Main client class
|
|
22
|
+
var client_1 = require("./client");
|
|
23
|
+
Object.defineProperty(exports, "PcoClient", { enumerable: true, get: function () { return client_1.PcoClient; } });
|
|
24
|
+
// Client manager for caching and lifecycle management
|
|
25
|
+
var client_manager_1 = require("./client-manager");
|
|
26
|
+
Object.defineProperty(exports, "PcoClientManager", { enumerable: true, get: function () { return client_manager_1.PcoClientManager; } });
|
|
27
|
+
// ===== v1.x Compatibility Exports (Deprecated) =====
|
|
28
|
+
// Export all types for backward compatibility
|
|
20
29
|
__exportStar(require("./types"), exports);
|
|
21
30
|
var core_1 = require("./core");
|
|
22
31
|
Object.defineProperty(exports, "createPcoClient", { enumerable: true, get: function () { return core_1.createPcoClient; } });
|
|
@@ -27,6 +36,11 @@ Object.defineProperty(exports, "getRateLimitInfo", { enumerable: true, get: func
|
|
|
27
36
|
Object.defineProperty(exports, "getSingle", { enumerable: true, get: function () { return core_1.getSingle; } });
|
|
28
37
|
Object.defineProperty(exports, "patch", { enumerable: true, get: function () { return core_1.patch; } });
|
|
29
38
|
Object.defineProperty(exports, "post", { enumerable: true, get: function () { return core_1.post; } });
|
|
39
|
+
var auth_1 = require("./auth");
|
|
40
|
+
Object.defineProperty(exports, "attemptTokenRefresh", { enumerable: true, get: function () { return auth_1.attemptTokenRefresh; } });
|
|
41
|
+
Object.defineProperty(exports, "hasRefreshTokenCapability", { enumerable: true, get: function () { return auth_1.hasRefreshTokenCapability; } });
|
|
42
|
+
Object.defineProperty(exports, "refreshAccessToken", { enumerable: true, get: function () { return auth_1.refreshAccessToken; } });
|
|
43
|
+
Object.defineProperty(exports, "updateClientTokens", { enumerable: true, get: function () { return auth_1.updateClientTokens; } });
|
|
30
44
|
// Export API error
|
|
31
45
|
var api_error_1 = require("./api-error");
|
|
32
46
|
Object.defineProperty(exports, "PcoApiError", { enumerable: true, get: function () { return api_error_1.PcoApiError; } });
|
|
@@ -42,24 +56,27 @@ Object.defineProperty(exports, "PcoError", { enumerable: true, get: function ()
|
|
|
42
56
|
Object.defineProperty(exports, "retryWithBackoff", { enumerable: true, get: function () { return error_handling_1.retryWithBackoff; } });
|
|
43
57
|
Object.defineProperty(exports, "shouldNotRetry", { enumerable: true, get: function () { return error_handling_1.shouldNotRetry; } });
|
|
44
58
|
Object.defineProperty(exports, "withErrorBoundary", { enumerable: true, get: function () { return error_handling_1.withErrorBoundary; } });
|
|
45
|
-
// Export People-specific functions
|
|
59
|
+
// Export People-specific functions (deprecated)
|
|
46
60
|
var people_1 = require("./people");
|
|
61
|
+
Object.defineProperty(exports, "createFieldDefinition", { enumerable: true, get: function () { return people_1.createFieldDefinition; } });
|
|
47
62
|
Object.defineProperty(exports, "createFieldOption", { enumerable: true, get: function () { return people_1.createFieldOption; } });
|
|
48
63
|
Object.defineProperty(exports, "createPerson", { enumerable: true, get: function () { return people_1.createPerson; } });
|
|
49
64
|
Object.defineProperty(exports, "createPersonAddress", { enumerable: true, get: function () { return people_1.createPersonAddress; } });
|
|
50
65
|
Object.defineProperty(exports, "createPersonEmail", { enumerable: true, get: function () { return people_1.createPersonEmail; } });
|
|
51
66
|
Object.defineProperty(exports, "createPersonFieldData", { enumerable: true, get: function () { return people_1.createPersonFieldData; } });
|
|
52
|
-
Object.defineProperty(exports, "createPersonFileFieldData", { enumerable: true, get: function () { return people_1.createPersonFileFieldData; } });
|
|
53
67
|
Object.defineProperty(exports, "createPersonPhoneNumber", { enumerable: true, get: function () { return people_1.createPersonPhoneNumber; } });
|
|
54
68
|
Object.defineProperty(exports, "createPersonSocialProfile", { enumerable: true, get: function () { return people_1.createPersonSocialProfile; } });
|
|
55
69
|
Object.defineProperty(exports, "createWorkflowCard", { enumerable: true, get: function () { return people_1.createWorkflowCard; } });
|
|
56
70
|
Object.defineProperty(exports, "createWorkflowCardNote", { enumerable: true, get: function () { return people_1.createWorkflowCardNote; } });
|
|
71
|
+
Object.defineProperty(exports, "deleteFieldDefinition", { enumerable: true, get: function () { return people_1.deleteFieldDefinition; } });
|
|
57
72
|
Object.defineProperty(exports, "deletePerson", { enumerable: true, get: function () { return people_1.deletePerson; } });
|
|
58
73
|
Object.defineProperty(exports, "deletePersonFieldData", { enumerable: true, get: function () { return people_1.deletePersonFieldData; } });
|
|
74
|
+
Object.defineProperty(exports, "deleteSocialProfile", { enumerable: true, get: function () { return people_1.deleteSocialProfile; } });
|
|
59
75
|
Object.defineProperty(exports, "getFieldDefinitions", { enumerable: true, get: function () { return people_1.getFieldDefinitions; } });
|
|
60
76
|
Object.defineProperty(exports, "getFieldOptions", { enumerable: true, get: function () { return people_1.getFieldOptions; } });
|
|
61
77
|
Object.defineProperty(exports, "getHousehold", { enumerable: true, get: function () { return people_1.getHousehold; } });
|
|
62
78
|
Object.defineProperty(exports, "getHouseholds", { enumerable: true, get: function () { return people_1.getHouseholds; } });
|
|
79
|
+
Object.defineProperty(exports, "getTabs", { enumerable: true, get: function () { return people_1.getTabs; } });
|
|
63
80
|
Object.defineProperty(exports, "getListById", { enumerable: true, get: function () { return people_1.getListById; } });
|
|
64
81
|
Object.defineProperty(exports, "getListCategories", { enumerable: true, get: function () { return people_1.getListCategories; } });
|
|
65
82
|
Object.defineProperty(exports, "getLists", { enumerable: true, get: function () { return people_1.getLists; } });
|
|
@@ -93,20 +110,27 @@ Object.defineProperty(exports, "TIMEOUT_CONFIG", { enumerable: true, get: functi
|
|
|
93
110
|
Object.defineProperty(exports, "withTimeout", { enumerable: true, get: function () { return error_scenarios_1.withTimeout; } });
|
|
94
111
|
// ===== Helper Functions =====
|
|
95
112
|
var helpers_1 = require("./helpers");
|
|
113
|
+
Object.defineProperty(exports, "buildQueryParams", { enumerable: true, get: function () { return helpers_1.buildQueryParams; } });
|
|
96
114
|
Object.defineProperty(exports, "calculateAge", { enumerable: true, get: function () { return helpers_1.calculateAge; } });
|
|
97
115
|
Object.defineProperty(exports, "createPersonWithContact", { enumerable: true, get: function () { return helpers_1.createPersonWithContact; } });
|
|
98
116
|
Object.defineProperty(exports, "createWorkflowCardWithNote", { enumerable: true, get: function () { return helpers_1.createWorkflowCardWithNote; } });
|
|
99
117
|
Object.defineProperty(exports, "exportAllPeopleData", { enumerable: true, get: function () { return helpers_1.exportAllPeopleData; } });
|
|
118
|
+
Object.defineProperty(exports, "extractFileUrl", { enumerable: true, get: function () { return helpers_1.extractFileUrl; } });
|
|
100
119
|
Object.defineProperty(exports, "formatDate", { enumerable: true, get: function () { return helpers_1.formatDate; } });
|
|
101
120
|
Object.defineProperty(exports, "formatPersonName", { enumerable: true, get: function () { return helpers_1.formatPersonName; } });
|
|
102
121
|
Object.defineProperty(exports, "getCompletePersonProfile", { enumerable: true, get: function () { return helpers_1.getCompletePersonProfile; } });
|
|
122
|
+
Object.defineProperty(exports, "getFileExtension", { enumerable: true, get: function () { return helpers_1.getFileExtension; } });
|
|
123
|
+
Object.defineProperty(exports, "getFilename", { enumerable: true, get: function () { return helpers_1.getFilename; } });
|
|
103
124
|
Object.defineProperty(exports, "getListsWithCategories", { enumerable: true, get: function () { return helpers_1.getListsWithCategories; } });
|
|
104
125
|
Object.defineProperty(exports, "getOrganizationInfo", { enumerable: true, get: function () { return helpers_1.getOrganizationInfo; } });
|
|
105
126
|
Object.defineProperty(exports, "getPeopleByHousehold", { enumerable: true, get: function () { return helpers_1.getPeopleByHousehold; } });
|
|
106
127
|
Object.defineProperty(exports, "getPersonWorkflowCardsWithNotes", { enumerable: true, get: function () { return helpers_1.getPersonWorkflowCardsWithNotes; } });
|
|
107
128
|
Object.defineProperty(exports, "getPrimaryContact", { enumerable: true, get: function () { return helpers_1.getPrimaryContact; } });
|
|
129
|
+
Object.defineProperty(exports, "isFileUpload", { enumerable: true, get: function () { return helpers_1.isFileUpload; } });
|
|
130
|
+
Object.defineProperty(exports, "isFileUrl", { enumerable: true, get: function () { return helpers_1.isFileUrl; } });
|
|
108
131
|
Object.defineProperty(exports, "isValidEmail", { enumerable: true, get: function () { return helpers_1.isValidEmail; } });
|
|
109
132
|
Object.defineProperty(exports, "isValidPhone", { enumerable: true, get: function () { return helpers_1.isValidPhone; } });
|
|
133
|
+
Object.defineProperty(exports, "processFileValue", { enumerable: true, get: function () { return helpers_1.processFileValue; } });
|
|
110
134
|
Object.defineProperty(exports, "searchPeople", { enumerable: true, get: function () { return helpers_1.searchPeople; } });
|
|
111
135
|
Object.defineProperty(exports, "validatePersonData", { enumerable: true, get: function () { return helpers_1.validatePersonData; } });
|
|
112
136
|
// ===== Performance Optimization =====
|
|
@@ -121,3 +145,13 @@ Object.defineProperty(exports, "PerformanceMonitor", { enumerable: true, get: fu
|
|
|
121
145
|
Object.defineProperty(exports, "processInBatches", { enumerable: true, get: function () { return performance_1.processInBatches; } });
|
|
122
146
|
Object.defineProperty(exports, "processLargeDataset", { enumerable: true, get: function () { return performance_1.processLargeDataset; } });
|
|
123
147
|
Object.defineProperty(exports, "streamPeopleData", { enumerable: true, get: function () { return performance_1.streamPeopleData; } });
|
|
148
|
+
// ===== Testing Utilities =====
|
|
149
|
+
var testing_1 = require("./testing");
|
|
150
|
+
Object.defineProperty(exports, "MockPcoClient", { enumerable: true, get: function () { return testing_1.MockPcoClient; } });
|
|
151
|
+
Object.defineProperty(exports, "MockResponseBuilder", { enumerable: true, get: function () { return testing_1.MockResponseBuilder; } });
|
|
152
|
+
Object.defineProperty(exports, "RequestRecorder", { enumerable: true, get: function () { return testing_1.RequestRecorder; } });
|
|
153
|
+
Object.defineProperty(exports, "createMockClient", { enumerable: true, get: function () { return testing_1.createMockClient; } });
|
|
154
|
+
Object.defineProperty(exports, "createRecordingClient", { enumerable: true, get: function () { return testing_1.createRecordingClient; } });
|
|
155
|
+
Object.defineProperty(exports, "createTestClient", { enumerable: true, get: function () { return testing_1.createTestClient; } });
|
|
156
|
+
Object.defineProperty(exports, "createErrorMockClient", { enumerable: true, get: function () { return testing_1.createErrorMockClient; } });
|
|
157
|
+
Object.defineProperty(exports, "createSlowMockClient", { enumerable: true, get: function () { return testing_1.createSlowMockClient; } });
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.0.0 Person Matching Logic
|
|
3
|
+
*/
|
|
4
|
+
import type { PeopleModule } from '../modules/people';
|
|
5
|
+
import type { PersonResource } from '../types';
|
|
6
|
+
import { PersonMatchOptions } from '../modules/people';
|
|
7
|
+
export interface MatchResult {
|
|
8
|
+
person: PersonResource;
|
|
9
|
+
score: number;
|
|
10
|
+
reason: string;
|
|
11
|
+
}
|
|
12
|
+
export declare class PersonMatcher {
|
|
13
|
+
private peopleModule;
|
|
14
|
+
private strategies;
|
|
15
|
+
private scorer;
|
|
16
|
+
constructor(peopleModule: PeopleModule);
|
|
17
|
+
/**
|
|
18
|
+
* Find or create a person with smart matching
|
|
19
|
+
*/
|
|
20
|
+
findOrCreate(options: PersonMatchOptions): Promise<PersonResource>;
|
|
21
|
+
/**
|
|
22
|
+
* Find the best match for a person
|
|
23
|
+
*/
|
|
24
|
+
findMatch(options: PersonMatchOptions): Promise<MatchResult | null>;
|
|
25
|
+
/**
|
|
26
|
+
* Get potential matching candidates
|
|
27
|
+
*/
|
|
28
|
+
private getCandidates;
|
|
29
|
+
/**
|
|
30
|
+
* Create a new person
|
|
31
|
+
*/
|
|
32
|
+
private createPerson;
|
|
33
|
+
/**
|
|
34
|
+
* Get all potential matches with detailed scoring
|
|
35
|
+
*/
|
|
36
|
+
getAllMatches(options: PersonMatchOptions): Promise<MatchResult[]>;
|
|
37
|
+
/**
|
|
38
|
+
* Check if a person matches the given criteria
|
|
39
|
+
*/
|
|
40
|
+
isMatch(personId: string, options: PersonMatchOptions): Promise<MatchResult | null>;
|
|
41
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* v2.0.0 Person Matching Logic
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PersonMatcher = void 0;
|
|
7
|
+
const strategies_1 = require("./strategies");
|
|
8
|
+
const scoring_1 = require("./scoring");
|
|
9
|
+
class PersonMatcher {
|
|
10
|
+
constructor(peopleModule) {
|
|
11
|
+
this.peopleModule = peopleModule;
|
|
12
|
+
this.strategies = new strategies_1.MatchStrategies();
|
|
13
|
+
this.scorer = new scoring_1.MatchScorer();
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Find or create a person with smart matching
|
|
17
|
+
*/
|
|
18
|
+
async findOrCreate(options) {
|
|
19
|
+
const { createIfNotFound = true, matchStrategy = 'fuzzy', ...searchOptions } = options;
|
|
20
|
+
// Try to find existing person
|
|
21
|
+
const match = await this.findMatch({ ...searchOptions, matchStrategy });
|
|
22
|
+
if (match) {
|
|
23
|
+
return match.person;
|
|
24
|
+
}
|
|
25
|
+
// Create new person if not found and creation is enabled
|
|
26
|
+
if (createIfNotFound) {
|
|
27
|
+
return this.createPerson(options);
|
|
28
|
+
}
|
|
29
|
+
throw new Error(`No matching person found and creation is disabled`);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Find the best match for a person
|
|
33
|
+
*/
|
|
34
|
+
async findMatch(options) {
|
|
35
|
+
const { matchStrategy = 'fuzzy' } = options;
|
|
36
|
+
// Get all potential matches
|
|
37
|
+
const candidates = await this.getCandidates(options);
|
|
38
|
+
if (candidates.length === 0) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
// Score and rank candidates
|
|
42
|
+
const scoredCandidates = candidates.map(candidate => ({
|
|
43
|
+
person: candidate,
|
|
44
|
+
score: this.scorer.scoreMatch(candidate, options),
|
|
45
|
+
reason: this.scorer.getMatchReason(candidate, options),
|
|
46
|
+
}));
|
|
47
|
+
// Sort by score (highest first)
|
|
48
|
+
scoredCandidates.sort((a, b) => b.score - a.score);
|
|
49
|
+
// Apply strategy-specific filtering
|
|
50
|
+
const bestMatch = this.strategies.selectBestMatch(scoredCandidates, matchStrategy);
|
|
51
|
+
return bestMatch;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Get potential matching candidates
|
|
55
|
+
*/
|
|
56
|
+
async getCandidates(options) {
|
|
57
|
+
const candidates = [];
|
|
58
|
+
const { email, phone, firstName, lastName } = options;
|
|
59
|
+
// Strategy 1: Exact email match
|
|
60
|
+
if (email) {
|
|
61
|
+
try {
|
|
62
|
+
const emailMatches = await this.peopleModule.search({ email });
|
|
63
|
+
candidates.push(...emailMatches.data);
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
// Email search failed, continue with other strategies
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Strategy 2: Exact phone match
|
|
70
|
+
if (phone) {
|
|
71
|
+
try {
|
|
72
|
+
const phoneMatches = await this.peopleModule.search({ phone });
|
|
73
|
+
candidates.push(...phoneMatches.data);
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
// Phone search failed, continue with other strategies
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Strategy 3: Name-based search
|
|
80
|
+
if (firstName && lastName) {
|
|
81
|
+
try {
|
|
82
|
+
const nameMatches = await this.peopleModule.search({
|
|
83
|
+
name: `${firstName} ${lastName}`
|
|
84
|
+
});
|
|
85
|
+
candidates.push(...nameMatches.data);
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
// Name search failed, continue with other strategies
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// Strategy 4: Broader search if no exact matches
|
|
92
|
+
if (candidates.length === 0 && (firstName || lastName)) {
|
|
93
|
+
try {
|
|
94
|
+
const broadMatches = await this.peopleModule.search({
|
|
95
|
+
name: firstName || lastName || '',
|
|
96
|
+
});
|
|
97
|
+
candidates.push(...broadMatches.data);
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
// Broad search failed
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Remove duplicates based on person ID
|
|
104
|
+
const uniqueCandidates = candidates.filter((person, index, self) => index === self.findIndex(p => p.id === person.id));
|
|
105
|
+
return uniqueCandidates;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Create a new person
|
|
109
|
+
*/
|
|
110
|
+
async createPerson(options) {
|
|
111
|
+
const personData = {};
|
|
112
|
+
if (options.firstName)
|
|
113
|
+
personData.first_name = options.firstName;
|
|
114
|
+
if (options.lastName)
|
|
115
|
+
personData.last_name = options.lastName;
|
|
116
|
+
if (options.email)
|
|
117
|
+
personData.email = options.email;
|
|
118
|
+
if (options.phone)
|
|
119
|
+
personData.phone = options.phone;
|
|
120
|
+
const person = await this.peopleModule.create(personData);
|
|
121
|
+
// Add contact information if provided
|
|
122
|
+
const contacts = {};
|
|
123
|
+
if (options.email) {
|
|
124
|
+
contacts.email = { address: options.email, primary: true };
|
|
125
|
+
}
|
|
126
|
+
if (options.phone) {
|
|
127
|
+
contacts.phone = { number: options.phone, primary: true };
|
|
128
|
+
}
|
|
129
|
+
if (Object.keys(contacts).length > 0) {
|
|
130
|
+
await this.peopleModule.createWithContacts(personData, contacts);
|
|
131
|
+
}
|
|
132
|
+
return person;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Get all potential matches with detailed scoring
|
|
136
|
+
*/
|
|
137
|
+
async getAllMatches(options) {
|
|
138
|
+
const candidates = await this.getCandidates(options);
|
|
139
|
+
return candidates.map(candidate => ({
|
|
140
|
+
person: candidate,
|
|
141
|
+
score: this.scorer.scoreMatch(candidate, options),
|
|
142
|
+
reason: this.scorer.getMatchReason(candidate, options),
|
|
143
|
+
})).sort((a, b) => b.score - a.score);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Check if a person matches the given criteria
|
|
147
|
+
*/
|
|
148
|
+
async isMatch(personId, options) {
|
|
149
|
+
const person = await this.peopleModule.getById(personId);
|
|
150
|
+
const score = this.scorer.scoreMatch(person, options);
|
|
151
|
+
if (score > 0.5) { // Threshold for considering it a match
|
|
152
|
+
return {
|
|
153
|
+
person,
|
|
154
|
+
score,
|
|
155
|
+
reason: this.scorer.getMatchReason(person, options),
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
exports.PersonMatcher = PersonMatcher;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.0.0 Person Match Scoring
|
|
3
|
+
*/
|
|
4
|
+
import type { PersonResource } from '../types';
|
|
5
|
+
import type { PersonMatchOptions } from '../modules/people';
|
|
6
|
+
export declare class MatchScorer {
|
|
7
|
+
/**
|
|
8
|
+
* Score a person match based on various criteria
|
|
9
|
+
*/
|
|
10
|
+
scoreMatch(person: PersonResource, options: PersonMatchOptions): number;
|
|
11
|
+
/**
|
|
12
|
+
* Get a human-readable reason for the match
|
|
13
|
+
*/
|
|
14
|
+
getMatchReason(person: PersonResource, options: PersonMatchOptions): string;
|
|
15
|
+
/**
|
|
16
|
+
* Score email matching
|
|
17
|
+
*/
|
|
18
|
+
private scoreEmailMatch;
|
|
19
|
+
/**
|
|
20
|
+
* Score phone matching
|
|
21
|
+
*/
|
|
22
|
+
private scorePhoneMatch;
|
|
23
|
+
/**
|
|
24
|
+
* Score name matching
|
|
25
|
+
*/
|
|
26
|
+
private scoreNameMatch;
|
|
27
|
+
/**
|
|
28
|
+
* Score additional criteria
|
|
29
|
+
*/
|
|
30
|
+
private scoreAdditionalCriteria;
|
|
31
|
+
/**
|
|
32
|
+
* Calculate string similarity using Levenshtein distance
|
|
33
|
+
*/
|
|
34
|
+
private calculateStringSimilarity;
|
|
35
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* v2.0.0 Person Match Scoring
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MatchScorer = void 0;
|
|
7
|
+
class MatchScorer {
|
|
8
|
+
/**
|
|
9
|
+
* Score a person match based on various criteria
|
|
10
|
+
*/
|
|
11
|
+
scoreMatch(person, options) {
|
|
12
|
+
let totalScore = 0;
|
|
13
|
+
let maxScore = 0;
|
|
14
|
+
// Email matching (highest weight)
|
|
15
|
+
if (options.email) {
|
|
16
|
+
const emailScore = this.scoreEmailMatch(person, options.email);
|
|
17
|
+
totalScore += emailScore * 0.4;
|
|
18
|
+
maxScore += 0.4;
|
|
19
|
+
}
|
|
20
|
+
// Phone matching (high weight)
|
|
21
|
+
if (options.phone) {
|
|
22
|
+
const phoneScore = this.scorePhoneMatch(person, options.phone);
|
|
23
|
+
totalScore += phoneScore * 0.3;
|
|
24
|
+
maxScore += 0.3;
|
|
25
|
+
}
|
|
26
|
+
// Name matching (medium weight)
|
|
27
|
+
if (options.firstName || options.lastName) {
|
|
28
|
+
const nameScore = this.scoreNameMatch(person, options);
|
|
29
|
+
totalScore += nameScore * 0.2;
|
|
30
|
+
maxScore += 0.2;
|
|
31
|
+
}
|
|
32
|
+
// Additional criteria (lower weight)
|
|
33
|
+
const additionalScore = this.scoreAdditionalCriteria(person, options);
|
|
34
|
+
totalScore += additionalScore * 0.1;
|
|
35
|
+
maxScore += 0.1;
|
|
36
|
+
return maxScore > 0 ? totalScore / maxScore : 0;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Get a human-readable reason for the match
|
|
40
|
+
*/
|
|
41
|
+
getMatchReason(person, options) {
|
|
42
|
+
const reasons = [];
|
|
43
|
+
if (options.email && this.scoreEmailMatch(person, options.email) > 0.8) {
|
|
44
|
+
reasons.push('exact email match');
|
|
45
|
+
}
|
|
46
|
+
if (options.phone && this.scorePhoneMatch(person, options.phone) > 0.8) {
|
|
47
|
+
reasons.push('exact phone match');
|
|
48
|
+
}
|
|
49
|
+
if (options.firstName || options.lastName) {
|
|
50
|
+
const nameScore = this.scoreNameMatch(person, options);
|
|
51
|
+
if (nameScore > 0.8) {
|
|
52
|
+
reasons.push('exact name match');
|
|
53
|
+
}
|
|
54
|
+
else if (nameScore > 0.6) {
|
|
55
|
+
reasons.push('similar name match');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (reasons.length === 0) {
|
|
59
|
+
return 'partial match';
|
|
60
|
+
}
|
|
61
|
+
return reasons.join(', ');
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Score email matching
|
|
65
|
+
*/
|
|
66
|
+
scoreEmailMatch(person, email) {
|
|
67
|
+
// This would need to check the person's emails
|
|
68
|
+
// For now, return a placeholder score
|
|
69
|
+
// In a real implementation, you'd fetch the person's emails and compare
|
|
70
|
+
return 0;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Score phone matching
|
|
74
|
+
*/
|
|
75
|
+
scorePhoneMatch(person, phone) {
|
|
76
|
+
// This would need to check the person's phone numbers
|
|
77
|
+
// For now, return a placeholder score
|
|
78
|
+
// In a real implementation, you'd fetch the person's phone numbers and compare
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Score name matching
|
|
83
|
+
*/
|
|
84
|
+
scoreNameMatch(person, options) {
|
|
85
|
+
const attrs = person.attributes;
|
|
86
|
+
if (!attrs)
|
|
87
|
+
return 0;
|
|
88
|
+
let score = 0;
|
|
89
|
+
// First name matching
|
|
90
|
+
if (options.firstName && attrs.first_name) {
|
|
91
|
+
const firstNameScore = this.calculateStringSimilarity(options.firstName.toLowerCase(), attrs.first_name.toLowerCase());
|
|
92
|
+
score += firstNameScore * 0.5;
|
|
93
|
+
}
|
|
94
|
+
// Last name matching
|
|
95
|
+
if (options.lastName && attrs.last_name) {
|
|
96
|
+
const lastNameScore = this.calculateStringSimilarity(options.lastName.toLowerCase(), attrs.last_name.toLowerCase());
|
|
97
|
+
score += lastNameScore * 0.5;
|
|
98
|
+
}
|
|
99
|
+
return score;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Score additional criteria
|
|
103
|
+
*/
|
|
104
|
+
scoreAdditionalCriteria(person, options) {
|
|
105
|
+
// Add scoring for other criteria like campus, status, etc.
|
|
106
|
+
return 0;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Calculate string similarity using Levenshtein distance
|
|
110
|
+
*/
|
|
111
|
+
calculateStringSimilarity(str1, str2) {
|
|
112
|
+
if (str1 === str2)
|
|
113
|
+
return 1;
|
|
114
|
+
if (str1.length === 0 || str2.length === 0)
|
|
115
|
+
return 0;
|
|
116
|
+
const matrix = [];
|
|
117
|
+
const len1 = str1.length;
|
|
118
|
+
const len2 = str2.length;
|
|
119
|
+
// Initialize matrix
|
|
120
|
+
for (let i = 0; i <= len1; i++) {
|
|
121
|
+
matrix[i] = [i];
|
|
122
|
+
}
|
|
123
|
+
for (let j = 0; j <= len2; j++) {
|
|
124
|
+
matrix[0][j] = j;
|
|
125
|
+
}
|
|
126
|
+
// Fill matrix
|
|
127
|
+
for (let i = 1; i <= len1; i++) {
|
|
128
|
+
for (let j = 1; j <= len2; j++) {
|
|
129
|
+
const cost = str1[i - 1] === str2[j - 1] ? 0 : 1;
|
|
130
|
+
matrix[i][j] = Math.min(matrix[i - 1][j] + 1, // deletion
|
|
131
|
+
matrix[i][j - 1] + 1, // insertion
|
|
132
|
+
matrix[i - 1][j - 1] + cost // substitution
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
const distance = matrix[len1][len2];
|
|
137
|
+
const maxLength = Math.max(len1, len2);
|
|
138
|
+
return 1 - distance / maxLength;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
exports.MatchScorer = MatchScorer;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v2.0.0 Person Matching Strategies
|
|
3
|
+
*/
|
|
4
|
+
import type { MatchResult } from './matcher';
|
|
5
|
+
export type MatchStrategy = 'exact' | 'fuzzy' | 'aggressive';
|
|
6
|
+
export declare class MatchStrategies {
|
|
7
|
+
/**
|
|
8
|
+
* Select the best match based on strategy
|
|
9
|
+
*/
|
|
10
|
+
selectBestMatch(candidates: MatchResult[], strategy: MatchStrategy): MatchResult | null;
|
|
11
|
+
/**
|
|
12
|
+
* Exact matching strategy - only return matches with very high confidence
|
|
13
|
+
*/
|
|
14
|
+
private selectExactMatch;
|
|
15
|
+
/**
|
|
16
|
+
* Fuzzy matching strategy - return best match above threshold
|
|
17
|
+
*/
|
|
18
|
+
private selectFuzzyMatch;
|
|
19
|
+
/**
|
|
20
|
+
* Aggressive matching strategy - return best match with lower threshold
|
|
21
|
+
*/
|
|
22
|
+
private selectAggressiveMatch;
|
|
23
|
+
/**
|
|
24
|
+
* Get all matches above threshold for a strategy
|
|
25
|
+
*/
|
|
26
|
+
getAllMatchesAboveThreshold(candidates: MatchResult[], strategy: MatchStrategy): MatchResult[];
|
|
27
|
+
/**
|
|
28
|
+
* Get the threshold for a strategy
|
|
29
|
+
*/
|
|
30
|
+
getThreshold(strategy: MatchStrategy): number;
|
|
31
|
+
/**
|
|
32
|
+
* Check if a score meets the strategy threshold
|
|
33
|
+
*/
|
|
34
|
+
meetsThreshold(score: number, strategy: MatchStrategy): boolean;
|
|
35
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* v2.0.0 Person Matching Strategies
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MatchStrategies = void 0;
|
|
7
|
+
class MatchStrategies {
|
|
8
|
+
/**
|
|
9
|
+
* Select the best match based on strategy
|
|
10
|
+
*/
|
|
11
|
+
selectBestMatch(candidates, strategy) {
|
|
12
|
+
if (candidates.length === 0) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
switch (strategy) {
|
|
16
|
+
case 'exact':
|
|
17
|
+
return this.selectExactMatch(candidates);
|
|
18
|
+
case 'fuzzy':
|
|
19
|
+
return this.selectFuzzyMatch(candidates);
|
|
20
|
+
case 'aggressive':
|
|
21
|
+
return this.selectAggressiveMatch(candidates);
|
|
22
|
+
default:
|
|
23
|
+
return this.selectFuzzyMatch(candidates);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Exact matching strategy - only return matches with very high confidence
|
|
28
|
+
*/
|
|
29
|
+
selectExactMatch(candidates) {
|
|
30
|
+
// Only return matches with score >= 0.9
|
|
31
|
+
const exactMatches = candidates.filter(c => c.score >= 0.9);
|
|
32
|
+
return exactMatches.length > 0 ? exactMatches[0] : null;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Fuzzy matching strategy - return best match above threshold
|
|
36
|
+
*/
|
|
37
|
+
selectFuzzyMatch(candidates) {
|
|
38
|
+
// Return best match with score >= 0.7
|
|
39
|
+
const fuzzyMatches = candidates.filter(c => c.score >= 0.7);
|
|
40
|
+
return fuzzyMatches.length > 0 ? fuzzyMatches[0] : null;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Aggressive matching strategy - return best match with lower threshold
|
|
44
|
+
*/
|
|
45
|
+
selectAggressiveMatch(candidates) {
|
|
46
|
+
// Return best match with score >= 0.5
|
|
47
|
+
const aggressiveMatches = candidates.filter(c => c.score >= 0.5);
|
|
48
|
+
return aggressiveMatches.length > 0 ? aggressiveMatches[0] : null;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Get all matches above threshold for a strategy
|
|
52
|
+
*/
|
|
53
|
+
getAllMatchesAboveThreshold(candidates, strategy) {
|
|
54
|
+
const threshold = this.getThreshold(strategy);
|
|
55
|
+
return candidates.filter(c => c.score >= threshold);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Get the threshold for a strategy
|
|
59
|
+
*/
|
|
60
|
+
getThreshold(strategy) {
|
|
61
|
+
switch (strategy) {
|
|
62
|
+
case 'exact':
|
|
63
|
+
return 0.9;
|
|
64
|
+
case 'fuzzy':
|
|
65
|
+
return 0.7;
|
|
66
|
+
case 'aggressive':
|
|
67
|
+
return 0.5;
|
|
68
|
+
default:
|
|
69
|
+
return 0.7;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Check if a score meets the strategy threshold
|
|
74
|
+
*/
|
|
75
|
+
meetsThreshold(score, strategy) {
|
|
76
|
+
return score >= this.getThreshold(strategy);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
exports.MatchStrategies = MatchStrategies;
|