@govela/create 0.0.0-stage → 0.6.0
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/LICENSE +21 -0
- package/README.md +17 -2
- package/bin/create.js +146 -0
- package/package.json +24 -4
- package/templates/app/base/AGENTS.md +36 -0
- package/templates/app/base/README.md +19 -0
- package/templates/app/base/_github/workflows/ci.yml +23 -0
- package/templates/app/base/_gitignore +7 -0
- package/templates/app/base/cmd/server/main.go +53 -0
- package/templates/app/base/go.mod +8 -0
- package/templates/app/base/server/routes/load.go +30 -0
- package/templates/app/base/vela.config.json +6 -0
- package/templates/app/base/vite.config.js +11 -0
- package/templates/app/base/vitest.setup.__EXT__ +5 -0
- package/templates/app/js/eslint.config.js +12 -0
- package/templates/app/js/package.json +29 -0
- package/templates/app/js/src/routes/Layout.vela +24 -0
- package/templates/app/js/src/routes/Page.test.js +13 -0
- package/templates/app/js/src/routes/Page.vela +10 -0
- package/templates/app/ts/eslint.config.js +14 -0
- package/templates/app/ts/package.json +31 -0
- package/templates/app/ts/src/routes/Layout.vela +26 -0
- package/templates/app/ts/src/routes/Page.test.ts +13 -0
- package/templates/app/ts/src/routes/Page.vela +12 -0
- package/templates/app/ts/tsconfig.json +4 -0
- package/templates/app/ts/vela.app.json +1 -0
- package/templates/default/base/AGENTS.md +28 -0
- package/templates/default/base/README.md +17 -0
- package/templates/default/base/_github/workflows/ci.yml +20 -0
- package/templates/default/base/_gitignore +2 -0
- package/templates/default/base/index.html +12 -0
- package/templates/default/base/vite.config.js +9 -0
- package/templates/default/base/vitest.setup.__EXT__ +5 -0
- package/templates/default/js/eslint.config.js +12 -0
- package/templates/default/js/package.json +28 -0
- package/templates/default/js/src/App.vela +25 -0
- package/templates/default/js/src/Counter.test.js +20 -0
- package/templates/default/js/src/Counter.vela +23 -0
- package/templates/default/js/src/main.js +4 -0
- package/templates/default/ts/eslint.config.js +14 -0
- package/templates/default/ts/package.json +30 -0
- package/templates/default/ts/src/App.vela +25 -0
- package/templates/default/ts/src/Counter.test.ts +20 -0
- package/templates/default/ts/src/Counter.vela +27 -0
- package/templates/default/ts/src/main.ts +4 -0
- package/templates/default/ts/tsconfig.json +18 -0
- package/templates/ssr/base/AGENTS.md +34 -0
- package/templates/ssr/base/README.md +30 -0
- package/templates/ssr/base/_github/workflows/ci.yml +23 -0
- package/templates/ssr/base/_gitignore +4 -0
- package/templates/ssr/base/cmd/server/main.go +57 -0
- package/templates/ssr/base/go.mod +5 -0
- package/templates/ssr/base/vela.config.json +6 -0
- package/templates/ssr/base/vite.config.js +11 -0
- package/templates/ssr/base/vitest.setup.__EXT__ +5 -0
- package/templates/ssr/js/eslint.config.js +12 -0
- package/templates/ssr/js/package.json +30 -0
- package/templates/ssr/js/src/App.vela +27 -0
- package/templates/ssr/js/src/Counter.test.js +20 -0
- package/templates/ssr/js/src/Counter.vela +23 -0
- package/templates/ssr/js/src/client.js +5 -0
- package/templates/ssr/ts/eslint.config.js +14 -0
- package/templates/ssr/ts/package.json +32 -0
- package/templates/ssr/ts/src/App.vela +27 -0
- package/templates/ssr/ts/src/Counter.test.ts +20 -0
- package/templates/ssr/ts/src/Counter.vela +27 -0
- package/templates/ssr/ts/src/client.ts +5 -0
- package/templates/ssr/ts/tsconfig.json +18 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# __NAME__
|
|
2
|
+
|
|
3
|
+
A [Vela](https://github.com/elauven/vela) application: Vite with
|
|
4
|
+
`@govela/unplugin`, Vitest with `@govela/testing`, ESLint with
|
|
5
|
+
`@govela/eslint-plugin`.
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install
|
|
9
|
+
npm run dev # http://localhost:5173
|
|
10
|
+
npm test # component tests
|
|
11
|
+
npm run check # compiler diagnostics
|
|
12
|
+
npm run lint # eslint
|
|
13
|
+
npm run build # production build into dist/
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
`.github/workflows/ci.yml` runs the check, the linter, the tests and the build on every
|
|
17
|
+
push.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
test:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v5
|
|
12
|
+
- uses: actions/setup-node@v5
|
|
13
|
+
with:
|
|
14
|
+
node-version: '24'
|
|
15
|
+
cache: npm
|
|
16
|
+
- run: npm ci
|
|
17
|
+
- run: npm run check
|
|
18
|
+
- run: npm run lint
|
|
19
|
+
- run: npm test
|
|
20
|
+
- run: npm run build
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>__NAME__</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<div id="app"></div>
|
|
10
|
+
<script type="module" src="/src/main.__EXT__"></script>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { defineConfig } from 'eslint/config';
|
|
2
|
+
import js from '@eslint/js';
|
|
3
|
+
import globals from 'globals';
|
|
4
|
+
import vela from '@govela/eslint-plugin';
|
|
5
|
+
|
|
6
|
+
export default defineConfig(
|
|
7
|
+
{ ignores: ['dist/', 'out/', 'build/', 'src/_app/'] },
|
|
8
|
+
js.configs.recommended,
|
|
9
|
+
vela.configs.recommended,
|
|
10
|
+
{ files: ['src/**/*.js', '**/*.vela/*.js'], languageOptions: { globals: globals.browser } },
|
|
11
|
+
{ files: ['*.config.js'], languageOptions: { globals: globals.node } },
|
|
12
|
+
);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "__NAME__",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "vite",
|
|
7
|
+
"check": "vela check --project src",
|
|
8
|
+
"lint": "eslint .",
|
|
9
|
+
"test": "vitest run",
|
|
10
|
+
"build": "vite build",
|
|
11
|
+
"preview": "vite preview"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@govela/runtime": "__VERSION__"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@eslint/js": "^10.0.1",
|
|
18
|
+
"@govela/compiler": "__VERSION__",
|
|
19
|
+
"@govela/eslint-plugin": "__VERSION__",
|
|
20
|
+
"@govela/testing": "__VERSION__",
|
|
21
|
+
"@govela/unplugin": "__VERSION__",
|
|
22
|
+
"eslint": "^10.14.0",
|
|
23
|
+
"globals": "^17.0.0",
|
|
24
|
+
"happy-dom": "^21.0.4",
|
|
25
|
+
"vite": "^8.3.5",
|
|
26
|
+
"vitest": "^5.1.0"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import Counter from './Counter.vela';
|
|
3
|
+
|
|
4
|
+
let total = $state(0);
|
|
5
|
+
|
|
6
|
+
function changed(event) {
|
|
7
|
+
total = event.detail;
|
|
8
|
+
}
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<template>
|
|
12
|
+
<main>
|
|
13
|
+
<h1>Vela</h1>
|
|
14
|
+
<Counter :step={1} @on:change={changed}>Clicks</Counter>
|
|
15
|
+
<p class="total">Total: {total}</p>
|
|
16
|
+
</main>
|
|
17
|
+
</template>
|
|
18
|
+
|
|
19
|
+
<style>
|
|
20
|
+
main {
|
|
21
|
+
font-family: system-ui, sans-serif;
|
|
22
|
+
max-width: 32rem;
|
|
23
|
+
margin: 4rem auto;
|
|
24
|
+
}
|
|
25
|
+
</style>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { expect, test } from 'vitest';
|
|
2
|
+
import { fireEvent, render } from '@govela/testing';
|
|
3
|
+
import Counter from './Counter.vela';
|
|
4
|
+
|
|
5
|
+
test('counts by its step and reports the count', async () => {
|
|
6
|
+
const counts = [];
|
|
7
|
+
const { container } = render(Counter, {
|
|
8
|
+
props: { step: 2 },
|
|
9
|
+
slots: { default: 'Clicks' },
|
|
10
|
+
events: { change: (event) => counts.push(event.detail) },
|
|
11
|
+
});
|
|
12
|
+
const button = container.querySelector('button');
|
|
13
|
+
expect(button.textContent).toBe('Clicks: 0');
|
|
14
|
+
|
|
15
|
+
await fireEvent.click(button);
|
|
16
|
+
await fireEvent.click(button);
|
|
17
|
+
|
|
18
|
+
expect(button.textContent).toBe('Clicks: 4');
|
|
19
|
+
expect(counts).toEqual([2, 4]);
|
|
20
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export let step = 1;
|
|
3
|
+
|
|
4
|
+
let count = $state(0);
|
|
5
|
+
|
|
6
|
+
function increment() {
|
|
7
|
+
count += step;
|
|
8
|
+
$$dispatch('change', count);
|
|
9
|
+
}
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<template>
|
|
13
|
+
<button @click={increment}>
|
|
14
|
+
<slot>Count</slot>: {count}
|
|
15
|
+
</button>
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
<style>
|
|
19
|
+
button {
|
|
20
|
+
font: inherit;
|
|
21
|
+
padding: 0.5rem 1rem;
|
|
22
|
+
}
|
|
23
|
+
</style>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { defineConfig } from 'eslint/config';
|
|
2
|
+
import js from '@eslint/js';
|
|
3
|
+
import globals from 'globals';
|
|
4
|
+
import tseslint from 'typescript-eslint';
|
|
5
|
+
import vela from '@govela/eslint-plugin';
|
|
6
|
+
|
|
7
|
+
export default defineConfig(
|
|
8
|
+
{ ignores: ['dist/', 'out/', 'build/', 'src/_app/'] },
|
|
9
|
+
js.configs.recommended,
|
|
10
|
+
tseslint.configs.recommended,
|
|
11
|
+
vela.configs.recommended,
|
|
12
|
+
{ files: ['src/**/*.ts', '**/*.vela/*.ts'], languageOptions: { globals: globals.browser } },
|
|
13
|
+
{ files: ['*.config.js'], languageOptions: { globals: globals.node } },
|
|
14
|
+
);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "__NAME__",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "vite",
|
|
7
|
+
"check": "vela check --project src --types",
|
|
8
|
+
"lint": "eslint .",
|
|
9
|
+
"test": "vitest run",
|
|
10
|
+
"build": "vite build",
|
|
11
|
+
"preview": "vite preview"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@govela/runtime": "__VERSION__"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@eslint/js": "^10.0.1",
|
|
18
|
+
"@govela/compiler": "__VERSION__",
|
|
19
|
+
"@govela/eslint-plugin": "__VERSION__",
|
|
20
|
+
"@govela/testing": "__VERSION__",
|
|
21
|
+
"@govela/unplugin": "__VERSION__",
|
|
22
|
+
"eslint": "^10.14.0",
|
|
23
|
+
"globals": "^17.0.0",
|
|
24
|
+
"happy-dom": "^21.0.4",
|
|
25
|
+
"typescript": "^6.0.3",
|
|
26
|
+
"typescript-eslint": "^8.72.1",
|
|
27
|
+
"vite": "^8.3.5",
|
|
28
|
+
"vitest": "^5.1.0"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Counter from './Counter.vela';
|
|
3
|
+
|
|
4
|
+
let total = $state(0);
|
|
5
|
+
|
|
6
|
+
function changed(event: CustomEvent<number>): void {
|
|
7
|
+
total = event.detail;
|
|
8
|
+
}
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<template>
|
|
12
|
+
<main>
|
|
13
|
+
<h1>Vela</h1>
|
|
14
|
+
<Counter :step={1} @on:change={changed}>Clicks</Counter>
|
|
15
|
+
<p class="total">Total: {total}</p>
|
|
16
|
+
</main>
|
|
17
|
+
</template>
|
|
18
|
+
|
|
19
|
+
<style>
|
|
20
|
+
main {
|
|
21
|
+
font-family: system-ui, sans-serif;
|
|
22
|
+
max-width: 32rem;
|
|
23
|
+
margin: 4rem auto;
|
|
24
|
+
}
|
|
25
|
+
</style>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { expect, test } from 'vitest';
|
|
2
|
+
import { fireEvent, render } from '@govela/testing';
|
|
3
|
+
import Counter from './Counter.vela';
|
|
4
|
+
|
|
5
|
+
test('counts by its step and reports the count', async () => {
|
|
6
|
+
const counts: number[] = [];
|
|
7
|
+
const { container } = render(Counter, {
|
|
8
|
+
props: { step: 2 },
|
|
9
|
+
slots: { default: 'Clicks' },
|
|
10
|
+
events: { change: (event) => counts.push(event.detail) },
|
|
11
|
+
});
|
|
12
|
+
const button = container.querySelector('button')!;
|
|
13
|
+
expect(button.textContent).toBe('Clicks: 0');
|
|
14
|
+
|
|
15
|
+
await fireEvent.click(button);
|
|
16
|
+
await fireEvent.click(button);
|
|
17
|
+
|
|
18
|
+
expect(button.textContent).toBe('Clicks: 4');
|
|
19
|
+
expect(counts).toEqual([2, 4]);
|
|
20
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface $$Events {
|
|
3
|
+
change: number;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export let step: number = 1;
|
|
7
|
+
|
|
8
|
+
let count = $state(0);
|
|
9
|
+
|
|
10
|
+
function increment(): void {
|
|
11
|
+
count += step;
|
|
12
|
+
$$dispatch('change', count);
|
|
13
|
+
}
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<template>
|
|
17
|
+
<button @click={increment}>
|
|
18
|
+
<slot>Count</slot>: {count}
|
|
19
|
+
</button>
|
|
20
|
+
</template>
|
|
21
|
+
|
|
22
|
+
<style>
|
|
23
|
+
button {
|
|
24
|
+
font: inherit;
|
|
25
|
+
padding: 0.5rem 1rem;
|
|
26
|
+
}
|
|
27
|
+
</style>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"noEmit": true,
|
|
8
|
+
"isolatedModules": true,
|
|
9
|
+
"verbatimModuleSyntax": true,
|
|
10
|
+
"erasableSyntaxOnly": true,
|
|
11
|
+
"allowImportingTsExtensions": true,
|
|
12
|
+
"useDefineForClassFields": true,
|
|
13
|
+
"skipLibCheck": true,
|
|
14
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
15
|
+
"types": ["@govela/runtime/ambient"]
|
|
16
|
+
},
|
|
17
|
+
"include": ["src"]
|
|
18
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Agent instructions
|
|
2
|
+
|
|
3
|
+
This is a server-rendered Vela application. Before you create or edit a
|
|
4
|
+
`.vela` component, read the Vela authoring guide of the compiler version
|
|
5
|
+
this project uses:
|
|
6
|
+
|
|
7
|
+
https://github.com/elauven/vela/blob/v__VERSION__/AGENTS.md
|
|
8
|
+
|
|
9
|
+
It defines the component shape, the runes, the template syntax, the rules
|
|
10
|
+
of server rendering and what Vela does not support. When a compiler
|
|
11
|
+
diagnostic disagrees with an example, trust the diagnostic.
|
|
12
|
+
|
|
13
|
+
## This project
|
|
14
|
+
|
|
15
|
+
- Components live in `src/`. `vela` (configured by `vela.config.json`)
|
|
16
|
+
compiles them to Go renderers in `out/server`; `cmd/server` renders
|
|
17
|
+
`App` with them; `src/client.__EXT__` hydrates the HTML in the browser.
|
|
18
|
+
- Code that runs during the first render is translated to Go: keep it free
|
|
19
|
+
of browser APIs (`window`, `document`, `Date.now()`). Put browser work in
|
|
20
|
+
handlers, `$effect` or `onMount`. Treat every `VELA-SSR-*` diagnostic as
|
|
21
|
+
an error to fix.
|
|
22
|
+
- Tests are `*.test.__EXT__` files next to the components, run by Vitest with
|
|
23
|
+
`@govela/testing` (`render`, `fireEvent`).
|
|
24
|
+
|
|
25
|
+
## Before handing off
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
npm run check # vela check --ssr: compiler and server-rendering diagnostics (and types)
|
|
29
|
+
npm run lint # eslint: the code of the components and modules
|
|
30
|
+
npm test # vitest run
|
|
31
|
+
npm run build # vela, vite build and go build
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
All of them must pass.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# __NAME__
|
|
2
|
+
|
|
3
|
+
A server-rendered [Vela](https://github.com/elauven/vela) application: the
|
|
4
|
+
Go server in `cmd/server` renders the components, Vite with
|
|
5
|
+
`@govela/unplugin` builds the client that hydrates them, Vitest with
|
|
6
|
+
`@govela/testing` tests them.
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
npm install
|
|
10
|
+
go mod tidy
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Development, three processes:
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npm run dev:vela # vela --watch: Go renderers into out/
|
|
17
|
+
npm run dev # Vite on http://localhost:5173
|
|
18
|
+
npm run dev:server # the Go server on http://127.0.0.1:8080
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Restart the Go server after a change of a component (`out/.vela-ready`
|
|
22
|
+
is written after every successful build).
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
npm test # component tests
|
|
26
|
+
npm run check # compiler and server-rendering diagnostics
|
|
27
|
+
npm run lint # eslint
|
|
28
|
+
npm run build # out/, dist/ and build/server
|
|
29
|
+
npm start # the production server, serving dist/
|
|
30
|
+
```
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
test:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v5
|
|
12
|
+
- uses: actions/setup-go@v6
|
|
13
|
+
with:
|
|
14
|
+
go-version-file: go.mod
|
|
15
|
+
- uses: actions/setup-node@v5
|
|
16
|
+
with:
|
|
17
|
+
node-version: '24'
|
|
18
|
+
cache: npm
|
|
19
|
+
- run: npm ci
|
|
20
|
+
- run: npm run check
|
|
21
|
+
- run: npm run lint
|
|
22
|
+
- run: npm test
|
|
23
|
+
- run: npm run build
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// The server: renders App with the Go renderer `vela` generates into
|
|
2
|
+
// out/server, and adds the client from the Vite dev server (-dev) or from
|
|
3
|
+
// the output of vite build (-dist).
|
|
4
|
+
package main
|
|
5
|
+
|
|
6
|
+
import (
|
|
7
|
+
"flag"
|
|
8
|
+
"fmt"
|
|
9
|
+
"log"
|
|
10
|
+
"net"
|
|
11
|
+
"net/http"
|
|
12
|
+
"path/filepath"
|
|
13
|
+
|
|
14
|
+
"github.com/elauven/vela/ssr_runtime/vite"
|
|
15
|
+
|
|
16
|
+
components "__MODULE__/out/server/components"
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
func main() {
|
|
20
|
+
addr := flag.String("addr", "127.0.0.1:8080", "listen address")
|
|
21
|
+
dev := flag.String("dev", "", "URL of the Vite dev server; serve dist/ when empty")
|
|
22
|
+
dist := flag.String("dist", "dist", "output directory of vite build")
|
|
23
|
+
flag.Parse()
|
|
24
|
+
|
|
25
|
+
mux := http.NewServeMux()
|
|
26
|
+
var assets *vite.Assets
|
|
27
|
+
if *dev != "" {
|
|
28
|
+
assets = vite.Dev(*dev)
|
|
29
|
+
} else {
|
|
30
|
+
var err error
|
|
31
|
+
if assets, err = vite.Load(filepath.Join(*dist, ".vite", "manifest.json"), "/"); err != nil {
|
|
32
|
+
log.Fatal(err)
|
|
33
|
+
}
|
|
34
|
+
mux.Handle("/assets/", http.FileServer(http.Dir(*dist)))
|
|
35
|
+
}
|
|
36
|
+
tags, err := assets.Tags("src/client.__EXT__")
|
|
37
|
+
if err != nil {
|
|
38
|
+
log.Fatal(err)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
mux.HandleFunc("/{$}", func(w http.ResponseWriter, r *http.Request) {
|
|
42
|
+
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
43
|
+
fmt.Fprintf(w, "<!doctype html><html><head><meta charset=\"utf-8\">%s</head><body><div id=\"app\">", tags)
|
|
44
|
+
props := components.AppProps{Set: map[string]bool{"title": true}, Title: "Vela"}
|
|
45
|
+
if err := components.RenderAppContext(r.Context(), w, props, components.AppSlots{}); err != nil {
|
|
46
|
+
log.Print(err)
|
|
47
|
+
}
|
|
48
|
+
fmt.Fprint(w, "</div></body></html>")
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
listener, err := net.Listen("tcp", *addr)
|
|
52
|
+
if err != nil {
|
|
53
|
+
log.Fatal(err)
|
|
54
|
+
}
|
|
55
|
+
fmt.Println("http://" + listener.Addr().String() + "/")
|
|
56
|
+
log.Fatal(http.Serve(listener, mux))
|
|
57
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import vela from '@govela/unplugin/vite';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
plugins: [vela()],
|
|
5
|
+
server: { origin: 'http://localhost:5173' },
|
|
6
|
+
build: { manifest: true, rollupOptions: { input: 'src/client.__EXT__' } },
|
|
7
|
+
test: {
|
|
8
|
+
environment: 'happy-dom',
|
|
9
|
+
setupFiles: ['./vitest.setup.__EXT__'],
|
|
10
|
+
},
|
|
11
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { defineConfig } from 'eslint/config';
|
|
2
|
+
import js from '@eslint/js';
|
|
3
|
+
import globals from 'globals';
|
|
4
|
+
import vela from '@govela/eslint-plugin';
|
|
5
|
+
|
|
6
|
+
export default defineConfig(
|
|
7
|
+
{ ignores: ['dist/', 'out/', 'build/', 'src/_app/'] },
|
|
8
|
+
js.configs.recommended,
|
|
9
|
+
vela.configs.recommended,
|
|
10
|
+
{ files: ['src/**/*.js', '**/*.vela/*.js'], languageOptions: { globals: globals.browser } },
|
|
11
|
+
{ files: ['*.config.js'], languageOptions: { globals: globals.node } },
|
|
12
|
+
);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "__NAME__",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "vite",
|
|
7
|
+
"dev:vela": "vela --watch",
|
|
8
|
+
"dev:server": "go run ./cmd/server -dev http://localhost:5173",
|
|
9
|
+
"check": "vela check --project src --ssr",
|
|
10
|
+
"lint": "eslint .",
|
|
11
|
+
"test": "vitest run",
|
|
12
|
+
"build": "vela && vite build && go build -o build/server ./cmd/server",
|
|
13
|
+
"start": "./build/server"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@govela/runtime": "__VERSION__"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@eslint/js": "^10.0.1",
|
|
20
|
+
"@govela/compiler": "__VERSION__",
|
|
21
|
+
"@govela/eslint-plugin": "__VERSION__",
|
|
22
|
+
"@govela/testing": "__VERSION__",
|
|
23
|
+
"@govela/unplugin": "__VERSION__",
|
|
24
|
+
"eslint": "^10.14.0",
|
|
25
|
+
"globals": "^17.0.0",
|
|
26
|
+
"happy-dom": "^21.0.4",
|
|
27
|
+
"vite": "^8.3.5",
|
|
28
|
+
"vitest": "^5.1.0"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import Counter from './Counter.vela';
|
|
3
|
+
|
|
4
|
+
export let title = 'Vela';
|
|
5
|
+
|
|
6
|
+
let total = $state(0);
|
|
7
|
+
|
|
8
|
+
function changed(event) {
|
|
9
|
+
total = event.detail;
|
|
10
|
+
}
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<template>
|
|
14
|
+
<main>
|
|
15
|
+
<h1>{title}</h1>
|
|
16
|
+
<Counter :step={1} @on:change={changed}>Clicks</Counter>
|
|
17
|
+
<p class="total">Total: {total}</p>
|
|
18
|
+
</main>
|
|
19
|
+
</template>
|
|
20
|
+
|
|
21
|
+
<style>
|
|
22
|
+
main {
|
|
23
|
+
font-family: system-ui, sans-serif;
|
|
24
|
+
max-width: 32rem;
|
|
25
|
+
margin: 4rem auto;
|
|
26
|
+
}
|
|
27
|
+
</style>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { expect, test } from 'vitest';
|
|
2
|
+
import { fireEvent, render } from '@govela/testing';
|
|
3
|
+
import Counter from './Counter.vela';
|
|
4
|
+
|
|
5
|
+
test('counts by its step and reports the count', async () => {
|
|
6
|
+
const counts = [];
|
|
7
|
+
const { container } = render(Counter, {
|
|
8
|
+
props: { step: 2 },
|
|
9
|
+
slots: { default: 'Clicks' },
|
|
10
|
+
events: { change: (event) => counts.push(event.detail) },
|
|
11
|
+
});
|
|
12
|
+
const button = container.querySelector('button');
|
|
13
|
+
expect(button.textContent).toBe('Clicks: 0');
|
|
14
|
+
|
|
15
|
+
await fireEvent.click(button);
|
|
16
|
+
await fireEvent.click(button);
|
|
17
|
+
|
|
18
|
+
expect(button.textContent).toBe('Clicks: 4');
|
|
19
|
+
expect(counts).toEqual([2, 4]);
|
|
20
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export let step = 1;
|
|
3
|
+
|
|
4
|
+
let count = $state(0);
|
|
5
|
+
|
|
6
|
+
function increment() {
|
|
7
|
+
count += step;
|
|
8
|
+
$$dispatch('change', count);
|
|
9
|
+
}
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<template>
|
|
13
|
+
<button @click={increment}>
|
|
14
|
+
<slot>Count</slot>: {count}
|
|
15
|
+
</button>
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
<style>
|
|
19
|
+
button {
|
|
20
|
+
font: inherit;
|
|
21
|
+
padding: 0.5rem 1rem;
|
|
22
|
+
}
|
|
23
|
+
</style>
|