@pyreon/cli 0.5.6 → 0.6.0
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/lib/types/index.d.ts +30 -254
- package/lib/types/index.d.ts.map +1 -1
- package/package.json +2 -2
package/lib/types/index.d.ts
CHANGED
|
@@ -1,259 +1,35 @@
|
|
|
1
|
-
|
|
2
|
-
import * as fs from "node:fs";
|
|
3
|
-
import * as path from "node:path";
|
|
4
|
-
import { detectReactPatterns, generateContext as generateContext$1, hasReactPatterns, migrateReactCode } from "@pyreon/compiler";
|
|
1
|
+
import { ProjectContext, ProjectContext as ProjectContext$1 } from "@pyreon/compiler";
|
|
5
2
|
|
|
6
|
-
//#region src/context.ts
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
* Delegates scanning to @pyreon/compiler's unified project scanner,
|
|
11
|
-
* then writes the result to disk and ensures .pyreon/ is gitignored.
|
|
12
|
-
*/
|
|
13
|
-
async function generateContext(options) {
|
|
14
|
-
const context = generateContext$1(options.cwd);
|
|
15
|
-
const outDir = options.outPath ? path.dirname(options.outPath) : path.join(options.cwd, ".pyreon");
|
|
16
|
-
const outFile = options.outPath ?? path.join(outDir, "context.json");
|
|
17
|
-
if (!fs.existsSync(outDir)) fs.mkdirSync(outDir, {
|
|
18
|
-
recursive: true
|
|
19
|
-
});
|
|
20
|
-
fs.writeFileSync(outFile, JSON.stringify(context, null, 2), "utf-8");
|
|
21
|
-
ensureGitignore(options.cwd);
|
|
22
|
-
const relOut = path.relative(options.cwd, outFile);
|
|
23
|
-
console.log(` ✓ Generated ${relOut} (${context.components.length} components, ${context.routes.length} routes, ${context.islands.length} islands)`);
|
|
24
|
-
return context;
|
|
25
|
-
}
|
|
26
|
-
function ensureGitignore(cwd) {
|
|
27
|
-
const gitignorePath = path.join(cwd, ".gitignore");
|
|
28
|
-
try {
|
|
29
|
-
const content = fs.existsSync(gitignorePath) ? fs.readFileSync(gitignorePath, "utf-8") : "";
|
|
30
|
-
if (!content.includes(".pyreon/") && !content.includes(".pyreon\n")) {
|
|
31
|
-
const addition = content.endsWith("\n") ? ".pyreon/\n" : "\n.pyreon/\n";
|
|
32
|
-
fs.appendFileSync(gitignorePath, addition);
|
|
33
|
-
}
|
|
34
|
-
} catch {}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
//#endregion
|
|
38
|
-
//#region src/doctor.ts
|
|
39
|
-
/**
|
|
40
|
-
* pyreon doctor — project-wide health check for AI-friendly development
|
|
41
|
-
*
|
|
42
|
-
* Runs a pipeline of checks:
|
|
43
|
-
* 1. React pattern detection (imports, hooks, JSX attributes)
|
|
44
|
-
* 2. Import source validation (@pyreon/* vs react/vue)
|
|
45
|
-
* 3. Common Pyreon mistakes (signal without call, key vs by, etc.)
|
|
46
|
-
*
|
|
47
|
-
* Output modes:
|
|
48
|
-
* - Human-readable (default): colored terminal output
|
|
49
|
-
* - JSON (--json): structured output for AI agent consumption
|
|
50
|
-
* - CI (--ci): exits with code 1 on any error
|
|
51
|
-
*
|
|
52
|
-
* Fix mode (--fix): auto-applies safe transforms via migrateReactCode
|
|
53
|
-
*/
|
|
54
|
-
async function doctor(options) {
|
|
55
|
-
const startTime = performance.now();
|
|
56
|
-
const result = runChecks(collectSourceFiles(options.cwd), options);
|
|
57
|
-
const elapsed = Math.round(performance.now() - startTime);
|
|
58
|
-
if (options.json) printJson(result);else printHuman(result, elapsed);
|
|
59
|
-
return result.summary.totalErrors;
|
|
60
|
-
}
|
|
61
|
-
function shouldSkipDirEntry(entry) {
|
|
62
|
-
if (!entry.isDirectory()) return false;
|
|
63
|
-
return entry.name.startsWith(".") || sourceIgnoreDirs.has(entry.name);
|
|
64
|
-
}
|
|
65
|
-
function walkSourceFiles(dir, results) {
|
|
66
|
-
let entries;
|
|
67
|
-
try {
|
|
68
|
-
entries = fs.readdirSync(dir, {
|
|
69
|
-
withFileTypes: true
|
|
70
|
-
});
|
|
71
|
-
} catch {
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
for (const entry of entries) {
|
|
75
|
-
if (shouldSkipDirEntry(entry)) continue;
|
|
76
|
-
const fullPath = path.join(dir, entry.name);
|
|
77
|
-
if (entry.isDirectory()) walkSourceFiles(fullPath, results);else if (entry.isFile() && sourceExtensions.has(path.extname(entry.name))) results.push(fullPath);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
function collectSourceFiles(cwd) {
|
|
81
|
-
const results = [];
|
|
82
|
-
walkSourceFiles(cwd, results);
|
|
83
|
-
return results;
|
|
84
|
-
}
|
|
85
|
-
function checkFileWithFix(file, relPath) {
|
|
86
|
-
let code;
|
|
87
|
-
try {
|
|
88
|
-
code = fs.readFileSync(file, "utf-8");
|
|
89
|
-
} catch {
|
|
90
|
-
return {
|
|
91
|
-
result: null,
|
|
92
|
-
fixCount: 0
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
if (!hasReactPatterns(code)) return {
|
|
96
|
-
result: null,
|
|
97
|
-
fixCount: 0
|
|
98
|
-
};
|
|
99
|
-
const migrated = migrateReactCode(code, relPath);
|
|
100
|
-
if (migrated.changes.length > 0) fs.writeFileSync(file, migrated.code, "utf-8");
|
|
101
|
-
const remaining = detectReactPatterns(migrated.code, relPath);
|
|
102
|
-
if (remaining.length > 0 || migrated.changes.length > 0) return {
|
|
103
|
-
result: {
|
|
104
|
-
file: relPath,
|
|
105
|
-
diagnostics: remaining,
|
|
106
|
-
fixed: migrated.changes.length > 0
|
|
107
|
-
},
|
|
108
|
-
fixCount: migrated.changes.length
|
|
109
|
-
};
|
|
110
|
-
return {
|
|
111
|
-
result: null,
|
|
112
|
-
fixCount: 0
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
function checkFileDetectOnly(file, relPath) {
|
|
116
|
-
let code;
|
|
117
|
-
try {
|
|
118
|
-
code = fs.readFileSync(file, "utf-8");
|
|
119
|
-
} catch {
|
|
120
|
-
return null;
|
|
121
|
-
}
|
|
122
|
-
if (!hasReactPatterns(code)) return null;
|
|
123
|
-
const diagnostics = detectReactPatterns(code, relPath);
|
|
124
|
-
if (diagnostics.length > 0) return {
|
|
125
|
-
file: relPath,
|
|
126
|
-
diagnostics,
|
|
127
|
-
fixed: false
|
|
128
|
-
};
|
|
129
|
-
return null;
|
|
3
|
+
//#region src/context.d.ts
|
|
4
|
+
interface ContextOptions {
|
|
5
|
+
cwd: string;
|
|
6
|
+
outPath?: string | undefined;
|
|
130
7
|
}
|
|
131
|
-
function
|
|
132
|
-
const fileResults = [];
|
|
133
|
-
let totalFixed = 0;
|
|
134
|
-
for (const file of files) {
|
|
135
|
-
const relPath = path.relative(options.cwd, file);
|
|
136
|
-
if (options.fix) {
|
|
137
|
-
const {
|
|
138
|
-
result,
|
|
139
|
-
fixCount
|
|
140
|
-
} = checkFileWithFix(file, relPath);
|
|
141
|
-
totalFixed += fixCount;
|
|
142
|
-
if (result) fileResults.push(result);
|
|
143
|
-
} else {
|
|
144
|
-
const result = checkFileDetectOnly(file, relPath);
|
|
145
|
-
if (result) fileResults.push(result);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
const totalErrors = fileResults.reduce((sum, f) => sum + f.diagnostics.length, 0);
|
|
149
|
-
const totalFixable = fileResults.reduce((sum, f) => sum + f.diagnostics.filter(d => d.fixable).length, 0);
|
|
150
|
-
return {
|
|
151
|
-
passed: totalErrors === 0,
|
|
152
|
-
files: fileResults,
|
|
153
|
-
summary: {
|
|
154
|
-
filesScanned: files.length,
|
|
155
|
-
filesWithIssues: fileResults.length,
|
|
156
|
-
totalErrors,
|
|
157
|
-
totalFixable,
|
|
158
|
-
totalFixed
|
|
159
|
-
}
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
function printJson(result) {
|
|
163
|
-
console.log(JSON.stringify(result, null, 2));
|
|
164
|
-
}
|
|
165
|
-
function printFileResult(fileResult) {
|
|
166
|
-
if (fileResult.diagnostics.length === 0) return;
|
|
167
|
-
console.log(` ${fileResult.file}${fileResult.fixed ? " (partially fixed)" : ""}`);
|
|
168
|
-
for (const diag of fileResult.diagnostics) {
|
|
169
|
-
const fixTag = diag.fixable ? " [fixable]" : "";
|
|
170
|
-
console.log(` ${diag.line}:${diag.column} — ${diag.message}${fixTag}`);
|
|
171
|
-
console.log(` Current: ${diag.current}`);
|
|
172
|
-
console.log(` Suggested: ${diag.suggested}`);
|
|
173
|
-
console.log("");
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
function printSummary(summary) {
|
|
177
|
-
console.log(` ${summary.totalErrors} issue${summary.totalErrors === 1 ? "" : "s"} in ${summary.filesWithIssues} file${summary.filesWithIssues === 1 ? "" : "s"}`);
|
|
178
|
-
if (summary.totalFixable > 0) console.log(` ${summary.totalFixable} auto-fixable — run 'pyreon doctor --fix' to apply`);
|
|
179
|
-
console.log("");
|
|
180
|
-
}
|
|
181
|
-
function printHuman(result, elapsed) {
|
|
182
|
-
const {
|
|
183
|
-
summary
|
|
184
|
-
} = result;
|
|
185
|
-
console.log("");
|
|
186
|
-
console.log(` Pyreon Doctor — scanned ${summary.filesScanned} files in ${elapsed}ms`);
|
|
187
|
-
console.log("");
|
|
188
|
-
if (result.passed && summary.totalFixed === 0) {
|
|
189
|
-
console.log(" ✓ No issues found. Your code is Pyreon-native!");
|
|
190
|
-
console.log("");
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
193
|
-
if (summary.totalFixed > 0) {
|
|
194
|
-
console.log(` ✓ Auto-fixed ${summary.totalFixed} issue${summary.totalFixed === 1 ? "" : "s"}`);
|
|
195
|
-
console.log("");
|
|
196
|
-
}
|
|
197
|
-
for (const fileResult of result.files) printFileResult(fileResult);
|
|
198
|
-
printSummary(summary);
|
|
199
|
-
}
|
|
200
|
-
|
|
8
|
+
declare function generateContext(options: ContextOptions): Promise<ProjectContext$1>;
|
|
201
9
|
//#endregion
|
|
202
|
-
//#region src/
|
|
10
|
+
//#region src/doctor.d.ts
|
|
203
11
|
/**
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
if (!command || command === "--help" || command === "-h") {
|
|
226
|
-
printUsage();
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
if (command === "--version" || command === "-v") {
|
|
230
|
-
console.log("0.4.0");
|
|
231
|
-
return;
|
|
232
|
-
}
|
|
233
|
-
if (command === "doctor") {
|
|
234
|
-
const options = {
|
|
235
|
-
fix: args.includes("--fix"),
|
|
236
|
-
json: args.includes("--json"),
|
|
237
|
-
ci: args.includes("--ci"),
|
|
238
|
-
cwd: process.cwd()
|
|
239
|
-
};
|
|
240
|
-
const exitCode = await doctor(options);
|
|
241
|
-
if (options.ci && exitCode > 0) process.exit(1);
|
|
242
|
-
return;
|
|
243
|
-
}
|
|
244
|
-
if (command === "context") {
|
|
245
|
-
const outIdx = args.indexOf("--out");
|
|
246
|
-
const outPath = outIdx >= 0 ? args[outIdx + 1] : void 0;
|
|
247
|
-
await generateContext({
|
|
248
|
-
cwd: process.cwd(),
|
|
249
|
-
outPath
|
|
250
|
-
});
|
|
251
|
-
return;
|
|
252
|
-
}
|
|
253
|
-
console.error(`Unknown command: ${command}`);
|
|
254
|
-
printUsage();
|
|
255
|
-
process.exit(1);
|
|
256
|
-
}
|
|
12
|
+
* pyreon doctor — project-wide health check for AI-friendly development
|
|
13
|
+
*
|
|
14
|
+
* Runs a pipeline of checks:
|
|
15
|
+
* 1. React pattern detection (imports, hooks, JSX attributes)
|
|
16
|
+
* 2. Import source validation (@pyreon/* vs react/vue)
|
|
17
|
+
* 3. Common Pyreon mistakes (signal without call, key vs by, etc.)
|
|
18
|
+
*
|
|
19
|
+
* Output modes:
|
|
20
|
+
* - Human-readable (default): colored terminal output
|
|
21
|
+
* - JSON (--json): structured output for AI agent consumption
|
|
22
|
+
* - CI (--ci): exits with code 1 on any error
|
|
23
|
+
*
|
|
24
|
+
* Fix mode (--fix): auto-applies safe transforms via migrateReactCode
|
|
25
|
+
*/
|
|
26
|
+
interface DoctorOptions {
|
|
27
|
+
fix: boolean;
|
|
28
|
+
json: boolean;
|
|
29
|
+
ci: boolean;
|
|
30
|
+
cwd: string;
|
|
31
|
+
}
|
|
32
|
+
declare function doctor(options: DoctorOptions): Promise<number>;
|
|
257
33
|
//#endregion
|
|
258
|
-
export { doctor, generateContext };
|
|
259
|
-
//# sourceMappingURL=
|
|
34
|
+
export { type ContextOptions, type DoctorOptions, type ProjectContext, doctor, generateContext };
|
|
35
|
+
//# sourceMappingURL=index2.d.ts.map
|
package/lib/types/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"
|
|
1
|
+
{"version":3,"file":"index2.d.ts","names":[],"sources":["../../../src/context.ts","../../../src/doctor.ts"],"mappings":";;;UAaiB,cAAA;EACf,GAAA;EACA,OAAA;AAAA;AAAA,iBAGoB,eAAA,CAAgB,OAAA,EAAS,cAAA,GAAiB,OAAA,CAAQ,gBAAA;;;;;;AALxE;;;;;AAKA;;;;;;;UCOiB,aAAA;EACf,GAAA;EACA,IAAA;EACA,EAAA;EACA,GAAA;AAAA;AAAA,iBAqBoB,MAAA,CAAO,OAAA,EAAS,aAAA,GAAgB,OAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pyreon/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "CLI tools for Pyreon — doctor, generate, context",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"prepublishOnly": "bun run build"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@pyreon/compiler": "0.
|
|
45
|
+
"@pyreon/compiler": "0.6.0"
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
48
|
"typescript": ">=5.0.0"
|