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.
- package/LICENSE +21 -0
- package/README.md +306 -0
- package/dist/api/sublyzer.d.ts +29 -0
- package/dist/api/sublyzer.d.ts.map +1 -0
- package/dist/api/sublyzer.js +61 -0
- package/dist/api/sublyzer.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +199 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/ci.d.ts +9 -0
- package/dist/commands/ci.d.ts.map +1 -0
- package/dist/commands/ci.js +65 -0
- package/dist/commands/ci.js.map +1 -0
- package/dist/commands/compare.d.ts +7 -0
- package/dist/commands/compare.d.ts.map +1 -0
- package/dist/commands/compare.js +60 -0
- package/dist/commands/compare.js.map +1 -0
- package/dist/commands/doctor.d.ts +13 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +100 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/init.d.ts +10 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +88 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/open.d.ts +2 -0
- package/dist/commands/open.d.ts.map +1 -0
- package/dist/commands/open.js +16 -0
- package/dist/commands/open.js.map +1 -0
- package/dist/commands/pull.d.ts +9 -0
- package/dist/commands/pull.d.ts.map +1 -0
- package/dist/commands/pull.js +34 -0
- package/dist/commands/pull.js.map +1 -0
- package/dist/commands/report.d.ts +8 -0
- package/dist/commands/report.d.ts.map +1 -0
- package/dist/commands/report.js +47 -0
- package/dist/commands/report.js.map +1 -0
- package/dist/commands/run.d.ts +21 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +96 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/status.d.ts +5 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +52 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/config.d.ts +36 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +58 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.d.ts +13 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +12 -0
- package/dist/constants.js.map +1 -0
- package/dist/detect/git.d.ts +9 -0
- package/dist/detect/git.d.ts.map +1 -0
- package/dist/detect/git.js +25 -0
- package/dist/detect/git.js.map +1 -0
- package/dist/detect/meta.d.ts +8 -0
- package/dist/detect/meta.d.ts.map +1 -0
- package/dist/detect/meta.js +42 -0
- package/dist/detect/meta.js.map +1 -0
- package/dist/detect/routes.d.ts +2 -0
- package/dist/detect/routes.d.ts.map +1 -0
- package/dist/detect/routes.js +104 -0
- package/dist/detect/routes.js.map +1 -0
- package/dist/detect/stack.d.ts +15 -0
- package/dist/detect/stack.d.ts.map +1 -0
- package/dist/detect/stack.js +114 -0
- package/dist/detect/stack.js.map +1 -0
- package/dist/detect/workspaces.d.ts +6 -0
- package/dist/detect/workspaces.d.ts.map +1 -0
- package/dist/detect/workspaces.js +54 -0
- package/dist/detect/workspaces.js.map +1 -0
- package/dist/report/markdown.d.ts +5 -0
- package/dist/report/markdown.d.ts.map +1 -0
- package/dist/report/markdown.js +81 -0
- package/dist/report/markdown.js.map +1 -0
- package/dist/scan/audit.d.ts +16 -0
- package/dist/scan/audit.d.ts.map +1 -0
- package/dist/scan/audit.js +53 -0
- package/dist/scan/audit.js.map +1 -0
- package/dist/scan/health-score.d.ts +13 -0
- package/dist/scan/health-score.d.ts.map +1 -0
- package/dist/scan/health-score.js +60 -0
- package/dist/scan/health-score.js.map +1 -0
- package/dist/scan/history.d.ts +21 -0
- package/dist/scan/history.d.ts.map +1 -0
- package/dist/scan/history.js +82 -0
- package/dist/scan/history.js.map +1 -0
- package/dist/scan/outdated.d.ts +15 -0
- package/dist/scan/outdated.d.ts.map +1 -0
- package/dist/scan/outdated.js +54 -0
- package/dist/scan/outdated.js.map +1 -0
- package/dist/scan/policy.d.ts +5 -0
- package/dist/scan/policy.d.ts.map +1 -0
- package/dist/scan/policy.js +20 -0
- package/dist/scan/policy.js.map +1 -0
- package/dist/scan/snapshot.d.ts +47 -0
- package/dist/scan/snapshot.d.ts.map +1 -0
- package/dist/scan/snapshot.js +176 -0
- package/dist/scan/snapshot.js.map +1 -0
- package/dist/utils/gitignore.d.ts +3 -0
- package/dist/utils/gitignore.d.ts.map +1 -0
- package/dist/utils/gitignore.js +34 -0
- package/dist/utils/gitignore.js.map +1 -0
- package/dist/utils/log.d.ts +6 -0
- package/dist/utils/log.d.ts.map +1 -0
- package/dist/utils/log.js +17 -0
- package/dist/utils/log.js.map +1 -0
- package/dist/utils/prompt.d.ts +4 -0
- package/dist/utils/prompt.d.ts.map +1 -0
- package/dist/utils/prompt.js +35 -0
- package/dist/utils/prompt.js.map +1 -0
- 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 @@
|
|
|
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
|
+
}
|