codesift-mcp 0.7.0 → 0.8.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.
Files changed (158) hide show
  1. package/README.md +3 -3
  2. package/dist/cli/git-hooks-installer.d.ts.map +1 -1
  3. package/dist/cli/git-hooks-installer.js +18 -5
  4. package/dist/cli/git-hooks-installer.js.map +1 -1
  5. package/dist/cli/hooks.d.ts.map +1 -1
  6. package/dist/cli/hooks.js +53 -0
  7. package/dist/cli/hooks.js.map +1 -1
  8. package/dist/cli/setup.d.ts +5 -0
  9. package/dist/cli/setup.d.ts.map +1 -1
  10. package/dist/cli/setup.js +31 -5
  11. package/dist/cli/setup.js.map +1 -1
  12. package/dist/config.d.ts +2 -1
  13. package/dist/config.d.ts.map +1 -1
  14. package/dist/config.js +10 -1
  15. package/dist/config.js.map +1 -1
  16. package/dist/instructions.d.ts +1 -1
  17. package/dist/instructions.d.ts.map +1 -1
  18. package/dist/instructions.js +6 -1
  19. package/dist/instructions.js.map +1 -1
  20. package/dist/parser/extractors/hono.d.ts.map +1 -1
  21. package/dist/parser/extractors/hono.js +21 -13
  22. package/dist/parser/extractors/hono.js.map +1 -1
  23. package/dist/parser/extractors/php.d.ts +12 -0
  24. package/dist/parser/extractors/php.d.ts.map +1 -1
  25. package/dist/parser/extractors/php.js +440 -26
  26. package/dist/parser/extractors/php.js.map +1 -1
  27. package/dist/register-tool-loaders.d.ts +16 -0
  28. package/dist/register-tool-loaders.d.ts.map +1 -1
  29. package/dist/register-tool-loaders.js +26 -0
  30. package/dist/register-tool-loaders.js.map +1 -1
  31. package/dist/register-tools.d.ts +3 -1
  32. package/dist/register-tools.d.ts.map +1 -1
  33. package/dist/register-tools.js +354 -7
  34. package/dist/register-tools.js.map +1 -1
  35. package/dist/retrieval/codebase-retrieval.d.ts.map +1 -1
  36. package/dist/retrieval/codebase-retrieval.js +22 -0
  37. package/dist/retrieval/codebase-retrieval.js.map +1 -1
  38. package/dist/retrieval/retrieval-schemas.d.ts +4 -0
  39. package/dist/retrieval/retrieval-schemas.d.ts.map +1 -1
  40. package/dist/retrieval/semantic-handlers.js +1 -1
  41. package/dist/retrieval/semantic-handlers.js.map +1 -1
  42. package/dist/search/semantic.d.ts +21 -5
  43. package/dist/search/semantic.d.ts.map +1 -1
  44. package/dist/search/semantic.js +129 -4
  45. package/dist/search/semantic.js.map +1 -1
  46. package/dist/search/tool-ranker.js +1 -1
  47. package/dist/search/tool-ranker.js.map +1 -1
  48. package/dist/server-helpers.js +1 -1
  49. package/dist/server-helpers.js.map +1 -1
  50. package/dist/storage/index-store.d.ts.map +1 -1
  51. package/dist/storage/index-store.js +7 -5
  52. package/dist/storage/index-store.js.map +1 -1
  53. package/dist/storage/registry.d.ts +28 -4
  54. package/dist/storage/registry.d.ts.map +1 -1
  55. package/dist/storage/registry.js +126 -5
  56. package/dist/storage/registry.js.map +1 -1
  57. package/dist/storage/usage-stats.d.ts +2 -0
  58. package/dist/storage/usage-stats.d.ts.map +1 -1
  59. package/dist/storage/usage-stats.js +6 -0
  60. package/dist/storage/usage-stats.js.map +1 -1
  61. package/dist/tools/_helpers.d.ts.map +1 -1
  62. package/dist/tools/_helpers.js +14 -0
  63. package/dist/tools/_helpers.js.map +1 -1
  64. package/dist/tools/conversation-tools.js +1 -1
  65. package/dist/tools/conversation-tools.js.map +1 -1
  66. package/dist/tools/index-tools.d.ts +12 -0
  67. package/dist/tools/index-tools.d.ts.map +1 -1
  68. package/dist/tools/index-tools.js +52 -5
  69. package/dist/tools/index-tools.js.map +1 -1
  70. package/dist/tools/insights-tools.d.ts +137 -0
  71. package/dist/tools/insights-tools.d.ts.map +1 -0
  72. package/dist/tools/insights-tools.js +438 -0
  73. package/dist/tools/insights-tools.js.map +1 -0
  74. package/dist/tools/pattern-tools.d.ts +7 -0
  75. package/dist/tools/pattern-tools.d.ts.map +1 -1
  76. package/dist/tools/pattern-tools.js +287 -15
  77. package/dist/tools/pattern-tools.js.map +1 -1
  78. package/dist/tools/php-tools.d.ts +78 -4
  79. package/dist/tools/php-tools.d.ts.map +1 -1
  80. package/dist/tools/php-tools.js +824 -42
  81. package/dist/tools/php-tools.js.map +1 -1
  82. package/dist/tools/php8-compat-tools.d.ts +62 -0
  83. package/dist/tools/php8-compat-tools.d.ts.map +1 -0
  84. package/dist/tools/php8-compat-tools.js +287 -0
  85. package/dist/tools/php8-compat-tools.js.map +1 -0
  86. package/dist/tools/php8-migration-candidates-tools.d.ts +68 -0
  87. package/dist/tools/php8-migration-candidates-tools.d.ts.map +1 -0
  88. package/dist/tools/php8-migration-candidates-tools.js +476 -0
  89. package/dist/tools/php8-migration-candidates-tools.js.map +1 -0
  90. package/dist/tools/phpstan-baseline-tools.d.ts +62 -0
  91. package/dist/tools/phpstan-baseline-tools.d.ts.map +1 -0
  92. package/dist/tools/phpstan-baseline-tools.js +263 -0
  93. package/dist/tools/phpstan-baseline-tools.js.map +1 -0
  94. package/dist/tools/project-tools.d.ts +4 -2
  95. package/dist/tools/project-tools.d.ts.map +1 -1
  96. package/dist/tools/project-tools.js +19 -6
  97. package/dist/tools/project-tools.js.map +1 -1
  98. package/dist/tools/react-tools.d.ts +24 -0
  99. package/dist/tools/react-tools.d.ts.map +1 -1
  100. package/dist/tools/react-tools.js +292 -3
  101. package/dist/tools/react-tools.js.map +1 -1
  102. package/dist/tools/search-tools.d.ts.map +1 -1
  103. package/dist/tools/search-tools.js +35 -5
  104. package/dist/tools/search-tools.js.map +1 -1
  105. package/dist/tools/symbol-tools.d.ts.map +1 -1
  106. package/dist/tools/symbol-tools.js +4 -1
  107. package/dist/tools/symbol-tools.js.map +1 -1
  108. package/dist/tools/yii-console-tools.d.ts +69 -0
  109. package/dist/tools/yii-console-tools.d.ts.map +1 -0
  110. package/dist/tools/yii-console-tools.js +256 -0
  111. package/dist/tools/yii-console-tools.js.map +1 -0
  112. package/dist/tools/yii-migrations-tools.d.ts +79 -0
  113. package/dist/tools/yii-migrations-tools.d.ts.map +1 -0
  114. package/dist/tools/yii-migrations-tools.js +543 -0
  115. package/dist/tools/yii-migrations-tools.js.map +1 -0
  116. package/dist/tools/yii-modules-tools.d.ts +63 -0
  117. package/dist/tools/yii-modules-tools.d.ts.map +1 -0
  118. package/dist/tools/yii-modules-tools.js +201 -0
  119. package/dist/tools/yii-modules-tools.js.map +1 -0
  120. package/dist/tools/yii-rbac-tools.d.ts +89 -0
  121. package/dist/tools/yii-rbac-tools.d.ts.map +1 -0
  122. package/dist/tools/yii-rbac-tools.js +238 -0
  123. package/dist/tools/yii-rbac-tools.js.map +1 -0
  124. package/dist/tools/yii3-attribute-candidates-tools.d.ts +72 -0
  125. package/dist/tools/yii3-attribute-candidates-tools.d.ts.map +1 -0
  126. package/dist/tools/yii3-attribute-candidates-tools.js +301 -0
  127. package/dist/tools/yii3-attribute-candidates-tools.js.map +1 -0
  128. package/dist/tools/yii3-migration-tools.d.ts +74 -0
  129. package/dist/tools/yii3-migration-tools.d.ts.map +1 -0
  130. package/dist/tools/yii3-migration-tools.js +440 -0
  131. package/dist/tools/yii3-migration-tools.js.map +1 -0
  132. package/dist/types.d.ts +5 -1
  133. package/dist/types.d.ts.map +1 -1
  134. package/dist/utils/constant-file-pattern.d.ts +3 -1
  135. package/dist/utils/constant-file-pattern.d.ts.map +1 -1
  136. package/dist/utils/constant-file-pattern.js +6 -4
  137. package/dist/utils/constant-file-pattern.js.map +1 -1
  138. package/dist/utils/heritage-edges.d.ts +16 -0
  139. package/dist/utils/heritage-edges.d.ts.map +1 -1
  140. package/dist/utils/heritage-edges.js +31 -10
  141. package/dist/utils/heritage-edges.js.map +1 -1
  142. package/dist/utils/source-stripper.d.ts +23 -0
  143. package/dist/utils/source-stripper.d.ts.map +1 -0
  144. package/dist/utils/source-stripper.js +239 -0
  145. package/dist/utils/source-stripper.js.map +1 -0
  146. package/dist/utils/tsconfig-paths.d.ts +2 -2
  147. package/dist/utils/tsconfig-paths.d.ts.map +1 -1
  148. package/dist/utils/tsconfig-paths.js +10 -4
  149. package/dist/utils/tsconfig-paths.js.map +1 -1
  150. package/dist/utils/wall-clock.d.ts +9 -0
  151. package/dist/utils/wall-clock.d.ts.map +1 -0
  152. package/dist/utils/wall-clock.js +19 -0
  153. package/dist/utils/wall-clock.js.map +1 -0
  154. package/package.json +1 -1
  155. package/rules/codesift.md +10 -3
  156. package/rules/codesift.mdc +10 -3
  157. package/rules/codex.md +10 -3
  158. package/rules/gemini.md +10 -3
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Yii3 attribute conversion candidates (M2).
3
+ *
4
+ * Yii3 is natively PHP 8 attribute-based. The mechanical mapping from
5
+ * Yii2 array-config idioms to Yii3 attributes is well-defined, but
6
+ * applying it across thousands of files is the bottleneck for any
7
+ * Yii2→Yii3 migration. This tool surfaces every site that's a candidate
8
+ * for the conversion + a proposed attribute form, capped by sample limit
9
+ * so the consumer can triage at their own pace.
10
+ *
11
+ * Conversions covered:
12
+ *
13
+ * behaviors-to-attributes
14
+ * behaviors() returning an array with TimestampBehavior /
15
+ * BlameableBehavior / SluggableBehavior / etc → #[Behavior(class)] on
16
+ * the class. We surface the entire behaviors() body in `current_form`
17
+ * so the auditor sees the array-shape that needs conversion.
18
+ *
19
+ * rules-to-attributes
20
+ * rules() returning array of [['field'], 'validator'] tuples →
21
+ * #[Required], #[Email], #[StringLength(min: 1)] on the property.
22
+ * Each tuple becomes one or more proposed attributes.
23
+ *
24
+ * urlmanager-rule-to-route
25
+ * 'GET api/users/<id>' => 'user/view' (in urlManager rules) →
26
+ * #[Route(method: 'GET', path: '/api/users/{id}')] on the controller
27
+ * action. We resolve the controller/action target from the rule's
28
+ * right side. {param} placeholders are emitted but type constraints
29
+ * are dropped (Yii2 supports inline regex like <id:\\d+>; Yii3 uses
30
+ * route attributes like #[Route('/{id<int>}')]).
31
+ *
32
+ * Output shape:
33
+ * - candidates[] — flat list of all conversions
34
+ * - by_rule[] — grouped + sample-capped, sorted by count desc
35
+ * - summary — total + per-rule counts
36
+ *
37
+ * Like M1, this tool never auto-applies. Each candidate ships:
38
+ * current_form (the source as written today)
39
+ * suggested_replacement (the attribute equivalent)
40
+ * confidence ("high" | "medium" | "low")
41
+ * blockers[] (string reasons the conversion may be unsafe —
42
+ * e.g. "rule references a Closure validator that
43
+ * can't be lifted to an attribute")
44
+ */
45
+ export type Yii3AttributeRuleId = "behaviors-to-attributes" | "rules-to-attributes" | "urlmanager-rule-to-route";
46
+ export interface Yii3AttributeCandidate {
47
+ rule_id: Yii3AttributeRuleId;
48
+ file: string;
49
+ line: number;
50
+ current_form: string;
51
+ suggested_replacement: string;
52
+ confidence: "high" | "medium" | "low";
53
+ blockers: string[];
54
+ }
55
+ export interface Yii3AttributeCandidates {
56
+ repo: string;
57
+ scanned_files: number;
58
+ total_candidates: number;
59
+ by_rule: Array<{
60
+ rule_id: Yii3AttributeRuleId;
61
+ count: number;
62
+ samples: Yii3AttributeCandidate[];
63
+ }>;
64
+ candidates: Yii3AttributeCandidate[];
65
+ }
66
+ export declare function findYii3AttributeCandidates(repo: string, options?: {
67
+ file_pattern?: string;
68
+ rules?: Yii3AttributeRuleId[];
69
+ max_samples_per_rule?: number;
70
+ include_vendor?: boolean;
71
+ }): Promise<Yii3AttributeCandidates>;
72
+ //# sourceMappingURL=yii3-attribute-candidates-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yii3-attribute-candidates-tools.d.ts","sourceRoot":"","sources":["../../src/tools/yii3-attribute-candidates-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAUH,MAAM,MAAM,mBAAmB,GAC3B,yBAAyB,GACzB,qBAAqB,GACrB,0BAA0B,CAAC;AAE/B,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,mBAAmB,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACtC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,KAAK,CAAC;QACb,OAAO,EAAE,mBAAmB,CAAC;QAC7B,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,sBAAsB,EAAE,CAAC;KACnC,CAAC,CAAC;IACH,UAAU,EAAE,sBAAsB,EAAE,CAAC;CACtC;AAwBD,wBAAsB,2BAA2B,CAC/C,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;IACR,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAC9B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,GACA,OAAO,CAAC,uBAAuB,CAAC,CAmElC"}
@@ -0,0 +1,301 @@
1
+ /**
2
+ * Yii3 attribute conversion candidates (M2).
3
+ *
4
+ * Yii3 is natively PHP 8 attribute-based. The mechanical mapping from
5
+ * Yii2 array-config idioms to Yii3 attributes is well-defined, but
6
+ * applying it across thousands of files is the bottleneck for any
7
+ * Yii2→Yii3 migration. This tool surfaces every site that's a candidate
8
+ * for the conversion + a proposed attribute form, capped by sample limit
9
+ * so the consumer can triage at their own pace.
10
+ *
11
+ * Conversions covered:
12
+ *
13
+ * behaviors-to-attributes
14
+ * behaviors() returning an array with TimestampBehavior /
15
+ * BlameableBehavior / SluggableBehavior / etc → #[Behavior(class)] on
16
+ * the class. We surface the entire behaviors() body in `current_form`
17
+ * so the auditor sees the array-shape that needs conversion.
18
+ *
19
+ * rules-to-attributes
20
+ * rules() returning array of [['field'], 'validator'] tuples →
21
+ * #[Required], #[Email], #[StringLength(min: 1)] on the property.
22
+ * Each tuple becomes one or more proposed attributes.
23
+ *
24
+ * urlmanager-rule-to-route
25
+ * 'GET api/users/<id>' => 'user/view' (in urlManager rules) →
26
+ * #[Route(method: 'GET', path: '/api/users/{id}')] on the controller
27
+ * action. We resolve the controller/action target from the rule's
28
+ * right side. {param} placeholders are emitted but type constraints
29
+ * are dropped (Yii2 supports inline regex like <id:\\d+>; Yii3 uses
30
+ * route attributes like #[Route('/{id<int>}')]).
31
+ *
32
+ * Output shape:
33
+ * - candidates[] — flat list of all conversions
34
+ * - by_rule[] — grouped + sample-capped, sorted by count desc
35
+ * - summary — total + per-rule counts
36
+ *
37
+ * Like M1, this tool never auto-applies. Each candidate ships:
38
+ * current_form (the source as written today)
39
+ * suggested_replacement (the attribute equivalent)
40
+ * confidence ("high" | "medium" | "low")
41
+ * blockers[] (string reasons the conversion may be unsafe —
42
+ * e.g. "rule references a Closure validator that
43
+ * can't be lifted to an attribute")
44
+ */
45
+ import { readFile } from "node:fs/promises";
46
+ import { join } from "node:path";
47
+ import { getCodeIndex } from "./index-tools.js";
48
+ // ---------------------------------------------------------------------------
49
+ // Implementation
50
+ // ---------------------------------------------------------------------------
51
+ const VENDOR_RE = /(^|\/)(?:vendor|node_modules|runtime|tests\/_data)(\/|$)/;
52
+ const SAMPLE_LIMIT = 5;
53
+ export async function findYii3AttributeCandidates(repo, options) {
54
+ const index = await getCodeIndex(repo);
55
+ if (!index)
56
+ throw new Error(`Repository "${repo}" not found.`);
57
+ const sampleLimit = options?.max_samples_per_rule ?? SAMPLE_LIMIT;
58
+ const includeVendor = options?.include_vendor ?? false;
59
+ const filePattern = options?.file_pattern;
60
+ const ruleFilter = options?.rules ? new Set(options.rules) : null;
61
+ const phpFiles = index.files.filter((f) => {
62
+ if (!f.path.endsWith(".php"))
63
+ return false;
64
+ if (!includeVendor && VENDOR_RE.test(f.path))
65
+ return false;
66
+ if (filePattern && !f.path.includes(filePattern))
67
+ return false;
68
+ return true;
69
+ });
70
+ const candidates = [];
71
+ // Symbol-level rules use the index directly.
72
+ if (!ruleFilter || ruleFilter.has("behaviors-to-attributes")) {
73
+ findBehaviorsToAttributes(index, candidates);
74
+ }
75
+ if (!ruleFilter || ruleFilter.has("rules-to-attributes")) {
76
+ findRulesToAttributes(index, candidates);
77
+ }
78
+ // File-level rule (urlmanager-rule-to-route) reads config files directly.
79
+ if (!ruleFilter || ruleFilter.has("urlmanager-rule-to-route")) {
80
+ await Promise.all(phpFiles
81
+ .filter((f) => /config\/(?:web|main|api|backend|frontend|common)(?:[-_][\w-]+)?\.php$/.test(f.path))
82
+ .map(async (f) => {
83
+ let content;
84
+ try {
85
+ content = await readFile(join(index.root, f.path), "utf-8");
86
+ }
87
+ catch {
88
+ return;
89
+ }
90
+ findUrlManagerRules(content, f.path, candidates);
91
+ }));
92
+ }
93
+ // Group + cap.
94
+ const byRuleMap = new Map();
95
+ for (const c of candidates) {
96
+ if (!byRuleMap.has(c.rule_id))
97
+ byRuleMap.set(c.rule_id, []);
98
+ byRuleMap.get(c.rule_id).push(c);
99
+ }
100
+ const byRule = [...byRuleMap.entries()]
101
+ .map(([rule_id, list]) => ({
102
+ rule_id,
103
+ count: list.length,
104
+ samples: list.slice(0, sampleLimit),
105
+ }))
106
+ .sort((a, b) => b.count - a.count);
107
+ return {
108
+ repo,
109
+ scanned_files: phpFiles.length,
110
+ total_candidates: candidates.length,
111
+ by_rule: byRule,
112
+ candidates,
113
+ };
114
+ }
115
+ // ---------------------------------------------------------------------------
116
+ // Rule: behaviors() → #[Behavior(...)]
117
+ // ---------------------------------------------------------------------------
118
+ function findBehaviorsToAttributes(index, out) {
119
+ const behaviorsMethods = index.symbols.filter((s) => s.kind === "method" &&
120
+ s.name === "behaviors" &&
121
+ s.file.endsWith(".php") &&
122
+ s.source &&
123
+ !VENDOR_RE.test(s.file));
124
+ for (const m of behaviorsMethods) {
125
+ const src = m.source;
126
+ // Pull the body's `return [ ... ];` block. We don't try to walk
127
+ // every key; instead we count the entries that look like behavior
128
+ // class references and surface the whole body for the auditor.
129
+ const returnMatch = /return\s*\[([\s\S]*?)\]\s*;/.exec(src);
130
+ if (!returnMatch)
131
+ continue;
132
+ const body = returnMatch[1];
133
+ // Detect behavior classes — anything ending in "Behavior".
134
+ const behaviorRe = /([A-Z][\w]*Behavior)(?:::class|['"])/g;
135
+ const found = new Set();
136
+ let bm;
137
+ while ((bm = behaviorRe.exec(body)) !== null) {
138
+ found.add(bm[1]);
139
+ }
140
+ if (found.size === 0)
141
+ continue;
142
+ const blockers = [];
143
+ if (/=>\s*function\s*\(/.test(body)) {
144
+ blockers.push("behavior config contains closure — review manually");
145
+ }
146
+ const list = [...found];
147
+ out.push({
148
+ rule_id: "behaviors-to-attributes",
149
+ file: m.file,
150
+ line: m.start_line,
151
+ current_form: `behaviors() with ${list.length} entr${list.length === 1 ? "y" : "ies"}: ${list.join(", ")}`,
152
+ suggested_replacement: list
153
+ .map((b) => `#[Behavior(${b}::class)]`)
154
+ .join(" "),
155
+ confidence: blockers.length > 0 ? "medium" : "high",
156
+ blockers,
157
+ });
158
+ }
159
+ }
160
+ // ---------------------------------------------------------------------------
161
+ // Rule: rules() → #[Required], #[Email], etc.
162
+ // ---------------------------------------------------------------------------
163
+ const VALIDATOR_TO_ATTRIBUTE = {
164
+ required: "Required",
165
+ email: "Email",
166
+ string: "StringLength",
167
+ integer: "IntegerValue",
168
+ number: "NumericValue",
169
+ url: "Url",
170
+ boolean: "BooleanValue",
171
+ date: "Date",
172
+ in: "InRange",
173
+ match: "RegexMatch",
174
+ unique: "Unique",
175
+ exist: "Exist",
176
+ default: "DefaultValue",
177
+ filter: "Callback",
178
+ safe: "Safe",
179
+ };
180
+ function findRulesToAttributes(index, out) {
181
+ const rulesMethods = index.symbols.filter((s) => s.kind === "method" &&
182
+ s.name === "rules" &&
183
+ s.file.endsWith(".php") &&
184
+ s.source &&
185
+ !VENDOR_RE.test(s.file));
186
+ for (const m of rulesMethods) {
187
+ const src = m.source;
188
+ const returnMatch = /return\s*\[([\s\S]*?)\]\s*;/.exec(src);
189
+ if (!returnMatch)
190
+ continue;
191
+ const body = returnMatch[1];
192
+ // Each rule is a tuple [['field' | ['field1', ...]], 'validator', …].
193
+ // We capture the first two positional arguments per tuple.
194
+ const tupleRe = /\[\s*(?:\[([^\]]+)\]|['"]([\w-]+)['"])\s*,\s*['"]([\w-]+)['"]/g;
195
+ const seen = new Map();
196
+ let tm;
197
+ while ((tm = tupleRe.exec(body)) !== null) {
198
+ const fields = (tm[1] ?? tm[2] ?? "")
199
+ .split(",")
200
+ .map((x) => x.trim().replace(/^['"]|['"]$/g, ""))
201
+ .filter(Boolean);
202
+ const validator = tm[3];
203
+ for (const f of fields) {
204
+ if (!seen.has(f))
205
+ seen.set(f, new Set());
206
+ seen.get(f).add(validator);
207
+ }
208
+ }
209
+ if (seen.size === 0)
210
+ continue;
211
+ const blockers = [];
212
+ if (/=>\s*function\s*\(/.test(body)) {
213
+ blockers.push("rule references a closure validator — manual conversion");
214
+ }
215
+ for (const [field, validators] of seen.entries()) {
216
+ const attrs = [];
217
+ for (const v of validators) {
218
+ const mapped = VALIDATOR_TO_ATTRIBUTE[v];
219
+ if (mapped)
220
+ attrs.push(`#[${mapped}]`);
221
+ else
222
+ attrs.push(`#[Validator('${v}')]`);
223
+ }
224
+ out.push({
225
+ rule_id: "rules-to-attributes",
226
+ file: m.file,
227
+ line: m.start_line,
228
+ current_form: `rules() entry for $${field}: ${[...validators].join(", ")}`,
229
+ suggested_replacement: `${attrs.join(" ")} public mixed \$${field};`,
230
+ confidence: validators.size === 1 && VALIDATOR_TO_ATTRIBUTE[[...validators][0]] ? "high" : "medium",
231
+ blockers: [...blockers],
232
+ });
233
+ }
234
+ }
235
+ }
236
+ // ---------------------------------------------------------------------------
237
+ // Rule: urlManager rules → #[Route(...)]
238
+ // ---------------------------------------------------------------------------
239
+ function findUrlManagerRules(content, file, out) {
240
+ // Match `'GET api/users/<id>' => 'user/view'` style entries. Yii2
241
+ // urlManager also accepts unverbed forms ('home' => 'site/index'); we
242
+ // capture both. The right side is `controller/action[/sub]`.
243
+ const ruleRe = /['"](?:(GET|POST|PUT|DELETE|PATCH)\s+)?([^'"]+)['"]\s*=>\s*['"]([\w\/-]+)['"]/g;
244
+ let m;
245
+ while ((m = ruleRe.exec(content)) !== null) {
246
+ const verb = m[1] ?? null;
247
+ const pattern = m[2];
248
+ const target = m[3];
249
+ const line = countLines(content, m.index);
250
+ // Skip non-route contexts: rules() entries, validation messages, etc.
251
+ // Best heuristic: target must contain a "/" (controller/action shape).
252
+ if (!target.includes("/"))
253
+ continue;
254
+ // Reject obvious false positives: 'class' => 'app\\X' (FQCN target).
255
+ if (/\\/.test(target))
256
+ continue;
257
+ // Convert <param> and <param:regex> placeholders to Yii3 {param}.
258
+ // Regex constraints are dropped — Yii3 has its own attribute syntax.
259
+ const path = "/" +
260
+ pattern.replace(/<(\w+)(?::[^>]+)?>/g, "{$1}").replace(/^\//, "");
261
+ const targetSegments = target.split("/");
262
+ const action = targetSegments[targetSegments.length - 1];
263
+ const controller = targetSegments.slice(0, -1).join("/");
264
+ const blockers = [];
265
+ if (/<\w+:/.test(pattern)) {
266
+ blockers.push("rule has inline regex constraint — re-encode with Yii3 typed route");
267
+ }
268
+ if (target.split("/").length > 2) {
269
+ blockers.push("rule targets a module — verify Yii3 module mapping");
270
+ }
271
+ const verbDecl = verb ? `method: '${verb}'` : "";
272
+ const replacement = `#[Route(${[verbDecl, `path: '${path}'`].filter(Boolean).join(", ")})]\npublic function action${pascalize(action)}() { … }`;
273
+ out.push({
274
+ rule_id: "urlmanager-rule-to-route",
275
+ file,
276
+ line,
277
+ current_form: `'${verb ? verb + " " : ""}${pattern}' => '${target}'`,
278
+ suggested_replacement: `// On ${controller}Controller::action${pascalize(action)}:\n${replacement}`,
279
+ confidence: blockers.length === 0 ? "high" : "medium",
280
+ blockers,
281
+ });
282
+ }
283
+ }
284
+ // ---------------------------------------------------------------------------
285
+ // Helpers
286
+ // ---------------------------------------------------------------------------
287
+ function pascalize(s) {
288
+ return s
289
+ .split(/[-_]/)
290
+ .map((p) => (p.length > 0 ? p[0].toUpperCase() + p.slice(1) : ""))
291
+ .join("");
292
+ }
293
+ function countLines(source, idx) {
294
+ let line = 1;
295
+ for (let i = 0; i < idx; i++) {
296
+ if (source.charCodeAt(i) === 10)
297
+ line++;
298
+ }
299
+ return line;
300
+ }
301
+ //# sourceMappingURL=yii3-attribute-candidates-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yii3-attribute-candidates-tools.js","sourceRoot":"","sources":["../../src/tools/yii3-attribute-candidates-tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Yii3 migration audit (M4) — decision-support tool.
3
+ *
4
+ * Inventories Yii2-specific API usage across a codebase and projects an
5
+ * effort estimate so the team can choose between staying on Yii 2.0.49+
6
+ * with PHP 8 vs migrating to Yii3. The tool is grep-style by design: it
7
+ * does not try to understand semantics, only to count call sites by
8
+ * category and surface the highest-leverage blockers.
9
+ *
10
+ * Every category maps a Yii2 idiom to its Yii3 equivalent and assigns a
11
+ * severity + per-call effort estimate. The aggregated effort_estimate
12
+ * gives a rough hours-low/hours-high range. Severity reflects how hard
13
+ * the migration is, NOT how dangerous the current code is.
14
+ *
15
+ * Out of scope:
16
+ * - Vendor / third-party packages (we strip vendor/ paths before scan).
17
+ * - Semantic disambiguation (e.g. `Yii::$app->db` is service-locator
18
+ * even when the property is dynamically resolved at runtime — we
19
+ * don't try to detect that).
20
+ * - Migration plans for non-Yii frameworks (Laravel/Symfony).
21
+ */
22
+ export type Yii3MigrationCategoryName = "service-locator" | "object-factory" | "aliases" | "i18n" | "logger" | "application-props" | "module" | "request" | "response" | "session" | "user-identity" | "active-record" | "validators" | "form-model" | "widgets" | "view" | "url-manager" | "console" | "migrations" | "queue" | "rbac";
23
+ export type Severity = "critical" | "high" | "medium" | "low";
24
+ export type EffortBucket = "trivial" | "small" | "medium" | "large";
25
+ export interface CategoryDefinition {
26
+ category: Yii3MigrationCategoryName;
27
+ severity: Severity;
28
+ description: string;
29
+ yii3_replacement: string;
30
+ effort_per_call: EffortBucket;
31
+ /** One or more regexes; a file is counted once per match. The regex must
32
+ * be globally flagged so we can iterate matches in a single source pass. */
33
+ patterns: RegExp[];
34
+ }
35
+ export interface CategoryFinding {
36
+ category: Yii3MigrationCategoryName;
37
+ severity: Severity;
38
+ count: number;
39
+ effort_per_call: EffortBucket;
40
+ description: string;
41
+ yii3_replacement: string;
42
+ /** First few file:line:snippet triples — capped to keep output tight. */
43
+ sample_files: Array<{
44
+ file: string;
45
+ line: number;
46
+ snippet: string;
47
+ }>;
48
+ }
49
+ export interface Yii3MigrationAudit {
50
+ repo: string;
51
+ scanned_files: number;
52
+ total_call_sites: number;
53
+ by_category: CategoryFinding[];
54
+ by_severity: Record<Severity, number>;
55
+ blockers: Array<{
56
+ category: Yii3MigrationCategoryName;
57
+ reason: string;
58
+ related_files_count: number;
59
+ }>;
60
+ effort_estimate: {
61
+ hours_low: number;
62
+ hours_high: number;
63
+ note: string;
64
+ };
65
+ decision_signal: "stay-on-yii2" | "consider-yii3" | "high-effort-yii3" | "blocked";
66
+ yii_version_detected: string | null;
67
+ php_version_required: string | null;
68
+ }
69
+ export declare function yii3MigrationAudit(repo: string, options?: {
70
+ file_pattern?: string;
71
+ max_samples_per_category?: number;
72
+ include_vendor?: boolean;
73
+ }): Promise<Yii3MigrationAudit>;
74
+ //# sourceMappingURL=yii3-migration-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yii3-migration-tools.d.ts","sourceRoot":"","sources":["../../src/tools/yii3-migration-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAUH,MAAM,MAAM,yBAAyB,GACjC,iBAAiB,GACjB,gBAAgB,GAChB,SAAS,GACT,MAAM,GACN,QAAQ,GACR,mBAAmB,GACnB,QAAQ,GACR,SAAS,GACT,UAAU,GACV,SAAS,GACT,eAAe,GACf,eAAe,GACf,YAAY,GACZ,YAAY,GACZ,SAAS,GACT,MAAM,GACN,aAAa,GACb,SAAS,GACT,YAAY,GACZ,OAAO,GACP,MAAM,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAC9D,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEpE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,yBAAyB,CAAC;IACpC,QAAQ,EAAE,QAAQ,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,YAAY,CAAC;IAC9B;iFAC6E;IAC7E,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,yBAAyB,CAAC;IACpC,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,YAAY,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,yEAAyE;IACzE,YAAY,EAAE,KAAK,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B,WAAW,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACtC,QAAQ,EAAE,KAAK,CAAC;QACd,QAAQ,EAAE,yBAAyB,CAAC;QACpC,MAAM,EAAE,MAAM,CAAC;QACf,mBAAmB,EAAE,MAAM,CAAC;KAC7B,CAAC,CAAC;IACH,eAAe,EAAE;QACf,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,eAAe,EACX,cAAc,GACd,eAAe,GACf,kBAAkB,GAClB,SAAS,CAAC;IACd,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAqSD,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;IACR,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,GACA,OAAO,CAAC,kBAAkB,CAAC,CA2J7B"}