easy-cms 0.47.4 → 0.49.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -20,9 +20,9 @@ npx easy-cms migrate:create <name> # a migration for config changes
20
20
  npx easy-cms migrate # apply pending migrations
21
21
  npx easy-cms migrate:status
22
22
  npx easy-cms generate:types [--out file.ts]
23
- npx easy-cms create-admin [--email you@example.com] [--name] [--role]
23
+ npx easy-cms admin:create [--email you@example.com] [--name] [--role]
24
24
  npx easy-cms serve [--port 4000] [--watch]
25
- npx easy-cms run-scheduled # due scheduled jobs, webhook and email retries (cron)
25
+ npx easy-cms jobs:run # due scheduled jobs, webhook and email retries (cron)
26
26
  npx easy-cms backup <file> # SQLite snapshot while the CMS runs
27
27
  npx easy-cms copy --from <config> # copy content to another database
28
28
  ```
package/dist/bin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  run
4
- } from "./chunk-73JSCLZP.js";
4
+ } from "./chunk-IP3UPED4.js";
5
5
 
6
6
  // src/bin.ts
7
7
  process.exitCode = await run(process.argv.slice(2));
@@ -7,14 +7,12 @@ import { parseArgs } from "util";
7
7
  import { gzipSync } from "zlib";
8
8
  import {
9
9
  ConfigError,
10
- copyDatabase,
11
10
  createEasyCMS as createEasyCMS2,
12
11
  EasyCMSError,
13
- generateTypes,
14
12
  loadConfig,
15
- ValidationError,
16
- writeBackupFile
13
+ ValidationError
17
14
  } from "@easy-cms/core";
15
+ import { copyDatabase, generateTypes, writeBackupFile } from "@easy-cms/core/internal";
18
16
 
19
17
  // src/serve.ts
20
18
  import { watch } from "fs";
@@ -24,9 +22,9 @@ import { pipeline } from "stream/promises";
24
22
  import { adminHandlerFor } from "@easy-cms/admin";
25
23
  import {
26
24
  createEasyCMS,
27
- createRestHandler,
28
- createRootEndpointHandler
25
+ createRestHandler
29
26
  } from "@easy-cms/core";
27
+ import { createRootEndpointHandler, forwardedClientIp } from "@easy-cms/core/internal";
30
28
  function createStandaloneHandler(cms) {
31
29
  const config = cms.config;
32
30
  const adminPath = `/${config.admin.path.replace(/^\/+|\/+$/g, "")}`;
@@ -90,7 +88,7 @@ function header(req, name) {
90
88
  }
91
89
  function clientIpOf(req, trustProxy) {
92
90
  if (trustProxy) {
93
- const forwarded = header(req, "x-forwarded-for")?.split(",")[0]?.trim();
91
+ const forwarded = forwardedClientIp(header(req, "x-forwarded-for"));
94
92
  if (forwarded) return forwarded;
95
93
  }
96
94
  return req.socket.remoteAddress;
@@ -197,9 +195,9 @@ Commands:
197
195
  migrate:create <name> Create a migration from config changes
198
196
  migrate:status List migrations and whether they are applied
199
197
  generate:types Write TypeScript types for your collections and globals
200
- create-admin Create an admin user
198
+ admin:create Create an admin user (also: create-admin)
201
199
  serve Run the CMS as its own server (admin + REST API)
202
- run-scheduled Run due scheduled publishes, webhook and email retries
200
+ jobs:run Run due scheduled publishes, jobs, webhook and email retries (also: run-scheduled)
203
201
  backup <file> Copy the database to a SQLite file while the CMS runs
204
202
  copy --from <config> Copy all content from another config's database into this one
205
203
  <plugin command> Commands from your config's plugins, e.g. nested:rebuild
@@ -230,7 +228,7 @@ Lists migration files and whether each has been applied.
230
228
  Writes interfaces for every collection and global (default: easy-cms-types.ts).
231
229
  The file has no imports, so a frontend in another repository can copy it.
232
230
  `,
233
- "create-admin": `Usage: easy-cms create-admin [--email <email>] [--name <name>] [--role <role>] [options]
231
+ "admin:create": `Usage: easy-cms admin:create [--email <email>] [--name <name>] [--role <role>] [options]
234
232
 
235
233
  Creates a user (role "admin" unless --role is given). The password is asked for in the
236
234
  terminal, or read from EASY_CMS_ADMIN_PASSWORD when there is no terminal.
