aislop 0.7.0 → 0.8.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.
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env node
2
+ import { n as runSubprocess } from "./subprocess-CCnnN_oQ.js";
3
+ import { createRequire } from "node:module";
4
+ import path from "node:path";
5
+ import fs from "node:fs";
6
+
7
+ //#region src/engines/lint/expo-doctor.ts
8
+ const esmRequire = createRequire(import.meta.url);
9
+ const ISSUE_PREFIX = "✖ ";
10
+ const resolveExpoDoctorScript = () => {
11
+ try {
12
+ const packageJsonPath = esmRequire.resolve("expo-doctor/package.json");
13
+ const pkg = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
14
+ const binRelativePath = typeof pkg.bin === "string" ? pkg.bin : pkg.bin?.["expo-doctor"];
15
+ if (!binRelativePath) return null;
16
+ return path.join(path.dirname(packageJsonPath), binRelativePath);
17
+ } catch {
18
+ return null;
19
+ }
20
+ };
21
+ const toRuleSuffix = (title) => {
22
+ const slug = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
23
+ return slug.length > 0 ? slug : "issue";
24
+ };
25
+ const parseIssues = (output) => {
26
+ const lines = output.split("\n").map((line) => line.trimEnd());
27
+ const startIndex = lines.findIndex((line) => line.includes("Possible issues detected:"));
28
+ if (startIndex < 0) return [];
29
+ const issues = [];
30
+ let current = null;
31
+ let inAdvice = false;
32
+ for (let i = startIndex + 1; i < lines.length; i += 1) {
33
+ const line = lines[i].trim();
34
+ if (/^\d+\s+checks failed/.test(line)) break;
35
+ if (line.length === 0) continue;
36
+ if (line.startsWith(ISSUE_PREFIX)) {
37
+ if (current) issues.push(current);
38
+ current = {
39
+ title: line.slice(2).trim(),
40
+ details: [],
41
+ advice: []
42
+ };
43
+ inAdvice = false;
44
+ continue;
45
+ }
46
+ if (!current) continue;
47
+ if (line === "Advice:") {
48
+ inAdvice = true;
49
+ continue;
50
+ }
51
+ if (inAdvice) current.advice.push(line);
52
+ else current.details.push(line);
53
+ }
54
+ if (current) issues.push(current);
55
+ return issues;
56
+ };
57
+ const parseConfigError = (output) => {
58
+ const line = output.split("\n").find((candidate) => candidate.trim().startsWith("ConfigError:"));
59
+ return line ? line.trim() : null;
60
+ };
61
+ const toDiagnostics = (issues) => issues.map((issue) => {
62
+ const helpParts = [issue.details.join(" ").trim(), issue.advice.join(" ").trim()].filter((part) => part.length > 0);
63
+ return {
64
+ filePath: "package.json",
65
+ engine: "lint",
66
+ rule: `expo-doctor/${toRuleSuffix(issue.title)}`,
67
+ severity: "warning",
68
+ message: `Expo Doctor: ${issue.title}`,
69
+ help: helpParts.join(" "),
70
+ line: 0,
71
+ column: 0,
72
+ category: "Expo",
73
+ fixable: false
74
+ };
75
+ });
76
+ const hasExpoInstalled = (rootDirectory) => {
77
+ try {
78
+ createRequire(path.join(rootDirectory, "package.json")).resolve("expo/package.json");
79
+ return true;
80
+ } catch {
81
+ return false;
82
+ }
83
+ };
84
+ const runExpoDoctor = async (context) => {
85
+ if (!hasExpoInstalled(context.rootDirectory)) return [];
86
+ const scriptPath = resolveExpoDoctorScript();
87
+ let stdout = "";
88
+ let stderr = "";
89
+ try {
90
+ if (scriptPath) {
91
+ const result = await runSubprocess(process.execPath, [
92
+ scriptPath,
93
+ context.rootDirectory,
94
+ "--verbose"
95
+ ], {
96
+ cwd: context.rootDirectory,
97
+ timeout: 12e4
98
+ });
99
+ stdout = result.stdout;
100
+ stderr = result.stderr;
101
+ } else {
102
+ const result = await runSubprocess("npx", [
103
+ "--yes",
104
+ "expo-doctor",
105
+ context.rootDirectory,
106
+ "--verbose"
107
+ ], {
108
+ cwd: context.rootDirectory,
109
+ timeout: 12e4
110
+ });
111
+ stdout = result.stdout;
112
+ stderr = result.stderr;
113
+ }
114
+ } catch {
115
+ return [];
116
+ }
117
+ const output = [stdout, stderr].filter(Boolean).join("\n");
118
+ if (!output) return [];
119
+ const configError = parseConfigError(output);
120
+ if (configError) return [{
121
+ filePath: "package.json",
122
+ engine: "lint",
123
+ rule: "expo-doctor/config-error",
124
+ severity: "warning",
125
+ message: configError,
126
+ help: "Install project dependencies, then re-run `npx aislop scan`.",
127
+ line: 0,
128
+ column: 0,
129
+ category: "Expo",
130
+ fixable: false
131
+ }];
132
+ return toDiagnostics(parseIssues(output));
133
+ };
134
+
135
+ //#endregion
136
+ export { runExpoDoctor };
package/dist/index.d.ts CHANGED
@@ -38,6 +38,9 @@ declare const AislopConfigSchema: z.ZodObject<{
38
38
  maxNesting: z.ZodDefault<z.ZodNumber>;
39
39
  maxParams: z.ZodDefault<z.ZodNumber>;
40
40
  }, z.core.$strip>>;
41
+ lint: z.ZodDefault<z.ZodObject<{
42
+ typecheck: z.ZodDefault<z.ZodBoolean>;
43
+ }, z.core.$strip>>;
41
44
  security: z.ZodDefault<z.ZodObject<{
42
45
  audit: z.ZodDefault<z.ZodBoolean>;
43
46
  auditTimeout: z.ZodDefault<z.ZodNumber>;