@fydemy/cms 1.0.1 → 1.0.3

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/bin.js ADDED
@@ -0,0 +1,276 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
+ // If the importer is in node compatibility mode or this is not an ESM
19
+ // file that has been converted to a CommonJS file using a Babel-
20
+ // compatible transform (i.e. "__esModule" has not been set), then set
21
+ // "default" to the CommonJS "module.exports" for node compatibility.
22
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
+ mod
24
+ ));
25
+
26
+ // src/init/setup.ts
27
+ var import_promises = __toESM(require("fs/promises"));
28
+ var import_path = __toESM(require("path"));
29
+ var import_child_process = require("child_process");
30
+ var import_util = require("util");
31
+ var execAsync = (0, import_util.promisify)(import_child_process.exec);
32
+ async function initCMS(config = {}) {
33
+ const contentDir = config.contentDir || "public/content";
34
+ const fullPath = import_path.default.join(process.cwd(), contentDir);
35
+ const appDir = import_path.default.join(process.cwd(), "app");
36
+ try {
37
+ await import_promises.default.access(appDir);
38
+ } catch {
39
+ console.error(
40
+ '\u274C Error: "app" directory not found. This init script requires Next.js App Router.'
41
+ );
42
+ return;
43
+ }
44
+ console.log("\u{1F680} Initializing @fydemy/cms...");
45
+ console.log("\u{1F4E6} Checking dependencies...");
46
+ try {
47
+ const packageJsonPath = import_path.default.join(process.cwd(), "package.json");
48
+ const packageJson = JSON.parse(await import_promises.default.readFile(packageJsonPath, "utf-8"));
49
+ const dependencies = {
50
+ ...packageJson.dependencies,
51
+ ...packageJson.devDependencies
52
+ };
53
+ const missingDeps = [];
54
+ if (!dependencies["@fydemy/cms"]) missingDeps.push("@fydemy/cms");
55
+ if (!dependencies["tailwindcss"]) missingDeps.push("tailwindcss");
56
+ if (!dependencies["class-variance-authority"])
57
+ missingDeps.push("class-variance-authority");
58
+ if (!dependencies["clsx"]) missingDeps.push("clsx");
59
+ if (!dependencies["tailwind-merge"]) missingDeps.push("tailwind-merge");
60
+ if (!dependencies["@radix-ui/react-slot"])
61
+ missingDeps.push("@radix-ui/react-slot");
62
+ if (!dependencies["@radix-ui/react-label"])
63
+ missingDeps.push("@radix-ui/react-label");
64
+ if (missingDeps.length > 0) {
65
+ console.log(
66
+ `\u{1F527} Installing missing dependencies: ${missingDeps.join(", ")}...`
67
+ );
68
+ let installCmd = "npm install";
69
+ try {
70
+ await import_promises.default.access("pnpm-lock.yaml");
71
+ installCmd = "pnpm add";
72
+ } catch {
73
+ try {
74
+ await import_promises.default.access("yarn.lock");
75
+ installCmd = "yarn add";
76
+ } catch {
77
+ }
78
+ }
79
+ await execAsync(`${installCmd} ${missingDeps.join(" ")}`);
80
+ console.log("\u2705 Dependencies installed");
81
+ }
82
+ } catch (error) {
83
+ console.warn(
84
+ "\u26A0\uFE0F Could not check/install dependencies automatically. Please ensure all dependencies are installed."
85
+ );
86
+ }
87
+ await import_promises.default.mkdir(fullPath, { recursive: true });
88
+ const exampleContent = `---
89
+ title: Example Post
90
+ description: This is an example markdown file
91
+ date: ${(/* @__PURE__ */ new Date()).toISOString()}
92
+ ---
93
+
94
+ # Welcome to your CMS!
95
+
96
+ This is an example markdown file. You can edit or delete it from the admin dashboard.
97
+
98
+ ## Features
99
+
100
+ - File-based content storage
101
+ - Markdown with frontmatter
102
+ - GitHub integration for production
103
+ - Simple authentication
104
+ - No database required
105
+ `;
106
+ const examplePath = import_path.default.join(fullPath, "example.md");
107
+ await import_promises.default.writeFile(examplePath, exampleContent, "utf-8");
108
+ console.log("\u2705 Created content directory and example file");
109
+ const adminDir = import_path.default.join(appDir, "admin");
110
+ const loginDir = import_path.default.join(adminDir, "login");
111
+ await import_promises.default.mkdir(loginDir, { recursive: true });
112
+ const loginTemplate = await import_promises.default.readFile(
113
+ import_path.default.join(__dirname, "login.template.tsx"),
114
+ "utf-8"
115
+ );
116
+ const adminTemplate = await import_promises.default.readFile(
117
+ import_path.default.join(__dirname, "admin.template.tsx"),
118
+ "utf-8"
119
+ );
120
+ await import_promises.default.writeFile(import_path.default.join(adminDir, "page.tsx"), adminTemplate, "utf-8");
121
+ await import_promises.default.writeFile(import_path.default.join(loginDir, "page.tsx"), loginTemplate, "utf-8");
122
+ console.log("\u2705 Scaffolded Admin UI (shadcn/ui components)");
123
+ const componentsDir = import_path.default.join(process.cwd(), "components", "ui");
124
+ const libDir = import_path.default.join(process.cwd(), "lib");
125
+ await import_promises.default.mkdir(componentsDir, { recursive: true });
126
+ await import_promises.default.mkdir(libDir, { recursive: true });
127
+ const utilsTemplate = await import_promises.default.readFile(
128
+ import_path.default.join(__dirname, "lib", "utils.ts"),
129
+ "utf-8"
130
+ );
131
+ await import_promises.default.writeFile(import_path.default.join(libDir, "utils.ts"), utilsTemplate, "utf-8");
132
+ const componentFiles = [
133
+ "button.tsx",
134
+ "input.tsx",
135
+ "card.tsx",
136
+ "label.tsx",
137
+ "textarea.tsx",
138
+ "badge.tsx"
139
+ ];
140
+ for (const componentFile of componentFiles) {
141
+ const componentTemplate = await import_promises.default.readFile(
142
+ import_path.default.join(__dirname, "components", "ui", componentFile),
143
+ "utf-8"
144
+ );
145
+ await import_promises.default.writeFile(
146
+ import_path.default.join(componentsDir, componentFile),
147
+ componentTemplate,
148
+ "utf-8"
149
+ );
150
+ }
151
+ const componentsJsonTemplate = await import_promises.default.readFile(
152
+ import_path.default.join(__dirname, "components.json"),
153
+ "utf-8"
154
+ );
155
+ await import_promises.default.writeFile(
156
+ import_path.default.join(process.cwd(), "components.json"),
157
+ componentsJsonTemplate,
158
+ "utf-8"
159
+ );
160
+ console.log("\u2705 Scaffolded shadcn/ui components");
161
+ const apiCmsDir = import_path.default.join(appDir, "api", "cms");
162
+ await import_promises.default.mkdir(import_path.default.join(apiCmsDir, "login"), { recursive: true });
163
+ await import_promises.default.writeFile(
164
+ import_path.default.join(apiCmsDir, "login", "route.ts"),
165
+ `import { handleLogin } from '@fydemy/cms';
166
+ export { handleLogin as POST };
167
+ `,
168
+ "utf-8"
169
+ );
170
+ await import_promises.default.mkdir(import_path.default.join(apiCmsDir, "logout"), { recursive: true });
171
+ await import_promises.default.writeFile(
172
+ import_path.default.join(apiCmsDir, "logout", "route.ts"),
173
+ `import { handleLogout } from '@fydemy/cms';
174
+ export { handleLogout as POST };
175
+ `,
176
+ "utf-8"
177
+ );
178
+ await import_promises.default.mkdir(import_path.default.join(apiCmsDir, "upload"), { recursive: true });
179
+ await import_promises.default.writeFile(
180
+ import_path.default.join(apiCmsDir, "upload", "route.ts"),
181
+ `import { handleUpload } from '@fydemy/cms';
182
+ export { handleUpload as POST };
183
+ `,
184
+ "utf-8"
185
+ );
186
+ await import_promises.default.mkdir(import_path.default.join(apiCmsDir, "list", "[[...path]]"), {
187
+ recursive: true
188
+ });
189
+ await import_promises.default.writeFile(
190
+ import_path.default.join(apiCmsDir, "list", "[[...path]]", "route.ts"),
191
+ `import { createListApiHandlers } from '@fydemy/cms';
192
+
193
+ const handlers = createListApiHandlers();
194
+ export const GET = handlers.GET;
195
+ `,
196
+ "utf-8"
197
+ );
198
+ await import_promises.default.mkdir(import_path.default.join(apiCmsDir, "content", "[...path]"), {
199
+ recursive: true
200
+ });
201
+ await import_promises.default.writeFile(
202
+ import_path.default.join(apiCmsDir, "content", "[...path]", "route.ts"),
203
+ `import { createContentApiHandlers } from '@fydemy/cms';
204
+
205
+ const handlers = createContentApiHandlers();
206
+ export const GET = handlers.GET;
207
+ export const POST = handlers.POST;
208
+ export const DELETE = handlers.DELETE;
209
+ `,
210
+ "utf-8"
211
+ );
212
+ console.log("\u2705 Created API routes");
213
+ const middlewarePath = import_path.default.join(process.cwd(), "middleware.ts");
214
+ try {
215
+ await import_promises.default.access(middlewarePath);
216
+ console.log(
217
+ "\u26A0\uFE0F middleware.ts already exists. Please manually add the CMS auth middleware:"
218
+ );
219
+ console.log(`
220
+ import { createAuthMiddleware } from '@fydemy/cms';
221
+ // ... existing imports
222
+
223
+ export function middleware(request: NextRequest) {
224
+ // Add this:
225
+ const authResponse = createAuthMiddleware()(request);
226
+ if (authResponse) return authResponse;
227
+
228
+ // ... existing middleware logic
229
+ }
230
+ `);
231
+ } catch {
232
+ await import_promises.default.writeFile(
233
+ middlewarePath,
234
+ `import { createAuthMiddleware } from '@fydemy/cms';
235
+ import { NextRequest } from 'next/server';
236
+
237
+ export function middleware(request: NextRequest) {
238
+ return createAuthMiddleware()(request);
239
+ }
240
+
241
+ export const config = {
242
+ matcher: ['/admin/:path*'],
243
+ };
244
+ `,
245
+ "utf-8"
246
+ );
247
+ console.log("\u2705 Created middleware.ts");
248
+ }
249
+ const envExamplePath = import_path.default.join(process.cwd(), ".env.local.example");
250
+ await import_promises.default.writeFile(
251
+ envExamplePath,
252
+ `CMS_ADMIN_USERNAME=admin
253
+ CMS_ADMIN_PASSWORD=password
254
+ CMS_SESSION_SECRET=ensure_this_is_at_least_32_chars_long_random_string
255
+
256
+ # GitHub Storage (Production)
257
+ GITHUB_TOKEN=
258
+ GITHUB_REPO=owner/repo
259
+ GITHUB_BRANCH=main
260
+ `,
261
+ "utf-8"
262
+ );
263
+ console.log("");
264
+ console.log("\u{1F389} CMS initialized successfully!");
265
+ console.log(
266
+ "1. Copy .env.local.example to .env.local and set your credentials"
267
+ );
268
+ console.log("2. Run your dev server and visit /admin");
269
+ }
270
+
271
+ // src/bin.ts
272
+ initCMS().catch((err) => {
273
+ console.error("Error initializing CMS:", err);
274
+ process.exit(1);
275
+ });
276
+ //# sourceMappingURL=bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/init/setup.ts","../src/bin.ts"],"sourcesContent":["import fs from \"fs/promises\";\nimport path from \"path\";\nimport { exec } from \"child_process\";\nimport { promisify } from \"util\";\n\nconst execAsync = promisify(exec);\n\nexport interface InitCMSConfig {\n /** Directory where content is stored (default: \"public/content\") */\n contentDir?: string;\n}\n\n/**\n * Initialize CMS in a Next.js project\n * Creates the content directory and an example markdown file.\n * @param config - Configuration options\n */\nexport async function initCMS(config: InitCMSConfig = {}) {\n const contentDir = config.contentDir || \"public/content\";\n const fullPath = path.join(process.cwd(), contentDir);\n const appDir = path.join(process.cwd(), \"app\");\n\n // Check if we are in a Next.js App Router project\n try {\n await fs.access(appDir);\n } catch {\n console.error(\n '❌ Error: \"app\" directory not found. This init script requires Next.js App Router.'\n );\n return;\n }\n\n console.log(\"🚀 Initializing @fydemy/cms...\");\n\n // 0. Install Dependencies\n console.log(\"📦 Checking dependencies...\");\n try {\n const packageJsonPath = path.join(process.cwd(), \"package.json\");\n const packageJson = JSON.parse(await fs.readFile(packageJsonPath, \"utf-8\"));\n const dependencies = {\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n };\n\n const missingDeps = [];\n if (!dependencies[\"@fydemy/cms\"]) missingDeps.push(\"@fydemy/cms\");\n if (!dependencies[\"tailwindcss\"]) missingDeps.push(\"tailwindcss\");\n\n // shadcn dependencies\n if (!dependencies[\"class-variance-authority\"])\n missingDeps.push(\"class-variance-authority\");\n if (!dependencies[\"clsx\"]) missingDeps.push(\"clsx\");\n if (!dependencies[\"tailwind-merge\"]) missingDeps.push(\"tailwind-merge\");\n if (!dependencies[\"@radix-ui/react-slot\"])\n missingDeps.push(\"@radix-ui/react-slot\");\n if (!dependencies[\"@radix-ui/react-label\"])\n missingDeps.push(\"@radix-ui/react-label\");\n\n if (missingDeps.length > 0) {\n console.log(\n `🔧 Installing missing dependencies: ${missingDeps.join(\", \")}...`\n );\n // Detect package manager (default to npm if locking file not found)\n let installCmd = \"npm install\";\n try {\n await fs.access(\"pnpm-lock.yaml\");\n installCmd = \"pnpm add\";\n } catch {\n try {\n await fs.access(\"yarn.lock\");\n installCmd = \"yarn add\";\n } catch {\n // npm\n }\n }\n\n await execAsync(`${installCmd} ${missingDeps.join(\" \")}`);\n console.log(\"✅ Dependencies installed\");\n }\n } catch (error) {\n console.warn(\n \"⚠️ Could not check/install dependencies automatically. Please ensure all dependencies are installed.\"\n );\n }\n\n // 1. Create content directory and example file\n await fs.mkdir(fullPath, { recursive: true });\n\n const exampleContent = `---\ntitle: Example Post\ndescription: This is an example markdown file\ndate: ${new Date().toISOString()}\n---\n\n# Welcome to your CMS!\n\nThis is an example markdown file. You can edit or delete it from the admin dashboard.\n\n## Features\n\n- File-based content storage\n- Markdown with frontmatter\n- GitHub integration for production\n- Simple authentication\n- No database required\n`;\n\n const examplePath = path.join(fullPath, \"example.md\");\n await fs.writeFile(examplePath, exampleContent, \"utf-8\");\n console.log(\"✅ Created content directory and example file\");\n\n // 2. Scaffold Admin Pages (Ejected Code)\n const adminDir = path.join(appDir, \"admin\");\n const loginDir = path.join(adminDir, \"login\");\n\n await fs.mkdir(loginDir, { recursive: true });\n\n // Read template files from the dist directory (publicDir copied them there)\n const loginTemplate = await fs.readFile(\n path.join(__dirname, \"login.template.tsx\"),\n \"utf-8\"\n );\n const adminTemplate = await fs.readFile(\n path.join(__dirname, \"admin.template.tsx\"),\n \"utf-8\"\n );\n\n await fs.writeFile(path.join(adminDir, \"page.tsx\"), adminTemplate, \"utf-8\");\n\n await fs.writeFile(path.join(loginDir, \"page.tsx\"), loginTemplate, \"utf-8\");\n console.log(\"✅ Scaffolded Admin UI (shadcn/ui components)\");\n\n // 2.5. Scaffold shadcn/ui Components and Utilities\n const componentsDir = path.join(process.cwd(), \"components\", \"ui\");\n const libDir = path.join(process.cwd(), \"lib\");\n\n await fs.mkdir(componentsDir, { recursive: true });\n await fs.mkdir(libDir, { recursive: true });\n\n // Copy utils.ts\n const utilsTemplate = await fs.readFile(\n path.join(__dirname, \"lib\", \"utils.ts\"),\n \"utf-8\"\n );\n await fs.writeFile(path.join(libDir, \"utils.ts\"), utilsTemplate, \"utf-8\");\n\n // Copy shadcn components\n const componentFiles = [\n \"button.tsx\",\n \"input.tsx\",\n \"card.tsx\",\n \"label.tsx\",\n \"textarea.tsx\",\n \"badge.tsx\",\n ];\n\n for (const componentFile of componentFiles) {\n const componentTemplate = await fs.readFile(\n path.join(__dirname, \"components\", \"ui\", componentFile),\n \"utf-8\"\n );\n await fs.writeFile(\n path.join(componentsDir, componentFile),\n componentTemplate,\n \"utf-8\"\n );\n }\n\n // Copy components.json\n const componentsJsonTemplate = await fs.readFile(\n path.join(__dirname, \"components.json\"),\n \"utf-8\"\n );\n await fs.writeFile(\n path.join(process.cwd(), \"components.json\"),\n componentsJsonTemplate,\n \"utf-8\"\n );\n\n console.log(\"✅ Scaffolded shadcn/ui components\");\n\n // 3. Scaffold API Routes\n const apiCmsDir = path.join(appDir, \"api\", \"cms\");\n\n // Login\n await fs.mkdir(path.join(apiCmsDir, \"login\"), { recursive: true });\n await fs.writeFile(\n path.join(apiCmsDir, \"login\", \"route.ts\"),\n `import { handleLogin } from '@fydemy/cms';\\nexport { handleLogin as POST };\\n`,\n \"utf-8\"\n );\n\n // Logout\n await fs.mkdir(path.join(apiCmsDir, \"logout\"), { recursive: true });\n await fs.writeFile(\n path.join(apiCmsDir, \"logout\", \"route.ts\"),\n `import { handleLogout } from '@fydemy/cms';\\nexport { handleLogout as POST };\\n`,\n \"utf-8\"\n );\n\n // Upload\n await fs.mkdir(path.join(apiCmsDir, \"upload\"), { recursive: true });\n await fs.writeFile(\n path.join(apiCmsDir, \"upload\", \"route.ts\"),\n `import { handleUpload } from '@fydemy/cms';\\nexport { handleUpload as POST };\\n`,\n \"utf-8\"\n );\n\n // List\n await fs.mkdir(path.join(apiCmsDir, \"list\", \"[[...path]]\"), {\n recursive: true,\n });\n await fs.writeFile(\n path.join(apiCmsDir, \"list\", \"[[...path]]\", \"route.ts\"),\n `import { createListApiHandlers } from '@fydemy/cms';\\n\\nconst handlers = createListApiHandlers();\\nexport const GET = handlers.GET;\\n`,\n \"utf-8\"\n );\n\n // Content\n await fs.mkdir(path.join(apiCmsDir, \"content\", \"[...path]\"), {\n recursive: true,\n });\n await fs.writeFile(\n path.join(apiCmsDir, \"content\", \"[...path]\", \"route.ts\"),\n `import { createContentApiHandlers } from '@fydemy/cms';\\n\\nconst handlers = createContentApiHandlers();\\nexport const GET = handlers.GET;\\nexport const POST = handlers.POST;\\nexport const DELETE = handlers.DELETE;\\n`,\n \"utf-8\"\n );\n console.log(\"✅ Created API routes\");\n\n // 4. Middleware\n const middlewarePath = path.join(process.cwd(), \"middleware.ts\");\n try {\n await fs.access(middlewarePath);\n console.log(\n \"⚠️ middleware.ts already exists. Please manually add the CMS auth middleware:\"\n );\n console.log(`\nimport { createAuthMiddleware } from '@fydemy/cms';\n// ... existing imports\n\nexport function middleware(request: NextRequest) {\n // Add this:\n const authResponse = createAuthMiddleware()(request);\n if (authResponse) return authResponse;\n \n // ... existing middleware logic\n}\n`);\n } catch {\n await fs.writeFile(\n middlewarePath,\n `import { createAuthMiddleware } from '@fydemy/cms';\\nimport { NextRequest } from 'next/server';\\n\\nexport function middleware(request: NextRequest) {\\n return createAuthMiddleware()(request);\\n}\\n\\nexport const config = {\\n matcher: ['/admin/:path*'],\\n};\\n`,\n \"utf-8\"\n );\n console.log(\"✅ Created middleware.ts\");\n }\n\n // 5. Env example\n const envExamplePath = path.join(process.cwd(), \".env.local.example\");\n await fs.writeFile(\n envExamplePath,\n `CMS_ADMIN_USERNAME=admin\\nCMS_ADMIN_PASSWORD=password\\nCMS_SESSION_SECRET=ensure_this_is_at_least_32_chars_long_random_string\\n\\n# GitHub Storage (Production)\\nGITHUB_TOKEN=\\nGITHUB_REPO=owner/repo\\nGITHUB_BRANCH=main\\n`,\n \"utf-8\"\n );\n\n console.log(\"\");\n console.log(\"🎉 CMS initialized successfully!\");\n console.log(\n \"1. Copy .env.local.example to .env.local and set your credentials\"\n );\n console.log(\"2. Run your dev server and visit /admin\");\n}\n","#!/usr/bin/env node\n\nimport { initCMS } from \"./init/setup\";\n\ninitCMS().catch((err: unknown) => {\n console.error(\"Error initializing CMS:\", err);\n process.exit(1);\n});\n"],"mappings":"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","names":["path","fs"]}
package/dist/bin.mjs ADDED
@@ -0,0 +1,253 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/init/setup.ts
4
+ import fs from "fs/promises";
5
+ import path from "path";
6
+ import { exec } from "child_process";
7
+ import { promisify } from "util";
8
+ var execAsync = promisify(exec);
9
+ async function initCMS(config = {}) {
10
+ const contentDir = config.contentDir || "public/content";
11
+ const fullPath = path.join(process.cwd(), contentDir);
12
+ const appDir = path.join(process.cwd(), "app");
13
+ try {
14
+ await fs.access(appDir);
15
+ } catch {
16
+ console.error(
17
+ '\u274C Error: "app" directory not found. This init script requires Next.js App Router.'
18
+ );
19
+ return;
20
+ }
21
+ console.log("\u{1F680} Initializing @fydemy/cms...");
22
+ console.log("\u{1F4E6} Checking dependencies...");
23
+ try {
24
+ const packageJsonPath = path.join(process.cwd(), "package.json");
25
+ const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf-8"));
26
+ const dependencies = {
27
+ ...packageJson.dependencies,
28
+ ...packageJson.devDependencies
29
+ };
30
+ const missingDeps = [];
31
+ if (!dependencies["@fydemy/cms"]) missingDeps.push("@fydemy/cms");
32
+ if (!dependencies["tailwindcss"]) missingDeps.push("tailwindcss");
33
+ if (!dependencies["class-variance-authority"])
34
+ missingDeps.push("class-variance-authority");
35
+ if (!dependencies["clsx"]) missingDeps.push("clsx");
36
+ if (!dependencies["tailwind-merge"]) missingDeps.push("tailwind-merge");
37
+ if (!dependencies["@radix-ui/react-slot"])
38
+ missingDeps.push("@radix-ui/react-slot");
39
+ if (!dependencies["@radix-ui/react-label"])
40
+ missingDeps.push("@radix-ui/react-label");
41
+ if (missingDeps.length > 0) {
42
+ console.log(
43
+ `\u{1F527} Installing missing dependencies: ${missingDeps.join(", ")}...`
44
+ );
45
+ let installCmd = "npm install";
46
+ try {
47
+ await fs.access("pnpm-lock.yaml");
48
+ installCmd = "pnpm add";
49
+ } catch {
50
+ try {
51
+ await fs.access("yarn.lock");
52
+ installCmd = "yarn add";
53
+ } catch {
54
+ }
55
+ }
56
+ await execAsync(`${installCmd} ${missingDeps.join(" ")}`);
57
+ console.log("\u2705 Dependencies installed");
58
+ }
59
+ } catch (error) {
60
+ console.warn(
61
+ "\u26A0\uFE0F Could not check/install dependencies automatically. Please ensure all dependencies are installed."
62
+ );
63
+ }
64
+ await fs.mkdir(fullPath, { recursive: true });
65
+ const exampleContent = `---
66
+ title: Example Post
67
+ description: This is an example markdown file
68
+ date: ${(/* @__PURE__ */ new Date()).toISOString()}
69
+ ---
70
+
71
+ # Welcome to your CMS!
72
+
73
+ This is an example markdown file. You can edit or delete it from the admin dashboard.
74
+
75
+ ## Features
76
+
77
+ - File-based content storage
78
+ - Markdown with frontmatter
79
+ - GitHub integration for production
80
+ - Simple authentication
81
+ - No database required
82
+ `;
83
+ const examplePath = path.join(fullPath, "example.md");
84
+ await fs.writeFile(examplePath, exampleContent, "utf-8");
85
+ console.log("\u2705 Created content directory and example file");
86
+ const adminDir = path.join(appDir, "admin");
87
+ const loginDir = path.join(adminDir, "login");
88
+ await fs.mkdir(loginDir, { recursive: true });
89
+ const loginTemplate = await fs.readFile(
90
+ path.join(__dirname, "login.template.tsx"),
91
+ "utf-8"
92
+ );
93
+ const adminTemplate = await fs.readFile(
94
+ path.join(__dirname, "admin.template.tsx"),
95
+ "utf-8"
96
+ );
97
+ await fs.writeFile(path.join(adminDir, "page.tsx"), adminTemplate, "utf-8");
98
+ await fs.writeFile(path.join(loginDir, "page.tsx"), loginTemplate, "utf-8");
99
+ console.log("\u2705 Scaffolded Admin UI (shadcn/ui components)");
100
+ const componentsDir = path.join(process.cwd(), "components", "ui");
101
+ const libDir = path.join(process.cwd(), "lib");
102
+ await fs.mkdir(componentsDir, { recursive: true });
103
+ await fs.mkdir(libDir, { recursive: true });
104
+ const utilsTemplate = await fs.readFile(
105
+ path.join(__dirname, "lib", "utils.ts"),
106
+ "utf-8"
107
+ );
108
+ await fs.writeFile(path.join(libDir, "utils.ts"), utilsTemplate, "utf-8");
109
+ const componentFiles = [
110
+ "button.tsx",
111
+ "input.tsx",
112
+ "card.tsx",
113
+ "label.tsx",
114
+ "textarea.tsx",
115
+ "badge.tsx"
116
+ ];
117
+ for (const componentFile of componentFiles) {
118
+ const componentTemplate = await fs.readFile(
119
+ path.join(__dirname, "components", "ui", componentFile),
120
+ "utf-8"
121
+ );
122
+ await fs.writeFile(
123
+ path.join(componentsDir, componentFile),
124
+ componentTemplate,
125
+ "utf-8"
126
+ );
127
+ }
128
+ const componentsJsonTemplate = await fs.readFile(
129
+ path.join(__dirname, "components.json"),
130
+ "utf-8"
131
+ );
132
+ await fs.writeFile(
133
+ path.join(process.cwd(), "components.json"),
134
+ componentsJsonTemplate,
135
+ "utf-8"
136
+ );
137
+ console.log("\u2705 Scaffolded shadcn/ui components");
138
+ const apiCmsDir = path.join(appDir, "api", "cms");
139
+ await fs.mkdir(path.join(apiCmsDir, "login"), { recursive: true });
140
+ await fs.writeFile(
141
+ path.join(apiCmsDir, "login", "route.ts"),
142
+ `import { handleLogin } from '@fydemy/cms';
143
+ export { handleLogin as POST };
144
+ `,
145
+ "utf-8"
146
+ );
147
+ await fs.mkdir(path.join(apiCmsDir, "logout"), { recursive: true });
148
+ await fs.writeFile(
149
+ path.join(apiCmsDir, "logout", "route.ts"),
150
+ `import { handleLogout } from '@fydemy/cms';
151
+ export { handleLogout as POST };
152
+ `,
153
+ "utf-8"
154
+ );
155
+ await fs.mkdir(path.join(apiCmsDir, "upload"), { recursive: true });
156
+ await fs.writeFile(
157
+ path.join(apiCmsDir, "upload", "route.ts"),
158
+ `import { handleUpload } from '@fydemy/cms';
159
+ export { handleUpload as POST };
160
+ `,
161
+ "utf-8"
162
+ );
163
+ await fs.mkdir(path.join(apiCmsDir, "list", "[[...path]]"), {
164
+ recursive: true
165
+ });
166
+ await fs.writeFile(
167
+ path.join(apiCmsDir, "list", "[[...path]]", "route.ts"),
168
+ `import { createListApiHandlers } from '@fydemy/cms';
169
+
170
+ const handlers = createListApiHandlers();
171
+ export const GET = handlers.GET;
172
+ `,
173
+ "utf-8"
174
+ );
175
+ await fs.mkdir(path.join(apiCmsDir, "content", "[...path]"), {
176
+ recursive: true
177
+ });
178
+ await fs.writeFile(
179
+ path.join(apiCmsDir, "content", "[...path]", "route.ts"),
180
+ `import { createContentApiHandlers } from '@fydemy/cms';
181
+
182
+ const handlers = createContentApiHandlers();
183
+ export const GET = handlers.GET;
184
+ export const POST = handlers.POST;
185
+ export const DELETE = handlers.DELETE;
186
+ `,
187
+ "utf-8"
188
+ );
189
+ console.log("\u2705 Created API routes");
190
+ const middlewarePath = path.join(process.cwd(), "middleware.ts");
191
+ try {
192
+ await fs.access(middlewarePath);
193
+ console.log(
194
+ "\u26A0\uFE0F middleware.ts already exists. Please manually add the CMS auth middleware:"
195
+ );
196
+ console.log(`
197
+ import { createAuthMiddleware } from '@fydemy/cms';
198
+ // ... existing imports
199
+
200
+ export function middleware(request: NextRequest) {
201
+ // Add this:
202
+ const authResponse = createAuthMiddleware()(request);
203
+ if (authResponse) return authResponse;
204
+
205
+ // ... existing middleware logic
206
+ }
207
+ `);
208
+ } catch {
209
+ await fs.writeFile(
210
+ middlewarePath,
211
+ `import { createAuthMiddleware } from '@fydemy/cms';
212
+ import { NextRequest } from 'next/server';
213
+
214
+ export function middleware(request: NextRequest) {
215
+ return createAuthMiddleware()(request);
216
+ }
217
+
218
+ export const config = {
219
+ matcher: ['/admin/:path*'],
220
+ };
221
+ `,
222
+ "utf-8"
223
+ );
224
+ console.log("\u2705 Created middleware.ts");
225
+ }
226
+ const envExamplePath = path.join(process.cwd(), ".env.local.example");
227
+ await fs.writeFile(
228
+ envExamplePath,
229
+ `CMS_ADMIN_USERNAME=admin
230
+ CMS_ADMIN_PASSWORD=password
231
+ CMS_SESSION_SECRET=ensure_this_is_at_least_32_chars_long_random_string
232
+
233
+ # GitHub Storage (Production)
234
+ GITHUB_TOKEN=
235
+ GITHUB_REPO=owner/repo
236
+ GITHUB_BRANCH=main
237
+ `,
238
+ "utf-8"
239
+ );
240
+ console.log("");
241
+ console.log("\u{1F389} CMS initialized successfully!");
242
+ console.log(
243
+ "1. Copy .env.local.example to .env.local and set your credentials"
244
+ );
245
+ console.log("2. Run your dev server and visit /admin");
246
+ }
247
+
248
+ // src/bin.ts
249
+ initCMS().catch((err) => {
250
+ console.error("Error initializing CMS:", err);
251
+ process.exit(1);
252
+ });
253
+ //# sourceMappingURL=bin.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/init/setup.ts","../src/bin.ts"],"sourcesContent":["import fs from \"fs/promises\";\nimport path from \"path\";\nimport { exec } from \"child_process\";\nimport { promisify } from \"util\";\n\nconst execAsync = promisify(exec);\n\nexport interface InitCMSConfig {\n /** Directory where content is stored (default: \"public/content\") */\n contentDir?: string;\n}\n\n/**\n * Initialize CMS in a Next.js project\n * Creates the content directory and an example markdown file.\n * @param config - Configuration options\n */\nexport async function initCMS(config: InitCMSConfig = {}) {\n const contentDir = config.contentDir || \"public/content\";\n const fullPath = path.join(process.cwd(), contentDir);\n const appDir = path.join(process.cwd(), \"app\");\n\n // Check if we are in a Next.js App Router project\n try {\n await fs.access(appDir);\n } catch {\n console.error(\n '❌ Error: \"app\" directory not found. This init script requires Next.js App Router.'\n );\n return;\n }\n\n console.log(\"🚀 Initializing @fydemy/cms...\");\n\n // 0. Install Dependencies\n console.log(\"📦 Checking dependencies...\");\n try {\n const packageJsonPath = path.join(process.cwd(), \"package.json\");\n const packageJson = JSON.parse(await fs.readFile(packageJsonPath, \"utf-8\"));\n const dependencies = {\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n };\n\n const missingDeps = [];\n if (!dependencies[\"@fydemy/cms\"]) missingDeps.push(\"@fydemy/cms\");\n if (!dependencies[\"tailwindcss\"]) missingDeps.push(\"tailwindcss\");\n\n // shadcn dependencies\n if (!dependencies[\"class-variance-authority\"])\n missingDeps.push(\"class-variance-authority\");\n if (!dependencies[\"clsx\"]) missingDeps.push(\"clsx\");\n if (!dependencies[\"tailwind-merge\"]) missingDeps.push(\"tailwind-merge\");\n if (!dependencies[\"@radix-ui/react-slot\"])\n missingDeps.push(\"@radix-ui/react-slot\");\n if (!dependencies[\"@radix-ui/react-label\"])\n missingDeps.push(\"@radix-ui/react-label\");\n\n if (missingDeps.length > 0) {\n console.log(\n `🔧 Installing missing dependencies: ${missingDeps.join(\", \")}...`\n );\n // Detect package manager (default to npm if locking file not found)\n let installCmd = \"npm install\";\n try {\n await fs.access(\"pnpm-lock.yaml\");\n installCmd = \"pnpm add\";\n } catch {\n try {\n await fs.access(\"yarn.lock\");\n installCmd = \"yarn add\";\n } catch {\n // npm\n }\n }\n\n await execAsync(`${installCmd} ${missingDeps.join(\" \")}`);\n console.log(\"✅ Dependencies installed\");\n }\n } catch (error) {\n console.warn(\n \"⚠️ Could not check/install dependencies automatically. Please ensure all dependencies are installed.\"\n );\n }\n\n // 1. Create content directory and example file\n await fs.mkdir(fullPath, { recursive: true });\n\n const exampleContent = `---\ntitle: Example Post\ndescription: This is an example markdown file\ndate: ${new Date().toISOString()}\n---\n\n# Welcome to your CMS!\n\nThis is an example markdown file. You can edit or delete it from the admin dashboard.\n\n## Features\n\n- File-based content storage\n- Markdown with frontmatter\n- GitHub integration for production\n- Simple authentication\n- No database required\n`;\n\n const examplePath = path.join(fullPath, \"example.md\");\n await fs.writeFile(examplePath, exampleContent, \"utf-8\");\n console.log(\"✅ Created content directory and example file\");\n\n // 2. Scaffold Admin Pages (Ejected Code)\n const adminDir = path.join(appDir, \"admin\");\n const loginDir = path.join(adminDir, \"login\");\n\n await fs.mkdir(loginDir, { recursive: true });\n\n // Read template files from the dist directory (publicDir copied them there)\n const loginTemplate = await fs.readFile(\n path.join(__dirname, \"login.template.tsx\"),\n \"utf-8\"\n );\n const adminTemplate = await fs.readFile(\n path.join(__dirname, \"admin.template.tsx\"),\n \"utf-8\"\n );\n\n await fs.writeFile(path.join(adminDir, \"page.tsx\"), adminTemplate, \"utf-8\");\n\n await fs.writeFile(path.join(loginDir, \"page.tsx\"), loginTemplate, \"utf-8\");\n console.log(\"✅ Scaffolded Admin UI (shadcn/ui components)\");\n\n // 2.5. Scaffold shadcn/ui Components and Utilities\n const componentsDir = path.join(process.cwd(), \"components\", \"ui\");\n const libDir = path.join(process.cwd(), \"lib\");\n\n await fs.mkdir(componentsDir, { recursive: true });\n await fs.mkdir(libDir, { recursive: true });\n\n // Copy utils.ts\n const utilsTemplate = await fs.readFile(\n path.join(__dirname, \"lib\", \"utils.ts\"),\n \"utf-8\"\n );\n await fs.writeFile(path.join(libDir, \"utils.ts\"), utilsTemplate, \"utf-8\");\n\n // Copy shadcn components\n const componentFiles = [\n \"button.tsx\",\n \"input.tsx\",\n \"card.tsx\",\n \"label.tsx\",\n \"textarea.tsx\",\n \"badge.tsx\",\n ];\n\n for (const componentFile of componentFiles) {\n const componentTemplate = await fs.readFile(\n path.join(__dirname, \"components\", \"ui\", componentFile),\n \"utf-8\"\n );\n await fs.writeFile(\n path.join(componentsDir, componentFile),\n componentTemplate,\n \"utf-8\"\n );\n }\n\n // Copy components.json\n const componentsJsonTemplate = await fs.readFile(\n path.join(__dirname, \"components.json\"),\n \"utf-8\"\n );\n await fs.writeFile(\n path.join(process.cwd(), \"components.json\"),\n componentsJsonTemplate,\n \"utf-8\"\n );\n\n console.log(\"✅ Scaffolded shadcn/ui components\");\n\n // 3. Scaffold API Routes\n const apiCmsDir = path.join(appDir, \"api\", \"cms\");\n\n // Login\n await fs.mkdir(path.join(apiCmsDir, \"login\"), { recursive: true });\n await fs.writeFile(\n path.join(apiCmsDir, \"login\", \"route.ts\"),\n `import { handleLogin } from '@fydemy/cms';\\nexport { handleLogin as POST };\\n`,\n \"utf-8\"\n );\n\n // Logout\n await fs.mkdir(path.join(apiCmsDir, \"logout\"), { recursive: true });\n await fs.writeFile(\n path.join(apiCmsDir, \"logout\", \"route.ts\"),\n `import { handleLogout } from '@fydemy/cms';\\nexport { handleLogout as POST };\\n`,\n \"utf-8\"\n );\n\n // Upload\n await fs.mkdir(path.join(apiCmsDir, \"upload\"), { recursive: true });\n await fs.writeFile(\n path.join(apiCmsDir, \"upload\", \"route.ts\"),\n `import { handleUpload } from '@fydemy/cms';\\nexport { handleUpload as POST };\\n`,\n \"utf-8\"\n );\n\n // List\n await fs.mkdir(path.join(apiCmsDir, \"list\", \"[[...path]]\"), {\n recursive: true,\n });\n await fs.writeFile(\n path.join(apiCmsDir, \"list\", \"[[...path]]\", \"route.ts\"),\n `import { createListApiHandlers } from '@fydemy/cms';\\n\\nconst handlers = createListApiHandlers();\\nexport const GET = handlers.GET;\\n`,\n \"utf-8\"\n );\n\n // Content\n await fs.mkdir(path.join(apiCmsDir, \"content\", \"[...path]\"), {\n recursive: true,\n });\n await fs.writeFile(\n path.join(apiCmsDir, \"content\", \"[...path]\", \"route.ts\"),\n `import { createContentApiHandlers } from '@fydemy/cms';\\n\\nconst handlers = createContentApiHandlers();\\nexport const GET = handlers.GET;\\nexport const POST = handlers.POST;\\nexport const DELETE = handlers.DELETE;\\n`,\n \"utf-8\"\n );\n console.log(\"✅ Created API routes\");\n\n // 4. Middleware\n const middlewarePath = path.join(process.cwd(), \"middleware.ts\");\n try {\n await fs.access(middlewarePath);\n console.log(\n \"⚠️ middleware.ts already exists. Please manually add the CMS auth middleware:\"\n );\n console.log(`\nimport { createAuthMiddleware } from '@fydemy/cms';\n// ... existing imports\n\nexport function middleware(request: NextRequest) {\n // Add this:\n const authResponse = createAuthMiddleware()(request);\n if (authResponse) return authResponse;\n \n // ... existing middleware logic\n}\n`);\n } catch {\n await fs.writeFile(\n middlewarePath,\n `import { createAuthMiddleware } from '@fydemy/cms';\\nimport { NextRequest } from 'next/server';\\n\\nexport function middleware(request: NextRequest) {\\n return createAuthMiddleware()(request);\\n}\\n\\nexport const config = {\\n matcher: ['/admin/:path*'],\\n};\\n`,\n \"utf-8\"\n );\n console.log(\"✅ Created middleware.ts\");\n }\n\n // 5. Env example\n const envExamplePath = path.join(process.cwd(), \".env.local.example\");\n await fs.writeFile(\n envExamplePath,\n `CMS_ADMIN_USERNAME=admin\\nCMS_ADMIN_PASSWORD=password\\nCMS_SESSION_SECRET=ensure_this_is_at_least_32_chars_long_random_string\\n\\n# GitHub Storage (Production)\\nGITHUB_TOKEN=\\nGITHUB_REPO=owner/repo\\nGITHUB_BRANCH=main\\n`,\n \"utf-8\"\n );\n\n console.log(\"\");\n console.log(\"🎉 CMS initialized successfully!\");\n console.log(\n \"1. Copy .env.local.example to .env.local and set your credentials\"\n );\n console.log(\"2. Run your dev server and visit /admin\");\n}\n","#!/usr/bin/env node\n\nimport { initCMS } from \"./init/setup\";\n\ninitCMS().catch((err: unknown) => {\n console.error(\"Error initializing CMS:\", err);\n process.exit(1);\n});\n"],"mappings":"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","names":[]}
@@ -0,0 +1,36 @@
1
+ import * as React from "react";
2
+ import { cva, type VariantProps } from "class-variance-authority";
3
+
4
+ import { cn } from "@/lib/utils";
5
+
6
+ const badgeVariants = cva(
7
+ "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
8
+ {
9
+ variants: {
10
+ variant: {
11
+ default:
12
+ "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
13
+ secondary:
14
+ "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
15
+ destructive:
16
+ "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
17
+ outline: "text-foreground",
18
+ },
19
+ },
20
+ defaultVariants: {
21
+ variant: "default",
22
+ },
23
+ }
24
+ );
25
+
26
+ export interface BadgeProps
27
+ extends React.HTMLAttributes<HTMLDivElement>,
28
+ VariantProps<typeof badgeVariants> {}
29
+
30
+ function Badge({ className, variant, ...props }: BadgeProps) {
31
+ return (
32
+ <div className={cn(badgeVariants({ variant }), className)} {...props} />
33
+ );
34
+ }
35
+
36
+ export { Badge, badgeVariants };