sublyzer-snapshot 0.3.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.
Files changed (115) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +306 -0
  3. package/dist/api/sublyzer.d.ts +29 -0
  4. package/dist/api/sublyzer.d.ts.map +1 -0
  5. package/dist/api/sublyzer.js +61 -0
  6. package/dist/api/sublyzer.js.map +1 -0
  7. package/dist/cli.d.ts +3 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +199 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/commands/ci.d.ts +9 -0
  12. package/dist/commands/ci.d.ts.map +1 -0
  13. package/dist/commands/ci.js +65 -0
  14. package/dist/commands/ci.js.map +1 -0
  15. package/dist/commands/compare.d.ts +7 -0
  16. package/dist/commands/compare.d.ts.map +1 -0
  17. package/dist/commands/compare.js +60 -0
  18. package/dist/commands/compare.js.map +1 -0
  19. package/dist/commands/doctor.d.ts +13 -0
  20. package/dist/commands/doctor.d.ts.map +1 -0
  21. package/dist/commands/doctor.js +100 -0
  22. package/dist/commands/doctor.js.map +1 -0
  23. package/dist/commands/init.d.ts +10 -0
  24. package/dist/commands/init.d.ts.map +1 -0
  25. package/dist/commands/init.js +88 -0
  26. package/dist/commands/init.js.map +1 -0
  27. package/dist/commands/open.d.ts +2 -0
  28. package/dist/commands/open.d.ts.map +1 -0
  29. package/dist/commands/open.js +16 -0
  30. package/dist/commands/open.js.map +1 -0
  31. package/dist/commands/pull.d.ts +9 -0
  32. package/dist/commands/pull.d.ts.map +1 -0
  33. package/dist/commands/pull.js +34 -0
  34. package/dist/commands/pull.js.map +1 -0
  35. package/dist/commands/report.d.ts +8 -0
  36. package/dist/commands/report.d.ts.map +1 -0
  37. package/dist/commands/report.js +47 -0
  38. package/dist/commands/report.js.map +1 -0
  39. package/dist/commands/run.d.ts +21 -0
  40. package/dist/commands/run.d.ts.map +1 -0
  41. package/dist/commands/run.js +96 -0
  42. package/dist/commands/run.js.map +1 -0
  43. package/dist/commands/status.d.ts +5 -0
  44. package/dist/commands/status.d.ts.map +1 -0
  45. package/dist/commands/status.js +52 -0
  46. package/dist/commands/status.js.map +1 -0
  47. package/dist/config.d.ts +36 -0
  48. package/dist/config.d.ts.map +1 -0
  49. package/dist/config.js +58 -0
  50. package/dist/config.js.map +1 -0
  51. package/dist/constants.d.ts +13 -0
  52. package/dist/constants.d.ts.map +1 -0
  53. package/dist/constants.js +12 -0
  54. package/dist/constants.js.map +1 -0
  55. package/dist/detect/git.d.ts +9 -0
  56. package/dist/detect/git.d.ts.map +1 -0
  57. package/dist/detect/git.js +25 -0
  58. package/dist/detect/git.js.map +1 -0
  59. package/dist/detect/meta.d.ts +8 -0
  60. package/dist/detect/meta.d.ts.map +1 -0
  61. package/dist/detect/meta.js +42 -0
  62. package/dist/detect/meta.js.map +1 -0
  63. package/dist/detect/routes.d.ts +2 -0
  64. package/dist/detect/routes.d.ts.map +1 -0
  65. package/dist/detect/routes.js +104 -0
  66. package/dist/detect/routes.js.map +1 -0
  67. package/dist/detect/stack.d.ts +15 -0
  68. package/dist/detect/stack.d.ts.map +1 -0
  69. package/dist/detect/stack.js +114 -0
  70. package/dist/detect/stack.js.map +1 -0
  71. package/dist/detect/workspaces.d.ts +6 -0
  72. package/dist/detect/workspaces.d.ts.map +1 -0
  73. package/dist/detect/workspaces.js +54 -0
  74. package/dist/detect/workspaces.js.map +1 -0
  75. package/dist/report/markdown.d.ts +5 -0
  76. package/dist/report/markdown.d.ts.map +1 -0
  77. package/dist/report/markdown.js +81 -0
  78. package/dist/report/markdown.js.map +1 -0
  79. package/dist/scan/audit.d.ts +16 -0
  80. package/dist/scan/audit.d.ts.map +1 -0
  81. package/dist/scan/audit.js +53 -0
  82. package/dist/scan/audit.js.map +1 -0
  83. package/dist/scan/health-score.d.ts +13 -0
  84. package/dist/scan/health-score.d.ts.map +1 -0
  85. package/dist/scan/health-score.js +60 -0
  86. package/dist/scan/health-score.js.map +1 -0
  87. package/dist/scan/history.d.ts +21 -0
  88. package/dist/scan/history.d.ts.map +1 -0
  89. package/dist/scan/history.js +82 -0
  90. package/dist/scan/history.js.map +1 -0
  91. package/dist/scan/outdated.d.ts +15 -0
  92. package/dist/scan/outdated.d.ts.map +1 -0
  93. package/dist/scan/outdated.js +54 -0
  94. package/dist/scan/outdated.js.map +1 -0
  95. package/dist/scan/policy.d.ts +5 -0
  96. package/dist/scan/policy.d.ts.map +1 -0
  97. package/dist/scan/policy.js +20 -0
  98. package/dist/scan/policy.js.map +1 -0
  99. package/dist/scan/snapshot.d.ts +47 -0
  100. package/dist/scan/snapshot.d.ts.map +1 -0
  101. package/dist/scan/snapshot.js +176 -0
  102. package/dist/scan/snapshot.js.map +1 -0
  103. package/dist/utils/gitignore.d.ts +3 -0
  104. package/dist/utils/gitignore.d.ts.map +1 -0
  105. package/dist/utils/gitignore.js +34 -0
  106. package/dist/utils/gitignore.js.map +1 -0
  107. package/dist/utils/log.d.ts +6 -0
  108. package/dist/utils/log.d.ts.map +1 -0
  109. package/dist/utils/log.js +17 -0
  110. package/dist/utils/log.js.map +1 -0
  111. package/dist/utils/prompt.d.ts +4 -0
  112. package/dist/utils/prompt.d.ts.map +1 -0
  113. package/dist/utils/prompt.js +35 -0
  114. package/dist/utils/prompt.js.map +1 -0
  115. package/package.json +51 -0
