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/artisan.js CHANGED
@@ -1,19 +1,19 @@
1
1
  /*
2
2
  * The backend commands:
3
3
  *
4
- * kreftjs migrate run new migrations
5
- * kreftjs migrate:rollback [--step 2] undo the last batch (or the last 2 migrations)
6
- * kreftjs migrate:fresh [--seed] drop every table, migrate again (and seed)
7
- * kreftjs migrate:status which migrations ran
8
- * kreftjs db:seed [--class PostSeeder] run database/seeders/DatabaseSeeder.js (or another seeder)
9
- * kreftjs route:list the routes in routes/api.js
10
- * kreftjs make:model Post [-m -f -s -c -p -r] [--route=file] [--auth] [--all]
11
- * kreftjs make:controller PostController [--api] [--model Post] [--route=file] [--auth]
12
- * kreftjs make:page Post [--model Post] [--route=file] [--auth]
13
- * kreftjs make:migration create_posts_table
14
- * kreftjs make:seeder PostSeeder
15
- * kreftjs make:factory PostFactory
16
- * kreftjs make:middleware EnsureIsAdmin
4
+ * kreft migrate run new migrations
5
+ * kreft migrate:rollback [--step 2] undo the last batch (or the last 2 migrations)
6
+ * kreft migrate:fresh [--seed] drop every table, migrate again (and seed)
7
+ * kreft migrate:status which migrations ran
8
+ * kreft db:seed [--class PostSeeder] run database/seeders/DatabaseSeeder.js (or another seeder)
9
+ * kreft route:list the routes in routes/api.js
10
+ * kreft make:model Post [-m -f -s -c -p -r] [--route=file] [--auth] [--all]
11
+ * kreft make:controller PostController [--api] [--model Post] [--route=file] [--auth]
12
+ * kreft make:page Post [--model Post] [--route=file] [--auth]
13
+ * kreft make:migration create_posts_table
14
+ * kreft make:seeder PostSeeder
15
+ * kreft make:factory PostFactory
16
+ * kreft make:middleware EnsureIsAdmin
17
17
  *
18
18
  * Every command takes --db <url> (or DATABASE_URL in .env) and --backend <folder> (default: the project).
19
19
  */
@@ -168,13 +168,13 @@ async function runSeed(db, b, ctx, className) {
168
168
  // an older project: database/seed.sql
169
169
  const sql = path.join(ctx.base, 'database', 'seed.sql');
170
170
  if (!className && fs.existsSync(sql)) { await db.exec(fs.readFileSync(sql, 'utf8')); return console.log(' Seeded from database/seed.sql'); }
171
- console.log(` No database/seeders/${className || 'DatabaseSeeder'}.js. Make one with: kreftjs make:seeder ${className || 'DatabaseSeeder'}`);
171
+ console.log(` No database/seeders/${className || 'DatabaseSeeder'}.js. Make one with: kreft make:seeder ${className || 'DatabaseSeeder'}`);
172
172
  }
173
173
 
174
174
  /* ------------------------------------------------------------------ make:… */
175
175
  const pascal = (s) => s.replace(/(^|[-_\s])(\w)/g, (_, __, c) => c.toUpperCase()).replace(/[^\w]/g, '');
176
176
  // 'User/ProfileController', 'user\\profile-controller' or 'User.ProfileController' → { dirs: ['User'], name: 'ProfileController' }
