@mauroandre/velojs 0.0.3 → 0.0.5

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>;
@@ -1,10 +1,13 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
-
4
- const PACKAGE_NAME = "@mauroandre/velojs";
5
-
6
- const templates: Record<string, string> = {
7
- "package.json": `{
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": `{
8
11
  "name": "my-velojs-app",
9
12
  "version": "0.1.0",
10
13
  "type": "module",
@@ -14,7 +17,7 @@ const templates: Record<string, string> = {
14
17
  "start": "velojs start"
15
18
  },
16
19
  "dependencies": {
17
- "${PACKAGE_NAME}": "latest"
20
+ "${i}": "^${m()}"
18
21
  },
19
22
  "devDependencies": {
20
23
  "@types/node": "latest",
@@ -22,13 +25,11 @@ const templates: Record<string, string> = {
22
25
  }
23
26
  }
24
27
  `,
25
-
26
- "vite.config.ts": `import { veloPlugin } from "${PACKAGE_NAME}/vite";
28
+ "vite.config.ts": `import { veloPlugin } from "${i}/vite";
27
29
 
28
30
  export default { plugins: [veloPlugin()] };
29
31
  `,
30
-
31
- "tsconfig.json": `{
32
+ "tsconfig.json": `{
32
33
  "compilerOptions": {
33
34
  "module": "esnext",
34
35
  "moduleResolution": "bundler",
@@ -49,8 +50,7 @@ export default { plugins: [veloPlugin()] };
49
50
  "exclude": ["node_modules", "dist"]
50
51
  }
51
52
  `,
52
-
53
- "app/routes.tsx": `import type { AppRoutes } from "${PACKAGE_NAME}";
53
+ "app/routes.tsx": `import type { AppRoutes } from "${i}";
54
54
 
55
55
  import * as Root from "./client-root.js";
56
56
  import * as Home from "./pages/Home.js";
@@ -65,16 +65,13 @@ export default [
65
65
  },
66
66
  ] satisfies AppRoutes;
67
67
  `,
68
-
69
- "app/server.tsx": `// Server initialization
68
+ "app/server.tsx": `// Server initialization
70
69
  // Use this file to set up server-side logic:
71
- // import { addRoutes, onServer } from "${PACKAGE_NAME}/server";
70
+ // import { addRoutes, onServer } from "${i}/server";
72
71
  `,
73
-
74
- "app/client.tsx": `import "./styles/global.css";
72
+ "app/client.tsx": `import "./styles/global.css";
75
73
  `,
76
-
77
- "app/client-root.tsx": `import { Scripts } from "${PACKAGE_NAME}";
74
+ "app/client-root.tsx": `import { Scripts } from "${i}";
78
75
 
79
76
  interface RootProps {
80
77
  children: preact.ComponentChildren;
@@ -94,8 +91,7 @@ export const Component = ({ children }: RootProps) => {
94
91
  );
95
92
  };
96
93
  `,
97
-
98
- "app/styles/global.css": `*,
94
+ "app/styles/global.css": `*,
99
95
  *::before,
100
96
  *::after {
101
97
  box-sizing: border-box;
@@ -119,8 +115,7 @@ a:hover {
119
115
  text-decoration: underline;
120
116
  }
121
117
  `,
122
-
123
- "app/pages/Home.tsx": `export const Component = () => {
118
+ "app/pages/Home.tsx": `export const Component = () => {
124
119
  return (
125
120
  <main style={{ maxWidth: 640, margin: "80px auto", padding: "0 20px" }}>
126
121
  <h1>Welcome to VeloJS</h1>
@@ -128,53 +123,27 @@ a:hover {
128
123
  </main>
129
124
  );
130
125
  };
131
- `,
126
+ `
132
127
  };
133
-
134
- export async function runInit(dirName?: string): Promise<void> {
135
- const targetDir = dirName
136
- ? path.resolve(process.cwd(), dirName)
137
- : process.cwd();
138
-
139
- const dirBaseName = path.basename(targetDir);
140
-
141
- // Check if directory exists and is non-empty
142
- if (fs.existsSync(targetDir)) {
143
- const entries = fs.readdirSync(targetDir).filter(
144
- (e) => !e.startsWith(".") && e !== "node_modules"
145
- );
146
- if (entries.length > 0) {
147
- console.error(
148
- `Error: Directory "${dirBaseName}" is not empty. Use an empty directory.`
149
- );
150
- process.exit(1);
151
- }
152
- } else {
153
- fs.mkdirSync(targetDir, { recursive: true });
154
- }
155
-
156
- // Write all template files
157
- for (const [filePath, content] of Object.entries(templates)) {
158
- const fullPath = path.join(targetDir, filePath);
159
- const dir = path.dirname(fullPath);
160
-
161
- if (!fs.existsSync(dir)) {
162
- fs.mkdirSync(dir, { recursive: true });
163
- }
164
-
165
- // Replace app name in package.json
166
- const finalContent = filePath === "package.json"
167
- ? content.replace("my-velojs-app", dirBaseName)
168
- : content;
169
-
170
- fs.writeFileSync(fullPath, finalContent);
171
- }
172
-
173
- console.log(`\nProject created in ${dirName ? dirBaseName : "current directory"}!\n`);
174
- console.log("Next steps:\n");
175
- if (dirName) {
176
- console.log(` cd ${dirBaseName}`);
177
- }
178
- console.log(" npm install");
179
- console.log(" npx velojs dev\n");
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
+ `);
180
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[];