@mauroandre/velojs 0.0.38 → 0.0.39
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/agent/skills/velojs-project-graph/SKILL.md +97 -0
- package/dist/cli.js +42 -31
- package/dist/graph.d.ts +37 -0
- package/dist/graph.js +202 -0
- package/dist/init.js +16 -7
- package/dist/vite.js +279 -248
- package/package.json +1 -1
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: velojs-project-graph
|
|
3
|
+
description: "Use `.velojs/graph.json` to understand the project's route tree and module dependency graph before reading any source files. Always consult the graph first when exploring a VeloJS codebase. Generate it with `velojs graph` if missing."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Project Graph
|
|
7
|
+
|
|
8
|
+
VeloJS can generate a structural snapshot of your project — the route tree hierarchy, module dependency graph, and convention exports — as a single JSON file at `.velojs/graph.json`. This file gives an AI agent (or any tool) a complete map of the codebase in a few KB, replacing dozens of exploratory file reads.
|
|
9
|
+
|
|
10
|
+
## When to use
|
|
11
|
+
|
|
12
|
+
Always. Before reading any source file in a VeloJS project, check `.velojs/graph.json` first. It tells you:
|
|
13
|
+
|
|
14
|
+
- **Route tree** — full hierarchy of layouts, pages, paths, `isRoot`, and middlewares
|
|
15
|
+
- **Module dependencies** — for every module: what it imports (`imports`) and who imports it (`importedBy`)
|
|
16
|
+
- **Convention exports** — which modules export `loader`, `action_*`, `stream_*`, `socket_*`
|
|
17
|
+
|
|
18
|
+
## Generating the graph
|
|
19
|
+
|
|
20
|
+
If `.velojs/graph.json` does not exist, generate it:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
velojs graph
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
This runs a fast Babel-based crawl of `app/routes.tsx` and its transitive imports. No build. No Vite. Sub-second. Works even if the project does not compile.
|
|
27
|
+
|
|
28
|
+
The graph is also regenerated automatically on every `velojs build` (via the `velo:graph` plugin) and on every file change during `velojs dev`.
|
|
29
|
+
|
|
30
|
+
## Graph structure
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
interface GraphJson {
|
|
34
|
+
routes: RouteTreeNode[];
|
|
35
|
+
modules: Record<string, ModuleInfo>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface RouteTreeNode {
|
|
39
|
+
moduleId: string | null; // e.g. "pages/Home", null if no module
|
|
40
|
+
fullPath: string | null; // e.g. "/admin/users/:id"
|
|
41
|
+
path: string | null; // e.g. "/users/:id"
|
|
42
|
+
isRoot: boolean; // root layout (renders <html>)
|
|
43
|
+
middlewares: string[]; // middleware identifiers
|
|
44
|
+
children: RouteTreeNode[];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
interface ModuleInfo {
|
|
48
|
+
file: string; // relative path from project root
|
|
49
|
+
kind: "root" | "layout" | "page" | "unknown";
|
|
50
|
+
exports: {
|
|
51
|
+
hasComponent: boolean;
|
|
52
|
+
hasLoader: boolean;
|
|
53
|
+
actions: string[]; // e.g. ["save", "delete"]
|
|
54
|
+
streams: string[]; // e.g. ["progress", "logs"]
|
|
55
|
+
sockets: string[]; // e.g. ["terminal"]
|
|
56
|
+
};
|
|
57
|
+
imports: string[]; // moduleIds this module depends on
|
|
58
|
+
importedBy: string[]; // moduleIds that depend on this module
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Common queries
|
|
63
|
+
|
|
64
|
+
### "Which routes use this loader?"
|
|
65
|
+
|
|
66
|
+
1. Find the loader's module in `modules` → note its `moduleId`
|
|
67
|
+
2. Search `routes` recursively for nodes where `moduleId` matches
|
|
68
|
+
3. The matching node's ancestors are the layouts wrapping it
|
|
69
|
+
|
|
70
|
+
### "What breaks if I change this file?"
|
|
71
|
+
|
|
72
|
+
1. Find the module in `modules[moduleId]`
|
|
73
|
+
2. Follow `importedBy` — these modules import it
|
|
74
|
+
3. Transitively follow `importedBy` on those modules
|
|
75
|
+
4. Filter to modules where `kind` is `"page"` to see which pages are affected
|
|
76
|
+
|
|
77
|
+
### "What actions does this page expose?"
|
|
78
|
+
|
|
79
|
+
1. Find the page in `modules[moduleId]`
|
|
80
|
+
2. Read `exports.actions` — e.g. `["save", "delete"]`
|
|
81
|
+
3. These are the `action_*` exports callable from the client
|
|
82
|
+
|
|
83
|
+
### "Where is the auth middleware applied?"
|
|
84
|
+
|
|
85
|
+
1. Search `routes` recursively for nodes where `middlewares` includes the auth middleware name
|
|
86
|
+
2. The matching nodes and their children are protected
|
|
87
|
+
|
|
88
|
+
### "Which modules have no tests?"
|
|
89
|
+
|
|
90
|
+
Compare `modules` keys against the `tests/` directory. Modules with no corresponding test file are candidates for new tests.
|
|
91
|
+
|
|
92
|
+
## Notes
|
|
93
|
+
|
|
94
|
+
- External imports (`@mauroandre/velojs`, `preact`, `wouter-preact`) are recorded in `imports` but not crawled
|
|
95
|
+
- `export function action_*` is NOT detected — only `export const action_*` (matches framework behavior)
|
|
96
|
+
- Path-less layouts (no `path` property) have `fullPath: ""` and `path: ""`
|
|
97
|
+
- The graph is regenerated on every build and on file changes during dev — never stale
|
package/dist/cli.js
CHANGED
|
@@ -1,43 +1,44 @@
|
|
|
1
|
-
import { spawnSync as
|
|
2
|
-
import { resolve as
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { spawnSync as a } from "node:child_process";
|
|
2
|
+
import { join as n, resolve as u } from "node:path";
|
|
3
|
+
import p from "node:fs";
|
|
4
|
+
const r = process.argv.slice(2), c = r[0], v = (e, s = []) => {
|
|
5
|
+
const t = a(e, s, {
|
|
5
6
|
stdio: "inherit",
|
|
6
7
|
cwd: process.cwd()
|
|
7
8
|
});
|
|
8
|
-
process.exit(
|
|
9
|
-
},
|
|
10
|
-
|
|
11
|
-
},
|
|
12
|
-
const
|
|
9
|
+
process.exit(t.status ?? 0);
|
|
10
|
+
}, g = () => {
|
|
11
|
+
v("npx", ["vite", ...r.slice(1)]);
|
|
12
|
+
}, h = (e) => {
|
|
13
|
+
const s = Date.now().toString(36), t = {
|
|
13
14
|
...process.env,
|
|
14
|
-
VELO_BUILD_HASH:
|
|
15
|
+
VELO_BUILD_HASH: s,
|
|
15
16
|
...e ? { VELO_STATIC: "1" } : {}
|
|
16
17
|
};
|
|
17
18
|
console.log("Building client...");
|
|
18
|
-
const o =
|
|
19
|
+
const o = a("npx", ["vite", "build"], {
|
|
19
20
|
stdio: "inherit",
|
|
20
21
|
cwd: process.cwd(),
|
|
21
|
-
env:
|
|
22
|
+
env: t
|
|
22
23
|
});
|
|
23
24
|
o.status !== 0 && (console.error("Client build failed. Aborting."), process.exit(o.status ?? 1)), console.log("Building server...");
|
|
24
|
-
const
|
|
25
|
+
const i = a("npx", ["vite", "build", "--mode", "server"], {
|
|
25
26
|
stdio: "inherit",
|
|
26
27
|
cwd: process.cwd(),
|
|
27
|
-
env:
|
|
28
|
+
env: t
|
|
28
29
|
});
|
|
29
|
-
|
|
30
|
-
},
|
|
30
|
+
i.status !== 0 && (console.error("Server build failed. Aborting."), process.exit(i.status ?? 1)), console.log("Build complete!"), e && w();
|
|
31
|
+
}, w = async () => {
|
|
31
32
|
process.env.NODE_ENV = "production", process.env.VELO_STATIC = "1";
|
|
32
|
-
const
|
|
33
|
-
(!
|
|
34
|
-
const { generateStatic:
|
|
35
|
-
await
|
|
36
|
-
},
|
|
33
|
+
const s = await import(u(process.cwd(), "dist/server.js")), t = s.default, o = s.routes;
|
|
34
|
+
(!t || !o) && (console.error("Failed to load app or routes from dist/server.js"), process.exit(1));
|
|
35
|
+
const { generateStatic: i } = await import("./static.js");
|
|
36
|
+
await i(t, o);
|
|
37
|
+
}, b = () => {
|
|
37
38
|
process.env.NODE_ENV = "production";
|
|
38
|
-
const e =
|
|
39
|
-
|
|
40
|
-
},
|
|
39
|
+
const e = u(process.cwd(), "dist/server.js");
|
|
40
|
+
v("node", [e]);
|
|
41
|
+
}, d = () => {
|
|
41
42
|
console.log(`
|
|
42
43
|
VeloJS CLI
|
|
43
44
|
|
|
@@ -50,6 +51,7 @@ Commands:
|
|
|
50
51
|
build Build for production (client + server)
|
|
51
52
|
build --static Build as static site (HTML + JSON)
|
|
52
53
|
start Start production server
|
|
54
|
+
graph [app-dir] Generate .velojs/graph.json (route tree + dependency graph)
|
|
53
55
|
|
|
54
56
|
Examples:
|
|
55
57
|
velojs init my-app
|
|
@@ -57,30 +59,39 @@ Examples:
|
|
|
57
59
|
velojs build
|
|
58
60
|
velojs build --static
|
|
59
61
|
velojs start
|
|
62
|
+
velojs graph
|
|
63
|
+
velojs graph src/app
|
|
60
64
|
`);
|
|
61
65
|
};
|
|
62
66
|
switch (c) {
|
|
63
67
|
case "init": {
|
|
64
68
|
const { runInit: e } = await import("./init.js");
|
|
65
|
-
await e(
|
|
69
|
+
await e(r[1]);
|
|
66
70
|
break;
|
|
67
71
|
}
|
|
68
72
|
case "dev":
|
|
69
|
-
|
|
73
|
+
g();
|
|
70
74
|
break;
|
|
71
75
|
case "build": {
|
|
72
|
-
const e =
|
|
73
|
-
|
|
76
|
+
const e = r.includes("--static");
|
|
77
|
+
h(e);
|
|
74
78
|
break;
|
|
75
79
|
}
|
|
76
80
|
case "start":
|
|
77
|
-
|
|
81
|
+
b();
|
|
78
82
|
break;
|
|
83
|
+
case "graph": {
|
|
84
|
+
const { buildGraph: e } = await import("./graph.js"), s = process.cwd(), t = r[1] && !r[1].startsWith("-") ? r[1] : null, o = n(s, t ?? "app"), i = e(o), l = n(s, ".velojs");
|
|
85
|
+
p.mkdirSync(l, { recursive: !0 });
|
|
86
|
+
const m = n(l, "graph.json");
|
|
87
|
+
p.writeFileSync(m, JSON.stringify(i, null, 2)), console.log("Graph written to .velojs/graph.json");
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
79
90
|
case "help":
|
|
80
91
|
case "--help":
|
|
81
92
|
case "-h":
|
|
82
|
-
|
|
93
|
+
d();
|
|
83
94
|
break;
|
|
84
95
|
default:
|
|
85
|
-
c && console.error(`Unknown command: ${c}`),
|
|
96
|
+
c && console.error(`Unknown command: ${c}`), d(), process.exit(1);
|
|
86
97
|
}
|
package/dist/graph.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VeloJS Project Graph
|
|
3
|
+
*
|
|
4
|
+
* Builds a structural JSON snapshot of the project — route tree hierarchy,
|
|
5
|
+
* module dependency graph, and convention exports — from source code alone.
|
|
6
|
+
* No Vite, no dev server, no build. Used by `velojs graph` and by the
|
|
7
|
+
* `velo:graph` Vite plugin.
|
|
8
|
+
*/
|
|
9
|
+
export interface RouteTreeNode {
|
|
10
|
+
moduleId: string | null;
|
|
11
|
+
fullPath: string | null;
|
|
12
|
+
path: string | null;
|
|
13
|
+
isRoot: boolean;
|
|
14
|
+
middlewares: string[];
|
|
15
|
+
children: RouteTreeNode[];
|
|
16
|
+
}
|
|
17
|
+
export interface ModuleExports {
|
|
18
|
+
hasComponent: boolean;
|
|
19
|
+
hasLoader: boolean;
|
|
20
|
+
actions: string[];
|
|
21
|
+
streams: string[];
|
|
22
|
+
sockets: string[];
|
|
23
|
+
}
|
|
24
|
+
export interface ModuleInfo {
|
|
25
|
+
file: string;
|
|
26
|
+
kind: "root" | "layout" | "page" | "unknown";
|
|
27
|
+
exports: ModuleExports;
|
|
28
|
+
imports: string[];
|
|
29
|
+
importedBy: string[];
|
|
30
|
+
}
|
|
31
|
+
export interface GraphJson {
|
|
32
|
+
routes: RouteTreeNode[];
|
|
33
|
+
modules: Record<string, ModuleInfo>;
|
|
34
|
+
}
|
|
35
|
+
export declare function detectExports(filePath: string): ModuleExports;
|
|
36
|
+
export declare function buildRouteTree(code: string): RouteTreeNode[];
|
|
37
|
+
export declare function buildGraph(appDir: string): GraphJson;
|
package/dist/graph.js
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import y from "node:fs";
|
|
2
|
+
import E from "node:path";
|
|
3
|
+
import { parse as T } from "@babel/parser";
|
|
4
|
+
import w from "@babel/traverse";
|
|
5
|
+
import * as a from "@babel/types";
|
|
6
|
+
const g = typeof w == "function" ? w : w.default, W = /export\s+(const|function)\s+Component/, _ = /export\s+(const|function)\s+loader/, b = /export\s+const\s+action_(\w+)/g, k = /export\s+const\s+stream_(\w+)/g, M = /export\s+const\s+socket_(\w+)/g;
|
|
7
|
+
function A(i) {
|
|
8
|
+
let e;
|
|
9
|
+
try {
|
|
10
|
+
e = y.readFileSync(i, "utf-8");
|
|
11
|
+
} catch {
|
|
12
|
+
return {
|
|
13
|
+
hasComponent: !1,
|
|
14
|
+
hasLoader: !1,
|
|
15
|
+
actions: [],
|
|
16
|
+
streams: [],
|
|
17
|
+
sockets: []
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
const s = [];
|
|
21
|
+
let o;
|
|
22
|
+
const u = new RegExp(b.source, "g");
|
|
23
|
+
for (; (o = u.exec(e)) !== null; )
|
|
24
|
+
s.push(o[1]);
|
|
25
|
+
const t = [], c = new RegExp(k.source, "g");
|
|
26
|
+
for (; (o = c.exec(e)) !== null; )
|
|
27
|
+
t.push(o[1]);
|
|
28
|
+
const n = [], r = new RegExp(M.source, "g");
|
|
29
|
+
for (; (o = r.exec(e)) !== null; )
|
|
30
|
+
n.push(o[1]);
|
|
31
|
+
return {
|
|
32
|
+
hasComponent: W.test(e),
|
|
33
|
+
hasLoader: _.test(e),
|
|
34
|
+
actions: s,
|
|
35
|
+
streams: t,
|
|
36
|
+
sockets: n
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function C(i) {
|
|
40
|
+
const e = T(i, {
|
|
41
|
+
sourceType: "module",
|
|
42
|
+
plugins: ["typescript", "jsx"]
|
|
43
|
+
}), s = /* @__PURE__ */ new Map();
|
|
44
|
+
g(e, {
|
|
45
|
+
ImportDeclaration(u) {
|
|
46
|
+
const t = u.node.source.value;
|
|
47
|
+
for (const c of u.node.specifiers)
|
|
48
|
+
a.isImportNamespaceSpecifier(c) && s.set(c.local.name, t);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
let o = null;
|
|
52
|
+
return g(e, {
|
|
53
|
+
ExportDefaultDeclaration(u) {
|
|
54
|
+
const t = u.node.declaration;
|
|
55
|
+
a.isArrayExpression(t) ? o = t : (a.isTSSatisfiesExpression(t) || a.isTSAsExpression(t)) && a.isArrayExpression(t.expression) && (o = t.expression);
|
|
56
|
+
}
|
|
57
|
+
}), { imports: s, arrayNode: o };
|
|
58
|
+
}
|
|
59
|
+
function L(i, e) {
|
|
60
|
+
if (!i) return null;
|
|
61
|
+
const s = e.get(i);
|
|
62
|
+
return s ? s.replace(/^\.\//, "").replace(/\.(tsx?|jsx?|js)$/, "") : null;
|
|
63
|
+
}
|
|
64
|
+
function O(i, e, s) {
|
|
65
|
+
const o = [];
|
|
66
|
+
for (const u of i) {
|
|
67
|
+
if (!a.isObjectExpression(u)) continue;
|
|
68
|
+
let t = "", c = e, n = null, r = null, d = !1;
|
|
69
|
+
const x = [], m = u.properties.filter(
|
|
70
|
+
(l) => a.isObjectProperty(l)
|
|
71
|
+
);
|
|
72
|
+
for (const l of m) {
|
|
73
|
+
const j = l.key, I = a.isIdentifier(j) ? j.name : null;
|
|
74
|
+
if (I === "path" && a.isStringLiteral(l.value) && (t = l.value.value, t && !t.startsWith("/") ? c = e + "/" + t : c = e + t), I === "module" && a.isIdentifier(l.value) && (n = l.value.name), I === "children" && a.isArrayExpression(l.value) && (r = l.value), I === "isRoot" && a.isBooleanLiteral(l.value) && (d = l.value.value), I === "middlewares" && a.isArrayExpression(l.value))
|
|
75
|
+
for (const R of l.value.elements)
|
|
76
|
+
R && a.isIdentifier(R) && x.push(R.name);
|
|
77
|
+
}
|
|
78
|
+
const f = L(n, s), h = !r && t === "/" ? e || "/" : c, p = r ? O(r.elements, c, s) : [];
|
|
79
|
+
o.push({
|
|
80
|
+
moduleId: f,
|
|
81
|
+
fullPath: f ? h : null,
|
|
82
|
+
path: f ? t : null,
|
|
83
|
+
isRoot: d,
|
|
84
|
+
middlewares: x,
|
|
85
|
+
children: p
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return o;
|
|
89
|
+
}
|
|
90
|
+
function D(i) {
|
|
91
|
+
const { imports: e, arrayNode: s } = C(i);
|
|
92
|
+
return s ? O(s.elements, "", e) : [];
|
|
93
|
+
}
|
|
94
|
+
const S = [".tsx", ".ts", ".jsx", ".js"];
|
|
95
|
+
function F(i, e, s) {
|
|
96
|
+
if (e.startsWith(".") && (e.endsWith(".js") || e.endsWith(".jsx") || e.endsWith(".ts") || e.endsWith(".tsx"))) {
|
|
97
|
+
const o = E.dirname(i), t = E.resolve(o, e).replace(/\.(tsx?|jsx?|js)$/, "");
|
|
98
|
+
for (const n of S) {
|
|
99
|
+
const r = t + n;
|
|
100
|
+
if (y.existsSync(r)) return r;
|
|
101
|
+
}
|
|
102
|
+
const c = [t];
|
|
103
|
+
for (const n of c)
|
|
104
|
+
if (y.existsSync(n) && y.statSync(n).isDirectory())
|
|
105
|
+
for (const r of S) {
|
|
106
|
+
const d = E.join(n, "index" + r);
|
|
107
|
+
if (y.existsSync(d)) return d;
|
|
108
|
+
}
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
function N(i, e) {
|
|
114
|
+
const s = E.relative(e, i);
|
|
115
|
+
return s.startsWith("..") ? null : s.replace(/\.(tsx?|jsx?|js)$/, "");
|
|
116
|
+
}
|
|
117
|
+
function B(i, e) {
|
|
118
|
+
const s = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Set();
|
|
119
|
+
function u(t) {
|
|
120
|
+
if (o.has(t)) return;
|
|
121
|
+
o.add(t);
|
|
122
|
+
const c = N(t, e);
|
|
123
|
+
if (!c) return;
|
|
124
|
+
let n;
|
|
125
|
+
try {
|
|
126
|
+
n = y.readFileSync(t, "utf-8");
|
|
127
|
+
} catch {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const r = [], d = T(n, {
|
|
131
|
+
sourceType: "module",
|
|
132
|
+
plugins: ["typescript", "jsx"]
|
|
133
|
+
});
|
|
134
|
+
g(d, {
|
|
135
|
+
ImportDeclaration(x) {
|
|
136
|
+
const m = x.node.source.value;
|
|
137
|
+
if (m.startsWith(".")) {
|
|
138
|
+
const f = F(
|
|
139
|
+
t,
|
|
140
|
+
m
|
|
141
|
+
);
|
|
142
|
+
if (f) {
|
|
143
|
+
const v = N(
|
|
144
|
+
f,
|
|
145
|
+
e
|
|
146
|
+
);
|
|
147
|
+
v && (r.push(v), u(f));
|
|
148
|
+
}
|
|
149
|
+
} else
|
|
150
|
+
r.push(m);
|
|
151
|
+
}
|
|
152
|
+
}), s.set(c, { file: t, imports: r });
|
|
153
|
+
}
|
|
154
|
+
return u(i), { modules: s };
|
|
155
|
+
}
|
|
156
|
+
function q(i) {
|
|
157
|
+
const e = E.join(i, "routes.tsx");
|
|
158
|
+
let s;
|
|
159
|
+
try {
|
|
160
|
+
s = y.readFileSync(e, "utf-8");
|
|
161
|
+
} catch {
|
|
162
|
+
return { routes: [], modules: {} };
|
|
163
|
+
}
|
|
164
|
+
const o = D(s), { modules: u } = B(
|
|
165
|
+
e,
|
|
166
|
+
i
|
|
167
|
+
), t = {}, c = /* @__PURE__ */ new Map();
|
|
168
|
+
for (const [n, r] of u) {
|
|
169
|
+
let d = "unknown";
|
|
170
|
+
const x = (h) => {
|
|
171
|
+
for (const p of h) {
|
|
172
|
+
if (p.moduleId === n)
|
|
173
|
+
return p.isRoot ? "root" : p.children.length > 0 ? "layout" : "page";
|
|
174
|
+
const l = x(p.children);
|
|
175
|
+
if (l) return l;
|
|
176
|
+
}
|
|
177
|
+
return null;
|
|
178
|
+
}, m = x(o);
|
|
179
|
+
m && (d = m);
|
|
180
|
+
const f = r.file, v = A(f);
|
|
181
|
+
for (const h of r.imports) {
|
|
182
|
+
c.has(h) || c.set(h, []);
|
|
183
|
+
const p = c.get(h);
|
|
184
|
+
p.includes(n) || p.push(n);
|
|
185
|
+
}
|
|
186
|
+
t[n] = {
|
|
187
|
+
file: E.relative(process.cwd(), f),
|
|
188
|
+
kind: d,
|
|
189
|
+
exports: v,
|
|
190
|
+
imports: r.imports,
|
|
191
|
+
importedBy: []
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
for (const [n, r] of Object.entries(t))
|
|
195
|
+
r.importedBy = c.get(n) ?? [];
|
|
196
|
+
return { routes: o, modules: t };
|
|
197
|
+
}
|
|
198
|
+
export {
|
|
199
|
+
q as buildGraph,
|
|
200
|
+
D as buildRouteTree,
|
|
201
|
+
A as detectExports
|
|
202
|
+
};
|
package/dist/init.js
CHANGED
|
@@ -7,6 +7,15 @@ function m() {
|
|
|
7
7
|
return JSON.parse(t.readFileSync(e, "utf-8")).version;
|
|
8
8
|
}
|
|
9
9
|
const u = {
|
|
10
|
+
".gitignore": `# Dependencies
|
|
11
|
+
node_modules/
|
|
12
|
+
|
|
13
|
+
# Build output
|
|
14
|
+
dist/
|
|
15
|
+
|
|
16
|
+
# Project graph
|
|
17
|
+
.velojs/
|
|
18
|
+
`,
|
|
10
19
|
"package.json": `{
|
|
11
20
|
"name": "my-velojs-app",
|
|
12
21
|
"version": "0.1.0",
|
|
@@ -139,22 +148,22 @@ a:hover {
|
|
|
139
148
|
`
|
|
140
149
|
};
|
|
141
150
|
async function x(o) {
|
|
142
|
-
const e = o ? s.resolve(process.cwd(), o) : process.cwd(),
|
|
151
|
+
const e = o ? s.resolve(process.cwd(), o) : process.cwd(), n = s.basename(e);
|
|
143
152
|
t.existsSync(e) ? t.readdirSync(e).filter(
|
|
144
|
-
(
|
|
153
|
+
(r) => !r.startsWith(".") && r !== "node_modules"
|
|
145
154
|
).length > 0 && (console.error(
|
|
146
|
-
`Error: Directory "${
|
|
155
|
+
`Error: Directory "${n}" is not empty. Use an empty directory.`
|
|
147
156
|
), process.exit(1)) : t.mkdirSync(e, { recursive: !0 });
|
|
148
|
-
for (const [a,
|
|
157
|
+
for (const [a, r] of Object.entries(u)) {
|
|
149
158
|
const p = s.join(e, a), l = s.dirname(p);
|
|
150
159
|
t.existsSync(l) || t.mkdirSync(l, { recursive: !0 });
|
|
151
|
-
const c = a === "package.json" ?
|
|
160
|
+
const c = a === "package.json" ? r.replace("my-velojs-app", n) : r;
|
|
152
161
|
t.writeFileSync(p, c);
|
|
153
162
|
}
|
|
154
163
|
console.log(`
|
|
155
|
-
Project created in ${o ?
|
|
164
|
+
Project created in ${o ? n : "current directory"}!
|
|
156
165
|
`), console.log(`Next steps:
|
|
157
|
-
`), o && console.log(` cd ${
|
|
166
|
+
`), o && console.log(` cd ${n}`), console.log(" npm install"), console.log(` npx velojs dev
|
|
158
167
|
`);
|
|
159
168
|
}
|
|
160
169
|
export {
|