create-evikit 2.4.0 → 2.5.1

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.
@@ -0,0 +1,18 @@
1
+ when:
2
+ - event: push
3
+ branch: main
4
+ - event: pull_request
5
+
6
+ steps:
7
+ - name: build
8
+ image: node:24-alpine
9
+ commands:
10
+ - apk add git
11
+ # Are types correct?
12
+ - npm i
13
+ - npm run lint
14
+ - npm run build
15
+ # Does todo app example build?
16
+ - npm link
17
+ - npx create-evikit my-app
18
+ - (cd my-app; npm run build)
package/README.md ADDED
@@ -0,0 +1,36 @@
1
+ # create-evikit
2
+
3
+ Create a monolith server-rendered Preact app with an API powered by a node:sqlite database, using [EviKit](https://evikit.js.org/):
4
+
5
+ ```sh
6
+ npm init evikit my-app
7
+ cd my-app
8
+ npm run dev
9
+ ```
10
+
11
+ Open http://localhost:5173/, try editing the example routes and see changes live.
12
+
13
+ You can continue with the [EviKit tutorial](https://codeberg.org/nykula/evikit#documentation). With this initializer, you don't have to manually install dependencies, add scripts to `package.json`, or create typical files such as `index.html` and `vite.config.js`.
14
+
15
+ > 😉 If you are new to Preact and the concept of Virtual DOM, it is a good idea to complete the [Preact tutorial](https://preactjs.com/tutorial/) first.
16
+
17
+ ## Read more
18
+
19
+ Think of EviKit as an [LXDE](https://en.wikipedia.org/wiki/LXDE#Software_components_of_LXDE) of web frameworks, it stands on the shoulders of awesome libraries and tools from the Preact and Node.js ecosystems:
20
+
21
+ - **[valibot](https://valibot.dev/guides/introduction/)** - Lets you declare detabase schema and validate API input/output.
22
+ - **[hoofd/preact](https://github.com/0no-co/hoofd)** - Populates `<title>` and `<meta>` tags.
23
+ - **[gettext.js](https://github.com/smhg/gettext-parser)** - Lets you pluralize translated strings.
24
+ - **[vite](https://vite.dev/guide/)** - Builds your app for development and production.
25
+ - **[express](https://expressjs.com/)** - Lets you apply compression, serve static files and use other familiar middleware.
26
+ - [@fastify/busboy](https://github.com/fastify/busboy) - Parses forms, including uploaded files.
27
+ - [@preact/preset-vite](https://github.com/preactjs/preset-vite) - In development, shows your code changes without reloading the page.
28
+ - [env-paths](https://github.com/fastify/busboy) - Saves your database in standard system-specific directory.
29
+ - [gettext-parser](https://github.com/smhg/gettext-parser) - Parses translation files.
30
+ - [preact-iso](https://github.com/preactjs/preact-iso) - Handles routing and hydrates the server-rendered code on the client.
31
+
32
+ ## License
33
+
34
+ SPDX-License-Identifier: 0BSD
35
+
36
+ Note: this license applies to this example application template. EviKit itself uses the MIT license.
@@ -25,7 +25,7 @@ for (const file of [...template, "eslint.config.js", "tsconfig.json"]) {
25
25
  path,
26
26
  readFileSync(join(ownRoot, file), "utf8")
27
27
  .replace(
28
- /<link\s+href="[^"]+"(\s+media="[^"]+")?\s+rel="[a-z]+"\s+\/>\s+/g,
28
+ /<link\s+href="[^"]+"\s+media="[^"]+"\s+rel="[a-z]+"\s+\/>\s+/g,
29
29
  "",
30
30
  )
31
31
  .replace(', "uk"', ""),
@@ -120,8 +120,8 @@ writeFileSync(
120
120
  writeFileSync(
121
121
  join(target, ".env"),
122
122
  `
123
- ORIGIN=http://localhost:8000
124
- PORT=8000
123
+ ORIGIN=http://localhost:5173
124
+ PORT=5173
125
125
  `.trimStart(),
126
126
  );
127
127
 
@@ -146,6 +146,7 @@ const pkg = {
146
146
  dependencies: {
147
147
  "accept-language": dependencies["accept-language"],
148
148
  classnames: dependencies.classnames,
149
+ "cross-env": dependencies["cross-env"],
149
150
  evikit: dependencies.evikit,
150
151
  express: dependencies.express,
151
152
  "file-type": dependencies["file-type"],
@@ -163,7 +164,6 @@ const pkg = {
163
164
  "@types/express": devDependencies["@types/express"],
164
165
  "@types/node": devDependencies["@types/node"],
165
166
  "@types/swagger-ui-express": devDependencies["@types/swagger-ui-express"],
166
- "cross-env": devDependencies["cross-env"],
167
167
  daisyui: devDependencies.daisyui,
168
168
  eslint: devDependencies.eslint,
169
169
  "eslint-config-prettier": devDependencies["eslint-config-prettier"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-evikit",
3
- "version": "2.4.0",
3
+ "version": "2.5.1",
4
4
  "type": "module",
5
5
  "bin": "bin/create-evikit.js",
6
6
  "scripts": {
@@ -21,7 +21,6 @@
21
21
  "@types/express": "^5.0.6",
22
22
  "@types/node": "^26.1.0",
23
23
  "@types/swagger-ui-express": "^4.1.8",
24
- "cross-env": "^10.1.0",
25
24
  "daisyui": "^5.6.14",
26
25
  "eslint": "^10.6.0",
27
26
  "eslint-config-prettier": "^10.1.8",
@@ -37,7 +36,8 @@
37
36
  "@speed-highlight/core": "^1.2.17",
38
37
  "accept-language": "^3.0.20",
39
38
  "classnames": "^2.5.1",
40
- "evikit": "^2.4.0",
39
+ "cross-env": "^10.1.0",
40
+ "evikit": "^2.5.0",
41
41
  "express": "^5.2.1",
42
42
  "file-type": "^22.0.1",
43
43
  "hoofd": "^1.7.3",
@@ -1,3 +1,4 @@
1
+ import { daemon } from "evikit/server";
1
2
  import { sqlite } from "evikit/sqlite";
2
3
 
3
4
  import pkg from "../../../package.json" with { type: "json" };
@@ -5,15 +6,13 @@ import * as schema from "./schema.js";
5
6
 
6
7
  export const db = sqlite({ pkg, schema });
7
8
 
8
- if (
9
- process.env["npm_command"] == "start" ||
10
- process.env["npm_lifecycle_event"] == "dev"
11
- ) {
12
- setInterval(() => {
9
+ daemon(() => {
10
+ const interval = setInterval(() => {
13
11
  db.Todo.delete({
14
12
  text: db.Todo.select()
15
13
  .filter(({ createdAt }) => createdAt < Date.now() - 10 * 60e3)
16
14
  .map(({ text }) => text),
17
15
  });
18
16
  }, 1000);
19
- }
17
+ return () => clearInterval(interval);
18
+ });
@@ -168,11 +168,22 @@ npm run dev
168
168
 
169
169
  h(
170
170
  Code,
171
- { file: data?.File["src/routes/todo/page.js"], lang: "js" },
171
+ {
172
+ class: "row-span-2",
173
+ file: data?.File["src/routes/todo/page.js"],
174
+ lang: "js",
175
+ },
172
176
  span(null, "src/routes/"),
173
177
  b(null, "todo/page.js"),
174
178
  ),
175
179
 
180
+ h(
181
+ Code,
182
+ { file: data?.File["src/lib/db/index.js"], lang: "js" },
183
+ span(null, "src/lib/"),
184
+ b(null, "db/index.js"),
185
+ ),
186
+
176
187
  h(
177
188
  Code,
178
189
  { file: data?.File["src/routes/error.js"], lang: "js" },
@@ -227,13 +238,6 @@ npm run dev
227
238
  b(null, "vite.config.js"),
228
239
  ),
229
240
 
230
- h(
231
- Code,
232
- { file: data?.File["src/lib/db/index.js"], lang: "js", tag: "details" },
233
- span(null, "src/lib/"),
234
- b(null, "db/index.js"),
235
- ),
236
-
237
241
  h(
238
242
  Code,
239
243
  { file: data?.File["index.html"], lang: "html", tag: "details" },
@@ -299,8 +303,8 @@ npm run dev
299
303
  );
300
304
  }
301
305
 
302
- /** @param {{ children?: any, lang: string, file: string | undefined, note?: string, tag?: string }} props */
303
- function Code({ children, file, lang, note, tag }) {
306
+ /** @param {{ children?: any, class?: string, lang: string, file: string | undefined, note?: string, tag?: string }} props */
307
+ function Code({ children, class: className, file, lang, note, tag }) {
304
308
  const inner = pre(
305
309
  { class: "mt-4 overflow-auto text-sm" },
306
310
  code(
@@ -319,7 +323,7 @@ function Code({ children, file, lang, note, tag }) {
319
323
  ),
320
324
  );
321
325
  const more = note ? p({ class: "mt-5", ...sanitize(note) }) : undefined;
322
- const style = `${darkBg} mb-4 mx-0 overflow-hidden p-4 rounded-xl`;
326
+ const style = `${className} ${darkBg} mb-4 mx-0 overflow-hidden p-4 rounded-xl`;
323
327
  return tag == "details"
324
328
  ? details({ class: style }, summary(null, children), inner, more)
325
329
  : figure({ class: style }, figcaption(null, children), inner, more);