kreftjs 0.0.3-beta → 0.0.5-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.
Files changed (54) hide show
  1. package/LICENSE +95 -0
  2. package/README.md +13 -13
  3. package/bin/add.js +11 -11
  4. package/bin/artisan-more.js +41 -41
  5. package/bin/artisan.js +41 -41
  6. package/bin/backend/command.js +1 -1
  7. package/bin/backend/factory.js +1 -1
  8. package/bin/backend/index.js +3 -3
  9. package/bin/backend/model.js +2 -2
  10. package/bin/backend/notifications.js +1 -1
  11. package/bin/backend/queue.js +2 -2
  12. package/bin/backend/schedule.js +2 -2
  13. package/bin/backend/seo-pages.js +1 -1
  14. package/bin/backend/storage.js +1 -1
  15. package/bin/backend/support.js +4 -4
  16. package/bin/backend/typescript.js +1 -1
  17. package/bin/build.js +11 -11
  18. package/bin/db-api.js +3 -3
  19. package/bin/db.js +1 -1
  20. package/bin/deps.js +6 -6
  21. package/bin/electron.js +11 -11
  22. package/bin/env.js +2 -2
  23. package/bin/guard.js +2 -2
  24. package/bin/kreftjs-config.js +1 -1
  25. package/bin/kreftjs.js +105 -105
  26. package/bin/layout.js +1 -1
  27. package/bin/no-auth.js +4 -4
  28. package/bin/prerender.js +4 -4
  29. package/bin/server-routes.js +2 -2
  30. package/bin/ssr.js +2 -2
  31. package/bin/terminal.js +1 -1
  32. package/bin/to-ts.js +1 -1
  33. package/bin/update.js +14 -14
  34. package/bin/urls-file.js +1 -1
  35. package/bin/vite.js +11 -11
  36. package/docs/Docs.kreftjs +1 -1
  37. package/docs/README.md +140 -123
  38. package/kreftjs.d.ts +1 -1
  39. package/kreftjs.js +18 -18
  40. package/package.json +2 -1
  41. package/templates/app/README.md +20 -20
  42. package/templates/app/backend/database/migrations/0001_01_01_000000_create_users_table.js +1 -1
  43. package/templates/app/backend/database/migrations/0001_01_01_000002_create_jobs_table.js +1 -1
  44. package/templates/app/backend/database/seeders/DatabaseSeeder.js +1 -1
  45. package/templates/app/backend/routes/api.js +1 -1
  46. package/templates/app/backend/routes/console.js +2 -2
  47. package/templates/app/frontend/errors/ErrorMonitor.kreftjs +2 -2
  48. package/templates/app/frontend/index.html +1 -1
  49. package/templates/app/frontend/kreftjs.d.ts +1 -1
  50. package/templates/app/frontend/kreftjs.js +18 -18
  51. package/templates/app/frontend/pages/Dashboard.kreftjs +1 -1
  52. package/templates/app/frontend/pages/ErrorMonitor.kreftjs +1 -1
  53. package/templates/app/frontend/pages/Home.kreftjs +2 -2
  54. package/templates/errors/ErrorMonitor.kreftjs +1 -1
package/bin/kreftjs.js CHANGED
@@ -2,15 +2,15 @@
2
2
  /*
3
3
  * The kreftjs command
4
4
  *
5
- * kreftjs new my-app create a new Kreft project
6
- * kreftjs dev run the dev server in this folder (http://localhost:8000)
7
- * kreftjs dev --port 3000 another port
8
- * kreftjs dev ./site another folder
9
- * kreftjs build build this folder for production into ./dist
10
- * kreftjs vscode install colors and snippets for .kreftjs files in VS Code
11
- * kreftjs serve dist run the built app in production (with --db: its database API)
12
- * kreftjs db migrate run new database/migrations/*.sql (also: seed, tables, sql "…")
13
- * kreftjs help show this help
5
+ * kreft new my-app create a new Kreft project
6
+ * kreft dev run the dev server in this folder (http://localhost:8000)
7
+ * kreft dev --port 3000 another port
8
+ * kreft dev ./site another folder
9
+ * kreft build build this folder for production into ./dist
10
+ * kreft vscode install colors and snippets for .kreftjs files in VS Code
11
+ * kreft serve dist run the built app in production (with --db: its database API)
12
+ * kreft db migrate run new database/migrations/*.sql (also: seed, tables, sql "…")
13
+ * kreft help show this help
14
14
  *
15
15
  * No dependencies — only Node.js.
16
16
  */
@@ -71,7 +71,7 @@ guard.checkStart(command);
71
71
  if (['queue:work', 'queue:start', 'schedule:work'].includes(command)) guard.watch([process.cwd()]);
72
72
  if (commands[command]) commands[command](rest);
73
73
  else if (command && !command.startsWith('-')) {
74
- // your own commands: app/Console/Commands (kreftjs make:command SendReport)
74
+ // your own commands: app/Console/Commands (kreft make:command SendReport)
75
75
  require('./artisan-more.js').runCustom(command, rest).then((found) => { if (!found) unknown(); }, (e) => { console.error(' ' + (e.stack || e)); process.exitCode = 1; });
76
76
  } else unknown();
77
77
 
