@fydemy/cms 1.0.4 ā 1.0.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/README.md +1 -18
- package/dist/bin.js +36 -8
- package/dist/bin.js.map +1 -1
- package/dist/bin.mjs +36 -8
- package/dist/bin.mjs.map +1 -1
- package/dist/index.js +287 -679
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +287 -679
- package/dist/index.mjs.map +1 -1
- package/package.json +13 -10
- package/LICENSE +0 -21
package/README.md
CHANGED
|
@@ -70,24 +70,7 @@ GITHUB_BRANCH=main
|
|
|
70
70
|
|
|
71
71
|
> **Security Note**: Use strong passwords and keep `CMS_SESSION_SECRET` at least 32 characters long.
|
|
72
72
|
|
|
73
|
-
### 3.
|
|
74
|
-
|
|
75
|
-
The init command will guide you to update `middleware.ts` to protect admin routes:
|
|
76
|
-
|
|
77
|
-
```typescript
|
|
78
|
-
import { createAuthMiddleware } from "@fydemy/cms";
|
|
79
|
-
import { NextRequest } from "next/server";
|
|
80
|
-
|
|
81
|
-
export function middleware(request: NextRequest) {
|
|
82
|
-
return createAuthMiddleware()(request);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export const config = {
|
|
86
|
-
matcher: ["/admin/:path*"],
|
|
87
|
-
};
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
### 4. Read Content in Your App
|
|
73
|
+
### 3. Read Content in Your App
|
|
91
74
|
|
|
92
75
|
```typescript
|
|
93
76
|
import { getMarkdownContent } from "@fydemy/cms";
|
package/dist/bin.js
CHANGED
|
@@ -277,20 +277,48 @@ export const config = {
|
|
|
277
277
|
);
|
|
278
278
|
console.log("\u2705 Created middleware.ts");
|
|
279
279
|
}
|
|
280
|
-
|
|
281
|
-
await
|
|
282
|
-
|
|
283
|
-
|
|
280
|
+
console.log("\n\u2699\uFE0F Configuration");
|
|
281
|
+
const rl = await import("readline");
|
|
282
|
+
const askQuestion = (query) => {
|
|
283
|
+
const interface_ = rl.createInterface({
|
|
284
|
+
input: process.stdin,
|
|
285
|
+
output: process.stdout
|
|
286
|
+
});
|
|
287
|
+
return new Promise((resolve) => {
|
|
288
|
+
interface_.question(query, (ans) => {
|
|
289
|
+
interface_.close();
|
|
290
|
+
resolve(ans);
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
};
|
|
294
|
+
const storageChoice = await askQuestion(
|
|
295
|
+
"Select production storage provider:\n 1. GitHub (default)\n 2. S3 / Cloudflare R2 / Vercel Blob\nEnter choice [1]: "
|
|
296
|
+
);
|
|
297
|
+
const isS3 = storageChoice.trim() === "2";
|
|
298
|
+
let envContent = `CMS_ADMIN_USERNAME=admin
|
|
284
299
|
CMS_ADMIN_PASSWORD=password
|
|
285
300
|
CMS_SESSION_SECRET=ensure_this_is_at_least_32_chars_long_random_string
|
|
286
301
|
|
|
287
|
-
|
|
302
|
+
`;
|
|
303
|
+
if (isS3) {
|
|
304
|
+
envContent += `# S3 / Cloudflare R2 / Vercel Blob Storage
|
|
305
|
+
STORAGE_BUCKET=my-bucket
|
|
306
|
+
STORAGE_ENDPOINT=https://<accountid>.r2.cloudflarestorage.com
|
|
307
|
+
STORAGE_ACCESS_KEY_ID=
|
|
308
|
+
STORAGE_SECRET_ACCESS_KEY=
|
|
309
|
+
STORAGE_REGION=auto
|
|
310
|
+
STORAGE_PUBLIC_URL=https://pub-<id>.r2.dev
|
|
311
|
+
`;
|
|
312
|
+
} else {
|
|
313
|
+
envContent += `# GitHub Storage (Production)
|
|
314
|
+
# Generate at https://github.com/settings/tokens (Needs 'repo' or 'contents:write' scope)
|
|
288
315
|
GITHUB_TOKEN=
|
|
289
316
|
GITHUB_REPO=owner/repo
|
|
290
317
|
GITHUB_BRANCH=main
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
);
|
|
318
|
+
`;
|
|
319
|
+
}
|
|
320
|
+
const envExamplePath = import_path.default.join(process.cwd(), ".env.local.example");
|
|
321
|
+
await import_promises.default.writeFile(envExamplePath, envContent, "utf-8");
|
|
294
322
|
console.log("");
|
|
295
323
|
console.log("\u{1F389} CMS initialized successfully!");
|
|
296
324
|
console.log(
|
package/dist/bin.js.map
CHANGED
|
@@ -1 +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';\nimport { NextRequest } from 'next/server';\n\nconst handlers = createListApiHandlers();\n\nexport async function GET(\n request: NextRequest,\n context: { params: Promise<{ path?: string[] }> }\n) {\n const params = await context.params;\n return handlers.GET(request, { params });\n}\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';\nimport { NextRequest } from 'next/server';\n\nconst handlers = createContentApiHandlers();\n\nexport async function GET(\n request: NextRequest,\n context: { params: Promise<{ path: string[] }> }\n) {\n const params = await context.params;\n return handlers.GET(request, { params });\n}\n\nexport async function POST(\n request: NextRequest,\n context: { params: Promise<{ path: string[] }> }\n) {\n const params = await context.params;\n return handlers.POST(request, { params });\n}\n\nexport async function DELETE(\n request: NextRequest,\n context: { params: Promise<{ path: string[] }> }\n) {\n const params = await context.params;\n return handlers.DELETE(request, { params });\n}\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 runtime: 'nodejs',\\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"]}
|
|
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';\nimport { NextRequest } from 'next/server';\n\nconst handlers = createListApiHandlers();\n\nexport async function GET(\n request: NextRequest,\n context: { params: Promise<{ path?: string[] }> }\n) {\n const params = await context.params;\n return handlers.GET(request, { params });\n}\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';\nimport { NextRequest } from 'next/server';\n\nconst handlers = createContentApiHandlers();\n\nexport async function GET(\n request: NextRequest,\n context: { params: Promise<{ path: string[] }> }\n) {\n const params = await context.params;\n return handlers.GET(request, { params });\n}\n\nexport async function POST(\n request: NextRequest,\n context: { params: Promise<{ path: string[] }> }\n) {\n const params = await context.params;\n return handlers.POST(request, { params });\n}\n\nexport async function DELETE(\n request: NextRequest,\n context: { params: Promise<{ path: string[] }> }\n) {\n const params = await context.params;\n return handlers.DELETE(request, { params });\n}\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 runtime: 'nodejs',\\n};\\n`,\n \"utf-8\"\n );\n console.log(\"ā
Created middleware.ts\");\n }\n\n // 5. Env example & Storage Selection\n console.log(\"\\nāļø Configuration\");\n\n // Interactive storage selection\n const rl = await import(\"readline\");\n const askQuestion = (query: string): Promise<string> => {\n const interface_ = rl.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n return new Promise((resolve) => {\n interface_.question(query, (ans) => {\n interface_.close();\n resolve(ans);\n });\n });\n };\n\n const storageChoice = await askQuestion(\n \"Select production storage provider:\\n 1. GitHub (default)\\n 2. S3 / Cloudflare R2 / Vercel Blob\\nEnter choice [1]: \"\n );\n\n const isS3 = storageChoice.trim() === \"2\";\n\n let envContent = `CMS_ADMIN_USERNAME=admin\nCMS_ADMIN_PASSWORD=password\nCMS_SESSION_SECRET=ensure_this_is_at_least_32_chars_long_random_string\n\n`;\n\n if (isS3) {\n envContent += `# S3 / Cloudflare R2 / Vercel Blob Storage\nSTORAGE_BUCKET=my-bucket\nSTORAGE_ENDPOINT=https://<accountid>.r2.cloudflarestorage.com\nSTORAGE_ACCESS_KEY_ID=\nSTORAGE_SECRET_ACCESS_KEY=\nSTORAGE_REGION=auto\nSTORAGE_PUBLIC_URL=https://pub-<id>.r2.dev\n`;\n } else {\n envContent += `# GitHub Storage (Production)\n# Generate at https://github.com/settings/tokens (Needs 'repo' or 'contents:write' scope)\nGITHUB_TOKEN=\nGITHUB_REPO=owner/repo\nGITHUB_BRANCH=main\n`;\n }\n\n const envExamplePath = path.join(process.cwd(), \".env.local.example\");\n await fs.writeFile(envExamplePath, envContent, \"utf-8\");\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
CHANGED
|
@@ -254,20 +254,48 @@ export const config = {
|
|
|
254
254
|
);
|
|
255
255
|
console.log("\u2705 Created middleware.ts");
|
|
256
256
|
}
|
|
257
|
-
|
|
258
|
-
await
|
|
259
|
-
|
|
260
|
-
|
|
257
|
+
console.log("\n\u2699\uFE0F Configuration");
|
|
258
|
+
const rl = await import("readline");
|
|
259
|
+
const askQuestion = (query) => {
|
|
260
|
+
const interface_ = rl.createInterface({
|
|
261
|
+
input: process.stdin,
|
|
262
|
+
output: process.stdout
|
|
263
|
+
});
|
|
264
|
+
return new Promise((resolve) => {
|
|
265
|
+
interface_.question(query, (ans) => {
|
|
266
|
+
interface_.close();
|
|
267
|
+
resolve(ans);
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
};
|
|
271
|
+
const storageChoice = await askQuestion(
|
|
272
|
+
"Select production storage provider:\n 1. GitHub (default)\n 2. S3 / Cloudflare R2 / Vercel Blob\nEnter choice [1]: "
|
|
273
|
+
);
|
|
274
|
+
const isS3 = storageChoice.trim() === "2";
|
|
275
|
+
let envContent = `CMS_ADMIN_USERNAME=admin
|
|
261
276
|
CMS_ADMIN_PASSWORD=password
|
|
262
277
|
CMS_SESSION_SECRET=ensure_this_is_at_least_32_chars_long_random_string
|
|
263
278
|
|
|
264
|
-
|
|
279
|
+
`;
|
|
280
|
+
if (isS3) {
|
|
281
|
+
envContent += `# S3 / Cloudflare R2 / Vercel Blob Storage
|
|
282
|
+
STORAGE_BUCKET=my-bucket
|
|
283
|
+
STORAGE_ENDPOINT=https://<accountid>.r2.cloudflarestorage.com
|
|
284
|
+
STORAGE_ACCESS_KEY_ID=
|
|
285
|
+
STORAGE_SECRET_ACCESS_KEY=
|
|
286
|
+
STORAGE_REGION=auto
|
|
287
|
+
STORAGE_PUBLIC_URL=https://pub-<id>.r2.dev
|
|
288
|
+
`;
|
|
289
|
+
} else {
|
|
290
|
+
envContent += `# GitHub Storage (Production)
|
|
291
|
+
# Generate at https://github.com/settings/tokens (Needs 'repo' or 'contents:write' scope)
|
|
265
292
|
GITHUB_TOKEN=
|
|
266
293
|
GITHUB_REPO=owner/repo
|
|
267
294
|
GITHUB_BRANCH=main
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
);
|
|
295
|
+
`;
|
|
296
|
+
}
|
|
297
|
+
const envExamplePath = path.join(process.cwd(), ".env.local.example");
|
|
298
|
+
await fs.writeFile(envExamplePath, envContent, "utf-8");
|
|
271
299
|
console.log("");
|
|
272
300
|
console.log("\u{1F389} CMS initialized successfully!");
|
|
273
301
|
console.log(
|
package/dist/bin.mjs.map
CHANGED
|
@@ -1 +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';\nimport { NextRequest } from 'next/server';\n\nconst handlers = createListApiHandlers();\n\nexport async function GET(\n request: NextRequest,\n context: { params: Promise<{ path?: string[] }> }\n) {\n const params = await context.params;\n return handlers.GET(request, { params });\n}\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';\nimport { NextRequest } from 'next/server';\n\nconst handlers = createContentApiHandlers();\n\nexport async function GET(\n request: NextRequest,\n context: { params: Promise<{ path: string[] }> }\n) {\n const params = await context.params;\n return handlers.GET(request, { params });\n}\n\nexport async function POST(\n request: NextRequest,\n context: { params: Promise<{ path: string[] }> }\n) {\n const params = await context.params;\n return handlers.POST(request, { params });\n}\n\nexport async function DELETE(\n request: NextRequest,\n context: { params: Promise<{ path: string[] }> }\n) {\n const params = await context.params;\n return handlers.DELETE(request, { params });\n}\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 runtime: 'nodejs',\\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":[]}
|
|
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';\nimport { NextRequest } from 'next/server';\n\nconst handlers = createListApiHandlers();\n\nexport async function GET(\n request: NextRequest,\n context: { params: Promise<{ path?: string[] }> }\n) {\n const params = await context.params;\n return handlers.GET(request, { params });\n}\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';\nimport { NextRequest } from 'next/server';\n\nconst handlers = createContentApiHandlers();\n\nexport async function GET(\n request: NextRequest,\n context: { params: Promise<{ path: string[] }> }\n) {\n const params = await context.params;\n return handlers.GET(request, { params });\n}\n\nexport async function POST(\n request: NextRequest,\n context: { params: Promise<{ path: string[] }> }\n) {\n const params = await context.params;\n return handlers.POST(request, { params });\n}\n\nexport async function DELETE(\n request: NextRequest,\n context: { params: Promise<{ path: string[] }> }\n) {\n const params = await context.params;\n return handlers.DELETE(request, { params });\n}\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 runtime: 'nodejs',\\n};\\n`,\n \"utf-8\"\n );\n console.log(\"ā
Created middleware.ts\");\n }\n\n // 5. Env example & Storage Selection\n console.log(\"\\nāļø Configuration\");\n\n // Interactive storage selection\n const rl = await import(\"readline\");\n const askQuestion = (query: string): Promise<string> => {\n const interface_ = rl.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n return new Promise((resolve) => {\n interface_.question(query, (ans) => {\n interface_.close();\n resolve(ans);\n });\n });\n };\n\n const storageChoice = await askQuestion(\n \"Select production storage provider:\\n 1. GitHub (default)\\n 2. S3 / Cloudflare R2 / Vercel Blob\\nEnter choice [1]: \"\n );\n\n const isS3 = storageChoice.trim() === \"2\";\n\n let envContent = `CMS_ADMIN_USERNAME=admin\nCMS_ADMIN_PASSWORD=password\nCMS_SESSION_SECRET=ensure_this_is_at_least_32_chars_long_random_string\n\n`;\n\n if (isS3) {\n envContent += `# S3 / Cloudflare R2 / Vercel Blob Storage\nSTORAGE_BUCKET=my-bucket\nSTORAGE_ENDPOINT=https://<accountid>.r2.cloudflarestorage.com\nSTORAGE_ACCESS_KEY_ID=\nSTORAGE_SECRET_ACCESS_KEY=\nSTORAGE_REGION=auto\nSTORAGE_PUBLIC_URL=https://pub-<id>.r2.dev\n`;\n } else {\n envContent += `# GitHub Storage (Production)\n# Generate at https://github.com/settings/tokens (Needs 'repo' or 'contents:write' scope)\nGITHUB_TOKEN=\nGITHUB_REPO=owner/repo\nGITHUB_BRANCH=main\n`;\n }\n\n const envExamplePath = path.join(process.cwd(), \".env.local.example\");\n await fs.writeFile(envExamplePath, envContent, \"utf-8\");\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":[]}
|