@rachelallyson/planning-center-people-ts 1.1.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.
Files changed (56) hide show
  1. package/CHANGELOG.md +116 -0
  2. package/README.md +16 -0
  3. package/dist/batch.d.ts +47 -0
  4. package/dist/batch.js +376 -0
  5. package/dist/client-manager.d.ts +66 -0
  6. package/dist/client-manager.js +150 -0
  7. package/dist/client.d.ts +71 -0
  8. package/dist/client.js +123 -0
  9. package/dist/core/http.d.ts +47 -0
  10. package/dist/core/http.js +242 -0
  11. package/dist/core/pagination.d.ts +34 -0
  12. package/dist/core/pagination.js +164 -0
  13. package/dist/index.d.ts +13 -3
  14. package/dist/index.js +23 -5
  15. package/dist/matching/matcher.d.ts +41 -0
  16. package/dist/matching/matcher.js +161 -0
  17. package/dist/matching/scoring.d.ts +35 -0
  18. package/dist/matching/scoring.js +141 -0
  19. package/dist/matching/strategies.d.ts +35 -0
  20. package/dist/matching/strategies.js +79 -0
  21. package/dist/modules/base.d.ts +46 -0
  22. package/dist/modules/base.js +82 -0
  23. package/dist/modules/contacts.d.ts +103 -0
  24. package/dist/modules/contacts.js +130 -0
  25. package/dist/modules/fields.d.ts +157 -0
  26. package/dist/modules/fields.js +294 -0
  27. package/dist/modules/households.d.ts +42 -0
  28. package/dist/modules/households.js +74 -0
  29. package/dist/modules/lists.d.ts +62 -0
  30. package/dist/modules/lists.js +92 -0
  31. package/dist/modules/notes.d.ts +74 -0
  32. package/dist/modules/notes.js +125 -0
  33. package/dist/modules/people.d.ts +196 -0
  34. package/dist/modules/people.js +221 -0
  35. package/dist/modules/workflows.d.ts +131 -0
  36. package/dist/modules/workflows.js +221 -0
  37. package/dist/monitoring.d.ts +53 -0
  38. package/dist/monitoring.js +142 -0
  39. package/dist/testing/index.d.ts +9 -0
  40. package/dist/testing/index.js +24 -0
  41. package/dist/testing/recorder.d.ts +58 -0
  42. package/dist/testing/recorder.js +195 -0
  43. package/dist/testing/simple-builders.d.ts +33 -0
  44. package/dist/testing/simple-builders.js +124 -0
  45. package/dist/testing/simple-factories.d.ts +91 -0
  46. package/dist/testing/simple-factories.js +279 -0
  47. package/dist/testing/types.d.ts +160 -0
  48. package/dist/testing/types.js +5 -0
  49. package/dist/types/batch.d.ts +50 -0
  50. package/dist/types/batch.js +5 -0
  51. package/dist/types/client.d.ts +81 -0
  52. package/dist/types/client.js +5 -0
  53. package/dist/types/events.d.ts +85 -0
  54. package/dist/types/events.js +5 -0
  55. package/dist/types/people.d.ts +20 -1
  56. package/package.json +9 -3
