kreftjs 0.0.2-beta → 0.0.4-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/README.md +12 -12
  2. package/bin/add.js +14 -14
  3. package/bin/artisan-more.js +41 -41
  4. package/bin/artisan.js +41 -41
  5. package/bin/backend/command.js +1 -1
  6. package/bin/backend/factory.js +1 -1
  7. package/bin/backend/index.js +3 -3
  8. package/bin/backend/model.js +2 -2
  9. package/bin/backend/notifications.js +1 -1
  10. package/bin/backend/queue.js +2 -2
  11. package/bin/backend/schedule.js +2 -2
  12. package/bin/backend/seo-pages.js +1 -1
  13. package/bin/backend/storage.js +1 -1
  14. package/bin/backend/support.js +4 -4
  15. package/bin/backend/typescript.js +1 -1
  16. package/bin/build.js +11 -11
  17. package/bin/db-api.js +3 -3
  18. package/bin/db.js +1 -1
  19. package/bin/deps.js +6 -6
  20. package/bin/electron.js +12 -12
  21. package/bin/env.js +2 -2
  22. package/bin/guard.js +2 -2
  23. package/bin/kreftjs-config.js +1 -1
  24. package/bin/kreftjs.js +105 -109
  25. package/bin/layout.js +1 -1
  26. package/bin/no-auth.js +4 -4
  27. package/bin/prerender.js +4 -4
  28. package/bin/server-routes.js +2 -2
  29. package/bin/ssr.js +2 -2
  30. package/bin/terminal.js +1 -1
  31. package/bin/to-ts.js +1 -1
  32. package/bin/update.js +17 -17
  33. package/bin/urls-file.js +1 -1
  34. package/bin/vite.js +11 -11
  35. package/bin/win-spawn.js +39 -0
  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 +3 -4
  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
  */