177
- // (folders are made when they don't exist yet, e.g. kreftjs make:controller User/ProfileController)
177
+ // (folders are made when they don't exist yet, e.g. kreft make:controller User/ProfileController)
178
178
  function nested(raw) {
179
179
  const parts = String(raw || '').split(/[\\/]+/).map((p) => pascal(p)).filter(Boolean);
180
180
  const name = parts.pop() || '';
@@ -298,7 +298,7 @@ module.exports = ${name}
298
298
  migration: (name) => {
299
299
  const create = name.match(/^create_(\w+?)_table$/);
300
300
  const change = name.match(/^\w+_(?:to|from|in)_(\w+?)_table$/);
301
- if (create) return `// kreftjs migrate runs up(); kreftjs migrate:rollback runs down()
301
+ if (create) return `// kreft migrate runs up(); kreft migrate:rollback runs down()
302
302
  module.exports = {
303
303
  up(schema) {
304
304
  schema.create('${create[1]}', (table) => {
@@ -313,7 +313,7 @@ module.exports = {
313
313
  }
314
314
  `;
315
315
  const t = change ? change[1] : 'table_name';
316
- return `// kreftjs migrate runs up(); kreftjs migrate:rollback runs down()
316
+ return `// kreft migrate runs up(); kreft migrate:rollback runs down()
317
317
  module.exports = {
318
318
  up(schema) {
319
319
  schema.table('${t}', (table) => {
@@ -331,7 +331,7 @@ module.exports = {
331
331
  },
332
332
  seeder: (name, model, modelReq) => `const { Seeder, DB } = require('kreftjs/server')
333
333
  ${model ? `const ${model} = require('${modelReq || '../../app/Models/' + model}')\n` : ''}
334
- // kreftjs db:seed --class ${name} (or this.call(${name}) from DatabaseSeeder)
334
+ // kreft db:seed --class ${name} (or this.call(${name}) from DatabaseSeeder)
335
335
  class ${name} extends Seeder {
336
336
  async run() {
337
337
  ${model ? ` // await ${model}.factory().count(10).create()\n // await ${model}.create({ … })\n` : name === 'DatabaseSeeder' ? ' // await this.call([UserSeeder, PostSeeder])\n' : " // await DB.table('posts').insert({ … })\n"} }
@@ -1186,15 +1186,15 @@ const make = {
1186
1186
  model(args) {
1187
1187
  const o = options(args), ctx = context(o);
1188
1188
  let { dirs, name, rel } = nested(o._[0]);
1189
- if (!name) return console.error(' kreftjs make:model Post [-m -f -s -c -p -r] [--route=file] [--auth] [--all] [--folder=Admin] (Shop/Product: app/Models/Shop/Product.js)');
1189
+ if (!name) return console.error(' kreft make:model Post [-m -f -s -c -p -r] [--route=file] [--auth] [--all] [--folder=Admin] (Shop/Product: app/Models/Shop/Product.js)');
1190
1190
  const all = o.flags.has('a') || o.flags.has('all');
1191
1191
  const auth = o.flags.has('auth');
1192
1192
  const hasRoute = all || o.flags.has('r') || o.flags.has('route') || Boolean(o.route);
1193
1193
 
1194
1194
  // Support placing all auxiliary files (controllers, pages, routes) in a specific folder [except model]:
1195
- // e.g. kreftjs make:model Post --all --folder=Admin
1196
- // kreftjs make:model Post --all Admin
1197
- // kreftjs make:model Admin/Post --all --flat-model
1195
+ // e.g. kreft make:model Post --all --folder=Admin
1196
+ // kreft make:model Post --all Admin
1197
+ // kreft make:model Admin/Post --all --flat-model
1198
1198
  const targetFolder = o.folder || o.subfolder || o['in'] || o.group || o.path || (o._[1] && !o._[1].startsWith('-') ? o._[1] : null);
1199
1199
  const flatModel = o.flags.has('flat-model') || o.flags.has('except-model') || o.flags.has('no-model-dir') || Boolean(targetFolder);
1200
1200
 
@@ -1222,7 +1222,7 @@ const make = {
1222
1222
  controller(args) {
1223
1223
  const o = options(args), ctx = context(o);
1224
1224
  let { dirs, name } = nested(o._[0]);
1225
- if (!name) return console.error(' kreftjs make:controller PostController [--api] [--model Post] [--route=file] [--auth]');
1225
+ if (!name) return console.error(' kreft make:controller PostController [--api] [--model Post] [--route=file] [--auth]');
1226
1226
  if (!/Controller$/.test(name)) name += 'Controller';
1227
1227
  const m = o.model ? nested(o.model) : o.flags.has('api') || o.flags.has('resource') ? { dirs: [], name: name.replace(/Controller$/, '') } : null;
1228
1228
  const model = m ? m.name : null;
@@ -1250,7 +1250,7 @@ const make = {
1250
1250
  page(args) {
1251
1251
  const o = options(args), ctx = context(o);
1252
1252
  let { dirs, name } = nested(o._[0]);
1253
- if (!name) return console.error(' kreftjs make:page Post [--model Post] [--route=file] [--auth]');
1253
+ if (!name) return console.error(' kreft make:page Post [--model Post] [--route=file] [--auth]');
1254
1254
  const m = o.model ? nested(o.model) : { dirs, name };
1255
1255
  const modelDirs = m.dirs && m.dirs.length ? m.dirs : dirs;
1256
1256
  const endpoint = [...(modelDirs.length ? modelDirs.map((d) => snake(d).replace(/_/g, '-')) : []), plural(snake(m.name)).replace(/_/g, '-')].join('/');
@@ -1270,7 +1270,7 @@ const make = {
1270
1270
  factory(args) {
1271
1271
  const o = options(args), ctx = context(o);
1272
1272
  let { dirs, name } = nested(o._[0]);
1273
- if (!name) return console.error(' kreftjs make:factory PostFactory [--model Post]');
1273
+ if (!name) return console.error(' kreft make:factory PostFactory [--model Post]');
1274
1274
  if (!name.endsWith('Factory')) name += 'Factory';
1275
1275
  const m = o.model ? nested(o.model) : { dirs: [], name: name.replace(/Factory$/, '') };
1276
1276
  const modelReq = '../../app/Models/' + [...m.dirs, m.name].join('/');
@@ -1279,14 +1279,14 @@ const make = {
1279
1279
  migration(args) {
1280
1280
  const o = options(args), ctx = context(o);
1281
1281
  const name = snake(o._[0] || '').replace(/[^a-z0-9_]/g, '_');
1282
- if (!name) return console.error(' kreftjs make:migration create_posts_table');
1282
+ if (!name) return console.error(' kreft make:migration create_posts_table');
1283
1283
  const dir = migrationsOf(o, ctx);
1284
1284
  write(path.join(dir, `${nextStamp(dir)}_${name}.js`), stubs.migration(name));
1285
1285
  },
1286
1286
  seeder(args) {
1287
1287
  const o = options(args), ctx = context(o);
1288
1288
  let { dirs, name } = nested(o._[0]);
1289
- if (!name) return console.error(' kreftjs make:seeder PostSeeder');
1289
+ if (!name) return console.error(' kreft make:seeder PostSeeder');
1290
1290
  if (!/Seeder$/.test(name)) name += 'Seeder';
1291
1291
  const m = o.model ? nested(o.model) : null;
1292
1292
  const modelReq = m ? up(2 + dirs.length) + ['app', 'Models', ...m.dirs, m.name].join('/') : null;
@@ -1295,14 +1295,14 @@ const make = {
1295
1295
  middleware(args) {
1296
1296
  const o = options(args), ctx = context(o);
1297
1297
  const { dirs, name } = nested(o._[0]);
1298
- if (!name) return console.error(' kreftjs make:middleware EnsureIsAdmin');
1298
+ if (!name) return console.error(' kreft make:middleware EnsureIsAdmin');
1299
1299
  write(path.join(ctx.base, 'app', 'Http', 'Middleware', ...dirs, name + '.js'), stubs.middleware(name));
1300
1300
  if (dirs.length) console.log(dim(` In a folder, give it a name in app/Http/Kernel.js: aliases: { '${snake(name).replace(/_/g, '-')}': 'Middleware/${[...dirs, name].join('/')}.js' }`));
1301
1301
  },
1302
1302
  request(args) {
1303
1303
  const o = options(args), ctx = context(o);
1304
1304
  let { dirs, name } = nested(o._[0]);
1305
- if (!name) return console.error(' kreftjs make:request StorePostRequest [--model Post]');
1305
+ if (!name) return console.error(' kreft make:request StorePostRequest [--model Post]');
1306
1306
  if (!/Request$/.test(name)) name += 'Request';
1307
1307
  const reqDir = path.join(ctx.base, 'app', 'Http', 'Requests');
1308
1308
  if (!fs.existsSync(reqDir)) fs.mkdirSync(reqDir, { recursive: true });
@@ -1317,7 +1317,7 @@ const make = {
1317
1317
  resource(args) {
1318
1318
  const o = options(args), ctx = context(o);
1319
1319
  let { dirs, name } = nested(o._[0]);
1320
- if (!name) return console.error(' kreftjs make:resource PostResource');
1320
+ if (!name) return console.error(' kreft make:resource PostResource');
1321
1321
  if (!/Resource$/.test(name)) name += 'Resource';
1322
1322
  const resDir = path.join(ctx.base, 'app', 'Http', 'Resources');
1323
1323
  if (!fs.existsSync(resDir)) fs.mkdirSync(resDir, { recursive: true });
@@ -1331,7 +1331,7 @@ const make = {
1331
1331
  rule(args) {
1332
1332
  const o = options(args), ctx = context(o);
1333
1333
  let { dirs, name } = nested(o._[0]);
1334
- if (!name) return console.error(' kreftjs make:rule Uppercase');
1334
+ if (!name) return console.error(' kreft make:rule Uppercase');
1335
1335
  const ruleDir = path.join(ctx.base, 'app', 'Rules');
1336
1336
  if (!fs.existsSync(ruleDir)) fs.mkdirSync(ruleDir, { recursive: true });
1337
1337
  const isTs = isTsProject(path.join(ruleDir, ...dirs, name + '.js'));
@@ -1345,7 +1345,7 @@ const make = {
1345
1345
  const o = options(args), ctx = context(o);
1346
1346
  const locale = (o._[0] || '').toLowerCase().trim();
1347
1347
  if (!locale || /[\/\\]|\.\./.test(locale)) {
1348
- console.error(' kreftjs make:lang <locale> (e.g. kreftjs make:lang ar)');
1348
+ console.error(' kreft make:lang <locale> (e.g. kreft make:lang ar)');
1349
1349
  return;
1350
1350
  }
1351
1351
  // Place in project root lang/ (matching standard Laravel 9/10/11) or backend/lang/ if already existing
@@ -1494,7 +1494,7 @@ const make = {
1494
1494
  console.log(dim(` Use in frontend: { __('auth.failed') } or { t('Sign In') }`));
1495
1495
  },
1496
1496
  };
1497
- // kreftjs make:errors — the error pages (errors/404.kreftjs, 403, 500…)
1497
+ // kreft make:errors — the error pages (errors/404.kreftjs, 403, 500…)
1498
1498
  make.errors = function (args) {
1499
1499
  const o = options(args), ctx = context(o);
1500
1500
  const from = path.join(__dirname, '..', 'templates', 'errors');
@@ -1511,12 +1511,12 @@ make.errors = function (args) {
1511
1511
  }
1512
1512
  };
1513
1513
 
1514
- // kreftjs make:routes admin → frontend/routes/admin.kreftjs (pages), listed in Kreftjs.router({ routes: […] }) in index.html
1515
- // kreftjs make:routes admin --api → backend/routes/admin.js (API), loaded by routes/api.js
1514
+ // kreft make:routes admin → frontend/routes/admin.kreftjs (pages), listed in Kreftjs.router({ routes: […] }) in index.html
1515
+ // kreft make:routes admin --api → backend/routes/admin.js (API), loaded by routes/api.js
1516
1516
  make.routes = function (args) {
1517
1517
  const o = options(args), ctx = context(o);
1518
1518
  const name = String(o._[0] || '').replace(/\.(kreftjs|kreft|som|js)$/, '').replace(/[^\w-]/g, '');
1519
- if (!name) return console.error(' kreftjs make:routes admin (pages)\n kreftjs make:routes admin --api (API)');
1519
+ if (!name) return console.error(' kreft make:routes admin (pages)\n kreft make:routes admin --api (API)');
1520
1520
  if (o.flags.has('api')) {
1521
1521
  const file = path.join(ctx.base, 'routes', name + '.js');
1522
1522
  if (!write(file, stubs.apiRoutes(name))) return;
@@ -1549,12 +1549,12 @@ make.routes = function (args) {
1549
1549
  console.log(` ${green('UPDATED')} ${path.relative(process.cwd(), index)} (${entry} in Kreftjs.router)`);
1550
1550
  };
1551
1551
 
1552
- // kreftjs make:admin you@example.com → that user may open the admin panel (/admin)
1553
- // kreftjs make:admin you@example.com --remove
1552
+ // kreft make:admin you@example.com → that user may open the admin panel (/admin)
1553
+ // kreft make:admin you@example.com --remove
1554
1554
  commands['make:admin'] = async function (args) {
1555
1555
  const o = options(args), ctx = context(o);
1556
1556
  const email = String(o._[0] || '').trim().toLowerCase(); // Register keeps emails in lowercase
1557
- if (!email) return console.error(' kreftjs make:admin you@example.com (--remove takes the rights away)');
1557
+ if (!email) return console.error(' kreft make:admin you@example.com (--remove takes the rights away)');
1558
1558
  await withDb(o, ctx, async (db) => {
1559
1559
  const value = o.flags.has('remove') ? 0 : 1;
1560
1560
  const r = await db.run(`UPDATE ${db.q('users')} SET ${db.q('is_admin')} = ? WHERE LOWER(${db.q('email')}) = ?`, [db.kind === 'postgres' ? Boolean(value) : value, email]);
@@ -1615,8 +1615,8 @@ async function removeModel(args) {
1615
1615
  }
1616
1616
 
1617
1617
  if (!targetModelName) {
1618
- console.error(' Usage: kreftjs remove:model <Name> [--all] [--controller] [--request] [--route] [--migration] [--seeder] [--factory] [--page] [--folder=Folder]');
1619
- console.error(' kreftjs remove model <Name> [options]');
1618
+ console.error(' Usage: kreft remove:model <Name> [--all] [--controller] [--request] [--route] [--migration] [--seeder] [--factory] [--page] [--folder=Folder]');
1619
+ console.error(' kreft remove model <Name> [options]');
1620
1620
  console.error(' kreft:remove model <Name> [options]');
1621
1621
  return;
1622
1622
  }
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Custom console commands (app/Console/Commands, kreftjs make:command SendReport).
2
+ * Custom console commands (app/Console/Commands, kreft make:command SendReport).
3
3
  *
4
4
  * class SendReport extends Command {
5
5
  * static signature = 'send:report {user} {--queue}'
@@ -144,7 +144,7 @@ class Factory {
144
144
  }
145
145
  }
146
146
  }
147
- if (!def) throw new Error(`No factory for ${Model && Model.name ? Model.name : 'Model'}. Make one: kreftjs make:factory ${(Model && Model.name) || 'Model'}Factory`);
147
+ if (!def) throw new Error(`No factory for ${Model && Model.name ? Model.name : 'Model'}. Make one: kreft make:factory ${(Model && Model.name) || 'Model'}Factory`);
148
148
  return new Factory(def);
149
149
  }
150
150
  constructor(def) {
@@ -5,8 +5,8 @@
5
5
  * app/Http/Controllers/PostController.js
6
6
  * app/Http/Middleware/Authenticate.js 'auth' in a route finds Authenticate.js (or Auth.js)
7
7
  * app/Models/Post.js
8
- * database/migrations/*.js kreftjs migrate, kreftjs migrate:rollback, kreftjs migrate:fresh --seed
9
- * database/seeders/DatabaseSeeder.js kreftjs db:seed
8
+ * database/migrations/*.js kreft migrate, kreft migrate:rollback, kreft migrate:fresh --seed
9
+ * database/seeders/DatabaseSeeder.js kreft db:seed
10
10
  *
11
11
  * In your files: const { Route, Model, DB, abort, response } = require('kreftjs/server')
12
12
  */
@@ -171,7 +171,7 @@ function createBackend(baseDir, { db = null, production = false, log = console,
171
171
  const known = { auth: 'Authenticate', guest: 'RedirectIfAuthenticated', verified: 'EnsureEmailIsVerified', 'password.confirm': 'RequirePassword', admin: 'EnsureIsAdmin', role: 'EnsureHasRole', abilities: 'CheckAbilities', ability: 'CheckForAnyAbility' }[name];
172
172
  const names = [name, p, p + 'Middleware', known].filter(Boolean);
173
173
  const file = names.map((n) => findFile(path.join(dir, n))).find(Boolean);
174
- if (!file) throw new Error(`No middleware "${name}". Make it with: kreftjs make:middleware ${p}`);
174
+ if (!file) throw new Error(`No middleware "${name}". Make it with: kreft make:middleware ${p}`);
175
175
  if (!isInsideDir(file, path.resolve(baseDir, 'app'))) throw new Error(`Forbidden middleware path.`);
176
176
  return { fn: await loadModuleAsync(file), args };
177
177
  }
@@ -61,7 +61,7 @@ class ModelNotFoundError extends Error {
61
61
  }
62
62
  }
63
63
 
64
- // where the project's backend is (for factories); set by kreftjs dev / kreftjs serve / the kreftjs commands
64
+ // where the project's backend is (for factories); set by kreft dev / kreft serve / the kreftjs commands
65
65
  let baseDir = null;
66
66
  const setBaseDir = (dir) => { baseDir = dir; };
67
67
  const getBaseDir = () => baseDir;
@@ -454,7 +454,7 @@ class Model {
454
454
  if ((await fire(C, 'saving', this)) === false) return false;
455
455
  if ((await fire(C, creating ? 'creating' : 'updating', this)) === false) return false;
456
456
  if (!(await tableExists(C.table))) {
457
- throw new Error(`Table "${C.table}" does not exist in the database. Run "kreftjs migrate" to create it.`);
457
+ throw new Error(`Table "${C.table}" does not exist in the database. Run "kreft migrate" to create it.`);
458
458
  }
459
459
  const cols = await columnsOf(C.table);
460
460
  const has = (c) => cols.some((x) => x.name === c);
@@ -16,7 +16,7 @@
16
16
  *
17
17
  * await user.notify(new InvoicePaid(invoice))
18
18
  * await Notification.send(users, new InvoicePaid(invoice))
19
- * const list = await user.notifications().get() // the notifications table (kreftjs notifications:table)
19
+ * const list = await user.notifications().get() // the notifications table (kreft notifications:table)
20
20
  * await user.unreadNotifications().update({ read_at: new Date() })
21
21
  */
22
22
  const crypto = require('crypto');
@@ -15,7 +15,7 @@
15
15
  * await dispatch(new SendWelcomeEmail(user), { delay: 60 }) // in a minute
16
16
  * await dispatchSync(new SendWelcomeEmail(user)) // now
17
17
  *
18
- * QUEUE_CONNECTION in .env: database (the jobs table; kreftjs dev and `kreftjs queue:work` run them) or sync (at once).
18
+ * QUEUE_CONNECTION in .env: database (the jobs table; kreft dev and `kreft queue:work` run them) or sync (at once).
19
19
  */
20
20
  const crypto = require('crypto');
21
21
  const fs = require('fs');
@@ -377,7 +377,7 @@ async function workOne({ queues = ['default'], log = () => {} } = {}) {
377
377
  }
378
378
  }
379
379
 
380
- // kreftjs queue:work — runs jobs as they come (stop with Ctrl+C)
380
+ // kreft queue:work — runs jobs as they come (stop with Ctrl+C)
381
381
  async function work({ queues = ['default'], once = false, sleep = 1, maxJobs = Infinity, log = console.log, stopWhenEmpty = false } = {}) {
382
382
  const workerStartedAt = Date.now();
383
383
  let n = 0;
@@ -7,7 +7,7 @@
7
7
  * Schedule.command('cache:clear').hourly()
8
8
  * Schedule.call(fn).cron('* /15 * * * *') (no space: every 15 minutes)
9
9
  *
10
- * kreftjs dev runs them while it is on; for a real server: kreftjs schedule:work (or `kreftjs schedule:run` from cron each minute).
10
+ * kreft dev runs them while it is on; for a real server: kreft schedule:work (or `kreft schedule:run` from cron each minute).
11
11
  */
12
12
  const tasks = [];
13
13
 
@@ -96,7 +96,7 @@ function loadSchedule(baseDir) {
96
96
  require(file);
97
97
  return file;
98
98
  }
99
- // kreftjs dev / kreftjs schedule:work: check every minute, on the minute
99
+ // kreft dev / kreftjs schedule:work: check every minute, on the minute
100
100
  function startScheduler(baseDir, log = console.log) {
101
101
  let timer = null;
102
102
  const tick = async () => {
@@ -12,7 +12,7 @@
12
12
  * if (!post) return null // answered as 404 (and noindex)
13
13
  * return { title: post.title, description: post.excerpt, og: { image: post.image }, schema: { '@type': 'Article', headline: post.title } }
14
14
  * },
15
- * // the addresses of your data pages, for `kreftjs sitemap`: '/path' or { path, lastmod }
15
+ * // the addresses of your data pages, for `kreft sitemap`: '/path' or { path, lastmod }
16
16
  * urls: async () => (await Post.all()).map((p) => ({ path: '/posts/' + p.slug, lastmod: p.updated_at })),
17
17
  * }
18
18
  *
@@ -5,7 +5,7 @@
5
5
  * const data = await req.validate({ avatar: 'required|image|max:2048' }) // KB
6
6
  * const file = req.file('avatar') // { name, size, type, extension() }
7
7
  * const stored = await file.store('avatars') // 'avatars/3f9c…e1.jpg' on the public disk
8
- * Storage.url(stored) // '/storage/avatars/3f9c…e1.jpg' — kreftjs dev and kreftjs serve send it
8
+ * Storage.url(stored) // '/storage/avatars/3f9c…e1.jpg' — kreft dev and kreft serve send it
9
9
  *
10
10
  * await Storage.put('reports/today.txt', 'hello') // the local disk: backend/storage/app (private)
11
11
  * await Storage.get('reports/today.txt') Storage.exists(…) Storage.delete(…) Storage.files('reports')
@@ -98,11 +98,11 @@ function appKey() {
98
98
  if (k) {
99
99
  const buf = k.startsWith('base64:') ? Buffer.from(k.slice(7), 'base64') : Buffer.from(k);
100
100
  if (buf.length >= 16) return buf;
101
- if (production) throw new Error('APP_KEY is shorter than 16 bytes. Run `kreftjs key:generate` and put the new key in .env.');
102
- console.warn(' APP_KEY in .env is shorter than 16 bytes; run `kreftjs key:generate` for a 256-bit key.');
101
+ if (production) throw new Error('APP_KEY is shorter than 16 bytes. Run `kreft key:generate` and put the new key in .env.');
102
+ console.warn(' APP_KEY in .env is shorter than 16 bytes; run `kreft key:generate` for a 256-bit key.');
103
103
  return buf;
104
104
  }
105
- if (production) throw new Error('APP_KEY is not set. Run `kreftjs key:generate` and put the key in .env (production needs one that every process shares).');
105
+ if (production) throw new Error('APP_KEY is not set. Run `kreft key:generate` and put the key in .env (production needs one that every process shares).');
106
106
  if (!fallbackKey) {
107
107
  fallbackKey = crypto.randomBytes(32);
108
108
  console.warn(' No APP_KEY in .env: signed links stop working when the server restarts.');
@@ -170,7 +170,7 @@ const Mail = {
170
170
  if (!transport) {
171
171
  let nodemailer;
172
172
  try { nodemailer = require(require.resolve('nodemailer', { paths: [process.cwd()] })); } catch (_) {
173
- throw new Error('MAIL_URL is set: install the mailer with kreftjs add nodemailer');
173
+ throw new Error('MAIL_URL is set: install the mailer with kreft add nodemailer');
174
174
  }
175
175
  transport = nodemailer.createTransport(process.env.MAIL_URL);
176
176
  }
@@ -2,7 +2,7 @@
2
2
  * TypeScript support across backend and frontend:
3
3
  * - Backend: routes/api.ts, config/*.ts, server/*.ts, and every .ts file in app/ and database/ load like .js files.
4
4
  * - Frontend: .ts modules (e.g. frontend/logic/*.ts) and .kreftjs components with TypeScript syntax work natively in
5
- * both `kreftjs dev` and `kreftjs build`.
5
+ * both `kreft dev` and `kreft build`.
6
6
  *
7
7
  * Uses `esbuild` when installed in the project, or falls back to Kreft's built-in zero-dependency TypeScript
8
8
  * compiler (`Kreftjs.stripTypeScript` + ESM-to-CJS transform) so TypeScript projects work out of the box with zero setup.
package/bin/build.js CHANGED
@@ -1,13 +1,13 @@
1
1
  /*
2
- * kreftjs build — turns a Kreft app into production files.
2
+ * kreft build — turns a Kreft app into production files.
3
3
  *
4
- * kreftjs build build this folder into ./dist
5
- * kreftjs build ./site build another folder
6
- * kreftjs build --out public choose the output folder
7
- * kreftjs build --base / change <base href> in index.html
8
- * kreftjs build --prerender also save every page as ready HTML (needs: npm i -D jsdom)
9
- * kreftjs build --prerender --urls urls.js ... and the addresses in that file (pages that come from your data)
10
- * kreftjs build --include docs also copy another folder into the output
4
+ * kreft build build this folder into ./dist
5
+ * kreft build ./site build another folder
6
+ * kreft build --out public choose the output folder
7
+ * kreft build --base / change <base href> in index.html
8
+ * kreft build --prerender also save every page as ready HTML (needs: npm i -D jsdom)
9
+ * kreft build --prerender --urls urls.js ... and the addresses in that file (pages that come from your data)
10
+ * kreft build --include docs also copy another folder into the output
11
11
  *
12
12
  * What it does:
13
13
  * 1. Compiles every .kreftjs file ahead of time into app.js (no .kreftjs files are downloaded in production).
@@ -113,7 +113,7 @@ module.exports = function build(args) {
113
113
  const langInject = Object.keys(langData).length ? `Kreftjs.translations(${JSON.stringify(langData)});\n` : '';
114
114
 
115
115
  const precompiled = [...fns].map(([key, src]) => `F[${JSON.stringify(key)}] = ${src};`).join('\n');
116
- const appJs = `/* Built by kreftjs build — do not edit. Rebuild from your .kreftjs files instead. */
116
+ const appJs = `/* Built by kreft build — do not edit. Rebuild from your .kreftjs files instead. */
117
117
  ${env.envScript(env.publicEnv())}
118
118
  (function (Kreftjs) {
119
119
  if (!Kreftjs) throw new Error('Load kreftjs.js before app.js');
@@ -204,7 +204,7 @@ ${indent(components.join('\n\n'))}
204
204
  const links = cssLinks.map(({ spec, local }) => {
205
205
  if (local) return spec;
206
206
  const file = deps.packageFile(project, spec);
207
- if (!file) fail(`The CSS file "${spec}" was not found in node_modules. Run: kreftjs add ${(spec.match(deps.NAME) || [spec])[0]}`);
207
+ if (!file) fail(`The CSS file "${spec}" was not found in node_modules. Run: kreft add ${(spec.match(deps.NAME) || [spec])[0]}`);
208
208
  const info = deps.packageJson(project, spec);
209
209
  copyCss(file, info.dir, path.join(dist, 'vendor', info.name));
210
210
  return toUrlPath(path.join('vendor', info.name, path.relative(info.dir, file)));
@@ -237,7 +237,7 @@ ${indent(components.join('\n\n'))}
237
237
  ...files.sort().map(([f, n]) => ` ${cyan(kb(n))} ${toUrlPath(f)}`),
238
238
  '---',
239
239
  ` ${bold('Output:')} ${dist}`,
240
- ` ${bold('Preview:')} kreftjs dev ${path.relative(process.cwd(), dist) || '.'}`,
240
+ ` ${bold('Preview:')} kreft dev ${path.relative(process.cwd(), dist) || '.'}`,
241
241
  ];
242
242
  console.log('\n' + renderBox(lines, { width: 66, borderColor: green }) + '\n');
243
243
  };
package/bin/db-api.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*
2
- * A REST API made from the tables of a database (used by `kreftjs dev --db` and `kreftjs serve --db`).
2
+ * A REST API made from the tables of a database (used by `kreft dev --db` and `kreft serve --db`).
3
3
  *
4
4
  * GET /api the tables you can use
5
5
  * GET /api/posts rows ?userId=3 ?title_like=som ?likes_gte=5 ?q=text
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * Which tables, and what each allows, comes from `tables` (kreftjs.config.json):
17
17
  * { "posts": true, "users": { "write": false, "hidden": ["password"] }, "logs": false }
18
- * `kreftjs dev` shows every table unless you list them; `kreftjs serve` shows only the tables you list.
18
+ * `kreft dev` shows every table unless you list them; `kreft serve` shows only the tables you list.
19
19
  */
20
20
  const { validate } = require('../kreftjs.js'); // the same rules as Kreftjs.validate in the browser
21
21
  const MAX_BODY = 1024 * 1024;
@@ -48,7 +48,7 @@ function createDbApi(db, { tables: allow = null, production = false, prefix = '/
48
48
  }
49
49
  return out;
50
50
  };
51
- // `kreftjs serve` reads the tables once; `kreftjs dev` looks again every 2 s, so a new table shows up by itself
51
+ // `kreft serve` reads the tables once; `kreft dev` looks again every 2 s, so a new table shows up by itself
52
52
  let loadedAt = 0;
53
53
  const tables = async () => {
54
54
  if (schema && (production || Date.now() - loadedAt < 2000)) return schema;
package/bin/db.js CHANGED
@@ -33,7 +33,7 @@ function parseUrl(url) {
33
33
  function driver(name, root) {
34
34
  const paths = [root || process.cwd(), process.cwd(), __dirname];
35
35
  try { return require(require.resolve(name, { paths })); }
36
- catch (_) { throw new Error(`To use this database, install its driver in your project:\n\n kreftjs add ${name}\n`); }
36
+ catch (_) { throw new Error(`To use this database, install its driver in your project:\n\n kreft add ${name}\n`); }
37
37
  }
38
38
 
39
39
  const TEXT = /char|text|clob|string|uuid|enum|json/i;
package/bin/deps.js CHANGED
@@ -5,10 +5,10 @@
5
5
  * import { debounce } from 'lodash'
6
6
  * import 'bootstrap/dist/css/bootstrap.min.css'
7
7
  *
8
- * kreftjs dev answers /__kreft/deps/<package> with the package as one browser-ready ES module, made by
8
+ * kreft dev answers /__kreft/deps/<package> with the package as one browser-ready ES module, made by
9
9
  * esbuild (npm i -D esbuild), and adds an import map so the browser knows where 'dayjs' is.
10
- * kreftjs build writes the same files into dist/deps/. Without esbuild, packages that already ship
11
- * ES modules still work in kreftjs dev; older CommonJS ones (like lodash) need esbuild.
10
+ * kreft build writes the same files into dist/deps/. Without esbuild, packages that already ship
11
+ * ES modules still work in kreft dev; older CommonJS ones (like lodash) need esbuild.
12
12
  */
13
13
  const fs = require('fs');
14
14
  const path = require('path');
@@ -57,14 +57,14 @@ function isEsm(root, spec) {
57
57
 
58
58
  const cache = new Map();
59
59
  // one package (or a file inside it) as a single ES module for the browser.
60
- // bundle() is async (kreftjs dev); bundleSync() is the same for kreftjs build.
60
+ // bundle() is async (kreft dev); bundleSync() is the same for kreft build.
61
61
  function prepare(root, spec, minify) {
62
62
  const esbuild = loadEsbuild(root);
63
- if (!esbuild) throw Object.assign(new Error(`To use "${spec}" in the browser, install esbuild once: kreftjs add -D esbuild`), { code: 'NO_ESBUILD' });
63
+ if (!esbuild) throw Object.assign(new Error(`To use "${spec}" in the browser, install esbuild once: kreft add -D esbuild`), { code: 'NO_ESBUILD' });
64
64
  // only packages by name: never a path that would bundle (and show) one of your own server files
65
65
  if (!isBare(spec) || spec.split('/').some((p) => p === '..' || p === '.')) throw Object.assign(new Error(`"${spec}" is not a package name.`), { code: 'MISSING' });
66
66
  const file = resolveFrom(root, spec);
67
- if (!file) throw Object.assign(new Error(`The package "${spec}" is not installed. Run: kreftjs add ${(spec.match(NAME) || [spec])[0]}`), { code: 'MISSING' });
67
+ if (!file) throw Object.assign(new Error(`The package "${spec}" is not installed. Run: kreft add ${(spec.match(NAME) || [spec])[0]}`), { code: 'MISSING' });
68
68
  const key = spec + '|' + fs.statSync(file).mtimeMs + '|' + minify + '|' + root;
69
69
  const s = JSON.stringify(spec);
70
70
  let tries;
package/bin/electron.js CHANGED
@@ -2,12 +2,12 @@
2
2
  * Electron.js Desktop Support for Kreft
3
3
  *
4
4
  * Commands:
5
- * kreftjs electron:init Add Electron files to an existing project (alias: kreftjs make:electron)
6
- * kreftjs electron:dev Run the app in an Electron desktop window with hot reload (alias: kreftjs electron)
7
- * kreftjs electron:build Build static bundle (kreftjs build) and package desktop installer (electron-builder)
5
+ * kreft electron:init Add Electron files to an existing project (alias: kreft make:electron)
6
+ * kreft electron:dev Run the app in an Electron desktop window with hot reload (alias: kreft electron)
7
+ * kreft electron:build Build static bundle (kreft build) and package desktop installer (electron-builder)
8
8
  *
9
9
  * CLI flag:
10
- * kreftjs new my-app --electron
10
+ * kreft new my-app --electron
11
11
  */
12
12
  const fs = require('fs');
13
13
  const path = require('path');
@@ -286,9 +286,9 @@ function init(args = []) {
286
286
  const pkg = JSON.parse(fs.readFileSync(pkgFile, 'utf8'));
287
287
  pkg.main = 'electron/main.js';
288
288
  pkg.scripts = pkg.scripts || {};
289
- pkg.scripts['electron'] = 'kreftjs electron';
290
- pkg.scripts['electron:dev'] = 'kreftjs electron:dev';
291
- pkg.scripts['electron:build'] = 'kreftjs electron:build';
289
+ pkg.scripts['electron'] = 'kreft electron';
290
+ pkg.scripts['electron:dev'] = 'kreft electron:dev';
291
+ pkg.scripts['electron:build'] = 'kreft electron:build';
292
292
 
293
293
  pkg.devDependencies = pkg.devDependencies || {};
294
294
  if (!pkg.devDependencies['electron']) pkg.devDependencies['electron'] = '^34.2.0';
@@ -317,8 +317,8 @@ function init(args = []) {
317
317
 
318
318
  Next:
319
319
  npm install (install electron & electron-builder)
320
- kreftjs electron:dev (start dev server & launch desktop window)
321
- kreftjs electron:build (build production installer)
320
+ kreft electron:dev (start dev server & launch desktop window)
321
+ kreft electron:build (build production installer)
322
322
  `);
323
323
  }
324
324
 
@@ -433,7 +433,7 @@ function startDev(args, port) {
433
433
 
434
434
  electronProcess.on('error', (err) => {
435
435
  if (err.code === 'ENOENT') {
436
- console.error('\n Electron is not installed locally. Run: kreftjs add -D electron\n');
436
+ console.error('\n Electron is not installed locally. Run: kreft add -D electron\n');
437
437
  } else {
438
438
  console.error(' Electron launch error: ' + err.message);
439
439
  }
@@ -489,7 +489,7 @@ function build(args = []) {
489
489
 
490
490
  packProc.on('error', (err) => {
491
491
  if (err.code === 'ENOENT') {
492
- console.error('\n electron-builder is not installed. Run: kreftjs add -D electron-builder\n');
492
+ console.error('\n electron-builder is not installed. Run: kreft add -D electron-builder\n');
493
493
  } else {
494
494
  console.error(' Packaging error: ' + err.message);
495
495
  }
package/bin/env.js CHANGED
@@ -1,13 +1,13 @@
1
1
  /*
2
2
  * .env files and environment management.
3
3
  *
4
- * # .env (never sent to the browser, never copied by kreftjs build)
4
+ * # .env (never sent to the browser, never copied by kreft build)
5
5
  * APP_NAME="My shop"
6
6
  * DATABASE_URL=sqlite:database/app.db
7
7
  * MAIL_PASSWORD=secret
8
8
  * PUBLIC_APP_NAME=${APP_NAME} ← PUBLIC_ values also reach the browser: env.PUBLIC_APP_NAME
9
9
  *
10
- * Read by kreftjs dev, kreftjs serve, kreftjs build and kreftjs db. Values already set in the real environment win,
10
+ * Read by kreft dev, kreft serve, kreft build and kreft db. Values already set in the real environment win,
11
11
  * so a server can override the file. In server/*.js: process.env.MAIL_PASSWORD (or ctx.env).
12
12
  */
13
13
  const fs = require('fs');
package/bin/guard.js CHANGED
@@ -2,11 +2,11 @@
2
2
  * Folder guard: Kreft notices when the folder it works in is deleted, moved or put in the Trash.
3
3
  *
4
4
  * A running process keeps working on a folder that was moved away (the files are still there, under a new
5
- * name), so `kreftjs dev` would carry on serving a project you thought was gone, and a terminal opened in the
5
+ * name), so `kreft dev` would carry on serving a project you thought was gone, and a terminal opened in the
6
6
  * old folder would run commands against the Trash. The operating system cannot be asked to refuse the
7
7
  * delete, so Kreft says it loudly instead:
8
8
  * - every command first checks that the folder it runs in is not deleted or in the Trash;
9
- * - `kreftjs dev`, `kreftjs serve` and the queue / schedule workers check every second and stop with a message.
9
+ * - `kreft dev`, `kreft serve` and the queue / schedule workers check every second and stop with a message.
10
10
  */
11
11
  const fs = require('fs');
12
12
  const path = require('path');
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * kreftjs.config.json: { "db": "sqlite:database/app.db", "tables": { "posts": true, "users": { "write": false, "hidden": ["password"] } } }
3
- * Looked for in the folder being served, then its parents (so `kreftjs serve dist` finds the project's file).
3
+ * Looked for in the folder being served, then its parents (so `kreft serve dist` finds the project's file).
4
4
  * "${NAME}" in a value is replaced with that value from .env or the environment.
5
5
  */
6
6
  const fs = require('fs');