@evjs/cli 0.0.1-rc.17 → 0.0.1-rc.18
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 +2 -1
- package/dist/create-webpack-config.js +14 -0
- package/dist/index.js +8 -1
- package/package.json +1 -1
- package/templates/basic-csr/README.md +23 -0
- package/templates/basic-csr/package.json +1 -1
- package/templates/basic-server-fns/README.md +24 -0
- package/templates/basic-server-fns/package.json +1 -1
- package/templates/complex-routing/README.md +27 -0
- package/templates/complex-routing/package.json +1 -1
- package/templates/configured-server-fns/README.md +24 -0
- package/templates/configured-server-fns/ev.config.ts +3 -3
- package/templates/configured-server-fns/package.json +1 -1
- package/templates/configured-server-fns/src/routes.tsx +1 -1
- package/templates/with-tailwind/ev.config.ts +20 -0
- package/templates/with-tailwind/index.html +11 -0
- package/templates/with-tailwind/package.json +28 -0
- package/templates/with-tailwind/postcss.config.mjs +5 -0
- package/templates/with-tailwind/src/main.tsx +15 -0
- package/templates/with-tailwind/src/pages/__root.tsx +30 -0
- package/templates/with-tailwind/src/pages/home.tsx +85 -0
- package/templates/with-tailwind/src/styles.css +2 -0
- package/templates/with-tailwind/tsconfig.json +17 -0
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ No configuration file is needed. `ev dev` and `ev build` work out of the box wit
|
|
|
28
28
|
|
|
29
29
|
### `ev init [name]`
|
|
30
30
|
|
|
31
|
-
Templates: `basic-csr`, `basic-server-fns`, `
|
|
31
|
+
Templates: `basic-csr`, `basic-server-fns`, `configured-server-fns`, `complex-routing`, `with-tailwind`.
|
|
32
32
|
Option: `-t, --template <template>` to skip interactive selection.
|
|
33
33
|
|
|
34
34
|
### `ev dev`
|
|
@@ -54,6 +54,7 @@ export default defineConfig({
|
|
|
54
54
|
client: {
|
|
55
55
|
entry: "./src/main.tsx",
|
|
56
56
|
html: "./index.html",
|
|
57
|
+
plugins: [{ name: "tailwind", loaders: [{ test: /\.css$/, use: ["style-loader", "css-loader", "postcss-loader"] }] }],
|
|
57
58
|
dev: { port: 3000 },
|
|
58
59
|
},
|
|
59
60
|
server: {
|
|
@@ -74,6 +74,20 @@ export function createWebpackConfig(config, cwd) {
|
|
|
74
74
|
},
|
|
75
75
|
],
|
|
76
76
|
},
|
|
77
|
+
// Plugin-declared loaders
|
|
78
|
+
...(client?.plugins ?? []).flatMap((plugin) => (plugin.loaders ?? []).map((rule) => {
|
|
79
|
+
const entries = Array.isArray(rule.use) ? rule.use : [rule.use];
|
|
80
|
+
return {
|
|
81
|
+
test: rule.test,
|
|
82
|
+
...(rule.exclude ? { exclude: rule.exclude } : {}),
|
|
83
|
+
use: entries.map((entry) => typeof entry === "string"
|
|
84
|
+
? { loader: resolveLoader(entry) }
|
|
85
|
+
: {
|
|
86
|
+
loader: resolveLoader(entry.loader),
|
|
87
|
+
...(entry.options ? { options: entry.options } : {}),
|
|
88
|
+
}),
|
|
89
|
+
};
|
|
90
|
+
})),
|
|
77
91
|
],
|
|
78
92
|
},
|
|
79
93
|
plugins: [
|
package/dist/index.js
CHANGED
|
@@ -52,6 +52,10 @@ program
|
|
|
52
52
|
title: "Complex Routing (params, search, layouts, loaders)",
|
|
53
53
|
value: "complex-routing",
|
|
54
54
|
},
|
|
55
|
+
{
|
|
56
|
+
title: "With Tailwind CSS (plugin loaders example)",
|
|
57
|
+
value: "with-tailwind",
|
|
58
|
+
},
|
|
55
59
|
],
|
|
56
60
|
},
|
|
57
61
|
], {
|
|
@@ -144,12 +148,15 @@ program
|
|
|
144
148
|
const manifestPath = path.resolve(cwd, "dist/manifest.json");
|
|
145
149
|
const bootstrapPath = path.resolve(cwd, "dist/server/_dev_start.cjs");
|
|
146
150
|
if (fs.existsSync(manifestPath)) {
|
|
151
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
|
|
152
|
+
// Only start API server if there are actual server functions
|
|
153
|
+
if (Object.keys(manifest.server?.fns ?? {}).length === 0)
|
|
154
|
+
return;
|
|
147
155
|
apiStarted = true;
|
|
148
156
|
const backendConfig = evjsConfig?.server?.backend ?? "node";
|
|
149
157
|
const [backend, ...backendExtraArgs] = backendConfig.split(/\s+/);
|
|
150
158
|
logger.info `Server bundle detected, starting ${backend} API...`;
|
|
151
159
|
try {
|
|
152
|
-
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
|
|
153
160
|
const serverBundlePath = path.resolve(cwd, "dist/server", manifest.server.entry);
|
|
154
161
|
fs.writeFileSync(bootstrapPath, [
|
|
155
162
|
`const bundle = require(${JSON.stringify(serverBundlePath)});`,
|
package/package.json
CHANGED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# basic-csr
|
|
2
|
+
|
|
3
|
+
Minimal client-side rendering example — no server functions, just routing.
|
|
4
|
+
|
|
5
|
+
## Run
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm run dev -w example-basic-csr
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Key Files
|
|
12
|
+
|
|
13
|
+
| File | Purpose |
|
|
14
|
+
|------|---------|
|
|
15
|
+
| `src/main.tsx` | App bootstrap with `createApp` |
|
|
16
|
+
| `src/pages/` | Route components (Home, Posts) |
|
|
17
|
+
|
|
18
|
+
## What It Demonstrates
|
|
19
|
+
|
|
20
|
+
- `createApp` + `createRoute` from `@evjs/runtime`
|
|
21
|
+
- Client-side routing with TanStack Router
|
|
22
|
+
- Dynamic route params (`$postId`)
|
|
23
|
+
- No server functions — pure CSR
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# basic-server-fns
|
|
2
|
+
|
|
3
|
+
Basic server functions with `query()` / `mutation()` wrappers.
|
|
4
|
+
|
|
5
|
+
## Run
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm run dev -w example-basic-server-fns
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Key Files
|
|
12
|
+
|
|
13
|
+
| File | Purpose |
|
|
14
|
+
|------|---------|
|
|
15
|
+
| `src/main.tsx` | App bootstrap |
|
|
16
|
+
| `src/routes.tsx` | Routes + components |
|
|
17
|
+
| `src/api/users.server.ts` | `"use server"` CRUD functions |
|
|
18
|
+
|
|
19
|
+
## What It Demonstrates
|
|
20
|
+
|
|
21
|
+
- `"use server"` directive for auto-discovered server functions
|
|
22
|
+
- `query(fn).useQuery()` for data fetching
|
|
23
|
+
- `mutation(fn).useMutation()` for mutations
|
|
24
|
+
- `invalidates` for auto cache invalidation on mutation success
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# complex-routing
|
|
2
|
+
|
|
3
|
+
Advanced routing patterns with TanStack Router.
|
|
4
|
+
|
|
5
|
+
## Run
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm run dev -w example-complex-routing
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Key Files
|
|
12
|
+
|
|
13
|
+
| File | Purpose |
|
|
14
|
+
|------|---------|
|
|
15
|
+
| `src/main.tsx` | Route tree assembly |
|
|
16
|
+
| `src/pages/__root.tsx` | Root layout with navigation |
|
|
17
|
+
| `src/pages/home.tsx` | Index route |
|
|
18
|
+
| `src/pages/posts/` | Nested routes with loader |
|
|
19
|
+
|
|
20
|
+
## What It Demonstrates
|
|
21
|
+
|
|
22
|
+
- Dynamic route params (`$postId`)
|
|
23
|
+
- Pathless layout routes
|
|
24
|
+
- Route loaders with `queryClient.ensureQueryData`
|
|
25
|
+
- Search params with `validateSearch`
|
|
26
|
+
- Catch-all 404 route
|
|
27
|
+
- Type-safe `route.useParams()`
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# configured-server-fns
|
|
2
|
+
|
|
3
|
+
Server functions with `ev.config.ts` and module-level query/mutation proxies.
|
|
4
|
+
|
|
5
|
+
## Run
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm run dev -w example-configured-server-fns
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Key Files
|
|
12
|
+
|
|
13
|
+
| File | Purpose |
|
|
14
|
+
|------|---------|
|
|
15
|
+
| `ev.config.ts` | Custom ports and settings |
|
|
16
|
+
| `src/routes.tsx` | Routes with `createQueryProxy` / `createMutationProxy` |
|
|
17
|
+
| `src/api/users.server.ts` | User CRUD functions |
|
|
18
|
+
|
|
19
|
+
## What It Demonstrates
|
|
20
|
+
|
|
21
|
+
- `ev.config.ts` with `defineConfig` for custom ports
|
|
22
|
+
- `createQueryProxy(module)` for grouped queries
|
|
23
|
+
- `createMutationProxy(module)` for grouped mutations
|
|
24
|
+
- Direct mutation args: `mutate({ name, email })` (not array-wrapped)
|
|
@@ -39,9 +39,9 @@ export default defineConfig({
|
|
|
39
39
|
// Server function endpoint path (default: "/api/fn")
|
|
40
40
|
endpoint: "/api/fn",
|
|
41
41
|
|
|
42
|
-
// Server backend
|
|
43
|
-
//
|
|
44
|
-
backend: "
|
|
42
|
+
// Server backend command (default: "node")
|
|
43
|
+
// Supports: "node", "bun", "deno run --allow-net", etc.
|
|
44
|
+
backend: "node",
|
|
45
45
|
|
|
46
46
|
// Middleware module paths to auto-register in server entry
|
|
47
47
|
// These are imported and applied in order
|
|
@@ -60,7 +60,7 @@ function UsersPage() {
|
|
|
60
60
|
async function handleCreate(e: { preventDefault: () => void }) {
|
|
61
61
|
e.preventDefault();
|
|
62
62
|
if (!name || !email) return;
|
|
63
|
-
await doCreateUser(
|
|
63
|
+
await doCreateUser({ name, email });
|
|
64
64
|
setName("");
|
|
65
65
|
setEmail("");
|
|
66
66
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { defineConfig } from "@evjs/cli";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Example: Using client plugins to add Tailwind CSS support.
|
|
5
|
+
*/
|
|
6
|
+
export default defineConfig({
|
|
7
|
+
client: {
|
|
8
|
+
plugins: [
|
|
9
|
+
{
|
|
10
|
+
name: "tailwind",
|
|
11
|
+
loaders: [
|
|
12
|
+
{
|
|
13
|
+
test: /\.css$/,
|
|
14
|
+
use: ["style-loader", "css-loader", "postcss-loader"],
|
|
15
|
+
},
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
],
|
|
19
|
+
},
|
|
20
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "example-with-tailwind",
|
|
3
|
+
"version": "0.0.1-rc.18",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "ev dev",
|
|
7
|
+
"build": "ev build",
|
|
8
|
+
"check-types": "tsc --noEmit"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@evjs/runtime": "*",
|
|
12
|
+
"@tailwindcss/typography": "^0.5.19",
|
|
13
|
+
"react": "^19.2.4",
|
|
14
|
+
"react-dom": "^19.2.4"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@evjs/cli": "*",
|
|
18
|
+
"@tailwindcss/postcss": "^4.1.10",
|
|
19
|
+
"@types/react": "^19.0.8",
|
|
20
|
+
"@types/react-dom": "^19.0.3",
|
|
21
|
+
"css-loader": "^7.1.2",
|
|
22
|
+
"postcss": "^8.5.6",
|
|
23
|
+
"postcss-loader": "^8.1.1",
|
|
24
|
+
"style-loader": "^4.0.0",
|
|
25
|
+
"tailwindcss": "^4.1.10",
|
|
26
|
+
"typescript": "^5.7.3"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createApp } from "@evjs/runtime/client";
|
|
2
|
+
import { rootRoute } from "./pages/__root";
|
|
3
|
+
import { homeRoute } from "./pages/home";
|
|
4
|
+
|
|
5
|
+
const routeTree = rootRoute.addChildren([homeRoute]);
|
|
6
|
+
|
|
7
|
+
const app = createApp({ routeTree });
|
|
8
|
+
|
|
9
|
+
declare module "@tanstack/react-router" {
|
|
10
|
+
interface Register {
|
|
11
|
+
router: typeof app.router;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
app.render("#app");
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createRootRoute, Link, Outlet } from "@evjs/runtime/client";
|
|
2
|
+
import "../styles.css";
|
|
3
|
+
|
|
4
|
+
function Root() {
|
|
5
|
+
return (
|
|
6
|
+
<div className="min-h-screen bg-gradient-to-br from-slate-900 via-slate-800 to-slate-900 text-white">
|
|
7
|
+
<nav className="border-b border-white/10 backdrop-blur-sm bg-white/5">
|
|
8
|
+
<div className="max-w-4xl mx-auto px-6 py-4 flex items-center gap-6">
|
|
9
|
+
<Link
|
|
10
|
+
to="/"
|
|
11
|
+
className="text-lg font-bold bg-gradient-to-r from-blue-400 to-violet-400 bg-clip-text text-transparent"
|
|
12
|
+
>
|
|
13
|
+
evjs
|
|
14
|
+
</Link>
|
|
15
|
+
<Link
|
|
16
|
+
to="/"
|
|
17
|
+
className="text-sm text-slate-300 hover:text-white transition-colors"
|
|
18
|
+
>
|
|
19
|
+
Home
|
|
20
|
+
</Link>
|
|
21
|
+
</div>
|
|
22
|
+
</nav>
|
|
23
|
+
<Outlet />
|
|
24
|
+
</div>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const rootRoute = createRootRoute({
|
|
29
|
+
component: Root,
|
|
30
|
+
});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { createRoute } from "@evjs/runtime/client";
|
|
2
|
+
import { rootRoute } from "./__root";
|
|
3
|
+
|
|
4
|
+
export const homeRoute = createRoute({
|
|
5
|
+
getParentRoute: () => rootRoute,
|
|
6
|
+
path: "/",
|
|
7
|
+
component: () => (
|
|
8
|
+
<main className="max-w-4xl mx-auto px-6 py-16">
|
|
9
|
+
{/* Hero */}
|
|
10
|
+
<div className="text-center mb-16">
|
|
11
|
+
<h1
|
|
12
|
+
className="text-5xl font-extrabold tracking-tight bg-gradient-to-r from-blue-400 via-violet-400 to-fuchsia-400 bg-clip-text text-transparent"
|
|
13
|
+
data-testid="title"
|
|
14
|
+
>
|
|
15
|
+
Tailwind Plugin Example
|
|
16
|
+
</h1>
|
|
17
|
+
<p
|
|
18
|
+
className="mt-4 text-lg text-slate-400 max-w-xl mx-auto"
|
|
19
|
+
data-testid="subtitle"
|
|
20
|
+
>
|
|
21
|
+
Styled with Tailwind CSS v4 via the evjs plugin system — no webpack
|
|
22
|
+
config needed.
|
|
23
|
+
</p>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
{/* Feature cards */}
|
|
27
|
+
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-16">
|
|
28
|
+
<div className="rounded-xl border border-white/10 bg-white/5 backdrop-blur-sm p-6 hover:bg-white/10 transition-colors">
|
|
29
|
+
<div className="text-3xl mb-3">🔌</div>
|
|
30
|
+
<h3 className="font-semibold text-white mb-1">Plugin Loaders</h3>
|
|
31
|
+
<p className="text-sm text-slate-400">
|
|
32
|
+
Declare loaders in ev.config.ts. The framework handles the rest.
|
|
33
|
+
</p>
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
<div className="rounded-xl border border-white/10 bg-white/5 backdrop-blur-sm p-6 hover:bg-white/10 transition-colors">
|
|
37
|
+
<div className="text-3xl mb-3">🎨</div>
|
|
38
|
+
<h3 className="font-semibold text-white mb-1">Tailwind CSS v4</h3>
|
|
39
|
+
<p className="text-sm text-slate-400">
|
|
40
|
+
Full utility-first styling with zero configuration overhead.
|
|
41
|
+
</p>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<div className="rounded-xl border border-white/10 bg-white/5 backdrop-blur-sm p-6 hover:bg-white/10 transition-colors">
|
|
45
|
+
<div className="text-3xl mb-3">⚡</div>
|
|
46
|
+
<h3 className="font-semibold text-white mb-1">Zero Config</h3>
|
|
47
|
+
<p className="text-sm text-slate-400">
|
|
48
|
+
evjs works out of the box. Plugins extend it cleanly.
|
|
49
|
+
</p>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
{/* Typography plugin demo */}
|
|
54
|
+
<div className="rounded-xl border border-white/10 bg-white/5 backdrop-blur-sm p-8 mb-16">
|
|
55
|
+
<div className="prose prose-invert max-w-none" data-testid="prose">
|
|
56
|
+
<h2>Typography Plugin</h2>
|
|
57
|
+
<p>
|
|
58
|
+
This section uses <code>@tailwindcss/typography</code> via the{" "}
|
|
59
|
+
<code>prose</code> class. It automatically styles headings,
|
|
60
|
+
paragraphs, code blocks, lists, and more with beautiful defaults.
|
|
61
|
+
</p>
|
|
62
|
+
<ul>
|
|
63
|
+
<li>Automatic heading styles</li>
|
|
64
|
+
<li>Beautiful paragraph spacing</li>
|
|
65
|
+
<li>
|
|
66
|
+
Styled <code>code</code> elements
|
|
67
|
+
</li>
|
|
68
|
+
</ul>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
{/* Config preview */}
|
|
73
|
+
<div className="rounded-xl border border-white/10 bg-white/5 backdrop-blur-sm p-6">
|
|
74
|
+
<h2 className="text-lg font-semibold text-white mb-4">ev.config.ts</h2>
|
|
75
|
+
<pre className="text-sm text-slate-300 bg-black/30 rounded-lg p-4 overflow-x-auto">
|
|
76
|
+
<code>{`export default defineConfig({
|
|
77
|
+
client: {
|
|
78
|
+
plugins: [tailwind()],
|
|
79
|
+
},
|
|
80
|
+
});`}</code>
|
|
81
|
+
</pre>
|
|
82
|
+
</div>
|
|
83
|
+
</main>
|
|
84
|
+
),
|
|
85
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"jsx": "react-jsx",
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"lib": ["ESNext", "DOM", "DOM.Iterable"],
|
|
7
|
+
"moduleResolution": "Bundler",
|
|
8
|
+
"verbatimModuleSyntax": true,
|
|
9
|
+
"noEmit": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"strict": true,
|
|
12
|
+
"noUnusedLocals": true,
|
|
13
|
+
"noUnusedParameters": true,
|
|
14
|
+
"noFallthroughCasesInSwitch": true
|
|
15
|
+
},
|
|
16
|
+
"include": ["src"]
|
|
17
|
+
}
|