@@ -35,10 +35,6 @@ if (require.main === module && (process.argv.includes('--gc') || process.env.AUT
35
35
  }
36
36
 
37
37
  const rawArgs = process.argv.slice(2).filter((a) => a !== '--gc');
38
- // `som` (and `somjs`) still run this file, so an existing global install keeps working
39
- if (require.main === module && /^(som|somjs)(\.cmd|\.js)?$/i.test(path.basename(process.argv[1] || ''))) {
40
- console.error(' The "som" command is now "kreftjs" (Som.js is now Kreft). "som" still works for now: use "kreftjs" from here on.');
41
- }
42
38
  const [command = 'help', ...rest] = rawArgs;
43
39
 
44
40
  const commands = {
@@ -75,7 +71,7 @@ guard.checkStart(command);
75
71
  if (['queue:work', 'queue:start', 'schedule:work'].includes(command)) guard.watch([process.cwd()]);
76
72
  if (commands[command]) commands[command](rest);
77
73
  else if (command && !command.startsWith('-')) {
78
- // your own commands: app/Console/Commands (kreftjs make:command SendReport)
74
+ // your own commands: app/Console/Commands (kreft make:command SendReport)
79
75
  require('./artisan-more.js').runCustom(command, rest).then((found) => { if (!found) unknown(); }, (e) => { console.error(' ' + (e.stack || e)); process.exitCode = 1; });
80
76
  } else unknown();
81
77
 
@@ -85,7 +81,7 @@ function help() {
85
81
  Kreft ${pkg.version}
86
82
 
87
83
  Usage:
88
- 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,
89
85
  password reset, email verification and profile pages (on SQLite)
90
86
  --db <kind> …on another database (sqlite, mysql or postgres), plus a Todos example
91
87
  --no-auth …without login, register, profile and users (--auth: with them, the default)
@@ -95,7 +91,7 @@ function help() {
95
91
  --js …use JavaScript (default when non-interactive)
96
92
  --electron …with Electron desktop app support (main.js, preload.js, packaging)
97
93
  --vite …with Vite.js bundling & instant HMR (vite.config.js, npm run vite)
98
- kreftjs dev [folder] Start the dev server (default: this folder)
94
+ kreft dev [folder] Start the dev server (default: this folder)
99
95
  --port <number> Port to use (default: 8000, or the next free one)
100
96
  --host <address> Who may open it (default: 127.0.0.1, only this computer; 0.0.0.0: your network)
101
97
  --api <file.json> Serve a REST API from a JSON file at /api (GET, POST, PUT, PATCH, DELETE)
@@ -108,83 +104,83 @@ function help() {
108
104
  --server <dir> Your own Node.js code for /api (default: server/): server/hello.js → /api/hello
109
105
  --db <database> Serve the tables of a database at /api (new migrations run first):
110
106
  sqlite:database/app.db (built in, nothing to install)
111
- mysql://user:pass@localhost:3306/shop (kreftjs add mysql2)
112
- postgres://user:pass@localhost:5432/shop (kreftjs add pg)
113
- 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;
114
110
  only the tables listed in kreftjs.config.json are served
115
111
 
116
112
  Bundler & Dev Server (Vite.js):
117
- kreftjs vite Start Vite dev server and proxy backend API (alias: kreftjs vite:dev)
118
- kreftjs vite:dev Start Vite dev server with instant HMR and backend proxy
119
- kreftjs vite:build Build production bundle with Vite and Rollup
120
- kreftjs vite:preview Preview production build locally with Vite
121
- 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)
122
118
 
123
119
  Desktop (Electron.js):
124
- kreftjs electron Start dev server and launch desktop window (alias: kreftjs electron:dev)
125
- kreftjs electron:dev Start dev server and launch desktop window
126
- kreftjs electron:build Build static bundle and package desktop app with electron-builder
127
- kreftjs electron:init Add Electron support to an existing project (alias: kreftjs make:electron)
128
-
129
- The backend (kreftjs list shows every command, yours too):
130
- kreftjs key:generate Set the application encryption key in .env (--show: print only)
131
- kreftjs migrate Run new migrations in database/migrations (.js or .sql)
132
- kreftjs migrate:rollback Undo the last batch of migrations (--step 2: the last two)
133
- kreftjs migrate:fresh Drop every table and migrate again (--seed: then seed)
134
- kreftjs migrate:status Which migrations ran
135
- kreftjs db:seed Run database/seeders/DatabaseSeeder.js (--class PostSeeder: another one)
136
- kreftjs route:list The routes in routes/api.js
137
- kreftjs storage:link Connect public/storage to storage/app/public (--force) (alias: kreftjs link:storage)
138
- kreftjs storage:unlink Remove the storage link (alias: kreftjs unlink:storage)
139
- kreftjs sitemap Generate public/sitemap.xml and robots.txt
140
- kreftjs log Tail recent log entries from storage/logs/kreft.log (--lines 50, --level error)
141
- kreftjs log:clear Clear the log file
142
- kreftjs make:model Post app/Models/Post.js (-m -f -s -c -p -r, --route=file, --auth, --all)
143
- kreftjs make:controller PostController (--api, --model Post, -r, --route=file, --auth)
144
- kreftjs make:request StorePostRequest app/Http/Requests/StorePostRequest.js (--model Post)
145
- kreftjs make:resource PostResource app/Http/Resources/PostResource.js
146
- kreftjs make:rule Uppercase app/Rules/Uppercase.js
147
- kreftjs make:page Post frontend/pages/Post.kreftjs (--model Post, -r, --route=file, --auth)
148
- kreftjs make:factory PostFactory database/factories/PostFactory.js (--model Post)
149
- kreftjs make:migration create_posts_table
150
- kreftjs make:seeder PostSeeder
151
- kreftjs make:middleware EnsureIsAdmin
152
- kreftjs make:job SendWelcomeEmail app/Jobs/SendWelcomeEmail.js
153
- kreftjs make:event OrderShipped app/Events/OrderShipped.js
154
- kreftjs make:listener SendShipmentNotice app/Listeners/SendShipmentNotice.js (--event OrderShipped)
155
- kreftjs make:mail WelcomeMail app/Mail/WelcomeMail.js
156
- kreftjs make:notification InvoicePaid app/Notifications/InvoicePaid.js
157
- kreftjs make:policy PostPolicy app/Policies/PostPolicy.js (--model Post)
158
- kreftjs make:observer PostObserver app/Observers/PostObserver.js (--model Post)
159
- kreftjs make:command SendReport app/Console/Commands/SendReport.js (--command report:send)
160
- kreftjs make:errors The error pages in errors/ (401, 403, 404, 419, 429, 500, 503…)
161
- kreftjs make:admin <email> Let that user open the admin panel at /admin (--remove: take it away)
162
- kreftjs make:routes admin A new route file for pages: frontend/routes/admin.kreftjs (--api: backend/routes/admin.js)
163
- kreftjs db tables List tables and columns
164
- kreftjs db sql "<SQL>" Run one SQL statement and print the result
165
- 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)
166
162
  --out <folder> Where to write it (default: dist)
167
163
  --base <path> Change the <base href> (for example /)
168
164
  --prerender [paths] Also save every page as ready HTML (needs: npm i -D jsdom)
169
165
  --include <folder> Also copy this folder into the output (for example docs)
170
- 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)
171
167
  -D, --dev Install as devDependency
172
168
  -y, --yes Auto-confirm unverified community packages in CI/CD
173
169
  --dry-run, --check Inspect package security report without installing
174
170
  --allow-scripts Permit postinstall lifecycle scripts (default: sandboxed with --ignore-scripts)
175
171
  --force Bypass redundancy blocks, typosquat traps and security warnings
176
- 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
177
173
  --latest Upgrade packages to their latest versions
178
174
  --check Check for outdated packages (npm outdated)
179
175
  --core Update only Kreft runtime files (kreftjs.js, kreftjs.d.ts, server.d.ts)
180
176
  --npm Update only npm dependencies
181
- 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)
182
178
 
183
179
  Examples:
184
- kreftjs new shop
180
+ kreft new shop
185
181
  cd shop
186
182
  npm run dev
187
- kreftjs update
183
+ kreft update
188
184
  npm run build
189
185
  `);
190
186
  }
@@ -195,7 +191,7 @@ function unknown() {
195
191
  process.exit(1);
196
192
  }
197
193
 
198
- /* ------------------------------------------------------------------ kreftjs new */
194
+ /* ------------------------------------------------------------------ kreft new */
199
195
  async function createProject(args) {
200
196
  let name = null, dbKind = null, ui = null, ts = false, langChosen = false, electron = false, vite = false, redis = false, auth = true, authChosen = false;
201
197
  for (let i = 0; i < args.length; i++) {
@@ -221,7 +217,7 @@ async function createProject(args) {
221
217
  process.exit(1);
222
218
  }
223
219
  if (!name) {
224
- 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)');
225
221
  process.exit(1);
226
222
  }
227
223
  const target = path.resolve(name);
@@ -268,8 +264,8 @@ async function createProject(args) {
268
264
  version: '0.1.0',
269
265
  private: true,
270
266
  scripts: {
271
- dev: 'kreftjs dev --seed', start: 'kreftjs dev --seed', build: 'kreftjs build', preview: 'kreftjs dev dist', serve: 'kreftjs serve dist',
272
- 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',
273
269
  },
274
270
  };
275
271
  // .env: the project's own settings (from .env.example, with its name filled in)
@@ -302,7 +298,7 @@ async function createProject(args) {
302
298
  Created ${name}/
303
299
 
304
300
  Next:
305
- 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)' : ''}
306
302
  npm run dev
307
303
 
308
304
  ${auth ? ` Then log in as test@example.com with the password "password", or register.
@@ -310,7 +306,7 @@ ${auth ? ` Then log in as test@example.com with the password "password", or reg
310
306
  ` : ' Created without authentication (--no-auth): there is no login, registration or users table.\n'}`);
311
307
  }
312
308
 
313
- // 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
314
310
  function toTypeScript(target, projectPkg) {
315
311
  const { toTs, TSCONFIG } = require('./to-ts.js');
316
312
  const walk = (dir) => {
@@ -345,7 +341,7 @@ export interface ApiList<T> {
345
341
  // a typed helper for the frontend, used like any module: import { money } from '../logic/format.ts'
346
342
  fs.mkdirSync(path.join(target, 'frontend', 'logic'), { recursive: true });
347
343
  fs.writeFileSync(path.join(target, 'frontend', 'logic', 'format.ts'), `// A TypeScript module for the pages: import { money, ago } from '../logic/format.ts'
348
- // 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
349
345
 
350
346
  export function money(amount: number, currency: string = 'USD'): string {
351
347
  return new Intl.NumberFormat('en', { style: 'currency', currency }).format(amount)
@@ -392,7 +388,7 @@ button { font-variant-numeric: tabular-nums; justify-self: start; }
392
388
  }
393
389
  }
