@mr.dj2u/doctor 0.1.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/dist/checks/app-architecture.d.ts +4 -0
- package/dist/checks/app-architecture.d.ts.map +1 -0
- package/dist/checks/app-architecture.js +75 -0
- package/dist/checks/app-architecture.js.map +1 -0
- package/dist/checks/env-hygiene.d.ts +4 -0
- package/dist/checks/env-hygiene.d.ts.map +1 -0
- package/dist/checks/env-hygiene.js +54 -0
- package/dist/checks/env-hygiene.js.map +1 -0
- package/dist/checks/eslint.d.ts +10 -0
- package/dist/checks/eslint.d.ts.map +1 -0
- package/dist/checks/eslint.js +23 -0
- package/dist/checks/eslint.js.map +1 -0
- package/dist/checks/expo-config.d.ts +3 -0
- package/dist/checks/expo-config.d.ts.map +1 -0
- package/dist/checks/expo-config.js +51 -0
- package/dist/checks/expo-config.js.map +1 -0
- package/dist/checks/expo-doctor.d.ts +8 -0
- package/dist/checks/expo-doctor.d.ts.map +1 -0
- package/dist/checks/expo-doctor.js +22 -0
- package/dist/checks/expo-doctor.js.map +1 -0
- package/dist/checks/gitignore-env.d.ts +3 -0
- package/dist/checks/gitignore-env.d.ts.map +1 -0
- package/dist/checks/gitignore-env.js +30 -0
- package/dist/checks/gitignore-env.js.map +1 -0
- package/dist/checks/index.d.ts +15 -0
- package/dist/checks/index.d.ts.map +1 -0
- package/dist/checks/index.js +15 -0
- package/dist/checks/index.js.map +1 -0
- package/dist/checks/package-scripts.d.ts +3 -0
- package/dist/checks/package-scripts.d.ts.map +1 -0
- package/dist/checks/package-scripts.js +56 -0
- package/dist/checks/package-scripts.js.map +1 -0
- package/dist/checks/project-docs.d.ts +3 -0
- package/dist/checks/project-docs.d.ts.map +1 -0
- package/dist/checks/project-docs.js +45 -0
- package/dist/checks/project-docs.js.map +1 -0
- package/dist/checks/script-checks.d.ts +9 -0
- package/dist/checks/script-checks.d.ts.map +1 -0
- package/dist/checks/script-checks.js +59 -0
- package/dist/checks/script-checks.js.map +1 -0
- package/dist/checks/seo-metadata.d.ts +3 -0
- package/dist/checks/seo-metadata.d.ts.map +1 -0
- package/dist/checks/seo-metadata.js +41 -0
- package/dist/checks/seo-metadata.js.map +1 -0
- package/dist/checks/ssr-safety.d.ts +4 -0
- package/dist/checks/ssr-safety.d.ts.map +1 -0
- package/dist/checks/ssr-safety.js +33 -0
- package/dist/checks/ssr-safety.js.map +1 -0
- package/dist/checks/styling-stack.d.ts +3 -0
- package/dist/checks/styling-stack.d.ts.map +1 -0
- package/dist/checks/styling-stack.js +35 -0
- package/dist/checks/styling-stack.js.map +1 -0
- package/dist/checks/todo-for-context.d.ts +3 -0
- package/dist/checks/todo-for-context.d.ts.map +1 -0
- package/dist/checks/todo-for-context.js +56 -0
- package/dist/checks/todo-for-context.js.map +1 -0
- package/dist/checks/typescript.d.ts +7 -0
- package/dist/checks/typescript.d.ts.map +1 -0
- package/dist/checks/typescript.js +18 -0
- package/dist/checks/typescript.js.map +1 -0
- package/dist/cli-main.d.ts +15 -0
- package/dist/cli-main.d.ts.map +1 -0
- package/dist/cli-main.js +83 -0
- package/dist/cli-main.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +13 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +52 -0
- package/dist/index.js.map +1 -0
- package/dist/reporter.d.ts +5 -0
- package/dist/reporter.d.ts.map +1 -0
- package/dist/reporter.js +50 -0
- package/dist/reporter.js.map +1 -0
- package/dist/scan-file.d.ts +3 -0
- package/dist/scan-file.d.ts.map +1 -0
- package/dist/scan-file.js +35 -0
- package/dist/scan-file.js.map +1 -0
- package/dist/types.d.ts +46 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +25 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +211 -0
- package/dist/utils.js.map +1 -0
- package/package.json +45 -0
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export type DoctorCheckStatus = 'pass' | 'warn' | 'error' | 'skip';
|
|
2
|
+
export type DoctorMode = 'fast' | 'ci' | 'full';
|
|
3
|
+
export interface DoctorCheckResult {
|
|
4
|
+
name: string;
|
|
5
|
+
status: DoctorCheckStatus;
|
|
6
|
+
message: string;
|
|
7
|
+
details?: Record<string, unknown>;
|
|
8
|
+
}
|
|
9
|
+
export interface DoctorReport {
|
|
10
|
+
projectPath: string;
|
|
11
|
+
timestamp: string;
|
|
12
|
+
mode: DoctorMode;
|
|
13
|
+
checks: DoctorCheckResult[];
|
|
14
|
+
summary: {
|
|
15
|
+
score: number;
|
|
16
|
+
errors: number;
|
|
17
|
+
warnings: number;
|
|
18
|
+
passed: number;
|
|
19
|
+
skipped: number;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export interface DoctorOptions {
|
|
23
|
+
mode?: DoctorMode;
|
|
24
|
+
fix?: boolean;
|
|
25
|
+
runScripts?: boolean;
|
|
26
|
+
timeoutMs?: number;
|
|
27
|
+
}
|
|
28
|
+
export interface ScanFileOptions {
|
|
29
|
+
projectPath?: string;
|
|
30
|
+
}
|
|
31
|
+
export type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun';
|
|
32
|
+
export interface CommandResult {
|
|
33
|
+
code: number | null;
|
|
34
|
+
stdout: string;
|
|
35
|
+
stderr: string;
|
|
36
|
+
timedOut: boolean;
|
|
37
|
+
}
|
|
38
|
+
export interface PackageJson {
|
|
39
|
+
name?: string;
|
|
40
|
+
packageManager?: string;
|
|
41
|
+
main?: string;
|
|
42
|
+
scripts?: Record<string, string>;
|
|
43
|
+
dependencies?: Record<string, string>;
|
|
44
|
+
devDependencies?: Record<string, string>;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AACnE,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC;AAEhD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC5B,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AAE7D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { CommandResult, PackageJson, PackageManager } from './types.js';
|
|
2
|
+
export declare const SOURCE_EXTENSIONS: Set<string>;
|
|
3
|
+
export declare function readPackageJson(filePath: string): Promise<PackageJson | null>;
|
|
4
|
+
export declare function findFiles(rootPath: string, predicate: (filePath: string) => boolean): Promise<string[]>;
|
|
5
|
+
export declare function firstExistingPath(paths: string[]): Promise<string | null>;
|
|
6
|
+
export declare function readOptionalText(filePath: string): Promise<string | null>;
|
|
7
|
+
export declare function pathExists(filePath: string): Promise<boolean>;
|
|
8
|
+
export declare function pathExistsSyncLike(filePath: string): boolean;
|
|
9
|
+
export declare function detectPackageManager(projectPath: string, packageJson: PackageJson): Promise<PackageManager>;
|
|
10
|
+
export declare function runShellCommand(command: string, cwd: string, timeoutMs: number): Promise<CommandResult>;
|
|
11
|
+
export declare function buildRunScriptCommand(packageManager: PackageManager, scriptName: string, extraArgs?: string[]): string;
|
|
12
|
+
export declare function commandResultToCheck(name: string, command: string, result: CommandResult): {
|
|
13
|
+
name: string;
|
|
14
|
+
status: 'pass' | 'error';
|
|
15
|
+
message: string;
|
|
16
|
+
details: Record<string, unknown>;
|
|
17
|
+
};
|
|
18
|
+
export declare function compactCommandOutput(result: CommandResult): Record<string, unknown>;
|
|
19
|
+
export declare function readString(value: unknown): string | undefined;
|
|
20
|
+
export declare function readStringRecord(value: unknown): Record<string, string> | undefined;
|
|
21
|
+
export declare function readNestedString(value: Record<string, unknown> | null, keys: string[]): string | undefined;
|
|
22
|
+
export declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
23
|
+
export declare function tail(output: string, maxLines?: number): string;
|
|
24
|
+
export declare function relative(rootPath: string, filePath: string): string;
|
|
25
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE7E,eAAO,MAAM,iBAAiB,aAA0C,CAAC;AAczE,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAmBnF;AAED,wBAAsB,SAAS,CAC7B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,GACvC,OAAO,CAAC,MAAM,EAAE,CAAC,CAuBnB;AAED,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAO/E;AAED,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAM/E;AAED,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOnE;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,WAAW,GACvB,OAAO,CAAC,cAAc,CAAC,CAUzB;AAED,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,aAAa,CAAC,CAuCxB;AAED,wBAAgB,qBAAqB,CACnC,cAAc,EAAE,cAAc,EAC9B,UAAU,EAAE,MAAM,EAClB,SAAS,GAAE,MAAM,EAAO,GACvB,MAAM,CAaR;AAED,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,aAAa,GACpB;IACD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,CAkBA;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAOnF;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAE7D;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CASnF;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EACrC,IAAI,EAAE,MAAM,EAAE,GACb,MAAM,GAAG,SAAS,CASpB;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE;AAED,wBAAgB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,SAAK,GAAG,MAAM,CAG1D;AAED,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEnE"}
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { access, readFile, readdir } from 'node:fs/promises';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
export const SOURCE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx']);
|
|
6
|
+
const EXCLUDED_DIRS = new Set([
|
|
7
|
+
'.git',
|
|
8
|
+
'.expo',
|
|
9
|
+
'.turbo',
|
|
10
|
+
'mds',
|
|
11
|
+
'build',
|
|
12
|
+
'coverage',
|
|
13
|
+
'dist',
|
|
14
|
+
'node_modules',
|
|
15
|
+
'temp',
|
|
16
|
+
]);
|
|
17
|
+
export async function readPackageJson(filePath) {
|
|
18
|
+
try {
|
|
19
|
+
const raw = await readFile(filePath, 'utf8');
|
|
20
|
+
const parsed = JSON.parse(raw);
|
|
21
|
+
if (!isRecord(parsed)) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
name: readString(parsed.name),
|
|
26
|
+
packageManager: readString(parsed.packageManager),
|
|
27
|
+
main: readString(parsed.main),
|
|
28
|
+
scripts: readStringRecord(parsed.scripts),
|
|
29
|
+
dependencies: readStringRecord(parsed.dependencies),
|
|
30
|
+
devDependencies: readStringRecord(parsed.devDependencies),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export async function findFiles(rootPath, predicate) {
|
|
38
|
+
if (!(await pathExists(rootPath))) {
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
const results = [];
|
|
42
|
+
const entries = await readdir(rootPath, { withFileTypes: true });
|
|
43
|
+
for (const entry of entries) {
|
|
44
|
+
const filePath = path.join(rootPath, entry.name);
|
|
45
|
+
if (entry.isDirectory()) {
|
|
46
|
+
if (!EXCLUDED_DIRS.has(entry.name)) {
|
|
47
|
+
results.push(...(await findFiles(filePath, predicate)));
|
|
48
|
+
}
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (entry.isFile() && predicate(filePath)) {
|
|
52
|
+
results.push(filePath);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return results;
|
|
56
|
+
}
|
|
57
|
+
export async function firstExistingPath(paths) {
|
|
58
|
+
for (const filePath of paths) {
|
|
59
|
+
if (await pathExists(filePath)) {
|
|
60
|
+
return filePath;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
export async function readOptionalText(filePath) {
|
|
66
|
+
try {
|
|
67
|
+
return await readFile(filePath, 'utf8');
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
export async function pathExists(filePath) {
|
|
74
|
+
try {
|
|
75
|
+
await access(filePath);
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
export function pathExistsSyncLike(filePath) {
|
|
83
|
+
return existsSync(filePath);
|
|
84
|
+
}
|
|
85
|
+
export async function detectPackageManager(projectPath, packageJson) {
|
|
86
|
+
const declared = packageJson.packageManager ?? '';
|
|
87
|
+
if (declared.startsWith('pnpm@'))
|
|
88
|
+
return 'pnpm';
|
|
89
|
+
if (declared.startsWith('yarn@'))
|
|
90
|
+
return 'yarn';
|
|
91
|
+
if (declared.startsWith('bun@'))
|
|
92
|
+
return 'bun';
|
|
93
|
+
if (declared.startsWith('npm@'))
|
|
94
|
+
return 'npm';
|
|
95
|
+
if (await pathExists(path.join(projectPath, 'pnpm-lock.yaml')))
|
|
96
|
+
return 'pnpm';
|
|
97
|
+
if (await pathExists(path.join(projectPath, 'yarn.lock')))
|
|
98
|
+
return 'yarn';
|
|
99
|
+
if (await pathExists(path.join(projectPath, 'bun.lockb')))
|
|
100
|
+
return 'bun';
|
|
101
|
+
return 'npm';
|
|
102
|
+
}
|
|
103
|
+
export async function runShellCommand(command, cwd, timeoutMs) {
|
|
104
|
+
return new Promise((resolve) => {
|
|
105
|
+
const child = spawn(command, {
|
|
106
|
+
cwd,
|
|
107
|
+
shell: true,
|
|
108
|
+
windowsHide: true,
|
|
109
|
+
env: { ...process.env, CI: 'true' },
|
|
110
|
+
});
|
|
111
|
+
let stdout = '';
|
|
112
|
+
let stderr = '';
|
|
113
|
+
let settled = false;
|
|
114
|
+
const finish = (result) => {
|
|
115
|
+
if (settled) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
settled = true;
|
|
119
|
+
clearTimeout(timeout);
|
|
120
|
+
resolve(result);
|
|
121
|
+
};
|
|
122
|
+
const timeout = setTimeout(() => {
|
|
123
|
+
child.kill('SIGTERM');
|
|
124
|
+
finish({ code: null, stdout, stderr, timedOut: true });
|
|
125
|
+
}, timeoutMs);
|
|
126
|
+
child.stdout?.on('data', (chunk) => {
|
|
127
|
+
stdout += chunk.toString();
|
|
128
|
+
});
|
|
129
|
+
child.stderr?.on('data', (chunk) => {
|
|
130
|
+
stderr += chunk.toString();
|
|
131
|
+
});
|
|
132
|
+
child.on('error', (error) => {
|
|
133
|
+
finish({ code: 1, stdout, stderr: `${stderr}\n${error.message}`.trim(), timedOut: false });
|
|
134
|
+
});
|
|
135
|
+
child.on('close', (code) => {
|
|
136
|
+
finish({ code, stdout, stderr, timedOut: false });
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
export function buildRunScriptCommand(packageManager, scriptName, extraArgs = []) {
|
|
141
|
+
const suffix = extraArgs.length > 0 ? ` ${extraArgs.join(' ')}` : '';
|
|
142
|
+
switch (packageManager) {
|
|
143
|
+
case 'pnpm':
|
|
144
|
+
return `pnpm run ${scriptName}${suffix}`;
|
|
145
|
+
case 'yarn':
|
|
146
|
+
return `yarn ${scriptName}${suffix}`;
|
|
147
|
+
case 'bun':
|
|
148
|
+
return `bun run ${scriptName}${suffix}`;
|
|
149
|
+
case 'npm':
|
|
150
|
+
return `npm run ${scriptName}${suffix}`;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
export function commandResultToCheck(name, command, result) {
|
|
154
|
+
if (result.code === 0) {
|
|
155
|
+
return {
|
|
156
|
+
name,
|
|
157
|
+
status: 'pass',
|
|
158
|
+
message: `${command} passed.`,
|
|
159
|
+
details: compactCommandOutput(result),
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
return {
|
|
163
|
+
name,
|
|
164
|
+
status: 'error',
|
|
165
|
+
message: result.timedOut
|
|
166
|
+
? `${command} timed out.`
|
|
167
|
+
: `${command} failed with exit code ${result.code ?? 'unknown'}.`,
|
|
168
|
+
details: compactCommandOutput(result),
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
export function compactCommandOutput(result) {
|
|
172
|
+
return {
|
|
173
|
+
code: result.code,
|
|
174
|
+
timedOut: result.timedOut,
|
|
175
|
+
stdout: tail(result.stdout),
|
|
176
|
+
stderr: tail(result.stderr),
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
export function readString(value) {
|
|
180
|
+
return typeof value === 'string' ? value : undefined;
|
|
181
|
+
}
|
|
182
|
+
export function readStringRecord(value) {
|
|
183
|
+
if (!isRecord(value)) {
|
|
184
|
+
return undefined;
|
|
185
|
+
}
|
|
186
|
+
const entries = Object.entries(value).filter((entry) => {
|
|
187
|
+
return typeof entry[1] === 'string';
|
|
188
|
+
});
|
|
189
|
+
return Object.fromEntries(entries);
|
|
190
|
+
}
|
|
191
|
+
export function readNestedString(value, keys) {
|
|
192
|
+
let current = value;
|
|
193
|
+
for (const key of keys) {
|
|
194
|
+
if (!isRecord(current)) {
|
|
195
|
+
return undefined;
|
|
196
|
+
}
|
|
197
|
+
current = current[key];
|
|
198
|
+
}
|
|
199
|
+
return readString(current);
|
|
200
|
+
}
|
|
201
|
+
export function isRecord(value) {
|
|
202
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
203
|
+
}
|
|
204
|
+
export function tail(output, maxLines = 30) {
|
|
205
|
+
const lines = output.trim().split(/\r?\n/).filter(Boolean);
|
|
206
|
+
return lines.slice(-maxLines).join('\n');
|
|
207
|
+
}
|
|
208
|
+
export function relative(rootPath, filePath) {
|
|
209
|
+
return path.relative(rootPath, filePath).replace(/\\/g, '/');
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mr.dj2u/doctor",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Production Doctor: multi-check engine for Expo apps (lint, tsc, expo doctor, architecture)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": "./dist/cli.js",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"types": "./dist/index.d.ts"
|
|
14
|
+
},
|
|
15
|
+
"./checks": {
|
|
16
|
+
"import": "./dist/checks/index.js",
|
|
17
|
+
"types": "./dist/checks/index.d.ts"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"main": "./dist/index.js",
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsc",
|
|
24
|
+
"type-check": "tsc --noEmit",
|
|
25
|
+
"lint": "eslint src",
|
|
26
|
+
"lint:fix": "eslint src --fix",
|
|
27
|
+
"test": "vitest run --passWithNoTests",
|
|
28
|
+
"dev": "tsc --watch",
|
|
29
|
+
"clean": "node -e \"const fs=require('node:fs'); for (const p of ['dist','tsconfig.tsbuildinfo']) fs.rmSync(p,{recursive:true,force:true});\""
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"execa": "^6.1.0",
|
|
33
|
+
"json5": "^2.2.3"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@types/node": "^20.10.0",
|
|
37
|
+
"typescript": "^5.9.0"
|
|
38
|
+
},
|
|
39
|
+
"keywords": ["expo", "doctor", "lint", "typescript", "quality"],
|
|
40
|
+
"author": "DJ",
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public"
|
|
44
|
+
}
|
|
45
|
+
}
|