@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,189 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.scaffoldGrid = scaffoldGrid;
4
+ function scaffoldGrid(opts) {
5
+ const name = opts.addon_name.toLowerCase().replace(/[^a-z0-9_]/g, '_');
6
+ const gridName = opts.grid_name || 'items';
7
+ const GridName = gridName.split('_').map(capitalize).join('');
8
+ const files = {};
9
+ const ctrl = `package/system/controllers/${name}`;
10
+ const gridFile = `${ctrl}/backend/grids/grid_${gridName}.php`;
11
+ files[gridFile] = generateGrid(name, gridName, opts.columns, opts.options, opts.actions);
12
+ files[`${ctrl}/manifest.xml`] = generateManifest(name, GridName);
13
+ return {
14
+ addon_name: name,
15
+ grid_name: gridName,
16
+ function_name: `grid_${gridName}`,
17
+ file_path: gridFile,
18
+ files,
19
+ columns_count: opts.columns.length,
20
+ options: opts.options || {},
21
+ structure_notes: [
22
+ `Грид: ${gridFile}`,
23
+ `Функция: grid_${gridName}($controller)`,
24
+ `Используйте в listgrid trait: $this->grid_name = '${gridName}'`,
25
+ ],
26
+ };
27
+ }
28
+ function capitalize(str) {
29
+ return str.charAt(0).toUpperCase() + str.slice(1);
30
+ }
31
+ function generateGrid(name, gridName, columns, options, actions) {
32
+ const opts = options || {};
33
+ const isDraggable = opts.is_draggable ?? false;
34
+ const isSortable = opts.is_sortable ?? true;
35
+ const isFilter = opts.is_filter ?? true;
36
+ const isPagination = opts.is_pagination ?? true;
37
+ const isSelectable = opts.is_selectable ?? false;
38
+ const orderBy = opts.order_by || 'id';
39
+ const orderTo = opts.order_to || 'desc';
40
+ const showId = opts.show_id ?? true;
41
+ let gridOptions = `[
42
+ 'is_sortable' => ${isSortable},
43
+ 'is_filter' => ${isFilter},
44
+ 'is_pagination' => ${isPagination},
45
+ 'is_draggable' => ${isDraggable},
46
+ 'is_selectable' => ${isSelectable},
47
+ 'order_by' => '${orderBy}',
48
+ 'order_to' => '${orderTo}',
49
+ `;
50
+ if (opts.filter_button_title) {
51
+ gridOptions += `,
52
+ 'filter_button_title' => '${opts.filter_button_title}'`;
53
+ }
54
+ gridOptions += `
55
+ ]`;
56
+ const columnsCode = generateColumns(columns, name, showId);
57
+ const actionsCode = generateActions(actions || getDefaultActions(name));
58
+ return `<?php
59
+
60
+ // ВАЖНО: грид — это ФУНКЦИЯ, а не класс!
61
+ // Имя функции = grid_ + значение $this->grid_name из экшена
62
+
63
+ function grid_${gridName}($controller) {
64
+
65
+ ${opts.is_collapsible
66
+ ? `$columns_state = $controller->cms_user->getAttribute('grid_columns_state', [], 'grid_${name}');
67
+
68
+ $is_collapsed = !empty($columns_state['collapsed']);`
69
+ : ''}
70
+
71
+ ${columnsCode}
72
+
73
+ ${actionsCode}
74
+
75
+ return [
76
+ 'options' => ${gridOptions},
77
+ 'columns' => $columns,
78
+ 'actions' => $actions,
79
+ ];
80
+ }
81
+ `;
82
+ }
83
+ function generateColumns(columns, name, showId) {
84
+ let code = ` $columns = [
85
+ `;
86
+ for (const column of columns) {
87
+ if (column.name === 'id' && !showId) {
88
+ continue;
89
+ }
90
+ code += ` '${column.name}' => [
91
+ `;
92
+ code += ` 'title' => LANG_${name.toUpperCase()}_${column.name.toUpperCase().replace(/_/g, '_')},
93
+ `;
94
+ if (column.width) {
95
+ code += ` 'width' => ${column.width},
96
+ `;
97
+ }
98
+ if (column.show !== undefined) {
99
+ code += ` 'show' => ${column.show},
100
+ `;
101
+ }
102
+ if (column.filter) {
103
+ code += ` 'filter' => '${column.filter}',
104
+ `;
105
+ }
106
+ if (column.href) {
107
+ code += ` 'href' => '${column.href}',
108
+ `;
109
+ }
110
+ if (column.flag) {
111
+ code += ` 'flag' => true,
112
+ `;
113
+ }
114
+ if (column.flag_toggle) {
115
+ code += ` 'flag_toggle' => '${column.flag_toggle}',
116
+ `;
117
+ }
118
+ if (column.handler) {
119
+ code += ` 'handler' => function ($value) {
120
+ return ${column.handler};
121
+ },
122
+ `;
123
+ }
124
+ if (column.order_by !== undefined) {
125
+ code += ` 'order_by' => ${column.order_by},
126
+ `;
127
+ }
128
+ code += ` ],
129
+ `;
130
+ }
131
+ code += ` ];
132
+ `;
133
+ return code;
134
+ }
135
+ function generateActions(actions) {
136
+ let code = ` $actions = [
137
+ `;
138
+ for (const action of actions) {
139
+ code += ` [
140
+ 'title' => LANG_${action.title.toUpperCase().replace(/[^A-Z]/g, '_')},
141
+ `;
142
+ if (action.icon) {
143
+ code += ` 'icon' => '${action.icon}',
144
+ `;
145
+ }
146
+ if (action.class) {
147
+ code += ` 'class' => '${action.class}',
148
+ `;
149
+ }
150
+ if (action.confirm) {
151
+ code += ` 'confirm' => LANG_${action.confirm.toUpperCase().replace(/[^A-Z]/g, '_')},
152
+ `;
153
+ }
154
+ code += ` 'href' => '${action.href}',
155
+ `;
156
+ code += ` ],
157
+ `;
158
+ }
159
+ code += ` ];
160
+ `;
161
+ return code;
162
+ }
163
+ function getDefaultActions(_name) {
164
+ return [
165
+ {
166
+ title: 'EDIT',
167
+ href: `href_to($controller->root_url, 'items', ['edit', '{id}'])`,
168
+ icon: 'pen',
169
+ },
170
+ {
171
+ title: 'DELETE',
172
+ href: `href_to($controller->root_url, 'items', ['delete', '{id}'])`,
173
+ icon: 'times-circle',
174
+ class: 'text-danger',
175
+ confirm: 'DELETE_CONFIRM',
176
+ },
177
+ ];
178
+ }
179
+ function generateManifest(name, GridName) {
180
+ return `<?xml version="1.0" encoding="utf-8"?>
181
+ <addon>
182
+ <name>${name}</name>
183
+ <title>${GridName}</title>
184
+ <version>1.0.0</version>
185
+ <files>
186
+ <file>backend/grids/grid_${GridName.toLowerCase()}.php</file>
187
+ </files>
188
+ </addon>`;
189
+ }
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listHooks = listHooks;
4
+ exports.getHookDetails = getHookDetails;
5
+ exports.searchHooks = searchHooks;
6
+ const hooks_js_1 = require("../data/hooks.js");
7
+ const pagination_js_1 = require("../utils/pagination.js");
8
+ function listHooks(category, type, pageOptions = {}) {
9
+ let filtered = hooks_js_1.hooks;
10
+ if (category) {
11
+ filtered = filtered.filter(h => h.category === category);
12
+ }
13
+ if (type) {
14
+ filtered = filtered.filter(h => h.type === type || h.type.includes(type));
15
+ }
16
+ const page = (0, pagination_js_1.paginate)(filtered, pageOptions);
17
+ return {
18
+ total: filtered.length,
19
+ categories: hooks_js_1.hookCategories,
20
+ page: page.page,
21
+ hooks: page.items.map(h => ({
22
+ name: h.name,
23
+ type: h.type,
24
+ category: h.category,
25
+ description: h.description,
26
+ parameters_count: h.parameters.length,
27
+ return_type: h.return_type,
28
+ source: h.source,
29
+ })),
30
+ };
31
+ }
32
+ function getHookDetails(hookName) {
33
+ const lower = hookName.toLowerCase();
34
+ const exact = hooks_js_1.hooks.filter(h => h.name.toLowerCase() === lower);
35
+ const partial = hooks_js_1.hooks.filter(h => h.name.toLowerCase().includes(lower));
36
+ const matches = exact.length > 0 ? exact : partial;
37
+ if (matches.length === 0) {
38
+ // Поиск похожих
39
+ const lower = hookName.toLowerCase();
40
+ const similar = hooks_js_1.hooks
41
+ .filter(h => h.name.includes(lower.split('_')[0]) || h.category === lower)
42
+ .slice(0, 5)
43
+ .map(h => h.name);
44
+ return {
45
+ code: 'HOOK_NOT_FOUND',
46
+ error: `Хук "${hookName}" не найден`,
47
+ similar_hooks: similar,
48
+ tip: 'Используйте list_hooks для просмотра всех доступных хуков',
49
+ };
50
+ }
51
+ if (matches.length > 1) {
52
+ return {
53
+ code: 'AMBIGUOUS_HOOK',
54
+ error: `Запрос "${hookName}" соответствует нескольким хукам`,
55
+ candidates: matches.slice(0, 20).map(h => h.name),
56
+ };
57
+ }
58
+ const [hook] = matches;
59
+ const className = buildClassName(hook);
60
+ return {
61
+ name: hook.name,
62
+ type: hook.type,
63
+ category: hook.category,
64
+ description: hook.description,
65
+ parameters: hook.parameters,
66
+ return_type: hook.return_type,
67
+ since: hook.since,
68
+ source: hook.source,
69
+ implementation: {
70
+ file_path: `hooks/${hook.name}.php`,
71
+ class_name: className,
72
+ usage_note: hook.type === 'filter'
73
+ ? 'ОБЯЗАТЕЛЬНО вернуть модифицированные данные через return'
74
+ : 'Можно не возвращать данные, но рекомендуется return $data для цепочки',
75
+ },
76
+ example: hook.example,
77
+ manifest_xml: `<hook controller="{your_addon_name}" name="${hook.name}" />`,
78
+ };
79
+ }
80
+ function searchHooks(query) {
81
+ const lower = query.trim().toLowerCase();
82
+ const results = hooks_js_1.hooks.filter(h => h.name.includes(lower) ||
83
+ h.description.toLowerCase().includes(lower) ||
84
+ h.category.includes(lower) ||
85
+ h.parameters.some(p => p.name.toLowerCase().includes(lower) || p.description.toLowerCase().includes(lower)));
86
+ return {
87
+ query,
88
+ total: results.length,
89
+ results: results.map(h => ({
90
+ name: h.name,
91
+ type: h.type,
92
+ category: h.category,
93
+ description: h.description,
94
+ })),
95
+ };
96
+ }
97
+ function buildClassName(hook) {
98
+ // on{AddonName}{HookNameCamelCase}
99
+ const hookCamel = hook.name
100
+ .split('_')
101
+ .map(w => w.charAt(0).toUpperCase() + w.slice(1))
102
+ .join('');
103
+ return `on{AddonName}${hookCamel}`;
104
+ }