@easy-cms/core 1.5.0 → 1.7.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/dist/{chunk-NFUXZ3FX.js → chunk-AVUGFJ4Q.js} +212 -29
- package/dist/{config-CB8mhU2a.d.ts → config-CzW6kBeb.d.ts} +31 -4
- package/dist/{handler-bybEUkpd.d.ts → handler-BsBQ-2qf.d.ts} +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +3 -1
- package/dist/internal.d.ts +12 -4
- package/dist/internal.js +7 -1
- package/dist/{plugin-CJCqvyo_.d.ts → plugin-BmKxHxuu.d.ts} +1 -1
- package/dist/plugin.d.ts +2 -2
- package/package.json +1 -1
|
@@ -2678,7 +2678,7 @@ var Mailer = class {
|
|
|
2678
2678
|
error: null
|
|
2679
2679
|
});
|
|
2680
2680
|
} catch (error) {
|
|
2681
|
-
this.logger.error(`Could not save email: ${error.message}
|
|
2681
|
+
this.logger.error(`Could not save email: ${error.message}`, { error });
|
|
2682
2682
|
}
|
|
2683
2683
|
this.track(this.deliver(message2, body, id));
|
|
2684
2684
|
}
|
|
@@ -2726,7 +2726,9 @@ var Mailer = class {
|
|
|
2726
2726
|
return this.attempt(JSON.parse(message2));
|
|
2727
2727
|
}
|
|
2728
2728
|
track(delivery) {
|
|
2729
|
-
const tracked = delivery.catch(
|
|
2729
|
+
const tracked = delivery.catch(
|
|
2730
|
+
(error) => this.logger.error(`Email queue failed: ${error.message}`, { error })
|
|
2731
|
+
).finally(() => this.pending.delete(tracked));
|
|
2730
2732
|
this.pending.add(tracked);
|
|
2731
2733
|
}
|
|
2732
2734
|
async deliver(message2, body, id) {
|
|
@@ -2787,6 +2789,42 @@ function configSignature(config) {
|
|
|
2787
2789
|
}
|
|
2788
2790
|
var signatures = /* @__PURE__ */ new WeakMap();
|
|
2789
2791
|
|
|
2792
|
+
// src/health.ts
|
|
2793
|
+
var HEADERS = { "content-type": "application/json; charset=utf-8", "cache-control": "no-store" };
|
|
2794
|
+
var migrated = /* @__PURE__ */ new WeakSet();
|
|
2795
|
+
async function pendingMigrations(cms) {
|
|
2796
|
+
if (migrated.has(cms)) return 0;
|
|
2797
|
+
const pending = (await cms.db.migrationStatus()).filter((m) => !m.applied).length;
|
|
2798
|
+
if (pending === 0) migrated.add(cms);
|
|
2799
|
+
return pending;
|
|
2800
|
+
}
|
|
2801
|
+
async function healthResponse(check3, instance) {
|
|
2802
|
+
const cms = instance;
|
|
2803
|
+
if (check3 === "healthz") return new Response("ok", { headers: { "cache-control": "no-store" } });
|
|
2804
|
+
if (!cms) {
|
|
2805
|
+
return Response.json(
|
|
2806
|
+
{ status: "error", checks: { startup: "error" } },
|
|
2807
|
+
{ status: 503, headers: HEADERS }
|
|
2808
|
+
);
|
|
2809
|
+
}
|
|
2810
|
+
const checks = {};
|
|
2811
|
+
try {
|
|
2812
|
+
await cms.db.count({ collection: USERS });
|
|
2813
|
+
checks.database = "ok";
|
|
2814
|
+
const pending = await pendingMigrations(cms);
|
|
2815
|
+
checks.migrations = pending === 0 ? "ok" : `${pending} pending`;
|
|
2816
|
+
} catch (error) {
|
|
2817
|
+
if (checks.database) checks.migrations = "error";
|
|
2818
|
+
else Object.assign(checks, { database: "error", migrations: "not checked" });
|
|
2819
|
+
cms.logger.error(`Readiness check failed: ${error.message}`, { error });
|
|
2820
|
+
}
|
|
2821
|
+
const ok = Object.values(checks).every((value) => value === "ok");
|
|
2822
|
+
return Response.json(
|
|
2823
|
+
{ status: ok ? "ok" : "error", checks },
|
|
2824
|
+
{ status: ok ? 200 : 503, headers: HEADERS }
|
|
2825
|
+
);
|
|
2826
|
+
}
|
|
2827
|
+
|
|
2790
2828
|
// src/copy.ts
|
|
2791
2829
|
var BATCH = 200;
|
|
2792
2830
|
async function copyDatabase(source, target, options = {}) {
|
|
@@ -3112,7 +3150,7 @@ async function startBackup(cms, trigger, author) {
|
|
|
3112
3150
|
}
|
|
3113
3151
|
});
|
|
3114
3152
|
void runBackup(cms, row).catch(
|
|
3115
|
-
(error) => cms.logger.error(`Backup failed: ${error.message}
|
|
3153
|
+
(error) => cms.logger.error(`Backup failed: ${error.message}`, { error })
|
|
3116
3154
|
);
|
|
3117
3155
|
return toAdmin(row);
|
|
3118
3156
|
}
|
|
@@ -3221,7 +3259,7 @@ async function runDueBackups(cms, now = /* @__PURE__ */ new Date()) {
|
|
|
3221
3259
|
if (!due) return;
|
|
3222
3260
|
if (await inProgress(cms, now.getTime())) return;
|
|
3223
3261
|
await startBackup(cms, "scheduled").catch(
|
|
3224
|
-
(error) => cms.logger.error(`Scheduled backup could not start: ${error.message}
|
|
3262
|
+
(error) => cms.logger.error(`Scheduled backup could not start: ${error.message}`, { error })
|
|
3225
3263
|
);
|
|
3226
3264
|
}
|
|
3227
3265
|
async function backupAttention(cms, now = Date.now()) {
|
|
@@ -3290,12 +3328,58 @@ async function deleteBackup(cms, id) {
|
|
|
3290
3328
|
var consoleLogger = {
|
|
3291
3329
|
info: (message2) => console.info(`[easy-cms] ${message2}`),
|
|
3292
3330
|
warn: (message2) => console.warn(`[easy-cms] ${message2}`),
|
|
3293
|
-
error: (message2) =>
|
|
3331
|
+
error: (message2, details) => {
|
|
3332
|
+
const stack = details?.error instanceof Error ? details.error.stack : void 0;
|
|
3333
|
+
console.error(`[easy-cms] ${message2}${stack ? `
|
|
3334
|
+
${stack}` : ""}`);
|
|
3335
|
+
}
|
|
3294
3336
|
};
|
|
3295
3337
|
var silentLogger = { info() {
|
|
3296
3338
|
}, warn() {
|
|
3297
3339
|
}, error() {
|
|
3298
3340
|
} };
|
|
3341
|
+
function logFormat(logs) {
|
|
3342
|
+
const env = process.env.EASY_CMS_LOG_FORMAT;
|
|
3343
|
+
if (env === "json" || env === "pretty") return env;
|
|
3344
|
+
return logs?.format ?? "pretty";
|
|
3345
|
+
}
|
|
3346
|
+
var jsonLoggers = /* @__PURE__ */ new WeakSet();
|
|
3347
|
+
var isJsonLogger = (logger) => jsonLoggers.has(logger);
|
|
3348
|
+
function errorFields(error) {
|
|
3349
|
+
if (error instanceof Error)
|
|
3350
|
+
return { name: error.name, message: error.message, stack: error.stack };
|
|
3351
|
+
return { message: String(error) };
|
|
3352
|
+
}
|
|
3353
|
+
function jsonLogger(write = (line, level) => (level === "info" ? process.stdout : process.stderr).write(`${line}
|
|
3354
|
+
`)) {
|
|
3355
|
+
const log = (level) => (message2, details) => {
|
|
3356
|
+
const store2 = auditContext.getStore();
|
|
3357
|
+
const { error, ...rest } = details ?? {};
|
|
3358
|
+
const entry = {
|
|
3359
|
+
time: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3360
|
+
level,
|
|
3361
|
+
name: "easy-cms",
|
|
3362
|
+
message: message2,
|
|
3363
|
+
...store2?.requestId ? { requestId: store2.requestId } : {},
|
|
3364
|
+
...store2?.runId ? { runId: store2.runId } : {},
|
|
3365
|
+
...rest,
|
|
3366
|
+
...error === void 0 ? {} : { error: errorFields(error) }
|
|
3367
|
+
};
|
|
3368
|
+
let line;
|
|
3369
|
+
try {
|
|
3370
|
+
line = JSON.stringify(entry);
|
|
3371
|
+
} catch {
|
|
3372
|
+
line = JSON.stringify({
|
|
3373
|
+
...entry,
|
|
3374
|
+
...Object.fromEntries(Object.keys(rest).map((k) => [k, "[unserializable]"]))
|
|
3375
|
+
});
|
|
3376
|
+
}
|
|
3377
|
+
write(line, level);
|
|
3378
|
+
};
|
|
3379
|
+
const logger = { info: log("info"), warn: log("warn"), error: log("error") };
|
|
3380
|
+
jsonLoggers.add(logger);
|
|
3381
|
+
return logger;
|
|
3382
|
+
}
|
|
3299
3383
|
|
|
3300
3384
|
// src/media-folders.ts
|
|
3301
3385
|
var FOLDER_LEVELS = ["view", "edit", "manage"];
|
|
@@ -3790,7 +3874,7 @@ var VersionStore = class {
|
|
|
3790
3874
|
};
|
|
3791
3875
|
|
|
3792
3876
|
// src/local-api.ts
|
|
3793
|
-
import { createHmac as createHmac6, randomBytes as randomBytes6, timingSafeEqual as timingSafeEqual5 } from "crypto";
|
|
3877
|
+
import { createHmac as createHmac6, randomBytes as randomBytes6, randomUUID as randomUUID3, timingSafeEqual as timingSafeEqual5 } from "crypto";
|
|
3794
3878
|
|
|
3795
3879
|
// src/auth/common-passwords.ts
|
|
3796
3880
|
var LIST = `
|
|
@@ -4342,7 +4426,7 @@ function read(response, maxBytes, deadline) {
|
|
|
4342
4426
|
var keys = (list) => new Set(list.split(/\s+/).filter(Boolean));
|
|
4343
4427
|
var CONFIG = keys(`secret db serverURL cors cronSecret timeZone webhooks events jobs localization routes admin
|
|
4344
4428
|
upload auth collections globals endpoints cliCommands onRequest fieldTypes apiKeys email backups
|
|
4345
|
-
audit plugins`);
|
|
4429
|
+
audit logs plugins`);
|
|
4346
4430
|
var ADMIN = keys("path locale brand siteURL nav commands modules pages dashboard switcher");
|
|
4347
4431
|
var AUTH = keys(`roles rbac tokenExpiration maxLoginAttempts lockWindow trustedOrigins
|
|
4348
4432
|
resetPasswordExpiration inviteExpiration providers providerSignUp password setupCode members emails`);
|
|
@@ -4350,6 +4434,7 @@ var MEMBERS = keys("roles signUp pages emails");
|
|
|
4350
4434
|
var UPLOAD = keys("dir maxFileSize mimeTypes storage imageSizes fromURL folders privateStorage");
|
|
4351
4435
|
var BACKUPS = keys("frequency at keep dir storage sqlite encryptionKey");
|
|
4352
4436
|
var AUDIT = keys("keepDays values failedLogins scope");
|
|
4437
|
+
var LOGS = keys("format requests");
|
|
4353
4438
|
var COLLECTION = keys(`slug labels fields useAsTitle drafts versions schedule preview access hooks
|
|
4354
4439
|
admin`);
|
|
4355
4440
|
var GLOBAL = keys("slug label fields drafts versions schedule preview access hooks scope admin");
|
|
@@ -4472,6 +4557,7 @@ function checkConfigKeys(config, add) {
|
|
|
4472
4557
|
check2(c.upload, "upload", "upload", UPLOAD, add);
|
|
4473
4558
|
check2(c.backups, "backups", "backups", BACKUPS, add);
|
|
4474
4559
|
if (isObject(c.audit)) check2(c.audit, "audit", "audit", AUDIT, add);
|
|
4560
|
+
check2(c.logs, "logs", "logs", LOGS, add);
|
|
4475
4561
|
for (const [kind, list] of [
|
|
4476
4562
|
["collections", c.collections],
|
|
4477
4563
|
["globals", c.globals]
|
|
@@ -4661,7 +4747,9 @@ var Webhooks = class {
|
|
|
4661
4747
|
return this.attempt(hook, delivery.event, delivery.body, delivery.delivery);
|
|
4662
4748
|
}
|
|
4663
4749
|
track(delivery) {
|
|
4664
|
-
const tracked = delivery.catch(
|
|
4750
|
+
const tracked = delivery.catch(
|
|
4751
|
+
(error) => this.logger.error(`Webhook queue failed: ${error.message}`, { error })
|
|
4752
|
+
).finally(() => this.pending.delete(tracked));
|
|
4665
4753
|
this.pending.add(tracked);
|
|
4666
4754
|
}
|
|
4667
4755
|
async deliver(hook, payload) {
|
|
@@ -4686,7 +4774,7 @@ var Webhooks = class {
|
|
|
4686
4774
|
try {
|
|
4687
4775
|
queued = await saved;
|
|
4688
4776
|
} catch (error) {
|
|
4689
|
-
this.logger.error(`Could not save webhook delivery: ${error.message}
|
|
4777
|
+
this.logger.error(`Could not save webhook delivery: ${error.message}`, { error });
|
|
4690
4778
|
}
|
|
4691
4779
|
for (let attempt = 0; ; attempt++) {
|
|
4692
4780
|
const result = await this.attempt(hook, event, body, delivery);
|
|
@@ -4773,7 +4861,9 @@ var RESERVED_SLUGS = /* @__PURE__ */ new Set([
|
|
|
4773
4861
|
"jobs",
|
|
4774
4862
|
"auth",
|
|
4775
4863
|
"migrations",
|
|
4776
|
-
"access"
|
|
4864
|
+
"access",
|
|
4865
|
+
"healthz",
|
|
4866
|
+
"readyz"
|
|
4777
4867
|
]);
|
|
4778
4868
|
var SYSTEM_FIELD_NAMES = /* @__PURE__ */ new Set(["id", "createdAt", "updatedAt"]);
|
|
4779
4869
|
var SLUG_PATTERN = /^[a-z][a-z0-9_-]*$/;
|
|
@@ -4797,6 +4887,7 @@ function validateConfig(config) {
|
|
|
4797
4887
|
validateUpload(config, add);
|
|
4798
4888
|
validateBackups(config, add, (issue) => issues.push(issue));
|
|
4799
4889
|
validateAudit(config, add);
|
|
4890
|
+
validateLogs(config, add);
|
|
4800
4891
|
validateAuth(config, add);
|
|
4801
4892
|
validateCors(config.cors, add);
|
|
4802
4893
|
validateLocalization(config, add);
|
|
@@ -5419,6 +5510,19 @@ function validateUpload(config, add) {
|
|
|
5419
5510
|
var FOLDER_KEY = /^[a-z0-9][a-z0-9_-]{0,59}$/;
|
|
5420
5511
|
var MIME_PATTERN = /^([\w.+-]+\/(\*|[\w.+-]+)|documents|office|archives)$/i;
|
|
5421
5512
|
var HOST_PATTERN = /^(\*|(\*\.)?[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*)$/i;
|
|
5513
|
+
function validateLogs(config, add) {
|
|
5514
|
+
const logs = config.logs;
|
|
5515
|
+
if (logs === void 0) return;
|
|
5516
|
+
if (typeof logs !== "object" || logs === null) {
|
|
5517
|
+
add("logs", "must be an object", "e.g. logs: { format: 'json' }");
|
|
5518
|
+
return;
|
|
5519
|
+
}
|
|
5520
|
+
const { format, requests } = logs;
|
|
5521
|
+
if (format !== void 0 && format !== "pretty" && format !== "json")
|
|
5522
|
+
add("logs.format", "must be 'pretty' or 'json'");
|
|
5523
|
+
if (requests !== void 0 && typeof requests !== "boolean")
|
|
5524
|
+
add("logs.requests", "must be true or false");
|
|
5525
|
+
}
|
|
5422
5526
|
function validateAudit(config, add) {
|
|
5423
5527
|
const audit = config.audit;
|
|
5424
5528
|
if (audit !== void 0 && typeof audit !== "boolean") {
|
|
@@ -5933,6 +6037,8 @@ var RESERVED_ENDPOINT_ROOTS = /* @__PURE__ */ new Set([
|
|
|
5933
6037
|
"media",
|
|
5934
6038
|
"api-keys",
|
|
5935
6039
|
"auth",
|
|
6040
|
+
"healthz",
|
|
6041
|
+
"readyz",
|
|
5936
6042
|
// Kept free for later versions.
|
|
5937
6043
|
"system",
|
|
5938
6044
|
"health",
|
|
@@ -6056,12 +6162,13 @@ function validateEndpoints(config, collectionSlugs, add) {
|
|
|
6056
6162
|
const taken = [
|
|
6057
6163
|
config.routes?.api ?? "/api/cms",
|
|
6058
6164
|
`/${(config.admin?.path ?? "/admin").replace(/^\/+|\/+$/g, "")}`,
|
|
6059
|
-
"/healthz"
|
|
6165
|
+
"/healthz",
|
|
6166
|
+
"/readyz"
|
|
6060
6167
|
].map((p) => p.replace(/\/+$/, "")).find((p) => route2 === p || route2.startsWith(`${p}/`) || p.startsWith(`${route2}/`));
|
|
6061
6168
|
if (taken)
|
|
6062
6169
|
add(
|
|
6063
6170
|
`${path}.path`,
|
|
6064
|
-
`"${route2}" is served by ${taken === "/healthz" ? "the standalone server" : `"${taken}"`}`
|
|
6171
|
+
`"${route2}" is served by ${taken === "/healthz" || taken === "/readyz" ? "the standalone server" : `"${taken}"`}`
|
|
6065
6172
|
);
|
|
6066
6173
|
} else if (RESERVED_ENDPOINT_ROOTS.has(first) || collectionSlugs.has(first)) {
|
|
6067
6174
|
add(
|
|
@@ -6287,7 +6394,7 @@ function resolveAudit(audit) {
|
|
|
6287
6394
|
// src/local-api.ts
|
|
6288
6395
|
async function createEasyCMS(config, options = {}) {
|
|
6289
6396
|
const resolved3 = await resolveConfig(config);
|
|
6290
|
-
const logger = options.logger ?? consoleLogger;
|
|
6397
|
+
const logger = options.logger ?? (logFormat(resolved3.logs) === "json" ? jsonLogger() : consoleLogger);
|
|
6291
6398
|
for (const warning of resolved3.warnings)
|
|
6292
6399
|
logger.warn(
|
|
6293
6400
|
`Config: ${warning.path} ${warning.message}${warning.hint ? ` (${warning.hint})` : ""}`
|
|
@@ -7142,7 +7249,9 @@ var EasyCMS = class {
|
|
|
7142
7249
|
try {
|
|
7143
7250
|
return config.preview({ doc, locale }) ?? null;
|
|
7144
7251
|
} catch (error) {
|
|
7145
|
-
this.logger.error(`preview URL of "${config.slug}" failed: ${error.message}
|
|
7252
|
+
this.logger.error(`preview URL of "${config.slug}" failed: ${error.message}`, {
|
|
7253
|
+
error
|
|
7254
|
+
});
|
|
7146
7255
|
return null;
|
|
7147
7256
|
}
|
|
7148
7257
|
}
|
|
@@ -7628,7 +7737,7 @@ var EasyCMS = class {
|
|
|
7628
7737
|
if (this.schedulerTimer) return;
|
|
7629
7738
|
this.schedulerTimer = setInterval(() => {
|
|
7630
7739
|
void this.runJobs().catch(
|
|
7631
|
-
(error) => this.logger.error(`Scheduled jobs failed: ${error.message}
|
|
7740
|
+
(error) => this.logger.error(`Scheduled jobs failed: ${error.message}`, { error })
|
|
7632
7741
|
);
|
|
7633
7742
|
}, interval);
|
|
7634
7743
|
this.schedulerTimer.unref?.();
|
|
@@ -7644,13 +7753,20 @@ var EasyCMS = class {
|
|
|
7644
7753
|
return run;
|
|
7645
7754
|
}
|
|
7646
7755
|
runJobsNow(now) {
|
|
7647
|
-
|
|
7756
|
+
const requestId = auditContext.getStore()?.requestId;
|
|
7757
|
+
const run = {
|
|
7758
|
+
via: "scheduler",
|
|
7759
|
+
user: null,
|
|
7760
|
+
runId: randomUUID3(),
|
|
7761
|
+
...requestId ? { requestId } : {}
|
|
7762
|
+
};
|
|
7763
|
+
return auditContext.run(run, async () => {
|
|
7648
7764
|
const scheduled = await this.runScheduled(now);
|
|
7649
7765
|
await this.pruneFailedDeliveries(now);
|
|
7650
7766
|
await runDueBackups(this, now).catch(
|
|
7651
|
-
(error) => this.logger.error(`Backups: ${error.message}
|
|
7767
|
+
(error) => this.logger.error(`Backups: ${error.message}`, { error })
|
|
7652
7768
|
);
|
|
7653
|
-
await this.audit.upkeep(now).catch((error) => this.logger.error(`Audit log: ${error.message}
|
|
7769
|
+
await this.audit.upkeep(now).catch((error) => this.logger.error(`Audit log: ${error.message}`, { error }));
|
|
7654
7770
|
const result = {
|
|
7655
7771
|
scheduled,
|
|
7656
7772
|
webhooks: await this.retryWebhooks(now),
|
|
@@ -7658,7 +7774,7 @@ var EasyCMS = class {
|
|
|
7658
7774
|
jobs: await this.runConfigJobs(now)
|
|
7659
7775
|
};
|
|
7660
7776
|
const ranAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
7661
|
-
await this.db.updateGlobal({ slug: JOBS_RAN, data: { at: ranAt, updatedAt: ranAt } }).catch((error) => this.logger.error(`Jobs: ${error.message}
|
|
7777
|
+
await this.db.updateGlobal({ slug: JOBS_RAN, data: { at: ranAt, updatedAt: ranAt } }).catch((error) => this.logger.error(`Jobs: ${error.message}`, { error }));
|
|
7662
7778
|
return result;
|
|
7663
7779
|
});
|
|
7664
7780
|
}
|
|
@@ -7730,10 +7846,10 @@ var EasyCMS = class {
|
|
|
7730
7846
|
} catch (caught) {
|
|
7731
7847
|
failed++;
|
|
7732
7848
|
error = (caught.message || String(caught)).slice(0, 500);
|
|
7733
|
-
this.logger.error(`Job ${job.name} failed: ${error}
|
|
7849
|
+
this.logger.error(`Job ${job.name} failed: ${error}`, { error: caught, job: job.name });
|
|
7734
7850
|
}
|
|
7735
7851
|
await this.recordJobRun(job.name, stamp, error, Date.now() - started).catch(
|
|
7736
|
-
(caught) => this.logger.error(`Job ${job.name}: ${caught.message}
|
|
7852
|
+
(caught) => this.logger.error(`Job ${job.name}: ${caught.message}`, { error: caught })
|
|
7737
7853
|
);
|
|
7738
7854
|
}
|
|
7739
7855
|
return { ran, failed };
|
|
@@ -7898,7 +8014,9 @@ var EasyCMS = class {
|
|
|
7898
8014
|
} catch (error) {
|
|
7899
8015
|
failed++;
|
|
7900
8016
|
const message2 = error.message;
|
|
7901
|
-
this.logger.error(`Scheduled ${action} of ${parent} ${row.doc} failed: ${message2}
|
|
8017
|
+
this.logger.error(`Scheduled ${action} of ${parent} ${row.doc} failed: ${message2}`, {
|
|
8018
|
+
error
|
|
8019
|
+
});
|
|
7902
8020
|
await this.db.update({
|
|
7903
8021
|
collection: SCHEDULED_JOBS,
|
|
7904
8022
|
id: row.id,
|
|
@@ -9688,7 +9806,10 @@ async function readAdminModule(cms, index) {
|
|
|
9688
9806
|
}
|
|
9689
9807
|
|
|
9690
9808
|
// src/version.ts
|
|
9691
|
-
var VERSION = true ? "1.
|
|
9809
|
+
var VERSION = true ? "1.7.0" : "0.0.0-dev";
|
|
9810
|
+
|
|
9811
|
+
// src/rest/handler.ts
|
|
9812
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
9692
9813
|
|
|
9693
9814
|
// src/rest/admin-deliveries.ts
|
|
9694
9815
|
var PER_PAGE = 50;
|
|
@@ -10635,7 +10756,43 @@ function withCors(cms, handle) {
|
|
|
10635
10756
|
return withHeaders(await handle(request), cors);
|
|
10636
10757
|
};
|
|
10637
10758
|
}
|
|
10759
|
+
var HEALTH_CHECKS = /* @__PURE__ */ new Map([
|
|
10760
|
+
["healthz", "healthz"],
|
|
10761
|
+
["readyz", "readyz"]
|
|
10762
|
+
]);
|
|
10763
|
+
var REQUEST_ID = /^[\w.-]{1,128}$/;
|
|
10638
10764
|
async function respond(cms, request, url, path, root, options, production) {
|
|
10765
|
+
const started = performance.now();
|
|
10766
|
+
const incoming = request.headers.get("x-request-id");
|
|
10767
|
+
const requestId = incoming && REQUEST_ID.test(incoming) ? incoming : randomUUID4();
|
|
10768
|
+
const requestLog = { userId: void 0 };
|
|
10769
|
+
const response = await auditContext.run(
|
|
10770
|
+
{ requestId },
|
|
10771
|
+
() => respondNow(cms, request, url, path, root, options, production, requestId, requestLog)
|
|
10772
|
+
);
|
|
10773
|
+
let tagged;
|
|
10774
|
+
try {
|
|
10775
|
+
response.headers.set("x-request-id", requestId);
|
|
10776
|
+
tagged = response;
|
|
10777
|
+
} catch {
|
|
10778
|
+
tagged = withHeaders(response, new Headers({ "x-request-id": requestId }));
|
|
10779
|
+
}
|
|
10780
|
+
const probe = !root && (path === "/healthz" || path === "/readyz");
|
|
10781
|
+
if (!probe && cms.config.logs?.requests !== false && isJsonLogger(cms.logger)) {
|
|
10782
|
+
auditContext.run(
|
|
10783
|
+
{ requestId },
|
|
10784
|
+
() => cms.logger.info(`${request.method} ${url.pathname} ${tagged.status}`, {
|
|
10785
|
+
method: request.method,
|
|
10786
|
+
path: url.pathname,
|
|
10787
|
+
status: tagged.status,
|
|
10788
|
+
durationMs: Math.round(performance.now() - started),
|
|
10789
|
+
...requestLog.userId === void 0 ? {} : { userId: requestLog.userId }
|
|
10790
|
+
})
|
|
10791
|
+
);
|
|
10792
|
+
}
|
|
10793
|
+
return tagged;
|
|
10794
|
+
}
|
|
10795
|
+
async function respondNow(cms, request, url, path, root, options, production, requestId, requestLog) {
|
|
10639
10796
|
const headers = new Headers({
|
|
10640
10797
|
"content-type": "application/json; charset=utf-8",
|
|
10641
10798
|
"cache-control": "no-store",
|
|
@@ -10645,11 +10802,21 @@ async function respond(cms, request, url, path, root, options, production) {
|
|
|
10645
10802
|
try {
|
|
10646
10803
|
if (path === null) throw new HttpError("Not found", 404);
|
|
10647
10804
|
const segments = pathSegments(path);
|
|
10805
|
+
const probe = !root && segments.length === 1 ? HEALTH_CHECKS.get(segments[0]) : void 0;
|
|
10806
|
+
if (probe) {
|
|
10807
|
+
const method2 = request.method.toUpperCase();
|
|
10808
|
+
if (method2 !== "GET" && method2 !== "HEAD") {
|
|
10809
|
+
headers.set("allow", "GET, HEAD");
|
|
10810
|
+
throw new HttpError("Method not allowed", 405);
|
|
10811
|
+
}
|
|
10812
|
+
return await healthResponse(probe, cms);
|
|
10813
|
+
}
|
|
10648
10814
|
const { token, via } = readToken(request);
|
|
10649
10815
|
const signedIn = token ? await cms.auth.verify(token) : null;
|
|
10650
10816
|
if (!signedIn && via === "bearer" && token?.startsWith("ecms_"))
|
|
10651
10817
|
throw new UnauthorizedError("Invalid or expired API key");
|
|
10652
10818
|
const { user, context } = await cms.applyOnRequest(request.headers, url, signedIn);
|
|
10819
|
+
requestLog.userId = user?.id;
|
|
10653
10820
|
const ctx = {
|
|
10654
10821
|
request,
|
|
10655
10822
|
url,
|
|
@@ -10666,7 +10833,8 @@ async function respond(cms, request, url, path, root, options, production) {
|
|
|
10666
10833
|
user,
|
|
10667
10834
|
context,
|
|
10668
10835
|
ip: options.getClientIp?.(request),
|
|
10669
|
-
userAgent: request.headers.get("user-agent")
|
|
10836
|
+
userAgent: request.headers.get("user-agent"),
|
|
10837
|
+
requestId
|
|
10670
10838
|
};
|
|
10671
10839
|
const result = await auditContext.run(
|
|
10672
10840
|
audit,
|
|
@@ -11851,7 +12019,7 @@ function errorResponse(cms, error, headers, production) {
|
|
|
11851
12019
|
if (error instanceof TooManyRequestsError && error.retryAfter !== void 0)
|
|
11852
12020
|
headers.set("retry-after", String(error.retryAfter));
|
|
11853
12021
|
if (error.status >= 500) {
|
|
11854
|
-
cms.logger.error(`REST request failed: ${error.
|
|
12022
|
+
cms.logger.error(`REST request failed: ${error.message}`, { error });
|
|
11855
12023
|
if (production)
|
|
11856
12024
|
return new Response(
|
|
11857
12025
|
JSON.stringify({ errors: [{ message: "Internal Server Error", code }] }),
|
|
@@ -11861,9 +12029,7 @@ function errorResponse(cms, error, headers, production) {
|
|
|
11861
12029
|
return new Response(JSON.stringify({ errors }), { status: error.status, headers });
|
|
11862
12030
|
}
|
|
11863
12031
|
const message2 = error instanceof Error ? error.message : String(error);
|
|
11864
|
-
cms.logger.error(
|
|
11865
|
-
`REST request failed: ${error instanceof Error ? error.stack ?? message2 : message2}`
|
|
11866
|
-
);
|
|
12032
|
+
cms.logger.error(`REST request failed: ${message2}`, { error });
|
|
11867
12033
|
const body = {
|
|
11868
12034
|
errors: [
|
|
11869
12035
|
{ message: production ? "Internal Server Error" : message2, code: "INTERNAL_SERVER_ERROR" }
|
|
@@ -11901,8 +12067,21 @@ function platformClientIp(headers) {
|
|
|
11901
12067
|
function createApiHandler(config, options = {}) {
|
|
11902
12068
|
const handlers = /* @__PURE__ */ new WeakMap();
|
|
11903
12069
|
const getClientIp = options.getClientIp ?? (options.trustProxy ? (r) => forwardedClientIp(r.headers.get("x-forwarded-for")) : (r) => platformClientIp(r.headers));
|
|
12070
|
+
const base = (options.basePath ?? config.routes?.api ?? "/api/cms").replace(/\/+$/, "");
|
|
11904
12071
|
return async (request) => {
|
|
11905
|
-
|
|
12072
|
+
let cms;
|
|
12073
|
+
try {
|
|
12074
|
+
cms = await sharedEasyCMS(config);
|
|
12075
|
+
} catch (error) {
|
|
12076
|
+
const { pathname } = new URL(request.url);
|
|
12077
|
+
const probe = pathname === `${base}/healthz` ? "healthz" : pathname === `${base}/readyz` ? "readyz" : null;
|
|
12078
|
+
if (!probe) throw error;
|
|
12079
|
+
if (probe === "readyz") {
|
|
12080
|
+
const logger = logFormat(config.logs) === "json" ? jsonLogger() : consoleLogger;
|
|
12081
|
+
logger.error(`Readiness check failed: ${error.message}`, { error });
|
|
12082
|
+
}
|
|
12083
|
+
return healthResponse(probe, null);
|
|
12084
|
+
}
|
|
11906
12085
|
let handler = handlers.get(cms);
|
|
11907
12086
|
if (!handler) {
|
|
11908
12087
|
handler = createRestHandler(cms, {
|
|
@@ -12000,12 +12179,16 @@ export {
|
|
|
12000
12179
|
validateFields,
|
|
12001
12180
|
consoleEmail,
|
|
12002
12181
|
configSignature,
|
|
12182
|
+
healthResponse,
|
|
12003
12183
|
copyDatabase,
|
|
12004
12184
|
diskStorage,
|
|
12005
12185
|
decryptBackup,
|
|
12006
12186
|
writeBackupFile,
|
|
12007
12187
|
consoleLogger,
|
|
12008
12188
|
silentLogger,
|
|
12189
|
+
logFormat,
|
|
12190
|
+
isJsonLogger,
|
|
12191
|
+
jsonLogger,
|
|
12009
12192
|
FOLDER_LEVELS,
|
|
12010
12193
|
MediaFolders,
|
|
12011
12194
|
DEFAULT_DEPTH,
|
|
@@ -93,13 +93,35 @@ declare const isSignedIn: Access;
|
|
|
93
93
|
*/
|
|
94
94
|
declare const isAdmin: Access;
|
|
95
95
|
|
|
96
|
+
/** More about a log line: `error` for what failed (its stack goes to the log). */
|
|
97
|
+
interface LogDetails {
|
|
98
|
+
readonly error?: unknown;
|
|
99
|
+
readonly [key: string]: unknown;
|
|
100
|
+
}
|
|
96
101
|
interface Logger {
|
|
97
|
-
info(message: string): void;
|
|
98
|
-
warn(message: string): void;
|
|
99
|
-
error(message: string): void;
|
|
102
|
+
info(message: string, details?: LogDetails): void;
|
|
103
|
+
warn(message: string, details?: LogDetails): void;
|
|
104
|
+
error(message: string, details?: LogDetails): void;
|
|
100
105
|
}
|
|
106
|
+
/** Readable lines for development; an error's stack follows its line. */
|
|
101
107
|
declare const consoleLogger: Logger;
|
|
102
108
|
declare const silentLogger: Logger;
|
|
109
|
+
/** Log line formats: `pretty` for people, `json` (one object per line) for log pipelines. */
|
|
110
|
+
interface LogsConfig {
|
|
111
|
+
/** Default `pretty`. The `EASY_CMS_LOG_FORMAT` environment variable wins over this. */
|
|
112
|
+
readonly format?: 'pretty' | 'json';
|
|
113
|
+
/** In `json`, a line for every API request (method, path, status, duration). Default true. */
|
|
114
|
+
readonly requests?: boolean;
|
|
115
|
+
}
|
|
116
|
+
/** The format in use: `EASY_CMS_LOG_FORMAT`, then the config, then `pretty`. */
|
|
117
|
+
declare function logFormat(logs: LogsConfig | undefined): 'pretty' | 'json';
|
|
118
|
+
/** Whether a logger writes JSON: it then also gets a line per API request (`logs.requests`). */
|
|
119
|
+
declare const isJsonLogger: (logger: Logger) => boolean;
|
|
120
|
+
/**
|
|
121
|
+
* One JSON object per line: `time`, `level`, `name`, `message`, the request's `requestId` (or
|
|
122
|
+
* the job run's `runId`), `error` with its stack, and any other details.
|
|
123
|
+
*/
|
|
124
|
+
declare function jsonLogger(write?: (line: string, level: 'info' | 'warn' | 'error') => void): Logger;
|
|
103
125
|
|
|
104
126
|
/** A document as stored: relationships and uploads are ids, never populated. */
|
|
105
127
|
type RawDocument = Record<string, unknown> & {
|
|
@@ -3281,6 +3303,11 @@ interface Config {
|
|
|
3281
3303
|
* actions, kept for `keep` days. `true` for the defaults.
|
|
3282
3304
|
*/
|
|
3283
3305
|
readonly audit?: boolean | AuditConfig;
|
|
3306
|
+
/**
|
|
3307
|
+
* How Easy CMS writes its logs: `{ format: 'json' }` for one JSON object per line, with the
|
|
3308
|
+
* request id. Ignored when `createEasyCMS` is given a `logger`.
|
|
3309
|
+
*/
|
|
3310
|
+
readonly logs?: LogsConfig;
|
|
3284
3311
|
readonly plugins?: readonly Plugin[];
|
|
3285
3312
|
}
|
|
3286
3313
|
/** The config after plugins ran, validation passed and defaults were applied. */
|
|
@@ -3312,4 +3339,4 @@ interface ResolvedConfig extends Omit<Config, 'cors' | 'localization' | 'routes'
|
|
|
3312
3339
|
*/
|
|
3313
3340
|
declare function defineConfig<const TConfig extends Config>(config: TConfig): TConfig;
|
|
3314
3341
|
|
|
3315
|
-
export { type BuiltinMediaCollection as $, ADAPTER_API_VERSION as A, type ApiKeyOperation as B, type ApiKeyPermissions as C, type ArrayField as D, type EmailSetting as E, type AuditChange as F, type AuditConfig as G, type AuditEntry as H, type ID as I, AuditLog as J, type AuditPage as K, type AuditVerification as L, Auth as M, type AuthConfig as N, type AuthProvider as O, type PaginatedDocs as P, type AuthProviderProfile as Q, type AuthProviderRequest as R, type AuthUser as S, type BackupsConfig as T, type BeforeChangeHook as U, type BeforeDeleteHook as V, type BeforeValidateHook as W, type Block as X, type BlocksField as Y, type BooleanField as Z, type BuiltinApiKeysCollection as _, ADMIN_ICONS as a, type GlobalDocument as a$, type BuiltinMediaFoldersCollection as a0, type BuiltinUsersCollection as a1, type BundleHints as a2, type CliCommand as a3, type CollectionAccess as a4, type CollectionAdmin as a5, type CollectionConfig as a6, type CollectionDocument as a7, type CollectionHooks as a8, type CollectionListAdmin as a9, type EndpointRequest as aA, type ErrorCode as aB, FIELD_TYPES as aC, type Field as aD, type FieldAccess as aE, type FieldAccessFn as aF, type FieldAdmin as aG, type FieldError as aH, type FieldRule as aI, type FieldType as aJ, type FieldTypeBase as aK, type FieldTypeDefinition as aL, type FieldTypeValidateContext as aM, type FieldValidate as aN, type FieldValidateContext as aO, type FieldValue as aP, type FieldsInput as aQ, type FieldsValue as aR, type FilterOptions as aS, type FilterOptionsArgs as aT, type FindArgs as aU, type FindOptions as aV, type FolderLevel as aW, type FolderPermissions as aX, ForbiddenError as aY, type GlobalAccess as aZ, type GlobalConfig as a_, type CollectionSlug as aa, type Config as ab, ConfigError as ac, type ConfigIssue as ad, type ContainerAdmin as ae, type CreateEasyCMSOptions as af, type CreateInput as ag, type CreateMigrationResult as ah, type CustomField as ai, type CustomFieldTypes as aj, type DashboardWidget as ak, type Database as al, type DatabaseAdapter as am, type DatabaseInitArgs as an, type DatabaseTransfer as ao, type DateField as ap, type DepthOptions as aq, type DirectUpload as ar, type DiskStorageOptions as as, type DocumentOf as at, EasyCMS as au, EasyCMSError as av, type EmailAdapter as aw, type EmailField as ax, type EmailMessage as ay, type Endpoint as az, type Access as b, type
|
|
3342
|
+
export { type BuiltinMediaCollection as $, ADAPTER_API_VERSION as A, type ApiKeyOperation as B, type ApiKeyPermissions as C, type ArrayField as D, type EmailSetting as E, type AuditChange as F, type AuditConfig as G, type AuditEntry as H, type ID as I, AuditLog as J, type AuditPage as K, type AuditVerification as L, Auth as M, type AuthConfig as N, type AuthProvider as O, type PaginatedDocs as P, type AuthProviderProfile as Q, type AuthProviderRequest as R, type AuthUser as S, type BackupsConfig as T, type BeforeChangeHook as U, type BeforeDeleteHook as V, type BeforeValidateHook as W, type Block as X, type BlocksField as Y, type BooleanField as Z, type BuiltinApiKeysCollection as _, ADMIN_ICONS as a, type GlobalDocument as a$, type BuiltinMediaFoldersCollection as a0, type BuiltinUsersCollection as a1, type BundleHints as a2, type CliCommand as a3, type CollectionAccess as a4, type CollectionAdmin as a5, type CollectionConfig as a6, type CollectionDocument as a7, type CollectionHooks as a8, type CollectionListAdmin as a9, type EndpointRequest as aA, type ErrorCode as aB, FIELD_TYPES as aC, type Field as aD, type FieldAccess as aE, type FieldAccessFn as aF, type FieldAdmin as aG, type FieldError as aH, type FieldRule as aI, type FieldType as aJ, type FieldTypeBase as aK, type FieldTypeDefinition as aL, type FieldTypeValidateContext as aM, type FieldValidate as aN, type FieldValidateContext as aO, type FieldValue as aP, type FieldsInput as aQ, type FieldsValue as aR, type FilterOptions as aS, type FilterOptionsArgs as aT, type FindArgs as aU, type FindOptions as aV, type FolderLevel as aW, type FolderPermissions as aX, ForbiddenError as aY, type GlobalAccess as aZ, type GlobalConfig as a_, type CollectionSlug as aa, type Config as ab, ConfigError as ac, type ConfigIssue as ad, type ContainerAdmin as ae, type CreateEasyCMSOptions as af, type CreateInput as ag, type CreateMigrationResult as ah, type CustomField as ai, type CustomFieldTypes as aj, type DashboardWidget as ak, type Database as al, type DatabaseAdapter as am, type DatabaseInitArgs as an, type DatabaseTransfer as ao, type DateField as ap, type DepthOptions as aq, type DirectUpload as ar, type DiskStorageOptions as as, type DocumentOf as at, EasyCMS as au, EasyCMSError as av, type EmailAdapter as aw, type EmailField as ax, type EmailMessage as ay, type Endpoint as az, type Access as b, type SignupResult as b$, type GlobalHooks as b0, type GlobalInput as b1, type GlobalSlug as b2, type GroupField as b3, type ImageSize as b4, type IncrementOptions as b5, type InferCollection as b6, type InferGlobal as b7, type JobConfig as b8, type JsonField as b9, type Plugin as bA, type PluginInfo as bB, type PluginTypes as bC, type PreviewTarget as bD, type PreviewURL as bE, QueryError as bF, ROLE_OPERATIONS as bG, type RawDocument as bH, type ReadOptions as bI, type RelationshipField as bJ, type RequestContext as bK, type ResolvedConfig as bL, type RichTextDocument as bM, type RichTextField as bN, type Role as bO, type RoleOperation as bP, type RolePermissions as bQ, Roles as bR, type RoutesConfig as bS, type ScheduledPublish as bT, SchemaError as bU, type SchemaMode as bV, type SelectField as bW, type SelectOption as bX, type Session as bY, type SidebarPanel as bZ, type SignupArgs as b_, type Label as ba, type LayoutNode as bb, type LivePreview as bc, type LocaleOf as bd, type LocalizationConfig as be, type LogDetails as bf, type Logger as bg, type LoginArgs as bh, type LogsConfig as bi, type MediaDocument as bj, type MediaSize as bk, type MembersConfig as bl, type MembersSignup as bm, type MigrationInfo as bn, type NavGroup as bo, NotFoundError as bp, type NumberField as bq, type OnRequest as br, type OnRequestArgs as bs, type Operation as bt, PLUGIN_API_VERSION as bu, type PasswordEmail as bv, type PasswordEmailArgs as bw, type PasswordEmailFn as bx, type PasswordLinkOptions as by, PayloadTooLargeError as bz, type AccessArgs as c, SingleSignOn as c0, type SlugField as c1, type SlugOf as c2, type SsoOutcome as c3, type SsoProviderRef as c4, type StorageAdapter as c5, type StoredFile as c6, type TextField as c7, type TextareaField as c8, TooManyRequestsError as c9, hasRows as cA, isAdmin as cB, isHasMany as cC, isSignedIn as cD, isStaff as cE, isSystemAdmin as cF, jsonLogger as cG, mimeAllowedBy as cH, rowFields as cI, silentLogger as cJ, uniqueWithinOf as cK, API_KEYS as cL, API_KEY_GLOBAL_OPERATIONS as cM, API_KEY_OPERATIONS as cN, DEFAULT_MAX_VERSIONS as cO, DEFAULT_PASSWORD_EMAILS as cP, FIELD_TYPE_BASES as cQ, FOLDER_LEVELS as cR, MediaFolders as cS, SSO_COOKIE as cT, codeOfStatus as cU, isJsonLogger as cV, keyAllows as cW, logFormat as cX, type TypedPlugin as ca, UnauthorizedError as cb, type UpdateInput as cc, type UpdateOptions as cd, type UploadConfig as ce, type UploadField as cf, type UploadFromURLConfig as cg, type UserIdentity as ch, ValidationError as ci, type Version as cj, type VersionSummary as ck, type VersionsConfig as cl, WEBHOOK_EVENTS as cm, type WebhookConfig as cn, type WebhookEvent as co, type WebhookPayload as cp, type Where as cq, type WhereOperators as cr, anyone as cs, consoleEmail as ct, consoleLogger as cu, createEasyCMS as cv, defineConfig as cw, defineFieldType as cx, definePlugin as cy, diskStorage as cz, type AccessOptions as d, type AdminBrand as e, type AdminCommand as f, type AdminComponent as g, type AdminConfig as h, type AdminFieldArgs as i, type AdminIcon as j, type AdminLocale as k, type AdminPage as l, type AdminRole as m, type AdminRoleChange as n, type AdminRoleField as o, type AdminRoleTarget as p, type AdminRoleView as q, type AdminRoles as r, type AdminSso as s, type AdminSwitcher as t, type AdminViewAccess as u, type AfterChangeHook as v, type AfterDeleteHook as w, type AfterReadHook as x, type ApiKeyContext as y, type ApiKeyGlobalOperation as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { I as ID, ab as Config, au as EasyCMS, be as LocalizationConfig, aD as Field, aH as FieldError, aS as FilterOptions, af as CreateEasyCMSOptions,
|
|
1
|
+
import { I as ID, ab as Config, au as EasyCMS, be as LocalizationConfig, aD as Field, aH as FieldError, aS as FilterOptions, af as CreateEasyCMSOptions, bL as ResolvedConfig } from './config-CzW6kBeb.js';
|
|
2
2
|
|
|
3
3
|
/** Decrypts a file from `encryptBackup`; throws for another key or a changed file. */
|
|
4
4
|
declare function decryptBackup(data: Uint8Array, encryptionKey: string): Uint8Array;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { P as PaginatedDocs, I as ID, E as EmailSetting } from './config-
|
|
2
|
-
export { A as ADAPTER_API_VERSION, a as ADMIN_ICONS, b as Access, c as AccessArgs, d as AccessOptions, e as AdminBrand, f as AdminCommand, g as AdminComponent, h as AdminConfig, i as AdminFieldArgs, j as AdminIcon, k as AdminLocale, l as AdminPage, m as AdminRole, n as AdminRoleChange, o as AdminRoleField, p as AdminRoleTarget, q as AdminRoleView, r as AdminRoles, s as AdminSso, t as AdminSwitcher, u as AdminViewAccess, v as AfterChangeHook, w as AfterDeleteHook, x as AfterReadHook, y as ApiKeyContext, z as ApiKeyGlobalOperation, B as ApiKeyOperation, C as ApiKeyPermissions, D as ArrayField, F as AuditChange, G as AuditConfig, H as AuditEntry, J as AuditLog, K as AuditPage, L as AuditVerification, M as Auth, N as AuthConfig, O as AuthProvider, Q as AuthProviderProfile, R as AuthProviderRequest, S as AuthUser, T as BackupsConfig, U as BeforeChangeHook, V as BeforeDeleteHook, W as BeforeValidateHook, X as Block, Y as BlocksField, Z as BooleanField, _ as BuiltinApiKeysCollection, $ as BuiltinMediaCollection, a0 as BuiltinMediaFoldersCollection, a1 as BuiltinUsersCollection, a2 as BundleHints, a3 as CliCommand, a4 as CollectionAccess, a5 as CollectionAdmin, a6 as CollectionConfig, a7 as CollectionDocument, a8 as CollectionHooks, a9 as CollectionListAdmin, aa as CollectionSlug, ab as Config, ac as ConfigError, ad as ConfigIssue, ae as ContainerAdmin, af as CreateEasyCMSOptions, ag as CreateInput, ah as CreateMigrationResult, ai as CustomField, aj as CustomFieldTypes, ak as DashboardWidget, al as Database, am as DatabaseAdapter, an as DatabaseInitArgs, ao as DatabaseTransfer, ap as DateField, aq as DepthOptions, ar as DirectUpload, as as DiskStorageOptions, at as DocumentOf, au as EasyCMS, av as EasyCMSError, aw as EmailAdapter, ax as EmailField, ay as EmailMessage, az as Endpoint, aA as EndpointRequest, aB as ErrorCode, aC as FIELD_TYPES, aD as Field, aE as FieldAccess, aF as FieldAccessFn, aG as FieldAdmin, aH as FieldError, aI as FieldRule, aJ as FieldType, aK as FieldTypeBase, aL as FieldTypeDefinition, aM as FieldTypeValidateContext, aN as FieldValidate, aO as FieldValidateContext, aP as FieldValue, aQ as FieldsInput, aR as FieldsValue, aS as FilterOptions, aT as FilterOptionsArgs, aU as FindArgs, aV as FindOptions, aW as FolderLevel, aX as FolderPermissions, aY as ForbiddenError, aZ as GlobalAccess, a_ as GlobalConfig, a$ as GlobalDocument, b0 as GlobalHooks, b1 as GlobalInput, b2 as GlobalSlug, b3 as GroupField, b4 as ImageSize, b5 as IncrementOptions, b6 as InferCollection, b7 as InferGlobal, b8 as JobConfig, b9 as JsonField, ba as Label, bb as LayoutNode, bc as LivePreview, bd as LocaleOf, be as LocalizationConfig, bf as
|
|
3
|
-
export { A as ADMIN_API_VERSION, a as AdminCollection, b as AdminComponentRef, c as AdminElementProps, d as AdminField, e as AdminGlobal, f as AdminLayoutNode, g as AdminNavGroup, h as AdminNavItem, i as AdminNavNode, j as AdminPageRef, k as AdminPageRoute, l as AdminSchema, m as AdminWidgetRef, S as SetFieldDetail, w as warnDeprecated } from './plugin-
|
|
4
|
-
export { A as AdminBackup, a as AdminBackups, b as ApiHandlerOptions, B as BackupState, L as LoadConfigOptions, R as RestHandler, c as RestHandlerOptions, d as createApiHandler, e as createRestHandler, l as loadConfig, r as resolveConfig, s as sharedEasyCMS, f as slugify } from './handler-
|
|
1
|
+
import { P as PaginatedDocs, I as ID, E as EmailSetting } from './config-CzW6kBeb.js';
|
|
2
|
+
export { A as ADAPTER_API_VERSION, a as ADMIN_ICONS, b as Access, c as AccessArgs, d as AccessOptions, e as AdminBrand, f as AdminCommand, g as AdminComponent, h as AdminConfig, i as AdminFieldArgs, j as AdminIcon, k as AdminLocale, l as AdminPage, m as AdminRole, n as AdminRoleChange, o as AdminRoleField, p as AdminRoleTarget, q as AdminRoleView, r as AdminRoles, s as AdminSso, t as AdminSwitcher, u as AdminViewAccess, v as AfterChangeHook, w as AfterDeleteHook, x as AfterReadHook, y as ApiKeyContext, z as ApiKeyGlobalOperation, B as ApiKeyOperation, C as ApiKeyPermissions, D as ArrayField, F as AuditChange, G as AuditConfig, H as AuditEntry, J as AuditLog, K as AuditPage, L as AuditVerification, M as Auth, N as AuthConfig, O as AuthProvider, Q as AuthProviderProfile, R as AuthProviderRequest, S as AuthUser, T as BackupsConfig, U as BeforeChangeHook, V as BeforeDeleteHook, W as BeforeValidateHook, X as Block, Y as BlocksField, Z as BooleanField, _ as BuiltinApiKeysCollection, $ as BuiltinMediaCollection, a0 as BuiltinMediaFoldersCollection, a1 as BuiltinUsersCollection, a2 as BundleHints, a3 as CliCommand, a4 as CollectionAccess, a5 as CollectionAdmin, a6 as CollectionConfig, a7 as CollectionDocument, a8 as CollectionHooks, a9 as CollectionListAdmin, aa as CollectionSlug, ab as Config, ac as ConfigError, ad as ConfigIssue, ae as ContainerAdmin, af as CreateEasyCMSOptions, ag as CreateInput, ah as CreateMigrationResult, ai as CustomField, aj as CustomFieldTypes, ak as DashboardWidget, al as Database, am as DatabaseAdapter, an as DatabaseInitArgs, ao as DatabaseTransfer, ap as DateField, aq as DepthOptions, ar as DirectUpload, as as DiskStorageOptions, at as DocumentOf, au as EasyCMS, av as EasyCMSError, aw as EmailAdapter, ax as EmailField, ay as EmailMessage, az as Endpoint, aA as EndpointRequest, aB as ErrorCode, aC as FIELD_TYPES, aD as Field, aE as FieldAccess, aF as FieldAccessFn, aG as FieldAdmin, aH as FieldError, aI as FieldRule, aJ as FieldType, aK as FieldTypeBase, aL as FieldTypeDefinition, aM as FieldTypeValidateContext, aN as FieldValidate, aO as FieldValidateContext, aP as FieldValue, aQ as FieldsInput, aR as FieldsValue, aS as FilterOptions, aT as FilterOptionsArgs, aU as FindArgs, aV as FindOptions, aW as FolderLevel, aX as FolderPermissions, aY as ForbiddenError, aZ as GlobalAccess, a_ as GlobalConfig, a$ as GlobalDocument, b0 as GlobalHooks, b1 as GlobalInput, b2 as GlobalSlug, b3 as GroupField, b4 as ImageSize, b5 as IncrementOptions, b6 as InferCollection, b7 as InferGlobal, b8 as JobConfig, b9 as JsonField, ba as Label, bb as LayoutNode, bc as LivePreview, bd as LocaleOf, be as LocalizationConfig, bf as LogDetails, bg as Logger, bh as LoginArgs, bi as LogsConfig, bj as MediaDocument, bk as MediaSize, bl as MembersConfig, bm as MembersSignup, bn as MigrationInfo, bo as NavGroup, bp as NotFoundError, bq as NumberField, br as OnRequest, bs as OnRequestArgs, bt as Operation, bu as PLUGIN_API_VERSION, bv as PasswordEmail, bw as PasswordEmailArgs, bx as PasswordEmailFn, by as PasswordLinkOptions, bz as PayloadTooLargeError, bA as Plugin, bB as PluginInfo, bC as PluginTypes, bD as PreviewTarget, bE as PreviewURL, bF as QueryError, bG as ROLE_OPERATIONS, bH as RawDocument, bI as ReadOptions, bJ as RelationshipField, bK as RequestContext, bL as ResolvedConfig, bM as RichTextDocument, bN as RichTextField, bO as Role, bP as RoleOperation, bQ as RolePermissions, bR as Roles, bS as RoutesConfig, bT as ScheduledPublish, bU as SchemaError, bV as SchemaMode, bW as SelectField, bX as SelectOption, bY as Session, bZ as SidebarPanel, b_ as SignupArgs, b$ as SignupResult, c0 as SingleSignOn, c1 as SlugField, c2 as SlugOf, c3 as SsoOutcome, c4 as SsoProviderRef, c5 as StorageAdapter, c6 as StoredFile, c7 as TextField, c8 as TextareaField, c9 as TooManyRequestsError, ca as TypedPlugin, cb as UnauthorizedError, cc as UpdateInput, cd as UpdateOptions, ce as UploadConfig, cf as UploadField, cg as UploadFromURLConfig, ch as UserIdentity, ci as ValidationError, cj as Version, ck as VersionSummary, cl as VersionsConfig, cm as WEBHOOK_EVENTS, cn as WebhookConfig, co as WebhookEvent, cp as WebhookPayload, cq as Where, cr as WhereOperators, cs as anyone, ct as consoleEmail, cu as consoleLogger, cv as createEasyCMS, cw as defineConfig, cx as defineFieldType, cy as definePlugin, cz as diskStorage, cA as hasRows, cB as isAdmin, cC as isHasMany, cD as isSignedIn, cE as isStaff, cF as isSystemAdmin, cG as jsonLogger, cH as mimeAllowedBy, cI as rowFields, cJ as silentLogger, cK as uniqueWithinOf } from './config-CzW6kBeb.js';
|
|
3
|
+
export { A as ADMIN_API_VERSION, a as AdminCollection, b as AdminComponentRef, c as AdminElementProps, d as AdminField, e as AdminGlobal, f as AdminLayoutNode, g as AdminNavGroup, h as AdminNavItem, i as AdminNavNode, j as AdminPageRef, k as AdminPageRoute, l as AdminSchema, m as AdminWidgetRef, S as SetFieldDetail, w as warnDeprecated } from './plugin-BmKxHxuu.js';
|
|
4
|
+
export { A as AdminBackup, a as AdminBackups, b as ApiHandlerOptions, B as BackupState, L as LoadConfigOptions, R as RestHandler, c as RestHandlerOptions, d as createApiHandler, e as createRestHandler, l as loadConfig, r as resolveConfig, s as sharedEasyCMS, f as slugify } from './handler-BsBQ-2qf.js';
|
|
5
5
|
export { FieldCondition, matchesCondition } from './conditions.js';
|
|
6
6
|
|
|
7
7
|
type DeliveryKind = 'webhook' | 'email';
|
package/dist/index.js
CHANGED
|
@@ -18,12 +18,13 @@ import {
|
|
|
18
18
|
isSignedIn,
|
|
19
19
|
isStaff,
|
|
20
20
|
isSystemAdmin,
|
|
21
|
+
jsonLogger,
|
|
21
22
|
loadConfig,
|
|
22
23
|
resolveConfig,
|
|
23
24
|
sharedEasyCMS,
|
|
24
25
|
silentLogger,
|
|
25
26
|
slugify
|
|
26
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-AVUGFJ4Q.js";
|
|
27
28
|
import {
|
|
28
29
|
matchesCondition
|
|
29
30
|
} from "./chunk-U266LV4M.js";
|
|
@@ -86,6 +87,7 @@ export {
|
|
|
86
87
|
isSignedIn,
|
|
87
88
|
isStaff,
|
|
88
89
|
isSystemAdmin,
|
|
90
|
+
jsonLogger,
|
|
89
91
|
loadConfig,
|
|
90
92
|
matchesCondition,
|
|
91
93
|
resolveConfig,
|
package/dist/internal.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ab as Config, al as Database,
|
|
2
|
-
export {
|
|
3
|
-
export { C as CONFIG_FILE_NAMES, g as CSRF_COOKIE, h as CSRF_HEADER, D as DEFAULT_ADMIN_PATH, i as DEFAULT_API_PATH, j as DEFAULT_MAX_FILE_SIZE, k as DEFAULT_TOKEN_EXPIRATION, m as applyDefaults, n as applyPlugins, o as createRootEndpointHandler, p as decryptBackup, q as fillMissing, t as findConfigFile, u as forwardedClientIp, v as generateSlugs, w as importConfig, x as mergeForUpdate, y as parseId, z as platformClientIp, E as readCookie, F as validateFields, G as writeBackupFile } from './handler-
|
|
1
|
+
import { ab as Config, al as Database, au as EasyCMS, bo as NavGroup, a6 as CollectionConfig, I as ID, bH as RawDocument, aD as Field, bL as ResolvedConfig, ad as ConfigIssue } from './config-CzW6kBeb.js';
|
|
2
|
+
export { cL as API_KEYS, cM as API_KEY_GLOBAL_OPERATIONS, cN as API_KEY_OPERATIONS, cO as DEFAULT_MAX_VERSIONS, cP as DEFAULT_PASSWORD_EMAILS, cQ as FIELD_TYPE_BASES, cR as FOLDER_LEVELS, cS as MediaFolders, cT as SSO_COOKIE, cU as codeOfStatus, cA as hasRows, cC as isHasMany, cV as isJsonLogger, cW as keyAllows, cX as logFormat, cH as mimeAllowedBy, cI as rowFields, cK as uniqueWithinOf } from './config-CzW6kBeb.js';
|
|
3
|
+
export { C as CONFIG_FILE_NAMES, g as CSRF_COOKIE, h as CSRF_HEADER, D as DEFAULT_ADMIN_PATH, i as DEFAULT_API_PATH, j as DEFAULT_MAX_FILE_SIZE, k as DEFAULT_TOKEN_EXPIRATION, m as applyDefaults, n as applyPlugins, o as createRootEndpointHandler, p as decryptBackup, q as fillMissing, t as findConfigFile, u as forwardedClientIp, v as generateSlugs, w as importConfig, x as mergeForUpdate, y as parseId, z as platformClientIp, E as readCookie, F as validateFields, G as writeBackupFile } from './handler-BsBQ-2qf.js';
|
|
4
4
|
export { conditionIssues } from './conditions.js';
|
|
5
5
|
|
|
6
6
|
/** The session cookie the REST API sets at login. */
|
|
@@ -51,6 +51,14 @@ declare function copyDatabase(source: Database, target: Database, options?: {
|
|
|
51
51
|
onTable?: (progress: CopyProgress) => void;
|
|
52
52
|
}): Promise<CopyResult>;
|
|
53
53
|
|
|
54
|
+
type HealthCheck = 'healthz' | 'readyz';
|
|
55
|
+
/**
|
|
56
|
+
* `healthz`: the process answers (liveness), without touching the database. `readyz`: the CMS
|
|
57
|
+
* started, its database answers and no migration is pending (readiness); `503` otherwise, naming
|
|
58
|
+
* the check that failed, with the error in the log only. `cms` is `null` when it failed to start.
|
|
59
|
+
*/
|
|
60
|
+
declare function healthResponse<C extends Config>(check: HealthCheck, instance: EasyCMS<C> | null): Promise<Response>;
|
|
61
|
+
|
|
54
62
|
/** File types Easy CMS recognizes from their contents (FR-UPL-03). */
|
|
55
63
|
declare const EXTENSIONS: Readonly<Record<string, string>>;
|
|
56
64
|
/**
|
|
@@ -133,4 +141,4 @@ declare const BUILTIN_COLLECTIONS: readonly ["users", "media"];
|
|
|
133
141
|
/** Checks a config and returns every problem found. An empty array means it is valid. */
|
|
134
142
|
declare function validateConfig(config: Config): ConfigIssue[];
|
|
135
143
|
|
|
136
|
-
export { BUILTIN_COLLECTIONS, BUILTIN_NAV, type CopyProgress, type CopyResult, DEFAULT_DEPTH, EXTENSIONS, INTERNAL_COLLECTIONS, MAX_DEPTH, MEDIA, MEDIA_FOLDERS, MIME_GROUPS, MIN_PASSWORD_LENGTH, MIN_SECRET_LENGTH, SESSION_COOKIE, checkFormToken, checkRenamedOptions, configSignature, copyDatabase, expandMimeTypes, formToken, generateTypes, hashPassword, honeypotName, imageDimensions, mimeAllowed, populate, rateKeys, resolveAdminModule, singularize, sniffMimeType, validateConfig, verifyPassword, verifyTurnstile };
|
|
144
|
+
export { BUILTIN_COLLECTIONS, BUILTIN_NAV, type CopyProgress, type CopyResult, DEFAULT_DEPTH, EXTENSIONS, type HealthCheck, INTERNAL_COLLECTIONS, MAX_DEPTH, MEDIA, MEDIA_FOLDERS, MIME_GROUPS, MIN_PASSWORD_LENGTH, MIN_SECRET_LENGTH, SESSION_COOKIE, checkFormToken, checkRenamedOptions, configSignature, copyDatabase, expandMimeTypes, formToken, generateTypes, hashPassword, healthResponse, honeypotName, imageDimensions, mimeAllowed, populate, rateKeys, resolveAdminModule, singularize, sniffMimeType, validateConfig, verifyPassword, verifyTurnstile };
|
package/dist/internal.js
CHANGED
|
@@ -38,9 +38,12 @@ import {
|
|
|
38
38
|
forwardedClientIp,
|
|
39
39
|
generateSlugs,
|
|
40
40
|
hashPassword,
|
|
41
|
+
healthResponse,
|
|
41
42
|
honeypotName,
|
|
42
43
|
importConfig,
|
|
44
|
+
isJsonLogger,
|
|
43
45
|
keyAllows,
|
|
46
|
+
logFormat,
|
|
44
47
|
mergeForUpdate,
|
|
45
48
|
parseId,
|
|
46
49
|
platformClientIp,
|
|
@@ -53,7 +56,7 @@ import {
|
|
|
53
56
|
verifyPassword,
|
|
54
57
|
verifyTurnstile,
|
|
55
58
|
writeBackupFile
|
|
56
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-AVUGFJ4Q.js";
|
|
57
60
|
import {
|
|
58
61
|
conditionIssues
|
|
59
62
|
} from "./chunk-U266LV4M.js";
|
|
@@ -286,11 +289,14 @@ export {
|
|
|
286
289
|
generateTypes,
|
|
287
290
|
hasRows,
|
|
288
291
|
hashPassword,
|
|
292
|
+
healthResponse,
|
|
289
293
|
honeypotName,
|
|
290
294
|
imageDimensions,
|
|
291
295
|
importConfig,
|
|
292
296
|
isHasMany,
|
|
297
|
+
isJsonLogger,
|
|
293
298
|
keyAllows,
|
|
299
|
+
logFormat,
|
|
294
300
|
mergeForUpdate,
|
|
295
301
|
mimeAllowed,
|
|
296
302
|
mimeAllowedBy,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ba as Label, aD as Field, I as ID, k as AdminLocale, t as AdminSwitcher,
|
|
1
|
+
import { ba as Label, aD as Field, I as ID, k as AdminLocale, t as AdminSwitcher, c4 as SsoProviderRef } from './config-CzW6kBeb.js';
|
|
2
2
|
import { FieldCondition } from './conditions.js';
|
|
3
3
|
|
|
4
4
|
/** A Web Component from an admin module, with its `props` (plain JSON). */
|
package/dist/plugin.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { a as ADMIN_ICONS, g as AdminComponent, j as AdminIcon, S as AuthUser, a3 as CliCommand, a4 as CollectionAccess, a6 as CollectionConfig, ab as Config, ac as ConfigError, ak as DashboardWidget, av as EasyCMSError, az as Endpoint, aA as EndpointRequest, aB as ErrorCode, aD as Field, aE as FieldAccess, aH as FieldError, aK as FieldTypeBase, aL as FieldTypeDefinition, aM as FieldTypeValidateContext, aY as ForbiddenError, a_ as GlobalConfig, I as ID, b8 as JobConfig, ba as Label,
|
|
2
|
-
export { A as ADMIN_API_VERSION, c as AdminElementProps, k as AdminPageRoute, S as SetFieldDetail, w as warnDeprecated } from './plugin-
|
|
1
|
+
export { a as ADMIN_ICONS, g as AdminComponent, j as AdminIcon, S as AuthUser, a3 as CliCommand, a4 as CollectionAccess, a6 as CollectionConfig, ab as Config, ac as ConfigError, ak as DashboardWidget, av as EasyCMSError, az as Endpoint, aA as EndpointRequest, aB as ErrorCode, aD as Field, aE as FieldAccess, aH as FieldError, aK as FieldTypeBase, aL as FieldTypeDefinition, aM as FieldTypeValidateContext, aY as ForbiddenError, a_ as GlobalConfig, I as ID, b8 as JobConfig, ba as Label, bo as NavGroup, bp as NotFoundError, br as OnRequest, bs as OnRequestArgs, bu as PLUGIN_API_VERSION, bz as PayloadTooLargeError, bA as Plugin, bB as PluginInfo, bC as PluginTypes, bF as QueryError, bK as RequestContext, c9 as TooManyRequestsError, ca as TypedPlugin, cb as UnauthorizedError, ci as ValidationError, cq as Where, cx as defineFieldType, cy as definePlugin } from './config-CzW6kBeb.js';
|
|
2
|
+
export { A as ADMIN_API_VERSION, c as AdminElementProps, k as AdminPageRoute, S as SetFieldDetail, w as warnDeprecated } from './plugin-BmKxHxuu.js';
|
|
3
3
|
import './conditions.js';
|