@mauroandre/velojs 0.0.4 → 0.0.6

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/hooks.js ADDED
@@ -0,0 +1,72 @@
1
+ import { signal as f, useSignal as _ } from "@preact/signals";
2
+ import { useEffect as v } from "preact/hooks";
3
+ import { useLocation as d, useParams as w } from "wouter-preact";
4
+ function p(e) {
5
+ e.value !== null && typeof e.value == "object" && (e.value = { ...e.value });
6
+ }
7
+ function y(e) {
8
+ const t = f(!1);
9
+ if (typeof window > "u")
10
+ return { data: {
11
+ get value() {
12
+ return e ? globalThis.__veloServerData?.getStore?.()?.[e] ?? null : null;
13
+ }
14
+ }, loading: t };
15
+ const a = window.__PAGE_DATA__, r = e && a?.[e] ? a[e] : null;
16
+ return { data: f(r), loading: t };
17
+ }
18
+ function S(e, t) {
19
+ let a, r;
20
+ Array.isArray(e) ? r = e : (a = e, r = t);
21
+ let n = null;
22
+ if (typeof window > "u" && a) {
23
+ const i = globalThis.__veloServerData?.getStore?.();
24
+ i?.[a] && (n = i[a]);
25
+ }
26
+ if (typeof window < "u" && a) {
27
+ const o = window.__PAGE_DATA__;
28
+ o?.[a] && (n = o[a], delete o[a]);
29
+ }
30
+ const c = _(n), s = _(!1), l = () => {
31
+ if (typeof window > "u" || !a) return;
32
+ const o = window.location.pathname, i = new URLSearchParams(window.location.search);
33
+ i.set("_data", "1"), s.value = !0, fetch(`${o}?${i.toString()}`).then((u) => u.json()).then((u) => {
34
+ c.value = u[a], s.value = !1;
35
+ }).catch((u) => {
36
+ console.error("Erro ao carregar dados:", u), s.value = !1;
37
+ });
38
+ };
39
+ return v(() => {
40
+ n === null && l();
41
+ }, r ?? []), { data: c, loading: s, refetch: l };
42
+ }
43
+ function m() {
44
+ const [, e] = d();
45
+ return e;
46
+ }
47
+ function P() {
48
+ return typeof window > "u" ? globalThis.__veloServerData?.getStore?.()?.__params ?? {} : w();
49
+ }
50
+ function A() {
51
+ if (typeof window > "u")
52
+ return globalThis.__veloServerData?.getStore?.()?.__query ?? {};
53
+ const e = window.__PAGE_DATA__;
54
+ if (e?.__query)
55
+ return e.__query;
56
+ const t = new URLSearchParams(window.location.search), a = {};
57
+ return t.forEach((r, n) => {
58
+ a[n] = r;
59
+ }), a;
60
+ }
61
+ function T() {
62
+ return typeof window > "u" ? globalThis.__veloServerData?.getStore?.()?.__pathname ?? "/" : (d(), window.location.pathname);
63
+ }
64
+ export {
65
+ y as Loader,
66
+ p as touch,
67
+ S as useLoader,
68
+ m as useNavigate,
69
+ P as useParams,
70
+ T as usePathname,
71
+ A as useQuery
72
+ };
@@ -1,19 +1,5 @@
1
- // Types
2
- export type {
3
- AppRoutes,
4
- RouteNode,
5
- RouteModule,
6
- LoaderArgs,
7
- ActionArgs,
8
- Metadata,
9
- } from "./types.js";
10
-
11
- // Config
1
+ export type { AppRoutes, RouteNode, RouteModule, LoaderArgs, ActionArgs, Metadata, } from "./types.js";
12
2
  export type { VeloConfig } from "./config.js";
13
3
  export { defineConfig } from "./config.js";
14
-
15
- // Components
16
4
  export { Scripts, Link } from "./components.js";
