mcp-wordpress 1.1.7 → 1.2.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/README.md +388 -66
- package/dist/cache/CacheInvalidation.d.ts +118 -0
- package/dist/cache/CacheInvalidation.d.ts.map +1 -0
- package/dist/cache/CacheInvalidation.js +349 -0
- package/dist/cache/CacheInvalidation.js.map +1 -0
- package/dist/cache/CacheManager.d.ts +143 -0
- package/dist/cache/CacheManager.d.ts.map +1 -0
- package/dist/cache/CacheManager.js +308 -0
- package/dist/cache/CacheManager.js.map +1 -0
- package/dist/cache/HttpCacheWrapper.d.ts +121 -0
- package/dist/cache/HttpCacheWrapper.d.ts.map +1 -0
- package/dist/cache/HttpCacheWrapper.js +280 -0
- package/dist/cache/HttpCacheWrapper.js.map +1 -0
- package/dist/cache/__tests__/CacheInvalidation.test.d.ts +5 -0
- package/dist/cache/__tests__/CacheInvalidation.test.d.ts.map +1 -0
- package/dist/cache/__tests__/CacheInvalidation.test.js +236 -0
- package/dist/cache/__tests__/CacheInvalidation.test.js.map +1 -0
- package/dist/cache/__tests__/CacheManager.test.d.ts +5 -0
- package/dist/cache/__tests__/CacheManager.test.d.ts.map +1 -0
- package/dist/cache/__tests__/CacheManager.test.js +233 -0
- package/dist/cache/__tests__/CacheManager.test.js.map +1 -0
- package/dist/cache/__tests__/CachedWordPressClient.test.d.ts +5 -0
- package/dist/cache/__tests__/CachedWordPressClient.test.d.ts.map +1 -0
- package/dist/cache/__tests__/CachedWordPressClient.test.js +228 -0
- package/dist/cache/__tests__/CachedWordPressClient.test.js.map +1 -0
- package/dist/cache/__tests__/HttpCacheWrapper.test.d.ts +5 -0
- package/dist/cache/__tests__/HttpCacheWrapper.test.d.ts.map +1 -0
- package/dist/cache/__tests__/HttpCacheWrapper.test.js +296 -0
- package/dist/cache/__tests__/HttpCacheWrapper.test.js.map +1 -0
- package/dist/cache/index.d.ts +12 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +9 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/client/CachedWordPressClient.d.ts +160 -0
- package/dist/client/CachedWordPressClient.d.ts.map +1 -0
- package/dist/client/CachedWordPressClient.js +338 -0
- package/dist/client/CachedWordPressClient.js.map +1 -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/config/ConfigurationSchema.d.ts +281 -0
- package/dist/config/ConfigurationSchema.d.ts.map +1 -0
- package/dist/config/ConfigurationSchema.js +205 -0
- package/dist/config/ConfigurationSchema.js.map +1 -0
- package/dist/config/ServerConfiguration.d.ts +38 -0
- package/dist/config/ServerConfiguration.d.ts.map +1 -0
- package/dist/config/ServerConfiguration.js +158 -0
- package/dist/config/ServerConfiguration.js.map +1 -0
- package/dist/docs/DocumentationGenerator.d.ts +184 -0
- package/dist/docs/DocumentationGenerator.d.ts.map +1 -0
- package/dist/docs/DocumentationGenerator.js +735 -0
- package/dist/docs/DocumentationGenerator.js.map +1 -0
- package/dist/docs/MarkdownFormatter.d.ts +84 -0
- package/dist/docs/MarkdownFormatter.d.ts.map +1 -0
- package/dist/docs/MarkdownFormatter.js +448 -0
- package/dist/docs/MarkdownFormatter.js.map +1 -0
- package/dist/docs/index.d.ts +8 -0
- package/dist/docs/index.d.ts.map +1 -0
- package/dist/docs/index.js +7 -0
- package/dist/docs/index.js.map +1 -0
- package/dist/index.d.ts +1 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -212
- package/dist/index.js.map +1 -1
- package/dist/performance/AnomalyDetector.d.ts +63 -0
- package/dist/performance/AnomalyDetector.d.ts.map +1 -0
- package/dist/performance/AnomalyDetector.js +222 -0
- package/dist/performance/AnomalyDetector.js.map +1 -0
- package/dist/performance/BenchmarkAnalyzer.d.ts +67 -0
- package/dist/performance/BenchmarkAnalyzer.d.ts.map +1 -0
- package/dist/performance/BenchmarkAnalyzer.js +301 -0
- package/dist/performance/BenchmarkAnalyzer.js.map +1 -0
- package/dist/performance/MetricsCollector.d.ts +139 -0
- package/dist/performance/MetricsCollector.d.ts.map +1 -0
- package/dist/performance/MetricsCollector.js +320 -0
- package/dist/performance/MetricsCollector.js.map +1 -0
- package/dist/performance/PerformanceAnalytics.d.ts +162 -0
- package/dist/performance/PerformanceAnalytics.d.ts.map +1 -0
- package/dist/performance/PerformanceAnalytics.js +554 -0
- package/dist/performance/PerformanceAnalytics.js.map +1 -0
- package/dist/performance/PerformanceMonitor.d.ts +202 -0
- package/dist/performance/PerformanceMonitor.d.ts.map +1 -0
- package/dist/performance/PerformanceMonitor.js +478 -0
- package/dist/performance/PerformanceMonitor.js.map +1 -0
- package/dist/performance/TrendAnalyzer.d.ts +69 -0
- package/dist/performance/TrendAnalyzer.d.ts.map +1 -0
- package/dist/performance/TrendAnalyzer.js +203 -0
- package/dist/performance/TrendAnalyzer.js.map +1 -0
- package/dist/performance/index.d.ts +11 -0
- package/dist/performance/index.d.ts.map +1 -0
- package/dist/performance/index.js +8 -0
- package/dist/performance/index.js.map +1 -0
- package/dist/security/InputValidator.d.ts +215 -0
- package/dist/security/InputValidator.d.ts.map +1 -0
- package/dist/security/InputValidator.js +278 -0
- package/dist/security/InputValidator.js.map +1 -0
- package/dist/security/SecurityConfig.d.ts +129 -0
- package/dist/security/SecurityConfig.d.ts.map +1 -0
- package/dist/security/SecurityConfig.js +262 -0
- package/dist/security/SecurityConfig.js.map +1 -0
- package/dist/server/ConnectionTester.d.ts +24 -0
- package/dist/server/ConnectionTester.d.ts.map +1 -0
- package/dist/server/ConnectionTester.js +61 -0
- package/dist/server/ConnectionTester.js.map +1 -0
- package/dist/server/ToolRegistry.d.ts +46 -0
- package/dist/server/ToolRegistry.d.ts.map +1 -0
- package/dist/server/ToolRegistry.js +148 -0
- package/dist/server/ToolRegistry.js.map +1 -0
- package/dist/tools/BaseToolClass.d.ts +76 -0
- package/dist/tools/BaseToolClass.d.ts.map +1 -0
- package/dist/tools/BaseToolClass.js +104 -0
- package/dist/tools/BaseToolClass.js.map +1 -0
- package/dist/tools/BaseToolManager.d.ts +26 -0
- package/dist/tools/BaseToolManager.d.ts.map +1 -0
- package/dist/tools/BaseToolManager.js +56 -0
- package/dist/tools/BaseToolManager.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/cache.d.ts +260 -0
- package/dist/tools/cache.d.ts.map +1 -0
- package/dist/tools/cache.js +237 -0
- package/dist/tools/cache.js.map +1 -0
- package/dist/tools/index.d.ts +2 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +2 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/performance.d.ts +63 -0
- package/dist/tools/performance.d.ts.map +1 -0
- package/dist/tools/performance.js +865 -0
- package/dist/tools/performance.js.map +1 -0
- package/dist/types/client.d.ts +1 -0
- package/dist/types/client.d.ts.map +1 -1
- package/dist/types/client.js.map +1 -1
- package/dist/utils/toolWrapper.d.ts +4 -0
- package/dist/utils/toolWrapper.d.ts.map +1 -1
- package/dist/utils/toolWrapper.js +11 -0
- package/dist/utils/toolWrapper.js.map +1 -1
- package/dist/utils/validation.d.ts +68 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +185 -0
- package/dist/utils/validation.js.map +1 -0
- package/docs/CACHING.md +340 -0
- package/docs/DOCKER.md +451 -0
- package/docs/PERFORMANCE_MONITORING.md +471 -0
- package/docs/SECURITY_TESTING.md +393 -0
- package/docs/api/README.md +200 -0
- package/docs/api/categories/auth.md +40 -0
- package/docs/api/categories/cache.md +41 -0
- package/docs/api/categories/comment.md +44 -0
- package/docs/api/categories/media.md +43 -0
- package/docs/api/categories/page.md +43 -0
- package/docs/api/categories/performance.md +44 -0
- package/docs/api/categories/post.md +43 -0
- package/docs/api/categories/site.md +43 -0
- package/docs/api/categories/taxonomy.md +47 -0
- package/docs/api/categories/user.md +43 -0
- package/docs/api/openapi.json +3305 -0
- package/docs/api/summary.json +12 -0
- package/docs/api/tools/wp_approve_comment.md +98 -0
- package/docs/api/tools/wp_cache_clear.md +120 -0
- package/docs/api/tools/wp_cache_info.md +119 -0
- package/docs/api/tools/wp_cache_stats.md +119 -0
- package/docs/api/tools/wp_cache_warm.md +119 -0
- package/docs/api/tools/wp_create_application_password.md +102 -0
- package/docs/api/tools/wp_create_category.md +102 -0
- package/docs/api/tools/wp_create_comment.md +128 -0
- package/docs/api/tools/wp_create_page.md +135 -0
- package/docs/api/tools/wp_create_post.md +147 -0
- package/docs/api/tools/wp_create_tag.md +101 -0
- package/docs/api/tools/wp_create_user.md +135 -0
- package/docs/api/tools/wp_delete_application_password.md +101 -0
- package/docs/api/tools/wp_delete_category.md +100 -0
- package/docs/api/tools/wp_delete_comment.md +101 -0
- package/docs/api/tools/wp_delete_media.md +108 -0
- package/docs/api/tools/wp_delete_page.md +108 -0
- package/docs/api/tools/wp_delete_post.md +117 -0
- package/docs/api/tools/wp_delete_tag.md +100 -0
- package/docs/api/tools/wp_delete_user.md +108 -0
- package/docs/api/tools/wp_get_application_passwords.md +103 -0
- package/docs/api/tools/wp_get_auth_status.md +101 -0
- package/docs/api/tools/wp_get_category.md +103 -0
- package/docs/api/tools/wp_get_comment.md +103 -0
- package/docs/api/tools/wp_get_current_user.md +101 -0
- package/docs/api/tools/wp_get_media.md +103 -0
- package/docs/api/tools/wp_get_page.md +103 -0
- package/docs/api/tools/wp_get_page_revisions.md +103 -0
- package/docs/api/tools/wp_get_post.md +112 -0
- package/docs/api/tools/wp_get_post_revisions.md +103 -0
- package/docs/api/tools/wp_get_site_settings.md +108 -0
- package/docs/api/tools/wp_get_tag.md +103 -0
- package/docs/api/tools/wp_get_user.md +103 -0
- package/docs/api/tools/wp_list_categories.md +111 -0
- package/docs/api/tools/wp_list_comments.md +111 -0
- package/docs/api/tools/wp_list_media.md +145 -0
- package/docs/api/tools/wp_list_pages.md +145 -0
- package/docs/api/tools/wp_list_posts.md +156 -0
- package/docs/api/tools/wp_list_tags.md +110 -0
- package/docs/api/tools/wp_list_users.md +111 -0
- package/docs/api/tools/wp_performance_alerts.md +162 -0
- package/docs/api/tools/wp_performance_benchmark.md +160 -0
- package/docs/api/tools/wp_performance_export.md +162 -0
- package/docs/api/tools/wp_performance_history.md +161 -0
- package/docs/api/tools/wp_performance_optimize.md +162 -0
- package/docs/api/tools/wp_performance_stats.md +160 -0
- package/docs/api/tools/wp_search_site.md +99 -0
- package/docs/api/tools/wp_spam_comment.md +98 -0
- package/docs/api/tools/wp_switch_auth_method.md +122 -0
- package/docs/api/tools/wp_test_auth.md +96 -0
- package/docs/api/tools/wp_update_category.md +102 -0
- package/docs/api/tools/wp_update_comment.md +127 -0
- package/docs/api/tools/wp_update_media.md +129 -0
- package/docs/api/tools/wp_update_page.md +135 -0
- package/docs/api/tools/wp_update_post.md +144 -0
- package/docs/api/tools/wp_update_site_settings.md +127 -0
- package/docs/api/tools/wp_update_tag.md +102 -0
- package/docs/api/tools/wp_update_user.md +134 -0
- package/docs/api/tools/wp_upload_media.md +131 -0
- package/docs/api/types/WordPressPost.md +39 -0
- package/docs/contract-testing.md +183 -0
- package/docs/developer/NPM_AUTH_SETUP.md +3 -3
- package/docs/wordpress-rest-api-authentication-troubleshooting.md +218 -0
- package/package.json +84 -64
- package/src/cache/CacheInvalidation.ts +421 -0
- package/src/cache/CacheManager.ts +391 -0
- package/src/cache/HttpCacheWrapper.ts +372 -0
- package/src/cache/__tests__/CacheInvalidation.test.ts +299 -0
- package/src/cache/__tests__/CacheManager.test.ts +300 -0
- package/src/cache/__tests__/CachedWordPressClient.test.ts +304 -0
- package/src/cache/__tests__/HttpCacheWrapper.test.ts +359 -0
- package/src/cache/index.ts +26 -0
- package/src/client/CachedWordPressClient.ts +442 -0
- package/src/config/ConfigurationSchema.ts +246 -0
- package/src/config/ServerConfiguration.ts +215 -0
- package/src/docs/DocumentationGenerator.ts +952 -0
- package/src/docs/MarkdownFormatter.ts +494 -0
- package/src/docs/index.ts +21 -0
- package/src/index.ts +14 -274
- package/src/performance/MetricsCollector.ts +447 -0
- package/src/performance/PerformanceAnalytics.ts +762 -0
- package/src/performance/PerformanceMonitor.ts +649 -0
- package/src/performance/index.ts +28 -0
- package/src/security/InputValidator.ts +319 -0
- package/src/security/SecurityConfig.ts +301 -0
- package/src/server/ConnectionTester.ts +74 -0
- package/src/server/ToolRegistry.ts +194 -0
- package/src/tools/BaseToolManager.ts +66 -0
- package/src/tools/cache.ts +259 -0
- package/src/tools/index.ts +2 -0
- package/src/tools/performance.ts +948 -0
- package/src/types/client.ts +1 -0
- package/src/utils/toolWrapper.ts +11 -0
- package/src/utils/validation.ts +259 -0
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cached WordPress API Client
|
|
3
|
+
* Extends the base WordPress client with intelligent caching capabilities and performance monitoring
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { WordPressClient } from './api.js';
|
|
7
|
+
import { CacheManager } from '../cache/CacheManager.js';
|
|
8
|
+
import { HttpCacheWrapper } from '../cache/HttpCacheWrapper.js';
|
|
9
|
+
import { CacheInvalidation } from '../cache/CacheInvalidation.js';
|
|
10
|
+
import { SecurityConfig } from '../security/SecurityConfig.js';
|
|
11
|
+
import type {
|
|
12
|
+
WordPressClientConfig,
|
|
13
|
+
HTTPMethod,
|
|
14
|
+
RequestOptions
|
|
15
|
+
} from '../types/client.js';
|
|
16
|
+
import type {
|
|
17
|
+
WordPressPost,
|
|
18
|
+
WordPressUser,
|
|
19
|
+
WordPressCategory,
|
|
20
|
+
WordPressTag,
|
|
21
|
+
WordPressSiteSettings,
|
|
22
|
+
PostQueryParams,
|
|
23
|
+
CreatePostRequest,
|
|
24
|
+
UpdatePostRequest
|
|
25
|
+
} from '../types/wordpress.js';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* WordPress client with intelligent caching
|
|
29
|
+
*/
|
|
30
|
+
export class CachedWordPressClient extends WordPressClient {
|
|
31
|
+
private cacheManager: CacheManager;
|
|
32
|
+
private httpCache: HttpCacheWrapper;
|
|
33
|
+
private cacheInvalidation: CacheInvalidation;
|
|
34
|
+
private siteId: string;
|
|
35
|
+
|
|
36
|
+
constructor(config: WordPressClientConfig, siteId: string = 'default') {
|
|
37
|
+
super(config);
|
|
38
|
+
this.siteId = siteId;
|
|
39
|
+
|
|
40
|
+
// Initialize caching system
|
|
41
|
+
this.cacheManager = new CacheManager({
|
|
42
|
+
maxSize: SecurityConfig.cache.maxSize,
|
|
43
|
+
defaultTTL: SecurityConfig.cache.defaultTTL,
|
|
44
|
+
enableLRU: SecurityConfig.cache.enableLRU,
|
|
45
|
+
enableStats: SecurityConfig.cache.enableStats,
|
|
46
|
+
sitePrefix: siteId
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
this.httpCache = new HttpCacheWrapper(this.cacheManager, siteId);
|
|
50
|
+
this.cacheInvalidation = new CacheInvalidation(this.httpCache);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Override request method to add caching
|
|
55
|
+
*/
|
|
56
|
+
async request<T = any>(
|
|
57
|
+
method: HTTPMethod,
|
|
58
|
+
endpoint: string,
|
|
59
|
+
data: any = null,
|
|
60
|
+
options: RequestOptions = {}
|
|
61
|
+
): Promise<T> {
|
|
62
|
+
// Only cache GET requests
|
|
63
|
+
if (method.toUpperCase() !== 'GET' || !SecurityConfig.cache.enabled) {
|
|
64
|
+
const response = await super.request<T>(method, endpoint, data, options);
|
|
65
|
+
|
|
66
|
+
// Trigger cache invalidation for write operations
|
|
67
|
+
if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(method.toUpperCase())) {
|
|
68
|
+
await this.handleCacheInvalidation(method, endpoint, data);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return response;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Use cached request for GET operations
|
|
75
|
+
const requestFn = () => super.request<T>(method, endpoint, data, options);
|
|
76
|
+
|
|
77
|
+
const requestOptions = {
|
|
78
|
+
method,
|
|
79
|
+
url: `${this.config.baseUrl}/wp-json/wp/v2/${endpoint}`,
|
|
80
|
+
headers: {},
|
|
81
|
+
params: {},
|
|
82
|
+
data
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const cacheOptions = this.getCacheOptions(endpoint);
|
|
86
|
+
|
|
87
|
+
const response = await this.httpCache.request(
|
|
88
|
+
async () => {
|
|
89
|
+
const result = await requestFn();
|
|
90
|
+
return {
|
|
91
|
+
data: result,
|
|
92
|
+
status: 200,
|
|
93
|
+
headers: {}
|
|
94
|
+
};
|
|
95
|
+
},
|
|
96
|
+
requestOptions,
|
|
97
|
+
cacheOptions
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
return response.data;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Enhanced methods with caching optimization
|
|
105
|
+
*/
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Get posts with intelligent caching
|
|
109
|
+
*/
|
|
110
|
+
async getPosts(params: PostQueryParams = {}): Promise<WordPressPost[]> {
|
|
111
|
+
return await this.request<WordPressPost[]>('GET', 'posts', null, { params });
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Get single post with caching
|
|
116
|
+
*/
|
|
117
|
+
async getPost(id: number): Promise<WordPressPost> {
|
|
118
|
+
return await this.request<WordPressPost>('GET', `posts/${id}`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Create post with cache invalidation
|
|
123
|
+
*/
|
|
124
|
+
async createPost(data: CreatePostRequest): Promise<WordPressPost> {
|
|
125
|
+
const post = await super.createPost(data);
|
|
126
|
+
|
|
127
|
+
// Invalidate related caches
|
|
128
|
+
await this.cacheInvalidation.invalidateResource('posts', post.id, 'create');
|
|
129
|
+
|
|
130
|
+
return post;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Update post with cache invalidation
|
|
135
|
+
*/
|
|
136
|
+
async updatePost(data: UpdatePostRequest): Promise<WordPressPost> {
|
|
137
|
+
const post = await super.updatePost(data);
|
|
138
|
+
|
|
139
|
+
// Invalidate related caches
|
|
140
|
+
await this.cacheInvalidation.invalidateResource('posts', post.id, 'update');
|
|
141
|
+
|
|
142
|
+
return post;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Delete post with cache invalidation
|
|
147
|
+
*/
|
|
148
|
+
async deletePost(id: number, force?: boolean): Promise<{ deleted: boolean; previous?: WordPressPost }> {
|
|
149
|
+
const result = await super.deletePost(id, force);
|
|
150
|
+
|
|
151
|
+
// Invalidate related caches
|
|
152
|
+
await this.cacheInvalidation.invalidateResource('posts', id, 'delete');
|
|
153
|
+
|
|
154
|
+
return result;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Get current user with session caching
|
|
159
|
+
*/
|
|
160
|
+
async getCurrentUser(): Promise<WordPressUser> {
|
|
161
|
+
return await this.request<WordPressUser>('GET', 'users/me');
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Get categories with semi-static caching
|
|
166
|
+
*/
|
|
167
|
+
async getCategories(params: any = {}): Promise<WordPressCategory[]> {
|
|
168
|
+
return await this.request<WordPressCategory[]>('GET', 'categories', null, { params });
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Get tags with semi-static caching
|
|
173
|
+
*/
|
|
174
|
+
async getTags(params: any = {}): Promise<WordPressTag[]> {
|
|
175
|
+
return await this.request<WordPressTag[]>('GET', 'tags', null, { params });
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Get site settings with static caching
|
|
180
|
+
*/
|
|
181
|
+
async getSiteSettings(): Promise<WordPressSiteSettings> {
|
|
182
|
+
return await this.request<WordPressSiteSettings>('GET', 'settings');
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Cache management methods
|
|
187
|
+
*/
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Private helper methods
|
|
192
|
+
*/
|
|
193
|
+
|
|
194
|
+
private extractEndpoint(url: string): string {
|
|
195
|
+
// Simple approach - use the endpoint part
|
|
196
|
+
return url.replace(/^.*\/wp-json\/wp\/v2\//, '').split('?')[0];
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Get cache options based on endpoint
|
|
201
|
+
*/
|
|
202
|
+
private getCacheOptions(endpoint: string) {
|
|
203
|
+
// Determine cache type based on endpoint
|
|
204
|
+
if (this.isStaticEndpoint(endpoint)) {
|
|
205
|
+
return {
|
|
206
|
+
ttl: SecurityConfig.cache.ttlPresets.static,
|
|
207
|
+
cacheControl: SecurityConfig.cache.cacheHeaders.static
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (this.isSemiStaticEndpoint(endpoint)) {
|
|
212
|
+
return {
|
|
213
|
+
ttl: SecurityConfig.cache.ttlPresets.semiStatic,
|
|
214
|
+
cacheControl: SecurityConfig.cache.cacheHeaders.semiStatic
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (this.isSessionEndpoint(endpoint)) {
|
|
219
|
+
return {
|
|
220
|
+
ttl: SecurityConfig.cache.ttlPresets.session,
|
|
221
|
+
cacheControl: SecurityConfig.cache.cacheHeaders.session,
|
|
222
|
+
private: true
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Default to dynamic caching
|
|
227
|
+
return {
|
|
228
|
+
ttl: SecurityConfig.cache.ttlPresets.dynamic,
|
|
229
|
+
cacheControl: SecurityConfig.cache.cacheHeaders.dynamic
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Handle cache invalidation for write operations
|
|
235
|
+
*/
|
|
236
|
+
private async handleCacheInvalidation(
|
|
237
|
+
method: string,
|
|
238
|
+
endpoint: string,
|
|
239
|
+
data: any
|
|
240
|
+
): Promise<void> {
|
|
241
|
+
const resource = this.extractResourceFromEndpoint(endpoint);
|
|
242
|
+
const id = this.extractIdFromEndpoint(endpoint);
|
|
243
|
+
|
|
244
|
+
let operationType: 'create' | 'update' | 'delete';
|
|
245
|
+
|
|
246
|
+
switch (method.toUpperCase()) {
|
|
247
|
+
case 'POST':
|
|
248
|
+
operationType = 'create';
|
|
249
|
+
break;
|
|
250
|
+
case 'PUT':
|
|
251
|
+
case 'PATCH':
|
|
252
|
+
operationType = 'update';
|
|
253
|
+
break;
|
|
254
|
+
case 'DELETE':
|
|
255
|
+
operationType = 'delete';
|
|
256
|
+
break;
|
|
257
|
+
default:
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
await this.cacheInvalidation.invalidateResource(resource, id, operationType);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Extract resource type from endpoint
|
|
266
|
+
*/
|
|
267
|
+
private extractResourceFromEndpoint(endpoint: string): string {
|
|
268
|
+
const parts = endpoint.split('/');
|
|
269
|
+
return parts[0] || 'unknown';
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Extract ID from endpoint
|
|
274
|
+
*/
|
|
275
|
+
private extractIdFromEndpoint(endpoint: string): number | undefined {
|
|
276
|
+
const match = endpoint.match(/\/(\d+)(?:\/|$)/);
|
|
277
|
+
return match ? parseInt(match[1], 10) : undefined;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Check if endpoint contains static data
|
|
282
|
+
*/
|
|
283
|
+
private isStaticEndpoint(endpoint: string): boolean {
|
|
284
|
+
const staticEndpoints = ['settings', 'types', 'statuses'];
|
|
285
|
+
return staticEndpoints.some(pattern => endpoint.includes(pattern));
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Check if endpoint contains semi-static data
|
|
290
|
+
*/
|
|
291
|
+
private isSemiStaticEndpoint(endpoint: string): boolean {
|
|
292
|
+
const semiStaticEndpoints = ['categories', 'tags', 'users', 'taxonomies'];
|
|
293
|
+
return semiStaticEndpoints.some(pattern => endpoint.includes(pattern));
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Check if endpoint is session-related
|
|
298
|
+
*/
|
|
299
|
+
private isSessionEndpoint(endpoint: string): boolean {
|
|
300
|
+
const sessionEndpoints = ['users/me', 'application-passwords'];
|
|
301
|
+
return sessionEndpoints.some(pattern => endpoint.includes(pattern));
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Performance monitoring and cache management methods
|
|
306
|
+
*/
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Get cache statistics for performance monitoring
|
|
310
|
+
*/
|
|
311
|
+
getCacheStats(): any {
|
|
312
|
+
return this.cacheManager.getStats();
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Get cache manager instance (for performance monitoring integration)
|
|
317
|
+
*/
|
|
318
|
+
getCacheManager(): CacheManager {
|
|
319
|
+
return this.cacheManager;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Clear cache entries (for cache management tools)
|
|
324
|
+
*/
|
|
325
|
+
clearCache(): number {
|
|
326
|
+
const stats = this.cacheManager.getStats();
|
|
327
|
+
this.cacheManager.clear();
|
|
328
|
+
return stats.totalSize;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Clear cache entries matching pattern
|
|
333
|
+
*/
|
|
334
|
+
clearCachePattern(pattern: string): number {
|
|
335
|
+
const regex = new RegExp(pattern, 'i');
|
|
336
|
+
return this.cacheManager.clearPattern(regex);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Warm cache with essential data
|
|
341
|
+
*/
|
|
342
|
+
async warmCache(): Promise<void> {
|
|
343
|
+
try {
|
|
344
|
+
// Pre-load frequently accessed data
|
|
345
|
+
const warmupOperations = [
|
|
346
|
+
() => this.getCurrentUser().catch(() => null),
|
|
347
|
+
() => this.getCategories().catch(() => null),
|
|
348
|
+
() => this.getTags().catch(() => null),
|
|
349
|
+
() => this.getSiteSettings().catch(() => null)
|
|
350
|
+
];
|
|
351
|
+
|
|
352
|
+
// Execute warmup operations in parallel
|
|
353
|
+
await Promise.allSettled(warmupOperations.map(op => op()));
|
|
354
|
+
} catch (_error) {
|
|
355
|
+
// Ignore warmup errors - they shouldn't fail the cache warming
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Get cache efficiency metrics
|
|
361
|
+
*/
|
|
362
|
+
getCacheEfficiency(): {
|
|
363
|
+
hitRate: number;
|
|
364
|
+
missRate: number;
|
|
365
|
+
efficiency: string;
|
|
366
|
+
memoryUsage: number;
|
|
367
|
+
totalEntries: number;
|
|
368
|
+
} {
|
|
369
|
+
const stats = this.cacheManager.getStats();
|
|
370
|
+
const total = stats.hits + stats.misses;
|
|
371
|
+
const hitRate = total > 0 ? stats.hits / total : 0;
|
|
372
|
+
const missRate = 1 - hitRate;
|
|
373
|
+
|
|
374
|
+
let efficiency = 'Poor';
|
|
375
|
+
if (hitRate >= 0.9) efficiency = 'Excellent';
|
|
376
|
+
else if (hitRate >= 0.8) efficiency = 'Good';
|
|
377
|
+
else if (hitRate >= 0.6) efficiency = 'Fair';
|
|
378
|
+
|
|
379
|
+
return {
|
|
380
|
+
hitRate,
|
|
381
|
+
missRate,
|
|
382
|
+
efficiency,
|
|
383
|
+
memoryUsage: this.estimateMemoryUsage(),
|
|
384
|
+
totalEntries: stats.totalSize
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Get cache configuration info
|
|
390
|
+
*/
|
|
391
|
+
getCacheInfo(): {
|
|
392
|
+
enabled: boolean;
|
|
393
|
+
siteId: string;
|
|
394
|
+
maxSize: number;
|
|
395
|
+
defaultTTL: number;
|
|
396
|
+
currentSize: number;
|
|
397
|
+
ttlPresets: any;
|
|
398
|
+
} {
|
|
399
|
+
const stats = this.cacheManager.getStats();
|
|
400
|
+
|
|
401
|
+
return {
|
|
402
|
+
enabled: SecurityConfig.cache.enabled,
|
|
403
|
+
siteId: this.siteId,
|
|
404
|
+
maxSize: SecurityConfig.cache.maxSize,
|
|
405
|
+
defaultTTL: SecurityConfig.cache.defaultTTL,
|
|
406
|
+
currentSize: stats.totalSize,
|
|
407
|
+
ttlPresets: SecurityConfig.cache.ttlPresets
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Estimate memory usage of cache (in MB)
|
|
413
|
+
*/
|
|
414
|
+
private estimateMemoryUsage(): number {
|
|
415
|
+
const stats = this.cacheManager.getStats();
|
|
416
|
+
// Rough estimate: ~1KB per cache entry
|
|
417
|
+
return (stats.totalSize * 1024) / (1024 * 1024);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* Get detailed cache performance metrics
|
|
422
|
+
*/
|
|
423
|
+
getDetailedCacheMetrics(): {
|
|
424
|
+
statistics: any;
|
|
425
|
+
efficiency: any;
|
|
426
|
+
configuration: any;
|
|
427
|
+
siteInfo: {
|
|
428
|
+
siteId: string;
|
|
429
|
+
baseUrl: string;
|
|
430
|
+
};
|
|
431
|
+
} {
|
|
432
|
+
return {
|
|
433
|
+
statistics: this.getCacheStats(),
|
|
434
|
+
efficiency: this.getCacheEfficiency(),
|
|
435
|
+
configuration: this.getCacheInfo(),
|
|
436
|
+
siteInfo: {
|
|
437
|
+
siteId: this.siteId,
|
|
438
|
+
baseUrl: this.config.baseUrl
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Zod schema for WordPress authentication methods
|
|
5
|
+
*/
|
|
6
|
+
const AuthMethodSchema = z.enum([
|
|
7
|
+
'app-password',
|
|
8
|
+
'jwt',
|
|
9
|
+
'basic',
|
|
10
|
+
'api-key',
|
|
11
|
+
'cookie'
|
|
12
|
+
] as const);
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Zod schema for URL validation
|
|
16
|
+
*/
|
|
17
|
+
const UrlSchema = z
|
|
18
|
+
.string()
|
|
19
|
+
.url('Must be a valid URL')
|
|
20
|
+
.refine((url) => {
|
|
21
|
+
const parsed = new URL(url);
|
|
22
|
+
return parsed.protocol === 'http:' || parsed.protocol === 'https:';
|
|
23
|
+
}, 'URL must use http or https protocol');
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Zod schema for WordPress site configuration
|
|
27
|
+
*/
|
|
28
|
+
const SiteConfigSchema = z.object({
|
|
29
|
+
WORDPRESS_SITE_URL: UrlSchema,
|
|
30
|
+
WORDPRESS_USERNAME: z
|
|
31
|
+
.string()
|
|
32
|
+
.min(1, 'Username is required')
|
|
33
|
+
.max(60, 'Username must be 60 characters or less')
|
|
34
|
+
.regex(/^[a-zA-Z0-9._@-]+$/, 'Username contains invalid characters'),
|
|
35
|
+
WORDPRESS_APP_PASSWORD: z
|
|
36
|
+
.string()
|
|
37
|
+
.min(1, 'Password is required')
|
|
38
|
+
.refine((password) => {
|
|
39
|
+
// WordPress app passwords are typically 24 characters with spaces
|
|
40
|
+
// But we'll be flexible to support different auth methods
|
|
41
|
+
return password.length >= 8;
|
|
42
|
+
}, 'Password must be at least 8 characters'),
|
|
43
|
+
WORDPRESS_AUTH_METHOD: AuthMethodSchema.optional().default('app-password')
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Zod schema for site configuration with metadata
|
|
48
|
+
*/
|
|
49
|
+
const SiteSchema = z.object({
|
|
50
|
+
id: z
|
|
51
|
+
.string()
|
|
52
|
+
.min(1, 'Site ID is required')
|
|
53
|
+
.max(50, 'Site ID must be 50 characters or less')
|
|
54
|
+
.regex(
|
|
55
|
+
/^[a-zA-Z0-9_-]+$/,
|
|
56
|
+
'Site ID can only contain letters, numbers, underscores, and hyphens'
|
|
57
|
+
),
|
|
58
|
+
name: z
|
|
59
|
+
.string()
|
|
60
|
+
.min(1, 'Site name is required')
|
|
61
|
+
.max(100, 'Site name must be 100 characters or less'),
|
|
62
|
+
config: SiteConfigSchema
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Zod schema for multi-site configuration file
|
|
67
|
+
*/
|
|
68
|
+
const MultiSiteConfigSchema = z.object({
|
|
69
|
+
sites: z
|
|
70
|
+
.array(SiteSchema)
|
|
71
|
+
.min(1, 'At least one site must be configured')
|
|
72
|
+
.max(50, 'Maximum of 50 sites supported')
|
|
73
|
+
.refine((sites) => {
|
|
74
|
+
const ids = sites.map((site) => site.id);
|
|
75
|
+
const uniqueIds = new Set(ids);
|
|
76
|
+
return ids.length === uniqueIds.size;
|
|
77
|
+
}, 'Site IDs must be unique')
|
|
78
|
+
.refine((sites) => {
|
|
79
|
+
const names = sites.map((site) => site.name);
|
|
80
|
+
const uniqueNames = new Set(names);
|
|
81
|
+
return names.length === uniqueNames.size;
|
|
82
|
+
}, 'Site names must be unique')
|
|
83
|
+
.refine((sites) => {
|
|
84
|
+
const urls = sites.map((site) => site.config.WORDPRESS_SITE_URL);
|
|
85
|
+
const uniqueUrls = new Set(urls);
|
|
86
|
+
return urls.length === uniqueUrls.size;
|
|
87
|
+
}, 'Site URLs must be unique')
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Zod schema for environment variables (single-site mode)
|
|
92
|
+
*/
|
|
93
|
+
const EnvironmentConfigSchema = z.object({
|
|
94
|
+
WORDPRESS_SITE_URL: UrlSchema,
|
|
95
|
+
WORDPRESS_USERNAME: SiteConfigSchema.shape.WORDPRESS_USERNAME,
|
|
96
|
+
WORDPRESS_APP_PASSWORD: SiteConfigSchema.shape.WORDPRESS_APP_PASSWORD,
|
|
97
|
+
WORDPRESS_AUTH_METHOD: AuthMethodSchema.optional().default('app-password'),
|
|
98
|
+
// Optional environment variables
|
|
99
|
+
NODE_ENV: z.enum(['development', 'production', 'test']).optional(),
|
|
100
|
+
DEBUG: z.string().optional(),
|
|
101
|
+
DISABLE_CACHE: z.string().optional(),
|
|
102
|
+
LOG_LEVEL: z.enum(['error', 'warn', 'info', 'debug']).optional()
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Zod schema for MCP configuration passed from client
|
|
107
|
+
*/
|
|
108
|
+
const McpConfigSchema = z
|
|
109
|
+
.object({
|
|
110
|
+
wordpressSiteUrl: UrlSchema.optional(),
|
|
111
|
+
wordpressUsername: SiteConfigSchema.shape.WORDPRESS_USERNAME.optional(),
|
|
112
|
+
wordpressAppPassword:
|
|
113
|
+
SiteConfigSchema.shape.WORDPRESS_APP_PASSWORD.optional(),
|
|
114
|
+
wordpressAuthMethod: AuthMethodSchema.optional()
|
|
115
|
+
})
|
|
116
|
+
.optional();
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Type definitions derived from Zod schemas
|
|
120
|
+
*/
|
|
121
|
+
export type SiteConfigType = z.infer<typeof SiteConfigSchema>;
|
|
122
|
+
export type SiteType = z.infer<typeof SiteSchema>;
|
|
123
|
+
export type MultiSiteConfigType = z.infer<typeof MultiSiteConfigSchema>;
|
|
124
|
+
export type EnvironmentConfigType = z.infer<typeof EnvironmentConfigSchema>;
|
|
125
|
+
export type McpConfigType = z.infer<typeof McpConfigSchema>;
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Configuration validation utilities
|
|
129
|
+
*/
|
|
130
|
+
export class ConfigurationValidator {
|
|
131
|
+
/**
|
|
132
|
+
* Validate multi-site configuration from JSON file
|
|
133
|
+
*/
|
|
134
|
+
static validateMultiSiteConfig(config: unknown): MultiSiteConfigType {
|
|
135
|
+
try {
|
|
136
|
+
return MultiSiteConfigSchema.parse(config);
|
|
137
|
+
} catch (error) {
|
|
138
|
+
if (error instanceof z.ZodError) {
|
|
139
|
+
const messages = error.errors
|
|
140
|
+
.map((err) => `${err.path.join('.')}: ${err.message}`)
|
|
141
|
+
.join('; ');
|
|
142
|
+
throw new Error(
|
|
143
|
+
`Multi-site configuration validation failed: ${messages}`
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
throw error;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Validate environment configuration for single-site mode
|
|
152
|
+
*/
|
|
153
|
+
static validateEnvironmentConfig(
|
|
154
|
+
env: Record<string, string | undefined>
|
|
155
|
+
): EnvironmentConfigType {
|
|
156
|
+
try {
|
|
157
|
+
return EnvironmentConfigSchema.parse(env);
|
|
158
|
+
} catch (error) {
|
|
159
|
+
if (error instanceof z.ZodError) {
|
|
160
|
+
const messages = error.errors
|
|
161
|
+
.map((err) => `${err.path.join('.')}: ${err.message}`)
|
|
162
|
+
.join('; ');
|
|
163
|
+
throw new Error(
|
|
164
|
+
`Environment configuration validation failed: ${messages}`
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
throw error;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Validate MCP configuration passed from client
|
|
173
|
+
*/
|
|
174
|
+
static validateMcpConfig(config: unknown): McpConfigType {
|
|
175
|
+
try {
|
|
176
|
+
return McpConfigSchema.parse(config);
|
|
177
|
+
} catch (error) {
|
|
178
|
+
if (error instanceof z.ZodError) {
|
|
179
|
+
const messages = error.errors
|
|
180
|
+
.map((err) => `${err.path.join('.')}: ${err.message}`)
|
|
181
|
+
.join('; ');
|
|
182
|
+
throw new Error(`MCP configuration validation failed: ${messages}`);
|
|
183
|
+
}
|
|
184
|
+
throw error;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Validate a single site configuration
|
|
190
|
+
*/
|
|
191
|
+
static validateSiteConfig(config: unknown): SiteType {
|
|
192
|
+
try {
|
|
193
|
+
return SiteSchema.parse(config);
|
|
194
|
+
} catch (error) {
|
|
195
|
+
if (error instanceof z.ZodError) {
|
|
196
|
+
const messages = error.errors
|
|
197
|
+
.map((err) => `${err.path.join('.')}: ${err.message}`)
|
|
198
|
+
.join('; ');
|
|
199
|
+
throw new Error(`Site configuration validation failed: ${messages}`);
|
|
200
|
+
}
|
|
201
|
+
throw error;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Check if a configuration file structure is valid without throwing
|
|
207
|
+
*/
|
|
208
|
+
static isValidMultiSiteConfig(config: unknown): boolean {
|
|
209
|
+
const result = MultiSiteConfigSchema.safeParse(config);
|
|
210
|
+
return result.success;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Check if environment configuration is valid without throwing
|
|
215
|
+
*/
|
|
216
|
+
static isValidEnvironmentConfig(
|
|
217
|
+
env: Record<string, string | undefined>
|
|
218
|
+
): boolean {
|
|
219
|
+
const result = EnvironmentConfigSchema.safeParse(env);
|
|
220
|
+
return result.success;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Get validation errors without throwing
|
|
225
|
+
*/
|
|
226
|
+
static getValidationErrors(schema: z.ZodSchema, data: unknown): string[] {
|
|
227
|
+
const result = schema.safeParse(data);
|
|
228
|
+
if (result.success) {
|
|
229
|
+
return [];
|
|
230
|
+
}
|
|
231
|
+
return result.error.errors.map(
|
|
232
|
+
(err) => `${err.path.join('.')}: ${err.message}`
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Export schemas for direct use if needed
|
|
238
|
+
export {
|
|
239
|
+
SiteConfigSchema,
|
|
240
|
+
SiteSchema,
|
|
241
|
+
MultiSiteConfigSchema,
|
|
242
|
+
EnvironmentConfigSchema,
|
|
243
|
+
McpConfigSchema,
|
|
244
|
+
AuthMethodSchema,
|
|
245
|
+
UrlSchema
|
|
246
|
+
};
|