@rachelallyson/planning-center-people-ts 2.8.0 → 2.9.1
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 +74 -0
- package/LICENSE +1 -1
- package/README.md +12 -14
- package/dist/client-manager.js +5 -3
- package/dist/client.d.ts +8 -8
- package/dist/client.js +8 -11
- package/dist/core/http.d.ts +1 -1
- package/dist/core/http.js +15 -11
- package/dist/core.d.ts +3 -3
- package/dist/core.js +4 -4
- package/dist/error-handling.d.ts +1 -1
- package/dist/error-handling.js +3 -3
- package/dist/error-scenarios.js +4 -4
- package/dist/index.d.ts +8 -8
- package/dist/index.js +15 -15
- package/dist/matching/matcher.d.ts +22 -0
- package/dist/matching/matcher.js +251 -20
- package/dist/matching/scoring.d.ts +9 -7
- package/dist/matching/scoring.js +49 -20
- package/dist/matching/strategies.d.ts +1 -0
- package/dist/matching/strategies.js +15 -2
- package/dist/modules/campus.d.ts +5 -5
- package/dist/modules/campus.js +2 -2
- package/dist/modules/contacts.d.ts +1 -1
- package/dist/modules/contacts.js +2 -2
- package/dist/modules/fields.d.ts +4 -4
- package/dist/modules/fields.js +2 -2
- package/dist/modules/forms.d.ts +7 -4
- package/dist/modules/forms.js +5 -2
- package/dist/modules/households.d.ts +2 -2
- package/dist/modules/households.js +2 -2
- package/dist/modules/lists.d.ts +2 -2
- package/dist/modules/lists.js +2 -2
- package/dist/modules/notes.d.ts +2 -2
- package/dist/modules/notes.js +2 -2
- package/dist/modules/people.d.ts +57 -5
- package/dist/modules/people.js +38 -8
- package/dist/modules/reports.d.ts +5 -5
- package/dist/modules/reports.js +2 -2
- package/dist/modules/service-time.d.ts +5 -5
- package/dist/modules/service-time.js +2 -2
- package/dist/modules/workflows.d.ts +2 -2
- package/dist/modules/workflows.js +2 -2
- package/dist/people/contacts.d.ts +1 -1
- package/dist/people/core.d.ts +1 -1
- package/dist/people/fields.d.ts +1 -1
- package/dist/people/fields.js +4 -4
- package/dist/people/households.d.ts +1 -1
- package/dist/people/lists.d.ts +1 -1
- package/dist/people/notes.d.ts +1 -1
- package/dist/people/organization.d.ts +1 -1
- package/dist/people/workflows.d.ts +1 -1
- package/dist/types/client.d.ts +3 -96
- package/dist/types/client.js +2 -0
- package/dist/types/index.d.ts +1 -2
- package/dist/types/index.js +0 -2
- package/dist/types/people.d.ts +15 -15
- package/package.json +15 -17
- package/dist/api-error.d.ts +0 -10
- package/dist/api-error.js +0 -32
- package/dist/batch.d.ts +0 -47
- package/dist/batch.js +0 -376
- package/dist/modules/base.d.ts +0 -46
- package/dist/modules/base.js +0 -82
- package/dist/monitoring.d.ts +0 -53
- package/dist/monitoring.js +0 -142
- package/dist/rate-limiter.d.ts +0 -79
- package/dist/rate-limiter.js +0 -137
- package/dist/types/batch.d.ts +0 -50
- package/dist/types/batch.js +0 -5
- package/dist/types/events.d.ts +0 -85
- package/dist/types/events.js +0 -5
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rachelallyson/planning-center-people-ts",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "A strictly typed TypeScript client for Planning Center Online People API with
|
|
3
|
+
"version": "2.9.1",
|
|
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",
|
|
7
7
|
"scripts": {
|
|
@@ -13,11 +13,9 @@
|
|
|
13
13
|
"test:watch": "jest --watch --testPathIgnorePatterns=integration.test.ts",
|
|
14
14
|
"test:coverage": "jest --coverage --testPathIgnorePatterns=integration.test.ts",
|
|
15
15
|
"test:ci": "jest --ci --coverage --watchAll=false --testPathIgnorePatterns=integration.test.ts",
|
|
16
|
-
"test:integration": "dotenv -e .env.test -- jest --testPathPatterns=integration.test.ts --setupFilesAfterEnv='<rootDir>/tests/integration-setup.ts' --testTimeout=
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"test:edge-cases": "jest --testPathPatterns=edge-cases.test.ts --testTimeout=30000",
|
|
20
|
-
"test:all": "npm run test && npm run test:edge-cases",
|
|
16
|
+
"test:integration": "dotenv -e .env.test -- jest --testPathPatterns=integration/.*.integration.test.ts --setupFilesAfterEnv='<rootDir>/tests/integration-setup.ts' --testTimeout=60000",
|
|
17
|
+
"docs": "typedoc",
|
|
18
|
+
"docs:watch": "typedoc --watch",
|
|
21
19
|
"prepublishOnly": "npm run build"
|
|
22
20
|
},
|
|
23
21
|
"keywords": [
|
|
@@ -29,26 +27,25 @@
|
|
|
29
27
|
"json-api",
|
|
30
28
|
"people",
|
|
31
29
|
"church",
|
|
32
|
-
"crm",
|
|
33
30
|
"client",
|
|
34
31
|
"sdk",
|
|
35
32
|
"rate-limiting",
|
|
36
33
|
"error-handling",
|
|
37
|
-
"performance",
|
|
38
|
-
"caching",
|
|
39
34
|
"batch-operations",
|
|
40
|
-
"smart-matching",
|
|
41
35
|
"fluent-api",
|
|
42
|
-
"event-system"
|
|
43
|
-
"client-manager"
|
|
36
|
+
"event-system"
|
|
44
37
|
],
|
|
45
|
-
"author": "Rachel
|
|
38
|
+
"author": "Rachel Allyson",
|
|
46
39
|
"license": "MIT",
|
|
47
40
|
"devDependencies": {
|
|
48
41
|
"@types/jest": "^30.0.0",
|
|
42
|
+
"@types/node": "^20.0.0",
|
|
49
43
|
"dotenv": "^16.6.1",
|
|
50
44
|
"jest": "^30.2.0",
|
|
51
45
|
"ts-jest": "^29.4.4",
|
|
46
|
+
"tslib": "^2.8.1",
|
|
47
|
+
"typedoc": "^0.28.14",
|
|
48
|
+
"typedoc-plugin-markdown": "^4.9.0",
|
|
52
49
|
"typescript": "^5.9.3"
|
|
53
50
|
},
|
|
54
51
|
"files": [
|
|
@@ -59,12 +56,12 @@
|
|
|
59
56
|
],
|
|
60
57
|
"repository": {
|
|
61
58
|
"type": "git",
|
|
62
|
-
"url": "https://github.com/rachelallyson/planning-center-
|
|
59
|
+
"url": "https://github.com/rachelallyson/planning-center-monorepo.git"
|
|
63
60
|
},
|
|
64
61
|
"bugs": {
|
|
65
|
-
"url": "https://github.com/rachelallyson/planning-center-
|
|
62
|
+
"url": "https://github.com/rachelallyson/planning-center-monorepo/issues"
|
|
66
63
|
},
|
|
67
|
-
"homepage": "https://github.com/rachelallyson/planning-center-
|
|
64
|
+
"homepage": "https://github.com/rachelallyson/planning-center-monorepo#readme",
|
|
68
65
|
"engines": {
|
|
69
66
|
"node": ">=16.0.0"
|
|
70
67
|
},
|
|
@@ -72,6 +69,7 @@
|
|
|
72
69
|
"access": "public"
|
|
73
70
|
},
|
|
74
71
|
"dependencies": {
|
|
72
|
+
"@rachelallyson/planning-center-base-ts": "^1.0.0",
|
|
75
73
|
"form-data": "^4.0.4"
|
|
76
74
|
}
|
|
77
75
|
}
|
package/dist/api-error.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { RateLimitHeaders } from './rate-limiter';
|
|
2
|
-
import type { ErrorObject as JsonApiError } from './types';
|
|
3
|
-
export declare class PcoApiError extends Error {
|
|
4
|
-
readonly status: number;
|
|
5
|
-
readonly statusText: string;
|
|
6
|
-
readonly errors: JsonApiError[];
|
|
7
|
-
readonly rateLimitHeaders?: RateLimitHeaders;
|
|
8
|
-
constructor(message: string, status: number, statusText: string, errors: JsonApiError[], rateLimitHeaders?: RateLimitHeaders);
|
|
9
|
-
static fromFetchError(response: Response, data?: unknown): PcoApiError;
|
|
10
|
-
}
|
package/dist/api-error.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PcoApiError = void 0;
|
|
4
|
-
// ===== PCO API Error =====
|
|
5
|
-
class PcoApiError extends Error {
|
|
6
|
-
constructor(message, status, statusText, errors, rateLimitHeaders) {
|
|
7
|
-
super(message);
|
|
8
|
-
this.name = 'PcoApiError';
|
|
9
|
-
this.status = status;
|
|
10
|
-
this.statusText = statusText;
|
|
11
|
-
this.errors = errors;
|
|
12
|
-
this.rateLimitHeaders = rateLimitHeaders;
|
|
13
|
-
}
|
|
14
|
-
static fromFetchError(response, data) {
|
|
15
|
-
const status = response.status;
|
|
16
|
-
const statusText = response.statusText;
|
|
17
|
-
const apiErrors = Array.isArray(data?.errors)
|
|
18
|
-
? data.errors || []
|
|
19
|
-
: [];
|
|
20
|
-
const rateLimitHeaders = {
|
|
21
|
-
'Retry-After': response.headers.get('retry-after') ?? undefined,
|
|
22
|
-
'X-PCO-API-Request-Rate-Count': response.headers.get('x-pco-api-request-rate-count') ?? undefined,
|
|
23
|
-
'X-PCO-API-Request-Rate-Limit': response.headers.get('x-pco-api-request-rate-limit') ?? undefined,
|
|
24
|
-
'X-PCO-API-Request-Rate-Period': response.headers.get('x-pco-api-request-rate-period') ?? undefined,
|
|
25
|
-
};
|
|
26
|
-
const message = apiErrors.length > 0
|
|
27
|
-
? apiErrors.map(e => e.detail ?? e.title ?? 'Unknown error').join('; ')
|
|
28
|
-
: statusText;
|
|
29
|
-
return new PcoApiError(message, status, statusText, apiErrors, rateLimitHeaders);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
exports.PcoApiError = PcoApiError;
|
package/dist/batch.d.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* v2.0.0 Batch Operations Executor
|
|
3
|
-
*/
|
|
4
|
-
import type { PcoClient } from './client';
|
|
5
|
-
import type { PcoEventEmitter } from './monitoring';
|
|
6
|
-
import type { BatchOperation, BatchOptions, BatchSummary } from './types/batch';
|
|
7
|
-
export declare class BatchExecutor {
|
|
8
|
-
private client;
|
|
9
|
-
private eventEmitter;
|
|
10
|
-
constructor(client: PcoClient, eventEmitter: PcoEventEmitter);
|
|
11
|
-
/**
|
|
12
|
-
* Execute a batch of operations
|
|
13
|
-
*/
|
|
14
|
-
execute<T = any>(operations: BatchOperation[], options?: BatchOptions): Promise<BatchSummary>;
|
|
15
|
-
/**
|
|
16
|
-
* Resolve operation dependencies and references
|
|
17
|
-
*/
|
|
18
|
-
private resolveOperations;
|
|
19
|
-
/**
|
|
20
|
-
* Resolve references in operation data
|
|
21
|
-
*/
|
|
22
|
-
private resolveReferences;
|
|
23
|
-
/**
|
|
24
|
-
* Resolve string references like "$0.id" or "$1.data.attributes.name"
|
|
25
|
-
*/
|
|
26
|
-
private resolveStringReferences;
|
|
27
|
-
/**
|
|
28
|
-
* Get nested value from object using dot notation
|
|
29
|
-
*/
|
|
30
|
-
private getNestedValue;
|
|
31
|
-
/**
|
|
32
|
-
* Find dependencies for an operation
|
|
33
|
-
*/
|
|
34
|
-
private findDependencies;
|
|
35
|
-
/**
|
|
36
|
-
* Execute a single operation
|
|
37
|
-
*/
|
|
38
|
-
private executeOperation;
|
|
39
|
-
/**
|
|
40
|
-
* Rollback successful operations
|
|
41
|
-
*/
|
|
42
|
-
private rollbackOperations;
|
|
43
|
-
/**
|
|
44
|
-
* Rollback a single operation
|
|
45
|
-
*/
|
|
46
|
-
private rollbackOperation;
|
|
47
|
-
}
|
package/dist/batch.js
DELETED
|
@@ -1,376 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* v2.0.0 Batch Operations Executor
|
|
4
|
-
*/
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.BatchExecutor = void 0;
|
|
7
|
-
class BatchExecutor {
|
|
8
|
-
constructor(client, eventEmitter) {
|
|
9
|
-
this.client = client;
|
|
10
|
-
this.eventEmitter = eventEmitter;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Execute a batch of operations
|
|
14
|
-
*/
|
|
15
|
-
async execute(operations, options = {}) {
|
|
16
|
-
const { continueOnError = true, maxConcurrency = 5, enableRollback = false, onOperationComplete, onBatchComplete, } = options;
|
|
17
|
-
const startTime = Date.now();
|
|
18
|
-
const results = [];
|
|
19
|
-
const successfulOperations = [];
|
|
20
|
-
try {
|
|
21
|
-
// Resolve operation dependencies and references
|
|
22
|
-
const resolvedOperations = await this.resolveOperations(operations);
|
|
23
|
-
// Execute operations with dependency resolution
|
|
24
|
-
const semaphore = new Semaphore(maxConcurrency);
|
|
25
|
-
const operationResults = new Map();
|
|
26
|
-
const executeOperationWithDependencies = async (operation, index) => {
|
|
27
|
-
// Wait for dependencies to complete
|
|
28
|
-
if (operation.dependencies && operation.dependencies.length > 0) {
|
|
29
|
-
const dependencyPromises = operation.dependencies.map(depId => {
|
|
30
|
-
// Handle index-based dependencies
|
|
31
|
-
if (depId.startsWith('$index_')) {
|
|
32
|
-
const depIndex = parseInt(depId.substring(7));
|
|
33
|
-
const depOperation = resolvedOperations[depIndex];
|
|
34
|
-
if (!depOperation) {
|
|
35
|
-
throw new Error(`Dependency at index ${depIndex} not found`);
|
|
36
|
-
}
|
|
37
|
-
const depResult = operationResults.get(depOperation.id);
|
|
38
|
-
if (!depResult) {
|
|
39
|
-
throw new Error(`Dependency '${depOperation.id}' not found in operations list`);
|
|
40
|
-
}
|
|
41
|
-
return depResult;
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
// Handle operation ID-based dependencies
|
|
45
|
-
const depResult = operationResults.get(depId);
|
|
46
|
-
if (!depResult) {
|
|
47
|
-
throw new Error(`Dependency '${depId}' not found in operations list`);
|
|
48
|
-
}
|
|
49
|
-
return depResult;
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
|
-
await Promise.all(dependencyPromises);
|
|
53
|
-
}
|
|
54
|
-
await semaphore.acquire();
|
|
55
|
-
try {
|
|
56
|
-
// Create a function to get current results for reference resolution
|
|
57
|
-
const getCurrentResults = () => results;
|
|
58
|
-
const result = await this.executeOperation(operation, getCurrentResults);
|
|
59
|
-
const batchResult = {
|
|
60
|
-
index,
|
|
61
|
-
operation,
|
|
62
|
-
success: true,
|
|
63
|
-
data: result,
|
|
64
|
-
};
|
|
65
|
-
results.push(batchResult);
|
|
66
|
-
successfulOperations.push(operation);
|
|
67
|
-
onOperationComplete?.(batchResult);
|
|
68
|
-
return batchResult;
|
|
69
|
-
}
|
|
70
|
-
catch (error) {
|
|
71
|
-
const batchResult = {
|
|
72
|
-
index,
|
|
73
|
-
operation,
|
|
74
|
-
success: false,
|
|
75
|
-
error: error,
|
|
76
|
-
};
|
|
77
|
-
results.push(batchResult);
|
|
78
|
-
if (!continueOnError) {
|
|
79
|
-
throw error;
|
|
80
|
-
}
|
|
81
|
-
onOperationComplete?.(batchResult);
|
|
82
|
-
return batchResult;
|
|
83
|
-
}
|
|
84
|
-
finally {
|
|
85
|
-
semaphore.release();
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
// Create promises for all operations
|
|
89
|
-
const operationPromises = resolvedOperations.map((operation, index) => {
|
|
90
|
-
const promise = executeOperationWithDependencies(operation, index);
|
|
91
|
-
operationResults.set(operation.id, promise);
|
|
92
|
-
return promise;
|
|
93
|
-
});
|
|
94
|
-
await Promise.all(operationPromises);
|
|
95
|
-
const summary = {
|
|
96
|
-
total: operations.length,
|
|
97
|
-
successful: results.filter(r => r.success).length,
|
|
98
|
-
failed: results.filter(r => !r.success).length,
|
|
99
|
-
successRate: results.length > 0 ? results.filter(r => r.success).length / results.length : 0,
|
|
100
|
-
duration: Date.now() - startTime,
|
|
101
|
-
results,
|
|
102
|
-
};
|
|
103
|
-
onBatchComplete?.(results);
|
|
104
|
-
return summary;
|
|
105
|
-
}
|
|
106
|
-
catch (error) {
|
|
107
|
-
// Rollback successful operations if enabled
|
|
108
|
-
if (enableRollback && successfulOperations.length > 0) {
|
|
109
|
-
await this.rollbackOperations(successfulOperations);
|
|
110
|
-
}
|
|
111
|
-
throw error;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Resolve operation dependencies and references
|
|
116
|
-
*/
|
|
117
|
-
async resolveOperations(operations) {
|
|
118
|
-
const resolved = [];
|
|
119
|
-
for (let i = 0; i < operations.length; i++) {
|
|
120
|
-
const operation = operations[i];
|
|
121
|
-
const resolvedOperation = { ...operation };
|
|
122
|
-
// Resolve references in data
|
|
123
|
-
if (operation.data) {
|
|
124
|
-
resolvedOperation.resolvedData = await this.resolveReferences(operation.data, resolved);
|
|
125
|
-
}
|
|
126
|
-
// Determine dependencies
|
|
127
|
-
resolvedOperation.dependencies = this.findDependencies(operation, i);
|
|
128
|
-
resolved.push(resolvedOperation);
|
|
129
|
-
}
|
|
130
|
-
return resolved;
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Resolve references in operation data
|
|
134
|
-
*/
|
|
135
|
-
async resolveReferences(data, previousResults) {
|
|
136
|
-
if (typeof data === 'string') {
|
|
137
|
-
// Convert ResolvedBatchOperation[] to BatchResult[] for resolveStringReferences
|
|
138
|
-
const batchResults = previousResults.map((op, index) => ({
|
|
139
|
-
index,
|
|
140
|
-
operation: op,
|
|
141
|
-
success: true,
|
|
142
|
-
data: op.resolvedData || op.data,
|
|
143
|
-
}));
|
|
144
|
-
return this.resolveStringReferences(data, batchResults);
|
|
145
|
-
}
|
|
146
|
-
if (Array.isArray(data)) {
|
|
147
|
-
return Promise.all(data.map(item => this.resolveReferences(item, previousResults)));
|
|
148
|
-
}
|
|
149
|
-
if (data && typeof data === 'object') {
|
|
150
|
-
const resolved = {};
|
|
151
|
-
for (const [key, value] of Object.entries(data)) {
|
|
152
|
-
resolved[key] = await this.resolveReferences(value, previousResults);
|
|
153
|
-
}
|
|
154
|
-
return resolved;
|
|
155
|
-
}
|
|
156
|
-
return data;
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Resolve string references like "$0.id" or "$1.data.attributes.name"
|
|
160
|
-
*/
|
|
161
|
-
resolveStringReferences(str, previousResults) {
|
|
162
|
-
return str.replace(/\$(\d+)\.([\w.]+)/g, (match, indexStr, path) => {
|
|
163
|
-
const index = parseInt(indexStr);
|
|
164
|
-
if (index < previousResults.length) {
|
|
165
|
-
const result = previousResults[index];
|
|
166
|
-
// For simple references like $0.id, look in result.data.id
|
|
167
|
-
if (path === 'id' && result.data?.id) {
|
|
168
|
-
return String(result.data.id);
|
|
169
|
-
}
|
|
170
|
-
// For other paths, look in result.data
|
|
171
|
-
const value = this.getNestedValue(result.data, path);
|
|
172
|
-
return value !== undefined ? String(value) : match;
|
|
173
|
-
}
|
|
174
|
-
return match;
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
/**
|
|
178
|
-
* Get nested value from object using dot notation
|
|
179
|
-
*/
|
|
180
|
-
getNestedValue(obj, path) {
|
|
181
|
-
return path.split('.').reduce((current, key) => {
|
|
182
|
-
return current && current[key] !== undefined ? current[key] : undefined;
|
|
183
|
-
}, obj);
|
|
184
|
-
}
|
|
185
|
-
/**
|
|
186
|
-
* Find dependencies for an operation
|
|
187
|
-
*/
|
|
188
|
-
findDependencies(operation, currentIndex) {
|
|
189
|
-
const dependencies = [];
|
|
190
|
-
// If operation has explicit dependencies, use those
|
|
191
|
-
if (operation.dependencies && Array.isArray(operation.dependencies)) {
|
|
192
|
-
dependencies.push(...operation.dependencies);
|
|
193
|
-
}
|
|
194
|
-
// Also find references to previous operations by index
|
|
195
|
-
const operationStr = JSON.stringify(operation);
|
|
196
|
-
const referenceMatches = operationStr.match(/\$(\d+)/g);
|
|
197
|
-
if (referenceMatches) {
|
|
198
|
-
for (const match of referenceMatches) {
|
|
199
|
-
const index = parseInt(match.substring(1));
|
|
200
|
-
if (index < currentIndex) {
|
|
201
|
-
// Convert index to operation ID reference
|
|
202
|
-
const depRef = `$index_${index}`;
|
|
203
|
-
if (!dependencies.includes(depRef)) {
|
|
204
|
-
dependencies.push(depRef);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
return dependencies;
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* Execute a single operation
|
|
213
|
-
*/
|
|
214
|
-
async executeOperation(operation, getPreviousResults) {
|
|
215
|
-
const { type, resolvedData, data, endpoint, resourceType } = operation;
|
|
216
|
-
const operationData = resolvedData || data;
|
|
217
|
-
// Check if type is module.method format
|
|
218
|
-
if (type.includes('.')) {
|
|
219
|
-
// Existing module.method approach
|
|
220
|
-
const [module, method] = type.split('.');
|
|
221
|
-
if (!module || !method) {
|
|
222
|
-
throw new Error(`Invalid operation type: ${type}`);
|
|
223
|
-
}
|
|
224
|
-
// Get the appropriate module
|
|
225
|
-
const moduleInstance = this.client[module];
|
|
226
|
-
if (!moduleInstance) {
|
|
227
|
-
throw new Error(`Unknown module: ${module}`);
|
|
228
|
-
}
|
|
229
|
-
// Execute the method
|
|
230
|
-
const methodFunc = moduleInstance[method];
|
|
231
|
-
if (typeof methodFunc !== 'function') {
|
|
232
|
-
throw new Error(`Unknown method: ${module}.${method}`);
|
|
233
|
-
}
|
|
234
|
-
return methodFunc.call(moduleInstance, operationData);
|
|
235
|
-
}
|
|
236
|
-
else {
|
|
237
|
-
// New endpoint-based approach
|
|
238
|
-
const methodMap = {
|
|
239
|
-
'create': 'POST',
|
|
240
|
-
'update': 'PATCH',
|
|
241
|
-
'delete': 'DELETE'
|
|
242
|
-
};
|
|
243
|
-
const httpMethod = methodMap[type];
|
|
244
|
-
if (!httpMethod || !endpoint) {
|
|
245
|
-
throw new Error(`Invalid operation: ${type} requires endpoint`);
|
|
246
|
-
}
|
|
247
|
-
// Resolve endpoint references
|
|
248
|
-
const previousResults = getPreviousResults();
|
|
249
|
-
const resolvedEndpoint = this.resolveStringReferences(endpoint, previousResults);
|
|
250
|
-
// Map endpoint to module and method
|
|
251
|
-
if (resolvedEndpoint === '/people') {
|
|
252
|
-
// /people endpoint
|
|
253
|
-
if (type === 'create') {
|
|
254
|
-
return this.client.people.create(operationData);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
else if (resolvedEndpoint.startsWith('/people/') && resolvedEndpoint.includes('/emails')) {
|
|
258
|
-
// /people/{id}/emails endpoint
|
|
259
|
-
if (type === 'create') {
|
|
260
|
-
const personId = resolvedEndpoint.split('/')[2];
|
|
261
|
-
return this.client.people.addEmail(personId, operationData);
|
|
262
|
-
}
|
|
263
|
-
else if (type === 'update') {
|
|
264
|
-
const parts = resolvedEndpoint.split('/');
|
|
265
|
-
const personId = parts[2];
|
|
266
|
-
const emailId = parts[4];
|
|
267
|
-
return this.client.people.updateEmail(personId, emailId, operationData);
|
|
268
|
-
}
|
|
269
|
-
else if (type === 'delete') {
|
|
270
|
-
const parts = resolvedEndpoint.split('/');
|
|
271
|
-
const personId = parts[2];
|
|
272
|
-
const emailId = parts[4];
|
|
273
|
-
return this.client.people.deleteEmail(personId, emailId);
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
else if (resolvedEndpoint.startsWith('/people/') && resolvedEndpoint.includes('/phone_numbers')) {
|
|
277
|
-
// /people/{id}/phone_numbers endpoint
|
|
278
|
-
if (type === 'create') {
|
|
279
|
-
const personId = resolvedEndpoint.split('/')[2];
|
|
280
|
-
return this.client.people.addPhoneNumber(personId, operationData);
|
|
281
|
-
}
|
|
282
|
-
else if (type === 'update') {
|
|
283
|
-
const parts = resolvedEndpoint.split('/');
|
|
284
|
-
const personId = parts[2];
|
|
285
|
-
const phoneId = parts[4];
|
|
286
|
-
return this.client.people.updatePhoneNumber(personId, phoneId, operationData);
|
|
287
|
-
}
|
|
288
|
-
else if (type === 'delete') {
|
|
289
|
-
const parts = resolvedEndpoint.split('/');
|
|
290
|
-
const personId = parts[2];
|
|
291
|
-
const phoneId = parts[4];
|
|
292
|
-
return this.client.people.deletePhoneNumber(personId, phoneId);
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
else if (resolvedEndpoint.startsWith('/people/') && !resolvedEndpoint.includes('/emails') && !resolvedEndpoint.includes('/phone_numbers')) {
|
|
296
|
-
// /people/{id} endpoint
|
|
297
|
-
if (type === 'update') {
|
|
298
|
-
const personId = resolvedEndpoint.split('/')[2];
|
|
299
|
-
return this.client.people.update(personId, operationData);
|
|
300
|
-
}
|
|
301
|
-
else if (type === 'delete') {
|
|
302
|
-
const personId = resolvedEndpoint.split('/')[2];
|
|
303
|
-
return this.client.people.delete(personId);
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
throw new Error(`Unsupported endpoint for batch operation: ${resolvedEndpoint}`);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
/**
|
|
310
|
-
* Rollback successful operations
|
|
311
|
-
*/
|
|
312
|
-
async rollbackOperations(operations) {
|
|
313
|
-
// Reverse the order for rollback
|
|
314
|
-
const rollbackOps = [...operations].reverse();
|
|
315
|
-
for (const operation of rollbackOps) {
|
|
316
|
-
try {
|
|
317
|
-
await this.rollbackOperation(operation);
|
|
318
|
-
}
|
|
319
|
-
catch (error) {
|
|
320
|
-
console.error(`Failed to rollback operation ${operation.type}:`, error);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
/**
|
|
325
|
-
* Rollback a single operation
|
|
326
|
-
*/
|
|
327
|
-
async rollbackOperation(operation) {
|
|
328
|
-
const { type } = operation;
|
|
329
|
-
const [module, method] = type.split('.');
|
|
330
|
-
// Determine rollback method based on operation type
|
|
331
|
-
let rollbackMethod;
|
|
332
|
-
if (method.startsWith('create')) {
|
|
333
|
-
rollbackMethod = method.replace('create', 'delete');
|
|
334
|
-
}
|
|
335
|
-
else if (method.startsWith('add')) {
|
|
336
|
-
rollbackMethod = method.replace('add', 'delete');
|
|
337
|
-
}
|
|
338
|
-
else {
|
|
339
|
-
// For other operations, we might need to implement specific rollback logic
|
|
340
|
-
return;
|
|
341
|
-
}
|
|
342
|
-
const moduleInstance = this.client[module];
|
|
343
|
-
if (moduleInstance && typeof moduleInstance[rollbackMethod] === 'function') {
|
|
344
|
-
// This is a simplified rollback - in practice, you'd need to store
|
|
345
|
-
// the created resource IDs to properly rollback
|
|
346
|
-
console.warn(`Rollback not fully implemented for ${type}`);
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
exports.BatchExecutor = BatchExecutor;
|
|
351
|
-
/**
|
|
352
|
-
* Semaphore for controlling concurrency
|
|
353
|
-
*/
|
|
354
|
-
class Semaphore {
|
|
355
|
-
constructor(permits) {
|
|
356
|
-
this.waiting = [];
|
|
357
|
-
this.permits = permits;
|
|
358
|
-
}
|
|
359
|
-
async acquire() {
|
|
360
|
-
if (this.permits > 0) {
|
|
361
|
-
this.permits--;
|
|
362
|
-
return;
|
|
363
|
-
}
|
|
364
|
-
return new Promise(resolve => {
|
|
365
|
-
this.waiting.push(resolve);
|
|
366
|
-
});
|
|
367
|
-
}
|
|
368
|
-
release() {
|
|
369
|
-
this.permits++;
|
|
370
|
-
if (this.waiting.length > 0) {
|
|
371
|
-
const resolve = this.waiting.shift();
|
|
372
|
-
this.permits--;
|
|
373
|
-
resolve();
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
}
|
package/dist/modules/base.d.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* v2.0.0 Base Module Class
|
|
3
|
-
*/
|
|
4
|
-
import type { PcoHttpClient } from '../core/http';
|
|
5
|
-
import type { PaginationHelper } from '../core/pagination';
|
|
6
|
-
import type { PcoEventEmitter } from '../monitoring';
|
|
7
|
-
import type { PaginationOptions, PaginationResult } from '../core/pagination';
|
|
8
|
-
import type { ResourceObject } from '../types';
|
|
9
|
-
export declare abstract class BaseModule {
|
|
10
|
-
protected httpClient: PcoHttpClient;
|
|
11
|
-
protected paginationHelper: PaginationHelper;
|
|
12
|
-
protected eventEmitter: PcoEventEmitter;
|
|
13
|
-
constructor(httpClient: PcoHttpClient, paginationHelper: PaginationHelper, eventEmitter: PcoEventEmitter);
|
|
14
|
-
/**
|
|
15
|
-
* Get a single resource
|
|
16
|
-
*/
|
|
17
|
-
protected getSingle<T extends ResourceObject<string, any, any>>(endpoint: string, params?: Record<string, any>): Promise<T>;
|
|
18
|
-
/**
|
|
19
|
-
* Get a list of resources
|
|
20
|
-
*/
|
|
21
|
-
protected getList<T extends ResourceObject<string, any, any>>(endpoint: string, params?: Record<string, any>): Promise<{
|
|
22
|
-
data: T[];
|
|
23
|
-
meta?: any;
|
|
24
|
-
links?: any;
|
|
25
|
-
}>;
|
|
26
|
-
/**
|
|
27
|
-
* Create a resource
|
|
28
|
-
*/
|
|
29
|
-
protected createResource<T extends ResourceObject<string, any, any>>(endpoint: string, data: any, params?: Record<string, any>): Promise<T>;
|
|
30
|
-
/**
|
|
31
|
-
* Update a resource
|
|
32
|
-
*/
|
|
33
|
-
protected updateResource<T extends ResourceObject<string, any, any>>(endpoint: string, data: any, params?: Record<string, any>): Promise<T>;
|
|
34
|
-
/**
|
|
35
|
-
* Delete a resource
|
|
36
|
-
*/
|
|
37
|
-
protected deleteResource(endpoint: string, params?: Record<string, any>): Promise<void>;
|
|
38
|
-
/**
|
|
39
|
-
* Get all pages of a resource
|
|
40
|
-
*/
|
|
41
|
-
protected getAllPages<T extends ResourceObject<string, any, any>>(endpoint: string, params?: Record<string, any>, options?: PaginationOptions): Promise<PaginationResult<T>>;
|
|
42
|
-
/**
|
|
43
|
-
* Stream pages of a resource
|
|
44
|
-
*/
|
|
45
|
-
protected streamPages<T extends ResourceObject<string, any, any>>(endpoint: string, params?: Record<string, any>, options?: PaginationOptions): AsyncGenerator<T[], void, unknown>;
|
|
46
|
-
}
|
package/dist/modules/base.js
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* v2.0.0 Base Module Class
|
|
4
|
-
*/
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.BaseModule = void 0;
|
|
7
|
-
class BaseModule {
|
|
8
|
-
constructor(httpClient, paginationHelper, eventEmitter) {
|
|
9
|
-
this.httpClient = httpClient;
|
|
10
|
-
this.paginationHelper = paginationHelper;
|
|
11
|
-
this.eventEmitter = eventEmitter;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Get a single resource
|
|
15
|
-
*/
|
|
16
|
-
async getSingle(endpoint, params) {
|
|
17
|
-
const response = await this.httpClient.request({
|
|
18
|
-
method: 'GET',
|
|
19
|
-
endpoint,
|
|
20
|
-
params,
|
|
21
|
-
});
|
|
22
|
-
return response.data.data;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Get a list of resources
|
|
26
|
-
*/
|
|
27
|
-
async getList(endpoint, params) {
|
|
28
|
-
const response = await this.httpClient.request({
|
|
29
|
-
method: 'GET',
|
|
30
|
-
endpoint,
|
|
31
|
-
params,
|
|
32
|
-
});
|
|
33
|
-
return response.data;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Create a resource
|
|
37
|
-
*/
|
|
38
|
-
async createResource(endpoint, data, params) {
|
|
39
|
-
const response = await this.httpClient.request({
|
|
40
|
-
method: 'POST',
|
|
41
|
-
endpoint,
|
|
42
|
-
data,
|
|
43
|
-
params,
|
|
44
|
-
});
|
|
45
|
-
return response.data.data;
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Update a resource
|
|
49
|
-
*/
|
|
50
|
-
async updateResource(endpoint, data, params) {
|
|
51
|
-
const response = await this.httpClient.request({
|
|
52
|
-
method: 'PATCH',
|
|
53
|
-
endpoint,
|
|
54
|
-
data,
|
|
55
|
-
params,
|
|
56
|
-
});
|
|
57
|
-
return response.data.data;
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Delete a resource
|
|
61
|
-
*/
|
|
62
|
-
async deleteResource(endpoint, params) {
|
|
63
|
-
await this.httpClient.request({
|
|
64
|
-
method: 'DELETE',
|
|
65
|
-
endpoint,
|
|
66
|
-
params,
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Get all pages of a resource
|
|
71
|
-
*/
|
|
72
|
-
async getAllPages(endpoint, params, options) {
|
|
73
|
-
return this.paginationHelper.getAllPages(endpoint, params, options);
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Stream pages of a resource
|
|
77
|
-
*/
|
|
78
|
-
async *streamPages(endpoint, params, options) {
|
|
79
|
-
yield* this.paginationHelper.streamPages(endpoint, params, options);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
exports.BaseModule = BaseModule;
|