mcp-wordpress 1.1.2
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/LICENSE +21 -0
- package/README.md +568 -0
- package/bin/mcp-wordpress.js +12 -0
- package/bin/setup.js +302 -0
- package/bin/status.js +359 -0
- package/dist/client/WordPressClient.d.ts +81 -0
- package/dist/client/WordPressClient.d.ts.map +1 -0
- package/dist/client/WordPressClient.js +354 -0
- package/dist/client/WordPressClient.js.map +1 -0
- package/dist/client/api.d.ts +140 -0
- package/dist/client/api.d.ts.map +1 -0
- package/dist/client/api.js +727 -0
- package/dist/client/api.js.map +1 -0
- package/dist/client/auth.d.ts +121 -0
- package/dist/client/auth.d.ts.map +1 -0
- package/dist/client/auth.js +430 -0
- package/dist/client/auth.js.map +1 -0
- package/dist/client/managers/AuthenticationManager.d.ts +39 -0
- package/dist/client/managers/AuthenticationManager.d.ts.map +1 -0
- package/dist/client/managers/AuthenticationManager.js +159 -0
- package/dist/client/managers/AuthenticationManager.js.map +1 -0
- package/dist/client/managers/BaseManager.d.ts +22 -0
- package/dist/client/managers/BaseManager.d.ts.map +1 -0
- package/dist/client/managers/BaseManager.js +47 -0
- package/dist/client/managers/BaseManager.js.map +1 -0
- package/dist/client/managers/RequestManager.d.ts +45 -0
- package/dist/client/managers/RequestManager.d.ts.map +1 -0
- package/dist/client/managers/RequestManager.js +161 -0
- package/dist/client/managers/RequestManager.js.map +1 -0
- package/dist/client/managers/index.d.ts +8 -0
- package/dist/client/managers/index.d.ts.map +1 -0
- package/dist/client/managers/index.js +8 -0
- package/dist/client/managers/index.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +264 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +7 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +7 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/auth.d.ts +44 -0
- package/dist/tools/auth.d.ts.map +1 -0
- package/dist/tools/auth.js +126 -0
- package/dist/tools/auth.js.map +1 -0
- package/dist/tools/base.d.ts +37 -0
- package/dist/tools/base.d.ts.map +1 -0
- package/dist/tools/base.js +60 -0
- package/dist/tools/base.js.map +1 -0
- package/dist/tools/comments.d.ts +33 -0
- package/dist/tools/comments.d.ts.map +1 -0
- package/dist/tools/comments.js +228 -0
- package/dist/tools/comments.js.map +1 -0
- package/dist/tools/index.d.ts +9 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +9 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/media.d.ts +29 -0
- package/dist/tools/media.d.ts.map +1 -0
- package/dist/tools/media.js +208 -0
- package/dist/tools/media.js.map +1 -0
- package/dist/tools/pages.d.ts +30 -0
- package/dist/tools/pages.d.ts.map +1 -0
- package/dist/tools/pages.js +211 -0
- package/dist/tools/pages.js.map +1 -0
- package/dist/tools/posts.d.ts +30 -0
- package/dist/tools/posts.d.ts.map +1 -0
- package/dist/tools/posts.js +240 -0
- package/dist/tools/posts.js.map +1 -0
- package/dist/tools/site.d.ts +31 -0
- package/dist/tools/site.d.ts.map +1 -0
- package/dist/tools/site.js +192 -0
- package/dist/tools/site.js.map +1 -0
- package/dist/tools/taxonomies.d.ts +37 -0
- package/dist/tools/taxonomies.d.ts.map +1 -0
- package/dist/tools/taxonomies.js +280 -0
- package/dist/tools/taxonomies.js.map +1 -0
- package/dist/tools/users.d.ts +28 -0
- package/dist/tools/users.d.ts.map +1 -0
- package/dist/tools/users.js +201 -0
- package/dist/tools/users.js.map +1 -0
- package/dist/types/client.d.ts +215 -0
- package/dist/types/client.d.ts.map +1 -0
- package/dist/types/client.js +72 -0
- package/dist/types/client.js.map +1 -0
- package/dist/types/index.d.ts +157 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +12 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/mcp.d.ts +178 -0
- package/dist/types/mcp.d.ts.map +1 -0
- package/dist/types/mcp.js +7 -0
- package/dist/types/mcp.js.map +1 -0
- package/dist/types/wordpress.d.ts +443 -0
- package/dist/types/wordpress.d.ts.map +1 -0
- package/dist/types/wordpress.js +7 -0
- package/dist/types/wordpress.js.map +1 -0
- package/dist/utils/debug.d.ts +63 -0
- package/dist/utils/debug.d.ts.map +1 -0
- package/dist/utils/debug.js +195 -0
- package/dist/utils/debug.js.map +1 -0
- package/dist/utils/error.d.ts +19 -0
- package/dist/utils/error.d.ts.map +1 -0
- package/dist/utils/error.js +71 -0
- package/dist/utils/error.js.map +1 -0
- package/dist/utils/toolWrapper.d.ts +36 -0
- package/dist/utils/toolWrapper.d.ts.map +1 -0
- package/dist/utils/toolWrapper.js +90 -0
- package/dist/utils/toolWrapper.js.map +1 -0
- package/package.json +115 -0
- package/src/client/api.ts +1043 -0
- package/src/client/auth.ts +527 -0
- package/src/client/managers/AuthenticationManager.ts +190 -0
- package/src/client/managers/BaseManager.ts +73 -0
- package/src/client/managers/RequestManager.ts +214 -0
- package/src/client/managers/index.ts +8 -0
- package/src/index.ts +337 -0
- package/src/server.ts +7 -0
- package/src/tools/auth.ts +153 -0
- package/src/tools/comments.ts +263 -0
- package/src/tools/index.ts +8 -0
- package/src/tools/media.ts +240 -0
- package/src/tools/pages.ts +246 -0
- package/src/tools/posts.ts +277 -0
- package/src/tools/site.ts +227 -0
- package/src/tools/taxonomies.ts +322 -0
- package/src/tools/users.ts +233 -0
- package/src/types/client.ts +304 -0
- package/src/types/index.ts +207 -0
- package/src/types/mcp.ts +247 -0
- package/src/types/wordpress.ts +491 -0
- package/src/utils/debug.ts +258 -0
- package/src/utils/error.ts +88 -0
- package/src/utils/toolWrapper.ts +105 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debug Utility for MCP Server
|
|
3
|
+
*
|
|
4
|
+
* This module provides debug logging that only outputs when DEBUG mode is enabled.
|
|
5
|
+
* This prevents console.log from interfering with MCP STDIO communication.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { DebugInfo } from '../types/index.js';
|
|
9
|
+
|
|
10
|
+
// Log levels
|
|
11
|
+
export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
12
|
+
|
|
13
|
+
// Logger interface
|
|
14
|
+
export interface Logger {
|
|
15
|
+
log(...args: any[]): void;
|
|
16
|
+
info(...args: any[]): void;
|
|
17
|
+
warn(...args: any[]): void;
|
|
18
|
+
error(...args: any[]): void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Enhanced logger with structured logging
|
|
22
|
+
export interface StructuredLogger extends Logger {
|
|
23
|
+
logStructured(info: DebugInfo): void;
|
|
24
|
+
child(context: Record<string, any>): StructuredLogger;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Check if debug mode is enabled
|
|
28
|
+
const isDebugMode = (): boolean =>
|
|
29
|
+
process.env.DEBUG === 'true' ||
|
|
30
|
+
process.env.NODE_ENV === 'development';
|
|
31
|
+
|
|
32
|
+
// Get current timestamp
|
|
33
|
+
const getTimestamp = (): string => new Date().toISOString();
|
|
34
|
+
|
|
35
|
+
// Format log message with timestamp and level
|
|
36
|
+
const formatMessage = (level: LogLevel, args: any[]): string => {
|
|
37
|
+
const timestamp = getTimestamp();
|
|
38
|
+
const prefix = `[${timestamp}] [${level.toUpperCase()}]`;
|
|
39
|
+
return `${prefix} ${args.map(arg =>
|
|
40
|
+
typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)
|
|
41
|
+
).join(' ')}`;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// Handle circular references in objects
|
|
45
|
+
const safeStringify = (obj: any): string => {
|
|
46
|
+
try {
|
|
47
|
+
return JSON.stringify(obj, (key, value) => {
|
|
48
|
+
if (value instanceof Error) {
|
|
49
|
+
return {
|
|
50
|
+
name: value.name,
|
|
51
|
+
message: value.message,
|
|
52
|
+
stack: value.stack
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
return value;
|
|
56
|
+
}, 2);
|
|
57
|
+
} catch (error) {
|
|
58
|
+
return '[Object with circular reference]';
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Debug logger that only outputs in debug mode
|
|
64
|
+
*/
|
|
65
|
+
export const debug: Logger = {
|
|
66
|
+
log: (...args: any[]): void => {
|
|
67
|
+
if (isDebugMode()) {
|
|
68
|
+
console.error(formatMessage('debug', args)); // Use stderr for debug to avoid STDIO interference
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
info: (...args: any[]): void => {
|
|
73
|
+
if (isDebugMode()) {
|
|
74
|
+
console.error(formatMessage('info', args));
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
warn: (...args: any[]): void => {
|
|
79
|
+
if (isDebugMode()) {
|
|
80
|
+
console.error(formatMessage('warn', args));
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
error: (...args: any[]): void => {
|
|
85
|
+
if (isDebugMode()) {
|
|
86
|
+
console.error(formatMessage('error', args));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Silent logger for production use
|
|
93
|
+
*/
|
|
94
|
+
export const silent: Logger = {
|
|
95
|
+
log: (): void => {},
|
|
96
|
+
warn: (): void => {},
|
|
97
|
+
error: (): void => {},
|
|
98
|
+
info: (): void => {}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Enhanced structured logger
|
|
103
|
+
*/
|
|
104
|
+
class StructuredLoggerImpl implements StructuredLogger {
|
|
105
|
+
private context: Record<string, any>;
|
|
106
|
+
private enabled: boolean;
|
|
107
|
+
|
|
108
|
+
constructor(context: Record<string, any> = {}, enabled = isDebugMode()) {
|
|
109
|
+
this.context = context;
|
|
110
|
+
this.enabled = enabled;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private output(level: LogLevel, args: any[]): void {
|
|
114
|
+
if (!this.enabled) return;
|
|
115
|
+
|
|
116
|
+
const debugInfo: DebugInfo = {
|
|
117
|
+
timestamp: Date.now(),
|
|
118
|
+
level,
|
|
119
|
+
message: args.map(arg =>
|
|
120
|
+
typeof arg === 'object' ? safeStringify(arg) : String(arg)
|
|
121
|
+
).join(' '),
|
|
122
|
+
...(Object.keys(this.context).length > 0 && { context: this.context })
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
console.error(safeStringify(debugInfo));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
log(...args: any[]): void {
|
|
129
|
+
this.output('debug', args);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
info(...args: any[]): void {
|
|
133
|
+
this.output('info', args);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
warn(...args: any[]): void {
|
|
137
|
+
this.output('warn', args);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
error(...args: any[]): void {
|
|
141
|
+
this.output('error', args);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
logStructured(info: DebugInfo): void {
|
|
145
|
+
if (!this.enabled) return;
|
|
146
|
+
|
|
147
|
+
const enhancedInfo: DebugInfo = {
|
|
148
|
+
...info,
|
|
149
|
+
context: { ...this.context, ...info.context }
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
console.error(safeStringify(enhancedInfo));
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
child(context: Record<string, any>): StructuredLogger {
|
|
156
|
+
return new StructuredLoggerImpl(
|
|
157
|
+
{ ...this.context, ...context },
|
|
158
|
+
this.enabled
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Create a structured logger instance
|
|
165
|
+
*/
|
|
166
|
+
export const createStructuredLogger = (context: Record<string, any> = {}): StructuredLogger => {
|
|
167
|
+
return new StructuredLoggerImpl(context);
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Default logger instance
|
|
172
|
+
*/
|
|
173
|
+
export const logger: Logger = debug;
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Create a logger with context
|
|
177
|
+
*/
|
|
178
|
+
export const createLogger = (context: Record<string, any> = {}): StructuredLogger => {
|
|
179
|
+
return createStructuredLogger(context);
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Performance measurement utility
|
|
184
|
+
*/
|
|
185
|
+
export interface PerformanceTimer {
|
|
186
|
+
end(): number;
|
|
187
|
+
endWithLog(message?: string): number;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export const startTimer = (label?: string): PerformanceTimer => {
|
|
191
|
+
const start = Date.now();
|
|
192
|
+
|
|
193
|
+
return {
|
|
194
|
+
end(): number {
|
|
195
|
+
return Date.now() - start;
|
|
196
|
+
},
|
|
197
|
+
|
|
198
|
+
endWithLog(message = 'Operation'): number {
|
|
199
|
+
const duration = Date.now() - start;
|
|
200
|
+
debug.info(`${message} completed in ${duration}ms${label ? ` [${label}]` : ''}`);
|
|
201
|
+
return duration;
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Log error with stack trace
|
|
208
|
+
*/
|
|
209
|
+
export const logError = (error: Error | string, context?: Record<string, any>): void => {
|
|
210
|
+
if (typeof error === 'string') {
|
|
211
|
+
debug.error(error, context);
|
|
212
|
+
} else {
|
|
213
|
+
debug.error(`${error.name}: ${error.message}`, {
|
|
214
|
+
stack: error.stack,
|
|
215
|
+
...context
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Conditional logging
|
|
222
|
+
*/
|
|
223
|
+
export const logIf = (condition: boolean, level: LogLevel = 'debug') => {
|
|
224
|
+
if (!condition) return silent;
|
|
225
|
+
|
|
226
|
+
const loggers = {
|
|
227
|
+
log: debug.log,
|
|
228
|
+
info: debug.info,
|
|
229
|
+
warn: debug.warn,
|
|
230
|
+
error: debug.error
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
return loggers[level as keyof typeof loggers] || debug.log;
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Type-safe environment variable getter
|
|
238
|
+
*/
|
|
239
|
+
export const getEnvVar = (key: string, defaultValue?: string): string | undefined => {
|
|
240
|
+
const value = process.env[key];
|
|
241
|
+
if (value === undefined && defaultValue !== undefined) {
|
|
242
|
+
debug.warn(`Environment variable ${key} not found, using default: ${defaultValue}`);
|
|
243
|
+
return defaultValue;
|
|
244
|
+
}
|
|
245
|
+
return value;
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Validate required environment variables
|
|
250
|
+
*/
|
|
251
|
+
export const validateEnvVars = (required: string[]): void => {
|
|
252
|
+
const missing = required.filter(key => !process.env[key]);
|
|
253
|
+
if (missing.length > 0) {
|
|
254
|
+
const error = new Error(`Missing required environment variables: ${missing.join(', ')}`);
|
|
255
|
+
logError(error);
|
|
256
|
+
throw error;
|
|
257
|
+
}
|
|
258
|
+
};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error handling utilities
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export function getErrorMessage(error: unknown): string {
|
|
6
|
+
if (error instanceof Error) {
|
|
7
|
+
return error.message;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (typeof error === 'string') {
|
|
11
|
+
return error;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (error && typeof error === 'object' && 'message' in error) {
|
|
15
|
+
return String(error.message);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return 'Unknown error occurred';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function isError(error: unknown): error is Error {
|
|
22
|
+
return error instanceof Error;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function logAndReturn<T>(error: unknown, defaultValue: T): T {
|
|
26
|
+
console.error('Error occurred:', getErrorMessage(error));
|
|
27
|
+
return defaultValue;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Enhanced error handler for consistent tool error handling
|
|
32
|
+
*/
|
|
33
|
+
export function handleToolError(error: unknown, operation: string, context?: Record<string, unknown>): never {
|
|
34
|
+
console.error(`Error in ${operation}:`, error);
|
|
35
|
+
|
|
36
|
+
if (context) {
|
|
37
|
+
console.error('Context:', context);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const message = getErrorMessage(error);
|
|
41
|
+
|
|
42
|
+
// Provide more specific error messages based on error content
|
|
43
|
+
if (message.includes('ECONNREFUSED') || message.includes('ENOTFOUND')) {
|
|
44
|
+
throw new Error(`Connection failed during ${operation}. Please check your WordPress site URL and network connection.`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (message.includes('401') || message.includes('Unauthorized')) {
|
|
48
|
+
throw new Error(`Authentication failed during ${operation}. Please check your WordPress credentials.`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (message.includes('403') || message.includes('Forbidden')) {
|
|
52
|
+
throw new Error(`Permission denied during ${operation}. Please check your user permissions.`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (message.includes('429') || message.includes('Too Many Requests')) {
|
|
56
|
+
throw new Error(`Rate limit exceeded during ${operation}. Please try again later.`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
throw new Error(`Failed to ${operation}: ${message}`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Validates required parameters
|
|
64
|
+
*/
|
|
65
|
+
export function validateRequired(params: Record<string, unknown>, required: string[]): void {
|
|
66
|
+
const missing = required.filter(key => !params[key]);
|
|
67
|
+
if (missing.length > 0) {
|
|
68
|
+
throw new Error(`Missing required parameters: ${missing.join(', ')}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Validates site parameter for multi-site configurations
|
|
74
|
+
*/
|
|
75
|
+
export function validateSite(site: string | undefined, availableSites: string[]): string {
|
|
76
|
+
if (!site) {
|
|
77
|
+
if (availableSites.length === 1) {
|
|
78
|
+
return availableSites[0];
|
|
79
|
+
}
|
|
80
|
+
throw new Error(`Site parameter is required when multiple sites are configured. Available sites: ${availableSites.join(', ')}`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (!availableSites.includes(site)) {
|
|
84
|
+
throw new Error(`Site '${site}' not found. Available sites: ${availableSites.join(', ')}`);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return site;
|
|
88
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Wrapper Utility
|
|
3
|
+
* Standardizes error handling and reduces repetitive try-catch blocks
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { getErrorMessage } from "./error.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Wrapper for tool methods that standardizes error handling
|
|
10
|
+
*/
|
|
11
|
+
export function withErrorHandling<T extends any[], R>(
|
|
12
|
+
operation: string,
|
|
13
|
+
fn: (...args: T) => Promise<R>
|
|
14
|
+
): (...args: T) => Promise<R> {
|
|
15
|
+
return async (...args: T): Promise<R> => {
|
|
16
|
+
try {
|
|
17
|
+
return await fn(...args);
|
|
18
|
+
} catch (error) {
|
|
19
|
+
throw new Error(`${operation}: ${getErrorMessage(error)}`);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Wrapper for tool methods with validation
|
|
26
|
+
*/
|
|
27
|
+
export function withValidation<T extends any[], R>(
|
|
28
|
+
operation: string,
|
|
29
|
+
validator: (...args: T) => void,
|
|
30
|
+
fn: (...args: T) => Promise<R>
|
|
31
|
+
): (...args: T) => Promise<R> {
|
|
32
|
+
return async (...args: T): Promise<R> => {
|
|
33
|
+
try {
|
|
34
|
+
validator(...args);
|
|
35
|
+
return await fn(...args);
|
|
36
|
+
} catch (error) {
|
|
37
|
+
throw new Error(`${operation}: ${getErrorMessage(error)}`);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Common validation functions
|
|
44
|
+
*/
|
|
45
|
+
export const validators = {
|
|
46
|
+
requireSite: (client: any, params: any) => {
|
|
47
|
+
if (!client) {
|
|
48
|
+
throw new Error("WordPress client is required");
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
requireId: (params: { id?: number | string }) => {
|
|
53
|
+
if (!params.id) {
|
|
54
|
+
throw new Error("ID parameter is required");
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
requireNonEmpty: (value: any, fieldName: string) => {
|
|
59
|
+
if (!value || (typeof value === 'string' && value.trim() === '')) {
|
|
60
|
+
throw new Error(`${fieldName} cannot be empty`);
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
requireFields: (params: any, fields: string[]) => {
|
|
65
|
+
for (const field of fields) {
|
|
66
|
+
if (params[field] === undefined || params[field] === null) {
|
|
67
|
+
throw new Error(`${field} is required`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Decorator for class methods to add error handling
|
|
75
|
+
*/
|
|
76
|
+
export function errorHandler(operation: string) {
|
|
77
|
+
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
|
|
78
|
+
const originalMethod = descriptor.value;
|
|
79
|
+
|
|
80
|
+
descriptor.value = async function (...args: any[]) {
|
|
81
|
+
try {
|
|
82
|
+
return await originalMethod.apply(this, args);
|
|
83
|
+
} catch (error) {
|
|
84
|
+
throw new Error(`${operation}: ${getErrorMessage(error)}`);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
return descriptor;
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Helper to format success responses consistently
|
|
94
|
+
*/
|
|
95
|
+
export function formatSuccessResponse(content: string): string {
|
|
96
|
+
return content;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Helper to format error responses consistently
|
|
101
|
+
*/
|
|
102
|
+
export function formatErrorResponse(operation: string, error: any): never {
|
|
103
|
+
const message = getErrorMessage(error);
|
|
104
|
+
throw new Error(`${operation}: ${message}`);
|
|
105
|
+
}
|