394
390
 
395
- // 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
396
392
  function uiKits() { return {
397
393
  tailwind: ['<!-- Tailwind CSS: use its classes in any .kreftjs file -->', '<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>'],
398
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>'],
@@ -415,14 +411,14 @@ function addUiKit(target, ui) {
415
411
  fs.writeFileSync(file, updated);
416
412
  }
417
413
 
418
- // 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
419
415
  function addDatabase(target, kind, projectName) {
420
416
  const back = path.join(target, 'backend'), front = path.join(target, 'frontend');
421
417
  const file = (rel, text) => { fs.mkdirSync(path.dirname(path.join(back, rel)), { recursive: true }); fs.writeFileSync(path.join(back, rel), text); };
422
418
  const d = new Date(), p2 = (n) => String(n).padStart(2, '0');
423
419
  const stamp = `${d.getFullYear()}_${p2(d.getMonth() + 1)}_${p2(d.getDate())}_000001`;
424
420
  // A migration, a model, a controller, a seeder and a route
425
- 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().
426
422
  module.exports = {
427
423
  up(schema) {
428
424
  schema.create('todos', (table) => {
@@ -488,7 +484,7 @@ module.exports = TodoController
488
484
  file('database/seeders/TodoSeeder.js', `const { Seeder } = require('kreftjs/server')
489
485
  const Todo = require('../../app/Models/Todo')
490
486
 
491
- // 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)
492
488
  class TodoSeeder extends Seeder {
493
489
  async run() {
494
490
  await Todo.create({ title: 'Learn Kreft', done: true })
@@ -583,7 +579,7 @@ function copyFolder(from, to) {
583
579
  }
584
580
  }
585
581
 
586
- /* ------------------------------------------------------------------ kreftjs vscode */
582
+ /* ------------------------------------------------------------------ kreft vscode */
587
583
  function installVscode() {
588
584
  const os = require('os');
589
585
  const from = path.join(__dirname, '..', 'editors', 'vscode');
@@ -613,12 +609,12 @@ function installVscode() {
613
609
  console.log('\n Restart VS Code (or run "Reload Window") to see updated colors and formatting in .kreftjs files.\n');
614
610
  }
615
611
 
616
- /* ------------------------------------------------------------------ kreftjs dev */
612
+ /* ------------------------------------------------------------------ kreft dev */
617
613
  async function devServer(args, { production = false } = {}) {
618
614
  const isProd = Boolean(production || process.env.APP_ENV === 'production' || process.env.NODE_ENV === 'production');
619
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;
620
- // kreftjs dev only answers this computer; --host 0.0.0.0 shares it on your network.
621
- // 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).
622
618
  let host = production ? process.env.HOST || '0.0.0.0' : '127.0.0.1';
623
619
  for (let i = 0; i < args.length; i++) {
624
620
  if (args[i] === '--port' || args[i] === '-p') port = Number(args[++i]) || port;
@@ -639,7 +635,7 @@ async function devServer(args, { production = false } = {}) {
639
635
  const lay = require('./layout.js').layout(folder === 'dist' || folder === '.' ? '.' : folder);
640
636
  const root = !production && folder === '.' ? lay.frontend : path.resolve(folder);
641
637
  if (production && !fs.existsSync(root)) {
642
- console.error(` Nothing to serve in ${root}. Build first: kreftjs build`);
638
+ console.error(` Nothing to serve in ${root}. Build first: kreft build`);
643
639
  process.exit(1);
644
640
  }
645
641
  const mockApi = apiFile && !production ? createMockApi(path.resolve(apiFile), delay, saveApi) : null;
@@ -658,7 +654,7 @@ async function devServer(args, { production = false } = {}) {
658
654
  const hasBackend = Boolean(apiRoutesFile);
659
655
  // kreftjs serve: the backend must not sit inside the folder that is served, or its files could be downloaded
660
656
  if (production && hasBackend && (backendDir === root || backendDir.startsWith(root + path.sep))) {
661
- 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`);
662
658
  process.exit(1);
663
659
  }
664
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.');
@@ -668,7 +664,7 @@ async function devServer(args, { production = false } = {}) {
668
664
  const { createDbApi } = require('./db-api.js');
669
665
  try {
670
666
  db = await connect(dbUrl, { root: config.dir });
671
- 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`
672
668
  const { migrator, installAlias } = require('./backend/index.js');
673
669
  installAlias(); // require('kreftjs/server') and .ts files work in migrations and seeders
674
670
  require('./backend/model.js').setBaseDir(backendDir);
@@ -697,7 +693,7 @@ async function devServer(args, { production = false } = {}) {
697
693
  const n = backend.routes().length;
698
694
  backendRoutesCount = n;
699
695
  // queued jobs, mails and notifications run in the background here, and routes/console.js runs on schedule
700
- // (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)
701
697
  if (db) {
702
698
  const queue = require('./backend/queue.js');
703
699
  const queues = String(process.env.QUEUE_NAMES || 'high,default,low').split(',').map((x) => x.trim());
@@ -713,7 +709,7 @@ async function devServer(args, { production = false } = {}) {
713
709
  }
714
710
  if (process.env.SCHEDULER !== 'off') require('./backend/schedule.js').startScheduler(backendDir);
715
711
  }
716
- 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)`;
717
713
  }
718
714
 
719
715
  // ----- your own server code: server/hello.js → /api/hello (any Node.js package can be used there)
@@ -730,7 +726,7 @@ async function devServer(args, { production = false } = {}) {
730
726
  console.error(` --server: ${serverFolder} does not exist.`);
731
727
  process.exit(1);
732
728
  }
733
- // 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)
734
730
  const npmMap = () => (production ? null : deps.importMap(project));
735
731
 
736
732
  const types = {
@@ -743,7 +739,7 @@ async function devServer(args, { production = false } = {}) {
743
739
 
744
740
  const prodHeaders = isProd ? { 'Referrer-Policy': 'same-origin', 'X-Frame-Options': 'SAMEORIGIN', 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains; preload' } : {};
745
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
746
- // 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)
747
743
  if (!production && /\.(m|c)?ts$/i.test(file) && !file.endsWith('.d.ts')) {
748
744
  const { transpileTs } = require('./backend/typescript.js');
749
745
  res.writeHead(200, { 'Content-Type': 'text/javascript; charset=utf-8', 'Cache-Control': 'no-store', 'X-Content-Type-Options': 'nosniff' });
@@ -763,7 +759,7 @@ async function devServer(args, { production = false } = {}) {
763
759
  });
764
760
  if (!production && type === 'text/html') {
765
761
  let html = fs.readFileSync(file, 'utf8');
766
- // 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)
767
763
  const envTag = `<script>${env.envScript(env.publicEnv())}</script>`;
768
764
  const langHelper = require('./lang.js');
769
765
  const langDirs = langHelper.findLangDirs(root);
@@ -903,7 +899,7 @@ async function devServer(args, { production = false } = {}) {
903
899
  if (cur.mtimeMs === prev.mtimeMs) return; // not a real change (the file may not exist at all)
904
900
  const before = process.env.DATABASE_URL;
905
901
  env.loadEnv(envDir);
906
- 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)' : ''));
907
903
  clients.forEach((c) => c.write(`data: ${JSON.stringify({ type: 'reload', path: '/.env' })}\n\n`));
908
904
  });
909
905
  // files a browser must never get: the database itself, its settings and password, hidden files, locks, dumps
@@ -918,7 +914,7 @@ async function devServer(args, { production = false } = {}) {
918
914
  try { seo = await require('./backend/seo-pages.js').resolve(backendDir, urlPath, req); } catch (e) { console.log(' routes/seo.js: ' + (e && e.message || e)); }
919
915
  }
920
916
  // a crawler or link preview gets the page already drawn (and a 404 when the app shows its 404 page)
921
- 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
922
918
  const page = await ssr.render(urlPath, search);
923
919
  if (page) {
924
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 });
@@ -964,7 +960,7 @@ async function devServer(args, { production = false } = {}) {
964
960
  }
965
961
  if (urlPath.startsWith('/__kreft/npm/')) {
966
962
  const file = deps.packageFile(project, urlPath.slice('/__kreft/npm/'.length));
967
- 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] + ')'); }
968
964
  return send(res, file);
969
965
  }
970
966
  const spec = urlPath.slice('/__kreft/deps/'.length).replace(/\/$/, '');
@@ -977,7 +973,7 @@ async function devServer(args, { production = false } = {}) {
977
973
  const privateDirs = [serverDir, ...(hasBackend ? ['app', 'routes', 'database', 'config', 'storage'].map((d) => path.join(backendDir, d)) : []), path.join(root, 'config')];
978
974
  const insideServerDir = (file) => privateDirs.some((d) => file === d || file.startsWith(d + path.sep));
979
975
 
980
- // 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=…)
981
977
  const downPath = path.join(backendDir, 'storage', 'framework', 'down.json');
982
978
  let downCache = { at: 0, data: null };
983
979
  const downInfo = () => {
@@ -1017,7 +1013,7 @@ async function devServer(args, { production = false } = {}) {
1017
1013
  }
1018
1014
 
1019
1015
  // DNS rebinding: a web page can make its own name (evil.example) point at 127.0.0.1 and then read everything
1020
- // 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
1021
1017
  // therefore only answers the names of this computer (add more with KREFT_ALLOWED_HOSTS=my-tunnel.example).
1022
1018
  const hostOnly = (h) => String(h || '').toLowerCase().replace(/:\d+$/, '').replace(/^\[|\]$/g, '');
1023
1019
  const isLocalName = (n) => n === 'localhost' || n === '127.0.0.1' || n === '::1' || n.endsWith('.localhost');
@@ -1101,7 +1097,7 @@ async function devServer(args, { production = false } = {}) {
1101
1097
  }
1102
1098
  if (hot && urlPath.startsWith('/__kreft/')) return devFiles(req, res, urlPath);
1103
1099
  if (adminDir && (urlPath === '/admin' || urlPath.startsWith('/admin/'))) return adminFiles(req, res, urlPath);
1104
- // /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.
1105
1101
  // They are sent as downloads of plain data: an uploaded .html or .svg can't run scripts on your site.
1106
1102
  if (urlPath.startsWith('/storage/')) {
1107
1103
  const pub = path.join(backendDir, 'storage', 'app', 'public');
@@ -1189,7 +1185,7 @@ async function devServer(args, { production = false } = {}) {
1189
1185
 
1190
1186
  /* ------------------------------------------------------------------ settings: kreftjs.config.json
1191
1187
  * { "db": "sqlite:database/app.db", "tables": { "posts": true, "users": { "write": false, "hidden": ["password"] } } }
1192
- * 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).
1193
1189
  * DATABASE_URL in the environment wins over "db" — put real passwords there, not in the file.
1194
1190
  */
1195
1191
  function readConfig(start) { return require('./kreftjs-config.js').readConfig(start); }
@@ -1199,7 +1195,7 @@ function migrationsDir(...dirs) {
1199
1195
  }
1200
1196
  const describeDb = (url) => url.replace(/\/\/([^:@/]+):[^@/]*@/, '//$1:•••@');
1201
1197
 
1202
- /* ------------------------------------------------------------------ kreftjs db */
1198
+ /* ------------------------------------------------------------------ kreft db */
1203
1199
  async function dbCommand(args) {
1204
1200
  const [sub = 'help', ...rest] = args;
1205
1201
  let dbUrl = null, folder = '.', migrations = null;
@@ -1215,10 +1211,10 @@ async function dbCommand(args) {
1215
1211
  dbUrl = dbUrl || process.env.DATABASE_URL || config.db;
1216
1212
  if (sub === 'help' || !['migrate', 'seed', 'tables', 'sql'].includes(sub)) {
1217
1213
  console.log(`
1218
- kreftjs db migrate The same as kreftjs migrate
1219
- kreftjs db seed The same as kreftjs db:seed
1220
- kreftjs db tables List tables and columns
1221
- 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
1222
1218
 
1223
1219
  The database comes from --db, DATABASE_URL or "db" in kreftjs.config.json.
1224
1220
  `);
@@ -1229,7 +1225,7 @@ async function dbCommand(args) {
1229
1225
  let db;
1230
1226
  try {
1231
1227
  db = await connect(dbUrl, { root: config.dir });
1232
- 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
1233
1229
  await db.close(); db = null;
1234
1230
  return require('./artisan.js').commands[sub === 'migrate' ? 'migrate' : 'db:seed'](rest);
1235
1231
  } else if (sub === 'tables') {
@@ -1240,7 +1236,7 @@ async function dbCommand(args) {
1240
1236
  console.log('');
1241
1237
  } else if (sub === 'sql') {
1242
1238
  const sql = extra.join(' ');
1243
- 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); }
1244
1240
  if (/^\s*(select|with|pragma|show|describe|explain)\b/i.test(sql)) console.table(await db.query(sql));
1245
1241
  else { const r = await db.run(sql); console.log(` Done: ${r.changes} row${r.changes === 1 ? '' : 's'} changed.`); }
1246
1242
  }
@@ -1252,7 +1248,7 @@ async function dbCommand(args) {
1252
1248
  }
1253
1249
  }
1254
1250
 
1255
- /* ------------------------------------------------------------------ kreftjs dev --api db.json
1251
+ /* ------------------------------------------------------------------ kreft dev --api db.json
1256
1252
  * A small REST API for trying things out, made from a JSON file:
1257
1253
  * { "posts": [ { "id": 1, "title": "Hello" } ], "$required": { "posts": ["title"] } }
1258
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