@monodog/utils 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.
package/helpers.d.ts ADDED
@@ -0,0 +1,87 @@
1
+ export interface PackageInfo {
2
+ name: string;
3
+ version: string;
4
+ type: string;
5
+ path: string;
6
+ dependencies: Record<string, string>;
7
+ devDependencies: Record<string, string>;
8
+ peerDependencies: Record<string, string>;
9
+ scripts: Record<string, string>;
10
+ maintainers: string[];
11
+ description?: string;
12
+ license?: string;
13
+ repository?: Record<string, string>;
14
+ }
15
+ export interface DependencyInfo {
16
+ name: string;
17
+ version: string;
18
+ type: 'dependency' | 'devDependency' | 'peerDependency';
19
+ latest?: string;
20
+ status?: 'up-to-date' | 'outdated' | 'major-update' | 'unknown';
21
+ outdated?: boolean;
22
+ }
23
+ export interface PackageHealth {
24
+ buildStatus: 'success' | 'failed' | 'running' | 'unknown';
25
+ testCoverage: number;
26
+ lintStatus: 'pass' | 'fail' | 'unknown';
27
+ securityAudit: 'pass' | 'fail' | 'unknown';
28
+ overallScore: number;
29
+ }
30
+ export interface MonorepoStats {
31
+ totalPackages: number;
32
+ apps: number;
33
+ libraries: number;
34
+ tools: number;
35
+ healthyPackages: number;
36
+ warningPackages: number;
37
+ errorPackages: number;
38
+ outdatedDependencies: number;
39
+ totalDependencies: number;
40
+ }
41
+ /**
42
+ * Scans the monorepo and returns information about all packages
43
+ */
44
+ declare function scanMonorepo(rootDir: string): PackageInfo[];
45
+ /**
46
+ * Analyzes dependencies and determines their status
47
+ */
48
+ /**
49
+ * Calculates package health score based on various metrics
50
+ */
51
+ declare function calculatePackageHealth(buildStatus: PackageHealth['buildStatus'], testCoverage: number, lintStatus: PackageHealth['lintStatus'], securityAudit: PackageHealth['securityAudit']): PackageHealth;
52
+ /**
53
+ * Generates comprehensive monorepo statistics
54
+ */
55
+ declare function generateMonorepoStats(packages: PackageInfo[]): MonorepoStats;
56
+ /**
57
+ * Finds circular dependencies in the monorepo
58
+ */
59
+ declare function findCircularDependencies(packages: PackageInfo[]): string[][];
60
+ /**
61
+ * Generates a dependency graph for visualization
62
+ */
63
+ declare function generateDependencyGraph(packages: PackageInfo[]): {
64
+ nodes: {
65
+ label: string;
66
+ type: string;
67
+ version: string;
68
+ dependencies: number;
69
+ }[];
70
+ edges: {
71
+ from: string;
72
+ to: string;
73
+ type: string;
74
+ }[];
75
+ };
76
+ /**
77
+ * Checks if a package has outdated dependencies
78
+ */
79
+ declare function checkOutdatedDependencies(packageInfo: PackageInfo): DependencyInfo[];
80
+ /**
81
+ * Gets package size information
82
+ */
83
+ declare function getPackageSize(packagePath: string): {
84
+ size: number;
85
+ files: number;
86
+ };
87
+ export { scanMonorepo, generateMonorepoStats, findCircularDependencies, generateDependencyGraph, checkOutdatedDependencies, getPackageSize, calculatePackageHealth, };
package/helpers.js ADDED
@@ -0,0 +1,333 @@
1
+ // import { Package } from '@prisma/client';
2
+ import * as fs from 'fs';
3
+ import path from 'path';
4
+ /**
5
+ * Scans the monorepo and returns information about all packages
6
+ */
7
+ function scanMonorepo(rootDir) {
8
+ const packages = [];
9
+ console.log('rootDir', rootDir);
10
+ // Scan packages directory
11
+ const packagesDir = path.join(rootDir, 'packages');
12
+ if (fs.existsSync(packagesDir)) {
13
+ const packageDirs = fs
14
+ .readdirSync(packagesDir, { withFileTypes: true })
15
+ .filter(dirent => dirent.isDirectory())
16
+ .map(dirent => dirent.name);
17
+ for (const packageName of packageDirs) {
18
+ const packagePath = path.join(packagesDir, packageName);
19
+ const packageInfo = parsePackageInfo(packagePath, packageName);
20
+ if (packageInfo) {
21
+ packages.push(packageInfo);
22
+ }
23
+ }
24
+ }
25
+ // Scan apps directory
26
+ const appsDir = path.join(rootDir, 'apps');
27
+ if (fs.existsSync(appsDir)) {
28
+ const appDirs = fs
29
+ .readdirSync(appsDir, { withFileTypes: true })
30
+ .filter(dirent => dirent.isDirectory())
31
+ .map(dirent => dirent.name);
32
+ for (const appName of appDirs) {
33
+ const appPath = path.join(appsDir, appName);
34
+ const appInfo = parsePackageInfo(appPath, appName, 'app');
35
+ if (appInfo) {
36
+ packages.push(appInfo);
37
+ }
38
+ }
39
+ }
40
+ // Scan libs directory
41
+ const libsDir = path.join(rootDir, 'libs');
42
+ if (fs.existsSync(libsDir)) {
43
+ const libDirs = fs
44
+ .readdirSync(libsDir, { withFileTypes: true })
45
+ .filter(dirent => dirent.isDirectory())
46
+ .map(dirent => dirent.name);
47
+ for (const libName of libDirs) {
48
+ const libPath = path.join(libsDir, libName);
49
+ const libInfo = parsePackageInfo(libPath, libName, 'lib');
50
+ if (libInfo) {
51
+ packages.push(libInfo);
52
+ }
53
+ }
54
+ }
55
+ return packages;
56
+ }
57
+ /*** Parses package.json and determines package type */
58
+ function parsePackageInfo(packagePath, packageName, forcedType) {
59
+ const packageJsonPath = path.join(packagePath, 'package.json');
60
+ if (!fs.existsSync(packageJsonPath)) {
61
+ return null;
62
+ }
63
+ try {
64
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
65
+ // Determine package type
66
+ let packageType = 'lib';
67
+ if (forcedType) {
68
+ packageType = forcedType;
69
+ }
70
+ else if (packageJson.scripts && packageJson.scripts.start) {
71
+ packageType = 'app';
72
+ }
73
+ else if (packageJson.keywords && packageJson.keywords.includes('tool')) {
74
+ packageType = 'tool';
75
+ }
76
+ return {
77
+ name: packageJson.name || packageName,
78
+ version: packageJson.version || '0.0.0',
79
+ type: packageType,
80
+ path: packagePath,
81
+ dependencies: packageJson.dependencies || {},
82
+ devDependencies: packageJson.devDependencies || {},
83
+ peerDependencies: packageJson.peerDependencies || {},
84
+ scripts: packageJson.scripts || {},
85
+ maintainers: packageJson.maintainers || [],
86
+ description: packageJson.description,
87
+ license: packageJson.license,
88
+ repository: packageJson.repository || {},
89
+ };
90
+ }
91
+ catch (error) {
92
+ console.error(`Error parsing package.json for ${packageName}:`, error);
93
+ return null;
94
+ }
95
+ }
96
+ /**
97
+ * Analyzes dependencies and determines their status
98
+ */
99
+ // function analyzeDependencies(
100
+ // dependencies: Record<string, string>,
101
+ // type: 'production' | 'development' = 'production'
102
+ // ): DependencyInfo[] {
103
+ // return Object.entries(dependencies).map(([name, version]) => ({
104
+ // name,
105
+ // currentVersion: version,
106
+ // status: 'unknown', // Would be determined by npm registry check
107
+ // type,
108
+ // }));
109
+ // }
110
+ /**
111
+ * Calculates package health score based on various metrics
112
+ */
113
+ function calculatePackageHealth(buildStatus, testCoverage, lintStatus, securityAudit) {
114
+ let score = 0;
115
+ // Build status (30 points)
116
+ switch (buildStatus) {
117
+ case 'success':
118
+ score += 30;
119
+ break;
120
+ case 'running':
121
+ score += 15;
122
+ break;
123
+ case 'failed':
124
+ score += 0;
125
+ break;
126
+ default:
127
+ score += 10;
128
+ }
129
+ // Test coverage (25 points)
130
+ score += Math.min(25, (testCoverage / 100) * 25);
131
+ // Lint status (25 points)
132
+ switch (lintStatus) {
133
+ case 'pass':
134
+ score += 25;
135
+ break;
136
+ case 'fail':
137
+ score += 0;
138
+ break;
139
+ default:
140
+ score += 10;
141
+ }
142
+ // Security audit (20 points)
143
+ switch (securityAudit) {
144
+ case 'pass':
145
+ score += 20;
146
+ break;
147
+ case 'fail':
148
+ score += 0;
149
+ break;
150
+ default:
151
+ score += 10;
152
+ }
153
+ return {
154
+ buildStatus,
155
+ testCoverage,
156
+ lintStatus,
157
+ securityAudit,
158
+ overallScore: Math.round(score),
159
+ };
160
+ }
161
+ /**
162
+ * Generates comprehensive monorepo statistics
163
+ */
164
+ function generateMonorepoStats(packages) {
165
+ const stats = {
166
+ totalPackages: packages.length,
167
+ apps: packages.filter(p => p.type === 'app').length,
168
+ libraries: packages.filter(p => p.type === 'lib').length,
169
+ tools: packages.filter(p => p.type === 'tool').length,
170
+ healthyPackages: 0,
171
+ warningPackages: 0,
172
+ errorPackages: 0,
173
+ outdatedDependencies: 0,
174
+ totalDependencies: 0,
175
+ };
176
+ // Calculate dependency counts
177
+ packages.forEach(pkg => {
178
+ stats.totalDependencies += Object.keys(pkg.dependencies).length;
179
+ stats.totalDependencies += Object.keys(pkg.devDependencies).length;
180
+ stats.totalDependencies += Object.keys(pkg.peerDependencies ?? {}).length;
181
+ });
182
+ return stats;
183
+ }
184
+ /**
185
+ * Finds circular dependencies in the monorepo
186
+ */
187
+ function findCircularDependencies(packages) {
188
+ const graph = new Map();
189
+ const visited = new Set();
190
+ const recursionStack = new Set();
191
+ const circularDeps = [];
192
+ // Build dependency graph
193
+ packages.forEach(pkg => {
194
+ graph.set(pkg.name, Object.keys(pkg.dependencies));
195
+ });
196
+ function dfs(node, path) {
197
+ if (recursionStack.has(node)) {
198
+ const cycleStart = path.indexOf(node);
199
+ circularDeps.push(path.slice(cycleStart));
200
+ return;
201
+ }
202
+ if (visited.has(node)) {
203
+ return;
204
+ }
205
+ visited.add(node);
206
+ recursionStack.add(node);
207
+ path.push(node);
208
+ const dependencies = graph.get(node) || [];
209
+ for (const dep of dependencies) {
210
+ if (graph.has(dep)) {
211
+ dfs(dep, [...path]);
212
+ }
213
+ }
214
+ recursionStack.delete(node);
215
+ }
216
+ for (const node of graph.keys()) {
217
+ if (!visited.has(node)) {
218
+ dfs(node, []);
219
+ }
220
+ }
221
+ return circularDeps;
222
+ }
223
+ /**
224
+ * Generates a dependency graph for visualization
225
+ */
226
+ function generateDependencyGraph(packages) {
227
+ const nodes = packages.map(pkg => ({
228
+ // id: pkg.name,
229
+ label: pkg.name,
230
+ type: pkg.type,
231
+ version: pkg.version,
232
+ dependencies: Object.keys(pkg.dependencies).length,
233
+ }));
234
+ const edges = [];
235
+ packages.forEach(pkg => {
236
+ Object.keys(pkg.dependencies).forEach(depName => {
237
+ // Only include internal dependencies
238
+ if (packages.some(p => p.name === depName)) {
239
+ edges.push({
240
+ from: pkg.name,
241
+ to: depName,
242
+ type: 'internal',
243
+ });
244
+ }
245
+ });
246
+ });
247
+ return { nodes, edges };
248
+ }
249
+ /**
250
+ * Checks if a package has outdated dependencies
251
+ */
252
+ function checkOutdatedDependencies(packageInfo) {
253
+ const outdated = [];
254
+ // This would typically involve checking against npm registry
255
+ // For now, we'll simulate with some basic checks
256
+ Object.entries(packageInfo.dependencies).forEach(([name, version]) => {
257
+ if (version.startsWith('^') || version.startsWith('~')) {
258
+ // Could be outdated, would need registry check
259
+ outdated.push({
260
+ name,
261
+ version: version,
262
+ status: 'unknown',
263
+ type: 'dependency',
264
+ });
265
+ }
266
+ });
267
+ return outdated;
268
+ }
269
+ /**
270
+ * Formats version numbers for comparison
271
+ */
272
+ // function parseVersion(version: string): number[] {
273
+ // return version
274
+ // .replace(/^[^0-9]*/, '')
275
+ // .split('.')
276
+ // .map(Number);
277
+ // }
278
+ /**
279
+ * Compares two version strings
280
+ */
281
+ // function compareVersions(v1: string, v2: string): number {
282
+ // const parsed1 = parseVersion(v1);
283
+ // const parsed2 = parseVersion(v2);
284
+ // for (let i = 0; i < Math.max(parsed1.length, parsed2.length); i++) {
285
+ // const num1 = parsed1[i] || 0;
286
+ // const num2 = parsed2[i] || 0;
287
+ // if (num1 > num2) return 1;
288
+ // if (num1 < num2) return -1;
289
+ // }
290
+ // return 0;
291
+ // }
292
+ /**
293
+ * Gets package size information
294
+ */
295
+ function getPackageSize(packagePath) {
296
+ try {
297
+ let totalSize = 0;
298
+ let fileCount = 0;
299
+ const calculateSize = (dirPath) => {
300
+ const items = fs.readdirSync(dirPath, { withFileTypes: true });
301
+ for (const item of items) {
302
+ const fullPath = path.join(dirPath, item.name);
303
+ if (item.isDirectory()) {
304
+ // Skip node_modules and other build artifacts
305
+ if (!['node_modules', 'dist', 'build', '.git'].includes(item.name)) {
306
+ calculateSize(fullPath);
307
+ }
308
+ }
309
+ else {
310
+ try {
311
+ const stats = fs.statSync(fullPath);
312
+ totalSize += stats.size;
313
+ fileCount++;
314
+ }
315
+ catch (error) {
316
+ // Skip files we can't read
317
+ }
318
+ }
319
+ }
320
+ };
321
+ calculateSize(packagePath);
322
+ return {
323
+ size: totalSize,
324
+ files: fileCount,
325
+ };
326
+ }
327
+ catch (error) {
328
+ return { size: 0, files: 0 };
329
+ }
330
+ }
331
+ export { scanMonorepo, generateMonorepoStats, findCircularDependencies, generateDependencyGraph, checkOutdatedDependencies, getPackageSize,
332
+ // analyzeDependencies,
333
+ calculatePackageHealth, };
package/helpers.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["helpers.ts"],"names":[],"mappings":"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"}
package/helpers.ts ADDED
@@ -0,0 +1,445 @@
1
+ // import { Package } from '@prisma/client';
2
+ import * as fs from 'fs';
3
+ import path from 'path';
4
+
5
+ export interface PackageInfo {
6
+ name: string;
7
+ version: string;
8
+ type: string; //'app' | 'lib' | 'tool';
9
+ path: string;
10
+ dependencies: Record<string, string>;
11
+ devDependencies: Record<string, string>;
12
+ peerDependencies: Record<string, string>;
13
+ scripts: Record<string, string>;
14
+ maintainers: string[];
15
+ description?: string;
16
+ license?: string;
17
+ repository?: Record<string, string>;
18
+ }
19
+
20
+ export interface DependencyInfo {
21
+ // name: string;
22
+ // currentVersion: string;
23
+ // latestVersion?: string;
24
+ // status: 'up-to-date' | 'outdated' | 'major-update' | 'unknown';
25
+ // type: 'production' | 'development';
26
+ name: string;
27
+ version: string;
28
+ type: 'dependency' | 'devDependency' | 'peerDependency';
29
+ latest?: string;
30
+ status?: 'up-to-date' | 'outdated' | 'major-update' | 'unknown';
31
+ outdated?: boolean;
32
+ }
33
+
34
+ export interface PackageHealth {
35
+ buildStatus: 'success' | 'failed' | 'running' | 'unknown';
36
+ testCoverage: number;
37
+ lintStatus: 'pass' | 'fail' | 'unknown';
38
+ securityAudit: 'pass' | 'fail' | 'unknown';
39
+ overallScore: number;
40
+ }
41
+
42
+ export interface MonorepoStats {
43
+ totalPackages: number;
44
+ apps: number;
45
+ libraries: number;
46
+ tools: number;
47
+ healthyPackages: number;
48
+ warningPackages: number;
49
+ errorPackages: number;
50
+ outdatedDependencies: number;
51
+ totalDependencies: number;
52
+ }
53
+
54
+ /**
55
+ * Scans the monorepo and returns information about all packages
56
+ */
57
+ function scanMonorepo(rootDir: string): PackageInfo[] {
58
+ const packages: PackageInfo[] = [];
59
+ console.log('rootDir', rootDir);
60
+ // Scan packages directory
61
+ const packagesDir = path.join(rootDir, 'packages');
62
+ if (fs.existsSync(packagesDir)) {
63
+ const packageDirs = fs
64
+ .readdirSync(packagesDir, { withFileTypes: true })
65
+ .filter(dirent => dirent.isDirectory())
66
+ .map(dirent => dirent.name);
67
+
68
+ for (const packageName of packageDirs) {
69
+ const packagePath = path.join(packagesDir, packageName);
70
+ const packageInfo = parsePackageInfo(packagePath, packageName);
71
+ if (packageInfo) {
72
+ packages.push(packageInfo);
73
+ }
74
+ }
75
+ }
76
+
77
+ // Scan apps directory
78
+ const appsDir = path.join(rootDir, 'apps');
79
+ if (fs.existsSync(appsDir)) {
80
+ const appDirs = fs
81
+ .readdirSync(appsDir, { withFileTypes: true })
82
+ .filter(dirent => dirent.isDirectory())
83
+ .map(dirent => dirent.name);
84
+
85
+ for (const appName of appDirs) {
86
+ const appPath = path.join(appsDir, appName);
87
+ const appInfo = parsePackageInfo(appPath, appName, 'app');
88
+ if (appInfo) {
89
+ packages.push(appInfo);
90
+ }
91
+ }
92
+ }
93
+
94
+ // Scan libs directory
95
+ const libsDir = path.join(rootDir, 'libs');
96
+ if (fs.existsSync(libsDir)) {
97
+ const libDirs = fs
98
+ .readdirSync(libsDir, { withFileTypes: true })
99
+ .filter(dirent => dirent.isDirectory())
100
+ .map(dirent => dirent.name);
101
+
102
+ for (const libName of libDirs) {
103
+ const libPath = path.join(libsDir, libName);
104
+ const libInfo = parsePackageInfo(libPath, libName, 'lib');
105
+ if (libInfo) {
106
+ packages.push(libInfo);
107
+ }
108
+ }
109
+ }
110
+
111
+ return packages;
112
+ }
113
+
114
+ /*** Parses package.json and determines package type */
115
+ function parsePackageInfo(
116
+ packagePath: string,
117
+ packageName: string,
118
+ forcedType?: 'app' | 'lib' | 'tool'
119
+ ): PackageInfo | null {
120
+ const packageJsonPath = path.join(packagePath, 'package.json');
121
+
122
+ if (!fs.existsSync(packageJsonPath)) {
123
+ return null;
124
+ }
125
+
126
+ try {
127
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
128
+
129
+ // Determine package type
130
+ let packageType: 'app' | 'lib' | 'tool' = 'lib';
131
+ if (forcedType) {
132
+ packageType = forcedType;
133
+ } else if (packageJson.scripts && packageJson.scripts.start) {
134
+ packageType = 'app';
135
+ } else if (packageJson.keywords && packageJson.keywords.includes('tool')) {
136
+ packageType = 'tool';
137
+ }
138
+
139
+ return {
140
+ name: packageJson.name || packageName,
141
+ version: packageJson.version || '0.0.0',
142
+ type: packageType,
143
+ path: packagePath,
144
+ dependencies: packageJson.dependencies || {},
145
+ devDependencies: packageJson.devDependencies || {},
146
+ peerDependencies: packageJson.peerDependencies || {},
147
+ scripts: packageJson.scripts || {},
148
+ maintainers: packageJson.maintainers || [],
149
+ description: packageJson.description,
150
+ license: packageJson.license,
151
+ repository: packageJson.repository || {},
152
+ };
153
+ } catch (error) {
154
+ console.error(`Error parsing package.json for ${packageName}:`, error);
155
+ return null;
156
+ }
157
+ }
158
+
159
+ /**
160
+ * Analyzes dependencies and determines their status
161
+ */
162
+ // function analyzeDependencies(
163
+ // dependencies: Record<string, string>,
164
+ // type: 'production' | 'development' = 'production'
165
+ // ): DependencyInfo[] {
166
+ // return Object.entries(dependencies).map(([name, version]) => ({
167
+ // name,
168
+ // currentVersion: version,
169
+ // status: 'unknown', // Would be determined by npm registry check
170
+ // type,
171
+ // }));
172
+ // }
173
+
174
+ /**
175
+ * Calculates package health score based on various metrics
176
+ */
177
+ function calculatePackageHealth(
178
+ buildStatus: PackageHealth['buildStatus'],
179
+ testCoverage: number,
180
+ lintStatus: PackageHealth['lintStatus'],
181
+ securityAudit: PackageHealth['securityAudit']
182
+ ): PackageHealth {
183
+ let score = 0;
184
+
185
+ // Build status (30 points)
186
+ switch (buildStatus) {
187
+ case 'success':
188
+ score += 30;
189
+ break;
190
+ case 'running':
191
+ score += 15;
192
+ break;
193
+ case 'failed':
194
+ score += 0;
195
+ break;
196
+ default:
197
+ score += 10;
198
+ }
199
+
200
+ // Test coverage (25 points)
201
+ score += Math.min(25, (testCoverage / 100) * 25);
202
+
203
+ // Lint status (25 points)
204
+ switch (lintStatus) {
205
+ case 'pass':
206
+ score += 25;
207
+ break;
208
+ case 'fail':
209
+ score += 0;
210
+ break;
211
+ default:
212
+ score += 10;
213
+ }
214
+
215
+ // Security audit (20 points)
216
+ switch (securityAudit) {
217
+ case 'pass':
218
+ score += 20;
219
+ break;
220
+ case 'fail':
221
+ score += 0;
222
+ break;
223
+ default:
224
+ score += 10;
225
+ }
226
+
227
+ return {
228
+ buildStatus,
229
+ testCoverage,
230
+ lintStatus,
231
+ securityAudit,
232
+ overallScore: Math.round(score),
233
+ };
234
+ }
235
+
236
+ /**
237
+ * Generates comprehensive monorepo statistics
238
+ */
239
+ function generateMonorepoStats(packages: PackageInfo[]): MonorepoStats {
240
+ const stats: MonorepoStats = {
241
+ totalPackages: packages.length,
242
+ apps: packages.filter(p => p.type === 'app').length,
243
+ libraries: packages.filter(p => p.type === 'lib').length,
244
+ tools: packages.filter(p => p.type === 'tool').length,
245
+ healthyPackages: 0,
246
+ warningPackages: 0,
247
+ errorPackages: 0,
248
+ outdatedDependencies: 0,
249
+ totalDependencies: 0,
250
+ };
251
+
252
+ // Calculate dependency counts
253
+ packages.forEach(pkg => {
254
+ stats.totalDependencies += Object.keys(pkg.dependencies).length;
255
+ stats.totalDependencies += Object.keys(pkg.devDependencies).length;
256
+ stats.totalDependencies += Object.keys(pkg.peerDependencies ?? {}).length;
257
+ });
258
+
259
+ return stats;
260
+ }
261
+
262
+ /**
263
+ * Finds circular dependencies in the monorepo
264
+ */
265
+ function findCircularDependencies(packages: PackageInfo[]): string[][] {
266
+ const graph = new Map<string, string[]>();
267
+ const visited = new Set<string>();
268
+ const recursionStack = new Set<string>();
269
+ const circularDeps: string[][] = [];
270
+
271
+ // Build dependency graph
272
+ packages.forEach(pkg => {
273
+ graph.set(pkg.name, Object.keys(pkg.dependencies));
274
+ });
275
+
276
+ function dfs(node: string, path: string[]): void {
277
+ if (recursionStack.has(node)) {
278
+ const cycleStart = path.indexOf(node);
279
+ circularDeps.push(path.slice(cycleStart));
280
+ return;
281
+ }
282
+
283
+ if (visited.has(node)) {
284
+ return;
285
+ }
286
+
287
+ visited.add(node);
288
+ recursionStack.add(node);
289
+ path.push(node);
290
+
291
+ const dependencies = graph.get(node) || [];
292
+ for (const dep of dependencies) {
293
+ if (graph.has(dep)) {
294
+ dfs(dep, [...path]);
295
+ }
296
+ }
297
+
298
+ recursionStack.delete(node);
299
+ }
300
+
301
+ for (const node of graph.keys()) {
302
+ if (!visited.has(node)) {
303
+ dfs(node, []);
304
+ }
305
+ }
306
+
307
+ return circularDeps;
308
+ }
309
+
310
+ /**
311
+ * Generates a dependency graph for visualization
312
+ */
313
+ function generateDependencyGraph(packages: PackageInfo[]) {
314
+ const nodes = packages.map(pkg => ({
315
+ // id: pkg.name,
316
+ label: pkg.name,
317
+ type: pkg.type,
318
+ version: pkg.version,
319
+ dependencies: Object.keys(pkg.dependencies).length,
320
+ }));
321
+
322
+ const edges: Array<{ from: string; to: string; type: string }> = [];
323
+
324
+ packages.forEach(pkg => {
325
+ Object.keys(pkg.dependencies).forEach(depName => {
326
+ // Only include internal dependencies
327
+ if (packages.some(p => p.name === depName)) {
328
+ edges.push({
329
+ from: pkg.name,
330
+ to: depName,
331
+ type: 'internal',
332
+ });
333
+ }
334
+ });
335
+ });
336
+
337
+ return { nodes, edges };
338
+ }
339
+
340
+ /**
341
+ * Checks if a package has outdated dependencies
342
+ */
343
+ function checkOutdatedDependencies(packageInfo: PackageInfo): DependencyInfo[] {
344
+ const outdated: DependencyInfo[] = [];
345
+
346
+ // This would typically involve checking against npm registry
347
+ // For now, we'll simulate with some basic checks
348
+ Object.entries(packageInfo.dependencies).forEach(([name, version]) => {
349
+ if (version.startsWith('^') || version.startsWith('~')) {
350
+ // Could be outdated, would need registry check
351
+ outdated.push({
352
+ name,
353
+ version: version,
354
+ status: 'unknown',
355
+ type: 'dependency',
356
+ });
357
+ }
358
+ });
359
+
360
+ return outdated;
361
+ }
362
+
363
+ /**
364
+ * Formats version numbers for comparison
365
+ */
366
+ // function parseVersion(version: string): number[] {
367
+ // return version
368
+ // .replace(/^[^0-9]*/, '')
369
+ // .split('.')
370
+ // .map(Number);
371
+ // }
372
+
373
+ /**
374
+ * Compares two version strings
375
+ */
376
+ // function compareVersions(v1: string, v2: string): number {
377
+ // const parsed1 = parseVersion(v1);
378
+ // const parsed2 = parseVersion(v2);
379
+
380
+ // for (let i = 0; i < Math.max(parsed1.length, parsed2.length); i++) {
381
+ // const num1 = parsed1[i] || 0;
382
+ // const num2 = parsed2[i] || 0;
383
+
384
+ // if (num1 > num2) return 1;
385
+ // if (num1 < num2) return -1;
386
+ // }
387
+
388
+ // return 0;
389
+ // }
390
+
391
+ /**
392
+ * Gets package size information
393
+ */
394
+ function getPackageSize(packagePath: string): {
395
+ size: number;
396
+ files: number;
397
+ } {
398
+ try {
399
+ let totalSize = 0;
400
+ let fileCount = 0;
401
+
402
+ const calculateSize = (dirPath: string): void => {
403
+ const items = fs.readdirSync(dirPath, { withFileTypes: true });
404
+
405
+ for (const item of items) {
406
+ const fullPath = path.join(dirPath, item.name);
407
+
408
+ if (item.isDirectory()) {
409
+ // Skip node_modules and other build artifacts
410
+ if (!['node_modules', 'dist', 'build', '.git'].includes(item.name)) {
411
+ calculateSize(fullPath);
412
+ }
413
+ } else {
414
+ try {
415
+ const stats = fs.statSync(fullPath);
416
+ totalSize += stats.size;
417
+ fileCount++;
418
+ } catch (error) {
419
+ // Skip files we can't read
420
+ }
421
+ }
422
+ }
423
+ }
424
+
425
+ calculateSize(packagePath);
426
+
427
+ return {
428
+ size: totalSize,
429
+ files: fileCount,
430
+ };
431
+ } catch (error) {
432
+ return { size: 0, files: 0 };
433
+ }
434
+ }
435
+
436
+ export {
437
+ scanMonorepo,
438
+ generateMonorepoStats,
439
+ findCircularDependencies,
440
+ generateDependencyGraph,
441
+ checkOutdatedDependencies,
442
+ getPackageSize,
443
+ // analyzeDependencies,
444
+ calculatePackageHealth,
445
+ };
package/package.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "@monodog/utils",
3
+ "version": "1.0.0",
4
+ "description": "Shared utility functions for monodog monorepo dashboard",
5
+ "main": "dist/index.js",
6
+ "type": "module",
7
+ "types": "dist/index.d.ts",
8
+ "license": "MIT",
9
+ "scripts": {
10
+ "build": "tsc --build",
11
+ "test": "jest",
12
+ "clean": "rm -rf dist node_modules/.cache"
13
+ },
14
+ "devDependencies": {
15
+ "@types/node": "^20.10.0",
16
+ "typescript": "^5.2.2"
17
+ }
18
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ // Extends the shared Node configuration for server/utility environments
3
+ "extends": "@lakinmindfire/tsconfig/node.json",
4
+
5
+ "compilerOptions": {
6
+ // Output compilation results to the 'dist' directory
7
+ "outDir": "dist",
8
+ "declaration": true,
9
+ "sourceMap": true,
10
+ "esModuleInterop": true,
11
+ "module": "CommonJS",
12
+ "moduleResolution": "node",
13
+ "verbatimModuleSyntax": false,
14
+ "downlevelIteration": true,
15
+ },
16
+
17
+ // Include all TypeScript files in the 'src' folder
18
+ "include": ["index.ts", "helpers.ts"],
19
+
20
+ // Exclude node_modules and the output directory
21
+ "exclude": ["node_modules", "dist", "**/*.test.ts"]
22
+ }