@jatinmourya/ng-init 1.0.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,333 @@
1
+ import semver from 'semver';
2
+ import chalk from 'chalk';
3
+
4
+ /**
5
+ * Check if current Node version is compatible with Angular version
6
+ */
7
+ export function checkNodeCompatibility(currentNodeVersion, requiredNodeVersion) {
8
+ try {
9
+ const isCompatible = semver.satisfies(currentNodeVersion, requiredNodeVersion);
10
+ return {
11
+ compatible: isCompatible,
12
+ current: currentNodeVersion,
13
+ required: requiredNodeVersion
14
+ };
15
+ } catch (error) {
16
+ return {
17
+ compatible: false,
18
+ current: currentNodeVersion,
19
+ required: requiredNodeVersion,
20
+ error: error.message
21
+ };
22
+ }
23
+ }
24
+
25
+ /**
26
+ * Display compatibility status
27
+ */
28
+ export function displayCompatibilityStatus(compatibility) {
29
+ console.log(chalk.bold.cyan('\nšŸ“‹ Compatibility Check\n'));
30
+ console.log(chalk.gray('━'.repeat(50)));
31
+
32
+ console.log(chalk.white('Current Node.js: ') + chalk.cyan(`v${compatibility.current}`));
33
+ console.log(chalk.white('Required Node.js: ') + chalk.cyan(compatibility.required));
34
+
35
+ if (compatibility.compatible) {
36
+ console.log(chalk.white('Status: ') + chalk.green('āœ“ Compatible'));
37
+ } else {
38
+ console.log(chalk.white('Status: ') + chalk.red('āœ— Incompatible'));
39
+ }
40
+
41
+ console.log(chalk.gray('━'.repeat(50)) + '\n');
42
+
43
+ return compatibility.compatible;
44
+ }
45
+
46
+ /**
47
+ * Find compatible Node versions from available versions
48
+ */
49
+ export function findCompatibleVersions(availableVersions, requiredRange) {
50
+ try {
51
+ return availableVersions.filter(version => {
52
+ try {
53
+ return semver.satisfies(version, requiredRange);
54
+ } catch {
55
+ return false;
56
+ }
57
+ }).sort((a, b) => semver.rcompare(a, b)); // Sort descending (newest first)
58
+ } catch (error) {
59
+ return [];
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Get recommended Node version from range
65
+ */
66
+ export function getRecommendedNodeVersion(requiredRange) {
67
+ // Parse the range to get recommended version
68
+ try {
69
+ const ranges = requiredRange.split('||').map(r => r.trim());
70
+
71
+ // Try to extract version numbers
72
+ for (const range of ranges) {
73
+ const match = range.match(/(\d+)\./);
74
+ if (match) {
75
+ const major = parseInt(match[1]);
76
+ // Recommend LTS versions
77
+ if (major === 20) return '20.11.0';
78
+ if (major === 18) return '18.19.0';
79
+ if (major === 16) return '16.20.2';
80
+ if (major === 14) return '14.21.3';
81
+ }
82
+ }
83
+
84
+ return '18.19.0'; // Default to Node 18 LTS
85
+ } catch (error) {
86
+ return '18.19.0';
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Angular version to Node.js compatibility matrix
92
+ */
93
+ export const ANGULAR_NODE_COMPATIBILITY = {
94
+ '18': '^18.19.1 || ^20.11.1 || ^22.0.0',
95
+ '17': '^18.13.0 || ^20.9.0',
96
+ '16': '^16.14.0 || ^18.10.0',
97
+ '15': '^14.20.0 || ^16.13.0 || ^18.10.0',
98
+ '14': '^14.15.0 || ^16.10.0',
99
+ '13': '^12.20.0 || ^14.15.0 || ^16.10.0',
100
+ '12': '^12.20.0 || ^14.15.0',
101
+ '11': '^10.13.0 || ^12.11.0',
102
+ '10': '^10.13.0 || ^12.11.0'
103
+ };
104
+
105
+ /**
106
+ * Get Node requirement from compatibility matrix
107
+ */
108
+ export function getNodeRequirementFromMatrix(angularVersion) {
109
+ const majorVersion = angularVersion.split('.')[0];
110
+ return ANGULAR_NODE_COMPATIBILITY[majorVersion] || '^18.13.0 || ^20.9.0';
111
+ }
112
+
113
+ /**
114
+ * Validate Angular version format
115
+ */
116
+ export function isValidAngularVersion(version) {
117
+ return semver.valid(version) !== null;
118
+ }
119
+
120
+ /**
121
+ * Check if Angular CLI is installed globally
122
+ */
123
+ export function needsAngularCli(currentAngularCliVersion, targetAngularVersion) {
124
+ if (!currentAngularCliVersion) {
125
+ return {
126
+ needed: true,
127
+ reason: 'Angular CLI is not installed'
128
+ };
129
+ }
130
+
131
+ const currentMajor = parseInt(currentAngularCliVersion.split('.')[0]);
132
+ const targetMajor = parseInt(targetAngularVersion.split('.')[0]);
133
+
134
+ if (currentMajor !== targetMajor) {
135
+ return {
136
+ needed: true,
137
+ reason: `Angular CLI version mismatch (current: ${currentMajor}, target: ${targetMajor})`,
138
+ suggestion: `Consider using npx @angular/cli@${targetAngularVersion} instead`
139
+ };
140
+ }
141
+
142
+ return {
143
+ needed: false,
144
+ reason: 'Angular CLI version is compatible'
145
+ };
146
+ }
147
+
148
+ /**
149
+ * Library compatibility matrix for Angular versions
150
+ * Maps popular libraries to compatible versions based on Angular major version
151
+ */
152
+ export const LIBRARY_COMPATIBILITY_MATRIX = {
153
+ '@angular/material': {
154
+ '18': '^18.0.0',
155
+ '17': '^17.0.0',
156
+ '16': '^16.0.0',
157
+ '15': '^15.0.0',
158
+ '14': '^14.0.0',
159
+ '13': '^13.0.0',
160
+ '12': '^12.0.0'
161
+ },
162
+ '@angular/cdk': {
163
+ '18': '^18.0.0',
164
+ '17': '^17.0.0',
165
+ '16': '^16.0.0',
166
+ '15': '^15.0.0',
167
+ '14': '^14.0.0',
168
+ '13': '^13.0.0',
169
+ '12': '^12.0.0'
170
+ },
171
+ '@ng-bootstrap/ng-bootstrap': {
172
+ '18': '^17.0.0',
173
+ '17': '^16.0.0',
174
+ '16': '^14.0.0',
175
+ '15': '^13.0.0',
176
+ '14': '^12.0.0',
177
+ '13': '^10.0.0',
178
+ '12': '^10.0.0'
179
+ },
180
+ '@ngrx/store': {
181
+ '18': '^18.0.0',
182
+ '17': '^17.0.0',
183
+ '16': '^16.0.0',
184
+ '15': '^15.0.0',
185
+ '14': '^14.0.0',
186
+ '13': '^13.0.0',
187
+ '12': '^12.0.0'
188
+ },
189
+ '@ngrx/effects': {
190
+ '18': '^18.0.0',
191
+ '17': '^17.0.0',
192
+ '16': '^16.0.0',
193
+ '15': '^15.0.0',
194
+ '14': '^14.0.0',
195
+ '13': '^13.0.0',
196
+ '12': '^12.0.0'
197
+ },
198
+ '@ngrx/entity': {
199
+ '18': '^18.0.0',
200
+ '17': '^17.0.0',
201
+ '16': '^16.0.0',
202
+ '15': '^15.0.0',
203
+ '14': '^14.0.0',
204
+ '13': '^13.0.0',
205
+ '12': '^12.0.0'
206
+ },
207
+ '@ngrx/store-devtools': {
208
+ '18': '^18.0.0',
209
+ '17': '^17.0.0',
210
+ '16': '^16.0.0',
211
+ '15': '^15.0.0',
212
+ '14': '^14.0.0',
213
+ '13': '^13.0.0',
214
+ '12': '^12.0.0'
215
+ },
216
+ '@angular/pwa': {
217
+ '18': '^18.0.0',
218
+ '17': '^17.0.0',
219
+ '16': '^16.0.0',
220
+ '15': '^15.0.0',
221
+ '14': '^14.0.0',
222
+ '13': '^13.0.0',
223
+ '12': '^12.0.0'
224
+ },
225
+ '@angular/service-worker': {
226
+ '18': '^18.0.0',
227
+ '17': '^17.0.0',
228
+ '16': '^16.0.0',
229
+ '15': '^15.0.0',
230
+ '14': '^14.0.0',
231
+ '13': '^13.0.0',
232
+ '12': '^12.0.0'
233
+ },
234
+ '@angular/fire': {
235
+ '18': '^18.0.0',
236
+ '17': '^17.0.0',
237
+ '16': '^7.6.0',
238
+ '15': '^7.5.0',
239
+ '14': '^7.4.0',
240
+ '13': '^7.2.0',
241
+ '12': '^7.0.0'
242
+ }
243
+ };
244
+
245
+ /**
246
+ * Get compatible version for a library based on Angular version
247
+ */
248
+ export function getCompatibleLibraryVersion(libraryName, angularVersion) {
249
+ const angularMajor = angularVersion.split('.')[0];
250
+
251
+ // Check if library is in compatibility matrix
252
+ if (LIBRARY_COMPATIBILITY_MATRIX[libraryName]) {
253
+ const compatibleVersion = LIBRARY_COMPATIBILITY_MATRIX[libraryName][angularMajor];
254
+ if (compatibleVersion) {
255
+ return compatibleVersion;
256
+ }
257
+ }
258
+
259
+ // For Angular-scoped packages not in matrix, try to match version
260
+ if (libraryName.startsWith('@angular/')) {
261
+ return `^${angularMajor}.0.0`;
262
+ }
263
+
264
+ // Default to latest for other packages
265
+ return 'latest';
266
+ }
267
+
268
+ /**
269
+ * Resolve library versions for compatibility with Angular
270
+ */
271
+ export function resolveLibraryVersions(libraries, angularVersion) {
272
+ return libraries.map(lib => {
273
+ const requestedVersion = lib.version || 'latest';
274
+
275
+ // If version is 'latest', try to find compatible version
276
+ if (requestedVersion === 'latest') {
277
+ const compatibleVersion = getCompatibleLibraryVersion(lib.name, angularVersion);
278
+ return {
279
+ ...lib,
280
+ version: compatibleVersion,
281
+ originalVersion: requestedVersion,
282
+ adjusted: compatibleVersion !== 'latest'
283
+ };
284
+ }
285
+
286
+ // If a specific version is requested, keep it but flag potential incompatibility
287
+ return {
288
+ ...lib,
289
+ adjusted: false
290
+ };
291
+ });
292
+ }
293
+
294
+ /**
295
+ * Check if a library version is compatible with Angular version using semver
296
+ */
297
+ export function checkLibraryCompatibility(peerDependency, angularVersion) {
298
+ if (!peerDependency || peerDependency === 'No Angular peer dependency') {
299
+ return { compatible: true, reason: 'No Angular peer dependency specified' };
300
+ }
301
+
302
+ try {
303
+ const angularMajor = angularVersion.split('.')[0];
304
+
305
+ // Check if the peer dependency includes the Angular major version
306
+ const patterns = [
307
+ `^${angularMajor}.`,
308
+ `~${angularMajor}.`,
309
+ `>=${angularMajor}.`,
310
+ `${angularMajor}.x`,
311
+ `${angularMajor}.0.0`
312
+ ];
313
+
314
+ const isCompatible = patterns.some(pattern => peerDependency.includes(pattern));
315
+
316
+ if (isCompatible) {
317
+ return {
318
+ compatible: true,
319
+ reason: `Peer dependency '${peerDependency}' is compatible with Angular ${angularVersion}`
320
+ };
321
+ } else {
322
+ return {
323
+ compatible: false,
324
+ reason: `Peer dependency requires '${peerDependency}' but Angular ${angularVersion} is being used`
325
+ };
326
+ }
327
+ } catch (error) {
328
+ return {
329
+ compatible: false,
330
+ reason: `Error checking compatibility: ${error.message}`
331
+ };
332
+ }
333
+ }
@@ -0,0 +1,232 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ import chalk from 'chalk';
4
+ import { execa } from 'execa';
5
+ import ora from 'ora';
6
+
7
+ /**
8
+ * Initialize Git repository
9
+ */
10
+ export async function initGitRepo(projectPath) {
11
+ const spinner = ora('Initializing Git repository...').start();
12
+
13
+ try {
14
+ await execa('git', ['init'], { cwd: projectPath });
15
+ spinner.succeed('Git repository initialized');
16
+ return true;
17
+ } catch (error) {
18
+ spinner.fail('Failed to initialize Git repository');
19
+ console.error(chalk.red(error.message));
20
+ return false;
21
+ }
22
+ }
23
+
24
+ /**
25
+ * Create .gitignore file
26
+ */
27
+ export async function createGitignore(projectPath, content) {
28
+ try {
29
+ const gitignorePath = path.join(projectPath, '.gitignore');
30
+ await fs.writeFile(gitignorePath, content, 'utf-8');
31
+ console.log(chalk.green('āœ“ Created .gitignore'));
32
+ return true;
33
+ } catch (error) {
34
+ console.error(chalk.red('Failed to create .gitignore:'), error.message);
35
+ return false;
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Create initial commit
41
+ */
42
+ export async function createInitialCommit(projectPath, message) {
43
+ const spinner = ora('Creating initial commit...').start();
44
+
45
+ try {
46
+ await execa('git', ['add', '.'], { cwd: projectPath });
47
+ await execa('git', ['commit', '-m', message], { cwd: projectPath });
48
+ spinner.succeed('Initial commit created');
49
+ return true;
50
+ } catch (error) {
51
+ spinner.fail('Failed to create initial commit');
52
+ console.error(chalk.red(error.message));
53
+ return false;
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Create project folders
59
+ */
60
+ export async function createProjectFolders(projectPath, folders) {
61
+ const spinner = ora('Creating project structure...').start();
62
+
63
+ try {
64
+ for (const folder of folders) {
65
+ const folderPath = path.join(projectPath, folder);
66
+ await fs.mkdir(folderPath, { recursive: true });
67
+ }
68
+ spinner.succeed('Project structure created');
69
+ return true;
70
+ } catch (error) {
71
+ spinner.fail('Failed to create project structure');
72
+ console.error(chalk.red(error.message));
73
+ return false;
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Create project files
79
+ */
80
+ export async function createProjectFiles(projectPath, files) {
81
+ try {
82
+ for (const [filePath, content] of Object.entries(files)) {
83
+ const fullPath = path.join(projectPath, filePath);
84
+ const dir = path.dirname(fullPath);
85
+
86
+ // Ensure directory exists
87
+ await fs.mkdir(dir, { recursive: true });
88
+
89
+ // Write file
90
+ const fileContent = typeof content === 'string' ? content : JSON.stringify(content, null, 2);
91
+ await fs.writeFile(fullPath, fileContent, 'utf-8');
92
+ }
93
+ console.log(chalk.green(`āœ“ Created ${Object.keys(files).length} file(s)`));
94
+ return true;
95
+ } catch (error) {
96
+ console.error(chalk.red('Failed to create project files:'), error.message);
97
+ return false;
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Create README.md
103
+ */
104
+ export async function createReadme(projectPath, content) {
105
+ try {
106
+ const readmePath = path.join(projectPath, 'README.md');
107
+ await fs.writeFile(readmePath, content, 'utf-8');
108
+ console.log(chalk.green('āœ“ Created README.md'));
109
+ return true;
110
+ } catch (error) {
111
+ console.error(chalk.red('Failed to create README.md:'), error.message);
112
+ return false;
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Create CHANGELOG.md
118
+ */
119
+ export async function createChangelog(projectPath, content) {
120
+ try {
121
+ const changelogPath = path.join(projectPath, 'CHANGELOG.md');
122
+ await fs.writeFile(changelogPath, content, 'utf-8');
123
+ console.log(chalk.green('āœ“ Created CHANGELOG.md'));
124
+ return true;
125
+ } catch (error) {
126
+ console.error(chalk.red('Failed to create CHANGELOG.md:'), error.message);
127
+ return false;
128
+ }
129
+ }
130
+
131
+ /**
132
+ * Check if directory exists and is empty
133
+ */
134
+ export async function isDirectoryEmpty(dirPath) {
135
+ try {
136
+ const files = await fs.readdir(dirPath);
137
+ return files.length === 0;
138
+ } catch (error) {
139
+ // Directory doesn't exist
140
+ return true;
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Create directory if it doesn't exist
146
+ */
147
+ export async function ensureDirectory(dirPath) {
148
+ try {
149
+ await fs.mkdir(dirPath, { recursive: true });
150
+ return true;
151
+ } catch (error) {
152
+ console.error(chalk.red('Failed to create directory:'), error.message);
153
+ return false;
154
+ }
155
+ }
156
+
157
+ /**
158
+ * Validate directory name
159
+ */
160
+ export function validateDirectoryName(name) {
161
+ // Check for invalid characters
162
+ const invalidChars = /[<>:"|?*\x00-\x1f]/;
163
+ if (invalidChars.test(name)) {
164
+ return 'Directory name contains invalid characters';
165
+ }
166
+
167
+ // Check for reserved names (Windows)
168
+ const reserved = ['CON', 'PRN', 'AUX', 'NUL', 'COM1', 'COM2', 'COM3', 'COM4', 'COM5', 'COM6', 'COM7', 'COM8', 'COM9', 'LPT1', 'LPT2', 'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9'];
169
+ if (reserved.includes(name.toUpperCase())) {
170
+ return 'Directory name is reserved';
171
+ }
172
+
173
+ // Check for valid length
174
+ if (name.length === 0) {
175
+ return 'Directory name cannot be empty';
176
+ }
177
+
178
+ if (name.length > 255) {
179
+ return 'Directory name is too long';
180
+ }
181
+
182
+ return true;
183
+ }
184
+
185
+ /**
186
+ * Update package.json scripts
187
+ */
188
+ export async function updatePackageJsonScripts(projectPath, scripts) {
189
+ try {
190
+ const packageJsonPath = path.join(projectPath, 'package.json');
191
+ const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf-8'));
192
+
193
+ packageJson.scripts = {
194
+ ...packageJson.scripts,
195
+ ...scripts
196
+ };
197
+
198
+ await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2), 'utf-8');
199
+ console.log(chalk.green('āœ“ Updated package.json scripts'));
200
+ return true;
201
+ } catch (error) {
202
+ console.error(chalk.red('Failed to update package.json:'), error.message);
203
+ return false;
204
+ }
205
+ }
206
+
207
+ /**
208
+ * Read package.json
209
+ */
210
+ export async function readPackageJson(projectPath) {
211
+ try {
212
+ const packageJsonPath = path.join(projectPath, 'package.json');
213
+ const content = await fs.readFile(packageJsonPath, 'utf-8');
214
+ return JSON.parse(content);
215
+ } catch (error) {
216
+ return null;
217
+ }
218
+ }
219
+
220
+ /**
221
+ * Write package.json
222
+ */
223
+ export async function writePackageJson(projectPath, content) {
224
+ try {
225
+ const packageJsonPath = path.join(projectPath, 'package.json');
226
+ await fs.writeFile(packageJsonPath, JSON.stringify(content, null, 2), 'utf-8');
227
+ return true;
228
+ } catch (error) {
229
+ console.error(chalk.red('Failed to write package.json:'), error.message);
230
+ return false;
231
+ }
232
+ }