codesift-mcp 0.7.0 → 0.8.4
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 +3 -3
- package/dist/cli/git-hooks-installer.d.ts.map +1 -1
- package/dist/cli/git-hooks-installer.js +18 -5
- package/dist/cli/git-hooks-installer.js.map +1 -1
- package/dist/cli/hooks.d.ts.map +1 -1
- package/dist/cli/hooks.js +106 -2
- package/dist/cli/hooks.js.map +1 -1
- package/dist/cli/setup.d.ts +5 -0
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +31 -5
- package/dist/cli/setup.js.map +1 -1
- package/dist/config.d.ts +2 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +10 -1
- package/dist/config.js.map +1 -1
- package/dist/instructions.d.ts +1 -1
- package/dist/instructions.d.ts.map +1 -1
- package/dist/instructions.js +6 -1
- package/dist/instructions.js.map +1 -1
- package/dist/parser/extractors/hono.d.ts.map +1 -1
- package/dist/parser/extractors/hono.js +21 -13
- package/dist/parser/extractors/hono.js.map +1 -1
- package/dist/parser/extractors/php.d.ts +12 -0
- package/dist/parser/extractors/php.d.ts.map +1 -1
- package/dist/parser/extractors/php.js +440 -26
- package/dist/parser/extractors/php.js.map +1 -1
- package/dist/register-tool-loaders.d.ts +16 -0
- package/dist/register-tool-loaders.d.ts.map +1 -1
- package/dist/register-tool-loaders.js +26 -0
- package/dist/register-tool-loaders.js.map +1 -1
- package/dist/register-tools.d.ts +3 -1
- package/dist/register-tools.d.ts.map +1 -1
- package/dist/register-tools.js +354 -7
- package/dist/register-tools.js.map +1 -1
- package/dist/retrieval/codebase-retrieval.d.ts.map +1 -1
- package/dist/retrieval/codebase-retrieval.js +22 -0
- package/dist/retrieval/codebase-retrieval.js.map +1 -1
- package/dist/retrieval/retrieval-schemas.d.ts +4 -0
- package/dist/retrieval/retrieval-schemas.d.ts.map +1 -1
- package/dist/retrieval/semantic-handlers.js +1 -1
- package/dist/retrieval/semantic-handlers.js.map +1 -1
- package/dist/search/semantic.d.ts +21 -5
- package/dist/search/semantic.d.ts.map +1 -1
- package/dist/search/semantic.js +129 -4
- package/dist/search/semantic.js.map +1 -1
- package/dist/search/tool-ranker.js +1 -1
- package/dist/search/tool-ranker.js.map +1 -1
- package/dist/server-helpers.d.ts.map +1 -1
- package/dist/server-helpers.js +96 -1
- package/dist/server-helpers.js.map +1 -1
- package/dist/storage/index-store.d.ts.map +1 -1
- package/dist/storage/index-store.js +7 -5
- package/dist/storage/index-store.js.map +1 -1
- package/dist/storage/registry.d.ts +28 -4
- package/dist/storage/registry.d.ts.map +1 -1
- package/dist/storage/registry.js +126 -5
- package/dist/storage/registry.js.map +1 -1
- package/dist/storage/usage-stats.d.ts +2 -0
- package/dist/storage/usage-stats.d.ts.map +1 -1
- package/dist/storage/usage-stats.js +6 -0
- package/dist/storage/usage-stats.js.map +1 -1
- package/dist/storage/usage-tracker.js +1 -1
- package/dist/storage/usage-tracker.js.map +1 -1
- package/dist/tools/_helpers.d.ts.map +1 -1
- package/dist/tools/_helpers.js +14 -0
- package/dist/tools/_helpers.js.map +1 -1
- package/dist/tools/conversation-tools.js +1 -1
- package/dist/tools/conversation-tools.js.map +1 -1
- package/dist/tools/index-tools.d.ts +12 -0
- package/dist/tools/index-tools.d.ts.map +1 -1
- package/dist/tools/index-tools.js +52 -5
- package/dist/tools/index-tools.js.map +1 -1
- package/dist/tools/insights-tools.d.ts +137 -0
- package/dist/tools/insights-tools.d.ts.map +1 -0
- package/dist/tools/insights-tools.js +438 -0
- package/dist/tools/insights-tools.js.map +1 -0
- package/dist/tools/pattern-tools.d.ts +7 -0
- package/dist/tools/pattern-tools.d.ts.map +1 -1
- package/dist/tools/pattern-tools.js +287 -15
- package/dist/tools/pattern-tools.js.map +1 -1
- package/dist/tools/php-tools.d.ts +78 -4
- package/dist/tools/php-tools.d.ts.map +1 -1
- package/dist/tools/php-tools.js +824 -42
- package/dist/tools/php-tools.js.map +1 -1
- package/dist/tools/php8-compat-tools.d.ts +62 -0
- package/dist/tools/php8-compat-tools.d.ts.map +1 -0
- package/dist/tools/php8-compat-tools.js +287 -0
- package/dist/tools/php8-compat-tools.js.map +1 -0
- package/dist/tools/php8-migration-candidates-tools.d.ts +68 -0
- package/dist/tools/php8-migration-candidates-tools.d.ts.map +1 -0
- package/dist/tools/php8-migration-candidates-tools.js +476 -0
- package/dist/tools/php8-migration-candidates-tools.js.map +1 -0
- package/dist/tools/phpstan-baseline-tools.d.ts +62 -0
- package/dist/tools/phpstan-baseline-tools.d.ts.map +1 -0
- package/dist/tools/phpstan-baseline-tools.js +263 -0
- package/dist/tools/phpstan-baseline-tools.js.map +1 -0
- package/dist/tools/project-tools.d.ts +4 -2
- package/dist/tools/project-tools.d.ts.map +1 -1
- package/dist/tools/project-tools.js +19 -6
- package/dist/tools/project-tools.js.map +1 -1
- package/dist/tools/react-tools.d.ts +24 -0
- package/dist/tools/react-tools.d.ts.map +1 -1
- package/dist/tools/react-tools.js +292 -3
- package/dist/tools/react-tools.js.map +1 -1
- package/dist/tools/search-tools.d.ts.map +1 -1
- package/dist/tools/search-tools.js +92 -10
- package/dist/tools/search-tools.js.map +1 -1
- package/dist/tools/symbol-tools.d.ts.map +1 -1
- package/dist/tools/symbol-tools.js +4 -1
- package/dist/tools/symbol-tools.js.map +1 -1
- package/dist/tools/yii-console-tools.d.ts +69 -0
- package/dist/tools/yii-console-tools.d.ts.map +1 -0
- package/dist/tools/yii-console-tools.js +256 -0
- package/dist/tools/yii-console-tools.js.map +1 -0
- package/dist/tools/yii-migrations-tools.d.ts +79 -0
- package/dist/tools/yii-migrations-tools.d.ts.map +1 -0
- package/dist/tools/yii-migrations-tools.js +543 -0
- package/dist/tools/yii-migrations-tools.js.map +1 -0
- package/dist/tools/yii-modules-tools.d.ts +63 -0
- package/dist/tools/yii-modules-tools.d.ts.map +1 -0
- package/dist/tools/yii-modules-tools.js +201 -0
- package/dist/tools/yii-modules-tools.js.map +1 -0
- package/dist/tools/yii-rbac-tools.d.ts +89 -0
- package/dist/tools/yii-rbac-tools.d.ts.map +1 -0
- package/dist/tools/yii-rbac-tools.js +238 -0
- package/dist/tools/yii-rbac-tools.js.map +1 -0
- package/dist/tools/yii3-attribute-candidates-tools.d.ts +72 -0
- package/dist/tools/yii3-attribute-candidates-tools.d.ts.map +1 -0
- package/dist/tools/yii3-attribute-candidates-tools.js +301 -0
- package/dist/tools/yii3-attribute-candidates-tools.js.map +1 -0
- package/dist/tools/yii3-migration-tools.d.ts +74 -0
- package/dist/tools/yii3-migration-tools.d.ts.map +1 -0
- package/dist/tools/yii3-migration-tools.js +440 -0
- package/dist/tools/yii3-migration-tools.js.map +1 -0
- package/dist/types.d.ts +5 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/constant-file-pattern.d.ts +3 -1
- package/dist/utils/constant-file-pattern.d.ts.map +1 -1
- package/dist/utils/constant-file-pattern.js +6 -4
- package/dist/utils/constant-file-pattern.js.map +1 -1
- package/dist/utils/heritage-edges.d.ts +16 -0
- package/dist/utils/heritage-edges.d.ts.map +1 -1
- package/dist/utils/heritage-edges.js +31 -10
- package/dist/utils/heritage-edges.js.map +1 -1
- package/dist/utils/source-stripper.d.ts +23 -0
- package/dist/utils/source-stripper.d.ts.map +1 -0
- package/dist/utils/source-stripper.js +239 -0
- package/dist/utils/source-stripper.js.map +1 -0
- package/dist/utils/tsconfig-paths.d.ts +2 -2
- package/dist/utils/tsconfig-paths.d.ts.map +1 -1
- package/dist/utils/tsconfig-paths.js +10 -4
- package/dist/utils/tsconfig-paths.js.map +1 -1
- package/dist/utils/wall-clock.d.ts +9 -0
- package/dist/utils/wall-clock.d.ts.map +1 -0
- package/dist/utils/wall-clock.js +19 -0
- package/dist/utils/wall-clock.js.map +1 -0
- package/package.json +1 -1
- package/rules/codesift.md +10 -3
- package/rules/codesift.mdc +10 -3
- package/rules/codex.md +10 -3
- package/rules/gemini.md +10 -3
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Yii2 migrations audit (N2).
|
|
3
|
+
*
|
|
4
|
+
* Yii2 ships its own PHP-DSL migration system — `extends Migration` with
|
|
5
|
+
* `$this->createTable()`, `$this->addColumn()`, `$this->dropTable()`, etc.
|
|
6
|
+
* The generic SQL toolchain (migration_lint, analyze_schema, sql_audit) is
|
|
7
|
+
* auto-loaded for composer.json projects but parses only `.sql` files, so
|
|
8
|
+
* the 379 migrations in tgm-panel are invisible to it.
|
|
9
|
+
*
|
|
10
|
+
* This tool fills that gap. For each migration class we:
|
|
11
|
+
* 1. Map the DSL calls to a structured operation list
|
|
12
|
+
* (create_table, drop_table, add_column, ...).
|
|
13
|
+
* 2. Run audit checks per migration:
|
|
14
|
+
* - missing_safe_down (irreversible)
|
|
15
|
+
* - drop_without_safety (drop in safeUp without index/backup hint)
|
|
16
|
+
* - alter_without_online_ddl (alter on large tables without
|
|
17
|
+
* ALGORITHM=INPLACE, LOCK=NONE for MySQL 8)
|
|
18
|
+
* - fk_without_index (addForeignKey on a column without
|
|
19
|
+
* a corresponding createIndex earlier)
|
|
20
|
+
* 3. Surface a per-table operation index (which migrations touch table X).
|
|
21
|
+
*
|
|
22
|
+
* The DSL parser is deliberately regex-based, not tree-sitter. Migration
|
|
23
|
+
* methods follow a small, stable grammar (a few verbs from yii\\db\\Migration
|
|
24
|
+
* with predictable argument shapes) and the AST coverage we'd buy with a
|
|
25
|
+
* full walker isn't worth the cost. The audit is a discovery tool, not a
|
|
26
|
+
* gate — false positives are acceptable, false negatives are the failure
|
|
27
|
+
* mode we minimize.
|
|
28
|
+
*/
|
|
29
|
+
import { readFile } from "node:fs/promises";
|
|
30
|
+
import { join } from "node:path";
|
|
31
|
+
import { getCodeIndex } from "./index-tools.js";
|
|
32
|
+
const OP_MATCHERS = [
|
|
33
|
+
{
|
|
34
|
+
// $this->createTable('users', [...]) — plain string OR ::tableName() call.
|
|
35
|
+
re: /\$this->createTable\s*\(\s*(?:['"]([^'"]+)['"]|([\w\\]+)::tableName\s*\(\s*\))/g,
|
|
36
|
+
build: (m, line) => ({
|
|
37
|
+
kind: "create_table",
|
|
38
|
+
table: m[1] ?? m[2] ?? null,
|
|
39
|
+
raw: "createTable",
|
|
40
|
+
line,
|
|
41
|
+
}),
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
re: /\$this->dropTable\s*\(\s*(?:['"]([^'"]+)['"]|([\w\\]+)::tableName\s*\(\s*\))/g,
|
|
45
|
+
build: (m, line) => ({
|
|
46
|
+
kind: "drop_table",
|
|
47
|
+
table: m[1] ?? m[2] ?? null,
|
|
48
|
+
raw: "dropTable",
|
|
49
|
+
line,
|
|
50
|
+
}),
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
re: /\$this->renameTable\s*\(\s*['"]([^'"]+)['"]/g,
|
|
54
|
+
build: (m, line) => ({
|
|
55
|
+
kind: "rename_table",
|
|
56
|
+
table: m[1],
|
|
57
|
+
raw: "renameTable",
|
|
58
|
+
line,
|
|
59
|
+
}),
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
re: /\$this->addColumn\s*\(\s*['"]([^'"]+)['"]\s*,\s*['"]([^'"]+)['"]/g,
|
|
63
|
+
build: (m, line) => ({
|
|
64
|
+
kind: "add_column",
|
|
65
|
+
table: m[1],
|
|
66
|
+
column: m[2],
|
|
67
|
+
raw: "addColumn",
|
|
68
|
+
line,
|
|
69
|
+
}),
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
re: /\$this->dropColumn\s*\(\s*['"]([^'"]+)['"]\s*,\s*['"]([^'"]+)['"]/g,
|
|
73
|
+
build: (m, line) => ({
|
|
74
|
+
kind: "drop_column",
|
|
75
|
+
table: m[1],
|
|
76
|
+
column: m[2],
|
|
77
|
+
raw: "dropColumn",
|
|
78
|
+
line,
|
|
79
|
+
}),
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
re: /\$this->alterColumn\s*\(\s*['"]([^'"]+)['"]\s*,\s*['"]([^'"]+)['"]/g,
|
|
83
|
+
build: (m, line) => ({
|
|
84
|
+
kind: "alter_column",
|
|
85
|
+
table: m[1],
|
|
86
|
+
column: m[2],
|
|
87
|
+
raw: "alterColumn",
|
|
88
|
+
line,
|
|
89
|
+
}),
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
re: /\$this->renameColumn\s*\(\s*['"]([^'"]+)['"]\s*,\s*['"]([^'"]+)['"]/g,
|
|
93
|
+
build: (m, line) => ({
|
|
94
|
+
kind: "rename_column",
|
|
95
|
+
table: m[1],
|
|
96
|
+
column: m[2],
|
|
97
|
+
raw: "renameColumn",
|
|
98
|
+
line,
|
|
99
|
+
}),
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
re: /\$this->createIndex\s*\(\s*['"]([^'"]+)['"]\s*,\s*['"]([^'"]+)['"]/g,
|
|
103
|
+
build: (m, line) => ({
|
|
104
|
+
kind: "create_index",
|
|
105
|
+
table: m[2],
|
|
106
|
+
index_name: m[1],
|
|
107
|
+
raw: "createIndex",
|
|
108
|
+
line,
|
|
109
|
+
}),
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
re: /\$this->dropIndex\s*\(\s*['"]([^'"]+)['"]\s*,\s*['"]([^'"]+)['"]/g,
|
|
113
|
+
build: (m, line) => ({
|
|
114
|
+
kind: "drop_index",
|
|
115
|
+
table: m[2],
|
|
116
|
+
index_name: m[1],
|
|
117
|
+
raw: "dropIndex",
|
|
118
|
+
line,
|
|
119
|
+
}),
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
re: /\$this->addPrimaryKey\s*\(\s*['"]([^'"]+)['"]\s*,\s*['"]([^'"]+)['"]/g,
|
|
123
|
+
build: (m, line) => ({
|
|
124
|
+
kind: "add_primary_key",
|
|
125
|
+
table: m[2],
|
|
126
|
+
index_name: m[1],
|
|
127
|
+
raw: "addPrimaryKey",
|
|
128
|
+
line,
|
|
129
|
+
}),
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
re: /\$this->dropPrimaryKey\s*\(\s*['"]([^'"]+)['"]\s*,\s*['"]([^'"]+)['"]/g,
|
|
133
|
+
build: (m, line) => ({
|
|
134
|
+
kind: "drop_primary_key",
|
|
135
|
+
table: m[2],
|
|
136
|
+
index_name: m[1],
|
|
137
|
+
raw: "dropPrimaryKey",
|
|
138
|
+
line,
|
|
139
|
+
}),
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
// addForeignKey('fk_name', 'table', 'column', 'refTable', 'refColumn', ...)
|
|
143
|
+
re: /\$this->addForeignKey\s*\(\s*['"]([^'"]+)['"]\s*,\s*['"]([^'"]+)['"]\s*,\s*['"]([^'"]+)['"]/g,
|
|
144
|
+
build: (m, line) => ({
|
|
145
|
+
kind: "add_foreign_key",
|
|
146
|
+
fk_name: m[1],
|
|
147
|
+
table: m[2],
|
|
148
|
+
column: m[3],
|
|
149
|
+
raw: "addForeignKey",
|
|
150
|
+
line,
|
|
151
|
+
}),
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
re: /\$this->dropForeignKey\s*\(\s*['"]([^'"]+)['"]\s*,\s*['"]([^'"]+)['"]/g,
|
|
155
|
+
build: (m, line) => ({
|
|
156
|
+
kind: "drop_foreign_key",
|
|
157
|
+
fk_name: m[1],
|
|
158
|
+
table: m[2],
|
|
159
|
+
raw: "dropForeignKey",
|
|
160
|
+
line,
|
|
161
|
+
}),
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
re: /\$this->execute\s*\(\s*['"`]/g,
|
|
165
|
+
build: (_m, line) => ({
|
|
166
|
+
kind: "execute_raw_sql",
|
|
167
|
+
table: null,
|
|
168
|
+
raw: "execute",
|
|
169
|
+
line,
|
|
170
|
+
}),
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
re: /\$this->insert\s*\(\s*['"]([^'"]+)['"]/g,
|
|
174
|
+
build: (m, line) => ({
|
|
175
|
+
kind: "insert",
|
|
176
|
+
table: m[1],
|
|
177
|
+
raw: "insert",
|
|
178
|
+
line,
|
|
179
|
+
}),
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
re: /\$this->batchInsert\s*\(\s*['"]([^'"]+)['"]/g,
|
|
183
|
+
build: (m, line) => ({
|
|
184
|
+
kind: "batch_insert",
|
|
185
|
+
table: m[1],
|
|
186
|
+
raw: "batchInsert",
|
|
187
|
+
line,
|
|
188
|
+
}),
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
re: /\$this->update\s*\(\s*['"]([^'"]+)['"]/g,
|
|
192
|
+
build: (m, line) => ({
|
|
193
|
+
kind: "update",
|
|
194
|
+
table: m[1],
|
|
195
|
+
raw: "update",
|
|
196
|
+
line,
|
|
197
|
+
}),
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
re: /\$this->delete\s*\(\s*['"]([^'"]+)['"]/g,
|
|
201
|
+
build: (m, line) => ({
|
|
202
|
+
kind: "delete",
|
|
203
|
+
table: m[1],
|
|
204
|
+
raw: "delete",
|
|
205
|
+
line,
|
|
206
|
+
}),
|
|
207
|
+
},
|
|
208
|
+
];
|
|
209
|
+
// ---------------------------------------------------------------------------
|
|
210
|
+
// Implementation
|
|
211
|
+
// ---------------------------------------------------------------------------
|
|
212
|
+
const MIGRATION_BASE_NAMES = new Set(["Migration"]);
|
|
213
|
+
const MIGRATION_FILENAME_RE = /(?:^|\/)m\d+_\d+_[\w-]+\.php$/;
|
|
214
|
+
function isMigrationHierarchy(cls, index, visited = new Set(), depth = 0) {
|
|
215
|
+
if (depth > 5)
|
|
216
|
+
return false;
|
|
217
|
+
if (visited.has(cls.name))
|
|
218
|
+
return false;
|
|
219
|
+
visited.add(cls.name);
|
|
220
|
+
const exts = cls.extends ?? [];
|
|
221
|
+
for (const baseFqcn of exts) {
|
|
222
|
+
const last = baseFqcn.split(/[\\\\]+/).pop() ?? baseFqcn;
|
|
223
|
+
if (MIGRATION_BASE_NAMES.has(last))
|
|
224
|
+
return true;
|
|
225
|
+
const baseSym = index.symbols.find((s) => s.kind === "class" && s.name === last);
|
|
226
|
+
if (baseSym && isMigrationHierarchy(baseSym, index, visited, depth + 1)) {
|
|
227
|
+
return true;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
if (!cls.extends && cls.source) {
|
|
231
|
+
return /extends\s+(?:\\?yii\\db\\Migration|Migration)\b/.test(cls.source);
|
|
232
|
+
}
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
export async function analyzeYiiMigrations(repo, options) {
|
|
236
|
+
const index = await getCodeIndex(repo);
|
|
237
|
+
if (!index)
|
|
238
|
+
throw new Error(`Repository "${repo}" not found.`);
|
|
239
|
+
const ruleFilter = options?.rules ? new Set(options.rules) : null;
|
|
240
|
+
const filePattern = options?.file_pattern;
|
|
241
|
+
// Find migration class symbols. We require BOTH a Yii2 migration
|
|
242
|
+
// filename pattern AND a Migration ancestor — file name alone is a weak
|
|
243
|
+
// signal (some app code sits in folders named `migrations/`), and class
|
|
244
|
+
// alone misses tgm-panel's `extends Model` data-fix scripts which we
|
|
245
|
+
// intentionally exclude.
|
|
246
|
+
const migrationClasses = index.symbols.filter((s) => {
|
|
247
|
+
if (s.kind !== "class")
|
|
248
|
+
return false;
|
|
249
|
+
if (!s.file.endsWith(".php"))
|
|
250
|
+
return false;
|
|
251
|
+
if (!MIGRATION_FILENAME_RE.test(s.file))
|
|
252
|
+
return false;
|
|
253
|
+
if (filePattern && !s.file.includes(filePattern))
|
|
254
|
+
return false;
|
|
255
|
+
if (!isMigrationHierarchy(s, index))
|
|
256
|
+
return false;
|
|
257
|
+
return true;
|
|
258
|
+
});
|
|
259
|
+
const migrations = [];
|
|
260
|
+
const byTable = new Map();
|
|
261
|
+
for (const cls of migrationClasses) {
|
|
262
|
+
let content;
|
|
263
|
+
try {
|
|
264
|
+
content = await readFile(join(index.root, cls.file), "utf-8");
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
// Locate up/down method bodies. We approximate by finding the method
|
|
270
|
+
// header and grabbing the bytes between the next `{` and a balanced `}`.
|
|
271
|
+
// Yii2 method names: bare `up`/`down` (all lowercase) OR `safeUp`/`safeDown`
|
|
272
|
+
// (camelCase). Regex must accept both cases — the first version used
|
|
273
|
+
// `(?:safe)?Up` which only matched the camelCase form.
|
|
274
|
+
const upInfo = findMethodBody(content, /(?:safeUp|up)/);
|
|
275
|
+
const downInfo = findMethodBody(content, /(?:safeDown|down)/);
|
|
276
|
+
const isSafeTransactional = /\bfunction\s+safe(?:Up|Down)\s*\(/.test(content);
|
|
277
|
+
const upOps = upInfo ? extractOps(upInfo.body, upInfo.lineOffset) : [];
|
|
278
|
+
const downOps = downInfo ? extractOps(downInfo.body, downInfo.lineOffset) : [];
|
|
279
|
+
const tables = new Set();
|
|
280
|
+
for (const op of [...upOps, ...downOps]) {
|
|
281
|
+
if (op.table)
|
|
282
|
+
tables.add(op.table);
|
|
283
|
+
}
|
|
284
|
+
for (const t of tables) {
|
|
285
|
+
if (!byTable.has(t))
|
|
286
|
+
byTable.set(t, new Set());
|
|
287
|
+
byTable.get(t).add(cls.file);
|
|
288
|
+
}
|
|
289
|
+
const findings = auditMigration({
|
|
290
|
+
file: cls.file,
|
|
291
|
+
content,
|
|
292
|
+
upOps,
|
|
293
|
+
downOps,
|
|
294
|
+
hasSafeDown: !!downInfo,
|
|
295
|
+
ruleFilter,
|
|
296
|
+
});
|
|
297
|
+
migrations.push({
|
|
298
|
+
file: cls.file,
|
|
299
|
+
class_name: cls.name,
|
|
300
|
+
up_ops: upOps,
|
|
301
|
+
down_ops: downOps,
|
|
302
|
+
is_safe_transactional: isSafeTransactional,
|
|
303
|
+
tables: [...tables].sort(),
|
|
304
|
+
findings,
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
// Stable order: chronological by filename (timestamps sort lex-correctly
|
|
308
|
+
// in Yii2 since `m\d{6}_\d{6}_` always pads zeros).
|
|
309
|
+
migrations.sort((a, b) => a.file.localeCompare(b.file));
|
|
310
|
+
// Aggregate counts.
|
|
311
|
+
const findingsSummary = {};
|
|
312
|
+
for (const m of migrations) {
|
|
313
|
+
for (const f of m.findings) {
|
|
314
|
+
findingsSummary[f.rule_id] = (findingsSummary[f.rule_id] ?? 0) + 1;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
const byTableObj = {};
|
|
318
|
+
for (const [t, files] of byTable.entries()) {
|
|
319
|
+
byTableObj[t] = [...files].sort();
|
|
320
|
+
}
|
|
321
|
+
return {
|
|
322
|
+
repo,
|
|
323
|
+
scanned_files: migrationClasses.length,
|
|
324
|
+
total_migrations: migrations.length,
|
|
325
|
+
migrations,
|
|
326
|
+
by_table: byTableObj,
|
|
327
|
+
findings_summary: findingsSummary,
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
// ---------------------------------------------------------------------------
|
|
331
|
+
// Helpers
|
|
332
|
+
// ---------------------------------------------------------------------------
|
|
333
|
+
/**
|
|
334
|
+
* Find a method body within a class source by name pattern. Returns the
|
|
335
|
+
* body text (between the `{` after the method header and its matching
|
|
336
|
+
* `}`) plus the 1-based line of the body's opening brace, so per-op line
|
|
337
|
+
* numbers can be computed against the original file.
|
|
338
|
+
*
|
|
339
|
+
* Brace balancing uses a simple counter that ignores braces inside
|
|
340
|
+
* single/double-quoted strings, comments, and heredocs (the last is a
|
|
341
|
+
* best-effort skip — heredocs are rare in migrations).
|
|
342
|
+
*/
|
|
343
|
+
function findMethodBody(source, nameRe) {
|
|
344
|
+
// Build a bounded regex for "function NAME(...)"
|
|
345
|
+
const headerRe = new RegExp(`\\bfunction\\s+(${nameRe.source})\\s*\\(`, "g");
|
|
346
|
+
const headerMatch = headerRe.exec(source);
|
|
347
|
+
if (!headerMatch)
|
|
348
|
+
return null;
|
|
349
|
+
// Walk to the next `{` after the header.
|
|
350
|
+
const braceStart = source.indexOf("{", headerRe.lastIndex);
|
|
351
|
+
if (braceStart === -1)
|
|
352
|
+
return null;
|
|
353
|
+
// Balanced match.
|
|
354
|
+
let depth = 1;
|
|
355
|
+
let i = braceStart + 1;
|
|
356
|
+
while (i < source.length && depth > 0) {
|
|
357
|
+
const c = source[i];
|
|
358
|
+
if (c === "/" && source[i + 1] === "/") {
|
|
359
|
+
const nl = source.indexOf("\n", i);
|
|
360
|
+
i = nl === -1 ? source.length : nl + 1;
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
if (c === "/" && source[i + 1] === "*") {
|
|
364
|
+
const end = source.indexOf("*/", i + 2);
|
|
365
|
+
i = end === -1 ? source.length : end + 2;
|
|
366
|
+
continue;
|
|
367
|
+
}
|
|
368
|
+
if (c === '"' || c === "'") {
|
|
369
|
+
const quote = c;
|
|
370
|
+
i++;
|
|
371
|
+
while (i < source.length) {
|
|
372
|
+
if (source[i] === "\\") {
|
|
373
|
+
i += 2;
|
|
374
|
+
continue;
|
|
375
|
+
}
|
|
376
|
+
if (source[i] === quote) {
|
|
377
|
+
i++;
|
|
378
|
+
break;
|
|
379
|
+
}
|
|
380
|
+
i++;
|
|
381
|
+
}
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
if (c === "{")
|
|
385
|
+
depth++;
|
|
386
|
+
else if (c === "}")
|
|
387
|
+
depth--;
|
|
388
|
+
i++;
|
|
389
|
+
}
|
|
390
|
+
const body = source.slice(braceStart + 1, i - 1);
|
|
391
|
+
// 1-based line of the body's opening brace
|
|
392
|
+
const lineOffset = source.slice(0, braceStart).split("\n").length;
|
|
393
|
+
return { body, lineOffset };
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Strip PHP comments (// line, # line, /* … *\/ block) from a source string,
|
|
397
|
+
* preserving line breaks so byte-for-byte line numbers stay aligned with the
|
|
398
|
+
* original. Used by alter-without-online-ddl detection so that developer
|
|
399
|
+
* notes mentioning the hint don't silence the finding.
|
|
400
|
+
*
|
|
401
|
+
* Doesn't try to handle string literals — comments inside strings are rare
|
|
402
|
+
* in migrations and the false-negative impact is minimal.
|
|
403
|
+
*/
|
|
404
|
+
function stripPhpComments(source) {
|
|
405
|
+
let out = "";
|
|
406
|
+
let i = 0;
|
|
407
|
+
while (i < source.length) {
|
|
408
|
+
const c = source[i];
|
|
409
|
+
if (c === "/" && source[i + 1] === "/") {
|
|
410
|
+
const nl = source.indexOf("\n", i);
|
|
411
|
+
if (nl === -1) {
|
|
412
|
+
i = source.length;
|
|
413
|
+
}
|
|
414
|
+
else {
|
|
415
|
+
i = nl;
|
|
416
|
+
}
|
|
417
|
+
continue;
|
|
418
|
+
}
|
|
419
|
+
if (c === "/" && source[i + 1] === "*") {
|
|
420
|
+
const end = source.indexOf("*/", i + 2);
|
|
421
|
+
if (end === -1) {
|
|
422
|
+
i = source.length;
|
|
423
|
+
}
|
|
424
|
+
else {
|
|
425
|
+
// Preserve newlines inside the block so subsequent line numbers
|
|
426
|
+
// stay correct against the original source.
|
|
427
|
+
const block = source.slice(i, end + 2);
|
|
428
|
+
for (const ch of block)
|
|
429
|
+
if (ch === "\n")
|
|
430
|
+
out += "\n";
|
|
431
|
+
i = end + 2;
|
|
432
|
+
}
|
|
433
|
+
continue;
|
|
434
|
+
}
|
|
435
|
+
if (c === "#") {
|
|
436
|
+
const nl = source.indexOf("\n", i);
|
|
437
|
+
if (nl === -1) {
|
|
438
|
+
i = source.length;
|
|
439
|
+
}
|
|
440
|
+
else {
|
|
441
|
+
i = nl;
|
|
442
|
+
}
|
|
443
|
+
continue;
|
|
444
|
+
}
|
|
445
|
+
out += c;
|
|
446
|
+
i++;
|
|
447
|
+
}
|
|
448
|
+
return out;
|
|
449
|
+
}
|
|
450
|
+
function extractOps(body, baseLine) {
|
|
451
|
+
const ops = [];
|
|
452
|
+
for (const matcher of OP_MATCHERS) {
|
|
453
|
+
matcher.re.lastIndex = 0;
|
|
454
|
+
let m;
|
|
455
|
+
while ((m = matcher.re.exec(body)) !== null) {
|
|
456
|
+
const lineInBody = body.slice(0, m.index).split("\n").length - 1;
|
|
457
|
+
ops.push(matcher.build(m, baseLine + lineInBody));
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
// Sort by line so callers see operations in source order.
|
|
461
|
+
ops.sort((a, b) => a.line - b.line);
|
|
462
|
+
return ops;
|
|
463
|
+
}
|
|
464
|
+
function auditMigration(ctx) {
|
|
465
|
+
const out = [];
|
|
466
|
+
const include = (id) => !ctx.ruleFilter || ctx.ruleFilter.has(id);
|
|
467
|
+
// missing-safe-down: any up-side op exists but down is empty
|
|
468
|
+
if (include("missing-safe-down") && ctx.upOps.length > 0 && ctx.downOps.length === 0) {
|
|
469
|
+
out.push({
|
|
470
|
+
rule_id: "missing-safe-down",
|
|
471
|
+
severity: "medium",
|
|
472
|
+
description: "Migration has up()/safeUp() operations but no down()/safeDown() — irreversible deploys",
|
|
473
|
+
fix: "Implement safeDown() that reverses the up operations (or throw a clear exception explicitly).",
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
// alter-without-online-ddl: alter/drop column on tables without an
|
|
477
|
+
// accompanying ALGORITHM=INPLACE/LOCK=NONE hint anywhere in the migration.
|
|
478
|
+
// We require the user to have written a raw `execute()` with the hint OR
|
|
479
|
+
// a comment containing "ALGORITHM=INPLACE" — anything else flags. This
|
|
480
|
+
// is the highest-volume tgm-panel db-audit finding (DB6-001).
|
|
481
|
+
if (include("alter-without-online-ddl")) {
|
|
482
|
+
const destructive = [...ctx.upOps, ...ctx.downOps].filter((o) => o.kind === "alter_column" || o.kind === "drop_column" || o.kind === "drop_table");
|
|
483
|
+
if (destructive.length > 0) {
|
|
484
|
+
// Look for the hint only in code, not comments. A developer note like
|
|
485
|
+
// "TODO: add ALGORITHM=INPLACE" should NOT silence this finding —
|
|
486
|
+
// the hint must actually be in the migration's executed SQL.
|
|
487
|
+
const codeOnly = stripPhpComments(ctx.content);
|
|
488
|
+
const hasOnlineDdl = /ALGORITHM\s*=\s*INPLACE/i.test(codeOnly) ||
|
|
489
|
+
/LOCK\s*=\s*NONE/i.test(codeOnly) ||
|
|
490
|
+
/pt-online-schema-change|gh-ost/i.test(codeOnly);
|
|
491
|
+
if (!hasOnlineDdl) {
|
|
492
|
+
out.push({
|
|
493
|
+
rule_id: "alter-without-online-ddl",
|
|
494
|
+
severity: "high",
|
|
495
|
+
description: `Destructive operations (${destructive.map((d) => d.kind).join(", ")}) without explicit ALGORITHM=INPLACE/LOCK=NONE hint — risk of multi-minute lock on large tables under MySQL 8`,
|
|
496
|
+
fix: "Either invoke the destructive ops via raw SQL with ALGORITHM=INPLACE, LOCK=NONE, or document a pt-online-schema-change / gh-ost runbook for large tables.",
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
// fk-without-index: addForeignKey on (table, column) where no createIndex
|
|
502
|
+
// on the same (table, column) appears earlier in this migration (or
|
|
503
|
+
// already exists in a previous one — out of scope for a single-file scan).
|
|
504
|
+
if (include("fk-without-index")) {
|
|
505
|
+
const fks = ctx.upOps.filter((o) => o.kind === "add_foreign_key");
|
|
506
|
+
for (const fk of fks) {
|
|
507
|
+
if (!fk.table || !fk.column)
|
|
508
|
+
continue;
|
|
509
|
+
const idxBefore = ctx.upOps.find((o) => o.kind === "create_index" &&
|
|
510
|
+
o.table === fk.table &&
|
|
511
|
+
o.line < fk.line);
|
|
512
|
+
if (!idxBefore) {
|
|
513
|
+
out.push({
|
|
514
|
+
rule_id: "fk-without-index",
|
|
515
|
+
severity: "medium",
|
|
516
|
+
description: `addForeignKey on ${fk.table}.${fk.column} without createIndex on the same column earlier in this migration — slow FK lookups under load`,
|
|
517
|
+
fix: `Add $this->createIndex('idx_${fk.table}_${fk.column}', '${fk.table}', '${fk.column}') before the addForeignKey call.`,
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
// raw-sql-without-comment: raw $this->execute() without any preceding
|
|
523
|
+
// // comment — these need explanation for reviewers. Bounded to first
|
|
524
|
+
// execute() per migration to avoid noise.
|
|
525
|
+
if (include("raw-sql-without-comment")) {
|
|
526
|
+
const execOp = ctx.upOps.find((o) => o.kind === "execute_raw_sql");
|
|
527
|
+
if (execOp) {
|
|
528
|
+
// Heuristic: the line BEFORE the execute() call should be a comment.
|
|
529
|
+
const lines = ctx.content.split("\n");
|
|
530
|
+
const before = lines[execOp.line - 2] ?? "";
|
|
531
|
+
if (!/^\s*(\/\/|#|\/\*)/.test(before)) {
|
|
532
|
+
out.push({
|
|
533
|
+
rule_id: "raw-sql-without-comment",
|
|
534
|
+
severity: "low",
|
|
535
|
+
description: "Raw $this->execute() SQL with no preceding comment — review effort goes up sharply when raw SQL appears unexplained",
|
|
536
|
+
fix: "Add a // comment above the execute() line explaining why the DSL wasn't sufficient.",
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
return out;
|
|
542
|
+
}
|
|
543
|
+
//# sourceMappingURL=yii-migrations-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yii-migrations-tools.js","sourceRoot":"","sources":["../../src/tools/yii-migrations-tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Yii2 module inventory (N1).
|
|
3
|
+
*
|
|
4
|
+
* Scans a Yii2 codebase for classes extending `yii\\base\\Module` and emits
|
|
5
|
+
* a structured per-module summary: controller namespace, controllers, views,
|
|
6
|
+
* migrations path, components, sub-modules. Also resolves URL prefixes by
|
|
7
|
+
* cross-referencing config/web.php urlManager rules + the application's
|
|
8
|
+
* `modules` registration.
|
|
9
|
+
*
|
|
10
|
+
* Why this is its own tool (vs. squeezing into php_project_audit):
|
|
11
|
+
* - Modules are the primary architectural unit of medium/large Yii2 apps
|
|
12
|
+
* (tgm-panel: 11 modules; Mobi 2: similar). Routing, RBAC, and god-model
|
|
13
|
+
* analysis all benefit from being able to scope to a module.
|
|
14
|
+
* - The output is a graph of cross-file references (controllers ↔ views ↔
|
|
15
|
+
* migrations ↔ config), not a flat findings list.
|
|
16
|
+
*
|
|
17
|
+
* Implementation depends on the v2.0.0 PHP extractor — uses `s.extends`
|
|
18
|
+
* (introduced in Sprint 1) to detect Module subclasses structurally.
|
|
19
|
+
* Falls back to a regex check on `s.source` when `extends` is absent so
|
|
20
|
+
* stale indexes don't go silent.
|
|
21
|
+
*/
|
|
22
|
+
import { relative } from "node:path";
|
|
23
|
+
export interface YiiControllerRef {
|
|
24
|
+
class: string;
|
|
25
|
+
file: string;
|
|
26
|
+
/** Action methods discovered as children — names retain the `action` prefix
|
|
27
|
+
* so callers can map them back to URL action ids without ambiguity. */
|
|
28
|
+
actions: string[];
|
|
29
|
+
}
|
|
30
|
+
export interface YiiModuleSummary {
|
|
31
|
+
/** Module id derived from the directory name containing Module.php. */
|
|
32
|
+
id: string;
|
|
33
|
+
/** Fully-qualified class name (e.g. app\\modules\\review\\Module). */
|
|
34
|
+
class: string;
|
|
35
|
+
/** Path to the Module.php file. */
|
|
36
|
+
file: string;
|
|
37
|
+
/** Value of `controllerNamespace` property if declared, else null. */
|
|
38
|
+
controllerNamespace: string | null;
|
|
39
|
+
/** Path containing the module's controllers, derived from the Module.php
|
|
40
|
+
* location. */
|
|
41
|
+
controllers_path: string;
|
|
42
|
+
controllers: YiiControllerRef[];
|
|
43
|
+
/** Per-module views directory. */
|
|
44
|
+
views_path: string;
|
|
45
|
+
views_count: number;
|
|
46
|
+
/** Module's own migrations directory if present (e.g. modules/<id>/migrations/). */
|
|
47
|
+
migrations_path: string | null;
|
|
48
|
+
migrations_count: number;
|
|
49
|
+
/** Sub-module ids (modules nested under this module's modules() method). */
|
|
50
|
+
submodules: string[];
|
|
51
|
+
/** URL prefixes from main app config that route into this module. */
|
|
52
|
+
url_prefixes: string[];
|
|
53
|
+
}
|
|
54
|
+
export interface YiiModulesAudit {
|
|
55
|
+
repo: string;
|
|
56
|
+
total_modules: number;
|
|
57
|
+
modules: YiiModuleSummary[];
|
|
58
|
+
}
|
|
59
|
+
export declare function analyzeYiiModules(repo: string, options?: {
|
|
60
|
+
module_id?: string;
|
|
61
|
+
}): Promise<YiiModulesAudit>;
|
|
62
|
+
export { relative as _relativePathForTests };
|
|
63
|
+
//# sourceMappingURL=yii-modules-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yii-modules-tools.d.ts","sourceRoot":"","sources":["../../src/tools/yii-modules-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,EAAiB,QAAQ,EAAE,MAAM,WAAW,CAAC;AAOpD,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb;4EACwE;IACxE,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,uEAAuE;IACvE,EAAE,EAAE,MAAM,CAAC;IACX,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAC;IACd,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC;oBACgB;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,kCAAkC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,oFAAoF;IACpF,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,4EAA4E;IAC5E,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,qEAAqE;IACrE,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,gBAAgB,EAAE,CAAC;CAC7B;AAyCD,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/B,OAAO,CAAC,eAAe,CAAC,CAuG1B;AA0ED,OAAO,EAAE,QAAQ,IAAI,qBAAqB,EAAE,CAAC"}
|