forgestack-os-cli 0.3.4 → 0.3.6

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 (46) hide show
  1. package/README.md +382 -150
  2. package/dist/commands/doctor.d.ts +12 -0
  3. package/dist/commands/doctor.js +214 -0
  4. package/dist/commands/doctor.js.map +1 -0
  5. package/dist/commands/organize.d.ts +2 -0
  6. package/dist/commands/organize.js +126 -0
  7. package/dist/commands/organize.js.map +1 -0
  8. package/dist/commands/run-tasks.d.ts +12 -0
  9. package/dist/commands/run-tasks.js +125 -0
  10. package/dist/commands/run-tasks.js.map +1 -0
  11. package/dist/index.js +30 -0
  12. package/dist/index.js.map +1 -1
  13. package/dist/utils/doctor/check-database.d.ts +8 -0
  14. package/dist/utils/doctor/check-database.js +271 -0
  15. package/dist/utils/doctor/check-database.js.map +1 -0
  16. package/dist/utils/doctor/check-docker.d.ts +8 -0
  17. package/dist/utils/doctor/check-docker.js +212 -0
  18. package/dist/utils/doctor/check-docker.js.map +1 -0
  19. package/dist/utils/doctor/check-env.d.ts +12 -0
  20. package/dist/utils/doctor/check-env.js +207 -0
  21. package/dist/utils/doctor/check-env.js.map +1 -0
  22. package/dist/utils/doctor/check-lint.d.ts +8 -0
  23. package/dist/utils/doctor/check-lint.js +225 -0
  24. package/dist/utils/doctor/check-lint.js.map +1 -0
  25. package/dist/utils/doctor/check-node.d.ts +20 -0
  26. package/dist/utils/doctor/check-node.js +172 -0
  27. package/dist/utils/doctor/check-node.js.map +1 -0
  28. package/dist/utils/doctor/check-ports.d.ts +15 -0
  29. package/dist/utils/doctor/check-ports.js +166 -0
  30. package/dist/utils/doctor/check-ports.js.map +1 -0
  31. package/dist/utils/doctor/check-prisma.d.ts +8 -0
  32. package/dist/utils/doctor/check-prisma.js +202 -0
  33. package/dist/utils/doctor/check-prisma.js.map +1 -0
  34. package/dist/utils/doctor/index.d.ts +14 -0
  35. package/dist/utils/doctor/index.js +15 -0
  36. package/dist/utils/doctor/index.js.map +1 -0
  37. package/dist/utils/doctor/types.d.ts +50 -0
  38. package/dist/utils/doctor/types.js +5 -0
  39. package/dist/utils/doctor/types.js.map +1 -0
  40. package/dist/utils/file-organizer.d.ts +17 -0
  41. package/dist/utils/file-organizer.js +170 -0
  42. package/dist/utils/file-organizer.js.map +1 -0
  43. package/dist/utils/task-runner.d.ts +14 -0
  44. package/dist/utils/task-runner.js +79 -0
  45. package/dist/utils/task-runner.js.map +1 -0
  46. package/package.json +11 -4
