@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/README.md +19 -9
- package/agent/AGENTS.md +143 -0
- package/agent/skills/velojs-actions/SKILL.md +192 -0
- package/agent/skills/velojs-components/SKILL.md +99 -0
- package/agent/skills/velojs-endpoints/SKILL.md +187 -0
- package/agent/skills/velojs-event-streams/SKILL.md +705 -0
- package/agent/skills/velojs-getting-started/SKILL.md +191 -0
- package/agent/skills/velojs-hooks/SKILL.md +103 -0
- package/agent/skills/velojs-link-component/SKILL.md +67 -0
- package/agent/skills/velojs-loaders/SKILL.md +134 -0
- package/agent/skills/velojs-middlewares/SKILL.md +143 -0
- package/agent/skills/velojs-production-deploy/SKILL.md +96 -0
- package/agent/skills/velojs-project-graph/SKILL.md +97 -0
- package/agent/skills/velojs-routes/SKILL.md +209 -0
- package/agent/skills/velojs-scripts-component/SKILL.md +62 -0
- package/agent/skills/velojs-server-api/SKILL.md +155 -0
- package/agent/skills/velojs-sockets/SKILL.md +303 -0
- package/agent/skills/velojs-static-generation/SKILL.md +148 -0
- package/agent/skills/velojs-testing/SKILL.md +472 -0
- package/agent/skills/velojs-type-reference/SKILL.md +142 -0
- package/agent/skills/velojs-vite-plugin/SKILL.md +71 -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 +6 -2
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 {
|