@@ -81,7 +81,7 @@ function help() {
81
81
  Kreft ${pkg.version}
82
82
 
83
83
  Usage:
84
- kreftjs new <name> Create a new project in a folder called <name>, with login, register,
84
+ kreft new <name> Create a new project in a folder called <name>, with login, register,
85
85
  password reset, email verification and profile pages (on SQLite)
86
86
  --db <kind> …on another database (sqlite, mysql or postgres), plus a Todos example
87
87
  --no-auth …without login, register, profile and users (--auth: with them, the default)
@@ -91,7 +91,7 @@ function help() {
91
91
  --js …use JavaScript (default when non-interactive)
92
92
  --electron …with Electron desktop app support (main.js, preload.js, packaging)
93
93
  --vite …with Vite.js bundling & instant HMR (vite.config.js, npm run vite)
94
- kreftjs dev [folder] Start the dev server (default: this folder)
94
+ kreft dev [folder] Start the dev server (default: this folder)
95
95
  --port <number> Port to use (default: 8000, or the next free one)
96
96
  --host <address> Who may open it (default: 127.0.0.1, only this computer; 0.0.0.0: your network)
97
97
  --api <file.json> Serve a REST API from a JSON file at /api (GET, POST, PUT, PATCH, DELETE)
@@ -104,83 +104,83 @@ function help() {
104
104
  --server <dir> Your own Node.js code for /api (default: server/): server/hello.js → /api/hello
105
105
  --db <database> Serve the tables of a database at /api (new migrations run first):
106
106
  sqlite:database/app.db (built in, nothing to install)
107
- mysql://user:pass@localhost:3306/shop (kreftjs add mysql2)
108
- postgres://user:pass@localhost:5432/shop (kreftjs add pg)
109
- kreftjs serve [folder] Run a built app for real users (folder: dist). Same --port and --db;
107
+ mysql://user:pass@localhost:3306/shop (kreft add mysql2)
108
+ postgres://user:pass@localhost:5432/shop (kreft add pg)
109
+ kreft serve [folder] Run a built app for real users (folder: dist). Same --port and --db;
110
110
  only the tables listed in kreftjs.config.json are served
111
111
 
112
112
  Bundler & Dev Server (Vite.js):
113
- kreftjs vite Start Vite dev server and proxy backend API (alias: kreftjs vite:dev)
114
- kreftjs vite:dev Start Vite dev server with instant HMR and backend proxy
115
- kreftjs vite:build Build production bundle with Vite and Rollup
116
- kreftjs vite:preview Preview production build locally with Vite
117
- kreftjs vite:init Add Vite configuration to an existing project (alias: kreftjs make:vite)
113
+ kreft vite Start Vite dev server and proxy backend API (alias: kreft vite:dev)
114
+ kreft vite:dev Start Vite dev server with instant HMR and backend proxy
115
+ kreft vite:build Build production bundle with Vite and Rollup
116
+ kreft vite:preview Preview production build locally with Vite
117
+ kreft vite:init Add Vite configuration to an existing project (alias: kreft make:vite)
118
118
 
119
119
  Desktop (Electron.js):
120
- kreftjs electron Start dev server and launch desktop window (alias: kreftjs electron:dev)
121
- kreftjs electron:dev Start dev server and launch desktop window
122
- kreftjs electron:build Build static bundle and package desktop app with electron-builder
123
- kreftjs electron:init Add Electron support to an existing project (alias: kreftjs make:electron)
124
-
125
- The backend (kreftjs list shows every command, yours too):
126
- kreftjs key:generate Set the application encryption key in .env (--show: print only)
127
- kreftjs migrate Run new migrations in database/migrations (.js or .sql)
128
- kreftjs migrate:rollback Undo the last batch of migrations (--step 2: the last two)
129
- kreftjs migrate:fresh Drop every table and migrate again (--seed: then seed)
130
- kreftjs migrate:status Which migrations ran
131
- kreftjs db:seed Run database/seeders/DatabaseSeeder.js (--class PostSeeder: another one)
132
- kreftjs route:list The routes in routes/api.js
133
- kreftjs storage:link Connect public/storage to storage/app/public (--force) (alias: kreftjs link:storage)
134
- kreftjs storage:unlink Remove the storage link (alias: kreftjs unlink:storage)
135
- kreftjs sitemap Generate public/sitemap.xml and robots.txt
136
- kreftjs log Tail recent log entries from storage/logs/kreft.log (--lines 50, --level error)
137
- kreftjs log:clear Clear the log file
138
- kreftjs make:model Post app/Models/Post.js (-m -f -s -c -p -r, --route=file, --auth, --all)
139
- kreftjs make:controller PostController (--api, --model Post, -r, --route=file, --auth)
140
- kreftjs make:request StorePostRequest app/Http/Requests/StorePostRequest.js (--model Post)
141
- kreftjs make:resource PostResource app/Http/Resources/PostResource.js
142
- kreftjs make:rule Uppercase app/Rules/Uppercase.js
143
- kreftjs make:page Post frontend/pages/Post.kreftjs (--model Post, -r, --route=file, --auth)
144
- kreftjs make:factory PostFactory database/factories/PostFactory.js (--model Post)
145
- kreftjs make:migration create_posts_table
146
- kreftjs make:seeder PostSeeder
147
- kreftjs make:middleware EnsureIsAdmin
148
- kreftjs make:job SendWelcomeEmail app/Jobs/SendWelcomeEmail.js
149
- kreftjs make:event OrderShipped app/Events/OrderShipped.js
150
- kreftjs make:listener SendShipmentNotice app/Listeners/SendShipmentNotice.js (--event OrderShipped)
151
- kreftjs make:mail WelcomeMail app/Mail/WelcomeMail.js
152
- kreftjs make:notification InvoicePaid app/Notifications/InvoicePaid.js
153
- kreftjs make:policy PostPolicy app/Policies/PostPolicy.js (--model Post)
154
- kreftjs make:observer PostObserver app/Observers/PostObserver.js (--model Post)
155
- kreftjs make:command SendReport app/Console/Commands/SendReport.js (--command report:send)
156
- kreftjs make:errors The error pages in errors/ (401, 403, 404, 419, 429, 500, 503…)
157
- kreftjs make:admin <email> Let that user open the admin panel at /admin (--remove: take it away)
158
- kreftjs make:routes admin A new route file for pages: frontend/routes/admin.kreftjs (--api: backend/routes/admin.js)
159
- kreftjs db tables List tables and columns
160
- kreftjs db sql "<SQL>" Run one SQL statement and print the result
161
- kreftjs build [folder] Build for production (default: this folder)
120
+ kreft electron Start dev server and launch desktop window (alias: kreft electron:dev)
121
+ kreft electron:dev Start dev server and launch desktop window
122
+ kreft electron:build Build static bundle and package desktop app with electron-builder
123
+ kreft electron:init Add Electron support to an existing project (alias: kreft make:electron)
124
+
125
+ The backend (kreft list shows every command, yours too):
126
+ kreft key:generate Set the application encryption key in .env (--show: print only)
127
+ kreft migrate Run new migrations in database/migrations (.js or .sql)
128
+ kreft migrate:rollback Undo the last batch of migrations (--step 2: the last two)
129
+ kreft migrate:fresh Drop every table and migrate again (--seed: then seed)
130
+ kreft migrate:status Which migrations ran
131
+ kreft db:seed Run database/seeders/DatabaseSeeder.js (--class PostSeeder: another one)
132
+ kreft route:list The routes in routes/api.js
133
+ kreft storage:link Connect public/storage to storage/app/public (--force) (alias: kreft link:storage)
134
+ kreft storage:unlink Remove the storage link (alias: kreft unlink:storage)
135
+ kreft sitemap Generate public/sitemap.xml and robots.txt
136
+ kreft log Tail recent log entries from storage/logs/kreft.log (--lines 50, --level error)
137
+ kreft log:clear Clear the log file
138
+ kreft make:model Post app/Models/Post.js (-m -f -s -c -p -r, --route=file, --auth, --all)
139
+ kreft make:controller PostController (--api, --model Post, -r, --route=file, --auth)
140
+ kreft make:request StorePostRequest app/Http/Requests/StorePostRequest.js (--model Post)
141
+ kreft make:resource PostResource app/Http/Resources/PostResource.js
142
+ kreft make:rule Uppercase app/Rules/Uppercase.js
143
+ kreft make:page Post frontend/pages/Post.kreftjs (--model Post, -r, --route=file, --auth)
144
+ kreft make:factory PostFactory database/factories/PostFactory.js (--model Post)
145
+ kreft make:migration create_posts_table
146
+ kreft make:seeder PostSeeder
147
+ kreft make:middleware EnsureIsAdmin
148
+ kreft make:job SendWelcomeEmail app/Jobs/SendWelcomeEmail.js
149
+ kreft make:event OrderShipped app/Events/OrderShipped.js
150
+ kreft make:listener SendShipmentNotice app/Listeners/SendShipmentNotice.js (--event OrderShipped)
151
+ kreft make:mail WelcomeMail app/Mail/WelcomeMail.js
152
+ kreft make:notification InvoicePaid app/Notifications/InvoicePaid.js
153
+ kreft make:policy PostPolicy app/Policies/PostPolicy.js (--model Post)
154
+ kreft make:observer PostObserver app/Observers/PostObserver.js (--model Post)
155
+ kreft make:command SendReport app/Console/Commands/SendReport.js (--command report:send)
156
+ kreft make:errors The error pages in errors/ (401, 403, 404, 419, 429, 500, 503…)
157
+ kreft make:admin <email> Let that user open the admin panel at /admin (--remove: take it away)
158
+ kreft make:routes admin A new route file for pages: frontend/routes/admin.kreftjs (--api: backend/routes/admin.js)
159
+ kreft db tables List tables and columns
160
+ kreft db sql "<SQL>" Run one SQL statement and print the result
161
+ kreft build [folder] Build for production (default: this folder)
162
162
  --out <folder> Where to write it (default: dist)
163
163
  --base <path> Change the <base href> (for example /)
164
164
  --prerender [paths] Also save every page as ready HTML (needs: npm i -D jsdom)
165
165
  --include <folder> Also copy this folder into the output (for example docs)
166
- kreftjs add <packages...> Install npm packages with strict security gatekeeper (alias: kreftjs install, kreftjs i)
166
+ kreft add <packages...> Install npm packages with strict security gatekeeper (alias: kreft install, kreft i)
167
167
  -D, --dev Install as devDependency
168
168
  -y, --yes Auto-confirm unverified community packages in CI/CD
169
169
  --dry-run, --check Inspect package security report without installing
170
170
  --allow-scripts Permit postinstall lifecycle scripts (default: sandboxed with --ignore-scripts)
171
171
  --force Bypass redundancy blocks, typosquat traps and security warnings
172
- kreftjs update [packages] Update project packages (npm update) and Kreft runtime files
172
+ kreft update [packages] Update project packages (npm update) and Kreft runtime files
173
173
  --latest Upgrade packages to their latest versions
174
174
  --check Check for outdated packages (npm outdated)
175
175
  --core Update only Kreft runtime files (kreftjs.js, kreftjs.d.ts, server.d.ts)
176
176
  --npm Update only npm dependencies
177
- kreftjs vscode Install .kreftjs colors and snippets in VS Code (also Cursor, VSCodium)
177
+ kreft vscode Install .kreftjs colors and snippets in VS Code (also Cursor, VSCodium)
178
178
 
179
179
  Examples:
180
- kreftjs new shop
180
+ kreft new shop
181
181
  cd shop
182
182
  npm run dev
183
- kreftjs update
183
+ kreft update
184
184
  npm run build
185
185
  `);
186
186
  }
@@ -191,7 +191,7 @@ function unknown() {
191
191
  process.exit(1);
192
192
  }
193
193
 
194
- /* ------------------------------------------------------------------ kreftjs new */
194
+ /* ------------------------------------------------------------------ kreft new */
195
195
  async function createProject(args) {
196
196
  let name = null, dbKind = null, ui = null, ts = false, langChosen = false, electron = false, vite = false, redis = false, auth = true, authChosen = false;
197
197
  for (let i = 0; i < args.length; i++) {
@@ -217,7 +217,7 @@ async function createProject(args) {
217
217
  process.exit(1);
218
218
  }
219
219
  if (!name) {
220
- console.error(' Give the project a name: kreftjs new my-app (or: kreftjs new my-app --ts)');
220
+ console.error(' Give the project a name: kreft new my-app (or: kreft new my-app --ts)');
221
221
  process.exit(1);
222
222
  }
223
223
  const target = path.resolve(name);
@@ -264,8 +264,8 @@ async function createProject(args) {
264
264
  version: '0.1.0',
265
265
  private: true,
266
266
  scripts: {
267
- dev: 'kreftjs dev --seed', start: 'kreftjs dev --seed', build: 'kreftjs build', preview: 'kreftjs dev dist', serve: 'kreftjs serve dist',
268
- migrate: 'kreftjs migrate', 'db:seed': 'kreftjs db:seed', 'migrate:fresh': 'kreftjs migrate:fresh --seed',
267
+ dev: 'kreft dev --seed', start: 'kreft dev --seed', build: 'kreft build', preview: 'kreft dev dist', serve: 'kreft serve dist',
268
+ migrate: 'kreft migrate', 'db:seed': 'kreft db:seed', 'migrate:fresh': 'kreft migrate:fresh --seed',
269
269
  },
270
270
  };
271
271
  // .env: the project's own settings (from .env.example, with its name filled in)
@@ -298,7 +298,7 @@ async function createProject(args) {
298
298
  Created ${name}/
299
299
 
300
300
  Next:
301
- cd ${name}${ts ? '\n npm install (TypeScript, its Node.js types and esbuild)' : ''}${vite ? '\n npm install (install vite)\n kreftjs vite:dev (launch Vite dev server with instant HMR)' : ''}${electron ? '\n npm install (install electron & electron-builder)\n kreftjs electron:dev (launch desktop window)' : ''}${dbKind === 'mysql' ? '\n kreftjs add mysql2 (the MySQL driver, verified & sandboxed)' : dbKind === 'postgres' ? '\n kreftjs add pg (the PostgreSQL driver, verified & sandboxed)' : ''}${dbKind && dbKind !== 'sqlite' ? '\n (set DATABASE_URL in .env to your database)' : ''}
301
+ cd ${name}${ts ? '\n npm install (TypeScript, its Node.js types and esbuild)' : ''}${vite ? '\n npm install (install vite)\n kreft vite:dev (launch Vite dev server with instant HMR)' : ''}${electron ? '\n npm install (install electron & electron-builder)\n kreft electron:dev (launch desktop window)' : ''}${dbKind === 'mysql' ? '\n kreft add mysql2 (the MySQL driver, verified & sandboxed)' : dbKind === 'postgres' ? '\n kreft add pg (the PostgreSQL driver, verified & sandboxed)' : ''}${dbKind && dbKind !== 'sqlite' ? '\n (set DATABASE_URL in .env to your database)' : ''}
302
302
  npm run dev
303
303
 
304
304
  ${auth ? ` Then log in as test@example.com with the password "password", or register.
@@ -306,7 +306,7 @@ ${auth ? ` Then log in as test@example.com with the password "password", or reg
306
306
  ` : ' Created without authentication (--no-auth): there is no login, registration or users table.\n'}`);
307
307
  }
308
308
 
309
- // kreftjs new my-app --ts → TypeScript across backend (.ts) and frontend (.kreftjs, .ts), tsconfig.json, and npm run typecheck
309
+ // kreft new my-app --ts → TypeScript across backend (.ts) and frontend (.kreftjs, .ts), tsconfig.json, and npm run typecheck
310
310
  function toTypeScript(target, projectPkg) {
311
311
  const { toTs, TSCONFIG } = require('./to-ts.js');
312
312
  const walk = (dir) => {
@@ -341,7 +341,7 @@ export interface ApiList<T> {
341
341
  // a typed helper for the frontend, used like any module: import { money } from '../logic/format.ts'
342
342
  fs.mkdirSync(path.join(target, 'frontend', 'logic'), { recursive: true });
343
343
  fs.writeFileSync(path.join(target, 'frontend', 'logic', 'format.ts'), `// A TypeScript module for the pages: import { money, ago } from '../logic/format.ts'
344
- // kreftjs dev turns it into JavaScript as it is sent; kreftjs build writes it as format.js
344
+ // kreft dev turns it into JavaScript as it is sent; kreft build writes it as format.js
345
345
 
346
346
  export function money(amount: number, currency: string = 'USD'): string {
347
347
  return new Intl.NumberFormat('en', { style: 'currency', currency }).format(amount)
@@ -388,7 +388,7 @@ button { font-variant-numeric: tabular-nums; justify-self: start; }
388
388
  }
389
389
  }
390
390
 
391
- // kreftjs new my-app --ui bootstrap → the library's CDN links in index.html
391
+ // kreft new my-app --ui bootstrap → the library's CDN links in index.html
392
392
  function uiKits() { return {
393
393
  tailwind: ['<!-- Tailwind CSS: use its classes in any .kreftjs file -->', '<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>'],
394
394
  bootstrap: ['<!-- Bootstrap: its classes and components (data-bs-toggle…) work in any .kreftjs file -->', '<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">', '<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" defer></script>'],
@@ -411,14 +411,14 @@ function addUiKit(target, ui) {
411
411
  fs.writeFileSync(file, updated);
412
412
  }
413
413
 
414
- // kreftjs new my-app --db sqlite → database/migrations, a seed, kreftjs.config.json and a Todos page
414
+ // kreft new my-app --db sqlite → database/migrations, a seed, kreftjs.config.json and a Todos page
415
415
  function addDatabase(target, kind, projectName) {
416
416
  const back = path.join(target, 'backend'), front = path.join(target, 'frontend');
417
417
  const file = (rel, text) => { fs.mkdirSync(path.dirname(path.join(back, rel)), { recursive: true }); fs.writeFileSync(path.join(back, rel), text); };
418
418
  const d = new Date(), p2 = (n) => String(n).padStart(2, '0');
419
419
  const stamp = `${d.getFullYear()}_${p2(d.getMonth() + 1)}_${p2(d.getDate())}_000001`;
420
420
  // A migration, a model, a controller, a seeder and a route
421
- file(`database/migrations/${stamp}_create_todos_table.js`, `// kreftjs dev runs new migrations by itself (or: kreftjs migrate). kreftjs migrate:rollback runs down().
421
+ file(`database/migrations/${stamp}_create_todos_table.js`, `// kreft dev runs new migrations by itself (or: kreft migrate). kreft migrate:rollback runs down().
422
422
  module.exports = {
423
423
  up(schema) {
424
424
  schema.create('todos', (table) => {
@@ -484,7 +484,7 @@ module.exports = TodoController
484
484
  file('database/seeders/TodoSeeder.js', `const { Seeder } = require('kreftjs/server')
485
485
  const Todo = require('../../app/Models/Todo')
486
486
 
487
- // DatabaseSeeder calls this one (or on its own: kreftjs db:seed --class TodoSeeder)
487
+ // DatabaseSeeder calls this one (or on its own: kreft db:seed --class TodoSeeder)
488
488
  class TodoSeeder extends Seeder {
489
489
  async run() {
490
490
  await Todo.create({ title: 'Learn Kreft', done: true })
@@ -579,7 +579,7 @@ function copyFolder(from, to) {
579
579
  }
580
580
  }
581
581
 
582
- /* ------------------------------------------------------------------ kreftjs vscode */
582
+ /* ------------------------------------------------------------------ kreft vscode */
583
583
  function installVscode() {
584
584
  const os = require('os');
585
585
  const from = path.join(__dirname, '..', 'editors', 'vscode');
@@ -609,12 +609,12 @@ function installVscode() {
609
609
  console.log('\n Restart VS Code (or run "Reload Window") to see updated colors and formatting in .kreftjs files.\n');
610
610
  }
611
611
 
612
- /* ------------------------------------------------------------------ kreftjs dev */
612
+ /* ------------------------------------------------------------------ kreft dev */
613
613
  async function devServer(args, { production = false } = {}) {
614
614
  const isProd = Boolean(production || process.env.APP_ENV === 'production' || process.env.NODE_ENV === 'production');
615
615
  let port = production ? Number(process.env.PORT) || 8000 : 8000, folder = production ? 'dist' : '.', apiFile = null, delay = 0, saveApi = true, hot = !production, dbUrl = null, migrations = null, serverFolder = null, backendFolder = null, seedNew = false;
616
- // kreftjs dev only answers this computer; --host 0.0.0.0 shares it on your network.
617
- // kreftjs serve answers everyone (HOST in the environment can narrow it).
616
+ // kreft dev only answers this computer; --host 0.0.0.0 shares it on your network.
617
+ // kreft serve answers everyone (HOST in the environment can narrow it).
618
618
  let host = production ? process.env.HOST || '0.0.0.0' : '127.0.0.1';
619
619
  for (let i = 0; i < args.length; i++) {
620
620
  if (args[i] === '--port' || args[i] === '-p') port = Number(args[++i]) || port;
@@ -635,7 +635,7 @@ async function devServer(args, { production = false } = {}) {
635
635
  const lay = require('./layout.js').layout(folder === 'dist' || folder === '.' ? '.' : folder);
636
636
  const root = !production && folder === '.' ? lay.frontend : path.resolve(folder);
637
637
  if (production && !fs.existsSync(root)) {
638
- console.error(` Nothing to serve in ${root}. Build first: kreftjs build`);
638
+ console.error(` Nothing to serve in ${root}. Build first: kreft build`);
639
639
  process.exit(1);
640
640
  }
641
641
  const mockApi = apiFile && !production ? createMockApi(path.resolve(apiFile), delay, saveApi) : null;
@@ -654,7 +654,7 @@ async function devServer(args, { production = false } = {}) {
654
654
  const hasBackend = Boolean(apiRoutesFile);
655
655
  // kreftjs serve: the backend must not sit inside the folder that is served, or its files could be downloaded
656
656
  if (production && hasBackend && (backendDir === root || backendDir.startsWith(root + path.sep))) {
657
- console.error(` The backend (${backendDir}) is inside the folder being served (${root}).\n Serve the built site instead: kreftjs build, then kreftjs serve dist`);
657
+ console.error(` The backend (${backendDir}) is inside the folder being served (${root}).\n Serve the built site instead: kreft build, then kreft serve dist`);
658
658
  process.exit(1);
659
659
  }
660
660
  if (production && hasBackend && !process.env.APP_KEY) console.warn(' Warning: no APP_KEY in .env. Signed links (email verification) stop working on every restart.');
@@ -664,7 +664,7 @@ async function devServer(args, { production = false } = {}) {
664
664
  const { createDbApi } = require('./db-api.js');
665
665
  try {
666
666
  db = await connect(dbUrl, { root: config.dir });
667
- if (!production) { // kreftjs dev runs new migrations by itself; for kreftjs serve, run `kreftjs migrate`
667
+ if (!production) { // kreft dev runs new migrations by itself; for kreft serve, run `kreft migrate`
668
668
  const { migrator, installAlias } = require('./backend/index.js');
669
669
  installAlias(); // require('kreftjs/server') and .ts files work in migrations and seeders
670
670
  require('./backend/model.js').setBaseDir(backendDir);
@@ -693,7 +693,7 @@ async function devServer(args, { production = false } = {}) {
693
693
  const n = backend.routes().length;
694
694
  backendRoutesCount = n;
695
695
  // queued jobs, mails and notifications run in the background here, and routes/console.js runs on schedule
696
- // (QUEUE_WORKER=off or SCHEDULER=off in .env when a separate `kreftjs queue:work` / cron does it)
696
+ // (QUEUE_WORKER=off or SCHEDULER=off in .env when a separate `kreft queue:work` / cron does it)
697
697
  if (db) {
698
698
  const queue = require('./backend/queue.js');
699
699
  const queues = String(process.env.QUEUE_NAMES || 'high,default,low').split(',').map((x) => x.trim());
@@ -709,7 +709,7 @@ async function devServer(args, { production = false } = {}) {
709
709
  }
710
710
  if (process.env.SCHEDULER !== 'off') require('./backend/schedule.js').startScheduler(backendDir);
711
711
  }
712
- backendNote = `\n Routes: ${path.relative(process.cwd(), apiRoutesFile) || 'routes/api.js'} → ${n} route${n === 1 ? '' : 's'} at /api (kreftjs route:list)`;
712
+ backendNote = `\n Routes: ${path.relative(process.cwd(), apiRoutesFile) || 'routes/api.js'} → ${n} route${n === 1 ? '' : 's'} at /api (kreft route:list)`;
713
713
  }
714
714
 
715
715
  // ----- your own server code: server/hello.js → /api/hello (any Node.js package can be used there)
@@ -726,7 +726,7 @@ async function devServer(args, { production = false } = {}) {
726
726
  console.error(` --server: ${serverFolder} does not exist.`);
727
727
  process.exit(1);
728
728
  }
729
- // npm packages in the browser (kreftjs dev only; kreftjs build puts them in dist/deps)
729
+ // npm packages in the browser (kreft dev only; kreft build puts them in dist/deps)
730
730
  const npmMap = () => (production ? null : deps.importMap(project));
731
731
 
732
732
  const types = {
@@ -739,7 +739,7 @@ async function devServer(args, { production = false } = {}) {
739
739
 
740
740
  const prodHeaders = isProd ? { 'Referrer-Policy': 'same-origin', 'X-Frame-Options': 'SAMEORIGIN', 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains; preload' } : {};
741
741
  function send(res, file, opts = {}) { // opts.seo: tags for <head> (pages from seo.js), opts.status: 404 for a page that does not exist
742
- // a TypeScript module for the browser: its JavaScript (kreftjs build writes it as .js)
742
+ // a TypeScript module for the browser: its JavaScript (kreft build writes it as .js)
743
743
  if (!production && /\.(m|c)?ts$/i.test(file) && !file.endsWith('.d.ts')) {
744
744
  const { transpileTs } = require('./backend/typescript.js');
745
745
  res.writeHead(200, { 'Content-Type': 'text/javascript; charset=utf-8', 'Cache-Control': 'no-store', 'X-Content-Type-Options': 'nosniff' });
@@ -759,7 +759,7 @@ async function devServer(args, { production = false } = {}) {
759
759
  });
760
760
  if (!production && type === 'text/html') {
761
761
  let html = fs.readFileSync(file, 'utf8');
762
- // PUBLIC_ values from .env, as Kreftjs.env (kreftjs build puts them in app.js)
762
+ // PUBLIC_ values from .env, as Kreftjs.env (kreft build puts them in app.js)
763
763
  const envTag = `<script>${env.envScript(env.publicEnv())}</script>`;
764
764
  const langHelper = require('./lang.js');
765
765
  const langDirs = langHelper.findLangDirs(root);
@@ -899,7 +899,7 @@ async function devServer(args, { production = false } = {}) {
899
899
  if (cur.mtimeMs === prev.mtimeMs) return; // not a real change (the file may not exist at all)
900
900
  const before = process.env.DATABASE_URL;
901
901
  env.loadEnv(envDir);
902
- console.log(' .env changed' + (process.env.DATABASE_URL !== before ? ' (restart kreftjs dev to use the new DATABASE_URL)' : ''));
902
+ console.log(' .env changed' + (process.env.DATABASE_URL !== before ? ' (restart kreft dev to use the new DATABASE_URL)' : ''));
903
903
  clients.forEach((c) => c.write(`data: ${JSON.stringify({ type: 'reload', path: '/.env' })}\n\n`));
904
904
  });
905
905
  // files a browser must never get: the database itself, its settings and password, hidden files, locks, dumps
@@ -914,7 +914,7 @@ async function devServer(args, { production = false } = {}) {
914
914
  try { seo = await require('./backend/seo-pages.js').resolve(backendDir, urlPath, req); } catch (e) { console.log(' routes/seo.js: ' + (e && e.message || e)); }
915
915
  }
916
916
  // a crawler or link preview gets the page already drawn (and a 404 when the app shows its 404 page)
917
- if (ssr.wants(req) && (!seo || seo.status === 200) && !fs.readFileSync(file, 'utf8').includes('data-kreft-ssg')) { // a page kreftjs build --prerender already drew is sent as it is
917
+ if (ssr.wants(req) && (!seo || seo.status === 200) && !fs.readFileSync(file, 'utf8').includes('data-kreft-ssg')) { // a page kreft build --prerender already drew is sent as it is
918
918
  const page = await ssr.render(urlPath, search);
919
919
  if (page) {
920
920
  res.writeHead(page.status, { 'Content-Type': 'text/html; charset=utf-8', 'Cache-Control': isProd ? 'no-cache' : 'no-store', 'Vary': 'User-Agent', 'X-Content-Type-Options': 'nosniff', ...prodHeaders });
@@ -960,7 +960,7 @@ async function devServer(args, { production = false } = {}) {
960
960
  }
961
961
  if (urlPath.startsWith('/__kreft/npm/')) {
962
962
  const file = deps.packageFile(project, urlPath.slice('/__kreft/npm/'.length));
963
- if (!file) { res.writeHead(404, { 'Content-Type': 'text/plain; charset=utf-8' }); return res.end('Not in node_modules: ' + urlPath.slice(11) + ' (kreftjs add ' + (urlPath.slice(11).match(deps.NAME) || [''])[0] + ')'); }
963
+ if (!file) { res.writeHead(404, { 'Content-Type': 'text/plain; charset=utf-8' }); return res.end('Not in node_modules: ' + urlPath.slice(11) + ' (kreft add ' + (urlPath.slice(11).match(deps.NAME) || [''])[0] + ')'); }
964
964
  return send(res, file);
965
965
  }
966
966
  const spec = urlPath.slice('/__kreft/deps/'.length).replace(/\/$/, '');
@@ -973,7 +973,7 @@ async function devServer(args, { production = false } = {}) {
973
973
  const privateDirs = [serverDir, ...(hasBackend ? ['app', 'routes', 'database', 'config', 'storage'].map((d) => path.join(backendDir, d)) : []), path.join(root, 'config')];
974
974
  const insideServerDir = (file) => privateDirs.some((d) => file === d || file.startsWith(d + path.sep));
975
975
 
976
- // kreftjs down: storage/framework/down.json → a 503 for everyone, except with the secret (kreftjs down --secret=…)
976
+ // kreftjs down: storage/framework/down.json → a 503 for everyone, except with the secret (kreft down --secret=…)
977
977
  const downPath = path.join(backendDir, 'storage', 'framework', 'down.json');
978
978
  let downCache = { at: 0, data: null };
979
979
  const downInfo = () => {
@@ -1013,7 +1013,7 @@ async function devServer(args, { production = false } = {}) {
1013
1013
  }
1014
1014
 
1015
1015
  // DNS rebinding: a web page can make its own name (evil.example) point at 127.0.0.1 and then read everything
1016
- // kreftjs dev serves, with the browser believing it is the same site. A server that only answers this computer
1016
+ // kreft dev serves, with the browser believing it is the same site. A server that only answers this computer
1017
1017
  // therefore only answers the names of this computer (add more with KREFT_ALLOWED_HOSTS=my-tunnel.example).
1018
1018
  const hostOnly = (h) => String(h || '').toLowerCase().replace(/:\d+$/, '').replace(/^\[|\]$/g, '');
1019
1019
  const isLocalName = (n) => n === 'localhost' || n === '127.0.0.1' || n === '::1' || n.endsWith('.localhost');
@@ -1097,7 +1097,7 @@ async function devServer(args, { production = false } = {}) {
1097
1097
  }
1098
1098
  if (hot && urlPath.startsWith('/__kreft/')) return devFiles(req, res, urlPath);
1099
1099
  if (adminDir && (urlPath === '/admin' || urlPath.startsWith('/admin/'))) return adminFiles(req, res, urlPath);
1100
- // /storage/…: files on the public disk (backend/storage/app/public), connected by kreftjs storage:link.
1100
+ // /storage/…: files on the public disk (backend/storage/app/public), connected by kreft storage:link.
1101
1101
  // They are sent as downloads of plain data: an uploaded .html or .svg can't run scripts on your site.
1102
1102
  if (urlPath.startsWith('/storage/')) {
1103
1103
  const pub = path.join(backendDir, 'storage', 'app', 'public');
@@ -1185,7 +1185,7 @@ async function devServer(args, { production = false } = {}) {
1185
1185
 
1186
1186
  /* ------------------------------------------------------------------ settings: kreftjs.config.json
1187
1187
  * { "db": "sqlite:database/app.db", "tables": { "posts": true, "users": { "write": false, "hidden": ["password"] } } }
1188
- * Looked for in the folder being served, then its parents (so `kreftjs serve dist` finds the project's file).
1188
+ * Looked for in the folder being served, then its parents (so `kreft serve dist` finds the project's file).
1189
1189
  * DATABASE_URL in the environment wins over "db" — put real passwords there, not in the file.
1190
1190
  */
1191
1191
  function readConfig(start) { return require('./kreftjs-config.js').readConfig(start); }
@@ -1195,7 +1195,7 @@ function migrationsDir(...dirs) {
1195
1195
  }
1196
1196
  const describeDb = (url) => url.replace(/\/\/([^:@/]+):[^@/]*@/, '//$1:•••@');
1197
1197
 
1198
- /* ------------------------------------------------------------------ kreftjs db */
1198
+ /* ------------------------------------------------------------------ kreft db */
1199
1199
  async function dbCommand(args) {
1200
1200
  const [sub = 'help', ...rest] = args;
1201
1201
  let dbUrl = null, folder = '.', migrations = null;
@@ -1211,10 +1211,10 @@ async function dbCommand(args) {
1211
1211
  dbUrl = dbUrl || process.env.DATABASE_URL || config.db;
1212
1212
  if (sub === 'help' || !['migrate', 'seed', 'tables', 'sql'].includes(sub)) {
1213
1213
  console.log(`
1214
- kreftjs db migrate The same as kreftjs migrate
1215
- kreftjs db seed The same as kreftjs db:seed
1216
- kreftjs db tables List tables and columns
1217
- kreftjs db sql "<SQL>" Run one statement and print the result
1214
+ kreft db migrate The same as kreft migrate
1215
+ kreft db seed The same as kreft db:seed
1216
+ kreft db tables List tables and columns
1217
+ kreft db sql "<SQL>" Run one statement and print the result
1218
1218
 
1219
1219
  The database comes from --db, DATABASE_URL or "db" in kreftjs.config.json.
1220
1220
  `);
@@ -1225,7 +1225,7 @@ async function dbCommand(args) {
1225
1225
  let db;
1226
1226
  try {
1227
1227
  db = await connect(dbUrl, { root: config.dir });
1228
- if (sub === 'migrate' || sub === 'seed') { // the same as kreftjs migrate and kreftjs db:seed
1228
+ if (sub === 'migrate' || sub === 'seed') { // the same as kreft migrate and kreft db:seed
1229
1229
  await db.close(); db = null;
1230
1230
  return require('./artisan.js').commands[sub === 'migrate' ? 'migrate' : 'db:seed'](rest);
1231
1231
  } else if (sub === 'tables') {
@@ -1236,7 +1236,7 @@ async function dbCommand(args) {
1236
1236
  console.log('');
1237
1237
  } else if (sub === 'sql') {
1238
1238
  const sql = extra.join(' ');
1239
- if (!sql.trim()) { console.error(' kreftjs db sql "SELECT * FROM posts"'); process.exit(1); }
1239
+ if (!sql.trim()) { console.error(' kreft db sql "SELECT * FROM posts"'); process.exit(1); }
1240
1240
  if (/^\s*(select|with|pragma|show|describe|explain)\b/i.test(sql)) console.table(await db.query(sql));
1241
1241
  else { const r = await db.run(sql); console.log(` Done: ${r.changes} row${r.changes === 1 ? '' : 's'} changed.`); }
1242
1242
  }
@@ -1248,7 +1248,7 @@ async function dbCommand(args) {
1248
1248
  }
1249
1249
  }
1250
1250
 
1251
- /* ------------------------------------------------------------------ kreftjs dev --api db.json
1251
+ /* ------------------------------------------------------------------ kreft dev --api db.json
1252
1252
  * A small REST API for trying things out, made from a JSON file:
1253
1253
  * { "posts": [ { "id": 1, "title": "Hello" } ], "$required": { "posts": ["title"] } }
1254
1254
  *
package/bin/layout.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * Where a project's parts are.
3
3
  *
4
- * New projects (kreftjs new) keep frontend and backend apart:
4
+ * New projects (kreft new) keep frontend and backend apart:
5
5
  * frontend/ the only folder a browser can reach: index.html, pages, components, routes/web.kreftjs …
6
6
  * backend/ never served: routes/api.js, app/, database/ (and server/)
7
7
  * .env, package.json, node_modules/ at the top, next to both
package/bin/no-auth.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*
2
- * kreftjs new my-app --no-auth
2
+ * kreft new my-app --no-auth
3
3
  *
4
4
  * A new app comes with login, registration, password reset, email verification, a profile and an admin area. This takes
5
5
  * all of that out again, so the app starts as a plain site: the welcome page, the docs, the error monitor and the tests
@@ -24,7 +24,7 @@ const TO_REMOVE = [
24
24
 
25
25
  const API = (todos) => `// Your API: every address here starts with /api.
26
26
  // All API routes live directly in this file. Add your new routes here!
27
- // See them all anytime with: kreftjs route:list
27
+ // See them all anytime with: kreft route:list
28
28
  const { Route } = require('kreftjs/server')
29
29
  ${todos ? `const TodoController = require('../app/Http/Controllers/TodoController')
30
30
 
@@ -50,7 +50,7 @@ module.exports = AppServiceProvider
50
50
 
51
51
  const SEEDER = (todos) => `const { Seeder } = require('kreftjs/server')
52
52
 
53
- // kreftjs db:seed (kreftjs dev --seed fills a new database)
53
+ // kreft db:seed (kreft dev --seed fills a new database)
54
54
  class DatabaseSeeder extends Seeder {
55
55
  async run() {
56
56
  ${todos ? " await this.call(require('./TodoSeeder'))\n" : ''} }
@@ -134,7 +134,7 @@ function removeAuth(target) {
134
134
  const to = html.indexOf(" Kreftjs.app('App.kreftjs')");
135
135
  if (from >= 0 && to > from) {
136
136
  html = html.slice(0, from) + ` const router = Kreftjs.router({
137
- routes: ['routes/web.kreftjs'], // the pages are in routes/web.kreftjs; add more files: kreftjs make:routes admin
137
+ routes: ['routes/web.kreftjs'], // the pages are in routes/web.kreftjs; add more files: kreft make:routes admin
138
138
  layout: 'app', // every page goes inside layouts/app.kreftjs…
139
139
  errors: 'errors', // error pages: errors/404.kreftjs for unknown addresses, abort(403) → errors/403.kreftjs
140
140
  })
package/bin/prerender.js CHANGED
@@ -1,8 +1,8 @@
1
1
  /*
2
- * kreftjs build --prerender — saves every page of the router as ready HTML (static site generation).
2
+ * kreft build --prerender — saves every page of the router as ready HTML (static site generation).
3
3
  *
4
- * kreftjs build --prerender every route without :params
5
- * kreftjs build --prerender /users/1,/users/2 also these addresses
4
+ * kreft build --prerender every route without :params
5
+ * kreft build --prerender /users/1,/users/2 also these addresses
6
6
  *
7
7
  * Each page opens in a simulated browser (jsdom), waits until its data has loaded, and the result
8
8
  * is written to dist/<path>/index.html. Visitors and search engines get the content at once;
@@ -176,7 +176,7 @@ module.exports = async function prerender(dist, root, extra) {
176
176
  try {
177
177
  jsdom = loadJsdom(root);
178
178
  } catch (_) {
179
- throw new Error('it needs jsdom. Install it once in your project:\n\n kreftjs add -D jsdom\n');
179
+ throw new Error('it needs jsdom. Install it once in your project:\n\n kreft add -D jsdom\n');
180
180
  }
181
181
  const { JSDOM } = jsdom;
182
182
  if (typeof fetch !== 'function') throw new Error('it needs Node.js 18 or newer.');
@@ -17,7 +17,7 @@
17
17
  * Export get, post, put, patch and del (delete is a reserved word), or one `handle` for every method.
18
18
  * What you return goes back as JSON (nothing → 204). ctx.fail(status, message or { field: [...] })
19
19
  * stops with an error. ctx.res is Node's response, if you need it (stream, a file, a redirect).
20
- * kreftjs dev picks up changes to these files by itself.
20
+ * kreft dev picks up changes to these files by itself.
21
21
  */
22
22
  const fs = require('fs');
23
23
  const path = require('path');
@@ -62,7 +62,7 @@ function createServerRoutes(dir, { db = null, production = false, prefix = '/api
62
62
  return out.sort((a, b) => a.dynamic - b.dynamic); // /users/me before /users/[id]
63
63
  };
64
64
  const list = () => {
65
- // kreftjs dev looks for new files twice a second at most; kreftjs serve reads the folder once
65
+ // kreft dev looks for new files twice a second at most; kreft serve reads the folder once
66
66
  if (!scannedAt || (!production && Date.now() - scannedAt > 500)) { routes = scan(); scannedAt = Date.now(); }
67
67
  return routes;
68
68
  };
package/bin/ssr.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * Whole pages for crawlers and link previews: the server answers them with the page already drawn.
3
3
  *
4
4
  * A search engine or a chat app that does not run JavaScript would see an empty <div id="app">. For those
5
- * visitors the server opens the page in a simulated browser (the same one `kreftjs build --prerender` uses),
5
+ * visitors the server opens the page in a simulated browser (the same one `kreft build --prerender` uses),
6
6
  * waits until its data has loaded, and answers with the result. Everyone else gets the normal page.
7
7
  *
8
8
  * KREFT_SSR=bots (default) crawlers and link-preview bots only
@@ -45,7 +45,7 @@ function create({ root, origin, log = () => { }, cached = true }) {
45
45
  if (jsdom || unavailable) return jsdom;
46
46
  try { jsdom = require('./prerender.js').loadJsdom(root); } catch (_) {
47
47
  unavailable = true;
48
- if (mode !== 'off') log(' SSR for crawlers needs jsdom: kreftjs add -D jsdom (crawlers get the normal page until then)');
48
+ if (mode !== 'off') log(' SSR for crawlers needs jsdom: kreft add -D jsdom (crawlers get the normal page until then)');
49
49
  }
50
50
  return jsdom;
51
51
  }
package/bin/terminal.js CHANGED
@@ -167,7 +167,7 @@ function renderDevBanner({
167
167
  lines.push(` ${c.dim('•')} ${c.bold('Database:')} ${c.green(database)}`);
168
168
  }
169
169
  if (routesCount > 0) {
170
- lines.push(` ${c.dim('•')} ${c.bold('API:')} ${c.cyan(routesCount + ' routes')} ${c.dim('(kreftjs route:list)')}`);
170
+ lines.push(` ${c.dim('•')} ${c.bold('API:')} ${c.cyan(routesCount + ' routes')} ${c.dim('(kreft route:list)')}`);
171
171
  }
172
172
  if (serverRoutesCount > 0) {
173
173
  lines.push(` ${c.dim('•')} ${c.bold('Server:')} ${c.cyan(serverRoutesCount + ' custom endpoints')}`);
package/bin/to-ts.js CHANGED
@@ -1,4 +1,4 @@
1
- // JavaScript backend files → TypeScript (kreftjs new --ts, and kreftjs make:* in a TypeScript project):
1
+ // JavaScript backend files → TypeScript (kreft new --ts, and kreftjs make:* in a TypeScript project):
2
2
  // require → import, module.exports → export default. Inline require('./X') stays (it works at run time).
3
3
  function toTs(code) {
4
4
  return code