17
-
18
- // Re-export Hono types
19
5
  export type { Context, MiddlewareHandler, Next } from "hono";
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ import { defineConfig as e } from "./config.js";
2
+ import { Link as i, Scripts as n } from "./components.js";
3
+ export {
4
+ i as Link,
5
+ n as Scripts,
6
+ e as defineConfig
7
+ };
package/dist/init.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare function runInit(dirName?: string): Promise<void>;
package/dist/init.js ADDED
@@ -0,0 +1,149 @@
1
+ import t from "node:fs";
2
+ import s from "node:path";
3
+ import { fileURLToPath as d } from "node:url";
4
+ const i = "@mauroandre/velojs";
5
+ function m() {
6
+ const o = s.dirname(d(import.meta.url)), e = s.resolve(o, "../package.json");
7
+ return JSON.parse(t.readFileSync(e, "utf-8")).version;
8
+ }
9
+ const u = {
10
+ "package.json": `{
11
+ "name": "my-velojs-app",
12
+ "version": "0.1.0",
13
+ "type": "module",
14
+ "scripts": {
15
+ "dev": "velojs dev",
16
+ "build": "velojs build",
17
+ "start": "velojs start"
18
+ },
19
+ "dependencies": {
20
+ "${i}": "^${m()}"
21
+ },
22
+ "devDependencies": {
23
+ "@types/node": "latest",
24
+ "typescript": "latest"
25
+ }
26
+ }
27
+ `,
28
+ "vite.config.ts": `import { veloPlugin } from "${i}/vite";
29
+
30
+ export default { plugins: [veloPlugin()] };
31
+ `,
32
+ "tsconfig.json": `{
33
+ "compilerOptions": {
34
+ "module": "esnext",
35
+ "moduleResolution": "bundler",
36
+ "target": "esnext",
37
+ "lib": ["esnext", "dom"],
38
+ "types": ["node", "vite/client"],
39
+ "strict": true,
40
+ "noUncheckedIndexedAccess": true,
41
+ "verbatimModuleSyntax": true,
42
+ "isolatedModules": true,
43
+ "skipLibCheck": true,
44
+ "esModuleInterop": true,
45
+ "noEmit": true,
46
+ "jsx": "react-jsx",
47
+ "jsxImportSource": "preact"
48
+ },
49
+ "include": ["app/**/*"],
50
+ "exclude": ["node_modules", "dist"]
51
+ }
52
+ `,
53
+ "app/routes.tsx": `import type { AppRoutes } from "${i}";
54
+
55
+ import * as Root from "./client-root.js";
56
+ import * as Home from "./pages/Home.js";
57
+
58
+ export default [
59
+ {
60
+ module: Root,
61
+ isRoot: true,
62
+ children: [
63
+ { path: "/", module: Home },
64
+ ],
65
+ },
66
+ ] satisfies AppRoutes;
67
+ `,
68
+ "app/server.tsx": `// Server initialization
69
+ // Use this file to set up server-side logic:
70
+ // import { addRoutes, onServer } from "${i}/server";
71
+ `,
72
+ "app/client.tsx": `import "./styles/global.css";
73
+ `,
74
+ "app/client-root.tsx": `import { Scripts } from "${i}";
75
+
76
+ interface RootProps {
77
+ children: preact.ComponentChildren;
78
+ }
79
+
80
+ export const Component = ({ children }: RootProps) => {
81
+ return (
82
+ <html lang="en">
83
+ <head>
84
+ <meta charSet="utf-8" />
85
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
86
+ <title>VeloJS App</title>
87
+ <Scripts />
88
+ </head>
89
+ <body>{children}</body>
90
+ </html>
91
+ );
92
+ };
93
+ `,
94
+ "app/styles/global.css": `*,
95
+ *::before,
96
+ *::after {
97
+ box-sizing: border-box;
98
+ margin: 0;
99
+ padding: 0;
100
+ }
101
+
102
+ body {
103
+ font-family: system-ui, -apple-system, sans-serif;
104
+ line-height: 1.6;
105
+ color: #1a1a1a;
106
+ background: #fafafa;
107
+ }
108
+
109
+ a {
110
+ color: #0066cc;
111
+ text-decoration: none;
112
+ }
113
+
114
+ a:hover {
115
+ text-decoration: underline;
116
+ }
117
+ `,
118
+ "app/pages/Home.tsx": `export const Component = () => {
119
+ return (
120
+ <main style={{ maxWidth: 640, margin: "80px auto", padding: "0 20px" }}>
121
+ <h1>Welcome to VeloJS</h1>
122
+ <p>Edit <code>app/pages/Home.tsx</code> to get started.</p>
123
+ </main>
124
+ );
125
+ };
126
+ `
127
+ };
128
+ async function v(o) {
129
+ const e = o ? s.resolve(process.cwd(), o) : process.cwd(), r = s.basename(e);
130
+ t.existsSync(e) ? t.readdirSync(e).filter(
131
+ (n) => !n.startsWith(".") && n !== "node_modules"
132
+ ).length > 0 && (console.error(
133
+ `Error: Directory "${r}" is not empty. Use an empty directory.`
134
+ ), process.exit(1)) : t.mkdirSync(e, { recursive: !0 });
135
+ for (const [a, n] of Object.entries(u)) {
136
+ const c = s.join(e, a), l = s.dirname(c);
137
+ t.existsSync(l) || t.mkdirSync(l, { recursive: !0 });
138
+ const p = a === "package.json" ? n.replace("my-velojs-app", r) : n;
139
+ t.writeFileSync(c, p);
140
+ }
141
+ console.log(`
142
+ Project created in ${o ? r : "current directory"}!
143
+ `), console.log(`Next steps:
144
+ `), o && console.log(` cd ${r}`), console.log(" npm install"), console.log(` npx velojs dev
145
+ `);
146
+ }
147
+ export {
148
+ v as runInit
149
+ };
@@ -0,0 +1,14 @@
1
+ import { Hono } from "hono";
2
+ import type { AppRoutes } from "./types.js";
3
+ import { AsyncLocalStorage } from "node:async_hooks";
4
+ export declare const serverDataStorage: AsyncLocalStorage<Record<string, unknown>>;
5
+ type ServerCallback = (server: import("http").Server) => void;
6
+ export declare function onServer(fn: ServerCallback): void;
7
+ export interface StartServerOptions {
8
+ routes: AppRoutes;
9
+ port?: number;
10
+ }
11
+ export declare function addRoutes(fn: (app: Hono) => void | Promise<void>): void;
12
+ export declare const createApp: (routes: AppRoutes) => Promise<Hono>;
13
+ export declare const startServer: (options: StartServerOptions) => Promise<Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">>;
14
+ export default createApp;
package/dist/server.js ADDED
@@ -0,0 +1,168 @@
1
+ import { jsx as h } from "preact/jsx-runtime";
2
+ import { Hono as T } from "hono";
3
+ import { logger as A } from "hono/logger";
4
+ import { trimTrailingSlash as R } from "hono/trailing-slash";
5
+ import { render as D } from "preact-render-to-string";
6
+ import { Router as N } from "wouter-preact";
7
+ import { AsyncLocalStorage as O } from "node:async_hooks";
8
+ const v = new O();
9
+ globalThis.__veloServerData = v;
10
+ const g = [];
11
+ let p = null;
12
+ function x(t) {
13
+ if (p) {
14
+ t(p);
15
+ return;
16
+ }
17
+ g.push(t);
18
+ }
19
+ function y(t) {
20
+ p = t;
21
+ for (const e of g) e(t);
22
+ g.length = 0;
23
+ }
24
+ const w = [];
25
+ function B(t) {
26
+ w.push(t);
27
+ }
28
+ const b = (t, e, o) => {
29
+ if (t.req.query("_data") === "1")
30
+ return t.json(o ?? null);
31
+ const s = t.req.path, r = v.run(
32
+ o ?? {},
33
+ () => D(/* @__PURE__ */ h(N, { ssrPath: s, children: e }))
34
+ );
35
+ if (!o)
36
+ return t.html(r);
37
+ const a = `<script>window.__PAGE_DATA__=${JSON.stringify(
38
+ o
39
+ )}<\/script>`;
40
+ return t.html(r.replace("</head>", `${a}</head>`));
41
+ }, j = async (t, e) => {
42
+ const o = e.req.param(), s = e.req.query(), r = { params: o, query: s, c: e }, a = await Promise.all(
43
+ t.map(async (n) => {
44
+ if (!n.loader) return null;
45
+ const u = await n.loader(r), i = n.metadata?.moduleId;
46
+ return i ? { moduleId: i, loaderData: u } : null;
47
+ })
48
+ ), c = {
49
+ __params: o,
50
+ __query: s,
51
+ __pathname: e.req.path
52
+ };
53
+ for (const n of a)
54
+ n && (c[n.moduleId] = n.loaderData);
55
+ return {
56
+ components: t.map((n) => n.Component),
57
+ data: c
58
+ };
59
+ }, I = (t) => {
60
+ if (t.length === 0) return null;
61
+ const e = t.filter(Boolean);
62
+ if (e.length === 0) return null;
63
+ if (e.length === 1) {
64
+ const r = e[0];
65
+ return /* @__PURE__ */ h(r, {});
66
+ }
67
+ const o = e[e.length - 1];
68
+ return e.slice(0, -1).reduceRight((r, a) => /* @__PURE__ */ h(a, { children: r }), /* @__PURE__ */ h(o, {}));
69
+ }, S = (t, e, o = [], s = []) => {
70
+ for (const r of e) {
71
+ const a = [...o, r.module], c = [
72
+ ...s,
73
+ ...r.middlewares || []
74
+ ];
75
+ if (r.children)
76
+ S(
77
+ t,
78
+ r.children,
79
+ a,
80
+ c
81
+ );
82
+ else {
83
+ const n = r.module.metadata?.fullPath;
84
+ if (!n) {
85
+ console.warn(
86
+ `Module ${r.module.metadata?.moduleId} has no fullPath`
87
+ );
88
+ continue;
89
+ }
90
+ const u = async (i) => {
91
+ const { components: d, data: f } = await j(a, i), l = I(d);
92
+ return b(i, l, f);
93
+ };
94
+ c.length > 0 ? t.on(["GET"], [n], ...c, u) : t.on(["GET"], [n], u);
95
+ }
96
+ }
97
+ }, P = (t, e, o = []) => {
98
+ for (const s of e) {
99
+ const r = s.module.metadata?.moduleId, a = [
100
+ ...o,
101
+ ...s.middlewares || []
102
+ ];
103
+ if (r) {
104
+ const c = Object.keys(s.module).filter(
105
+ (n) => n.startsWith("action_")
106
+ );
107
+ for (const n of c) {
108
+ const u = n.replace("action_", ""), i = s.module[n];
109
+ if (typeof i == "function") {
110
+ const d = `/_action/${r}/${u}`, f = async (l) => {
111
+ let _ = {};
112
+ try {
113
+ _ = await l.req.json();
114
+ } catch {
115
+ }
116
+ const q = {
117
+ body: _,
118
+ params: l.req.param(),
119
+ query: l.req.query(),
120
+ c: l
121
+ };
122
+ try {
123
+ const m = await i(q);
124
+ return l.json(m ?? { ok: !0 });
125
+ } catch (m) {
126
+ const E = m instanceof Error ? m.message : "Action failed";
127
+ return l.json({ error: E }, 500);
128
+ }
129
+ };
130
+ a.length > 0 ? t.on(
131
+ ["POST"],
132
+ [d],
133
+ ...a,
134
+ f
135
+ ) : t.on(["POST"], [d], f);
136
+ }
137
+ }
138
+ }
139
+ s.children && P(t, s.children, a);
140
+ }
141
+ }, C = async (t) => {
142
+ const e = new T();
143
+ e.use(R()), process.env.NODE_ENV !== "production" && e.use("*", A());
144
+ for (const o of w)
145
+ await o(e);
146
+ if (S(e, t), P(e, t), process.env.NODE_ENV !== "production" && !p) {
147
+ const o = globalThis.__veloDevServer;
148
+ o && y(o);
149
+ }
150
+ return e;
151
+ }, K = async (t) => {
152
+ const { routes: e, port: o = Number(process.env.SERVER_PORT) || 3e3 } = t, s = await C(e);
153
+ if (process.env.NODE_ENV === "production") {
154
+ const { serve: r } = await import("@hono/node-server"), { serveStatic: a } = await import("@hono/node-server/serve-static"), { dirname: c, join: n } = await import("node:path"), { fileURLToPath: u } = await import("node:url"), i = c(u(import.meta.url)), d = n(i, "client");
155
+ (process.env.STATIC_BASE_URL || "").startsWith("http") || s.use("/*", a({ root: d })), console.log(`Server running on http://localhost:${o}`);
156
+ const l = r({ fetch: s.fetch, port: o });
157
+ y(l);
158
+ }
159
+ return s;
160
+ };
161
+ export {
162
+ B as addRoutes,
163
+ C as createApp,
164
+ C as default,
165
+ x as onServer,
166
+ v as serverDataStorage,
167
+ K as startServer
168
+ };
@@ -1,33 +1,28 @@
1
1
  import type { ComponentType } from "preact";