@@ -0,0 +1,221 @@
1
+ "use strict";
2
+ /**
3
+ * v2.0.0 Workflows Module
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.WorkflowsModule = void 0;
7
+ const base_1 = require("./base");
8
+ class WorkflowsModule extends base_1.BaseModule {
9
+ /**
10
+ * Get all workflows
11
+ */
12
+ async getAll(options = {}) {
13
+ const params = {};
14
+ if (options.where) {
15
+ Object.entries(options.where).forEach(([key, value]) => {
16
+ params[`where[${key}]`] = value;
17
+ });
18
+ }
19
+ if (options.include) {
20
+ params.include = options.include.join(',');
21
+ }
22
+ if (options.perPage) {
23
+ params.per_page = options.perPage;
24
+ }
25
+ if (options.page) {
26
+ params.page = options.page;
27
+ }
28
+ return this.getList('/workflows', params);
29
+ }
30
+ /**
31
+ * Get all workflows across all pages
32
+ */
33
+ async getAllPagesPaginated(options = {}, paginationOptions) {
34
+ const params = {};
35
+ if (options.where) {
36
+ Object.entries(options.where).forEach(([key, value]) => {
37
+ params[`where[${key}]`] = value;
38
+ });
39
+ }
40
+ if (options.include) {
41
+ params.include = options.include.join(',');
42
+ }
43
+ return this.getAllPages('/workflows', params, paginationOptions);
44
+ }
45
+ /**
46
+ * Get a single workflow by ID
47
+ */
48
+ async getById(id, include) {
49
+ const params = {};
50
+ if (include) {
51
+ params.include = include.join(',');
52
+ }
53
+ return this.getSingle(`/workflows/${id}`, params);
54
+ }
55
+ /**
56
+ * Create a workflow
57
+ */
58
+ async create(data) {
59
+ return this.createResource('/workflows', data);
60
+ }
61
+ /**
62
+ * Update a workflow
63
+ */
64
+ async update(id, data) {
65
+ return this.updateResource(`/workflows/${id}`, data);
66
+ }
67
+ /**
68
+ * Delete a workflow
69
+ */
70
+ async delete(id) {
71
+ return this.deleteResource(`/workflows/${id}`);
72
+ }
73
+ /**
74
+ * Get workflow cards for a person
75
+ */
76
+ async getPersonWorkflowCards(personId) {
77
+ return this.getList(`/people/${personId}/workflow_cards`);
78
+ }
79
+ /**
80
+ * Add a person to a workflow with smart duplicate detection
81
+ */
82
+ async addPersonToWorkflow(personId, workflowId, options = {}) {
83
+ const { skipIfExists = true, skipIfActive = true } = options;
84
+ // Check for existing workflow cards if requested
85
+ if (skipIfExists || skipIfActive) {
86
+ const existingCards = await this.getPersonWorkflowCards(personId);
87
+ const existingCard = existingCards.data.find(card => {
88
+ const workflowData = card.relationships?.workflow?.data;
89
+ return workflowData && !Array.isArray(workflowData) && workflowData.id === workflowId;
90
+ });
91
+ if (existingCard && existingCard.attributes) {
92
+ // Check if card is completed or removed
93
+ if (skipIfExists && (existingCard.attributes.completed_at || existingCard.attributes.removed_at)) {
94
+ throw new Error(`Person already has a completed/removed card in this workflow`);
95
+ }
96
+ // Check if card is active
97
+ if (skipIfActive && !existingCard.attributes.completed_at && !existingCard.attributes.removed_at) {
98
+ throw new Error(`Person already has an active card in this workflow`);
99
+ }
100
+ }
101
+ }
102
+ // Create the workflow card
103
+ const workflowCard = await this.createResource(`/workflows/${workflowId}/cards`, {
104
+ person_id: personId,
105
+ });
106
+ // Add note if provided
107
+ if (options.note || options.noteTemplate) {
108
+ const noteText = options.note || this.formatNoteTemplate(options.noteTemplate, { personId, workflowId });
109
+ await this.createWorkflowCardNote(personId, workflowCard.id, { note: noteText });
110
+ }
111
+ return workflowCard;
112
+ }
113
+ /**
114
+ * Create a workflow card
115
+ */
116
+ async createWorkflowCard(workflowId, personId) {
117
+ return this.createResource(`/workflows/${workflowId}/cards`, {
118
+ person_id: personId,
119
+ });
120
+ }
121
+ /**
122
+ * Update a workflow card
123
+ */
124
+ async updateWorkflowCard(workflowCardId, data, personId) {
125
+ // If personId is provided, use the person-specific endpoint
126
+ if (personId) {
127
+ return this.updateResource(`/people/${personId}/workflow_cards/${workflowCardId}`, data);
128
+ }
129
+ // Fallback to the generic endpoint (may not work for all operations)
130
+ return this.updateResource(`/workflow_cards/${workflowCardId}`, data);
131
+ }
132
+ /**
133
+ * Get workflow card notes
134
+ */
135
+ async getWorkflowCardNotes(personId, workflowCardId) {
136
+ return this.getList(`/people/${personId}/workflow_cards/${workflowCardId}/notes`);
137
+ }
138
+ /**
139
+ * Create a workflow card note
140
+ */
141
+ async createWorkflowCardNote(personId, workflowCardId, data) {
142
+ return this.createResource(`/people/${personId}/workflow_cards/${workflowCardId}/notes`, data);
143
+ }
144
+ /**
145
+ * Update a workflow card note
146
+ */
147
+ async updateWorkflowCardNote(personId, workflowCardId, noteId, data) {
148
+ return this.updateResource(`/people/${personId}/workflow_cards/${workflowCardId}/notes/${noteId}`, data);
149
+ }
150
+ /**
151
+ * Delete a workflow card note
152
+ */
153
+ async deleteWorkflowCardNote(personId, workflowCardId, noteId) {
154
+ return this.deleteResource(`/people/${personId}/workflow_cards/${workflowCardId}/notes/${noteId}`);
155
+ }
156
+ /**
157
+ * Create a workflow card with a note
158
+ */
159
+ async createWorkflowCardWithNote(workflowId, personId, noteData) {
160
+ const workflowCard = await this.createWorkflowCard(workflowId, personId);
161
+ const note = await this.createWorkflowCardNote(personId, workflowCard.id, noteData);
162
+ return { workflowCard, note };
163
+ }
164
+ /**
165
+ * Move a workflow card back to the previous step
166
+ */
167
+ async goBackWorkflowCard(personId, workflowCardId) {
168
+ return this.createResource(`/people/${personId}/workflow_cards/${workflowCardId}/go_back`, {});
169
+ }
170
+ /**
171
+ * Move a workflow card to the next step
172
+ */
173
+ async promoteWorkflowCard(personId, workflowCardId) {
174
+ return this.createResource(`/people/${personId}/workflow_cards/${workflowCardId}/promote`, {});
175
+ }
176
+ /**
177
+ * Remove a workflow card
178
+ */
179
+ async removeWorkflowCard(personId, workflowCardId) {
180
+ return this.createResource(`/people/${personId}/workflow_cards/${workflowCardId}/remove`, {});
181
+ }
182
+ /**
183
+ * Restore a workflow card
184
+ */
185
+ async restoreWorkflowCard(personId, workflowCardId) {
186
+ return this.createResource(`/people/${personId}/workflow_cards/${workflowCardId}/restore`, {});
187
+ }
188
+ /**
189
+ * Send an email to the subject of the workflow card
190
+ */
191
+ async sendEmailWorkflowCard(personId, workflowCardId, data) {
192
+ return this.createResource(`/people/${personId}/workflow_cards/${workflowCardId}/send_email`, data);
193
+ }
194
+ /**
195
+ * Move a workflow card to the next step without completing the current step
196
+ */
197
+ async skipStepWorkflowCard(personId, workflowCardId) {
198
+ return this.createResource(`/people/${personId}/workflow_cards/${workflowCardId}/skip_step`, {});
199
+ }
200
+ /**
201
+ * Snooze a workflow card for a specific duration
202
+ */
203
+ async snoozeWorkflowCard(personId, workflowCardId, data) {
204
+ return this.createResource(`/people/${personId}/workflow_cards/${workflowCardId}/snooze`, data);
205
+ }
206
+ /**
207
+ * Unsnooze a workflow card
208
+ */
209
+ async unsnoozeWorkflowCard(personId, workflowCardId) {
210
+ return this.createResource(`/people/${personId}/workflow_cards/${workflowCardId}/unsnooze`, {});
211
+ }
212
+ /**
213
+ * Format note template with variables
214
+ */
215
+ formatNoteTemplate(template, variables) {
216
+ return template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
217
+ return variables[key] || match;
218
+ });
219
+ }
220
+ }
221
+ exports.WorkflowsModule = WorkflowsModule;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * v2.0.0 Event System and Monitoring
3
+ */
4
+ import type { PcoEvent, EventHandler, EventType, EventEmitter } from './types/events';
5
+ export declare class PcoEventEmitter implements EventEmitter {
6
+ private handlers;
7
+ on<T extends PcoEvent>(eventType: T['type'], handler: EventHandler<T>): void;
8
+ off<T extends PcoEvent>(eventType: T['type'], handler: EventHandler<T>): void;
9
+ emit<T extends PcoEvent>(event: T): void;
10
+ /** Remove all event handlers */
11
+ removeAllListeners(eventType?: EventType): void;
12
+ /** Get the number of listeners for an event type */
13
+ listenerCount(eventType: EventType): number;
14
+ /** Get all registered event types */
15
+ eventTypes(): EventType[];
16
+ }
17
+ /**
18
+ * Request ID generator for tracking requests
19
+ */
20
+ export declare class RequestIdGenerator {
21
+ private counter;
22
+ generate(): string;
23
+ }
24
+ /**
25
+ * Performance metrics collector
26
+ */
27
+ export declare class PerformanceMetrics {
28
+ private metrics;
29
+ record(operation: string, duration: number, success?: boolean): void;
30
+ getMetrics(): Record<string, {
31
+ count: number;
32
+ averageTime: number;
33
+ minTime: number;
34
+ maxTime: number;
35
+ errorRate: number;
36
+ }>;
37
+ reset(): void;
38
+ }
39
+ /**
40
+ * Rate limit tracker
41
+ */
42
+ export declare class RateLimitTracker {
43
+ private limits;
44
+ update(endpoint: string, limit: number, remaining: number, resetTime: number): void;
45
+ getRemaining(endpoint: string): number;
46
+ getResetTime(endpoint: string): number;
47
+ isRateLimited(endpoint: string): boolean;
48
+ getAllLimits(): Record<string, {
49
+ limit: number;
50
+ remaining: number;
51
+ resetTime: number;
52
+ }>;
53
+ }
@@ -0,0 +1,142 @@
1
+ "use strict";
2
+ /**
3
+ * v2.0.0 Event System and Monitoring
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.RateLimitTracker = exports.PerformanceMetrics = exports.RequestIdGenerator = exports.PcoEventEmitter = void 0;
7
+ class PcoEventEmitter {
8
+ constructor() {
9
+ this.handlers = new Map();
10
+ }
11
+ on(eventType, handler) {
12
+ if (!this.handlers.has(eventType)) {
13
+ this.handlers.set(eventType, new Set());
14
+ }
15
+ this.handlers.get(eventType).add(handler);
16
+ }
17
+ off(eventType, handler) {
18
+ const eventHandlers = this.handlers.get(eventType);
19
+ if (eventHandlers) {
20
+ eventHandlers.delete(handler);
21
+ if (eventHandlers.size === 0) {
22
+ this.handlers.delete(eventType);
23
+ }
24
+ }
25
+ }
26
+ emit(event) {
27
+ const eventHandlers = this.handlers.get(event.type);
28
+ if (eventHandlers) {
29
+ for (const handler of eventHandlers) {
30
+ try {
31
+ handler(event);
32
+ }
33
+ catch (error) {
34
+ console.error(`Error in event handler for ${event.type}:`, error);
35
+ }
36
+ }
37
+ }
38
+ }
39
+ /** Remove all event handlers */
40
+ removeAllListeners(eventType) {
41
+ if (eventType) {
42
+ this.handlers.delete(eventType);
43
+ }
44
+ else {
45
+ this.handlers.clear();
46
+ }
47
+ }
48
+ /** Get the number of listeners for an event type */
49
+ listenerCount(eventType) {
50
+ return this.handlers.get(eventType)?.size || 0;
51
+ }
52
+ /** Get all registered event types */
53
+ eventTypes() {
54
+ return Array.from(this.handlers.keys());
55
+ }
56
+ }
57
+ exports.PcoEventEmitter = PcoEventEmitter;
58
+ /**
59
+ * Request ID generator for tracking requests
60
+ */
61
+ class RequestIdGenerator {
62
+ constructor() {
63
+ this.counter = 0;
64
+ }
65
+ generate() {
66
+ return `req_${Date.now()}_${++this.counter}`;
67
+ }
68
+ }
69
+ exports.RequestIdGenerator = RequestIdGenerator;
70
+ /**
71
+ * Performance metrics collector
72
+ */
73
+ class PerformanceMetrics {
74
+ constructor() {
75
+ this.metrics = new Map();
76
+ }
77
+ record(operation, duration, success = true) {
78
+ const existing = this.metrics.get(operation) || {
79
+ count: 0,
80
+ totalTime: 0,
81
+ minTime: Infinity,
82
+ maxTime: 0,
83
+ errors: 0,
84
+ };
85
+ existing.count++;
86
+ existing.totalTime += duration;
87
+ existing.minTime = Math.min(existing.minTime, duration);
88
+ existing.maxTime = Math.max(existing.maxTime, duration);
89
+ if (!success) {
90
+ existing.errors++;
91
+ }
92
+ this.metrics.set(operation, existing);
93
+ }
94
+ getMetrics() {
95
+ const result = {};
96
+ for (const [operation, metrics] of this.metrics) {
97
+ result[operation] = {
98
+ count: metrics.count,
99
+ averageTime: metrics.totalTime / metrics.count,
100
+ minTime: metrics.minTime === Infinity ? 0 : metrics.minTime,
101
+ maxTime: metrics.maxTime,
102
+ errorRate: metrics.errors / metrics.count,
103
+ };
104
+ }
105
+ return result;
106
+ }
107
+ reset() {
108
+ this.metrics.clear();
109
+ }
110
+ }
111
+ exports.PerformanceMetrics = PerformanceMetrics;
112
+ /**
113
+ * Rate limit tracker
114
+ */
115
+ class RateLimitTracker {
116
+ constructor() {
117
+ this.limits = new Map();
118
+ }
119
+ update(endpoint, limit, remaining, resetTime) {
120
+ this.limits.set(endpoint, { limit, remaining, resetTime });
121
+ }
122
+ getRemaining(endpoint) {
123
+ const limit = this.limits.get(endpoint);
124
+ return limit?.remaining || 0;
125
+ }
126
+ getResetTime(endpoint) {
127
+ const limit = this.limits.get(endpoint);
128
+ return limit?.resetTime || 0;
129
+ }
130
+ isRateLimited(endpoint) {
131
+ const limit = this.limits.get(endpoint);
132
+ return limit ? limit.remaining <= 0 : false;
133
+ }
134
+ getAllLimits() {
135
+ const result = {};
136
+ for (const [endpoint, limit] of this.limits) {
137
+ result[endpoint] = limit;
138
+ }
139
+ return result;
140
+ }
141
+ }
142
+ exports.RateLimitTracker = RateLimitTracker;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * v2.0.0 Testing Utilities
3
+ */
4
+ export { SimpleMockResponseBuilder as MockResponseBuilder } from './simple-builders';
5
+ export { SimpleMockPcoClient as MockPcoClient, createSimpleMockClient as createMockClient, createTestClient, createErrorMockClient, createSlowMockClient } from './simple-factories';
6
+ export type { SimpleMockClientConfig as MockClientConfig } from './simple-factories';
7
+ export { RequestRecorder } from './recorder';
8
+ export type { RecordingConfig } from './types';
9
+ export declare function createRecordingClient(config: any, recordingConfig: any): any;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ /**
3
+ * v2.0.0 Testing Utilities
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.RequestRecorder = exports.createSlowMockClient = exports.createErrorMockClient = exports.createTestClient = exports.createMockClient = exports.MockPcoClient = exports.MockResponseBuilder = void 0;
7
+ exports.createRecordingClient = createRecordingClient;
8
+ // Export simplified versions that work without complex type issues
9
+ var simple_builders_1 = require("./simple-builders");
10
+ Object.defineProperty(exports, "MockResponseBuilder", { enumerable: true, get: function () { return simple_builders_1.SimpleMockResponseBuilder; } });
11
+ var simple_factories_1 = require("./simple-factories");
12
+ Object.defineProperty(exports, "MockPcoClient", { enumerable: true, get: function () { return simple_factories_1.SimpleMockPcoClient; } });
13
+ Object.defineProperty(exports, "createMockClient", { enumerable: true, get: function () { return simple_factories_1.createSimpleMockClient; } });
14
+ Object.defineProperty(exports, "createTestClient", { enumerable: true, get: function () { return simple_factories_1.createTestClient; } });
15
+ Object.defineProperty(exports, "createErrorMockClient", { enumerable: true, get: function () { return simple_factories_1.createErrorMockClient; } });
16
+ Object.defineProperty(exports, "createSlowMockClient", { enumerable: true, get: function () { return simple_factories_1.createSlowMockClient; } });
17
+ // Export recorder (simplified)
18
+ var recorder_1 = require("./recorder");
19
+ Object.defineProperty(exports, "RequestRecorder", { enumerable: true, get: function () { return recorder_1.RequestRecorder; } });
20
+ // Export createRecordingClient (simplified)
21
+ function createRecordingClient(config, recordingConfig) {
22
+ // Simplified implementation
23
+ return new (require('./simple-factories').SimpleMockPcoClient)(config);
24
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * v2.0.0 Request/Response Recorder
3
+ */
4
+ import type { RecordingConfig, RecordedRequest } from './types';
5
+ export declare class RequestRecorder {
6
+ private config;
7
+ private requests;
8
+ private isRecording;
9
+ constructor(config: RecordingConfig);
10
+ /**
11
+ * Start recording requests
12
+ */
13
+ startRecording(): void;
14
+ /**
15
+ * Stop recording and save to file
16
+ */
17
+ stopRecording(): void;
18
+ /**
19
+ * Record a request/response pair
20
+ */
21
+ recordRequest(endpoint: string, method: string, params: Record<string, any> | undefined, data: any, response: any): void;
22
+ /**
23
+ * Replay a recorded request
24
+ */
25
+ replayRequest(endpoint: string, method: string, params: Record<string, any> | undefined, data: any): any | null;
26
+ /**
27
+ * Check if we should record or replay
28
+ */
29
+ shouldRecord(endpoint: string, method: string): boolean;
30
+ /**
31
+ * Get all recorded requests
32
+ */
33
+ getRequests(): RecordedRequest[];
34
+ /**
35
+ * Clear recorded requests
36
+ */
37
+ clearRequests(): void;
38
+ /**
39
+ * Save the current session to file
40
+ */
41
+ private saveSession;
42
+ /**
43
+ * Load a session from file
44
+ */
45
+ private loadSession;
46
+ /**
47
+ * Ensure the record directory exists
48
+ */
49
+ private ensureRecordDirectory;
50
+ /**
51
+ * Compare two parameter objects
52
+ */
53
+ private compareParams;
54
+ /**
55
+ * Compare two data objects
56
+ */
57
+ private compareData;
58
+ }