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 +2 -2
- package/dist/bin.js +1 -1
- package/dist/{chunk-73JSCLZP.js → chunk-IP3UPED4.js} +60 -43
- package/dist/index.js +1 -1
- package/package.json +4 -4
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
|
|
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
|
|
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
|
@@ -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")
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
286
|
-
const
|
|
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
|
|
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
|
|
353
|
-
const {
|
|
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
|
|
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
|
|
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
|
|
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, ...
|
|
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.
|
|
465
|
+
const found = config.cliCommands.find((c) => c.name === command);
|
|
456
466
|
if (!found) {
|
|
457
|
-
const extra = config.
|
|
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
|
-
|
|
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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "easy-cms",
|
|
3
|
-
"version": "0.
|
|
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.
|
|
25
|
-
"@easy-cms/admin": "^0.
|
|
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.
|
|
28
|
+
"@easy-cms/db-sqlite": "^0.49.0"
|
|
29
29
|
},
|
|
30
30
|
"publishConfig": {
|
|
31
31
|
"access": "public"
|