2
2
  import type { Context, MiddlewareHandler } from "hono";
3
-
4
3
  export interface LoaderArgs {
5
4
  params: Record<string, string>;
6
5
  query: Record<string, string>;
7
6
  c: Context;
8
7
  }
9
-
10
8
  export interface ActionArgs<TBody = unknown> {
11
9
  body: TBody;
12
10
  params?: Record<string, string>;
13
11
  query?: Record<string, string>;
14
12
  c?: Context;
15
13
  }
16
-
17
14
  export interface Metadata {
18
15
  moduleId: string;
19
16
  fullPath?: string;
20
17
  path?: string;
21
18
  [key: string]: unknown;
22
19
  }
23
-
24
20
  export interface RouteModule {
25
21
  Component: ComponentType<any>;
26
22
  loader?: (args: LoaderArgs) => Promise<any>;
27
23
  metadata?: Metadata;
28
24
  [key: `action_${string}`]: (args: ActionArgs<any>) => Promise<any>;
29
25
  }
30
-
31
26
  export interface RouteNode {
32
27
  path?: string;
33
28
  module: RouteModule;
@@ -35,5 +30,4 @@ export interface RouteNode {
35
30
  middlewares?: MiddlewareHandler[];
36
31
  isRoot?: boolean;
37
32
  }
38
-
39
33
  export type AppRoutes = RouteNode[];
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+
package/dist/vite.d.ts ADDED
@@ -0,0 +1,22 @@
1
+ import type { PluginOption } from "vite";
2
+ import type { VeloConfig } from "./config.js";
3
+ import * as t from "@babel/types";
4
+ export declare function injectMetadata(code: string, moduleId: string, fullPath?: string, path?: string): string;
5
+ export declare function transformLoaderFunctions(code: string, moduleId: string): string;
6
+ export declare function transformActionsForClient(code: string, moduleId: string): string;
7
+ export declare function removeLoaders(code: string): string;
8
+ export declare function removeMiddlewares(code: string): string;
9
+ export interface PathInfo {
10
+ fullPath: string;
11
+ path: string;
12
+ }
13
+ /**
14
+ * Parseia routes.tsx e retorna Map de moduleId → { fullPath, path }
15
+ * moduleId aqui é derivado do import source (ex: "./auth/Login.js" → "auth/Login")
16
+ */
17
+ export declare function buildFullPathMap(code: string): Map<string, PathInfo>;
18
+ /**
19
+ * Percorre recursivamente a árvore de rotas e coleta moduleName → { fullPath, path }
20
+ */
21
+ export declare function collectFullPaths(elements: (t.Expression | t.SpreadElement | null)[], parentPath: string, result: Map<string, PathInfo>): void;
22
+ export declare function veloPlugin(config?: VeloConfig): PluginOption[];