kreftjs 0.0.7-beta → 0.0.9-beta
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 +5 -31
- package/bin/artisan-more.js +2 -0
- package/bin/artisan.js +51 -49
- package/bin/backend/config.js +2 -2
- package/bin/backend/http.js +5 -5
- package/bin/backend/index.js +2 -2
- package/bin/backend/mcp.js +3 -5
- package/bin/backend/migrator.js +1 -3
- package/bin/backend/query.js +1 -1
- package/bin/backend/queue.js +8 -9
- package/bin/backend/redis.js +1 -1
- package/bin/backend/typescript.js +1 -1
- package/bin/build.js +22 -18
- package/bin/db-api.js +2 -2
- package/bin/db.js +4 -4
- package/bin/deps.js +1 -1
- package/bin/electron.js +3 -5
- package/bin/kreftjs-config.js +1 -6
- package/bin/kreftjs.js +34 -35
- package/bin/layout.js +1 -1
- package/bin/no-auth.js +18 -18
- package/bin/prerender.js +1 -1
- package/bin/ssr.js +3 -3
- package/bin/update.js +10 -10
- package/docs/{Docs.kreftjs → Docs.kreft} +1 -1
- package/docs/README.md +89 -102
- package/editors/vscode/README.md +3 -3
- package/editors/vscode/package.json +3 -4
- package/editors/vscode/snippets/kreftjs.json +2 -2
- package/kreftjs.d.ts +15 -27
- package/kreftjs.js +69 -79
- package/package.json +4 -4
- package/templates/app/README.md +10 -10
- package/templates/app/_env.example +2 -2
- package/templates/app/_vscode/settings.json +3 -2
- package/templates/app/backend/app/Http/Controllers/Admin/DashboardController.js +2 -2
- package/templates/app/backend/app/Http/Controllers/Admin/UserController.js +1 -1
- package/templates/app/backend/app/Http/Controllers/Auth/ApiTokenController.js +1 -1
- package/templates/app/backend/app/Http/Controllers/Auth/AuthenticatedSessionController.js +1 -1
- package/templates/app/backend/app/Http/Controllers/Auth/ConfirmablePasswordController.js +1 -1
- package/templates/app/backend/app/Http/Controllers/Auth/EmailVerificationController.js +1 -1
- package/templates/app/backend/app/Http/Controllers/Auth/NewPasswordController.js +1 -1
- package/templates/app/backend/app/Http/Controllers/Auth/PasswordResetLinkController.js +1 -1
- package/templates/app/backend/app/Http/Controllers/Auth/RegisteredUserController.js +1 -1
- package/templates/app/backend/app/Http/Controllers/Auth/SessionController.js +1 -1
- package/templates/app/backend/app/Http/Controllers/Auth/TwoFactorController.js +1 -1
- package/templates/app/backend/app/Http/Controllers/ProfileController.js +1 -1
- package/templates/app/backend/app/Http/Middleware/RequirePassword.js +1 -1
- package/templates/app/frontend/{App.kreftjs → App.kreft} +1 -1
- package/templates/app/frontend/components/profile/{ApiTokens.kreftjs → ApiTokens.kreft} +1 -1
- package/templates/app/frontend/components/profile/{Sessions.kreftjs → Sessions.kreft} +1 -1
- package/templates/app/frontend/components/profile/{TwoFactor.kreftjs → TwoFactor.kreft} +1 -1
- package/templates/app/frontend/errors/{ErrorMonitor.kreftjs → ErrorMonitor.kreft} +3 -3
- package/templates/app/frontend/index.html +8 -8
- package/templates/app/frontend/kreftjs.d.ts +15 -27
- package/templates/app/frontend/kreftjs.js +69 -79
- package/templates/app/frontend/layouts/{docs.kreftjs → docs.kreft} +1 -1
- package/templates/app/frontend/pages/{Dashboard.kreftjs → Dashboard.kreft} +1 -1
- package/templates/app/frontend/pages/{ErrorMonitor.kreftjs → ErrorMonitor.kreft} +2 -2
- package/templates/app/frontend/pages/{Home.kreftjs → Home.kreft} +2 -2
- package/templates/app/frontend/pages/{Profile.kreftjs → Profile.kreft} +3 -3
- package/templates/app/frontend/routes/web.kreft +34 -0
- package/templates/app/frontend/tests/components/{Counter.kreftjs → Counter.kreft} +1 -1
- package/templates/app/frontend/tests/pages/About.kreft +12 -0
- package/templates/app/frontend/tests/pages/{Test.kreftjs → Test.kreft} +1 -1
- package/templates/errors/{401.kreftjs → 401.kreft} +2 -2
- package/templates/errors/{402.kreftjs → 402.kreft} +2 -2
- package/templates/errors/{403.kreftjs → 403.kreft} +2 -2
- package/templates/errors/{404.kreftjs → 404.kreft} +2 -2
- package/templates/errors/{419.kreftjs → 419.kreft} +2 -2
- package/templates/errors/{429.kreftjs → 429.kreft} +2 -2
- package/templates/errors/{500.kreftjs → 500.kreft} +2 -2
- package/templates/errors/{503.kreftjs → 503.kreft} +2 -2
- package/templates/errors/{ErrorMonitor.kreftjs → ErrorMonitor.kreft} +13 -12
- package/templates/errors/{error.kreftjs → error.kreft} +2 -2
- package/templates/errors/{minimal.kreftjs → minimal.kreft} +1 -1
- package/tools/dev-client.js +2 -2
- package/tools/vite-plugin-kreftjs.d.ts +3 -5
- package/tools/vite-plugin-kreftjs.js +12 -14
- package/templates/app/frontend/routes/web.kreftjs +0 -34
- package/templates/app/frontend/tests/pages/About.kreftjs +0 -12
- /package/templates/app/frontend/components/{Field.kreftjs → Field.kreft} +0 -0
- /package/templates/app/frontend/components/{StatCard.kreftjs → StatCard.kreft} +0 -0
- /package/templates/app/frontend/layouts/{app.kreftjs → app.kreft} +0 -0
- /package/templates/app/frontend/layouts/{guest.kreftjs → guest.kreft} +0 -0
- /package/templates/app/frontend/pages/{Users.kreftjs → Users.kreft} +0 -0
- /package/templates/app/frontend/pages/auth/{ConfirmPassword.kreftjs → ConfirmPassword.kreft} +0 -0
- /package/templates/app/frontend/pages/auth/{ForgotPassword.kreftjs → ForgotPassword.kreft} +0 -0
- /package/templates/app/frontend/pages/auth/{Login.kreftjs → Login.kreft} +0 -0
- /package/templates/app/frontend/pages/auth/{Register.kreftjs → Register.kreft} +0 -0
- /package/templates/app/frontend/pages/auth/{ResetPassword.kreftjs → ResetPassword.kreft} +0 -0
- /package/templates/app/frontend/pages/auth/{VerifyEmail.kreftjs → VerifyEmail.kreft} +0 -0
package/bin/update.js
CHANGED
|
@@ -31,7 +31,7 @@ module.exports = function update(args = []) {
|
|
|
31
31
|
const a = args[i];
|
|
32
32
|
if (a === '--latest' || a === '-L') flags.add('latest');
|
|
33
33
|
else if (a === '--check' || a === '--dry-run') flags.add('check');
|
|
34
|
-
else if (a === '--core' || a === '--kreft'
|
|
34
|
+
else if (a === '--core' || a === '--kreft') flags.add('core');
|
|
35
35
|
else if (a === '--npm') flags.add('npm');
|
|
36
36
|
else if (a === '--help' || a === '-h') {
|
|
37
37
|
printHelp();
|
|
@@ -74,16 +74,16 @@ function updateRuntimeFiles(lay, project) {
|
|
|
74
74
|
const targets = [];
|
|
75
75
|
|
|
76
76
|
// Check frontend / local kreftjs.js
|
|
77
|
-
// an older project has kreft.js
|
|
77
|
+
// an older project has kreft.js (and the .d.ts): those files keep their names (index.html loads them) but get the new code
|
|
78
78
|
const named = (dir, name, ...legacy) => (!fs.existsSync(path.join(dir, name)) ? legacy.find((l) => fs.existsSync(path.join(dir, l))) || name : name);
|
|
79
|
-
const frontKreftJs = path.join(lay.frontend, named(lay.frontend, 'kreftjs.js', 'kreft.js'
|
|
80
|
-
const rootKreftJs = path.join(project, named(project, 'kreftjs.js', 'kreft.js'
|
|
79
|
+
const frontKreftJs = path.join(lay.frontend, named(lay.frontend, 'kreftjs.js', 'kreft.js'));
|
|
80
|
+
const rootKreftJs = path.join(project, named(project, 'kreftjs.js', 'kreft.js'));
|
|
81
81
|
if (fs.existsSync(frontKreftJs) && frontKreftJs !== sourceKreftJs) targets.push({ src: sourceKreftJs, dest: frontKreftJs, label: 'frontend/' + path.basename(frontKreftJs) });
|
|
82
82
|
else if (fs.existsSync(rootKreftJs) && rootKreftJs !== sourceKreftJs) targets.push({ src: sourceKreftJs, dest: rootKreftJs, label: path.basename(rootKreftJs) });
|
|
83
83
|
|
|
84
84
|
// Check frontend / local kreftjs.d.ts
|
|
85
|
-
const frontKreftDts = path.join(lay.frontend, named(lay.frontend, 'kreftjs.d.ts', 'kreft.d.ts'
|
|
86
|
-
const rootKreftDts = path.join(project, named(project, 'kreftjs.d.ts', 'kreft.d.ts'
|
|
85
|
+
const frontKreftDts = path.join(lay.frontend, named(lay.frontend, 'kreftjs.d.ts', 'kreft.d.ts'));
|
|
86
|
+
const rootKreftDts = path.join(project, named(project, 'kreftjs.d.ts', 'kreft.d.ts'));
|
|
87
87
|
if (fs.existsSync(frontKreftDts) && frontKreftDts !== sourceKreftDts) targets.push({ src: sourceKreftDts, dest: frontKreftDts, label: 'frontend/' + path.basename(frontKreftDts) });
|
|
88
88
|
else if (fs.existsSync(rootKreftDts) && rootKreftDts !== sourceKreftDts) targets.push({ src: sourceKreftDts, dest: rootKreftDts, label: path.basename(rootKreftDts) });
|
|
89
89
|
|
|
@@ -134,8 +134,8 @@ function updateRuntimeFiles(lay, project) {
|
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
function upgradeAppLayout(lay) {
|
|
137
|
-
let layoutFile = path.join(lay.frontend, 'layouts', 'app.
|
|
138
|
-
if (!fs.existsSync(layoutFile)) layoutFile = ['app.
|
|
137
|
+
let layoutFile = path.join(lay.frontend, 'layouts', 'app.kreft');
|
|
138
|
+
if (!fs.existsSync(layoutFile)) layoutFile = ['app.kreftjs'].map((n) => path.join(lay.frontend, 'layouts', n)).find((p) => fs.existsSync(p)) || layoutFile; // older projects
|
|
139
139
|
if (!fs.existsSync(layoutFile)) return;
|
|
140
140
|
let text = fs.readFileSync(layoutFile, 'utf8');
|
|
141
141
|
let changed = false;
|
|
@@ -162,9 +162,9 @@ function upgradeAppLayout(lay) {
|
|
|
162
162
|
if (changed) {
|
|
163
163
|
try {
|
|
164
164
|
fs.writeFileSync(layoutFile, text);
|
|
165
|
-
console.log(` ${green('DONE')} frontend/layouts/app.
|
|
165
|
+
console.log(` ${green('DONE')} frontend/layouts/app.kreft ${dim('(upgraded sidebar navigation to route names)')}`);
|
|
166
166
|
} catch (err) {
|
|
167
|
-
console.error(` ${red('FAIL')} frontend/layouts/app.
|
|
167
|
+
console.error(` ${red('FAIL')} frontend/layouts/app.kreft: ${err.message}`);
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
170
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- Kreft documentation viewer (docs/Docs.
|
|
1
|
+
<!-- Kreft documentation viewer (docs/Docs.kreft)
|
|
2
2
|
Reads docs/README.md, shows it as a manual: parts and chapters on the left, the page in the middle,
|
|
3
3
|
"On this page" on the right. It sits under the site header, so it uses the site's colours (ui.css),
|
|
4
4
|
including the light/dark switch. Keys: ⌘K or / search · [ and ] previous / next chapter · Esc closes. -->
|
package/docs/README.md
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
## Introduction
|
|
4
4
|
|
|
5
|
-
Kreft is a small reactive framework with its own component language. You write a component in a `.
|
|
5
|
+
Kreft is a small reactive framework with its own component language. You write a component in a `.kreft` file: declare your state, derived values and actions in plain words, then describe the page in a `<view>`. The framework also ships a full Node.js backend (routes, controllers, models, migrations, queues, mail) so one project can cover the whole stack.
|
|
6
6
|
|
|
7
7
|
```html
|
|
8
|
-
<!-- Counter.
|
|
8
|
+
<!-- Counter.kreft -->
|
|
9
9
|
state count = 0
|
|
10
10
|
derive double = count * 2
|
|
11
11
|
action add() { count++ }
|
|
@@ -19,7 +19,7 @@ action add() { count++ }
|
|
|
19
19
|
|
|
20
20
|
| Part | What it gives you |
|
|
21
21
|
|---|---|
|
|
22
|
-
| **The `.
|
|
22
|
+
| **The `.kreft` language** | `state`, `derive`, `action`, `watch`, props, events, slots, stores, a router with layouts and nested routes, forms with validation, animations. |
|
|
23
23
|
| **The backend** | `Route`, controllers, an Active Record `Model`, migrations, seeders, factories, jobs, mail, cache, file storage, policies, scheduling. |
|
|
24
24
|
| **Authentication** | Sign-in pages, password reset, email verification, two-factor codes, device sessions and API tokens, ready in every new project (leave them out with `--no-auth`). |
|
|
25
25
|
| **Tooling** | `kreft dev` with hot reload that keeps state, DevTools, an error monitor, `kreft build`, TypeScript, Vite and Electron support. |
|
|
@@ -82,7 +82,7 @@ npx kreftjs dev
|
|
|
82
82
|
### Check that it works
|
|
83
83
|
|
|
84
84
|
```bash
|
|
85
|
-
kreft --version # for example 0.0.
|
|
85
|
+
kreft --version # for example 0.0.9-beta
|
|
86
86
|
kreft about # Kreft and Node.js versions, this project's settings and drivers
|
|
87
87
|
kreft list # every command your version has
|
|
88
88
|
```
|
|
@@ -95,7 +95,7 @@ kreft list # every command your version has
|
|
|
95
95
|
kreft vscode
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
-
installs colors and snippets for `.
|
|
98
|
+
installs colors and snippets for `.kreft` files in VS Code (also Cursor and VSCodium). Restart the editor afterwards.
|
|
99
99
|
|
|
100
100
|
### Update
|
|
101
101
|
|
|
@@ -131,21 +131,6 @@ Run `npm link` inside the Kreft folder. The `kreft` command then runs that folde
|
|
|
131
131
|
|
|
132
132
|
Next: [Your first app](#your-first-app).
|
|
133
133
|
|
|
134
|
-
### Migrating from Som.js
|
|
135
|
-
|
|
136
|
-
Kreft is Som.js under a new name (the package and command are `kreftjs`), and an existing project keeps working without edits. `kreft`, an earlier spelling of the new name, is accepted in the same places:
|
|
137
|
-
|
|
138
|
-
- **Files:** `.som` (and `.kreft`) files still compile, next to `.kreftjs` ones. A name that is missing with one extension is tried with the others. Everything the tools write is `.kreftjs`.
|
|
139
|
-
- **Templates:** `s-if`, `s-each` and every other `s-` directive are read as `k-if`, `k-each` …, and `<som-view>`, `<som-link>` … as `<kreft-view>`, `<kreft-link>` …
|
|
140
|
-
- **JavaScript:** `Som` and `Kreft` are other names for `Kreftjs` (same object; `Som` is deprecated), and `Som.compileSom` is `Kreftjs.compile`.
|
|
141
|
-
- **Command:** use `kreft` (or `kreftjs`). Kreft does not install a `som` command, so it can be installed next to an old Som.js without an `EEXIST` error; remove the old one with `npm rm -g somjs`.
|
|
142
|
-
- **Server code:** `require('somjs/server')` (also `som/server`, `@somjs/server`, `kreft/server`) still works; new code uses `require('kreftjs/server')`.
|
|
143
|
-
- **Settings:** `kreft.config.json`, `som.config.json` and `SOM_` environment variables (`SOM_SSR`, `SOM_ALLOWED_HOSTS` …) are read when the `kreftjs.config.json` file or the `KREFT_` variable is missing.
|
|
144
|
-
- **Cookies:** new projects use `kreft_session`, `kreft_2fa` and `kreft_bypass`. An existing project keeps its `som_` names until you change `app/Auth/Session.js`, and the framework's CSRF check accepts both.
|
|
145
|
-
- **Kept on purpose:** the `som_migrations` table, the `som:` prefix of saved data in `localStorage`, and the `som:` Redis keys of the queue. Renaming them needs a migration, planned for 3.1.
|
|
146
|
-
|
|
147
|
-
To move a project over, rename `*.som` (or `*.kreft`) to `*.kreftjs` (and the paths that mention them), run `kreft update` and replace `s-` with `k-`.
|
|
148
|
-
|
|
149
134
|
## Your first app
|
|
150
135
|
|
|
151
136
|
Create a project, move into it and start the development server:
|
|
@@ -186,19 +171,19 @@ The new project already has a working login page. `npm run dev` creates the tabl
|
|
|
186
171
|
|
|
187
172
|
### The smallest possible app
|
|
188
173
|
|
|
189
|
-
You can use Kreft without any project at all. An app is an HTML page plus `.
|
|
174
|
+
You can use Kreft without any project at all. An app is an HTML page plus `.kreft` files:
|
|
190
175
|
|
|
191
176
|
```html
|
|
192
177
|
<!-- index.html -->
|
|
193
178
|
<div id="app"></div>
|
|
194
179
|
<script src="kreftjs.js"></script>
|
|
195
180
|
<script>
|
|
196
|
-
Kreftjs.app('App.
|
|
181
|
+
Kreftjs.app('App.kreft').mount('#app')
|
|
197
182
|
</script>
|
|
198
183
|
```
|
|
199
184
|
|
|
200
185
|
```html
|
|
201
|
-
<!-- App.
|
|
186
|
+
<!-- App.kreft -->
|
|
202
187
|
state name = 'World'
|
|
203
188
|
|
|
204
189
|
<view>
|
|
@@ -208,7 +193,7 @@ state name = 'World'
|
|
|
208
193
|
```
|
|
209
194
|
|
|
210
195
|
> [!WARNING]
|
|
211
|
-
> `.
|
|
196
|
+
> `.kreft` files need a web server. Browsers refuse to load files from `file://`, so always open your app through `npm run dev` or any other server.
|
|
212
197
|
|
|
213
198
|
## Project structure
|
|
214
199
|
|
|
@@ -218,10 +203,10 @@ state name = 'World'
|
|
|
218
203
|
my-app/
|
|
219
204
|
├── frontend/
|
|
220
205
|
│ ├── index.html entry point
|
|
221
|
-
│ ├── App.
|
|
222
|
-
│ ├── routes/web.
|
|
223
|
-
│ ├── layouts/ app.
|
|
224
|
-
│ ├── pages/ one .
|
|
206
|
+
│ ├── App.kreft root component and router container
|
|
207
|
+
│ ├── routes/web.kreft page routes
|
|
208
|
+
│ ├── layouts/ app.kreft (signed in), guest.kreft (sign-in pages)
|
|
209
|
+
│ ├── pages/ one .kreft file per screen, auth/ for sign-in pages
|
|
225
210
|
│ ├── components/ reusable pieces
|
|
226
211
|
│ ├── ui.css the design system
|
|
227
212
|
│ └── tests/ component tests
|
|
@@ -246,16 +231,16 @@ my-app/
|
|
|
246
231
|
|
|
247
232
|
### Adding a CSS library
|
|
248
233
|
|
|
249
|
-
Any CSS library works. Add its `<link>` to `index.html`, or install it and import the file from a `.
|
|
234
|
+
Any CSS library works. Add its `<link>` to `index.html`, or install it and import the file from a `.kreft` file; it becomes a `<link>` added once, and `kreft build` copies it (with its fonts and images) into `dist/vendor/`.
|
|
250
235
|
|
|
251
236
|
```html
|
|
252
237
|
import 'bootstrap/dist/css/bootstrap.min.css' // npm i bootstrap
|
|
253
|
-
import './theme.css' // your own file, next to this .
|
|
238
|
+
import './theme.css' // your own file, next to this .kreft file
|
|
254
239
|
```
|
|
255
240
|
|
|
256
241
|
### npm packages in the browser
|
|
257
242
|
|
|
258
|
-
Install a package with `kreft add`, then import it in any `.
|
|
243
|
+
Install a package with `kreft add`, then import it in any `.kreft` file:
|
|
259
244
|
|
|
260
245
|
```bash
|
|
261
246
|
kreft add dayjs nanoid lodash
|
|
@@ -277,9 +262,9 @@ state id = nanoid()
|
|
|
277
262
|
|
|
278
263
|
# The Kreft language
|
|
279
264
|
|
|
280
|
-
## Components and the .
|
|
265
|
+
## Components and the .kreft file
|
|
281
266
|
|
|
282
|
-
A `.
|
|
267
|
+
A `.kreft` file has three parts:
|
|
283
268
|
|
|
284
269
|
1. **The script**: everything outside `<view>` and `<style>`. Each line starts with a keyword.
|
|
285
270
|
2. **`<view>`**: the HTML of the component.
|
|
@@ -299,7 +284,7 @@ A `.kreftjs` file has three parts:
|
|
|
299
284
|
| `event` | `event save, remove` | Events this component sends to its parent with `send('save', data)`. |
|
|
300
285
|
| `use` | `use cart` | Use a shared store. `use mouse = trackMouse()` uses shared logic from a `.js` file. |
|
|
301
286
|
| `share` / `receive` | `share theme = 'dark'` | Give a value to everything inside this component / take a value a parent shared. |
|
|
302
|
-
| `import` | `import Card from './Card.
|
|
287
|
+
| `import` | `import Card from './Card.kreft'` | Use another component or a JavaScript module. |
|
|
303
288
|
| `saved` | `saved todos = []` | Like `state`, but kept in the browser (localStorage). |
|
|
304
289
|
| `load` | `load users = api.get('/api/users')` | Loads data and gives `users.data`, `users.loading`, `users.error`, `users.reload()`. |
|
|
305
290
|
|
|
@@ -308,7 +293,7 @@ Inside the script you use names **directly**: write `count++`, not `this.count++
|
|
|
308
293
|
### A complete example
|
|
309
294
|
|
|
310
295
|
```html
|
|
311
|
-
<!-- TodoPage.
|
|
296
|
+
<!-- TodoPage.kreft -->
|
|
312
297
|
state todos = []
|
|
313
298
|
state text = ''
|
|
314
299
|
|
|
@@ -344,7 +329,7 @@ when todos.length && remaining === 0 {
|
|
|
344
329
|
- An `action` that uses `await` becomes async automatically.
|
|
345
330
|
- A line that does not start with a keyword is normal JavaScript (`let timer`, `const max = 10`). Your actions can use it, but the view cannot. Use `state`, `derive` or `action` for anything the view needs.
|
|
346
331
|
- Every Kreft function is available in the script: `bus`, `store`, `signal`, `watch`, `tick`, `send`, `props`, `$route`, `$router`.
|
|
347
|
-
- Errors name the file and line, for example `"state" needs a name, like: state count = 0 (Bad.
|
|
332
|
+
- Errors name the file and line, for example `"state" needs a name, like: state count = 0 (Bad.kreft, line 3)`.
|
|
348
333
|
|
|
349
334
|
### Lifecycle
|
|
350
335
|
|
|
@@ -497,13 +482,13 @@ app.directive('focus', {
|
|
|
497
482
|
Register it once by its path, or import it where you need it:
|
|
498
483
|
|
|
499
484
|
```js
|
|
500
|
-
Kreftjs.app('App.
|
|
501
|
-
.component('UserCard', 'components/UserCard.
|
|
485
|
+
Kreftjs.app('App.kreft')
|
|
486
|
+
.component('UserCard', 'components/UserCard.kreft')
|
|
502
487
|
.mount('#app')
|
|
503
488
|
```
|
|
504
489
|
|
|
505
490
|
```html
|
|
506
|
-
import UserCard from './UserCard.
|
|
491
|
+
import UserCard from './UserCard.kreft'
|
|
507
492
|
|
|
508
493
|
<view>
|
|
509
494
|
<user-card name="Alice Smith" age={30}></user-card>
|
|
@@ -515,7 +500,7 @@ In the view, write component names in **kebab-case** (`<user-card>`).
|
|
|
515
500
|
### Props: parent to child
|
|
516
501
|
|
|
517
502
|
```html
|
|
518
|
-
<!-- UserCard.
|
|
503
|
+
<!-- UserCard.kreft -->
|
|
519
504
|
prop name
|
|
520
505
|
prop age = 0
|
|
521
506
|
prop admin = false
|
|
@@ -534,7 +519,7 @@ The default's type decides how plain text attributes are read: `age="30"` become
|
|
|
534
519
|
### Events: child to parent
|
|
535
520
|
|
|
536
521
|
```html
|
|
537
|
-
<!-- TodoItem.
|
|
522
|
+
<!-- TodoItem.kreft -->
|
|
538
523
|
prop todo
|
|
539
524
|
event remove
|
|
540
525
|
|
|
@@ -555,7 +540,7 @@ action removeTodo(id) { todos = todos.filter((t) => t.id !== id) }
|
|
|
555
540
|
### `k-model` on a component
|
|
556
541
|
|
|
557
542
|
```html
|
|
558
|
-
<!-- Toggle.
|
|
543
|
+
<!-- Toggle.kreft -->
|
|
559
544
|
prop modelValue = false
|
|
560
545
|
event update:modelValue
|
|
561
546
|
|
|
@@ -573,7 +558,7 @@ Named models: `k-model:title="pageTitle"` uses `prop title` and the event `updat
|
|
|
573
558
|
### Slots
|
|
574
559
|
|
|
575
560
|
```html
|
|
576
|
-
<!-- Card.
|
|
561
|
+
<!-- Card.kreft -->
|
|
577
562
|
prop items = []
|
|
578
563
|
|
|
579
564
|
<view>
|
|
@@ -648,7 +633,7 @@ Kreftjs.store('cart', {
|
|
|
648
633
|
})
|
|
649
634
|
```
|
|
650
635
|
|
|
651
|
-
Use it in any `.
|
|
636
|
+
Use it in any `.kreft` file. Every component sees the same data:
|
|
652
637
|
|
|
653
638
|
```html
|
|
654
639
|
use cart
|
|
@@ -686,7 +671,7 @@ use mouse = trackMouse()
|
|
|
686
671
|
### Share and receive
|
|
687
672
|
|
|
688
673
|
```html
|
|
689
|
-
<!-- Layout.
|
|
674
|
+
<!-- Layout.kreft -->
|
|
690
675
|
state settings = { theme: 'dark', lang: 'so' }
|
|
691
676
|
share settings = settings
|
|
692
677
|
|
|
@@ -722,7 +707,7 @@ saved token = '' as 'auth.token' <!-- choose the storage key yourself -->
|
|
|
722
707
|
```
|
|
723
708
|
|
|
724
709
|
- Every change is saved by itself, including deep ones: `todos.push(…)`, `todo.done = true`.
|
|
725
|
-
- The default key is `<Component>.<name
|
|
710
|
+
- The default key is `<Component>.<name>`, for example `Home.todos`. Use `as '…'` to share one value between components.
|
|
726
711
|
- A change made in another tab of the same site shows up in this tab too.
|
|
727
712
|
|
|
728
713
|
A store keeps its plain values when you add `saved`:
|
|
@@ -751,20 +736,20 @@ Kreftjs.storage.clear() // removes only what Kreft save
|
|
|
751
736
|
```js
|
|
752
737
|
const router = Kreftjs.router({
|
|
753
738
|
routes: [
|
|
754
|
-
{ path: '/', component: 'pages/Home.
|
|
755
|
-
{ path: '/users/:id', name: 'user', component: 'pages/User.
|
|
756
|
-
{ path: '/posts/:slug?', component: 'pages/Posts.
|
|
739
|
+
{ path: '/', component: 'pages/Home.kreft', meta: { title: 'Home' } },
|
|
740
|
+
{ path: '/users/:id', name: 'user', component: 'pages/User.kreft', props: true },
|
|
741
|
+
{ path: '/posts/:slug?', component: 'pages/Posts.kreft' },
|
|
757
742
|
{ path: '/old', redirect: '/' },
|
|
758
|
-
{ path: '/admin', component: 'pages/Admin.
|
|
759
|
-
{ path: '*', component: 'pages/NotFound.
|
|
743
|
+
{ path: '/admin', component: 'pages/Admin.kreft', guard: () => isAdmin() || '/login' },
|
|
744
|
+
{ path: '*', component: 'pages/NotFound.kreft' },
|
|
760
745
|
],
|
|
761
746
|
})
|
|
762
747
|
|
|
763
|
-
Kreftjs.app('App.
|
|
748
|
+
Kreftjs.app('App.kreft').use(router).mount('#app')
|
|
764
749
|
```
|
|
765
750
|
|
|
766
751
|
```html
|
|
767
|
-
<!-- App.
|
|
752
|
+
<!-- App.kreft -->
|
|
768
753
|
<view>
|
|
769
754
|
<nav>
|
|
770
755
|
<kreft-link to="/">Home</kreft-link>
|
|
@@ -777,7 +762,7 @@ Kreftjs.app('App.kreftjs').use(router).mount('#app')
|
|
|
777
762
|
With `props: true`, the `:id` parameter arrives as a prop:
|
|
778
763
|
|
|
779
764
|
```html
|
|
780
|
-
<!-- pages/User.
|
|
765
|
+
<!-- pages/User.kreft -->
|
|
781
766
|
prop id
|
|
782
767
|
derive user = users.find(id)
|
|
783
768
|
action back() { $router.back() }
|
|
@@ -797,11 +782,11 @@ Each page file is loaded the first time someone opens it.
|
|
|
797
782
|
|
|
798
783
|
### Route files
|
|
799
784
|
|
|
800
|
-
New projects keep their pages in `frontend/routes/web.
|
|
785
|
+
New projects keep their pages in `frontend/routes/web.kreft`, and `index.html` only points to it:
|
|
801
786
|
|
|
802
787
|
```js
|
|
803
788
|
Kreftjs.router({
|
|
804
|
-
routes: ['routes/web.
|
|
789
|
+
routes: ['routes/web.kreft', 'routes/shop.kreft'],
|
|
805
790
|
layout: 'app',
|
|
806
791
|
errors: 'errors',
|
|
807
792
|
middleware: {
|
|
@@ -812,27 +797,27 @@ Kreftjs.router({
|
|
|
812
797
|
```
|
|
813
798
|
|
|
814
799
|
```js
|
|
815
|
-
// routes/web.
|
|
816
|
-
Route.view('/', 'pages/Home.
|
|
817
|
-
Route.view('/posts/:id', 'pages/Post.
|
|
800
|
+
// routes/web.kreft
|
|
801
|
+
Route.view('/', 'pages/Home.kreft').name('home').title('Home')
|
|
802
|
+
Route.view('/posts/:id', 'pages/Post.kreft')
|
|
818
803
|
|
|
819
804
|
Route.middleware('auth').group(() => {
|
|
820
|
-
Route.view('/dashboard', 'pages/Dashboard.
|
|
805
|
+
Route.view('/dashboard', 'pages/Dashboard.kreft').middleware('verified')
|
|
821
806
|
})
|
|
822
807
|
|
|
823
808
|
Route.layout('guest').middleware('guest').group(() => {
|
|
824
|
-
Route.view('/login', 'pages/auth/Login.
|
|
809
|
+
Route.view('/login', 'pages/auth/Login.kreft').title('Log in')
|
|
825
810
|
})
|
|
826
811
|
|
|
827
812
|
Route.prefix('/account').name('account.').middleware('auth').group(() => {
|
|
828
|
-
Route.view('/settings', 'pages/account/Settings.
|
|
829
|
-
Route.view('', 'pages/account/General.
|
|
830
|
-
Route.view('mail', 'pages/account/Mail.
|
|
813
|
+
Route.view('/settings', 'pages/account/Settings.kreft').children(() => {
|
|
814
|
+
Route.view('', 'pages/account/General.kreft') // /account/settings
|
|
815
|
+
Route.view('mail', 'pages/account/Mail.kreft') // /account/settings/mail
|
|
831
816
|
})
|
|
832
817
|
})
|
|
833
818
|
|
|
834
819
|
Route.redirect('/home', '/')
|
|
835
|
-
Route.fallback('pages/NotFound.
|
|
820
|
+
Route.fallback('pages/NotFound.kreft')
|
|
836
821
|
```
|
|
837
822
|
|
|
838
823
|
| On a route | What it does |
|
|
@@ -852,7 +837,7 @@ Route.fallback('pages/NotFound.kreftjs')
|
|
|
852
837
|
A layout is the frame around your pages: bar, menu, footer. Put it in `layouts/` and use `<slot>` where the page goes.
|
|
853
838
|
|
|
854
839
|
```html
|
|
855
|
-
<!-- layouts/app.
|
|
840
|
+
<!-- layouts/app.kreft -->
|
|
856
841
|
state menuOpen = false
|
|
857
842
|
|
|
858
843
|
<view>
|
|
@@ -887,12 +872,12 @@ A page can also fill other places in its layout:
|
|
|
887
872
|
Each HTTP error can have its own page in `errors/`. Turn them on with `errors: 'errors'` in the router. New projects already have the folder (`kreft make:errors` adds it to an older one):
|
|
888
873
|
|
|
889
874
|
```text
|
|
890
|
-
errors/401.
|
|
891
|
-
errors/error.
|
|
892
|
-
errors/minimal.
|
|
875
|
+
errors/401.kreft 402.kreft 403.kreft 404.kreft 419.kreft 429.kreft 500.kreft 503.kreft
|
|
876
|
+
errors/error.kreft any other status
|
|
877
|
+
errors/minimal.kreft the shared frame
|
|
893
878
|
```
|
|
894
879
|
|
|
895
|
-
An unknown address shows `errors/404.
|
|
880
|
+
An unknown address shows `errors/404.kreft`; a page that cannot load shows `errors/500.kreft`. From any `.kreft` file, `abort(404)` (also `$router.abort()` and `Kreftjs.abort()`) shows the matching page:
|
|
896
881
|
|
|
897
882
|
```html
|
|
898
883
|
prop id
|
|
@@ -911,7 +896,7 @@ If you cannot change the server, use `mode: 'hash'`; URLs then look like `/#/use
|
|
|
911
896
|
|
|
912
897
|
## Fetching data
|
|
913
898
|
|
|
914
|
-
The global `api` client is available in every `.
|
|
899
|
+
The global `api` client is available in every `.kreft` file, and `Kreftjs.api` in plain JavaScript:
|
|
915
900
|
|
|
916
901
|
```js
|
|
917
902
|
const users = await api.get('/api/users', { query: { page: 2 } })
|
|
@@ -926,7 +911,7 @@ await api.delete('/api/users/1')
|
|
|
926
911
|
`load` declares a reactive resource. It handles the loading state, the error, and fetches again when the values it reads change:
|
|
927
912
|
|
|
928
913
|
```html
|
|
929
|
-
<!-- pages/Posts.
|
|
914
|
+
<!-- pages/Posts.kreft -->
|
|
930
915
|
state query = ''
|
|
931
916
|
state page = 1
|
|
932
917
|
|
|
@@ -1112,7 +1097,7 @@ On the server, request language comes from `?lang=`, the `lang` cookie or `Accep
|
|
|
1112
1097
|
|
|
1113
1098
|
## Using Kreft from JavaScript
|
|
1114
1099
|
|
|
1115
|
-
You can write components as plain objects. The rules match the `.
|
|
1100
|
+
You can write components as plain objects. The rules match the `.kreft` language: values are state, getters are derived values, functions are actions.
|
|
1116
1101
|
|
|
1117
1102
|
```js
|
|
1118
1103
|
Kreftjs.app({
|
|
@@ -1123,7 +1108,7 @@ Kreftjs.app({
|
|
|
1123
1108
|
}).mount('#app')
|
|
1124
1109
|
```
|
|
1125
1110
|
|
|
1126
|
-
| JavaScript | Same as in `.
|
|
1111
|
+
| JavaScript | Same as in `.kreft` |
|
|
1127
1112
|
|---|---|
|
|
1128
1113
|
| `Kreftjs.state({ … })` | `state` + `derive` + `action` together, for code outside components. |
|
|
1129
1114
|
| `Kreftjs.signal(0)` | One value, read and written with `.value`. |
|
|
@@ -1141,7 +1126,7 @@ Kreftjs.render(`<ul><li k-each="u in users">{u}</li></ul>`, { users: ['Alex', 'A
|
|
|
1141
1126
|
|
|
1142
1127
|
### Server templates
|
|
1143
1128
|
|
|
1144
|
-
Blade and similar engines use `{{ }}`; Kreft uses `{ }`, so they do not clash. Put `kreftjs.js` and your `.
|
|
1129
|
+
Blade and similar engines use `{{ }}`; Kreft uses `{ }`, so they do not clash. Put `kreftjs.js` and your `.kreft` files in your public folder and mount as usual.
|
|
1145
1130
|
|
|
1146
1131
|
# Backend
|
|
1147
1132
|
|
|
@@ -1397,13 +1382,13 @@ New projects come with every sign-in screen and the backend behind it:
|
|
|
1397
1382
|
|
|
1398
1383
|
| Page | Address | What it does |
|
|
1399
1384
|
|---|---|---|
|
|
1400
|
-
| `pages/auth/Login.
|
|
1401
|
-
| `pages/auth/Register.
|
|
1402
|
-
| `pages/auth/ForgotPassword.
|
|
1403
|
-
| `pages/auth/ResetPassword.
|
|
1404
|
-
| `pages/auth/VerifyEmail.
|
|
1405
|
-
| `pages/auth/ConfirmPassword.
|
|
1406
|
-
| `pages/Dashboard.
|
|
1385
|
+
| `pages/auth/Login.kreft` | `/login` | Log in with email and password. |
|
|
1386
|
+
| `pages/auth/Register.kreft` | `/register` | Make an account and get an email to verify the address. |
|
|
1387
|
+
| `pages/auth/ForgotPassword.kreft` | `/forgot-password` | Email a link to choose a new password. |
|
|
1388
|
+
| `pages/auth/ResetPassword.kreft` | `/reset-password/:token` | The link from that email. |
|
|
1389
|
+
| `pages/auth/VerifyEmail.kreft` | `/verify-email` | "Check your email", and the link from it opens `/verify-email/:id/:hash`. |
|
|
1390
|
+
| `pages/auth/ConfirmPassword.kreft` | `/confirm-password` | Type the password again before something serious. |
|
|
1391
|
+
| `pages/Dashboard.kreft`, `pages/Profile.kreft` | `/dashboard`, `/profile` | The first page after logging in; account settings. |
|
|
1407
1392
|
|
|
1408
1393
|
### How a login works
|
|
1409
1394
|
|
|
@@ -1649,7 +1634,7 @@ Run `kreft list` to see every command your installed version has, and `kreft hel
|
|
|
1649
1634
|
| `kreft add <package>` | A safer `npm install`. See [Packages](#packages). |
|
|
1650
1635
|
| `kreft about`, `kreft env`, `kreft log`, `kreft tinker` | Versions and folders, environment, logs, a console with your models (`await User.count()`). |
|
|
1651
1636
|
| `kreft down --secret=x` / `kreft up` | Maintenance mode: visitors get `503`, and `/x` lets you in. |
|
|
1652
|
-
| `kreft vscode` | Installs colors, snippets and folding for `.
|
|
1637
|
+
| `kreft vscode` | Installs colors, snippets and folding for `.kreft` files in VS Code, Cursor and VSCodium. |
|
|
1653
1638
|
|
|
1654
1639
|
### Generators and database
|
|
1655
1640
|
|
|
@@ -1675,7 +1660,7 @@ Run `kreft list` to see every command your installed version has, and `kreft hel
|
|
|
1675
1660
|
|
|
1676
1661
|
Everything here comes with Kreft. Nothing else to install.
|
|
1677
1662
|
|
|
1678
|
-
**Hot reload.** While `kreft dev` runs, save a `.
|
|
1663
|
+
**Hot reload.** While `kreft dev` runs, save a `.kreft` file and only that component is swapped; its state stays. A `.css` file is reloaded without a page refresh, and an error shows an overlay with the file and line.
|
|
1679
1664
|
|
|
1680
1665
|
**Kreft DevTools.** The **S** button in the corner (or <kbd>Alt</kbd>+<kbd>Shift</kbd>+<kbd>D</kbd>) opens a panel:
|
|
1681
1666
|
|
|
@@ -1702,10 +1687,10 @@ In development, an uncaught error on the server shows an interactive page instea
|
|
|
1702
1687
|
|
|
1703
1688
|
The page is only shown when `APP_ENV` is not `production` and `APP_DEBUG` is true. **In production the same error answers a plain `Server error.`** with no stack or file names.
|
|
1704
1689
|
|
|
1705
|
-
Frontend errors use the same design through `errors/ErrorMonitor.
|
|
1690
|
+
Frontend errors use the same design through `errors/ErrorMonitor.kreft`; pass it a caught exception:
|
|
1706
1691
|
|
|
1707
1692
|
```html
|
|
1708
|
-
import ErrorMonitor from 'errors/ErrorMonitor.
|
|
1693
|
+
import ErrorMonitor from 'errors/ErrorMonitor.kreft'
|
|
1709
1694
|
state caught = null
|
|
1710
1695
|
|
|
1711
1696
|
<view>
|
|
@@ -1726,16 +1711,16 @@ npm run preview # check the result: kreft dev dist
|
|
|
1726
1711
|
|---|---|
|
|
1727
1712
|
| `index.html` | Your page, now loading the files below. |
|
|
1728
1713
|
| `kreftjs.js` | The framework. |
|
|
1729
|
-
| `app.js` | Every `.
|
|
1714
|
+
| `app.js` | Every `.kreft` file, already compiled. |
|
|
1730
1715
|
| `app.css` | All `<style>` blocks; scoped ones already scoped. |
|
|
1731
1716
|
| `main.js` | The inline `<script>` code from `index.html`. |
|
|
1732
|
-
| `deps/`, `vendor/` | The npm packages and CSS your `.
|
|
1717
|
+
| `deps/`, `vendor/` | The npm packages and CSS your `.kreft` files import, minified. |
|
|
1733
1718
|
|
|
1734
1719
|
What you get:
|
|
1735
1720
|
|
|
1736
1721
|
- **A faster first load.** The browser downloads one `app.js` and compiles nothing.
|
|
1737
1722
|
- **A strict Content-Security-Policy works.** Every expression becomes a real function, so the built app never uses `eval` or `new Function`.
|
|
1738
|
-
- **Errors before you deploy.** A mistake in any `.
|
|
1723
|
+
- **Errors before you deploy.** A mistake in any `.kreft` file stops the build and names the file and line.
|
|
1739
1724
|
|
|
1740
1725
|
Options: `kreft build ./site --out public` builds another folder, and `--base /` changes `<base href>`. `--no-htaccess` skips the `.htaccess` file described below.
|
|
1741
1726
|
|
|
@@ -1751,10 +1736,12 @@ RewriteBase /
|
|
|
1751
1736
|
RewriteRule ^index\.html$ - [L]
|
|
1752
1737
|
RewriteCond %{REQUEST_FILENAME} !-f
|
|
1753
1738
|
RewriteCond %{REQUEST_FILENAME} !-d
|
|
1739
|
+
RewriteCond %{REQUEST_URI} !^/api/
|
|
1740
|
+
RewriteCond %{REQUEST_URI} !\.[A-Za-z0-9]+$
|
|
1754
1741
|
RewriteRule . /index.html [L]
|
|
1755
1742
|
```
|
|
1756
1743
|
|
|
1757
|
-
Apache only knows the files on disk, so without these rules `/docs` or any other clean address gives a 404 when someone opens or reloads it. With them, every address that is not a real file or folder opens `index.html` and the router takes over. Upload the file too (it starts with a dot, so some file managers hide it; turn on "show hidden files"). If the site lives in a folder, build with `--base /folder/` and the rules follow it. An `.htaccess` you keep in `public/` is used as it is. A relative base (`--base ./`, used by the desktop build) gets no file.
|
|
1744
|
+
Apache only knows the files on disk, so without these rules `/docs` or any other clean address gives a 404 when someone opens or reloads it. With them, every page address (no file extension, not under `/api/`) that is not a real file or folder opens `index.html` and the router takes over. A missing file such as `app.js`, or an `/api/` address, stays a plain 404, so code that asks for data never receives the page's HTML. Upload the file too (it starts with a dot, so some file managers hide it; turn on "show hidden files"). If the site lives in a folder, build with `--base /folder/` and the rules follow it. An `.htaccess` you keep in `public/` is used as it is. A relative base (`--base ./`, used by the desktop build) gets no file.
|
|
1758
1745
|
|
|
1759
1746
|
> [!NOTE]
|
|
1760
1747
|
> This hosts the front end only. Login, the database and everything under `/api` need the Node.js server, which Apache does not run.
|
|
@@ -1828,7 +1815,7 @@ module.exports = {
|
|
|
1828
1815
|
|
|
1829
1816
|
### Whole pages for crawlers
|
|
1830
1817
|
|
|
1831
|
-
A crawler or link preview (Googlebot, Bingbot, WhatsApp, Facebook, X, Slack, Telegram …) that doesn't run JavaScript would see an empty `<div id="app">`. For these visitors `kreft dev` and `kreft serve` open the page in the same simulated browser as `--prerender`, wait until its data has loaded, and answer with the page already drawn. If the app shows its `errors/404.
|
|
1818
|
+
A crawler or link preview (Googlebot, Bingbot, WhatsApp, Facebook, X, Slack, Telegram …) that doesn't run JavaScript would see an empty `<div id="app">`. For these visitors `kreft dev` and `kreft serve` open the page in the same simulated browser as `--prerender`, wait until its data has loaded, and answer with the page already drawn. If the app shows its `errors/404.kreft` page, the answer has status 404. A page that `kreft build --prerender` already drew is sent as it is. Everyone else gets the normal page.
|
|
1832
1819
|
|
|
1833
1820
|
```bash
|
|
1834
1821
|
npm i -D jsdom # once per project
|
|
@@ -1847,7 +1834,7 @@ kreft sitemap --url https://example.com # public/sitemap.xml an
|
|
|
1847
1834
|
kreft sitemap --url https://example.com --urls urls.js # and the addresses in that file
|
|
1848
1835
|
```
|
|
1849
1836
|
|
|
1850
|
-
It lists the routes of `Kreftjs.router({ routes })` in `index.html` and `routes/web.
|
|
1837
|
+
It lists the routes of `Kreftjs.router({ routes })` in `index.html` and `routes/web.kreft`, skipping redirects and patterns like `/posts/:id`, plus the `urls` of `backend/routes/seo.js` and `--urls`. A `lastmod` is written only when you give one (a database date such as `2026-01-02 10:00:00` becomes `2026-01-02`). A route can list `alternates: { en: '/about', ar: '/ar/about' }` for `xhtml:link` entries.
|
|
1851
1838
|
|
|
1852
1839
|
### Deploying the backend
|
|
1853
1840
|
|
|
@@ -1859,13 +1846,13 @@ Before you do, work through the [Production checklist](#production-checklist).
|
|
|
1859
1846
|
|
|
1860
1847
|
## TypeScript
|
|
1861
1848
|
|
|
1862
|
-
TypeScript works in the browser (`.
|
|
1849
|
+
TypeScript works in the browser (`.kreft` files and `.ts` modules) and on the server (`routes/api.ts`, `app/**/*.ts`, migrations, seeders).
|
|
1863
1850
|
|
|
1864
1851
|
```bash
|
|
1865
1852
|
kreft new my-app --ts
|
|
1866
1853
|
```
|
|
1867
1854
|
|
|
1868
|
-
Inside a `.
|
|
1855
|
+
Inside a `.kreft` file you can write `interface`, `type`, `enum`, `import type`, and typed `prop`, `state`, `derive` and `saved`. `kreftjs make:*` writes `.ts` files when the project has a `tsconfig.json` (or with `--ts`; `--js` forces JavaScript).
|
|
1869
1856
|
|
|
1870
1857
|
Execution needs no setup: Kreft uses `esbuild` if installed, otherwise Node's built-in type stripping (Node 22.6+), otherwise its own zero-dependency stripper.
|
|
1871
1858
|
|
|
@@ -1874,7 +1861,7 @@ Execution needs no setup: Kreft uses `esbuild` if installed, otherwise Node's bu
|
|
|
1874
1861
|
|
|
1875
1862
|
## Vite and Electron
|
|
1876
1863
|
|
|
1877
|
-
**Vite.** If your team prefers the Vite ecosystem, Kreft has a plugin that compiles `.
|
|
1864
|
+
**Vite.** If your team prefers the Vite ecosystem, Kreft has a plugin that compiles `.kreft` files on the fly:
|
|
1878
1865
|
|
|
1879
1866
|
```bash
|
|
1880
1867
|
kreft vite:init # writes vite.config.js with the Kreft plugin
|
|
@@ -1887,7 +1874,7 @@ kreft vite:preview
|
|
|
1887
1874
|
|
|
1888
1875
|
## Desktop apps with Electron
|
|
1889
1876
|
|
|
1890
|
-
Kreft can package your app as a desktop application for Windows, macOS and Linux. The pages are the same `.
|
|
1877
|
+
Kreft can package your app as a desktop application for Windows, macOS and Linux. The pages are the same `.kreft` files you already have; Electron only supplies the window.
|
|
1891
1878
|
|
|
1892
1879
|
### Quick start
|
|
1893
1880
|
|
|
@@ -2221,7 +2208,7 @@ Go through this before your first real user:
|
|
|
2221
2208
|
- The memory of which two-factor codes were already used, and login tickets, is kept per process. Behind several servers, a code can be replayed once on each. The per-account lockout (kept in the cache) still limits guessing.
|
|
2222
2209
|
- The sanitizer removes unsafe markup; it is not a substitute for choosing carefully what HTML you show.
|
|
2223
2210
|
- `--prerender` makes static HTML at build time. On a running server whole pages are drawn only for crawlers and link previews; every other visitor gets the page drawn by the browser, and an address the app does not have answers 200 (the app shows its own 404 page) unless `seo.js` says otherwise.
|
|
2224
|
-
- `.
|
|
2211
|
+
- `.kreft` files must be served over `http://` or `https://`, not opened from `file://`.
|
|
2225
2212
|
|
|
2226
2213
|
# Reference
|
|
2227
2214
|
|
|
@@ -2284,7 +2271,7 @@ Set these in `.env` (never commit it). Variables that start with `PUBLIC_` are c
|
|
|
2284
2271
|
|
|
2285
2272
|
| Group | Names |
|
|
2286
2273
|
|---|---|
|
|
2287
|
-
| `.
|
|
2274
|
+
| `.kreft` keywords | `state` `derive` `action` `when` `watch` `on` `prop` `event` `use` `share` `receive` `import` `saved` `load` `layout` |
|
|
2288
2275
|
| In the script | `send` `props` `bus` `store` `$route` `$router` `tick` and every `Kreft` function |
|
|
2289
2276
|
| In the view | `{expr}` `attr={expr}` `@event` `k-if` `k-elif` `k-else` `k-each` `k-key` `k-model` `k-show` `k-text` `k-html` `k-ref` `k-skip` `k-once` `k-memo` `k-animate` `{for}` |
|
|
2290
2277
|
| App | `Kreftjs.app(rootOrPath)` then `.component()` `.directive()` `.share()` `.use()` `.mount()` `.unmount()` |
|
|
@@ -2305,7 +2292,7 @@ Kreft is one framework for the browser and the server. The others below each cov
|
|
|
2305
2292
|
| | **Kreft** | **Next.js** | **Nuxt** | **Astro** | **AdonisJS** | **NestJS** |
|
|
2306
2293
|
|---|---|---|---|---|---|---|
|
|
2307
2294
|
| **What it is** | Frontend and backend in one | React framework | Vue framework | Content sites with islands of interactivity | Backend (MVC) | Backend (modules, dependency injection) |
|
|
2308
|
-
| **Components** | `.
|
|
2295
|
+
| **Components** | `.kreft` files, no Virtual DOM | React | Vue | Astro files; React, Vue, Svelte … inside | none (Edge templates, or Inertia) | none |
|
|
2309
2296
|
| **Pages drawn on the server** | At build time (`--prerender`), and for crawlers and link previews on request | Yes, for every visitor | Yes, for every visitor | Yes, mostly at build time | Only with Inertia | no |
|
|
2310
2297
|
| **Database layer** | Active Record `Model`, migrations, seeders, factories | none (use Prisma, Drizzle …) | none | none | Lucid (Active Record) | none (TypeORM, Prisma, MikroORM …) |
|
|
2311
2298
|
| **Sign-in, 2FA, API tokens** | Built in, in every new project | none (Auth.js …) | none (a module) | none | Built in | none (Passport, your own) |
|
|
@@ -2324,13 +2311,13 @@ Kreft is one framework for the browser and the server. The others below each cov
|
|
|
2324
2311
|
- **AdonisJS:** you want the same Laravel-like backend with a larger community and years of production use, and you will bring your own frontend.
|
|
2325
2312
|
- **NestJS:** you build a large API or microservices with many teams, and you want strict structure and dependency injection.
|
|
2326
2313
|
|
|
2327
|
-
**Things to weigh before choosing Kreft:** it is young and has one small community, few third-party packages are made for `.
|
|
2314
|
+
**Things to weigh before choosing Kreft:** it is young and has one small community, few third-party packages are made for `.kreft` files, and nobody has run it at large scale yet. See [Known limits](#known-limits).
|
|
2328
2315
|
|
|
2329
2316
|
## Coming from Vue
|
|
2330
2317
|
|
|
2331
2318
|
| Vue | Kreft |
|
|
2332
2319
|
|---|---|
|
|
2333
|
-
| `.vue` single-file component | `.
|
|
2320
|
+
| `.vue` single-file component | `.kreft` file: script, `<view>`, `<style scoped>` |
|
|
2334
2321
|
| `ref()`, `reactive()`, `computed()` | `state`, `derive` (JS: `Kreftjs.signal`, `Kreftjs.state`, `Kreftjs.derived`) |
|
|
2335
2322
|
| `watch`, `watchEffect` | `watch x { }`, `when cond { }` (JS: `Kreftjs.watch`, `Kreftjs.effect`) |
|
|
2336
2323
|
| `{{ x }}`, `:attr`, `@click` | `{x}`, `attr={x}`, `@click={fn}` |
|
|
@@ -2353,7 +2340,7 @@ Kreft is one framework for the browser and the server. The others below each cov
|
|
|
2353
2340
|
|
|
2354
2341
|
| Term | Meaning |
|
|
2355
2342
|
|---|---|
|
|
2356
|
-
| **Component** | A `.
|
|
2343
|
+
| **Component** | A `.kreft` file: script, view and style together. |
|
|
2357
2344
|
| **State** | A value that can change; the view follows it. |
|
|
2358
2345
|
| **Derived value** | A value calculated from other values; stays up to date by itself. |
|
|
2359
2346
|
| **Store** | State shared by many components. |
|