@@ -255,7 +253,7 @@ development its tables are created, in production run \`easy-cms migrate\` first
255
253
  Uploaded files are not copied: they stay in the uploads folder or bucket.
256
254
  Stop writing to the source while copying, or copy from a backup.
257
255
  `,
258
- "run-scheduled": `Usage: easy-cms run-scheduled [options]
256
+ "jobs:run": `Usage: easy-cms jobs:run [options]
259
257
 
260
258
  Runs due scheduled publishes and unpublishes, and retries failed webhook deliveries, once:
261
259
  for a cron job where no server process keeps running. Servers do this every minute on their own.
@@ -274,22 +272,31 @@ In production (NODE_ENV=production) pending migrations stop the server from star
274
272
  `
275
273
  };
276
274
  async function run(argv, io = defaultIO) {
275
+ const loose = parseArgs({
276
+ args: [...argv],
277
+ allowPositionals: true,
278
+ strict: false,
279
+ options: OPTIONS
280
+ });
281
+ const [named, ...looseRest] = loose.positionals;
282
+ const command = named === void 0 ? void 0 : RENAMED_COMMANDS[named] ?? named;
283
+ if (command && !(command in COMMAND_HELP))
284
+ return await pluginCommand(command, looseRest, loose.values, io);
277
285
  let parsed;
278
286
  try {
279
287
  parsed = parse(argv);
280
288
  } catch (error) {
281
289
  io.err(error.message);
282
- io.err(HELP);
290
+ io.err(command ? COMMAND_HELP[command] : HELP);
283
291
  return 1;
284
292
  }
285
- const { values, positionals } = parsed;
286
- const [command, ...rest] = positionals;
293
+ const { values } = parsed;
294
+ const rest = parsed.positionals.slice(1);
287
295
  if (!command) {
288
296
  ;
289
297
  (values.help ? io.out : io.err)(HELP);
290
298
  return values.help ? 0 : 1;
291
299
  }
292
- if (!(command in COMMAND_HELP)) return await pluginCommand(command, rest, values, io);
293
300
  if (values.help) {
294
301
  io.out(COMMAND_HELP[command]);
295
302
  return 0;
@@ -309,7 +316,7 @@ async function run(argv, io = defaultIO) {
309
316
  return 0;
310
317
  }
311
318
  if (command === "copy") return await copy(values.from, config, cwd, logger, io);
312
- const schema = command === "create-admin" && process.env.NODE_ENV !== "production" ? "push" : "skip";
319
+ const schema = command === "admin:create" && process.env.NODE_ENV !== "production" ? "push" : "skip";
313
320
  const cms = await createEasyCMS2(config, {
314
321
  cwd,
315
322
  schema,
@@ -349,8 +356,9 @@ async function run(argv, io = defaultIO) {
349
356
  io.out(`Backed up the database to ${file}`);
350
357
  return 0;
351
358
  }
352
- case "run-scheduled": {
353
- const { ran, failed, webhooks, emails } = await cms.runJobs();
359
+ case "jobs:run": {
360
+ const { scheduled, webhooks, emails } = await cms.runJobs();
361
+ const { ran, failed } = scheduled;
354
362
  io.out(`Ran ${ran} scheduled job(s)${failed ? `, ${failed} failed` : ""}.`);
355
363
  if (webhooks.sent || webhooks.failed)
356
364
  io.out(
@@ -385,11 +393,11 @@ async function run(argv, io = defaultIO) {
385
393
  }
386
394
  return 0;
387
395
  }
388
- case "create-admin": {
396
+ case "admin:create": {
389
397
  const email = values.email ?? (io.interactive && io.prompt ? await io.prompt("Email: ") : "");
390
398
  if (!email) {
391
399
  io.err("Missing --email.\n");
392
- io.err(COMMAND_HELP["create-admin"]);
400
+ io.err(COMMAND_HELP["admin:create"]);
393
401
  return 1;
394
402
  }
395
403
  const password = process.env.EASY_CMS_ADMIN_PASSWORD ?? (io.interactive && io.prompt ? await io.prompt("Password (8+ characters): ", { hidden: true }) : "");
@@ -435,7 +443,9 @@ async function run(argv, io = defaultIO) {
435
443
  }
436
444
  }
437
445
  async function pluginCommand(command, args, values, io) {
438
- const cwd = values.cwd ?? process.cwd();
446
+ const text = (value) => typeof value === "string" ? value : void 0;
447
+ const cwd = text(values.cwd) ?? process.cwd();
448
+ const configFile = text(values.config);
439
449
  loadDotEnv(cwd);
440
450
  const logger = { info: io.out, warn: (m) => io.err(`warning: ${m}`), error: io.err };
441
451
  const unknown = (note) => {
@@ -447,14 +457,14 @@ async function pluginCommand(command, args, values, io) {
447
457
  };
448
458
  let config;
449
459
  try {
450
- config = await loadConfig({ cwd, ...values.config ? { configFile: values.config } : {} });
460
+ config = await loadConfig({ cwd, ...configFile ? { configFile } : {} });
451
461
  } catch (error) {
452
462
  return unknown(`(Commands from the config were not loaded: ${error.message})`);
453
463
  }
454
464
  try {
455
- const found = config.commands.find((c) => c.name === command);
465
+ const found = config.cliCommands.find((c) => c.name === command);
456
466
  if (!found) {
457
- const extra = config.commands.map((c) => ` ${c.name.padEnd(24)}${c.description}`);
467
+ const extra = config.cliCommands.map((c) => ` ${c.name.padEnd(24)}${c.description}`);
458
468
  return unknown(extra.length ? `Commands from your config:
