modern-cms 1.1.5 ā 1.1.6
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/bin/modern-cms.js
CHANGED
|
@@ -40,10 +40,10 @@ function onCancel() {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
async function main() {
|
|
43
|
-
console.log("\
|
|
43
|
+
console.log("\nš modern-cms ā self-hosted drag-and-drop website CMS\n");
|
|
44
44
|
|
|
45
45
|
const { targetDir } = await prompts(
|
|
46
|
-
{ type: "text", name: "targetDir", message: "Where should the project be created?", initial: "./modern-cms-app" },
|
|
46
|
+
{ type: "text", name: "targetDir", message: "š Where should the project be created?", initial: "./modern-cms-app" },
|
|
47
47
|
{ onCancel }
|
|
48
48
|
);
|
|
49
49
|
const dest = path.resolve(process.cwd(), targetDir);
|
|
@@ -52,19 +52,20 @@ async function main() {
|
|
|
52
52
|
process.exit(1);
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
console.log(`\
|
|
55
|
+
console.log(`\nš¦ Copying project files into ${dest} ...`);
|
|
56
56
|
copyDir(TEMPLATE_DIR, dest);
|
|
57
57
|
|
|
58
58
|
// --- Database ---
|
|
59
|
+
console.log("\nšļø Database");
|
|
59
60
|
const db = await prompts(
|
|
60
61
|
[
|
|
61
62
|
{
|
|
62
63
|
type: "select",
|
|
63
64
|
name: "engine",
|
|
64
|
-
message: "Database",
|
|
65
|
+
message: "Database engine",
|
|
65
66
|
choices: [
|
|
66
|
-
{ title: "PostgreSQL", value: "postgresql" },
|
|
67
|
-
{ title: "MySQL", value: "mysql" },
|
|
67
|
+
{ title: "š PostgreSQL", value: "postgresql" },
|
|
68
|
+
{ title: "š¬ MySQL", value: "mysql" },
|
|
68
69
|
],
|
|
69
70
|
},
|
|
70
71
|
{ type: "text", name: "host", message: "Database host", initial: "localhost" },
|
|
@@ -92,6 +93,7 @@ async function main() {
|
|
|
92
93
|
}
|
|
93
94
|
|
|
94
95
|
// --- Ports ---
|
|
96
|
+
console.log("\nš Ports");
|
|
95
97
|
const ports = await prompts(
|
|
96
98
|
[
|
|
97
99
|
{ type: "text", name: "webPort", message: "Web app port", initial: "3000" },
|
|
@@ -101,15 +103,16 @@ async function main() {
|
|
|
101
103
|
);
|
|
102
104
|
|
|
103
105
|
// --- Storage ---
|
|
106
|
+
console.log("\nāļø File storage");
|
|
104
107
|
const { provider } = await prompts(
|
|
105
108
|
{
|
|
106
109
|
type: "select",
|
|
107
110
|
name: "provider",
|
|
108
|
-
message: "
|
|
111
|
+
message: "Storage provider",
|
|
109
112
|
choices: [
|
|
110
|
-
{ title: "AWS S3 (or any S3-compatible: MinIO, R2, Spaces...)", value: "s3" },
|
|
111
|
-
{ title: "Azure Blob Storage", value: "azure" },
|
|
112
|
-
{ title: "Cloudinary", value: "cloudinary" },
|
|
113
|
+
{ title: "šŖ£ AWS S3 (or any S3-compatible: MinIO, R2, Spaces...)", value: "s3" },
|
|
114
|
+
{ title: "š· Azure Blob Storage", value: "azure" },
|
|
115
|
+
{ title: "š¤ļø Cloudinary", value: "cloudinary" },
|
|
113
116
|
],
|
|
114
117
|
},
|
|
115
118
|
{ onCancel }
|
|
@@ -160,6 +163,7 @@ async function main() {
|
|
|
160
163
|
|
|
161
164
|
// --- Site / admin (necessary extras beyond what was asked for: the app needs to
|
|
162
165
|
// know its own public URLs, and the CMS needs an initial admin login) ---
|
|
166
|
+
console.log("\nš¤ Site & admin account");
|
|
163
167
|
const site = await prompts(
|
|
164
168
|
[
|
|
165
169
|
{ type: "text", name: "siteUrl", message: "Public site URL", initial: `http://localhost:${ports.webPort}` },
|
|
@@ -190,11 +194,11 @@ async function main() {
|
|
|
190
194
|
fs.writeFileSync(path.join(dest, ".env"), rootEnv);
|
|
191
195
|
|
|
192
196
|
if (!site.adminPassword) {
|
|
193
|
-
console.log(`\
|
|
197
|
+
console.log(`\nš Generated admin password: ${adminPassword}\n (save this ā it's only shown once)`);
|
|
194
198
|
}
|
|
195
199
|
|
|
196
|
-
console.log("\
|
|
197
|
-
console.log("Next steps:");
|
|
200
|
+
console.log("\nā
Done! Generated .env files for apps/api and apps/web.\n");
|
|
201
|
+
console.log("š Next steps:");
|
|
198
202
|
console.log(` cd ${targetDir}`);
|
|
199
203
|
console.log(" npm install");
|
|
200
204
|
if (usesDbPush(db.engine)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "modern-cms",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.6",
|
|
4
4
|
"description": "Self-hosted, drag-and-drop website CMS (Next.js + Express + Prisma). Interactive installer scaffolds a full project with your choice of PostgreSQL/MySQL and AWS S3/Azure Blob/Cloudinary storage.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -2,6 +2,7 @@ import express from "express";
|
|
|
2
2
|
import cors from "cors";
|
|
3
3
|
import cookieParser from "cookie-parser";
|
|
4
4
|
import { env } from "./env.js";
|
|
5
|
+
import { initStorage } from "./lib/storage/index.js";
|
|
5
6
|
import { securityHeaders } from "./middleware/securityHeaders.js";
|
|
6
7
|
import { authRouter } from "./routes/auth.routes.js";
|
|
7
8
|
import { pagesRouter } from "./routes/pages.routes.js";
|
|
@@ -61,6 +62,8 @@ app.use((err: any, _req: express.Request, res: express.Response, _next: express.
|
|
|
61
62
|
res.status(err.status ?? 500).json({ error: err.message ?? "Internal server error" });
|
|
62
63
|
});
|
|
63
64
|
|
|
65
|
+
initStorage();
|
|
66
|
+
|
|
64
67
|
app.listen(env.port, () => {
|
|
65
68
|
console.log(`pg-cms API listening on http://localhost:${env.port}`);
|
|
66
69
|
});
|
|
@@ -6,7 +6,21 @@ import { createCloudinaryStorage } from "./cloudinary.js";
|
|
|
6
6
|
|
|
7
7
|
let cached: StorageProvider | null = null;
|
|
8
8
|
|
|
9
|
+
// Printed once, at first upload/delete ā tells you exactly where files are actually
|
|
10
|
+
// going (bucket/container/cloud + folder), since that's the #1 source of "my upload
|
|
11
|
+
// succeeded but I can't find the file" confusion when double-checking the wrong place.
|
|
12
|
+
function logActiveProvider() {
|
|
13
|
+
if (env.storageProvider === "azure") {
|
|
14
|
+
console.log(`[storage] Using Azure Blob Storage ā container "${env.azure!.container}"`);
|
|
15
|
+
} else if (env.storageProvider === "cloudinary") {
|
|
16
|
+
console.log(`[storage] Using Cloudinary ā cloud "${env.cloudinary!.cloudName}", folder "${env.cloudinary!.folder}"`);
|
|
17
|
+
} else {
|
|
18
|
+
console.log(`[storage] Using S3 ā bucket "${env.s3!.bucket}" at ${env.s3!.endpoint}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
9
22
|
function build(): StorageProvider {
|
|
23
|
+
logActiveProvider();
|
|
10
24
|
if (env.storageProvider === "azure") return createAzureStorage();
|
|
11
25
|
if (env.storageProvider === "cloudinary") return createCloudinaryStorage();
|
|
12
26
|
return createS3Storage();
|
|
@@ -16,6 +30,12 @@ function getStorage(): StorageProvider {
|
|
|
16
30
|
return (cached ??= build());
|
|
17
31
|
}
|
|
18
32
|
|
|
33
|
+
/** Called once at server boot so the active provider/destination is visible in the
|
|
34
|
+
* logs immediately, rather than only appearing after the first upload. */
|
|
35
|
+
export function initStorage(): void {
|
|
36
|
+
getStorage();
|
|
37
|
+
}
|
|
38
|
+
|
|
19
39
|
export async function uploadBuffer(key: string, buffer: Buffer, contentType: string): Promise<string> {
|
|
20
40
|
return getStorage().upload(key, buffer, contentType);
|
|
21
41
|
}
|