create-vite-hyperapp 1.2.0 → 2.0.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/README.md +110 -18
- package/create-vite-hyperapp.mjs +193 -0
- package/package.json +18 -11
- package/templates/{template → common}/_gitignore +1 -1
- package/templates/{template-ts/src → common/src/app}/style.css +0 -4
- package/templates/{template → js-html-cli}/index.html +3 -3
- package/templates/js-html-cli/jsconfig.json +13 -0
- package/templates/js-html-cli/package.json +20 -0
- package/templates/js-html-cli/src/app/counter.js +5 -0
- package/templates/js-html-cli/src/app/logos.js +24 -0
- package/templates/js-html-cli/src/app/main.js +24 -0
- package/templates/{template → js-html-cli}/src/run.js +2 -2
- package/templates/js-html-cli/vite.config.js +12 -0
- package/templates/{template-ssr → js-html-ssr}/index.html +2 -2
- package/templates/js-html-ssr/jsconfig.json +13 -0
- package/templates/js-html-ssr/package.json +25 -0
- package/templates/{template-ssr → js-html-ssr}/server.js +10 -8
- package/templates/js-html-ssr/src/app/counter.js +5 -0
- package/templates/js-html-ssr/src/app/logos.js +24 -0
- package/templates/js-html-ssr/src/app/main.js +24 -0
- package/templates/{template-ssr → js-html-ssr}/src/entry-client.js +2 -2
- package/templates/js-html-ssr/src/entry-server.js +5 -0
- package/templates/js-html-ssr/vite.config.js +13 -0
- package/templates/js-jsx-cli/index.html +13 -0
- package/templates/js-jsx-cli/jsconfig.json +15 -0
- package/templates/{template → js-jsx-cli}/package.json +3 -3
- package/templates/js-jsx-cli/src/app/logos.jsx +15 -0
- package/templates/{template/src → js-jsx-cli/src/app}/main.jsx +1 -13
- package/templates/js-jsx-cli/src/run.js +5 -0
- package/templates/js-jsx-cli/vite.config.js +12 -0
- package/templates/js-jsx-ssr/index.html +13 -0
- package/templates/js-jsx-ssr/jsconfig.json +15 -0
- package/templates/{template-ssr → js-jsx-ssr}/package.json +7 -7
- package/templates/{template-ts-ssr → js-jsx-ssr}/server.js +11 -9
- package/templates/js-jsx-ssr/src/app/logos.jsx +15 -0
- package/templates/{template-ssr/src → js-jsx-ssr/src/app}/main.jsx +1 -13
- package/templates/js-jsx-ssr/src/entry-client.js +5 -0
- package/templates/js-jsx-ssr/src/entry-server.js +5 -0
- package/templates/js-jsx-ssr/vite.config.js +13 -0
- package/templates/js-plain-cli/index.html +13 -0
- package/templates/js-plain-cli/jsconfig.json +13 -0
- package/templates/{template-ts → js-plain-cli}/package.json +4 -5
- package/templates/js-plain-cli/src/app/counter.js +8 -0
- package/templates/js-plain-cli/src/app/logos.js +18 -0
- package/templates/js-plain-cli/src/app/main.js +25 -0
- package/templates/js-plain-cli/src/run.js +5 -0
- package/templates/js-plain-cli/vite.config.js +12 -0
- package/templates/js-plain-ssr/index.html +13 -0
- package/templates/js-plain-ssr/jsconfig.json +13 -0
- package/templates/{template-ts-ssr → js-plain-ssr}/package.json +8 -9
- package/templates/js-plain-ssr/server.js +62 -0
- package/templates/js-plain-ssr/src/app/counter.js +8 -0
- package/templates/js-plain-ssr/src/app/logos.js +18 -0
- package/templates/js-plain-ssr/src/app/main.js +25 -0
- package/templates/js-plain-ssr/src/entry-client.js +5 -0
- package/templates/js-plain-ssr/src/entry-server.js +5 -0
- package/templates/js-plain-ssr/vite.config.js +13 -0
- package/templates/tj-html-cli/index.html +13 -0
- package/templates/tj-html-cli/jsconfig.json +29 -0
- package/templates/tj-html-cli/package.json +21 -0
- package/templates/tj-html-cli/src/app/counter.js +16 -0
- package/templates/tj-html-cli/src/app/logos.js +24 -0
- package/templates/tj-html-cli/src/app/main.js +27 -0
- package/templates/tj-html-cli/src/run.js +5 -0
- package/templates/tj-html-cli/src/types/global.d.ts +13 -0
- package/templates/tj-html-cli/src/types/hyperapp-html.d.ts +101 -0
- package/templates/tj-html-cli/src/types/hyperapp-svg.d.ts +73 -0
- package/templates/tj-html-cli/src/types/hyperapp-tags.d.ts +34 -0
- package/templates/tj-html-cli/vite.config.js +12 -0
- package/templates/tj-html-ssr/index.html +13 -0
- package/templates/tj-html-ssr/jsconfig.json +31 -0
- package/templates/tj-html-ssr/package.json +29 -0
- package/templates/tj-html-ssr/server.js +63 -0
- package/templates/tj-html-ssr/src/app/counter.js +16 -0
- package/templates/tj-html-ssr/src/app/logos.js +24 -0
- package/templates/tj-html-ssr/src/app/main.js +27 -0
- package/templates/tj-html-ssr/src/entry-client.js +5 -0
- package/templates/tj-html-ssr/src/entry-server.js +5 -0
- package/templates/tj-html-ssr/src/types/global.d.ts +13 -0
- package/templates/tj-html-ssr/src/types/hyperapp-html.d.ts +101 -0
- package/templates/tj-html-ssr/src/types/hyperapp-svg.d.ts +73 -0
- package/templates/tj-html-ssr/src/types/hyperapp-tags.d.ts +34 -0
- package/templates/tj-html-ssr/vite.config.js +13 -0
- package/templates/tj-jsx-cli/index.html +13 -0
- package/templates/tj-jsx-cli/jsconfig.json +31 -0
- package/templates/tj-jsx-cli/package.json +19 -0
- package/templates/tj-jsx-cli/src/app/counter.jsx +18 -0
- package/templates/tj-jsx-cli/src/app/logos.jsx +15 -0
- package/templates/tj-jsx-cli/src/app/main.jsx +26 -0
- package/templates/tj-jsx-cli/src/run.js +5 -0
- package/templates/tj-jsx-cli/src/types/global.d.ts +13 -0
- package/templates/tj-jsx-cli/vite.config.js +12 -0
- package/templates/tj-jsx-ssr/index.html +13 -0
- package/templates/tj-jsx-ssr/jsconfig.json +33 -0
- package/templates/tj-jsx-ssr/package.json +27 -0
- package/templates/tj-jsx-ssr/server.js +63 -0
- package/templates/tj-jsx-ssr/src/app/counter.jsx +18 -0
- package/templates/tj-jsx-ssr/src/app/logos.jsx +15 -0
- package/templates/tj-jsx-ssr/src/app/main.jsx +26 -0
- package/templates/tj-jsx-ssr/src/entry-client.js +5 -0
- package/templates/tj-jsx-ssr/src/entry-server.js +5 -0
- package/templates/tj-jsx-ssr/src/types/global.d.ts +13 -0
- package/templates/tj-jsx-ssr/vite.config.js +13 -0
- package/templates/tj-plain-cli/index.html +13 -0
- package/templates/tj-plain-cli/jsconfig.json +29 -0
- package/templates/tj-plain-cli/package.json +19 -0
- package/templates/tj-plain-cli/src/app/counter.js +19 -0
- package/templates/tj-plain-cli/src/app/logos.js +18 -0
- package/templates/tj-plain-cli/src/app/main.js +28 -0
- package/templates/tj-plain-cli/src/run.js +5 -0
- package/templates/tj-plain-cli/src/types/global.d.ts +13 -0
- package/templates/tj-plain-cli/src/types/hyperapp-h.d.ts +37 -0
- package/templates/tj-plain-cli/vite.config.js +12 -0
- package/templates/tj-plain-ssr/index.html +13 -0
- package/templates/tj-plain-ssr/jsconfig.json +31 -0
- package/templates/tj-plain-ssr/package.json +27 -0
- package/templates/tj-plain-ssr/server.js +63 -0
- package/templates/tj-plain-ssr/src/app/counter.js +19 -0
- package/templates/tj-plain-ssr/src/app/logos.js +18 -0
- package/templates/tj-plain-ssr/src/app/main.js +28 -0
- package/templates/tj-plain-ssr/src/entry-client.js +5 -0
- package/templates/tj-plain-ssr/src/entry-server.js +5 -0
- package/templates/tj-plain-ssr/src/types/global.d.ts +13 -0
- package/templates/tj-plain-ssr/src/types/hyperapp-h.d.ts +37 -0
- package/templates/tj-plain-ssr/vite.config.js +13 -0
- package/templates/{template-ts → ts-html-cli}/index.html +3 -3
- package/templates/ts-html-cli/package.json +21 -0
- package/templates/ts-html-cli/src/app/counter.ts +12 -0
- package/templates/ts-html-cli/src/app/logos.ts +33 -0
- package/templates/ts-html-cli/src/app/main.ts +27 -0
- package/templates/{template-ts → ts-html-cli}/src/run.ts +2 -2
- package/templates/ts-html-cli/src/types/hyperapp-html.d.ts +101 -0
- package/templates/ts-html-cli/src/types/hyperapp-svg.d.ts +73 -0
- package/templates/ts-html-cli/src/types/hyperapp-tags.d.ts +34 -0
- package/templates/ts-html-cli/tsconfig.json +27 -0
- package/templates/ts-html-cli/vite.config.ts +12 -0
- package/templates/{template-ts-ssr → ts-html-ssr}/index.html +2 -2
- package/templates/ts-html-ssr/package.json +32 -0
- package/templates/ts-html-ssr/server.ts +63 -0
- package/templates/ts-html-ssr/src/app/counter.ts +12 -0
- package/templates/ts-html-ssr/src/app/logos.ts +33 -0
- package/templates/ts-html-ssr/src/app/main.ts +27 -0
- package/templates/{template-ts-ssr → ts-html-ssr}/src/entry-client.ts +2 -2
- package/templates/ts-html-ssr/src/entry-server.ts +5 -0
- package/templates/ts-html-ssr/src/types/hyperapp-html.d.ts +101 -0
- package/templates/ts-html-ssr/src/types/hyperapp-svg.d.ts +73 -0
- package/templates/ts-html-ssr/src/types/hyperapp-tags.d.ts +34 -0
- package/templates/ts-html-ssr/tsconfig.json +27 -0
- package/templates/ts-html-ssr/vite.config.ts +13 -0
- package/templates/ts-jsx-cli/index.html +13 -0
- package/templates/ts-jsx-cli/package.json +21 -0
- package/templates/{template-ts-ssr/src → ts-jsx-cli/src/app}/counter.tsx +3 -3
- package/templates/ts-jsx-cli/src/app/logos.tsx +19 -0
- package/templates/ts-jsx-cli/src/app/main.tsx +26 -0
- package/templates/ts-jsx-cli/src/assets/typescript.svg +1 -0
- package/templates/ts-jsx-cli/src/run.ts +5 -0
- package/templates/{template-ts → ts-jsx-cli}/tsconfig.json +6 -3
- package/templates/ts-jsx-cli/vite.config.ts +12 -0
- package/templates/ts-jsx-ssr/index.html +13 -0
- package/templates/ts-jsx-ssr/package.json +30 -0
- package/templates/ts-jsx-ssr/server.ts +63 -0
- package/templates/{template-ts/src → ts-jsx-ssr/src/app}/counter.tsx +3 -3
- package/templates/ts-jsx-ssr/src/app/logos.tsx +19 -0
- package/templates/{template-ts-ssr/src → ts-jsx-ssr/src/app}/main.tsx +1 -17
- package/templates/ts-jsx-ssr/src/assets/typescript.svg +1 -0
- package/templates/ts-jsx-ssr/src/entry-client.ts +5 -0
- package/templates/ts-jsx-ssr/src/entry-server.ts +5 -0
- package/templates/{template-ts-ssr → ts-jsx-ssr}/tsconfig.json +7 -4
- package/templates/ts-jsx-ssr/vite.config.ts +13 -0
- package/templates/ts-plain-cli/index.html +13 -0
- package/templates/ts-plain-cli/package.json +21 -0
- package/templates/ts-plain-cli/src/app/counter.ts +13 -0
- package/templates/ts-plain-cli/src/app/logos.ts +30 -0
- package/templates/ts-plain-cli/src/app/main.ts +27 -0
- package/templates/ts-plain-cli/src/assets/typescript.svg +1 -0
- package/templates/ts-plain-cli/src/run.ts +5 -0
- package/templates/ts-plain-cli/src/types/hyperapp-h.d.ts +37 -0
- package/templates/ts-plain-cli/tsconfig.json +27 -0
- package/templates/ts-plain-cli/vite.config.ts +12 -0
- package/templates/ts-plain-ssr/index.html +13 -0
- package/templates/ts-plain-ssr/package.json +30 -0
- package/templates/ts-plain-ssr/server.ts +63 -0
- package/templates/ts-plain-ssr/src/app/counter.ts +13 -0
- package/templates/ts-plain-ssr/src/app/logos.ts +30 -0
- package/templates/ts-plain-ssr/src/app/main.ts +27 -0
- package/templates/ts-plain-ssr/src/assets/typescript.svg +1 -0
- package/templates/ts-plain-ssr/src/entry-client.ts +5 -0
- package/templates/ts-plain-ssr/src/entry-server.ts +5 -0
- package/templates/ts-plain-ssr/src/types/hyperapp-h.d.ts +37 -0
- package/templates/ts-plain-ssr/tsconfig.json +27 -0
- package/templates/ts-plain-ssr/vite.config.ts +13 -0
- package/index.js +0 -154
- package/templates/template/public/vite.svg +0 -1
- package/templates/template/src/hyperapp.svg +0 -4
- package/templates/template/src/style.css +0 -97
- package/templates/template/vite.config.js +0 -6
- package/templates/template-ssr/_gitignore +0 -24
- package/templates/template-ssr/src/entry-server.js +0 -5
- package/templates/template-ssr/src/style.css +0 -97
- package/templates/template-ssr/vite.config.js +0 -6
- package/templates/template-ts/_gitignore +0 -24
- package/templates/template-ts/public/vite.svg +0 -1
- package/templates/template-ts/src/hyperapp.svg +0 -4
- package/templates/template-ts/src/main.tsx +0 -42
- package/templates/template-ts/src/vite-env.d.ts +0 -2
- package/templates/template-ts/vite.config.ts +0 -6
- package/templates/template-ts-ssr/_gitignore +0 -24
- package/templates/template-ts-ssr/public/vite.svg +0 -1
- package/templates/template-ts-ssr/src/entry-server.ts +0 -5
- package/templates/template-ts-ssr/src/style.css +0 -97
- package/templates/template-ts-ssr/src/vite-env.d.ts +0 -2
- package/templates/template-ts-ssr/vite.config.ts +0 -6
- /package/templates/{template-ssr/src/hyperapp.svg → common/public/favicon.svg} +0 -0
- /package/templates/{template-ts-ssr/src → common/src/assets}/hyperapp.svg +0 -0
- /package/templates/{template-ssr/public → common/src/assets}/vite.svg +0 -0
- /package/templates/{template-ssr/src → js-jsx-cli/src/app}/counter.jsx +0 -0
- /package/templates/{template/src → js-jsx-ssr/src/app}/counter.jsx +0 -0
- /package/templates/{template-ts-ssr/src → ts-html-cli/src/assets}/typescript.svg +0 -0
- /package/templates/{template-ts/src → ts-html-ssr/src/assets}/typescript.svg +0 -0
package/README.md
CHANGED
|
@@ -1,34 +1,126 @@
|
|
|
1
1
|
# create-vite-hyperapp
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Create a project using [Hyperapp](https://github.com/jorgebucaran/hyperapp) and [Vite](https://vite.dev/). The generated projects use [vite-plugin-hyperapp](https://github.com/zaceno/vite-plugin-hyperapp#readme) for development, builds, and optional server-side rendering; see its README for more about the plugin.
|
|
4
4
|
|
|
5
5
|
## Usage
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
```text
|
|
8
|
+
Usage: npm create vite-hyperapp -- [name] [options]
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
Create a Vite + Hyperapp project in an empty directory.
|
|
11
|
+
Run without arguments to choose options interactively.
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
Arguments:
|
|
14
|
+
name Project name and directory (default: hyperapp-app)
|
|
15
|
+
Use . or ./ for the current empty directory.
|
|
13
16
|
|
|
14
17
|
Options:
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
--types=none|jsdoc|typescript Type checking (default: typescript)
|
|
19
|
+
--views=plain|html|jsx View style (default: jsx)
|
|
20
|
+
--ssr=no|yes Server-side rendering (default: no)
|
|
21
|
+
-h, --help Show this message and exit
|
|
22
|
+
|
|
23
|
+
Examples:
|
|
24
|
+
npm create vite-hyperapp -- my-app --types=jsdoc --views=html --ssr=yes
|
|
25
|
+
npm create vite-hyperapp -- .
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Writing views
|
|
29
|
+
|
|
30
|
+
Choose how you want to write Hyperapp's view functions. These examples show the same counter component in plain JavaScript; your choice of view style is independent of your choice of typing system.
|
|
31
|
+
|
|
32
|
+
### Plain Hyperapp (`--views=plain`)
|
|
33
|
+
|
|
34
|
+
Use Hyperapp's built-in `h` and `text` functions:
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
import { h, text } from "hyperapp"
|
|
38
|
+
|
|
39
|
+
const Counter = ({ clicks, onclick }) =>
|
|
40
|
+
h("div", { class: "card" }, [
|
|
41
|
+
h("button", { onclick }, text("Clicks: " + clicks)),
|
|
42
|
+
])
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### HTML functions (`--views=html`)
|
|
46
|
+
|
|
47
|
+
Use tags from `@hyperapp/html` as functions:
|
|
48
|
+
|
|
49
|
+
```js
|
|
50
|
+
import { div, button, text } from "@hyperapp/html"
|
|
51
|
+
|
|
52
|
+
const Counter = ({ clicks, onclick }) =>
|
|
53
|
+
div({ class: "card" }, button({ onclick }, text("Clicks: " + clicks)))
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### JSX (`--views=jsx`)
|
|
57
|
+
|
|
58
|
+
Write markup-like components in `.jsx` files:
|
|
59
|
+
|
|
60
|
+
```jsx
|
|
61
|
+
const Counter = ({ clicks, onclick }) => (
|
|
62
|
+
<div class="card">
|
|
63
|
+
<button onclick={onclick}>Clicks: {clicks}</button>
|
|
64
|
+
</div>
|
|
65
|
+
)
|
|
23
66
|
```
|
|
24
67
|
|
|
25
|
-
##
|
|
68
|
+
## Typing
|
|
69
|
+
|
|
70
|
+
Choose separately whether—and how—to type-check your project. The following examples all use the HTML-function view style so you can compare the same component.
|
|
71
|
+
|
|
72
|
+
### JavaScript without type-checking (`--types=none`)
|
|
73
|
+
|
|
74
|
+
Write JavaScript without type annotations. `npm run build` does not run a type checker:
|
|
75
|
+
|
|
76
|
+
```js
|
|
77
|
+
import { div, button, text } from "@hyperapp/html"
|
|
78
|
+
|
|
79
|
+
const Counter = ({ clicks, onclick }) =>
|
|
80
|
+
div({ class: "card" }, button({ onclick }, text("Clicks: " + clicks)))
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### JavaScript with JSDoc type-checking (`--types=jsdoc`)
|
|
84
|
+
|
|
85
|
+
Keep `.js`/`.jsx` files and add types in [JSDoc comments](https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html). The build runs TypeScript's checker on your JavaScript:
|
|
26
86
|
|
|
27
|
-
|
|
87
|
+
```js
|
|
88
|
+
import { div, button, text } from "@hyperapp/html"
|
|
28
89
|
|
|
29
|
-
|
|
90
|
+
/**
|
|
91
|
+
* @template S
|
|
92
|
+
* @typedef CounterProps
|
|
93
|
+
* @property {number} clicks
|
|
94
|
+
* @property {Action<S>} onclick
|
|
95
|
+
*/
|
|
30
96
|
|
|
31
|
-
|
|
97
|
+
/**
|
|
98
|
+
* @template S
|
|
99
|
+
* @param {CounterProps<S>} props
|
|
100
|
+
*/
|
|
101
|
+
const Counter = ({ clicks, onclick }) =>
|
|
102
|
+
div({ class: "card" }, button({ onclick }, text("Clicks: " + clicks)))
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Here `Action<S>` is available from the generated project's `src/types/global.d.ts`.
|
|
106
|
+
|
|
107
|
+
### TypeScript (`--types=typescript`)
|
|
108
|
+
|
|
109
|
+
Use [TypeScript syntax](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html) in `.ts`/`.tsx` files. The build type-checks the project before bundling:
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
import { div, button, text } from "@hyperapp/html"
|
|
113
|
+
import type { Action } from "hyperapp"
|
|
114
|
+
|
|
115
|
+
type CounterProps<S> = {
|
|
116
|
+
clicks: number
|
|
117
|
+
onclick: Action<S>
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const Counter = <S>({ clicks, onclick }: CounterProps<S>) =>
|
|
121
|
+
div({ class: "card" }, button({ onclick }, text("Clicks: " + clicks)))
|
|
122
|
+
```
|
|
32
123
|
|
|
33
|
-
|
|
124
|
+
## Server-side rendering
|
|
34
125
|
|
|
126
|
+
With `--ssr=yes`, the server sends the initial view as HTML, so visitors can see it before the client app finishes loading. This can improve perceived loading speed. When the client starts, Hyperapp recycles the server-provided DOM rather than replacing it. The generated project includes separate client and server entries and a server for development and production. See the [vite-plugin-hyperapp SSR documentation](https://github.com/zaceno/vite-plugin-hyperapp#server-side-rendering) for more detail.
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { cpSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, renameSync, writeFileSync } from "node:fs"
|
|
3
|
+
import { basename, dirname, join, resolve } from "node:path"
|
|
4
|
+
import { fileURLToPath } from "node:url"
|
|
5
|
+
import { confirm, input, select } from "@inquirer/prompts"
|
|
6
|
+
import { bold, cyan, isColorSupported, red, white, yellow } from "colorette"
|
|
7
|
+
|
|
8
|
+
const templates = join(dirname(fileURLToPath(import.meta.url)), "templates")
|
|
9
|
+
const usage = `Usage: npm create vite-hyperapp -- [name] [options]
|
|
10
|
+
|
|
11
|
+
Create a Vite + Hyperapp project in an empty directory.
|
|
12
|
+
Run without arguments to choose options interactively.
|
|
13
|
+
|
|
14
|
+
Arguments:
|
|
15
|
+
name Project name and directory (default: hyperapp-app)
|
|
16
|
+
Use . or ./ for the current empty directory.
|
|
17
|
+
|
|
18
|
+
Options:
|
|
19
|
+
--types=none|jsdoc|typescript Type checking (default: typescript)
|
|
20
|
+
--views=plain|html|jsx View style (default: jsx)
|
|
21
|
+
--ssr=no|yes Server-side rendering (default: no)
|
|
22
|
+
-h, --help Show this message and exit
|
|
23
|
+
|
|
24
|
+
Examples:
|
|
25
|
+
npm create vite-hyperapp -- my-app --types=jsdoc --views=html --ssr=yes
|
|
26
|
+
npm create vite-hyperapp -- .
|
|
27
|
+
`
|
|
28
|
+
|
|
29
|
+
function parseOptions(args) {
|
|
30
|
+
const options = { name: "hyperapp-app", types: "typescript", views: "jsx", ssr: "no" }
|
|
31
|
+
const choices = {
|
|
32
|
+
types: ["none", "jsdoc", "typescript"],
|
|
33
|
+
views: ["plain", "html", "jsx"],
|
|
34
|
+
ssr: ["no", "yes"],
|
|
35
|
+
}
|
|
36
|
+
const seen = new Set()
|
|
37
|
+
let hasName = false
|
|
38
|
+
|
|
39
|
+
for (let i = 0; i < args.length; i++) {
|
|
40
|
+
const arg = args[i]
|
|
41
|
+
if (!arg.startsWith("-")) {
|
|
42
|
+
if (hasName) throw new Error("Provide only one project name. See --help.")
|
|
43
|
+
options.name = arg
|
|
44
|
+
hasName = true
|
|
45
|
+
continue
|
|
46
|
+
}
|
|
47
|
+
if (!arg.startsWith("--")) throw new Error(`Unknown argument: ${arg}. See --help.`)
|
|
48
|
+
const equal = arg.indexOf("=")
|
|
49
|
+
const key = arg.slice(2, equal === -1 ? undefined : equal)
|
|
50
|
+
if (!(key in choices)) throw new Error(`Unknown option: --${key}. See --help.`)
|
|
51
|
+
if (seen.has(key)) throw new Error(`--${key} was provided more than once.`)
|
|
52
|
+
seen.add(key)
|
|
53
|
+
|
|
54
|
+
const value = equal === -1 ? args[++i] : arg.slice(equal + 1)
|
|
55
|
+
if (!value || value.startsWith("--")) throw new Error(`--${key} requires a value. See --help.`)
|
|
56
|
+
if (!choices[key].includes(value)) {
|
|
57
|
+
throw new Error(`Invalid --${key} value: ${value}. Choose ${choices[key].join(", ")}.`)
|
|
58
|
+
}
|
|
59
|
+
options[key] = value
|
|
60
|
+
}
|
|
61
|
+
return options
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function getTarget(options) {
|
|
65
|
+
const here = options.name === "." || options.name === "./"
|
|
66
|
+
const name = here ? basename(process.cwd()) : options.name
|
|
67
|
+
if (!/^[a-z0-9][a-z0-9._-]*$/.test(name)) {
|
|
68
|
+
throw new Error(`Invalid project name: ${name}. Use lowercase letters, digits, dots, hyphens, or underscores (starting with a letter or digit).`)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const destination = here ? process.cwd() : resolve(process.cwd(), name)
|
|
72
|
+
if (existsSync(destination)) {
|
|
73
|
+
if (!lstatSync(destination).isDirectory()) throw new Error(`Target is not a directory: ${destination}`)
|
|
74
|
+
if (readdirSync(destination).length) throw new Error(`Target directory is not empty: ${destination}`)
|
|
75
|
+
}
|
|
76
|
+
return { here, name, destination }
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function createProject(options) {
|
|
80
|
+
const { here, name, destination } = getTarget(options)
|
|
81
|
+
const variant = `${{ none: "js", jsdoc: "tj", typescript: "ts" }[options.types]}-${options.views}-${options.ssr === "yes" ? "ssr" : "cli"}`
|
|
82
|
+
|
|
83
|
+
if (!existsSync(destination)) {
|
|
84
|
+
try {
|
|
85
|
+
mkdirSync(destination)
|
|
86
|
+
} catch (error) {
|
|
87
|
+
throw new Error(`Could not create target directory ${destination}: ${error.message}`)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
cpSync(join(templates, "common"), destination, { recursive: true, force: false, errorOnExist: true })
|
|
92
|
+
cpSync(join(templates, variant), destination, { recursive: true, force: false, errorOnExist: true })
|
|
93
|
+
renameSync(join(destination, "_gitignore"), join(destination, ".gitignore"))
|
|
94
|
+
|
|
95
|
+
for (const filename of ["package.json", "index.html"]) {
|
|
96
|
+
const path = join(destination, filename)
|
|
97
|
+
writeFileSync(path, readFileSync(path, "utf8").replaceAll("__PROJECTNAME__", name))
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
console.log(`Created ${name} in ${destination}.\n\nNext steps:`)
|
|
101
|
+
if (!here) console.log(` cd ${name}`)
|
|
102
|
+
console.log(" npm install\n npm run dev")
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async function wizard() {
|
|
106
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
107
|
+
throw new Error("The wizard needs an interactive terminal. Pass a name or options to run without it.")
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Colorette handles bold and white; truecolor supplies the requested RGB accent.
|
|
111
|
+
const logo = isColorSupported
|
|
112
|
+
? `\x1b[48;2;107;154;238m ${bold(white("+\\"))} \x1b[49m`
|
|
113
|
+
: "+\\"
|
|
114
|
+
const heading = isColorSupported
|
|
115
|
+
? `\x1b[38;2;107;154;238m${bold("Create a project with Vite & Hyperapp")}\x1b[39m`
|
|
116
|
+
: "Create a project with Vite & Hyperapp"
|
|
117
|
+
console.log(`\n${heading} ${logo}\n`)
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
const name = (await input({
|
|
121
|
+
message: "Project name (. or ./ for current directory)",
|
|
122
|
+
default: "hyperapp-app",
|
|
123
|
+
validate(value) {
|
|
124
|
+
try {
|
|
125
|
+
getTarget({ name: value.trim() || "hyperapp-app" })
|
|
126
|
+
return true
|
|
127
|
+
} catch (error) {
|
|
128
|
+
return error.message
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
})).trim() || "hyperapp-app"
|
|
132
|
+
|
|
133
|
+
const views = await select({
|
|
134
|
+
message: "Views",
|
|
135
|
+
choices: [
|
|
136
|
+
{ name: "Plain Hyperapp (h/text)", value: "plain" },
|
|
137
|
+
{ name: "@hyperapp/html", value: "html" },
|
|
138
|
+
{ name: "JSX", value: "jsx" },
|
|
139
|
+
],
|
|
140
|
+
default: "jsx",
|
|
141
|
+
})
|
|
142
|
+
const types = await select({
|
|
143
|
+
message: "Types",
|
|
144
|
+
choices: [
|
|
145
|
+
{ name: "JavaScript (no type-checking)", value: "none" },
|
|
146
|
+
{ name: "JavaScript with JSDoc type-checking", value: "jsdoc" },
|
|
147
|
+
{ name: "TypeScript", value: "typescript" },
|
|
148
|
+
],
|
|
149
|
+
default: "typescript",
|
|
150
|
+
})
|
|
151
|
+
const ssr = await select({
|
|
152
|
+
message: "Server-side rendering",
|
|
153
|
+
choices: [
|
|
154
|
+
{ name: "No (client-only)", value: "no" },
|
|
155
|
+
{ name: "Yes (SSR)", value: "yes" },
|
|
156
|
+
],
|
|
157
|
+
default: "no",
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
console.log(`\n${bold("Your project")}`)
|
|
161
|
+
console.log(` Name: ${cyan(name)}`)
|
|
162
|
+
console.log(` Views: ${cyan(views)}`)
|
|
163
|
+
console.log(` Types: ${cyan(types)}`)
|
|
164
|
+
console.log(` SSR: ${cyan(ssr)}`)
|
|
165
|
+
|
|
166
|
+
if (!await confirm({ message: "Create this project?", default: false })) {
|
|
167
|
+
console.log(yellow("Cancelled. No project was created."))
|
|
168
|
+
return
|
|
169
|
+
}
|
|
170
|
+
createProject({ name, views, types, ssr })
|
|
171
|
+
} catch (error) {
|
|
172
|
+
if (error.name !== "ExitPromptError") throw error
|
|
173
|
+
console.log(yellow("\nCancelled. No project was created."))
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
async function main() {
|
|
178
|
+
const args = process.argv.slice(2)
|
|
179
|
+
if (args.some(arg => arg === "--help" || arg === "-h")) {
|
|
180
|
+
console.log(usage)
|
|
181
|
+
} else if (args.length === 0) {
|
|
182
|
+
await wizard()
|
|
183
|
+
} else {
|
|
184
|
+
createProject(parseOptions(args))
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
try {
|
|
189
|
+
await main()
|
|
190
|
+
} catch (error) {
|
|
191
|
+
console.error(red(`Error: ${error.message}`))
|
|
192
|
+
process.exitCode = 1
|
|
193
|
+
}
|
package/package.json
CHANGED
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-vite-hyperapp",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Create a Vite + Hyperapp project",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/zaceno/create-vite-hyperapp.git"
|
|
9
8
|
},
|
|
10
9
|
"author": "Zacharias Enochsson",
|
|
11
10
|
"license": "MIT",
|
|
12
|
-
"
|
|
13
|
-
"minimist": "^1.2.8",
|
|
14
|
-
"prompts": "^2.4.2"
|
|
15
|
-
},
|
|
11
|
+
"type": "module",
|
|
16
12
|
"bin": {
|
|
17
|
-
"create-vite-hyperapp": "
|
|
13
|
+
"create-vite-hyperapp": "./create-vite-hyperapp.mjs"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"create-vite-hyperapp.mjs",
|
|
17
|
+
"templates"
|
|
18
|
+
],
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=22.18.0"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@inquirer/prompts": "^8.7.3",
|
|
24
|
+
"colorette": "^2.0.20"
|
|
18
25
|
}
|
|
19
26
|
}
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
|
-
<link rel="icon" type="image/svg+xml" href="/
|
|
5
|
+
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
-
<title>
|
|
7
|
+
<title>__PROJECTNAME__</title>
|
|
8
8
|
</head>
|
|
9
9
|
<body>
|
|
10
|
-
<
|
|
10
|
+
<main id="app"></main>
|
|
11
11
|
<script type="module" src="/src/run.js"></script>
|
|
12
12
|
</body>
|
|
13
13
|
</html>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "__PROJECTNAME__",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite",
|
|
8
|
+
"build": "vite build",
|
|
9
|
+
"preview": "vite preview"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@hyperapp/html": "^2.0.0",
|
|
13
|
+
"@hyperapp/svg": "^2.0.0",
|
|
14
|
+
"hyperapp": "^2.0.22"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"vite": "^8.3.4",
|
|
18
|
+
"vite-plugin-hyperapp": "^2.0.1"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { a, img } from "@hyperapp/html"
|
|
2
|
+
import viteLogo from "@/assets/vite.svg"
|
|
3
|
+
import hyperappLogo from "@/assets/hyperapp.svg"
|
|
4
|
+
|
|
5
|
+
const Logos = () => [
|
|
6
|
+
a(
|
|
7
|
+
{ href: "https://vitejs.dev" },
|
|
8
|
+
img({
|
|
9
|
+
src: viteLogo,
|
|
10
|
+
class: "logo",
|
|
11
|
+
alt: "Vite logo",
|
|
12
|
+
}),
|
|
13
|
+
),
|
|
14
|
+
a(
|
|
15
|
+
{ href: "https://github.com/jorgebucaran/hyperapp" },
|
|
16
|
+
img({
|
|
17
|
+
src: hyperappLogo,
|
|
18
|
+
class: "logo",
|
|
19
|
+
alt: "Hyperapp logo",
|
|
20
|
+
}),
|
|
21
|
+
),
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
export default Logos
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import "./style.css"
|
|
2
|
+
import { main, h1, p, text } from "@hyperapp/html"
|
|
3
|
+
import Counter from "./counter"
|
|
4
|
+
import Logos from "./logos"
|
|
5
|
+
|
|
6
|
+
export const init = () => ({
|
|
7
|
+
counter: 0,
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
const HandleClick = state => ({
|
|
11
|
+
...state,
|
|
12
|
+
counter: state.counter + 1,
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
export const view = state =>
|
|
16
|
+
main({ id: "app" }, [
|
|
17
|
+
h1(text("Vite + Hyperapp")),
|
|
18
|
+
...Logos(),
|
|
19
|
+
Counter({ clicks: state.counter, onclick: HandleClick }),
|
|
20
|
+
p(
|
|
21
|
+
{ class: "read-the-docs" },
|
|
22
|
+
text("Click on the Vite & Hyperapp logos to learn more"),
|
|
23
|
+
),
|
|
24
|
+
])
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { app } from "hyperapp"
|
|
2
|
-
import { init, view } from "./main"
|
|
2
|
+
import { init, view } from "./app/main"
|
|
3
3
|
const node = document.querySelector("#app")
|
|
4
4
|
if (!node) throw new Error("mountpoint not found")
|
|
5
|
-
|
|
5
|
+
app({ init, view, node })
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { defineConfig } from "vite"
|
|
2
|
+
import hyperapp from "vite-plugin-hyperapp"
|
|
3
|
+
import { fileURLToPath } from "node:url"
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
plugins: [hyperapp()],
|
|
7
|
+
resolve: {
|
|
8
|
+
alias: {
|
|
9
|
+
"@": fileURLToPath(new URL("./src", import.meta.url)),
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
})
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
|
-
<link rel="icon" type="image/svg+xml" href="/
|
|
5
|
+
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
-
<title>
|
|
7
|
+
<title>__PROJECTNAME__</title>
|
|
8
8
|
</head>
|
|
9
9
|
<body>
|
|
10
10
|
<!--ssr-outlet-->
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "__PROJECTNAME__",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "node server.js",
|
|
8
|
+
"build:client": "vite build --outDir dist/client",
|
|
9
|
+
"build:server": "vite build --outDir dist/server --ssr src/entry-server.js",
|
|
10
|
+
"build": "npm run build:client && npm run build:server",
|
|
11
|
+
"preview": "NODE_ENV=production node server.js"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"vite": "^8.3.4"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@hyperapp/html": "^2.0.0",
|
|
18
|
+
"@hyperapp/svg": "^2.0.0",
|
|
19
|
+
"compression": "^1.7.4",
|
|
20
|
+
"express": "^4.19.2",
|
|
21
|
+
"hyperapp": "^2.0.22",
|
|
22
|
+
"sirv": "^2.0.4",
|
|
23
|
+
"vite-plugin-hyperapp": "^2.0.1"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -19,7 +19,6 @@ async function createServer() {
|
|
|
19
19
|
vite = await createServer({
|
|
20
20
|
server: { middlewareMode: true },
|
|
21
21
|
appType: "custom",
|
|
22
|
-
base,
|
|
23
22
|
})
|
|
24
23
|
app.use(vite.middlewares)
|
|
25
24
|
} else {
|
|
@@ -29,26 +28,29 @@ async function createServer() {
|
|
|
29
28
|
app.use(base, sirv("./dist/client", { extensions: [] }))
|
|
30
29
|
}
|
|
31
30
|
|
|
32
|
-
app.use("*", async (req, res) => {
|
|
33
|
-
const url = req.originalUrl
|
|
31
|
+
app.use("*", async (req, res, next) => {
|
|
32
|
+
const url = req.originalUrl
|
|
33
|
+
if (!url.startsWith(base)) return next()
|
|
34
34
|
try {
|
|
35
35
|
let template
|
|
36
36
|
let render
|
|
37
37
|
if (!isProduction) {
|
|
38
|
+
if (!vite) throw new Error("Vite dev server is not initialized")
|
|
38
39
|
// Always read fresh template in development
|
|
39
40
|
template = await fs.readFile("./index.html", "utf-8")
|
|
40
41
|
template = await vite.transformIndexHtml(url, template)
|
|
41
42
|
render = (await vite.ssrLoadModule("/src/entry-server.js")).render
|
|
42
43
|
} else {
|
|
43
44
|
template = await fs.readFile("./dist/client/index.html", "utf-8")
|
|
44
|
-
|
|
45
|
+
const serverEntry = "./dist/server/entry-server.js"
|
|
46
|
+
render = (await import(serverEntry)).render
|
|
45
47
|
}
|
|
46
|
-
const html = template.replace(`<!--ssr-outlet-->`,
|
|
48
|
+
const html = template.replace(`<!--ssr-outlet-->`, () => render())
|
|
47
49
|
res.status(200).set({ "Content-Type": "text/html" }).end(html)
|
|
48
50
|
} catch (e) {
|
|
49
|
-
vite?.ssrFixStacktrace(e)
|
|
50
|
-
console.
|
|
51
|
-
res.status(500).end(
|
|
51
|
+
if (e instanceof Error) vite?.ssrFixStacktrace(e)
|
|
52
|
+
console.error(e)
|
|
53
|
+
res.status(500).end()
|
|
52
54
|
}
|
|
53
55
|
})
|
|
54
56
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { a, img } from "@hyperapp/html"
|
|
2
|
+
import viteLogo from "@/assets/vite.svg"
|
|
3
|
+
import hyperappLogo from "@/assets/hyperapp.svg"
|
|
4
|
+
|
|
5
|
+
const Logos = () => [
|
|
6
|
+
a(
|
|
7
|
+
{ href: "https://vitejs.dev" },
|
|
8
|
+
img({
|
|
9
|
+
src: viteLogo,
|
|
10
|
+
class: "logo",
|
|
11
|
+
alt: "Vite logo",
|
|
12
|
+
}),
|
|
13
|
+
),
|
|
14
|
+
a(
|
|
15
|
+
{ href: "https://github.com/jorgebucaran/hyperapp" },
|
|
16
|
+
img({
|
|
17
|
+
src: hyperappLogo,
|
|
18
|
+
class: "logo",
|
|
19
|
+
alt: "Hyperapp logo",
|
|
20
|
+
}),
|
|
21
|
+
),
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
export default Logos
|