@nexus_js/cli 0.6.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 +52 -0
- package/dist/add.d.ts +36 -0
- package/dist/add.d.ts.map +1 -0
- package/dist/add.js +342 -0
- package/dist/add.js.map +1 -0
- package/dist/analyzer.d.ts +70 -0
- package/dist/analyzer.d.ts.map +1 -0
- package/dist/analyzer.js +247 -0
- package/dist/analyzer.js.map +1 -0
- package/dist/audit.d.ts +35 -0
- package/dist/audit.d.ts.map +1 -0
- package/dist/audit.js +383 -0
- package/dist/audit.js.map +1 -0
- package/dist/bin.d.ts +6 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +367 -0
- package/dist/bin.js.map +1 -0
- package/dist/config.d.ts +41 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +2 -0
- package/dist/config.js.map +1 -0
- package/dist/create.d.ts +7 -0
- package/dist/create.d.ts.map +1 -0
- package/dist/create.js +256 -0
- package/dist/create.js.map +1 -0
- package/dist/fix.d.ts +22 -0
- package/dist/fix.d.ts.map +1 -0
- package/dist/fix.js +199 -0
- package/dist/fix.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/studio.d.ts +136 -0
- package/dist/studio.d.ts.map +1 -0
- package/dist/studio.js +721 -0
- package/dist/studio.js.map +1 -0
- package/package.json +63 -0
package/dist/analyzer.js
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nexus Bundle Budget Analyzer
|
|
3
|
+
*
|
|
4
|
+
* Generates a detailed visual report of JS payload per route.
|
|
5
|
+
* Runs automatically after `nexus build` or standalone with `nexus analyze`.
|
|
6
|
+
*
|
|
7
|
+
* Terminal output:
|
|
8
|
+
*
|
|
9
|
+
* ◆ Nexus Bundle Analysis
|
|
10
|
+
* ════════════════════════════════════════════════════════
|
|
11
|
+
*
|
|
12
|
+
* Route: /
|
|
13
|
+
* ┌─────────────────────────────┬────────┬────────┬───────┐
|
|
14
|
+
* │ Module │ Raw │ Gzip │ Share │
|
|
15
|
+
* ├─────────────────────────────┼────────┼────────┼───────┤
|
|
16
|
+
* │ @nexus_js/runtime (shared) │ 4.2KB │ 1.8KB │ ███░ │
|
|
17
|
+
* │ islands/Counter.client.js │ 1.1KB │ 0.5KB │ █░░░ │
|
|
18
|
+
* │ islands/SearchBar.client.js │ 2.8KB │ 1.1KB │ ██░░ │
|
|
19
|
+
* ├─────────────────────────────┼────────┼────────┼───────┤
|
|
20
|
+
* │ TOTAL │ 8.1KB │ 3.4KB │ │
|
|
21
|
+
* └─────────────────────────────┴────────┴────────┴───────┘
|
|
22
|
+
* Budget: ✓ Under 10KB limit
|
|
23
|
+
*
|
|
24
|
+
* Route: /blog/[slug] ← OVER BUDGET ⚠
|
|
25
|
+
* ...
|
|
26
|
+
*
|
|
27
|
+
* ─── Summary ─────────────────────────────────────────────
|
|
28
|
+
* Routes analyzed: 12
|
|
29
|
+
* Under budget: 10
|
|
30
|
+
* Over budget: 2 ⚠ /dashboard, /checkout
|
|
31
|
+
* Largest route: /checkout (48KB gzip)
|
|
32
|
+
* Zero-JS routes: 4 (/, /about, /blog, /contact)
|
|
33
|
+
*/
|
|
34
|
+
import { readFile, stat } from 'node:fs/promises';
|
|
35
|
+
import { join, relative } from 'node:path';
|
|
36
|
+
// ── ANSI helpers ──────────────────────────────────────────────────────────────
|
|
37
|
+
const C = {
|
|
38
|
+
reset: '\x1b[0m',
|
|
39
|
+
bold: '\x1b[1m',
|
|
40
|
+
dim: '\x1b[2m',
|
|
41
|
+
red: '\x1b[31m',
|
|
42
|
+
green: '\x1b[32m',
|
|
43
|
+
yellow: '\x1b[33m',
|
|
44
|
+
cyan: '\x1b[36m',
|
|
45
|
+
white: '\x1b[37m',
|
|
46
|
+
bgRed: '\x1b[41m',
|
|
47
|
+
bgGreen: '\x1b[42m',
|
|
48
|
+
};
|
|
49
|
+
// ── Main entry ────────────────────────────────────────────────────────────────
|
|
50
|
+
export async function analyzeBundles(opts) {
|
|
51
|
+
const budgetBytes = opts.budgetBytes ?? 50 * 1024; // 50KB gzip default
|
|
52
|
+
const outDir = join(opts.root, '.nexus', 'output');
|
|
53
|
+
const verbose = opts.verbose ?? true;
|
|
54
|
+
const routes = await collectRouteBudgets(outDir, budgetBytes);
|
|
55
|
+
const runtimeSize = await measureRuntime(outDir);
|
|
56
|
+
const report = {
|
|
57
|
+
routes,
|
|
58
|
+
runtimeSize,
|
|
59
|
+
generatedAt: new Date().toISOString(),
|
|
60
|
+
totalIslands: routes.flatMap((r) => r.modules.filter((m) => m.kind === 'island')).length,
|
|
61
|
+
zeroJSRoutes: routes.filter((r) => r.isZeroJS).length,
|
|
62
|
+
overBudgetRoutes: routes.filter((r) => r.overBudget).map((r) => r.route),
|
|
63
|
+
};
|
|
64
|
+
// Output
|
|
65
|
+
if (opts.format === 'json') {
|
|
66
|
+
const json = JSON.stringify(report, null, 2);
|
|
67
|
+
if (opts.outFile) {
|
|
68
|
+
const { writeFile } = await import('node:fs/promises');
|
|
69
|
+
await writeFile(opts.outFile, json, 'utf-8');
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
console.log(json);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
printTerminalReport(report, verbose);
|
|
77
|
+
}
|
|
78
|
+
return report;
|
|
79
|
+
}
|
|
80
|
+
// ── Route budget collection ───────────────────────────────────────────────────
|
|
81
|
+
async function collectRouteBudgets(outDir, budgetBytes) {
|
|
82
|
+
const routes = [];
|
|
83
|
+
// Read the manifest
|
|
84
|
+
let manifest;
|
|
85
|
+
try {
|
|
86
|
+
const raw = await readFile(join(outDir, 'manifest.json'), 'utf-8');
|
|
87
|
+
manifest = JSON.parse(raw);
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return [];
|
|
91
|
+
}
|
|
92
|
+
for (const route of manifest.routes) {
|
|
93
|
+
const modules = [];
|
|
94
|
+
// Check for client bundle
|
|
95
|
+
const clientPath = route.filepath.replace(/\.nx$/, '.client.js');
|
|
96
|
+
const clientAbs = join(outDir, clientPath);
|
|
97
|
+
try {
|
|
98
|
+
const info = await stat(clientAbs);
|
|
99
|
+
if (info.isFile()) {
|
|
100
|
+
const content = await readFile(clientAbs);
|
|
101
|
+
modules.push({
|
|
102
|
+
name: relative(outDir, clientAbs),
|
|
103
|
+
path: clientAbs,
|
|
104
|
+
rawBytes: content.length,
|
|
105
|
+
gzipBytes: estimateGzip(content.length),
|
|
106
|
+
kind: 'island',
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
catch { }
|
|
111
|
+
const totalRaw = modules.reduce((s, m) => s + m.rawBytes, 0);
|
|
112
|
+
const totalGzip = modules.reduce((s, m) => s + m.gzipBytes, 0);
|
|
113
|
+
routes.push({
|
|
114
|
+
route: route.pattern,
|
|
115
|
+
modules,
|
|
116
|
+
totalRaw,
|
|
117
|
+
totalGzip,
|
|
118
|
+
isZeroJS: modules.length === 0,
|
|
119
|
+
overBudget: totalGzip > budgetBytes,
|
|
120
|
+
budgetBytes,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
return routes;
|
|
124
|
+
}
|
|
125
|
+
async function measureRuntime(outDir) {
|
|
126
|
+
try {
|
|
127
|
+
const runtimePath = join(outDir, 'runtime.js');
|
|
128
|
+
const info = await stat(runtimePath);
|
|
129
|
+
return estimateGzip(info.size);
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
return 0; // Runtime not found — report 0
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// ── Terminal renderer ─────────────────────────────────────────────────────────
|
|
136
|
+
function printTerminalReport(report, verbose) {
|
|
137
|
+
const width = 66;
|
|
138
|
+
const line = '═'.repeat(width);
|
|
139
|
+
const thin = '─'.repeat(width);
|
|
140
|
+
console.log('');
|
|
141
|
+
console.log(` ${C.cyan}${C.bold}◆ Nexus Bundle Analysis${C.reset}`);
|
|
142
|
+
console.log(` ${C.dim}${line}${C.reset}`);
|
|
143
|
+
console.log('');
|
|
144
|
+
// Runtime overhead
|
|
145
|
+
if (report.runtimeSize > 0) {
|
|
146
|
+
console.log(` ${C.dim}Shared Runtime${C.reset} ${fmtSize(report.runtimeSize)} gzip ${C.dim}(amortized across all routes)${C.reset}`);
|
|
147
|
+
console.log('');
|
|
148
|
+
}
|
|
149
|
+
for (const route of report.routes) {
|
|
150
|
+
const statusIcon = route.isZeroJS
|
|
151
|
+
? `${C.green}◉ 0 JS${C.reset}`
|
|
152
|
+
: route.overBudget
|
|
153
|
+
? `${C.red}⚠ OVER BUDGET${C.reset}`
|
|
154
|
+
: `${C.green}✓${C.reset}`;
|
|
155
|
+
console.log(` ${C.bold}Route: ${route.route}${C.reset} ${statusIcon}`);
|
|
156
|
+
if (route.isZeroJS) {
|
|
157
|
+
console.log(` ${C.dim}No JavaScript sent to client — pure HTML${C.reset}`);
|
|
158
|
+
console.log('');
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
if (verbose && route.modules.length > 0) {
|
|
162
|
+
// Table header
|
|
163
|
+
console.log(` ${C.dim}┌${'─'.repeat(32)}┬────────┬────────┬──────────┐${C.reset}`);
|
|
164
|
+
console.log(` ${C.dim}│${C.reset} ${pad('Module', 30)} ${C.dim}│${C.reset} ${C.dim}Raw ${C.reset}${C.dim}│${C.reset} ${C.dim}Gzip ${C.reset}${C.dim}│${C.reset} Budget ${C.dim}│${C.reset}`);
|
|
165
|
+
console.log(` ${C.dim}├${'─'.repeat(32)}┼────────┼────────┼──────────┤${C.reset}`);
|
|
166
|
+
for (const mod of route.modules) {
|
|
167
|
+
const share = Math.min(1, mod.gzipBytes / route.budgetBytes);
|
|
168
|
+
const bar = buildBar(share, 8);
|
|
169
|
+
const name = truncate(mod.name, 30);
|
|
170
|
+
const kindBadge = kindColor(mod.kind);
|
|
171
|
+
console.log(` ${C.dim}│${C.reset} ${kindBadge}${pad(name, 30)}${C.reset} ${C.dim}│${C.reset} ${pad(fmtSize(mod.rawBytes), 6)} ${C.dim}│${C.reset} ${pad(fmtSize(mod.gzipBytes), 6)} ${C.dim}│${C.reset} ${bar} ${C.dim}│${C.reset}`);
|
|
172
|
+
}
|
|
173
|
+
console.log(` ${C.dim}├${'─'.repeat(32)}┼────────┼────────┼──────────┤${C.reset}`);
|
|
174
|
+
const totalColor = route.overBudget ? C.red : C.green;
|
|
175
|
+
console.log(` ${C.dim}│${C.reset} ${C.bold}${pad('TOTAL', 30)}${C.reset} ${C.dim}│${C.reset} ${pad(fmtSize(route.totalRaw), 6)} ${C.dim}│${C.reset} ${totalColor}${pad(fmtSize(route.totalGzip), 6)}${C.reset} ${C.dim}│${C.reset} ${buildBudgetBar(route)} ${C.dim}│${C.reset}`);
|
|
176
|
+
console.log(` ${C.dim}└${'─'.repeat(32)}┴────────┴────────┴──────────┘${C.reset}`);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
const totalColor = route.overBudget ? C.red : C.green;
|
|
180
|
+
console.log(` JS: ${fmtSize(route.totalRaw)} raw ${totalColor}${fmtSize(route.totalGzip)} gzip${C.reset} (${route.modules.length} island${route.modules.length !== 1 ? 's' : ''})`);
|
|
181
|
+
}
|
|
182
|
+
if (route.overBudget) {
|
|
183
|
+
const excess = fmtSize(route.totalGzip - route.budgetBytes);
|
|
184
|
+
console.log(` ${C.red}Budget exceeded by ${excess}. Consider: client:visible, code-splitting, or reducing island scope.${C.reset}`);
|
|
185
|
+
}
|
|
186
|
+
console.log('');
|
|
187
|
+
}
|
|
188
|
+
// Summary
|
|
189
|
+
console.log(` ${C.dim}${thin}${C.reset}`);
|
|
190
|
+
console.log(` ${C.bold}Summary${C.reset}`);
|
|
191
|
+
console.log(` Routes analyzed: ${report.routes.length}`);
|
|
192
|
+
console.log(` ${C.green}Zero-JS routes: ${report.zeroJSRoutes}${C.reset}`);
|
|
193
|
+
console.log(` Total islands: ${report.totalIslands}`);
|
|
194
|
+
if (report.overBudgetRoutes.length > 0) {
|
|
195
|
+
console.log(` ${C.red}Over budget: ${report.overBudgetRoutes.length}${C.reset}`);
|
|
196
|
+
for (const r of report.overBudgetRoutes) {
|
|
197
|
+
console.log(` ${C.dim}↳ ${r}${C.reset}`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
console.log(` ${C.green}All routes within budget ✓${C.reset}`);
|
|
202
|
+
}
|
|
203
|
+
console.log('');
|
|
204
|
+
}
|
|
205
|
+
// ── Formatters ────────────────────────────────────────────────────────────────
|
|
206
|
+
function fmtSize(bytes) {
|
|
207
|
+
if (bytes === 0)
|
|
208
|
+
return '0B';
|
|
209
|
+
if (bytes < 1024)
|
|
210
|
+
return `${bytes}B`;
|
|
211
|
+
if (bytes < 1024 * 1024)
|
|
212
|
+
return `${(bytes / 1024).toFixed(1)}KB`;
|
|
213
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
214
|
+
}
|
|
215
|
+
function pad(s, n) {
|
|
216
|
+
return s.length >= n ? s.slice(0, n) : s + ' '.repeat(n - s.length);
|
|
217
|
+
}
|
|
218
|
+
function truncate(s, n) {
|
|
219
|
+
return s.length > n ? '…' + s.slice(-(n - 1)) : s;
|
|
220
|
+
}
|
|
221
|
+
function buildBar(share, width) {
|
|
222
|
+
const filled = Math.round(share * width);
|
|
223
|
+
const empty = width - filled;
|
|
224
|
+
return `${C.cyan}${'█'.repeat(filled)}${C.dim}${'░'.repeat(empty)}${C.reset}`;
|
|
225
|
+
}
|
|
226
|
+
function buildBudgetBar(route) {
|
|
227
|
+
const share = Math.min(1, route.totalGzip / route.budgetBytes);
|
|
228
|
+
const width = 8;
|
|
229
|
+
const filled = Math.round(share * width);
|
|
230
|
+
const empty = width - filled;
|
|
231
|
+
const color = route.overBudget ? C.red : C.green;
|
|
232
|
+
return `${color}${'█'.repeat(Math.min(filled, width))}${C.dim}${'░'.repeat(Math.max(0, empty))}${C.reset}`;
|
|
233
|
+
}
|
|
234
|
+
function kindColor(kind) {
|
|
235
|
+
switch (kind) {
|
|
236
|
+
case 'runtime': return C.cyan;
|
|
237
|
+
case 'island': return C.green;
|
|
238
|
+
case 'shared': return C.yellow;
|
|
239
|
+
case 'action': return '\x1b[35m';
|
|
240
|
+
default: return '';
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/** Estimate gzip size: typically ~40% of raw for JS */
|
|
244
|
+
function estimateGzip(rawBytes) {
|
|
245
|
+
return Math.round(rawBytes * 0.4);
|
|
246
|
+
}
|
|
247
|
+
//# sourceMappingURL=analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"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"}
|
package/dist/audit.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* nexus audit — Security & Best Practices Auditor.
|
|
3
|
+
*
|
|
4
|
+
* Unlike `npm audit` (which only checks dependency CVEs), Nexus audit
|
|
5
|
+
* analyzes your application code and architecture for security issues:
|
|
6
|
+
*
|
|
7
|
+
* 1. Secret Leaks — env vars / keys referenced in client code
|
|
8
|
+
* 2. Missing CSRF — Server Actions without csrf protection
|
|
9
|
+
* 3. No Auth Guard — Routes that likely need authentication but don't have it
|
|
10
|
+
* 4. XSS Vectors — `innerHTML`, `dangerouslySetInnerHTML` patterns in islands
|
|
11
|
+
* 5. Security Headers — Missing CSP, HSTS, X-Frame-Options in nexus.config.ts
|
|
12
|
+
* 6. Forms Without Validation — Action handlers with no schema
|
|
13
|
+
* 7. Hardcoded Secrets — API keys embedded in source files
|
|
14
|
+
* 8. Open Redirects — Unvalidated redirect targets
|
|
15
|
+
* 9. Rate Limit Coverage — Public actions without rate limiting
|
|
16
|
+
* 10. Dependency Audit — Wraps npm/pnpm audit for CVE summary
|
|
17
|
+
*/
|
|
18
|
+
export type Severity = 'critical' | 'high' | 'medium' | 'low' | 'info';
|
|
19
|
+
export interface AuditFinding {
|
|
20
|
+
severity: Severity;
|
|
21
|
+
category: string;
|
|
22
|
+
title: string;
|
|
23
|
+
description: string;
|
|
24
|
+
file?: string;
|
|
25
|
+
line?: number;
|
|
26
|
+
fix?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface AuditOptions {
|
|
29
|
+
root: string;
|
|
30
|
+
fix?: boolean;
|
|
31
|
+
ci?: boolean;
|
|
32
|
+
json?: boolean;
|
|
33
|
+
}
|
|
34
|
+
export declare function runAudit(opts: AuditOptions): Promise<void>;
|
|
35
|
+
//# sourceMappingURL=audit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAwBH,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;AAEvE,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAK,QAAQ,CAAC;IACtB,QAAQ,EAAK,MAAM,CAAC;IACpB,KAAK,EAAQ,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAQ,MAAM,CAAC;IACpB,IAAI,CAAC,EAAQ,MAAM,CAAC;IACpB,GAAG,CAAC,EAAS,MAAM,CAAC;CACrB;AA6WD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAI,MAAM,CAAC;IACf,GAAG,CAAC,EAAI,OAAO,CAAC;IAChB,EAAE,CAAC,EAAK,OAAO,CAAC;IAChB,IAAI,CAAC,EAAG,OAAO,CAAC;CACjB;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAsChE"}
|