@@ -0,0 +1,54 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ function classify(current, latest) {
3
+ const c = current.replace(/^[\^~]/, '').split('.').map(Number);
4
+ const l = latest.replace(/^[\^~]/, '').split('.').map(Number);
5
+ if (l[0] > (c[0] || 0))
6
+ return 'major';
7
+ if (l[1] > (c[1] || 0))
8
+ return 'minor';
9
+ return 'patch';
10
+ }
11
+ export function runNpmOutdated(root = process.cwd()) {
12
+ const empty = { ran: false, total: 0, majorCount: 0, packages: [] };
13
+ const res = spawnSync(process.platform === 'win32' ? 'npm.cmd' : 'npm', ['outdated', '--json'], {
14
+ cwd: root,
15
+ encoding: 'utf8',
16
+ timeout: 60_000,
17
+ maxBuffer: 5 * 1024 * 1024,
18
+ });
19
+ const stdout = (res.stdout || '').trim();
20
+ if (!stdout) {
21
+ if (res.status === 0)
22
+ return { ...empty, ran: true, total: 0, majorCount: 0 };
23
+ return { ...empty, error: res.stderr?.slice(0, 120) || 'npm outdated failed' };
24
+ }
25
+ let parsed;
26
+ try {
27
+ parsed = JSON.parse(stdout);
28
+ }
29
+ catch {
30
+ return { ...empty, error: 'Failed to parse npm outdated JSON' };
31
+ }
32
+ const packages = [];
33
+ let majorCount = 0;
34
+ for (const [name, info] of Object.entries(parsed)) {
35
+ const current = String(info.current || '');
36
+ const latest = String(info.latest || '');
37
+ const wanted = String(info.wanted || latest);
38
+ const kind = classify(current, latest);
39
+ if (kind === 'major')
40
+ majorCount += 1;
41
+ packages.push({ name, current, wanted, latest, kind });
42
+ }
43
+ packages.sort((a, b) => {
44
+ const rank = { major: 0, minor: 1, patch: 2 };
45
+ return rank[a.kind] - rank[b.kind] || a.name.localeCompare(b.name);
46
+ });
47
+ return {
48
+ ran: true,
49
+ total: packages.length,
50
+ majorCount,
51
+ packages: packages.slice(0, 30),
52
+ };
53
+ }
54
+ //# sourceMappingURL=outdated.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outdated.js","sourceRoot":"","sources":["../../src/scan/outdated.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { FailOnLevel } from '../constants.js';
2
+ import type { ProjectSnapshot } from './snapshot.js';
3
+ export declare function shouldFailOnVulns(snapshot: ProjectSnapshot, level: FailOnLevel): boolean;
4
+ export declare function failOnMessage(snapshot: ProjectSnapshot, level: FailOnLevel): string;
5
+ //# sourceMappingURL=policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../src/scan/policy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,eAAe,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAcxF;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,eAAe,EAAE,KAAK,EAAE,WAAW,GAAG,MAAM,CAGnF"}
@@ -0,0 +1,20 @@
1
+ export function shouldFailOnVulns(snapshot, level) {
2
+ const s = snapshot.summary;
3
+ switch (level) {
4
+ case 'critical':
5
+ return s.criticalVulns > 0;
6
+ case 'high':
7
+ return s.criticalVulns > 0 || s.highVulns > 0;
8
+ case 'moderate':
9
+ return s.criticalVulns > 0 || s.highVulns > 0 || snapshot.audit.moderate > 0;
10
+ case 'any':
11
+ return s.vulnerablePackages > 0;
12
+ default:
13
+ return false;
14
+ }
15
+ }
16
+ export function failOnMessage(snapshot, level) {
17
+ const s = snapshot.summary;
18
+ return `Policy --fail-on ${level} triggered: ${s.criticalVulns} critical, ${s.highVulns} high, ${s.vulnerablePackages} total vulnerabilities`;
19
+ }
20
+ //# sourceMappingURL=policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/scan/policy.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,iBAAiB,CAAC,QAAyB,EAAE,KAAkB;IAC7E,MAAM,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC;IAC3B,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,UAAU;YACb,OAAO,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC;QAC7B,KAAK,MAAM;YACT,OAAO,CAAC,CAAC,aAAa,GAAG,CAAC,IAAI,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC;QAChD,KAAK,UAAU;YACb,OAAO,CAAC,CAAC,aAAa,GAAG,CAAC,IAAI,CAAC,CAAC,SAAS,GAAG,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC;QAC/E,KAAK,KAAK;YACR,OAAO,CAAC,CAAC,kBAAkB,GAAG,CAAC,CAAC;QAClC;YACE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,QAAyB,EAAE,KAAkB;IACzE,MAAM,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC;IAC3B,OAAO,oBAAoB,KAAK,eAAe,CAAC,CAAC,aAAa,cAAc,CAAC,CAAC,SAAS,UAAU,CAAC,CAAC,kBAAkB,wBAAwB,CAAC;AAChJ,CAAC"}
@@ -0,0 +1,47 @@
1
+ import { type GitInfo } from '../detect/git.js';
2
+ import { detectEnvFiles } from '../detect/meta.js';
3
+ import { detectStack, listDependencies } from '../detect/stack.js';
4
+ import { type WorkspaceInfo } from '../detect/workspaces.js';
5
+ import { type HealthScore } from './health-score.js';
6
+ import { type AuditSummary } from './audit.js';
7
+ import { type OutdatedSummary } from './outdated.js';
8
+ export type ProjectSnapshot = {
9
+ scannedAt: string;
10
+ projectName: string;
11
+ stack: ReturnType<typeof detectStack>;
12
+ routes: string[];
13
+ dependencies: ReturnType<typeof listDependencies>;
14
+ dependencyCount: number;
15
+ git: GitInfo;
16
+ env: ReturnType<typeof detectEnvFiles>;
17
+ nodeEngine?: string;
18
+ scripts: Record<string, string>;
19
+ workspaces: WorkspaceInfo;
20
+ outdated: OutdatedSummary;
21
+ audit: AuditSummary;
22
+ health: HealthScore;
23
+ summary: {
24
+ routeCount: number;
25
+ productionDeps: number;
26
+ devDeps: number;
27
+ vulnerablePackages: number;
28
+ criticalVulns: number;
29
+ highVulns: number;
30
+ healthScore: number;
31
+ healthGrade: HealthScore['grade'];
32
+ };
33
+ };
34
+ export type BuildSnapshotOptions = {
35
+ skipAudit?: boolean;
36
+ skipOutdated?: boolean;
37
+ };
38
+ export declare function buildProjectSnapshot(root?: string, opts?: BuildSnapshotOptions): ProjectSnapshot;
39
+ export type CollectItem = {
40
+ dataType: 'custom_event' | 'vulnerability' | 'performance';
41
+ severity?: 'low' | 'medium' | 'high' | 'critical';
42
+ source: string;
43
+ data: Record<string, unknown>;
44
+ };
45
+ export declare function snapshotToCollectItems(snapshot: ProjectSnapshot): CollectItem[];
46
+ export declare function printLocalSummary(snapshot: ProjectSnapshot): void;
47
+ //# sourceMappingURL=snapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../../src/scan/snapshot.ts"],"names":[],"mappings":"AACA,OAAO,EAAa,KAAK,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAmC,MAAM,mBAAmB,CAAC;AAEpF,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAmB,MAAM,oBAAoB,CAAC;AACpF,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC/E,OAAO,EAAuC,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC1F,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAkB,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAErE,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;IACtC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;IAClD,eAAe,EAAE,MAAM,CAAC;IACxB,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,UAAU,EAAE,aAAa,CAAC;IAC1B,QAAQ,EAAE,eAAe,CAAC;IAC1B,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE,WAAW,CAAC;IACpB,OAAO,EAAE;QACP,UAAU,EAAE,MAAM,CAAC;QACnB,cAAc,EAAE,MAAM,CAAC;QACvB,OAAO,EAAE,MAAM,CAAC;QAChB,kBAAkB,EAAE,MAAM,CAAC;QAC3B,aAAa,EAAE,MAAM,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;KACnC,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,IAAI,SAAgB,EAAE,IAAI,GAAE,oBAAyB,GAAG,eAAe,CAkD3G;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,cAAc,GAAG,eAAe,GAAG,aAAa,CAAC;IAC3D,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B,CAAC;AAEF,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,eAAe,GAAG,WAAW,EAAE,CAoF/E;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,CAsCjE"}
@@ -0,0 +1,176 @@
1
+ import { SDK_NAME, SDK_VERSION } from '../constants.js';
2
+ import { detectGit } from '../detect/git.js';
3
+ import { detectEnvFiles, detectNodeEngine, detectScripts } from '../detect/meta.js';
4
+ import { detectRoutes } from '../detect/routes.js';
5
+ import { detectStack, listDependencies, readProjectName } from '../detect/stack.js';
6
+ import { detectWorkspaces } from '../detect/workspaces.js';
7
+ import { computeHealthScore, formatHealthBar } from './health-score.js';
8
+ import { runNpmAudit } from './audit.js';
9
+ import { runNpmOutdated } from './outdated.js';
10
+ export function buildProjectSnapshot(root = process.cwd(), opts = {}) {
11
+ const stack = detectStack(root);
12
+ const routes = detectRoutes(stack.id, root);
13
+ const dependencies = listDependencies(root);
14
+ const audit = opts.skipAudit
15
+ ? { ran: false, total: 0, critical: 0, high: 0, moderate: 0, low: 0, advisories: [], error: 'skipped' }
16
+ : runNpmAudit(root);
17
+ const outdated = opts.skipOutdated
18
+ ? { ran: false, total: 0, majorCount: 0, packages: [], error: 'skipped' }
19
+ : runNpmOutdated(root);
20
+ const git = detectGit(root);
21
+ const env = detectEnvFiles(root);
22
+ const scripts = detectScripts(root);
23
+ const nodeEngine = detectNodeEngine(root);
24
+ const workspaces = detectWorkspaces(root);
25
+ const productionDeps = dependencies.filter((d) => !d.dev).length;
26
+ const devDeps = dependencies.filter((d) => d.dev).length;
27
+ const partial = {
28
+ scannedAt: new Date().toISOString(),
29
+ projectName: readProjectName(root),
30
+ stack,
31
+ routes,
32
+ dependencies,
33
+ dependencyCount: dependencies.length,
34
+ git,
35
+ env,
36
+ nodeEngine,
37
+ scripts,
38
+ workspaces,
39
+ outdated,
40
+ audit,
41
+ summary: {
42
+ routeCount: routes.length,
43
+ productionDeps,
44
+ devDeps,
45
+ vulnerablePackages: audit.total,
46
+ criticalVulns: audit.critical,
47
+ highVulns: audit.high,
48
+ healthScore: 0,
49
+ healthGrade: 'F',
50
+ },
51
+ };
52
+ const health = computeHealthScore(partial);
53
+ partial.summary.healthScore = health.score;
54
+ partial.summary.healthGrade = health.grade;
55
+ return { ...partial, health };
56
+ }
57
+ export function snapshotToCollectItems(snapshot) {
58
+ const items = [
59
+ {
60
+ dataType: 'custom_event',
61
+ source: SDK_NAME,
62
+ data: {
63
+ eventType: 'project_snapshot',
64
+ sdkVersion: SDK_VERSION,
65
+ projectName: snapshot.projectName,
66
+ stack: snapshot.stack,
67
+ health: snapshot.health,
68
+ routes: snapshot.routes.slice(0, 100),
69
+ routeCount: snapshot.summary.routeCount,
70
+ dependencyCount: snapshot.dependencyCount,
71
+ productionDeps: snapshot.summary.productionDeps,
72
+ devDeps: snapshot.summary.devDeps,
73
+ workspaces: snapshot.workspaces,
74
+ outdated: snapshot.outdated.ran
75
+ ? { total: snapshot.outdated.total, majorCount: snapshot.outdated.majorCount }
76
+ : null,
77
+ git: snapshot.git.available
78
+ ? { branch: snapshot.git.branch, commit: snapshot.git.commit, dirty: snapshot.git.dirty }
79
+ : null,
80
+ env: { exampleFiles: snapshot.env.found, hasDotEnv: snapshot.env.hasDotEnv },
81
+ nodeEngine: snapshot.nodeEngine,
82
+ scriptNames: Object.keys(snapshot.scripts).slice(0, 30),
83
+ audit: {
84
+ ran: snapshot.audit.ran,
85
+ total: snapshot.audit.total,
86
+ critical: snapshot.audit.critical,
87
+ high: snapshot.audit.high,
88
+ moderate: snapshot.audit.moderate,
89
+ low: snapshot.audit.low,
90
+ },
91
+ scannedAt: snapshot.scannedAt,
92
+ },
93
+ },
94
+ ];
95
+ for (const adv of snapshot.audit.advisories.slice(0, 15)) {
96
+ const sev = adv.severity;
97
+ items.push({
98
+ dataType: 'vulnerability',
99
+ severity: sev === 'critical' || sev === 'high' || sev === 'medium' || sev === 'low' ? sev : 'medium',
100
+ source: SDK_NAME,
101
+ data: {
102
+ type: 'dependency_audit',
103
+ package: adv.name,
104
+ title: adv.title,
105
+ severity: adv.severity,
106
+ scanner: 'npm-audit',
107
+ projectName: snapshot.projectName,
108
+ },
109
+ });
110
+ }
111
+ items.push({
112
+ dataType: 'performance',
113
+ source: SDK_NAME,
114
+ data: {
115
+ metric: 'snapshot_health_score',
116
+ value: snapshot.health.score,
117
+ unit: 'score',
118
+ grade: snapshot.health.grade,
119
+ projectName: snapshot.projectName,
120
+ stack: snapshot.stack.id,
121
+ },
122
+ });
123
+ if (snapshot.summary.routeCount > 0) {
124
+ items.push({
125
+ dataType: 'performance',
126
+ source: SDK_NAME,
127
+ data: {
128
+ metric: 'snapshot_route_count',
129
+ value: snapshot.summary.routeCount,
130
+ unit: 'routes',
131
+ projectName: snapshot.projectName,
132
+ stack: snapshot.stack.id,
133
+ },
134
+ });
135
+ }
136
+ return items;
137
+ }
138
+ export function printLocalSummary(snapshot) {
139
+ console.log('');
140
+ console.log(` Project: ${snapshot.projectName}`);
141
+ console.log(` Stack: ${snapshot.stack.label} (${snapshot.stack.confidence})`);
142
+ console.log(` Health: ${formatHealthBar(snapshot.health.score)} grade ${snapshot.health.grade}`);
143
+ const fw = Object.entries(snapshot.stack.frameworkVersions).slice(0, 4);
144
+ if (fw.length) {
145
+ console.log(` Frameworks: ${fw.map(([k, v]) => `${k}@${v}`).join(', ')}`);
146
+ }
147
+ if (snapshot.workspaces.packages.length > 1) {
148
+ console.log(` Monorepo: ${snapshot.workspaces.type} — ${snapshot.workspaces.packages.length} packages`);
149
+ }
150
+ console.log(` Routes: ${snapshot.summary.routeCount}`);
151
+ console.log(` Dependencies: ${snapshot.summary.productionDeps} prod / ${snapshot.summary.devDeps} dev`);
152
+ if (snapshot.outdated.ran && snapshot.outdated.total > 0) {
153
+ console.log(` Outdated: ${snapshot.outdated.total} (${snapshot.outdated.majorCount} major)`);
154
+ }
155
+ if (snapshot.git.available) {
156
+ const dirty = snapshot.git.dirty ? ' (dirty)' : '';
157
+ console.log(` Git: ${snapshot.git.branch} @ ${snapshot.git.commit}${dirty}`);
158
+ }
159
+ if (snapshot.audit.ran) {
160
+ console.log(` Vulnerabilities: ${snapshot.audit.total} (critical ${snapshot.audit.critical}, high ${snapshot.audit.high})`);
161
+ }
162
+ else {
163
+ console.log(` Vulnerabilities: skipped (${snapshot.audit.error || 'npm audit unavailable'})`);
164
+ }
165
+ if (snapshot.routes.length) {
166
+ console.log(' Sample routes:');
167
+ for (const r of snapshot.routes.slice(0, 8)) {
168
+ console.log(` • ${r}`);
169
+ }
170
+ if (snapshot.routes.length > 8) {
171
+ console.log(` … +${snapshot.routes.length - 8} more`);
172
+ }
173
+ }
174
+ console.log('');
175
+ }
176
+ //# sourceMappingURL=snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../src/scan/snapshot.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function ensureGitignore(root?: string): boolean;
2
+ export declare function printSdkHint(stackId: string, integrationCode: string, apiUrl: string): void;
3
+ //# sourceMappingURL=gitignore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitignore.d.ts","sourceRoot":"","sources":["../../src/utils/gitignore.ts"],"names":[],"mappings":"AAKA,wBAAgB,eAAe,CAAC,IAAI,SAAgB,GAAG,OAAO,CAe7D;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAW3F"}
@@ -0,0 +1,34 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import { GITIGNORE_ENTRY } from '../constants.js';
4
+ import { ok, info } from './log.js';
5
+ export function ensureGitignore(root = process.cwd()) {
6
+ const file = path.join(root, '.gitignore');
7
+ if (!fs.existsSync(file)) {
8
+ fs.writeFileSync(file, `# Sublyzer Snapshot (local integration config)\n${GITIGNORE_ENTRY}\n`, 'utf8');
9
+ ok(`Created .gitignore with ${GITIGNORE_ENTRY}`);
10
+ return true;
11
+ }
12
+ const content = fs.readFileSync(file, 'utf8');
13
+ if (content.includes('.sublyzer') || content.includes(GITIGNORE_ENTRY)) {
14
+ return false;
15
+ }
16
+ const next = content.endsWith('\n') ? content : `${content}\n`;
17
+ fs.writeFileSync(file, `${next}\n# Sublyzer Snapshot\n${GITIGNORE_ENTRY}\n`, 'utf8');
18
+ ok(`Added ${GITIGNORE_ENTRY} to .gitignore`);
19
+ return true;
20
+ }
21
+ export function printSdkHint(stackId, integrationCode, apiUrl) {
22
+ info('Production monitoring (optional — install the browser SDK):');
23
+ console.log('');
24
+ if (stackId === 'nextjs') {
25
+ console.log(` <script src="/sdks/sublyzer.js" defer data-integration-code="${integrationCode}" data-api-url="${apiUrl}"></script>`);
26
+ }
27
+ else {
28
+ console.log(` <script src="/sdks/sublyzer.js" defer data-integration-code="${integrationCode}" data-api-url="${apiUrl}"></script>`);
29
+ }
30
+ console.log('');
31
+ console.log(' Docs: https://sublyzer.com/docs/sdk');
32
+ console.log('');
33
+ }
34
+ //# sourceMappingURL=gitignore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitignore.js","sourceRoot":"","sources":["../../src/utils/gitignore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAEpC,MAAM,UAAU,eAAe,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE;IAClD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IAC3C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,mDAAmD,eAAe,IAAI,EAAE,MAAM,CAAC,CAAC;QACvG,EAAE,CAAC,2BAA2B,eAAe,EAAE,CAAC,CAAC;QACjD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC9C,IAAI,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;QACvE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,IAAI,CAAC;IAC/D,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,GAAG,IAAI,0BAA0B,eAAe,IAAI,EAAE,MAAM,CAAC,CAAC;IACrF,EAAE,CAAC,SAAS,eAAe,gBAAgB,CAAC,CAAC;IAC7C,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAe,EAAE,eAAuB,EAAE,MAAc;IACnF,IAAI,CAAC,6DAA6D,CAAC,CAAC;IACpE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,kEAAkE,eAAe,mBAAmB,MAAM,aAAa,CAAC,CAAC;IACvI,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,kEAAkE,eAAe,mBAAmB,MAAM,aAAa,CAAC,CAAC;IACvI,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAClB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export declare function info(msg: string): void;
2
+ export declare function ok(msg: string): void;
3
+ export declare function warn(msg: string): void;
4
+ export declare function fail(msg: string): never;
5
+ export declare function title(msg: string): void;
6
+ //# sourceMappingURL=log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../src/utils/log.ts"],"names":[],"mappings":"AAAA,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEtC;AAED,wBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEpC;AAED,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEtC;AAED,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAGvC;AAED,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEvC"}
@@ -0,0 +1,17 @@
1
+ export function info(msg) {
2
+ console.log(`\x1b[36m→\x1b[0m ${msg}`);
3
+ }
4
+ export function ok(msg) {
5
+ console.log(`\x1b[32m✓\x1b[0m ${msg}`);
6
+ }
7
+ export function warn(msg) {
8
+ console.warn(`\x1b[33m!\x1b[0m ${msg}`);
9
+ }
10
+ export function fail(msg) {
11
+ console.error(`\x1b[31m✗\x1b[0m ${msg}`);
12
+ process.exit(1);
13
+ }
14
+ export function title(msg) {
15
+ console.log(`\n\x1b[1m${msg}\x1b[0m\n`);
16
+ }
17
+ //# sourceMappingURL=log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/utils/log.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,IAAI,CAAC,GAAW;IAC9B,OAAO,CAAC,GAAG,CAAC,oBAAoB,GAAG,EAAE,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,EAAE,CAAC,GAAW;IAC5B,OAAO,CAAC,GAAG,CAAC,oBAAoB,GAAG,EAAE,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,GAAW;IAC9B,OAAO,CAAC,IAAI,CAAC,oBAAoB,GAAG,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,GAAW;IAC9B,OAAO,CAAC,KAAK,CAAC,oBAAoB,GAAG,EAAE,CAAC,CAAC;IACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,GAAW;IAC/B,OAAO,CAAC,GAAG,CAAC,YAAY,GAAG,WAAW,CAAC,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function prompt(question: string, defaultValue?: string): Promise<string>;
2
+ export declare function promptRequired(question: string, validate?: (v: string) => string | null): Promise<string>;
3
+ export declare function promptOptional(question: string): Promise<string | undefined>;
4
+ //# sourceMappingURL=prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/utils/prompt.ts"],"names":[],"mappings":"AAGA,wBAAsB,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CASrF;AAED,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAgB/G;AAED,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAGlF"}
@@ -0,0 +1,35 @@
1
+ import * as readline from 'node:readline/promises';
2
+ import { stdin as input, stdout as output } from 'node:process';
3
+ export async function prompt(question, defaultValue) {
4
+ const rl = readline.createInterface({ input, output });
5
+ try {
6
+ const suffix = defaultValue ? ` (${defaultValue})` : '';
7
+ const answer = (await rl.question(`${question}${suffix}: `)).trim();
8
+ return answer || defaultValue || '';
9
+ }
10
+ finally {
11
+ rl.close();
12
+ }
13
+ }
14
+ export async function promptRequired(question, validate) {
15
+ for (;;) {
16
+ const value = await prompt(question);
17
+ if (!value) {
18
+ console.log(' Required value.');
19
+ continue;
20
+ }
21
+ if (validate) {
22
+ const err = validate(value);
23
+ if (err) {
24
+ console.log(` ${err}`);
25
+ continue;
26
+ }
27
+ }
28
+ return value;
29
+ }
30
+ }
31
+ export async function promptOptional(question) {
32
+ const value = await prompt(question);
33
+ return value.trim() || undefined;
34
+ }
35
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/utils/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,KAAK,IAAI,KAAK,EAAE,MAAM,IAAI,MAAM,EAAE,MAAM,cAAc,CAAC;AAEhE,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,QAAgB,EAAE,YAAqB;IAClE,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IACvD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,KAAK,YAAY,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QACxD,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,GAAG,QAAQ,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACpE,OAAO,MAAM,IAAI,YAAY,IAAI,EAAE,CAAC;IACtC,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,QAAgB,EAAE,QAAuC;IAC5F,SAAS,CAAC;QACR,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;QACrC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;YACjC,SAAS;QACX,CAAC;QACD,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;YAC5B,IAAI,GAAG,EAAE,CAAC;gBACR,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;gBACxB,SAAS;YACX,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,QAAgB;IACnD,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;IACrC,OAAO,KAAK,CAAC,IAAI,EAAE,IAAI,SAAS,CAAC;AACnC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "sublyzer-snapshot",
3
+ "version": "0.3.0",
4
+ "description": "Open-source CLI — scan any project and push a health snapshot to Sublyzer in seconds",
5
+ "author": "Sublyzer <sublyzerone@gmail.com>",
6
+ "license": "MIT",
7
+ "homepage": "https://github.com/sublyzer-one/sublyzer-snapshot#readme",
8
+ "bugs": {
9
+ "url": "https://github.com/sublyzer-one/sublyzer-snapshot/issues"
10
+ },
11
+ "type": "module",
12
+ "bin": {
13
+ "sublyzer-snapshot": "./dist/cli.js"
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md",
18
+ "LICENSE"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsc",
22
+ "dev": "tsx src/cli.ts",
23
+ "prepublishOnly": "npm run build"
24
+ },
25
+ "engines": {
26
+ "node": ">=18"
27
+ },
28
+ "keywords": [
29
+ "sublyzer",
30
+ "monitoring",
31
+ "snapshot",
32
+ "cli",
33
+ "devtools",
34
+ "nextjs",
35
+ "nestjs",
36
+ "security",
37
+ "observability"
38
+ ],
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "https://github.com/sublyzer-one/sublyzer-snapshot.git"
42
+ },
43
+ "dependencies": {
44
+ "commander": "^12.1.0"
45
+ },
46
+ "devDependencies": {
47
+ "@types/node": "^22.10.0",
48
+ "tsx": "^4.19.2",
49
+ "typescript": "^5.7.2"
50
+ }
51
+ }