459
469
  ${extra.join("\n")}
460
470
  ` : void 0);
@@ -474,7 +484,13 @@ ${found.description}
474
484
  scheduler: false
475
485
  });
476
486
  try {
477
- return await found.run({ cms, args, log: io.out }) ?? 0;
487
+ const flags = Object.fromEntries(
488
+ Object.entries(values).filter(([key, value]) => !["config", "cwd", "help"].includes(key) && value !== void 0).map(([key, value]) => [
489
+ key.replace(/-([a-z])/g, (_, c) => c.toUpperCase()),
490
+ value
491
+ ])
492
+ );
493
+ return await found.run({ cms, args, flags, log: io.out }) ?? 0;
478
494
  } finally {
479
495
  await cms.destroy();
480
496
  }
@@ -490,25 +506,26 @@ ${found.description}
490
506
  return 1;
491
507
  }
492
508
  }
509
+ var RENAMED_COMMANDS = {
510
+ "create-admin": "admin:create",
511
+ "run-scheduled": "jobs:run"
512
+ };
513
+ var OPTIONS = {
514
+ config: { type: "string" },
515
+ cwd: { type: "string" },
516
+ out: { type: "string" },
517
+ from: { type: "string" },
518
+ email: { type: "string" },
519
+ name: { type: "string" },
520
+ role: { type: "string" },
521
+ port: { type: "string" },
522
+ host: { type: "string" },
523
+ watch: { type: "boolean" },
524
+ "trust-proxy": { type: "boolean" },
525
+ help: { type: "boolean", short: "h" }
526
+ };
493
527
  function parse(argv) {
494
- return parseArgs({
495
- args: [...argv],
496
- allowPositionals: true,
497
- options: {
498
- config: { type: "string" },
499
- cwd: { type: "string" },
500
- out: { type: "string" },
501
- from: { type: "string" },
502
- email: { type: "string" },
503
- name: { type: "string" },
504
- role: { type: "string" },
505
- port: { type: "string" },
506
- host: { type: "string" },
507
- watch: { type: "boolean" },
508
- "trust-proxy": { type: "boolean" },
509
- help: { type: "boolean", short: "h" }
510
- }
511
- });
528
+ return parseArgs({ args: [...argv], allowPositionals: true, options: OPTIONS });
512
529
  }
513
530
  async function serve(values, cwd, logger, load, io) {
514
531
  const port = Number(values.port ?? process.env.PORT ?? 4e3);
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  createStandaloneHandler,
3
3
  run,
4
4
  startServer
5
- } from "./chunk-73JSCLZP.js";
5
+ } from "./chunk-IP3UPED4.js";
6
6
  export {
7
7
  createStandaloneHandler,
8
8
  run,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "easy-cms",
3
- "version": "0.47.4",
3
+ "version": "0.49.0",
4
4
  "description": "Command line tool for Easy CMS",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -21,11 +21,11 @@
21
21
  "node": ">=22.12"
22
22
  },
23
23
  "dependencies": {
24
- "@easy-cms/core": "^0.47.4",
25
- "@easy-cms/admin": "^0.47.4"
24
+ "@easy-cms/core": "^0.49.0",
25
+ "@easy-cms/admin": "^0.49.0"
26
26
  },
27
27
  "devDependencies": {
28
- "@easy-cms/db-sqlite": "^0.47.4"
28
+ "@easy-cms/db-sqlite": "^0.49.0"
29
29
  },
30
30
  "publishConfig": {
31
31
  "access": "public"