@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.
Files changed (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +308 -0
  3. package/dist/__tests__/artifact-tool.test.js +196 -0
  4. package/dist/__tests__/db-tool.test.js +152 -0
  5. package/dist/__tests__/define-tool.test.js +106 -0
  6. package/dist/__tests__/find-tool.test.js +185 -0
  7. package/dist/__tests__/get-component-api.test.js +144 -0
  8. package/dist/__tests__/hardening.test.js +73 -0
  9. package/dist/__tests__/hooks-tool.test.js +173 -0
  10. package/dist/__tests__/mcp-integration-extra.test.js +166 -0
  11. package/dist/__tests__/mcp-integration.test.js +53 -0
  12. package/dist/__tests__/pagination.test.js +114 -0
  13. package/dist/__tests__/performance-baseline.test.js +56 -0
  14. package/dist/__tests__/project-patch.test.js +144 -0
  15. package/dist/__tests__/project-source.test.js +44 -0
  16. package/dist/__tests__/project-workflows-extra.test.js +165 -0
  17. package/dist/__tests__/project-workflows.test.js +51 -0
  18. package/dist/__tests__/scaffold-addon-roundtrip.test.js +287 -0
  19. package/dist/__tests__/serialization.test.js +170 -0
  20. package/dist/__tests__/source-knowledge-parsers.test.js +42 -0
  21. package/dist/__tests__/template-development.test.js +78 -0
  22. package/dist/__tests__/template-productivity.test.js +87 -0
  23. package/dist/__tests__/tools.test.js +2143 -0
  24. package/dist/data/components.js +2818 -0
  25. package/dist/data/controllers-map.js +7571 -0
  26. package/dist/data/core-api.js +9356 -0
  27. package/dist/data/database-schema.js +4555 -0
  28. package/dist/data/events-map.js +1339 -0
  29. package/dist/data/fields-map.js +3692 -0
  30. package/dist/data/hooks.js +2257 -0
  31. package/dist/data/js-api.js +123 -0
  32. package/dist/data/libs-api.js +264 -0
  33. package/dist/data/routes-map.js +203 -0
  34. package/dist/data/schemas-validation.js +255 -0
  35. package/dist/data/schemas.js +1404 -0
  36. package/dist/data/traits-map.js +1004 -0
  37. package/dist/data/version-profiles.js +41 -0
  38. package/dist/data/widgets-map.js +131 -0
  39. package/dist/data/wysiwyg-map.js +486 -0
  40. package/dist/generated/components-source.js +14748 -0
  41. package/dist/generated/hooks-source.js +3399 -0
  42. package/dist/generated/knowledge-meta.js +101 -0
  43. package/dist/index.js +13 -0
  44. package/dist/registry/database-tools.js +112 -0
  45. package/dist/registry/extension-tools.js +473 -0
  46. package/dist/registry/generator-tools.js +506 -0
  47. package/dist/registry/knowledge-tools.js +441 -0
  48. package/dist/registry/language-tools.js +99 -0
  49. package/dist/registry/meta-tools.js +152 -0
  50. package/dist/registry/project-tools.js +48 -0
  51. package/dist/registry/resources.js +98 -0
  52. package/dist/registry/source-tools.js +211 -0
  53. package/dist/registry/template-development-tools.js +79 -0
  54. package/dist/server.js +32 -0
  55. package/dist/tools/addon-tool.js +1437 -0
  56. package/dist/tools/admin-partial-tool.js +498 -0
  57. package/dist/tools/api-tool.js +294 -0
  58. package/dist/tools/artifact-tool.js +95 -0
  59. package/dist/tools/cache-tool.js +360 -0
  60. package/dist/tools/component-tool.js +415 -0
  61. package/dist/tools/controllers-tool.js +125 -0
  62. package/dist/tools/cron-tool.js +197 -0
  63. package/dist/tools/crud-tool.js +659 -0
  64. package/dist/tools/db-tool.js +198 -0
  65. package/dist/tools/email-tool.js +222 -0
  66. package/dist/tools/external-api-tool.js +596 -0
  67. package/dist/tools/filter-tool.js +341 -0
  68. package/dist/tools/form-tool.js +275 -0
  69. package/dist/tools/grid-tool.js +189 -0
  70. package/dist/tools/hooks-tool.js +104 -0
  71. package/dist/tools/import-export-tool.js +548 -0
  72. package/dist/tools/lang-tool.js +251 -0
  73. package/dist/tools/layout-override-tool.js +125 -0
  74. package/dist/tools/layout-tool.js +548 -0
  75. package/dist/tools/maria-tool.js +127 -0
  76. package/dist/tools/mariadb.js +201 -0
  77. package/dist/tools/migration-tool.js +329 -0
  78. package/dist/tools/oauth-tool.js +520 -0
  79. package/dist/tools/parser/components-parser.js +76 -0
  80. package/dist/tools/parser/controllers-parser.js +313 -0
  81. package/dist/tools/parser/core-parser.js +294 -0
  82. package/dist/tools/parser/coverage-generator.js +424 -0
  83. package/dist/tools/parser/events-parser.js +127 -0
  84. package/dist/tools/parser/fields-parser.js +382 -0
  85. package/dist/tools/parser/hooks-parser.js +106 -0
  86. package/dist/tools/parser/sql-parser.js +197 -0
  87. package/dist/tools/parser/traits-parser.js +161 -0
  88. package/dist/tools/parser/widgets-parser.js +150 -0
  89. package/dist/tools/permission-tool.js +348 -0
  90. package/dist/tools/project-patch-tool.js +73 -0
  91. package/dist/tools/project-source-tool.js +188 -0
  92. package/dist/tools/project-workflow-tool.js +186 -0
  93. package/dist/tools/requirement-tool.js +212 -0
  94. package/dist/tools/scaffold-tool.js +815 -0
  95. package/dist/tools/seo-tool.js +412 -0
  96. package/dist/tools/source-tool.js +155 -0
  97. package/dist/tools/template-development-tool.js +271 -0
  98. package/dist/tools/template-overrides-tool.js +294 -0
  99. package/dist/tools/template-productivity-tool.js +319 -0
  100. package/dist/tools/template-tool.js +665 -0
  101. package/dist/tools/test-tool.js +183 -0
  102. package/dist/tools/webhook-tool.js +427 -0
  103. package/dist/tools/widget-tool.js +331 -0
  104. package/dist/tools/wysiwyg-tool.js +137 -0
  105. package/dist/types/scaffold.js +68 -0
  106. package/dist/utils/define-tool.js +37 -0
  107. package/dist/utils/find-tool.js +97 -0
  108. package/dist/utils/mcp-result.js +18 -0
  109. package/dist/utils/pagination.js +27 -0
  110. package/dist/utils/serialization.js +27 -0
  111. package/package.json +94 -0
@@ -0,0 +1,251 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listLangKeys = listLangKeys;
4
+ exports.scaffoldLang = scaffoldLang;
5
+ function listLangKeys(params) {
6
+ const { addon_name, category } = params;
7
+ const prefix = `LANG_${addon_name.toUpperCase()}_`;
8
+ // Генерируем типовые ключи
9
+ const commonTemplates = [
10
+ { key: prefix + 'CONTROLLER', value: addon_name, category: 'system' },
11
+ { key: prefix + '_ADD', value: `Добавить ${addon_name}`, category: 'actions' },
12
+ { key: prefix + '_EDIT', value: `Редактировать ${addon_name}`, category: 'actions' },
13
+ { key: prefix + '_DELETE', value: `Удалить ${addon_name}`, category: 'actions' },
14
+ { key: prefix + '_LIST', value: `Список ${addon_name}`, category: 'pages' },
15
+ { key: prefix + '_VIEW', value: `Просмотр ${addon_name}`, category: 'pages' },
16
+ { key: prefix + '_SAVE', value: 'Сохранить', category: 'buttons' },
17
+ { key: prefix + '_CANCEL', value: 'Отмена', category: 'buttons' },
18
+ { key: prefix + '_APPLY', value: 'Применить', category: 'buttons' },
19
+ { key: prefix + '_BACK', value: 'Назад', category: 'buttons' },
20
+ { key: prefix + '_PUBLISHED', value: 'Опубликовано', category: 'status' },
21
+ { key: prefix + '_DRAFT', value: 'Черновик', category: 'status' },
22
+ {
23
+ key: prefix + '_DELETE_CONFIRM',
24
+ value: 'Вы уверены, что хотите удалить это?',
25
+ category: 'confirm',
26
+ },
27
+ { key: prefix + '_TITLE', value: 'Заголовок', category: 'fields' },
28
+ { key: prefix + '_DESCRIPTION', value: 'Описание', category: 'fields' },
29
+ { key: prefix + '_CONTENT', value: 'Контент', category: 'fields' },
30
+ { key: prefix + '_DATE', value: 'Дата', category: 'fields' },
31
+ { key: prefix + '_AUTHOR', value: 'Автор', category: 'fields' },
32
+ { key: prefix + '_ERROR_NOT_FOUND', value: `${addon_name} не найдено`, category: 'errors' },
33
+ { key: prefix + '_ERROR_SAVE', value: 'Ошибка сохранения', category: 'errors' },
34
+ { key: prefix + '_ERROR_DELETE', value: 'Ошибка удаления', category: 'errors' },
35
+ { key: prefix + '_PERM_VIEW', value: 'Просмотр', category: 'permissions' },
36
+ { key: prefix + '_PERM_ADD', value: 'Добавление', category: 'permissions' },
37
+ { key: prefix + '_PERM_EDIT', value: 'Редактирование', category: 'permissions' },
38
+ { key: prefix + '_PERM_DELETE', value: 'Удаление', category: 'permissions' },
39
+ { key: prefix + '_CREATED', value: 'Создано', category: 'dates' },
40
+ { key: prefix + '_UPDATED', value: 'Обновлено', category: 'dates' },
41
+ { key: prefix + '_EMPTY', value: `Нет ${addon_name}`, category: 'messages' },
42
+ {
43
+ key: prefix + '_SUCCESS_ADD',
44
+ value: `${addon_name} успешно добавлено`,
45
+ category: 'messages',
46
+ },
47
+ {
48
+ key: prefix + '_SUCCESS_UPDATE',
49
+ value: `${addon_name} успешно обновлено`,
50
+ category: 'messages',
51
+ },
52
+ {
53
+ key: prefix + '_SUCCESS_DELETE',
54
+ value: `${addon_name} успешно удалено`,
55
+ category: 'messages',
56
+ },
57
+ ];
58
+ // Добавляем варианты для множественного числа
59
+ commonTemplates.push({ key: prefix + '_COUNT', value: `Количество ${addon_name}`, category: 'fields' }, { key: prefix + '_TOTAL', value: `Всего ${addon_name}`, category: 'fields' }, { key: prefix + '_PER_PAGE', value: 'На странице', category: 'pagination' }, { key: prefix + '_ORDER', value: 'Сортировка', category: 'fields' }, { key: prefix + '_ASC', value: 'По возрастанию', category: 'sort' }, { key: prefix + '_DESC', value: 'По убыванию', category: 'sort' });
60
+ // Фильтрация по категории
61
+ let filtered = commonTemplates;
62
+ if (category) {
63
+ filtered = commonTemplates.filter(k => k.category === category);
64
+ }
65
+ return {
66
+ addon_name,
67
+ keys_count: filtered.length,
68
+ keys: filtered,
69
+ template: generateLangFile(addon_name, filtered),
70
+ };
71
+ }
72
+ function scaffoldLang(params) {
73
+ const { addon_name, keys = [], custom_keys = [] } = params;
74
+ const prefix = `LANG_${addon_name.toUpperCase()}_`;
75
+ // Базовые ключи если не указаны
76
+ const selectedKeys = keys.length > 0
77
+ ? keys
78
+ : [
79
+ 'CONTROLLER',
80
+ 'ADD',
81
+ 'EDIT',
82
+ 'DELETE',
83
+ 'LIST',
84
+ 'VIEW',
85
+ 'SAVE',
86
+ 'CANCEL',
87
+ 'APPLY',
88
+ 'BACK',
89
+ 'PUBLISHED',
90
+ 'DRAFT',
91
+ 'DELETE_CONFIRM',
92
+ 'TITLE',
93
+ 'DESCRIPTION',
94
+ 'CONTENT',
95
+ 'DATE',
96
+ 'AUTHOR',
97
+ 'ERROR_NOT_FOUND',
98
+ 'ERROR_SAVE',
99
+ 'ERROR_DELETE',
100
+ 'PERM_VIEW',
101
+ 'PERM_ADD',
102
+ 'PERM_EDIT',
103
+ 'PERM_DELETE',
104
+ 'CREATED',
105
+ 'UPDATED',
106
+ 'EMPTY',
107
+ 'SUCCESS_ADD',
108
+ 'SUCCESS_UPDATE',
109
+ 'SUCCESS_DELETE',
110
+ ];
111
+ const allKeys = [];
112
+ // Добавляем выбранные базовые
113
+ for (const k of selectedKeys) {
114
+ const keyName = k.startsWith(prefix) ? k : prefix + k;
115
+ allKeys.push({
116
+ key: keyName,
117
+ value: generateDefaultValue(addon_name, k),
118
+ category: getCategoryForKey(k),
119
+ });
120
+ }
121
+ // Добавляем кастомные
122
+ allKeys.push(...custom_keys);
123
+ // Сортируем по категориям
124
+ const categories = groupByCategory(allKeys);
125
+ return {
126
+ addon_name,
127
+ file_path: `system/languages/ru/controllers/${addon_name}/${addon_name}.php`,
128
+ categories,
129
+ file_content: generateLangFile(addon_name, allKeys),
130
+ usage: {
131
+ location: `/${addon_name}/system/languages/ru/controllers/${addon_name}/${addon_name}.php`,
132
+ include_note: 'Файл подключается автоматически через cmsCore::loadControllerLanguage()',
133
+ constants_format: "define('LANG_KEY', 'value');",
134
+ },
135
+ };
136
+ }
137
+ function generateDefaultValue(addonName, key) {
138
+ const cleanKey = key
139
+ .replace(/^LANG_/, '')
140
+ .replace(/^LANG_/, '')
141
+ .replace(/_/g, ' ');
142
+ const defaults = {
143
+ CONTROLLER: addonName,
144
+ ADD: `Добавить ${addonName}`,
145
+ EDIT: `Редактировать ${addonName}`,
146
+ DELETE: `Удалить ${addonName}`,
147
+ LIST: `Список ${addonName}`,
148
+ VIEW: `Просмотр ${addonName}`,
149
+ SAVE: 'Сохранить',
150
+ CANCEL: 'Отмена',
151
+ APPLY: 'Применить',
152
+ BACK: 'Назад',
153
+ PUBLISHED: 'Опубликовано',
154
+ DRAFT: 'Черновик',
155
+ DELETE_CONFIRM: 'Вы уверены, что хотите удалить?',
156
+ TITLE: 'Заголовок',
157
+ DESCRIPTION: 'Описание',
158
+ CONTENT: 'Контент',
159
+ DATE: 'Дата',
160
+ AUTHOR: 'Автор',
161
+ ERROR_NOT_FOUND: `${addonName} не найдено`,
162
+ ERROR_SAVE: 'Ошибка сохранения',
163
+ ERROR_DELETE: 'Ошибка удаления',
164
+ PERM_VIEW: 'Просмотр',
165
+ PERM_ADD: 'Добавление',
166
+ PERM_EDIT: 'Редактирование',
167
+ PERM_DELETE: 'Удаление',
168
+ CREATED: 'Создано',
169
+ UPDATED: 'Обновлено',
170
+ EMPTY: `Нет ${addonName}`,
171
+ SUCCESS_ADD: `${addonName} успешно добавлено`,
172
+ SUCCESS_UPDATE: `${addonName} успешно обновлено`,
173
+ SUCCESS_DELETE: `${addonName} успешно удалено`,
174
+ };
175
+ return defaults[cleanKey] || cleanKey.charAt(0).toUpperCase() + cleanKey.slice(1).toLowerCase();
176
+ }
177
+ function getCategoryForKey(key) {
178
+ const cleanKey = key
179
+ .replace(/^LANG_/, '')
180
+ .replace(/^_/, '')
181
+ .toLowerCase();
182
+ if (['controller'].includes(cleanKey))
183
+ return 'system';
184
+ if (['add', 'edit', 'delete', 'save', 'cancel', 'apply', 'back'].includes(cleanKey))
185
+ return 'actions';
186
+ if (['list', 'view'].includes(cleanKey))
187
+ return 'pages';
188
+ if (['published', 'draft'].includes(cleanKey))
189
+ return 'status';
190
+ if (['title', 'description', 'content', 'date', 'author', 'ordering'].includes(cleanKey))
191
+ return 'fields';
192
+ if (['error', 'not_found', 'save', 'delete'].some(s => cleanKey.includes(s)))
193
+ return 'errors';
194
+ if (['perm'].includes(cleanKey.slice(0, 4)))
195
+ return 'permissions';
196
+ if (['created', 'updated'].includes(cleanKey))
197
+ return 'dates';
198
+ if (['empty', 'success'].includes(cleanKey))
199
+ return 'messages';
200
+ if (['count', 'total', 'per_page'].includes(cleanKey))
201
+ return 'pagination';
202
+ if (['asc', 'desc', 'order'].includes(cleanKey))
203
+ return 'sort';
204
+ return 'other';
205
+ }
206
+ function groupByCategory(keys) {
207
+ const groups = {};
208
+ for (const k of keys) {
209
+ const cat = k.category || 'other';
210
+ if (!groups[cat])
211
+ groups[cat] = [];
212
+ groups[cat].push({ key: k.key, value: k.value });
213
+ }
214
+ return groups;
215
+ }
216
+ function generateLangFile(addonName, keys) {
217
+ const grouped = groupByCategory(keys);
218
+ const lines = [
219
+ '<?php',
220
+ '',
221
+ `// ${addonName} - Language file`,
222
+ `// Generated: ${new Date().toISOString().split('T')[0]}`,
223
+ '',
224
+ ];
225
+ const categoryOrder = [
226
+ 'system',
227
+ 'actions',
228
+ 'pages',
229
+ 'buttons',
230
+ 'status',
231
+ 'fields',
232
+ 'errors',
233
+ 'permissions',
234
+ 'dates',
235
+ 'pagination',
236
+ 'sort',
237
+ 'messages',
238
+ 'other',
239
+ ];
240
+ for (const cat of categoryOrder) {
241
+ if (!grouped[cat])
242
+ continue;
243
+ lines.push(`// ── ${cat.toUpperCase()} ───────────────────────────────────────`);
244
+ for (const k of grouped[cat]) {
245
+ const escapedValue = k.value.replace(/'/g, "\\'");
246
+ lines.push(`define('${k.key}', '${escapedValue}');`);
247
+ }
248
+ lines.push('');
249
+ }
250
+ return lines.join('\n');
251
+ }
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.scaffoldLayoutOverride = scaffoldLayoutOverride;
4
+ function scaffoldLayoutOverride(opts) {
5
+ const name = opts.addon_name.toLowerCase().replace(/[^a-z0-9_]/g, '_');
6
+ const Name = name.split('_').map(capitalize).join('');
7
+ const NAME = name.toUpperCase();
8
+ const files = {};
9
+ for (const override of opts.overrides) {
10
+ const controllerDir = override.controller.replace(/[^a-z0-9_]/gi, '_').toLowerCase();
11
+ const templateDir = override.template.replace(/[^a-z0-9_]/gi, '_').toLowerCase();
12
+ let filePath;
13
+ if (override.action) {
14
+ filePath = `templates/${templateDir}/controllers/${controllerDir}/${override.action}.tpl.php`;
15
+ }
16
+ else {
17
+ filePath = `templates/${templateDir}/controllers/${controllerDir}/index.tpl.php`;
18
+ }
19
+ files[filePath] = generateLayoutTemplate(name, Name, NAME, override, opts.options);
20
+ }
21
+ files[`package/system/languages/ru/controllers/${name}/${name}.php`] = generateLang(name, NAME, opts.overrides);
22
+ return {
23
+ addon_name: name,
24
+ overrides_count: opts.overrides.length,
25
+ files,
26
+ overrides: opts.overrides.map(o => ({
27
+ controller: o.controller,
28
+ template: o.template,
29
+ action: o.action,
30
+ path: o.action
31
+ ? `templates/${o.template}/controllers/${o.controller}/${o.action}.tpl.php`
32
+ : `templates/${o.template}/controllers/${o.controller}/index.tpl.php`,
33
+ })),
34
+ structure_notes: [
35
+ `Шаблоны переопределений размещаются в templates/{theme}/controllers/{controller}/`,
36
+ `Для применения: Скопируйте файлы в нужную тему`,
37
+ `Языковой файл: /system/languages/ru/controllers/${name}/${name}.php`,
38
+ ],
39
+ };
40
+ }
41
+ function capitalize(str) {
42
+ return str.charAt(0).toUpperCase() + str.slice(1);
43
+ }
44
+ function generateLayoutTemplate(name, Name, NAME, override, options) {
45
+ const useWrapper = options?.use_wrapper ?? false;
46
+ const addBreadcrumbs = options?.add_breadcrumbs ?? true;
47
+ let code = `<?php
48
+ /**
49
+ * Переопределение шаблона контроллера ${override.controller}${override.action ? `/${override.action}` : ''}
50
+ * для шаблона ${override.template}
51
+ *
52
+ * Оригинал: system/templates/${override.template}/controllers/${override.controller}/${override.action || 'index'}.tpl.php
53
+ */
54
+
55
+ `;
56
+ if (useWrapper) {
57
+ code += `
58
+ <?php if (!defined('DEBUG')) die('Quiet'); ?>
59
+ `;
60
+ }
61
+ code += `
62
+ <div class="${name}-controller ${name}-controller-${override.controller}${override.action ? ` ${name}-action-${override.action}` : ''}">
63
+ `;
64
+ if (addBreadcrumbs) {
65
+ code += `
66
+ <?php if ($this->breadcrumbs) { ?>
67
+ <div class="content-breadcrumbs">
68
+ <?php echo $this->breadcrumbs; ?>
69
+ </div>
70
+ <?php } ?>
71
+ `;
72
+ }
73
+ code += `
74
+ <div class="${name}-content">
75
+ <?php
76
+ // Вызов оригинального шаблона или рендер контента
77
+ // $content = $this->renderPartial('${override.controller}', '${override.action || 'index'}', $vars);
78
+ ?>
79
+
80
+ <!-- Ваш контент здесь -->
81
+ <div class="${name}-item">
82
+ <h2><?php echo html($item['title'] ?? '${Name}'); ?></h2>
83
+ <div class="${name}-body">
84
+ <?php echo $item['content'] ?? ''; ?>
85
+ </div>
86
+ </div>
87
+ </div>
88
+ `;
89
+ if (useWrapper) {
90
+ code += `
91
+
92
+ <aside class="${name}-sidebar">
93
+ <?php echo $this->widgets('${override.controller}_sidebar'); ?>
94
+ </aside>
95
+ `;
96
+ }
97
+ code += `
98
+ </div>
99
+ `;
100
+ return code;
101
+ }
102
+ function generateLang(name, NAME, overrides) {
103
+ let code = `<?php
104
+ /**
105
+ * Языковые константы для переопределений шаблонов ${name}
106
+ */
107
+
108
+ `;
109
+ for (const override of overrides) {
110
+ const ctrlName = override.controller.toUpperCase().replace(/[^A-Z]/g, '_');
111
+ const actionName = override.action
112
+ ? `_${override.action.toUpperCase().replace(/[^A-Z]/g, '_')}`
113
+ : '';
114
+ code += `define('LANG_${NAME}_OVERRIDE_${ctrlName}${actionName}', 'Переопределение: ${override.controller}${override.action ? `/${override.action}` : ''}');
115
+ `;
116
+ }
117
+ code += `
118
+
119
+ // Заголовки
120
+ define('LANG_${NAME}_TITLE', '${capitalize(name.replace(/_/g, ' '))}');
121
+ define('LANG_${NAME}_CONTENT', 'Контент');
122
+ define('LANG_${NAME}_SIDEBAR', 'Боковая панель');
123
+ `;
124
+ return code;
125
+ }