@manojkmfsi/monodog 1.1.6 → 1.1.8

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 (53) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +12 -0
  3. package/package.json +1 -1
  4. package/src/config/swagger-config.ts +0 -344
  5. package/src/config-loader.ts +0 -97
  6. package/src/constants/index.ts +0 -13
  7. package/src/constants/middleware.ts +0 -83
  8. package/src/constants/port.ts +0 -20
  9. package/src/constants/security.ts +0 -78
  10. package/src/controllers/commit-controller.ts +0 -31
  11. package/src/controllers/config-controller.ts +0 -42
  12. package/src/controllers/health-controller.ts +0 -24
  13. package/src/controllers/package-controller.ts +0 -67
  14. package/src/get-db-url.ts +0 -9
  15. package/src/index.ts +0 -9
  16. package/src/middleware/dashboard-startup.ts +0 -161
  17. package/src/middleware/error-handler.ts +0 -50
  18. package/src/middleware/index.ts +0 -20
  19. package/src/middleware/logger.ts +0 -65
  20. package/src/middleware/security.ts +0 -90
  21. package/src/middleware/server-startup.ts +0 -153
  22. package/src/middleware/swagger-middleware.ts +0 -58
  23. package/src/repositories/commit-repository.ts +0 -108
  24. package/src/repositories/dependency-repository.ts +0 -110
  25. package/src/repositories/index.ts +0 -10
  26. package/src/repositories/package-health-repository.ts +0 -75
  27. package/src/repositories/package-repository.ts +0 -142
  28. package/src/repositories/prisma-client.ts +0 -25
  29. package/src/routes/commit-routes.ts +0 -10
  30. package/src/routes/config-routes.ts +0 -14
  31. package/src/routes/health-routes.ts +0 -14
  32. package/src/routes/package-routes.ts +0 -22
  33. package/src/serve.ts +0 -41
  34. package/src/services/commit-service.ts +0 -44
  35. package/src/services/config-service.ts +0 -391
  36. package/src/services/git-service.ts +0 -140
  37. package/src/services/health-service.ts +0 -162
  38. package/src/services/package-service.ts +0 -228
  39. package/src/setup.ts +0 -78
  40. package/src/types/ci.ts +0 -122
  41. package/src/types/config.ts +0 -22
  42. package/src/types/database.ts +0 -67
  43. package/src/types/git.ts +0 -33
  44. package/src/types/health.ts +0 -11
  45. package/src/types/index.ts +0 -23
  46. package/src/types/package.ts +0 -39
  47. package/src/types/scanner.ts +0 -31
  48. package/src/types/swagger-jsdoc.d.ts +0 -15
  49. package/src/utils/ci-status.ts +0 -535
  50. package/src/utils/db-utils.ts +0 -92
  51. package/src/utils/health-utils.ts +0 -67
  52. package/src/utils/monorepo-scanner.ts +0 -576
  53. package/src/utils/utilities.ts +0 -427
