@mauroandre/velojs 0.0.37 → 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/dist/cli.js CHANGED
@@ -1,43 +1,44 @@
1
- import { spawnSync as n } from "node:child_process";
2
- import { resolve as l } from "node:path";
3
- const i = process.argv.slice(2), c = i[0], d = (e, t = []) => {
4
- const s = n(e, t, {
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(s.status ?? 0);
9
- }, p = () => {
10
- d("npx", ["vite", ...i.slice(1)]);
11
- }, u = (e) => {
12
- const t = Date.now().toString(36), s = {
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: t,
15
+ VELO_BUILD_HASH: s,
15
16
  ...e ? { VELO_STATIC: "1" } : {}
16
17
  };
17
18
  console.log("Building client...");
18
- const o = n("npx", ["vite", "build"], {
19
+ const o = a("npx", ["vite", "build"], {
19
20
  stdio: "inherit",
20
21
  cwd: process.cwd(),
21
- env: s
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 r = n("npx", ["vite", "build", "--mode", "server"], {
25
+ const i = a("npx", ["vite", "build", "--mode", "server"], {
25
26
  stdio: "inherit",
26
27
  cwd: process.cwd(),
27
- env: s
28
+ env: t
28
29
  });
29
- r.status !== 0 && (console.error("Server build failed. Aborting."), process.exit(r.status ?? 1)), console.log("Build complete!"), e && v();
30
- }, v = async () => {
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 t = await import(l(process.cwd(), "dist/server.js")), s = t.default, o = t.routes;
33
- (!s || !o) && (console.error("Failed to load app or routes from dist/server.js"), process.exit(1));
34
- const { generateStatic: r } = await import("./static.js");
35
- await r(s, o);
36
- }, m = () => {
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 = l(process.cwd(), "dist/server.js");
39
- d("node", [e]);
40
- }, a = () => {
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(i[1]);
69
+ await e(r[1]);
66
70
  break;
67
71
  }
68
72
  case "dev":
69
- p();
73
+ g();
70
74
  break;
71
75
  case "build": {
72
- const e = i.includes("--static");
73
- u(e);
76
+ const e = r.includes("--static");
77
+ h(e);
74
78
  break;
75
79
  }
76
80
  case "start":
77
- m();
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
- a();
93
+ d();
83
94
  break;
84
95
  default:
85
- c && console.error(`Unknown command: ${c}`), a(), process.exit(1);
96
+ c && console.error(`Unknown command: ${c}`), d(), process.exit(1);
86
97
  }
@@ -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(), r = s.basename(e);
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
- (n) => !n.startsWith(".") && n !== "node_modules"
153
+ (r) => !r.startsWith(".") && r !== "node_modules"
145
154
  ).length > 0 && (console.error(
146
- `Error: Directory "${r}" is not empty. Use an empty 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, n] of Object.entries(u)) {
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" ? n.replace("my-velojs-app", r) : n;
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 ? r : "current directory"}!
164
+ Project created in ${o ? n : "current directory"}!
156
165
  `), console.log(`Next steps:
157
- `), o && console.log(` cd ${r}`), console.log(" npm install"), console.log(` npx velojs dev
166
+ `), o && console.log(` cd ${n}`), console.log(" npm install"), console.log(` npx velojs dev
158
167
  `);
159
168
  }
160
169
  export {