@maxisoft/instantcms-mcp 1.2.3
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 +308 -0
- package/dist/__tests__/artifact-tool.test.js +196 -0
- package/dist/__tests__/db-tool.test.js +152 -0
- package/dist/__tests__/define-tool.test.js +106 -0
- package/dist/__tests__/find-tool.test.js +185 -0
- package/dist/__tests__/get-component-api.test.js +144 -0
- package/dist/__tests__/hardening.test.js +73 -0
- package/dist/__tests__/hooks-tool.test.js +173 -0
- package/dist/__tests__/mcp-integration-extra.test.js +166 -0
- package/dist/__tests__/mcp-integration.test.js +53 -0
- package/dist/__tests__/pagination.test.js +114 -0
- package/dist/__tests__/performance-baseline.test.js +56 -0
- package/dist/__tests__/project-patch.test.js +144 -0
- package/dist/__tests__/project-source.test.js +44 -0
- package/dist/__tests__/project-workflows-extra.test.js +165 -0
- package/dist/__tests__/project-workflows.test.js +51 -0
- package/dist/__tests__/scaffold-addon-roundtrip.test.js +287 -0
- package/dist/__tests__/serialization.test.js +170 -0
- package/dist/__tests__/source-knowledge-parsers.test.js +42 -0
- package/dist/__tests__/template-development.test.js +78 -0
- package/dist/__tests__/template-productivity.test.js +87 -0
- package/dist/__tests__/tools.test.js +2143 -0
- package/dist/data/components.js +2818 -0
- package/dist/data/controllers-map.js +7571 -0
- package/dist/data/core-api.js +9356 -0
- package/dist/data/database-schema.js +4555 -0
- package/dist/data/events-map.js +1339 -0
- package/dist/data/fields-map.js +3692 -0
- package/dist/data/hooks.js +2257 -0
- package/dist/data/js-api.js +123 -0
- package/dist/data/libs-api.js +264 -0
- package/dist/data/routes-map.js +203 -0
- package/dist/data/schemas-validation.js +255 -0
- package/dist/data/schemas.js +1404 -0
- package/dist/data/traits-map.js +1004 -0
- package/dist/data/version-profiles.js +41 -0
- package/dist/data/widgets-map.js +131 -0
- package/dist/data/wysiwyg-map.js +486 -0
- package/dist/generated/components-source.js +14748 -0
- package/dist/generated/hooks-source.js +3399 -0
- package/dist/generated/knowledge-meta.js +101 -0
- package/dist/index.js +13 -0
- package/dist/registry/database-tools.js +112 -0
- package/dist/registry/extension-tools.js +473 -0
- package/dist/registry/generator-tools.js +506 -0
- package/dist/registry/knowledge-tools.js +441 -0
- package/dist/registry/language-tools.js +99 -0
- package/dist/registry/meta-tools.js +152 -0
- package/dist/registry/project-tools.js +48 -0
- package/dist/registry/resources.js +98 -0
- package/dist/registry/source-tools.js +211 -0
- package/dist/registry/template-development-tools.js +79 -0
- package/dist/server.js +32 -0
- package/dist/tools/addon-tool.js +1437 -0
- package/dist/tools/admin-partial-tool.js +498 -0
- package/dist/tools/api-tool.js +294 -0
- package/dist/tools/artifact-tool.js +95 -0
- package/dist/tools/cache-tool.js +360 -0
- package/dist/tools/component-tool.js +415 -0
- package/dist/tools/controllers-tool.js +125 -0
- package/dist/tools/cron-tool.js +197 -0
- package/dist/tools/crud-tool.js +659 -0
- package/dist/tools/db-tool.js +198 -0
- package/dist/tools/email-tool.js +222 -0
- package/dist/tools/external-api-tool.js +596 -0
- package/dist/tools/filter-tool.js +341 -0
- package/dist/tools/form-tool.js +275 -0
- package/dist/tools/grid-tool.js +189 -0
- package/dist/tools/hooks-tool.js +104 -0
- package/dist/tools/import-export-tool.js +548 -0
- package/dist/tools/lang-tool.js +251 -0
- package/dist/tools/layout-override-tool.js +125 -0
- package/dist/tools/layout-tool.js +548 -0
- package/dist/tools/maria-tool.js +127 -0
- package/dist/tools/mariadb.js +201 -0
- package/dist/tools/migration-tool.js +329 -0
- package/dist/tools/oauth-tool.js +520 -0
- package/dist/tools/parser/components-parser.js +76 -0
- package/dist/tools/parser/controllers-parser.js +313 -0
- package/dist/tools/parser/core-parser.js +294 -0
- package/dist/tools/parser/coverage-generator.js +424 -0
- package/dist/tools/parser/events-parser.js +127 -0
- package/dist/tools/parser/fields-parser.js +382 -0
- package/dist/tools/parser/hooks-parser.js +106 -0
- package/dist/tools/parser/sql-parser.js +197 -0
- package/dist/tools/parser/traits-parser.js +161 -0
- package/dist/tools/parser/widgets-parser.js +150 -0
- package/dist/tools/permission-tool.js +348 -0
- package/dist/tools/project-patch-tool.js +73 -0
- package/dist/tools/project-source-tool.js +188 -0
- package/dist/tools/project-workflow-tool.js +186 -0
- package/dist/tools/requirement-tool.js +212 -0
- package/dist/tools/scaffold-tool.js +815 -0
- package/dist/tools/seo-tool.js +412 -0
- package/dist/tools/source-tool.js +155 -0
- package/dist/tools/template-development-tool.js +271 -0
- package/dist/tools/template-overrides-tool.js +294 -0
- package/dist/tools/template-productivity-tool.js +319 -0
- package/dist/tools/template-tool.js +665 -0
- package/dist/tools/test-tool.js +183 -0
- package/dist/tools/webhook-tool.js +427 -0
- package/dist/tools/widget-tool.js +331 -0
- package/dist/tools/wysiwyg-tool.js +137 -0
- package/dist/types/scaffold.js +68 -0
- package/dist/utils/define-tool.js +37 -0
- package/dist/utils/find-tool.js +97 -0
- package/dist/utils/mcp-result.js +18 -0
- package/dist/utils/pagination.js +27 -0
- package/dist/utils/serialization.js +27 -0
- package/package.json +94 -0
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Caching system scaffolding tool for InstantCMS
|
|
4
|
+
* Generates cache classes, tag-based cache invalidation, and hook handlers
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.cacheToolSchema = void 0;
|
|
8
|
+
exports.scaffoldCache = scaffoldCache;
|
|
9
|
+
const scaffold_1 = require("../types/scaffold");
|
|
10
|
+
/**
|
|
11
|
+
* Generates cache class
|
|
12
|
+
*/
|
|
13
|
+
function generateCacheClass(name, Name, options) {
|
|
14
|
+
return `<?php
|
|
15
|
+
// InstantCMS 2. ${name}/cache.php
|
|
16
|
+
|
|
17
|
+
class ${Name}Cache {
|
|
18
|
+
private static $instance = null;
|
|
19
|
+
private $cache = null;
|
|
20
|
+
private $prefix = '${name}_';
|
|
21
|
+
private $default_ttl = ${options.default_ttl};
|
|
22
|
+
|
|
23
|
+
private function __construct() {
|
|
24
|
+
$this->initCache();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public static function getInstance() {
|
|
28
|
+
if (self::$instance === null) {
|
|
29
|
+
self::$instance = new self();
|
|
30
|
+
}
|
|
31
|
+
return self::$instance;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
private function initCache() {
|
|
35
|
+
if (${options.use_redis}) {
|
|
36
|
+
$this->cache = cmsCache::getInstance('redis');
|
|
37
|
+
} elseif (${options.use_memcached}) {
|
|
38
|
+
$this->cache = cmsCache::getInstance('memcached');
|
|
39
|
+
} else {
|
|
40
|
+
$this->cache = cmsCache::getInstance();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public function get($key, $callback = null, $ttl = null) {
|
|
45
|
+
$cache_key = $this->prefix . $key;
|
|
46
|
+
$data = $this->cache->get($cache_key);
|
|
47
|
+
|
|
48
|
+
if ($data !== false) {
|
|
49
|
+
return $data;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if ($callback !== null) {
|
|
53
|
+
$data = call_user_func($callback);
|
|
54
|
+
$this->set($key, $data, $ttl);
|
|
55
|
+
return $data;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public function set($key, $value, $ttl = null) {
|
|
62
|
+
$cache_key = $this->prefix . $key;
|
|
63
|
+
$ttl = $ttl ?? $this->default_ttl;
|
|
64
|
+
|
|
65
|
+
return $this->cache->set($cache_key, $value, $ttl);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
public function delete($key) {
|
|
69
|
+
$cache_key = $this->prefix . $key;
|
|
70
|
+
return $this->cache->delete($cache_key);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
public function clear() {
|
|
74
|
+
return $this->cache->clean();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
public function exists($key) {
|
|
78
|
+
$cache_key = $this->prefix . $key;
|
|
79
|
+
return $this->cache->get($cache_key) !== false;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
public function increment($key, $offset = 1) {
|
|
83
|
+
$cache_key = $this->prefix . $key;
|
|
84
|
+
return $this->cache->increment($cache_key, $offset);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
public function decrement($key, $offset = 1) {
|
|
88
|
+
$cache_key = $this->prefix . $key;
|
|
89
|
+
return $this->cache->decrement($cache_key, $offset);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
public function remember($key, $callback, $ttl = null) {
|
|
93
|
+
return $this->get($key, $callback, $ttl);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
public function forget($key) {
|
|
97
|
+
return $this->delete($key);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
public function flush() {
|
|
101
|
+
return $this->clear();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
public function invalidateItem($item_id) {
|
|
105
|
+
$this->delete('item_' . $item_id);
|
|
106
|
+
$this->delete('list_page_1');
|
|
107
|
+
|
|
108
|
+
if (${options.use_tags}) {
|
|
109
|
+
$this->deleteTag('item:' . $item_id);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
public function invalidateList() {
|
|
114
|
+
$this->delete('list_page_1');
|
|
115
|
+
$this->delete('list_all');
|
|
116
|
+
|
|
117
|
+
if (${options.use_tags}) {
|
|
118
|
+
$this->deleteTag('list');
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
public function warmUp($callback) {
|
|
123
|
+
$data = call_user_func($callback);
|
|
124
|
+
$this->set('list_all', $data);
|
|
125
|
+
return $data;
|
|
126
|
+
}
|
|
127
|
+
}`;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Generates cache tags class for tag-based invalidation
|
|
131
|
+
*/
|
|
132
|
+
function generateCacheTags(name, Name, _options) {
|
|
133
|
+
return `<?php
|
|
134
|
+
// InstantCMS 2. ${name}/cache.tags.php
|
|
135
|
+
|
|
136
|
+
class ${Name}CacheTags {
|
|
137
|
+
private static $instance = null;
|
|
138
|
+
private $cache = null;
|
|
139
|
+
private $prefix = '${name}_tags_';
|
|
140
|
+
private $tag_index_key = '${name}_tag_index';
|
|
141
|
+
|
|
142
|
+
private function __construct() {
|
|
143
|
+
$this->cache = cmsCache::getInstance();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
public static function getInstance() {
|
|
147
|
+
if (self::$instance === null) {
|
|
148
|
+
self::$instance = new self();
|
|
149
|
+
}
|
|
150
|
+
return self::$instance;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
public function get($key, $tags, $callback = null, $ttl = null) {
|
|
154
|
+
$cache_key = $this->prefix . $key;
|
|
155
|
+
$data = $this->cache->get($cache_key);
|
|
156
|
+
|
|
157
|
+
if ($data !== false) {
|
|
158
|
+
$this->registerTags($key, $tags);
|
|
159
|
+
return $data;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if ($callback !== null) {
|
|
163
|
+
$data = call_user_func($callback);
|
|
164
|
+
$this->set($key, $data, $tags, $ttl);
|
|
165
|
+
return $data;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
public function set($key, $value, $tags, $ttl = null) {
|
|
172
|
+
$cache_key = $this->prefix . $key;
|
|
173
|
+
$this->cache->set($cache_key, $value, $ttl);
|
|
174
|
+
$this->registerTags($key, $tags);
|
|
175
|
+
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
public function invalidateTag($tag) {
|
|
180
|
+
$tag_index = $this->cache->get($this->tag_index_key) ?: [];
|
|
181
|
+
|
|
182
|
+
if (empty($tag_index[$tag])) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
foreach ($tag_index[$tag] as $key) {
|
|
187
|
+
$this->cache->delete($this->prefix . $key);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
unset($tag_index[$tag]);
|
|
191
|
+
$this->cache->set($this->tag_index_key, $tag_index);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
public function deleteTag($tag) {
|
|
195
|
+
return $this->invalidateTag($tag);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
public function flushByTag($tag) {
|
|
199
|
+
return $this->invalidateTag($tag);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
public function flushAll() {
|
|
203
|
+
$tag_index = $this->cache->get($this->tag_index_key) ?: [];
|
|
204
|
+
|
|
205
|
+
foreach ($tag_index as $tag => $keys) {
|
|
206
|
+
foreach ($keys as $key) {
|
|
207
|
+
$this->cache->delete($this->prefix . $key);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
$this->cache->delete($this->tag_index_key);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
private function registerTags($key, $tags) {
|
|
215
|
+
if (empty($tags)) {
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
$tag_index = $this->cache->get($this->tag_index_key) ?: [];
|
|
220
|
+
|
|
221
|
+
if (!is_array($tags)) {
|
|
222
|
+
$tags = [$tags];
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
foreach ($tags as $tag) {
|
|
226
|
+
if (empty($tag_index[$tag])) {
|
|
227
|
+
$tag_index[$tag] = [];
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (!in_array($key, $tag_index[$tag])) {
|
|
231
|
+
$tag_index[$tag][] = $key;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
$this->cache->set($this->tag_index_key, $tag_index);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
public function getTagStats() {
|
|
239
|
+
$tag_index = $this->cache->get($this->tag_index_key) ?: [];
|
|
240
|
+
return [
|
|
241
|
+
'total_tags' => count($tag_index),
|
|
242
|
+
'tags' => array_keys($tag_index),
|
|
243
|
+
];
|
|
244
|
+
}
|
|
245
|
+
}`;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Generates cache hook handlers
|
|
249
|
+
*/
|
|
250
|
+
function generateCacheHooks(name, Name, options) {
|
|
251
|
+
return `<?php
|
|
252
|
+
// InstantCMS 2. system/hooks/${name}/cache.hooks.php
|
|
253
|
+
|
|
254
|
+
class on${Name}CacheHook {
|
|
255
|
+
public function onAfterSave($item) {
|
|
256
|
+
${Name}Cache::getInstance()->invalidateItem($item['id']);
|
|
257
|
+
${Name}Cache::getInstance()->invalidateList();
|
|
258
|
+
|
|
259
|
+
if (${options.use_tags}) {
|
|
260
|
+
${Name}CacheTags::getInstance()->invalidateTag('item:' . $item['id']);
|
|
261
|
+
${Name}CacheTags::getInstance()->invalidateTag('list');
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
public function onAfterDelete($item) {
|
|
266
|
+
${Name}Cache::getInstance()->invalidateItem($item['id']);
|
|
267
|
+
${Name}Cache::getInstance()->invalidateList();
|
|
268
|
+
|
|
269
|
+
if (${options.use_tags}) {
|
|
270
|
+
${Name}CacheTags::getInstance()->invalidateTag('item:' . $item['id']);
|
|
271
|
+
${Name}CacheTags::getInstance()->invalidateTag('list');
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
public function onAfterPublish($item) {
|
|
276
|
+
${Name}Cache::getInstance()->invalidateItem($item['id']);
|
|
277
|
+
${Name}Cache::getInstance()->invalidateList();
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
public function onAfterUnpublish($item) {
|
|
281
|
+
${Name}Cache::getInstance()->invalidateItem($item['id']);
|
|
282
|
+
${Name}Cache::getInstance()->invalidateList();
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
public function onAfterBulkUpdate($ids) {
|
|
286
|
+
foreach ($ids as $id) {
|
|
287
|
+
${Name}Cache::getInstance()->invalidateItem($id);
|
|
288
|
+
}
|
|
289
|
+
${Name}Cache::getInstance()->invalidateList();
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
public function onClearCache() {
|
|
293
|
+
${Name}Cache::getInstance()->clear();
|
|
294
|
+
|
|
295
|
+
if (${options.use_tags}) {
|
|
296
|
+
${Name}CacheTags::getInstance()->flushAll();
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}`;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Generates a complete caching system for an InstantCMS addon
|
|
303
|
+
*
|
|
304
|
+
* @param opts - Configuration options for the cache system
|
|
305
|
+
* @returns Object containing generated files and metadata
|
|
306
|
+
*
|
|
307
|
+
* @example
|
|
308
|
+
* ```typescript
|
|
309
|
+
* const result = scaffoldCache({
|
|
310
|
+
* addon_name: 'blog',
|
|
311
|
+
* options: { use_redis: true, default_ttl: 3600, use_tags: true }
|
|
312
|
+
* });
|
|
313
|
+
* ```
|
|
314
|
+
*/
|
|
315
|
+
function scaffoldCache(opts) {
|
|
316
|
+
const { lowercase, UpperCamelCase } = (0, scaffold_1.normalizeAddonName)(opts.addon_name);
|
|
317
|
+
const files = {};
|
|
318
|
+
const options = {
|
|
319
|
+
use_memcached: opts.options?.use_memcached ?? false,
|
|
320
|
+
use_redis: opts.options?.use_redis ?? false,
|
|
321
|
+
default_ttl: opts.options?.default_ttl ?? 3600,
|
|
322
|
+
use_tags: opts.options?.use_tags ?? true,
|
|
323
|
+
};
|
|
324
|
+
files[`${lowercase}/cache.php`] = generateCacheClass(lowercase, UpperCamelCase, options);
|
|
325
|
+
if (options.use_tags) {
|
|
326
|
+
files[`${lowercase}/cache.tags.php`] = generateCacheTags(lowercase, UpperCamelCase, options);
|
|
327
|
+
}
|
|
328
|
+
files[`system/hooks/${lowercase}/cache.hooks.php`] = generateCacheHooks(lowercase, UpperCamelCase, options);
|
|
329
|
+
return {
|
|
330
|
+
addon_name: lowercase,
|
|
331
|
+
files,
|
|
332
|
+
options,
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
exports.cacheToolSchema = {
|
|
336
|
+
name: 'scaffold_cache',
|
|
337
|
+
description: 'Генерация системы кэширования для InstantCMS',
|
|
338
|
+
inputSchema: {
|
|
339
|
+
type: 'object',
|
|
340
|
+
properties: {
|
|
341
|
+
addon_name: { type: 'string', description: 'Имя дополнения' },
|
|
342
|
+
options: {
|
|
343
|
+
type: 'object',
|
|
344
|
+
properties: {
|
|
345
|
+
use_memcached: { type: 'boolean', description: 'Использовать Memcached' },
|
|
346
|
+
use_redis: { type: 'boolean', description: 'Использовать Redis' },
|
|
347
|
+
default_ttl: { type: 'number', description: 'TTL по умолчанию (секунды)' },
|
|
348
|
+
use_tags: { type: 'boolean', description: 'Использовать теги кэша' },
|
|
349
|
+
},
|
|
350
|
+
},
|
|
351
|
+
},
|
|
352
|
+
required: ['addon_name'],
|
|
353
|
+
},
|
|
354
|
+
inputExamples: [
|
|
355
|
+
{
|
|
356
|
+
addon_name: 'blog',
|
|
357
|
+
options: { use_redis: true, default_ttl: 3600, use_tags: true },
|
|
358
|
+
},
|
|
359
|
+
],
|
|
360
|
+
};
|