@@ -1,427 +0,0 @@
1
- // import { Package } from '@prisma/client';
2
- import * as fs from 'fs';
3
- import path from 'path';
4
- import { appConfig } from '../config-loader';
5
- import { AppLogger } from '../middleware/logger';
6
- import {calculatePackageHealth} from './health-utils';
7
- import * as yaml from 'js-yaml';
8
-
9
- import type { PackageInfo, DependencyInfo, MonorepoStats } from '../types';
10
-
11
- export type { PackageInfo, DependencyInfo, MonorepoStats } from '../types';
12
- export { type PackageHealth } from '../types';
13
-
14
- /**
15
- * Resolves simple workspace globs (like 'packages/*', 'apps/*') into actual package directory paths.
16
- * Note: This implementation only handles the 'folder/*' pattern and is not a full glob resolver.
17
- */
18
- export function resolveWorkspaceGlobs(rootDir: string, globs: string[]): string[] {
19
- const resolvedPaths: string[] = [];
20
-
21
- for (const glob of globs) {
22
- if (glob.endsWith('/*')) {
23
- const baseDirName = glob.slice(0, -2); // e.g., 'packages'
24
- const baseDirPath = path.join(rootDir, baseDirName);
25
-
26
- if (fs.existsSync(baseDirPath) && fs.statSync(baseDirPath).isDirectory()) {
27
- const subDirs = fs.readdirSync(baseDirPath, { withFileTypes: true })
28
- .filter(dirent => dirent.isDirectory())
29
- .map(dirent => path.join(baseDirName, dirent.name)); // e.g., 'packages/my-utils'
30
-
31
- resolvedPaths.push(...subDirs);
32
- }
33
- } else {
34
- // Handle non-glob paths (e.g., 'packages/my-package') if it's explicitly listed
35
- const directPath = path.join(rootDir, glob);
36
- if (fs.existsSync(directPath) && fs.statSync(directPath).isDirectory()) {
37
- resolvedPaths.push(glob);
38
- }
39
- }
40
- }
41
- return resolvedPaths;
42
- }
43
-
44
- /**
45
- * Parses pnpm-workspace.yaml and extracts workspace globs
46
- */
47
- function getWorkspacesFromPnpmYaml(rootDir: string): string[] | undefined {
48
- const workspaceYamlPath = path.join(rootDir, 'pnpm-workspace.yaml');
49
- if (!fs.existsSync(workspaceYamlPath)) {
50
- return undefined;
51
- }
52
-
53
- try {
54
- const yamlContent = fs.readFileSync(workspaceYamlPath, 'utf-8');
55
- const yamlData = yaml.load(yamlContent) as { packages?: (string | string[]) };
56
-
57
- if (yamlData && yamlData.packages) {
58
- // Filter out exclusion patterns (lines starting with '!')
59
- const packages = Array.isArray(yamlData.packages)
60
- ? yamlData.packages.filter((pkg) => typeof pkg === 'string' && !pkg.startsWith('!'))
61
- : [];
62
-
63
- if (packages.length > 0) {
64
- return packages;
65
- }
66
- }
67
- } catch (e) {
68
- AppLogger.error(`Error parsing pnpm-workspace.yaml at ${workspaceYamlPath}:`, e as Error);
69
- }
70
- return undefined;
71
- }
72
-
73
- /**
74
- * Reads workspace configuration from package.json or pnpm-workspace.yaml
75
- * Priority: package.json (if exists) -> pnpm-workspace.yaml
76
- */
77
- export function getWorkspacesFromRoot(rootDir: string): string[] | undefined {
78
- const packageJsonPath = path.join(rootDir, 'package.json');
79
-
80
- // Try package.json first
81
- if (fs.existsSync(packageJsonPath)) {
82
- try {
83
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
84
-
85
- // Handle both standard array and object format (used by yarn/pnpm)
86
- if (Array.isArray(packageJson.workspaces)) {
87
- AppLogger.info('Workspace configuration found in package.json');
88
- return packageJson.workspaces;
89
- } else if (packageJson.workspaces && Array.isArray(packageJson.workspaces.packages)) {
90
- AppLogger.info('Workspace configuration found in package.json');
91
- return packageJson.workspaces.packages;
92
- }
93
- } catch (e) {
94
- AppLogger.error(`Error parsing package.json at ${packageJsonPath}. Attempting to read pnpm-workspace.yaml...`, e as Error);
95
- }
96
- } else {
97
- AppLogger.warn(`No package.json found at root directory: ${rootDir}`);
98
- }
99
-
100
- // Fallback to pnpm-workspace.yaml
101
- const pnpmWorkspaces = getWorkspacesFromPnpmYaml(rootDir);
102
- if (pnpmWorkspaces && pnpmWorkspaces.length > 0) {
103
- AppLogger.info('Workspace configuration found in pnpm-workspace.yaml');
104
- return pnpmWorkspaces;
105
- }
106
-
107
- AppLogger.warn('No workspace configuration found in package.json or pnpm-workspace.yaml');
108
- return undefined;
109
- }
110
-
111
- /**
112
- * Scans the monorepo and returns information about all packages
113
- */
114
- function scanMonorepo(rootDir: string): PackageInfo[] {
115
- const packages: PackageInfo[] = [];
116
- AppLogger.debug('rootDir: ' + rootDir);
117
- const workspacesGlobs = appConfig.workspaces;
118
- // Use provided workspaces globs if given, otherwise attempt to detect from root package.json or pnpm-workspace.yaml
119
- const detectedWorkspacesGlobs = workspacesGlobs.length > 0 ? workspacesGlobs : getWorkspacesFromRoot(rootDir);
120
- if (detectedWorkspacesGlobs && detectedWorkspacesGlobs.length > 0) {
121
- if (workspacesGlobs.length) {
122
- AppLogger.info(`Using provided workspaces globs: ${detectedWorkspacesGlobs.join(', ')}`);
123
- } else {
124
- AppLogger.info(`Detected Monorepo Workspaces Globs: ${detectedWorkspacesGlobs.join(', ')}`);
125
- }
126
-
127
- // 1. Resolve the globs into concrete package directory paths
128
- const resolvedPackagePaths = resolveWorkspaceGlobs(rootDir, detectedWorkspacesGlobs);
129
-
130
- AppLogger.debug(`Resolved package directories (Total ${resolvedPackagePaths.length})`);
131
- if (resolvedPackagePaths.length < workspacesGlobs.length) {
132
- AppLogger.warn('Some workspaces globs provided are invalid.');
133
- }
134
-
135
- // 2. Integration of the requested loop structure for package scanning
136
- for (const workspacePath of resolvedPackagePaths) {
137
- const fullPackagePath = path.join(rootDir, workspacePath);
138
- // The package name would be read from the package.json inside this path
139
- const packageName = path.basename(fullPackagePath);
140
-
141
- AppLogger.debug(`- Scanning path: ${workspacePath} (Package: ${packageName})`);
142
-
143
- const packageInfo = parsePackageInfo(fullPackagePath, packageName);
144
- if (packageInfo) {
145
- packages.push(packageInfo);
146
- }
147
- }
148
- } else {
149
- AppLogger.warn('No workspace globs provided or detected. Returning empty package list.');
150
- }
151
-
152
- return packages;
153
- }
154
-
155
- /*** Parses package.json and determines package type */
156
- export function parsePackageInfo(
157
- packagePath: string,
158
- packageName: string,
159
- forcedType?: 'app' | 'lib' | 'tool'
160
- ): PackageInfo | null {
161
- const packageJsonPath = path.join(packagePath, 'package.json');
162
-
163
- if (!fs.existsSync(packageJsonPath)) {
164
- return null;
165
- }
166
-
167
- try {
168
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
169
-
170
- // Determine package type
171
- let packageType: 'app' | 'lib' | 'tool' = 'lib';
172
- if (forcedType) {
173
- packageType = forcedType;
174
- } else if (packageJson.scripts && packageJson.scripts.start) {
175
- packageType = 'app';
176
- } else if (packageJson.keywords && packageJson.keywords.includes('tool')) {
177
- packageType = 'tool';
178
- }
179
-
180
- return {
181
- name: packageJson.name || packageName,
182
- version: packageJson.version || '0.0.0',
183
- type: packageType,
184
- path: packagePath,
185
- dependencies: packageJson.dependencies || {},
186
- devDependencies: packageJson.devDependencies || {},
187
- peerDependencies: packageJson.peerDependencies || {},
188
- scripts: packageJson.scripts || {},
189
- maintainers: packageJson.maintainers || [],
190
- description: packageJson.description,
191
- license: packageJson.license,
192
- repository: packageJson.repository || {},
193
- };
194
- } catch (error) {
195
- AppLogger.error(`Error parsing package.json for ${packageName}`, error as Error);
196
- return null;
197
- }
198
- }
199
-
200
- /**
201
- * Generates comprehensive monorepo statistics
202
- */
203
- function generateMonorepoStats(packages: PackageInfo[]): MonorepoStats {
204
- const stats: MonorepoStats = {
205
- totalPackages: packages.length,
206
- apps: packages.filter(p => p.type === 'app').length,
207
- libraries: packages.filter(p => p.type === 'lib').length,
208
- tools: packages.filter(p => p.type === 'tool').length,
209
- healthyPackages: 0,
210
- warningPackages: 0,
211
- errorPackages: 0,
212
- outdatedDependencies: 0,
213
- totalDependencies: 0,
214
- };
215
-
216
- // Calculate dependency counts
217
- packages.forEach(pkg => {
218
- stats.totalDependencies += Object.keys(pkg.dependencies).length;
219
- stats.totalDependencies += Object.keys(pkg.devDependencies).length;
220
- stats.totalDependencies += Object.keys(pkg.peerDependencies ?? {}).length;
221
- });
222
-
223
- return stats;
224
- }
225
-
226
- /**
227
- * Finds circular dependencies in the monorepo
228
- */
229
- function findCircularDependencies(packages: PackageInfo[]): string[][] {
230
- const graph = new Map<string, string[]>();
231
- const visited = new Set<string>();
232
- const recursionStack = new Set<string>();
233
- const circularDeps: string[][] = [];
234
-
235
- // Build dependency graph
236
- packages.forEach(pkg => {
237
- graph.set(pkg.name, Object.keys(pkg.dependencies));
238
- });
239
-
240
- function dfs(node: string, path: string[]): void {
241
- if (recursionStack.has(node)) {
242
- const cycleStart = path.indexOf(node);
243
- circularDeps.push(path.slice(cycleStart));
244
- return;
245
- }
246
-
247
- if (visited.has(node)) {
248
- return;
249
- }
250
-
251
- visited.add(node);
252
- recursionStack.add(node);
253
- path.push(node);
254
-
255
- const dependencies = graph.get(node) || [];
256
- for (const dep of dependencies) {
257
- if (graph.has(dep)) {
258
- dfs(dep, [...path]);
259
- }
260
- }
261
-
262
- recursionStack.delete(node);
263
- }
264
-
265
- for (const node of graph.keys()) {
266
- if (!visited.has(node)) {
267
- dfs(node, []);
268
- }
269
- }
270
-
271
- return circularDeps;
272
- }
273
-
274
- /**
275
- * Generates a dependency graph for visualization
276
- */
277
- function generateDependencyGraph(packages: PackageInfo[]) {
278
- const nodes = packages.map(pkg => ({
279
- // id: pkg.name,
280
- label: pkg.name,
281
- type: pkg.type,
282
- version: pkg.version,
283
- dependencies: Object.keys(pkg.dependencies).length,
284
- }));
285
-
286
- const edges: Array<{ from: string; to: string; type: string }> = [];
287
-
288
- packages.forEach(pkg => {
289
- Object.keys(pkg.dependencies).forEach(depName => {
290
- // Only include internal dependencies
291
- if (packages.some(p => p.name === depName)) {
292
- edges.push({
293
- from: pkg.name,
294
- to: depName,
295
- type: 'internal',
296
- });
297
- }
298
- });
299
- });
300
-
301
- return { nodes, edges };
302
- }
303
-
304
- /**
305
- * Checks if a package has outdated dependencies
306
- */
307
- function checkOutdatedDependencies(packageInfo: PackageInfo): DependencyInfo[] {
308
- const outdated: DependencyInfo[] = [];
309
-
310
- // This would typically involve checking against npm registry
311
- // For now, we'll simulate with some basic checks
312
- Object.entries(packageInfo.dependencies).forEach(([name, version]) => {
313
- if (version.startsWith('^') || version.startsWith('~')) {
314
- // Could be outdated, would need registry check
315
- outdated.push({
316
- name,
317
- version: version,
318
- status: 'unknown',
319
- type: 'dependency',
320
- });
321
- }
322
- });
323
-
324
- return outdated;
325
- }
326
-
327
- /**
328
- * Gets package size information
329
- */
330
- function getPackageSize(packagePath: string): {
331
- size: number;
332
- files: number;
333
- } {
334
- try {
335
- let totalSize = 0;
336
- let fileCount = 0;
337
-
338
- const calculateSize = (dirPath: string): void => {
339
- const items = fs.readdirSync(dirPath, { withFileTypes: true });
340
-
341
- for (const item of items) {
342
- const fullPath = path.join(dirPath, item.name);
343
-
344
- if (item.isDirectory()) {
345
- // Skip node_modules and other build artifacts
346
- if (!['node_modules', 'dist', 'build', '.git'].includes(item.name)) {
347
- calculateSize(fullPath);
348
- }
349
- } else {
350
- try {
351
- const stats = fs.statSync(fullPath);
352
- totalSize += stats.size;
353
- fileCount++;
354
- } catch (error) {
355
- // Skip files we can't read
356
- }
357
- }
358
- }
359
- };
360
-
361
- calculateSize(packagePath);
362
-
363
- return {
364
- size: totalSize,
365
- files: fileCount,
366
- };
367
- } catch (error) {
368
- return { size: 0, files: 0 };
369
- }
370
- }
371
-
372
- /**
373
- * Find the monorepo root by looking for package.json with workspaces or pnpm-workspace.yaml
374
- */
375
- function findMonorepoRoot(): string {
376
- let currentDir = __dirname;
377
-
378
- while (currentDir !== path.parse(currentDir).root) {
379
- const packageJsonPath = path.join(currentDir, 'package.json');
380
- const pnpmWorkspacePath = path.join(currentDir, 'pnpm-workspace.yaml');
381
-
382
- // Check if this directory has package.json with workspaces or pnpm-workspace.yaml
383
- if (fs.existsSync(packageJsonPath)) {
384
- try {
385
- const packageJson = JSON.parse(
386
- fs.readFileSync(packageJsonPath, 'utf8')
387
- );
388
- // If it has workspaces or is the root monorepo package
389
- if (packageJson.workspaces || fs.existsSync(pnpmWorkspacePath)) {
390
- AppLogger.debug('Found monorepo root: ' + currentDir);
391
- return currentDir;
392
- }
393
- } catch (error) {
394
- // Continue searching if package.json is invalid
395
- }
396
- }
397
-
398
- // Check if we're at the git root
399
- const gitPath = path.join(currentDir, '.git');
400
- if (fs.existsSync(gitPath)) {
401
- AppLogger.debug('Found git root (likely monorepo root): ' + currentDir);
402
- return currentDir;
403
- }
404
-
405
- // Go up one directory
406
- const parentDir = path.dirname(currentDir);
407
- if (parentDir === currentDir) break; // Prevent infinite loop
408
- currentDir = parentDir;
409
- }
410
-
411
- // Fallback to process.cwd() if we can't find the root
412
- AppLogger.warn(
413
- 'Could not find monorepo root, using process.cwd(): ' + process.cwd()
414
- );
415
- return process.cwd();
416
- }
417
-
418
- export {
419
- scanMonorepo,
420
- generateMonorepoStats,
421
- findCircularDependencies,
422
- generateDependencyGraph,
423
- checkOutdatedDependencies,
424
- getPackageSize,
425
- calculatePackageHealth,
426
- findMonorepoRoot,
427
- };