@@ -0,0 +1,207 @@
1
+ /**
2
+ * Environment variable validation checks
3
+ */
4
+ import fs from 'fs-extra';
5
+ import path from 'path';
6
+ /**
7
+ * Parse .env file content into key-value pairs
8
+ */
9
+ function parseEnvFile(content) {
10
+ const env = {};
11
+ const lines = content.split('\n');
12
+ for (const line of lines) {
13
+ const trimmed = line.trim();
14
+ // Skip comments and empty lines
15
+ if (!trimmed || trimmed.startsWith('#'))
16
+ continue;
17
+ const match = trimmed.match(/^([^=]+)=(.*)$/);
18
+ if (match) {
19
+ const key = match[1].trim();
20
+ let value = match[2].trim();
21
+ // Remove quotes if present
22
+ if ((value.startsWith('"') && value.endsWith('"')) ||
23
+ (value.startsWith("'") && value.endsWith("'"))) {
24
+ value = value.slice(1, -1);
25
+ }
26
+ env[key] = value;
27
+ }
28
+ }
29
+ return env;
30
+ }
31
+ /**
32
+ * Infer the type of an environment variable from its example value
33
+ */
34
+ function inferEnvType(name, exampleValue) {
35
+ const lowerName = name.toLowerCase();
36
+ // URL detection
37
+ if (lowerName.includes('url') || lowerName.includes('uri') ||
38
+ lowerName.includes('endpoint') || lowerName.includes('host') ||
39
+ exampleValue.startsWith('http://') || exampleValue.startsWith('https://') ||
40
+ exampleValue.startsWith('postgres://') || exampleValue.startsWith('mongodb://') ||
41
+ exampleValue.startsWith('mysql://')) {
42
+ return 'url';
43
+ }
44
+ // Boolean detection
45
+ if (exampleValue.toLowerCase() === 'true' || exampleValue.toLowerCase() === 'false' ||
46
+ exampleValue === '0' || exampleValue === '1') {
47
+ return 'boolean';
48
+ }
49
+ // Number detection
50
+ if (lowerName.includes('port') || lowerName.includes('timeout') ||
51
+ lowerName.includes('limit') || lowerName.includes('size') ||
52
+ lowerName.includes('count') || lowerName.includes('max') ||
53
+ lowerName.includes('min') || /^\d+$/.test(exampleValue)) {
54
+ return 'number';
55
+ }
56
+ return 'string';
57
+ }
58
+ /**
59
+ * Validate a value against its expected type
60
+ */
61
+ function validateEnvValue(value, type) {
62
+ if (!value)
63
+ return false;
64
+ switch (type) {
65
+ case 'number':
66
+ return !isNaN(Number(value)) && value.trim() !== '';
67
+ case 'boolean':
68
+ return ['true', 'false', '0', '1', 'yes', 'no'].includes(value.toLowerCase());
69
+ case 'url':
70
+ try {
71
+ new URL(value);
72
+ return true;
73
+ }
74
+ catch {
75
+ // Also accept connection strings with protocols
76
+ return /^[a-z]+:\/\/.+/.test(value);
77
+ }
78
+ case 'string':
79
+ default:
80
+ return true;
81
+ }
82
+ }
83
+ /**
84
+ * Check environment variables against .env.example
85
+ */
86
+ export async function checkEnvVariables(cwd) {
87
+ const results = [];
88
+ const envExamplePath = path.join(cwd, '.env.example');
89
+ const envPath = path.join(cwd, '.env');
90
+ // Check if .env.example exists
91
+ if (!await fs.pathExists(envExamplePath)) {
92
+ results.push({
93
+ name: 'Environment Variables',
94
+ status: 'skip',
95
+ message: 'No .env.example found',
96
+ details: 'Create a .env.example file to enable environment variable validation',
97
+ });
98
+ return results;
99
+ }
100
+ // Read .env.example
101
+ const exampleContent = await fs.readFile(envExamplePath, 'utf-8');
102
+ const exampleVars = parseEnvFile(exampleContent);
103
+ if (Object.keys(exampleVars).length === 0) {
104
+ results.push({
105
+ name: 'Environment Variables',
106
+ status: 'skip',
107
+ message: '.env.example is empty',
108
+ });
109
+ return results;
110
+ }
111
+ // Check if .env exists
112
+ if (!await fs.pathExists(envPath)) {
113
+ const missingVars = Object.keys(exampleVars);
114
+ results.push({
115
+ name: 'Environment Variables',
116
+ status: 'fail',
117
+ message: `.env file not found (${missingVars.length} variables required)`,
118
+ details: `Missing: ${missingVars.join(', ')}`,
119
+ fix: 'Copy .env.example to .env and fill in the values',
120
+ });
121
+ return results;
122
+ }
123
+ // Read .env
124
+ const envContent = await fs.readFile(envPath, 'utf-8');
125
+ const envVars = parseEnvFile(envContent);
126
+ // Check for missing variables
127
+ const missingVars = [];
128
+ const invalidVars = [];
129
+ for (const [name, exampleValue] of Object.entries(exampleVars)) {
130
+ const currentValue = envVars[name];
131
+ if (currentValue === undefined || currentValue === '') {
132
+ missingVars.push(name);
133
+ }
134
+ else {
135
+ // Validate type
136
+ const expectedType = inferEnvType(name, exampleValue);
137
+ if (!validateEnvValue(currentValue, expectedType)) {
138
+ invalidVars.push({ name, expectedType });
139
+ }
140
+ }
141
+ }
142
+ // Report missing variables
143
+ if (missingVars.length > 0) {
144
+ results.push({
145
+ name: 'Missing .env Variables',
146
+ status: 'fail',
147
+ message: `${missingVars.length} environment variable(s) missing`,
148
+ details: missingVars.join(', '),
149
+ fix: 'Add the missing variables to your .env file',
150
+ });
151
+ }
152
+ else {
153
+ results.push({
154
+ name: 'Environment Variables',
155
+ status: 'pass',
156
+ message: 'All required environment variables are set',
157
+ });
158
+ }
159
+ // Report invalid type variables
160
+ if (invalidVars.length > 0) {
161
+ results.push({
162
+ name: 'Environment Variable Types',
163
+ status: 'warn',
164
+ message: `${invalidVars.length} variable(s) may have invalid types`,
165
+ details: invalidVars.map(v => `${v.name} (expected: ${v.expectedType})`).join(', '),
166
+ });
167
+ }
168
+ return results;
169
+ }
170
+ /**
171
+ * Generate a .env.missing report file
172
+ */
173
+ export async function generateMissingEnvReport(cwd) {
174
+ const envExamplePath = path.join(cwd, '.env.example');
175
+ const envPath = path.join(cwd, '.env');
176
+ if (!await fs.pathExists(envExamplePath)) {
177
+ return null;
178
+ }
179
+ const exampleContent = await fs.readFile(envExamplePath, 'utf-8');
180
+ const exampleVars = parseEnvFile(exampleContent);
181
+ let envVars = {};
182
+ if (await fs.pathExists(envPath)) {
183
+ const envContent = await fs.readFile(envPath, 'utf-8');
184
+ envVars = parseEnvFile(envContent);
185
+ }
186
+ const missingVars = [];
187
+ for (const name of Object.keys(exampleVars)) {
188
+ if (envVars[name] === undefined || envVars[name] === '') {
189
+ missingVars.push(name);
190
+ }
191
+ }
192
+ if (missingVars.length === 0) {
193
+ return null;
194
+ }
195
+ // Generate report content
196
+ const reportContent = `# Missing Environment Variables Report
197
+ # Generated: ${new Date().toISOString()}
198
+ #
199
+ # The following variables are defined in .env.example but missing from .env:
200
+
201
+ ${missingVars.map(v => `${v}=`).join('\n')}
202
+ `;
203
+ const reportPath = path.join(cwd, '.env.missing');
204
+ await fs.writeFile(reportPath, reportContent, 'utf-8');
205
+ return reportPath;
206
+ }
207
+ //# sourceMappingURL=check-env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-env.js","sourceRoot":"","sources":["../../../src/utils/doctor/check-env.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * ESLint and TypeScript compilation checks
3
+ */
4
+ import type { CheckResult } from './types.js';
5
+ /**
6
+ * Run all lint checks
7
+ */
8
+ export declare function runLintChecks(cwd: string): Promise<CheckResult[]>;
@@ -0,0 +1,225 @@
1
+ /**
2
+ * ESLint and TypeScript compilation checks
3
+ */
4
+ import { execSync } from 'child_process';
5
+ import fs from 'fs-extra';
6
+ import path from 'path';
7
+ /**
8
+ * Check if ESLint is configured in the project
9
+ */
10
+ async function hasEslintConfig(cwd) {
11
+ const eslintFiles = [
12
+ '.eslintrc',
13
+ '.eslintrc.js',
14
+ '.eslintrc.cjs',
15
+ '.eslintrc.json',
16
+ '.eslintrc.yml',
17
+ '.eslintrc.yaml',
18
+ 'eslint.config.js',
19
+ 'eslint.config.mjs',
20
+ 'eslint.config.cjs',
21
+ ];
22
+ for (const file of eslintFiles) {
23
+ if (await fs.pathExists(path.join(cwd, file))) {
24
+ return true;
25
+ }
26
+ }
27
+ // Check package.json for eslintConfig
28
+ const pkgPath = path.join(cwd, 'package.json');
29
+ if (await fs.pathExists(pkgPath)) {
30
+ try {
31
+ const pkg = await fs.readJson(pkgPath);
32
+ if (pkg.eslintConfig)
33
+ return true;
34
+ }
35
+ catch {
36
+ // Ignore JSON parse errors
37
+ }
38
+ }
39
+ return false;
40
+ }
41
+ /**
42
+ * Check if TypeScript is configured in the project
43
+ */
44
+ async function hasTypescriptConfig(cwd) {
45
+ return await fs.pathExists(path.join(cwd, 'tsconfig.json'));
46
+ }
47
+ /**
48
+ * Run ESLint and return results
49
+ */
50
+ async function runEslint(cwd) {
51
+ if (!await hasEslintConfig(cwd)) {
52
+ return {
53
+ name: 'ESLint',
54
+ status: 'skip',
55
+ message: 'No ESLint configuration found',
56
+ };
57
+ }
58
+ try {
59
+ // Check if ESLint is installed
60
+ const eslintPath = path.join(cwd, 'node_modules', '.bin', 'eslint');
61
+ if (!await fs.pathExists(eslintPath) && !await fs.pathExists(eslintPath + '.cmd')) {
62
+ return {
63
+ name: 'ESLint',
64
+ status: 'warn',
65
+ message: 'ESLint is not installed',
66
+ fix: 'Run: npm install eslint --save-dev',
67
+ };
68
+ }
69
+ // Run ESLint with JSON output
70
+ const output = execSync('npx eslint . --format json --max-warnings 0', {
71
+ cwd,
72
+ encoding: 'utf-8',
73
+ stdio: ['pipe', 'pipe', 'pipe'],
74
+ timeout: 60000,
75
+ });
76
+ try {
77
+ const results = JSON.parse(output);
78
+ let errorCount = 0;
79
+ let warningCount = 0;
80
+ for (const file of results) {
81
+ errorCount += file.errorCount || 0;
82
+ warningCount += file.warningCount || 0;
83
+ }
84
+ if (errorCount > 0) {
85
+ return {
86
+ name: 'ESLint',
87
+ status: 'fail',
88
+ message: `${errorCount} error(s), ${warningCount} warning(s)`,
89
+ fix: 'Run: npx eslint . --fix',
90
+ };
91
+ }
92
+ if (warningCount > 0) {
93
+ return {
94
+ name: 'ESLint',
95
+ status: 'warn',
96
+ message: `${warningCount} warning(s)`,
97
+ fix: 'Run: npx eslint . --fix',
98
+ };
99
+ }
100
+ return {
101
+ name: 'ESLint',
102
+ status: 'pass',
103
+ message: 'No linting issues found',
104
+ };
105
+ }
106
+ catch {
107
+ // JSON parse failed, but command succeeded
108
+ return {
109
+ name: 'ESLint',
110
+ status: 'pass',
111
+ message: 'No linting issues found',
112
+ };
113
+ }
114
+ }
115
+ catch (error) {
116
+ const errorOutput = error instanceof Error ? error.message : String(error);
117
+ // Try to parse error output as JSON
118
+ try {
119
+ const jsonMatch = errorOutput.match(/\[[\s\S]*\]/);
120
+ if (jsonMatch) {
121
+ const results = JSON.parse(jsonMatch[0]);
122
+ let errorCount = 0;
123
+ let warningCount = 0;
124
+ for (const file of results) {
125
+ errorCount += file.errorCount || 0;
126
+ warningCount += file.warningCount || 0;
127
+ }
128
+ if (errorCount > 0 || warningCount > 0) {
129
+ return {
130
+ name: 'ESLint',
131
+ status: errorCount > 0 ? 'fail' : 'warn',
132
+ message: `${errorCount} error(s), ${warningCount} warning(s)`,
133
+ fix: 'Run: npx eslint . --fix',
134
+ };
135
+ }
136
+ }
137
+ }
138
+ catch {
139
+ // JSON parse failed
140
+ }
141
+ // Check for common error patterns
142
+ if (errorOutput.includes('error') || errorOutput.includes('Error')) {
143
+ return {
144
+ name: 'ESLint',
145
+ status: 'fail',
146
+ message: 'ESLint found issues',
147
+ details: errorOutput.substring(0, 200),
148
+ fix: 'Run: npx eslint . --fix',
149
+ };
150
+ }
151
+ return {
152
+ name: 'ESLint',
153
+ status: 'fail',
154
+ message: 'ESLint check failed',
155
+ details: errorOutput.substring(0, 200),
156
+ };
157
+ }
158
+ }
159
+ /**
160
+ * Run TypeScript compiler check
161
+ */
162
+ async function runTypecheck(cwd) {
163
+ if (!await hasTypescriptConfig(cwd)) {
164
+ return {
165
+ name: 'TypeScript',
166
+ status: 'skip',
167
+ message: 'No tsconfig.json found',
168
+ };
169
+ }
170
+ try {
171
+ // Check if TypeScript is installed
172
+ const tscPath = path.join(cwd, 'node_modules', '.bin', 'tsc');
173
+ if (!await fs.pathExists(tscPath) && !await fs.pathExists(tscPath + '.cmd')) {
174
+ return {
175
+ name: 'TypeScript',
176
+ status: 'warn',
177
+ message: 'TypeScript is not installed',
178
+ fix: 'Run: npm install typescript --save-dev',
179
+ };
180
+ }
181
+ // Run tsc --noEmit
182
+ execSync('npx tsc --noEmit', {
183
+ cwd,
184
+ encoding: 'utf-8',
185
+ stdio: ['pipe', 'pipe', 'pipe'],
186
+ timeout: 120000,
187
+ });
188
+ return {
189
+ name: 'TypeScript',
190
+ status: 'pass',
191
+ message: 'No type errors found',
192
+ };
193
+ }
194
+ catch (error) {
195
+ const errorOutput = error instanceof Error ? error.message : String(error);
196
+ // Count errors
197
+ const errorMatches = errorOutput.match(/error TS\d+/g);
198
+ const errorCount = errorMatches ? errorMatches.length : 0;
199
+ if (errorCount > 0) {
200
+ return {
201
+ name: 'TypeScript',
202
+ status: 'fail',
203
+ message: `${errorCount} type error(s) found`,
204
+ details: errorOutput.split('\n').slice(0, 5).join('\n'),
205
+ fix: 'Fix the type errors in your TypeScript files',
206
+ };
207
+ }
208
+ return {
209
+ name: 'TypeScript',
210
+ status: 'fail',
211
+ message: 'TypeScript compilation failed',
212
+ details: errorOutput.substring(0, 200),
213
+ };
214
+ }
215
+ }
216
+ /**
217
+ * Run all lint checks
218
+ */
219
+ export async function runLintChecks(cwd) {
220
+ const results = [];
221
+ results.push(await runEslint(cwd));
222
+ results.push(await runTypecheck(cwd));
223
+ return results;
224
+ }
225
+ //# sourceMappingURL=check-lint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-lint.js","sourceRoot":"","sources":["../../../src/utils/doctor/check-lint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Node.js and package manager version checks
3
+ */
4
+ import type { CheckResult } from './types.js';
5
+ /**
6
+ * Check Node.js version
7
+ */
8
+ export declare function checkNodeVersion(cwd: string): Promise<CheckResult>;
9
+ /**
10
+ * Check npm version
11
+ */
12
+ export declare function checkNpmVersion(): Promise<CheckResult>;
13
+ /**
14
+ * Check pnpm installation (optional)
15
+ */
16
+ export declare function checkPnpmVersion(): Promise<CheckResult>;
17
+ /**
18
+ * Run all Node/package manager checks
19
+ */
20
+ export declare function runNodeChecks(cwd: string): Promise<CheckResult[]>;
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Node.js and package manager version checks
3
+ */
4
+ import { execSync } from 'child_process';
5
+ import fs from 'fs-extra';
6
+ import path from 'path';
7
+ /**
8
+ * Parse semantic version string
9
+ */
10
+ function parseVersion(version) {
11
+ const match = version.match(/(\d+)\.(\d+)\.(\d+)/);
12
+ if (!match)
13
+ return null;
14
+ return {
15
+ major: parseInt(match[1], 10),
16
+ minor: parseInt(match[2], 10),
17
+ patch: parseInt(match[3], 10),
18
+ };
19
+ }
20
+ /**
21
+ * Compare two versions, returns: -1 if a < b, 0 if equal, 1 if a > b
22
+ */
23
+ function compareVersions(a, b) {
24
+ const va = parseVersion(a);
25
+ const vb = parseVersion(b);
26
+ if (!va || !vb)
27
+ return 0;
28
+ if (va.major !== vb.major)
29
+ return va.major - vb.major;
30
+ if (va.minor !== vb.minor)
31
+ return va.minor - vb.minor;
32
+ return va.patch - vb.patch;
33
+ }
34
+ /**
35
+ * Get the required Node version from project config
36
+ */
37
+ async function getRequiredNodeVersion(cwd) {
38
+ // Check .nvmrc first
39
+ const nvmrcPath = path.join(cwd, '.nvmrc');
40
+ if (await fs.pathExists(nvmrcPath)) {
41
+ const content = await fs.readFile(nvmrcPath, 'utf-8');
42
+ return content.trim().replace(/^v/, '');
43
+ }
44
+ // Check package.json engines
45
+ const pkgPath = path.join(cwd, 'package.json');
46
+ if (await fs.pathExists(pkgPath)) {
47
+ try {
48
+ const pkg = await fs.readJson(pkgPath);
49
+ if (pkg.engines?.node) {
50
+ // Parse engine string like ">=18" or "^20.0.0"
51
+ const match = pkg.engines.node.match(/\d+(\.\d+)?(\.\d+)?/);
52
+ return match ? match[0] : null;
53
+ }
54
+ }
55
+ catch {
56
+ // Ignore JSON parse errors
57
+ }
58
+ }
59
+ return null;
60
+ }
61
+ /**
62
+ * Execute command and return output, or null on failure
63
+ */
64
+ function execCommand(command) {
65
+ try {
66
+ return execSync(command, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
67
+ }
68
+ catch {
69
+ return null;
70
+ }
71
+ }
72
+ /**
73
+ * Check Node.js version
74
+ */
75
+ export async function checkNodeVersion(cwd) {
76
+ const nodeVersion = execCommand('node --version');
77
+ if (!nodeVersion) {
78
+ return {
79
+ name: 'Node.js',
80
+ status: 'fail',
81
+ message: 'Node.js is not installed',
82
+ fix: 'Install Node.js from https://nodejs.org/',
83
+ };
84
+ }
85
+ const version = nodeVersion.replace(/^v/, '');
86
+ const requiredVersion = await getRequiredNodeVersion(cwd);
87
+ if (requiredVersion) {
88
+ const comparison = compareVersions(version, requiredVersion);
89
+ if (comparison < 0) {
90
+ return {
91
+ name: 'Node.js',
92
+ status: 'fail',
93
+ message: `Node version ${version} is below required ${requiredVersion}`,
94
+ fix: `Update Node.js to version ${requiredVersion} or higher`,
95
+ };
96
+ }
97
+ }
98
+ // Minimum supported version is 18
99
+ const parsed = parseVersion(version);
100
+ if (parsed && parsed.major < 18) {
101
+ return {
102
+ name: 'Node.js',
103
+ status: 'fail',
104
+ message: `Node version ${version} is too old (minimum: 18.x)`,
105
+ fix: 'Update Node.js to version 18 or higher',
106
+ };
107
+ }
108
+ return {
109
+ name: 'Node.js',
110
+ status: 'pass',
111
+ message: `Node version: ${version}`,
112
+ details: requiredVersion ? `Required: >=${requiredVersion}` : undefined,
113
+ };
114
+ }
115
+ /**
116
+ * Check npm version
117
+ */
118
+ export async function checkNpmVersion() {
119
+ const npmVersion = execCommand('npm --version');
120
+ if (!npmVersion) {
121
+ return {
122
+ name: 'npm',
123
+ status: 'fail',
124
+ message: 'npm is not installed',
125
+ fix: 'npm should be installed with Node.js. Try reinstalling Node.js.',
126
+ };
127
+ }
128
+ const parsed = parseVersion(npmVersion);
129
+ if (parsed && parsed.major < 8) {
130
+ return {
131
+ name: 'npm',
132
+ status: 'warn',
133
+ message: `npm version ${npmVersion} is outdated`,
134
+ fix: 'Run: npm install -g npm@latest',
135
+ };
136
+ }
137
+ return {
138
+ name: 'npm',
139
+ status: 'pass',
140
+ message: `npm version: ${npmVersion}`,
141
+ };
142
+ }
143
+ /**
144
+ * Check pnpm installation (optional)
145
+ */
146
+ export async function checkPnpmVersion() {
147
+ const pnpmVersion = execCommand('pnpm --version');
148
+ if (!pnpmVersion) {
149
+ return {
150
+ name: 'pnpm',
151
+ status: 'skip',
152
+ message: 'pnpm is not installed (optional)',
153
+ details: 'pnpm is an alternative package manager',
154
+ };
155
+ }
156
+ return {
157
+ name: 'pnpm',
158
+ status: 'pass',
159
+ message: `pnpm version: ${pnpmVersion}`,
160
+ };
161
+ }
162
+ /**
163
+ * Run all Node/package manager checks
164
+ */
165
+ export async function runNodeChecks(cwd) {
166
+ const results = [];
167
+ results.push(await checkNodeVersion(cwd));
168
+ results.push(await checkNpmVersion());
169
+ results.push(await checkPnpmVersion());
170
+ return results;
171
+ }
172
+ //# sourceMappingURL=check-node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-node.js","sourceRoot":"","sources":["../../../src/utils/doctor/check-node.ts"],"names":[],"mappings":"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"}