@plank-cms/plank 0.26.1 → 0.27.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/admin/assets/index-BTElP7oS.css +2 -0
- package/dist/admin/assets/index-C-XGjg93.js +223 -0
- package/dist/admin/index.html +2 -2
- package/dist/index.js +2 -2
- package/dist/{server-7LSVEAFA.js → server-HPYV4HWB.js} +112 -32
- package/package.json +4 -4
- package/dist/admin/assets/index-BLYpKKlP.js +0 -223
- package/dist/admin/assets/index-BWA7n9y8.css +0 -2
package/dist/admin/index.html
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
href="https://fonts.googleapis.com/css2?family=Google+Sans:ital,opsz,wght@0,17..18,400..700;1,17..18,400..700&display=swap"
|
|
13
13
|
rel="stylesheet"
|
|
14
14
|
/>
|
|
15
|
-
<script type="module" crossorigin src="/admin/assets/index-
|
|
16
|
-
<link rel="stylesheet" crossorigin href="/admin/assets/index-
|
|
15
|
+
<script type="module" crossorigin src="/admin/assets/index-C-XGjg93.js"></script>
|
|
16
|
+
<link rel="stylesheet" crossorigin href="/admin/assets/index-BTElP7oS.css">
|
|
17
17
|
</head>
|
|
18
18
|
<body>
|
|
19
19
|
<div id="root"></div>
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import { randomBytes } from "crypto";
|
|
|
7
7
|
import { resolve, join } from "path";
|
|
8
8
|
import fs from "fs-extra";
|
|
9
9
|
import { execa } from "execa";
|
|
10
|
-
var PACKAGE_VERSION = "0.
|
|
10
|
+
var PACKAGE_VERSION = "0.27.0";
|
|
11
11
|
function generateSecret() {
|
|
12
12
|
return randomBytes(32).toString("hex");
|
|
13
13
|
}
|
|
@@ -106,7 +106,7 @@ import { dirname, join as join2, resolve as resolve2 } from "path";
|
|
|
106
106
|
async function start() {
|
|
107
107
|
config({ path: resolve2(process.cwd(), ".env") });
|
|
108
108
|
process.env.PLANK_ADMIN_DIST = join2(dirname(fileURLToPath(import.meta.url)), "admin");
|
|
109
|
-
const { start: startServer } = await import("./server-
|
|
109
|
+
const { start: startServer } = await import("./server-HPYV4HWB.js");
|
|
110
110
|
await startServer();
|
|
111
111
|
}
|
|
112
112
|
|
|
@@ -651,7 +651,7 @@ import express from "express";
|
|
|
651
651
|
import cors from "cors";
|
|
652
652
|
import helmet from "helmet";
|
|
653
653
|
import { join as join4, dirname as dirname2 } from "path";
|
|
654
|
-
import { fileURLToPath as
|
|
654
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
655
655
|
|
|
656
656
|
// ../core/dist/routes/auth.js
|
|
657
657
|
import { Router } from "express";
|
|
@@ -2445,6 +2445,32 @@ async function getProvider() {
|
|
|
2445
2445
|
}
|
|
2446
2446
|
var upload = multer({ storage: multer.memoryStorage() });
|
|
2447
2447
|
|
|
2448
|
+
// ../core/dist/lib/publicAuthorSlug.js
|
|
2449
|
+
function slugifySegment(value) {
|
|
2450
|
+
return value.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/^-+|-+$/g, "");
|
|
2451
|
+
}
|
|
2452
|
+
function baseSlugFromUser(input) {
|
|
2453
|
+
const fullName = [input.firstName, input.lastName].map((value) => value?.trim() ?? "").filter(Boolean).join(" ");
|
|
2454
|
+
const base = fullName || input.email.split("@")[0] || "author";
|
|
2455
|
+
return slugifySegment(base) || "author";
|
|
2456
|
+
}
|
|
2457
|
+
async function resolveUniquePublicAuthorSlug(input, excludeUserId) {
|
|
2458
|
+
const baseSlug = baseSlugFromUser(input);
|
|
2459
|
+
let slug = baseSlug;
|
|
2460
|
+
let suffix = 2;
|
|
2461
|
+
while (true) {
|
|
2462
|
+
const { rows } = await pool_default.query(`SELECT id
|
|
2463
|
+
FROM plank_users
|
|
2464
|
+
WHERE public_author_slug = $1
|
|
2465
|
+
AND ($2::text IS NULL OR id != $2)
|
|
2466
|
+
LIMIT 1`, [slug, excludeUserId ?? null]);
|
|
2467
|
+
if (!rows[0])
|
|
2468
|
+
return slug;
|
|
2469
|
+
slug = `${baseSlug}-${suffix}`;
|
|
2470
|
+
suffix += 1;
|
|
2471
|
+
}
|
|
2472
|
+
}
|
|
2473
|
+
|
|
2448
2474
|
// ../core/dist/controllers/auth.js
|
|
2449
2475
|
var LoginSchema = z.object({
|
|
2450
2476
|
email: z.email(),
|
|
@@ -2456,6 +2482,8 @@ var Login2FASchema = z.object({
|
|
|
2456
2482
|
});
|
|
2457
2483
|
var RegisterSchema = z.object({
|
|
2458
2484
|
email: z.email(),
|
|
2485
|
+
firstName: z.string().trim().min(1).max(100),
|
|
2486
|
+
lastName: z.string().trim().min(1).max(100),
|
|
2459
2487
|
password: z.string().min(8)
|
|
2460
2488
|
});
|
|
2461
2489
|
var RATE_LIMIT_WINDOW_MS = 15 * 60 * 1e3;
|
|
@@ -2712,7 +2740,7 @@ async function register(req, res) {
|
|
|
2712
2740
|
res.status(400).json({ errors: flattenError(parsed.error, (i2) => i2.message) });
|
|
2713
2741
|
return;
|
|
2714
2742
|
}
|
|
2715
|
-
const { email, password } = parsed.data;
|
|
2743
|
+
const { email, firstName, lastName, password } = parsed.data;
|
|
2716
2744
|
const hashed = await bcrypt.hash(password, 12);
|
|
2717
2745
|
const { rows: roleRows } = await pool_default.query("SELECT id, name FROM plank_roles WHERE name = $1", ["Super Admin"]);
|
|
2718
2746
|
const superAdminRole = roleRows[0];
|
|
@@ -2721,7 +2749,10 @@ async function register(req, res) {
|
|
|
2721
2749
|
return;
|
|
2722
2750
|
}
|
|
2723
2751
|
const id = createId();
|
|
2724
|
-
|
|
2752
|
+
const publicAuthorSlug = await resolveUniquePublicAuthorSlug({ email, firstName, lastName });
|
|
2753
|
+
await pool_default.query(`INSERT INTO plank_users
|
|
2754
|
+
(id, email, password, role_id, first_name, last_name, public_author_slug)
|
|
2755
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7)`, [id, email, hashed, superAdminRole.id, firstName, lastName, publicAuthorSlug]);
|
|
2725
2756
|
res.status(201).json({ id, email });
|
|
2726
2757
|
}
|
|
2727
2758
|
|
|
@@ -3966,34 +3997,6 @@ var deleteEntry = async (req, res) => {
|
|
|
3966
3997
|
import bcrypt2 from "bcryptjs";
|
|
3967
3998
|
import { randomBytes as randomBytes6 } from "crypto";
|
|
3968
3999
|
import { z as z4, flattenError as flattenError4 } from "zod";
|
|
3969
|
-
|
|
3970
|
-
// ../core/dist/lib/publicAuthorSlug.js
|
|
3971
|
-
function slugifySegment(value) {
|
|
3972
|
-
return value.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/^-+|-+$/g, "");
|
|
3973
|
-
}
|
|
3974
|
-
function baseSlugFromUser(input) {
|
|
3975
|
-
const fullName = [input.firstName, input.lastName].map((value) => value?.trim() ?? "").filter(Boolean).join(" ");
|
|
3976
|
-
const base = fullName || input.email.split("@")[0] || "author";
|
|
3977
|
-
return slugifySegment(base) || "author";
|
|
3978
|
-
}
|
|
3979
|
-
async function resolveUniquePublicAuthorSlug(input, excludeUserId) {
|
|
3980
|
-
const baseSlug = baseSlugFromUser(input);
|
|
3981
|
-
let slug = baseSlug;
|
|
3982
|
-
let suffix = 2;
|
|
3983
|
-
while (true) {
|
|
3984
|
-
const { rows } = await pool_default.query(`SELECT id
|
|
3985
|
-
FROM plank_users
|
|
3986
|
-
WHERE public_author_slug = $1
|
|
3987
|
-
AND ($2::text IS NULL OR id != $2)
|
|
3988
|
-
LIMIT 1`, [slug, excludeUserId ?? null]);
|
|
3989
|
-
if (!rows[0])
|
|
3990
|
-
return slug;
|
|
3991
|
-
slug = `${baseSlug}-${suffix}`;
|
|
3992
|
-
suffix += 1;
|
|
3993
|
-
}
|
|
3994
|
-
}
|
|
3995
|
-
|
|
3996
|
-
// ../core/dist/controllers/users.js
|
|
3997
4000
|
var CreateUserSchema = z4.object({
|
|
3998
4001
|
email: z4.email(),
|
|
3999
4002
|
password: z4.string().min(8),
|
|
@@ -4907,6 +4910,82 @@ async function updateNamespaceSettings(req, res) {
|
|
|
4907
4910
|
res.json(maskSettings(namespace, updated));
|
|
4908
4911
|
}
|
|
4909
4912
|
|
|
4913
|
+
// ../core/dist/lib/version.js
|
|
4914
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
4915
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
4916
|
+
var PACKAGE_NAME = "@plank-cms/plank";
|
|
4917
|
+
var CHANGELOG_BASE_URL = "https://github.com/plank-cms/plank/releases";
|
|
4918
|
+
var UPDATE_COMMAND = "npm run update";
|
|
4919
|
+
var REGISTRY_URL = `https://registry.npmjs.org/${encodeURIComponent(PACKAGE_NAME)}/latest`;
|
|
4920
|
+
var CACHE_TTL_MS = 1e3 * 60 * 30;
|
|
4921
|
+
var packageJsonUrl = new URL("../../package.json", import.meta.url);
|
|
4922
|
+
var cachedVersionCheck = null;
|
|
4923
|
+
function normalizeVersion(value) {
|
|
4924
|
+
return value.trim().replace(/^v/i, "").split("-")[0].split(".").map((part) => Number.parseInt(part, 10) || 0);
|
|
4925
|
+
}
|
|
4926
|
+
function compareVersions(a2, b3) {
|
|
4927
|
+
const left = normalizeVersion(a2);
|
|
4928
|
+
const right = normalizeVersion(b3);
|
|
4929
|
+
const maxLength = Math.max(left.length, right.length);
|
|
4930
|
+
for (let index = 0; index < maxLength; index += 1) {
|
|
4931
|
+
const leftPart = left[index] ?? 0;
|
|
4932
|
+
const rightPart = right[index] ?? 0;
|
|
4933
|
+
if (leftPart > rightPart)
|
|
4934
|
+
return 1;
|
|
4935
|
+
if (leftPart < rightPart)
|
|
4936
|
+
return -1;
|
|
4937
|
+
}
|
|
4938
|
+
return 0;
|
|
4939
|
+
}
|
|
4940
|
+
function getChangelogUrl(version) {
|
|
4941
|
+
return version ? `${CHANGELOG_BASE_URL}/tag/${version}` : CHANGELOG_BASE_URL;
|
|
4942
|
+
}
|
|
4943
|
+
async function readCurrentVersion() {
|
|
4944
|
+
const packageJsonPath = fileURLToPath2(packageJsonUrl);
|
|
4945
|
+
const raw = await readFile2(packageJsonPath, "utf8");
|
|
4946
|
+
const parsed = JSON.parse(raw);
|
|
4947
|
+
return parsed.version ?? "0.0.0";
|
|
4948
|
+
}
|
|
4949
|
+
async function getVersionCheck() {
|
|
4950
|
+
if (cachedVersionCheck && cachedVersionCheck.expiresAt > Date.now()) {
|
|
4951
|
+
return cachedVersionCheck.value;
|
|
4952
|
+
}
|
|
4953
|
+
const currentVersion = await readCurrentVersion();
|
|
4954
|
+
let latestVersion = null;
|
|
4955
|
+
try {
|
|
4956
|
+
const response = await fetch(REGISTRY_URL, {
|
|
4957
|
+
signal: AbortSignal.timeout(4e3),
|
|
4958
|
+
headers: {
|
|
4959
|
+
Accept: "application/json"
|
|
4960
|
+
}
|
|
4961
|
+
});
|
|
4962
|
+
if (response.ok) {
|
|
4963
|
+
const payload = await response.json();
|
|
4964
|
+
latestVersion = payload.version ?? null;
|
|
4965
|
+
}
|
|
4966
|
+
} catch {
|
|
4967
|
+
}
|
|
4968
|
+
const value = {
|
|
4969
|
+
currentVersion,
|
|
4970
|
+
latestVersion,
|
|
4971
|
+
updateAvailable: latestVersion ? compareVersions(latestVersion, currentVersion) > 0 : false,
|
|
4972
|
+
changelogUrl: getChangelogUrl(latestVersion),
|
|
4973
|
+
updateCommand: UPDATE_COMMAND,
|
|
4974
|
+
checkedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
4975
|
+
};
|
|
4976
|
+
cachedVersionCheck = {
|
|
4977
|
+
expiresAt: Date.now() + CACHE_TTL_MS,
|
|
4978
|
+
value
|
|
4979
|
+
};
|
|
4980
|
+
return value;
|
|
4981
|
+
}
|
|
4982
|
+
|
|
4983
|
+
// ../core/dist/controllers/version.js
|
|
4984
|
+
async function getVersionInfo(_req, res) {
|
|
4985
|
+
const versionInfo = await getVersionCheck();
|
|
4986
|
+
res.json(versionInfo);
|
|
4987
|
+
}
|
|
4988
|
+
|
|
4910
4989
|
// ../core/dist/routes/admin.js
|
|
4911
4990
|
var router2 = Router2();
|
|
4912
4991
|
router2.use(authenticate);
|
|
@@ -4962,6 +5041,7 @@ router2.delete("/media/:id", authorize("media:delete"), deleteMedia);
|
|
|
4962
5041
|
router2.get("/modes", getAppModes);
|
|
4963
5042
|
router2.get("/client-settings", getClientSettings);
|
|
4964
5043
|
router2.get("/editorial-mode", getEditorialMode);
|
|
5044
|
+
router2.get("/version", getVersionInfo);
|
|
4965
5045
|
router2.get("/settings/:namespace", authorize("settings:overview:read"), getNamespaceSettings);
|
|
4966
5046
|
router2.put("/settings/:namespace", authorize("settings:overview:write"), updateNamespaceSettings);
|
|
4967
5047
|
router2.get("/webhooks", authorize("settings:webhooks:read"), listWebhooks);
|
|
@@ -5675,7 +5755,7 @@ if (isDev) {
|
|
|
5675
5755
|
app.get("/admin/*path", (_req, res) => res.redirect(adminDevUrl));
|
|
5676
5756
|
app.get("/admin", (_req, res) => res.redirect(adminDevUrl));
|
|
5677
5757
|
} else {
|
|
5678
|
-
const adminDist = process.env.PLANK_ADMIN_DIST ?? join4(dirname2(
|
|
5758
|
+
const adminDist = process.env.PLANK_ADMIN_DIST ?? join4(dirname2(fileURLToPath3(import.meta.url)), "../public/admin");
|
|
5679
5759
|
app.use("/admin", express.static(adminDist));
|
|
5680
5760
|
app.get("/admin/*path", (_req, res) => res.sendFile(join4(adminDist, "index.html")));
|
|
5681
5761
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plank-cms/plank",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0",
|
|
4
4
|
"description": "Self-hosted headless CMS. Deploy in minutes on your own infrastructure.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -55,9 +55,9 @@
|
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@types/fs-extra": "^11.0.4",
|
|
57
57
|
"tsup": "^8.5.0",
|
|
58
|
-
"@plank-cms/
|
|
59
|
-
"@plank-cms/schema": "0.
|
|
60
|
-
"@plank-cms/
|
|
58
|
+
"@plank-cms/core": "0.27.0",
|
|
59
|
+
"@plank-cms/schema": "0.27.0",
|
|
60
|
+
"@plank-cms/db": "0.27.0"
|
|
61
61
|
},
|
|
62
62
|
"scripts": {
|
|
63
63
|
"build": "tsup",
|