mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-26 06:44:58 +00:00
code: nextjs,frontends,package (3 files)
This commit is contained in:
@@ -19,22 +19,16 @@ type InstallPackagePayload = {
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const body = await readJson<InstallPackagePayload>(request)
|
||||
if (!body) {
|
||||
return NextResponse.json({ error: 'Invalid JSON payload' }, { status: 400 })
|
||||
}
|
||||
if (!body) return NextResponse.json({ error: 'Invalid JSON payload' }, { status: 400 })
|
||||
|
||||
const packageId = typeof body.packageId === 'string'
|
||||
? body.packageId.trim()
|
||||
: (typeof body.manifest?.id === 'string' ? body.manifest.id : '')
|
||||
if (!packageId) {
|
||||
return NextResponse.json({ error: 'Package ID is required' }, { status: 400 })
|
||||
}
|
||||
if (!packageId) return NextResponse.json({ error: 'Package ID is required' }, { status: 400 })
|
||||
|
||||
const entry = getPackageCatalogEntry(packageId)
|
||||
const content = body.content ?? entry?.content
|
||||
if (!content) {
|
||||
return NextResponse.json({ error: 'Package content not found' }, { status: 404 })
|
||||
}
|
||||
if (!content) return NextResponse.json({ error: 'Package content not found' }, { status: 404 })
|
||||
|
||||
const installed = await getInstalledPackages()
|
||||
if (installed.some((pkg) => pkg.packageId === packageId)) {
|
||||
@@ -43,14 +37,12 @@ export async function POST(request: NextRequest) {
|
||||
|
||||
await installPackageContent(packageId, content)
|
||||
|
||||
const installedPackage: InstalledPackage = {
|
||||
packageId,
|
||||
installedAt: typeof body.installedAt === 'number' ? body.installedAt : Date.now(),
|
||||
version: typeof body.version === 'string'
|
||||
? body.version
|
||||
: (body.manifest?.version ?? entry?.manifest.version ?? '0.0.0'),
|
||||
enabled: typeof body.enabled === 'boolean' ? body.enabled : true,
|
||||
}
|
||||
const installedAt = typeof body.installedAt === 'number' ? body.installedAt : Date.now()
|
||||
const version = typeof body.version === 'string'
|
||||
? body.version
|
||||
: (body.manifest?.version ?? entry?.manifest.version ?? '0.0.0')
|
||||
const enabled = typeof body.enabled === 'boolean' ? body.enabled : true
|
||||
const installedPackage: InstalledPackage = { packageId, installedAt, version, enabled }
|
||||
|
||||
await installPackage(installedPackage)
|
||||
return NextResponse.json({ installed: installedPackage }, { status: 201 })
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
import { createFileNode } from './create-file-node'
|
||||
import { createFolderNode } from './create-folder-node'
|
||||
import type { PackageTemplate, ReactAppTemplateConfig } from './types'
|
||||
|
||||
const appLayout = [
|
||||
"import './globals.css'",
|
||||
'',
|
||||
'export const metadata = {',
|
||||
" title: 'MetaBuilder App',",
|
||||
" description: 'Generated Next.js starter',",
|
||||
'}',
|
||||
'',
|
||||
'export default function RootLayout({ children }: { children: React.ReactNode }) {',
|
||||
' return (',
|
||||
' <html lang="en">',
|
||||
' <body>{children}</body>',
|
||||
' </html>',
|
||||
' )',
|
||||
'}',
|
||||
].join('\n')
|
||||
|
||||
const appPage = [
|
||||
"import { Hero } from '@/components/Hero'",
|
||||
'',
|
||||
'export default function HomePage() {',
|
||||
' return <Hero />',
|
||||
'}',
|
||||
].join('\n')
|
||||
|
||||
const heroComponent = [
|
||||
'export function Hero() {',
|
||||
' return (',
|
||||
' <main style={{ padding: "64px", fontFamily: "system-ui" }}>',
|
||||
' <h1 style={{ fontSize: "40px", marginBottom: "16px" }}>MetaBuilder App</h1>',
|
||||
' <p style={{ maxWidth: "560px", lineHeight: 1.6 }}>',
|
||||
' Ship fast with a generated Next.js starter, prewired for package exports.',
|
||||
' </p>',
|
||||
' </main>',
|
||||
' )',
|
||||
'}',
|
||||
].join('\n')
|
||||
|
||||
const packageJson = [
|
||||
'{',
|
||||
' "name": "metabuilder-web-app",',
|
||||
' "version": "0.1.0",',
|
||||
' "private": true,',
|
||||
' "scripts": {',
|
||||
' "dev": "next dev",',
|
||||
' "build": "next build",',
|
||||
' "start": "next start"',
|
||||
' },',
|
||||
' "dependencies": {',
|
||||
' "next": "latest",',
|
||||
' "react": "latest",',
|
||||
' "react-dom": "latest"',
|
||||
' }',
|
||||
'}',
|
||||
].join('\n')
|
||||
|
||||
const nextConfig = [
|
||||
'const nextConfig = {',
|
||||
' reactStrictMode: true,',
|
||||
'}',
|
||||
'',
|
||||
'export default nextConfig',
|
||||
].join('\n')
|
||||
|
||||
const tsConfig = [
|
||||
'{',
|
||||
' "compilerOptions": {',
|
||||
' "target": "ES2020",',
|
||||
' "lib": ["DOM", "DOM.Iterable", "ES2020"],',
|
||||
' "module": "ESNext",',
|
||||
' "moduleResolution": "Bundler",',
|
||||
' "jsx": "react-jsx",',
|
||||
' "strict": true',
|
||||
' }',
|
||||
'}',
|
||||
].join('\n')
|
||||
|
||||
const readme = [
|
||||
'# MetaBuilder Web App',
|
||||
'',
|
||||
'Generated starter with a hero component and app router layout.',
|
||||
'Use the Package IDE to export this project as a zip.',
|
||||
].join('\n')
|
||||
|
||||
export function buildReactAppTemplate(config: ReactAppTemplateConfig): PackageTemplate {
|
||||
const srcFolder = createFolderNode({
|
||||
name: 'src',
|
||||
expanded: true,
|
||||
children: [
|
||||
createFolderNode({
|
||||
name: 'app',
|
||||
expanded: true,
|
||||
children: [
|
||||
createFileNode({ name: 'layout.tsx', content: appLayout }),
|
||||
createFileNode({ name: 'page.tsx', content: appPage }),
|
||||
],
|
||||
}),
|
||||
createFolderNode({
|
||||
name: 'components',
|
||||
expanded: true,
|
||||
children: [createFileNode({ name: 'Hero.tsx', content: heroComponent })],
|
||||
}),
|
||||
createFolderNode({
|
||||
name: 'styles',
|
||||
expanded: true,
|
||||
children: [
|
||||
createFileNode({
|
||||
name: 'globals.css',
|
||||
content: 'body { margin: 0; background: #f8f9fb; color: #111827; }',
|
||||
}),
|
||||
],
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
||||
const publicFolder = createFolderNode({
|
||||
name: 'public',
|
||||
expanded: true,
|
||||
children: [createFileNode({ name: 'robots.txt', content: 'User-agent: *\nAllow: /' })],
|
||||
})
|
||||
|
||||
const root = createFolderNode({
|
||||
name: config.rootName,
|
||||
expanded: true,
|
||||
children: [
|
||||
srcFolder,
|
||||
publicFolder,
|
||||
createFileNode({ name: 'package.json', content: packageJson }),
|
||||
createFileNode({ name: 'next.config.ts', content: nextConfig }),
|
||||
createFileNode({ name: 'tsconfig.json', content: tsConfig }),
|
||||
createFileNode({ name: 'README.md', content: readme }),
|
||||
],
|
||||
})
|
||||
|
||||
return {
|
||||
id: config.id,
|
||||
name: config.name,
|
||||
description: config.description,
|
||||
rootName: config.rootName,
|
||||
tree: [root],
|
||||
tags: config.tags,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { buildPackageTemplate } from './build-package-template'
|
||||
import { buildReactAppTemplate } from './build-react-app-template'
|
||||
import { PACKAGE_TEMPLATE_CONFIGS, REACT_APP_TEMPLATE_CONFIG } from './template-configs'
|
||||
import type { PackageTemplate } from './types'
|
||||
|
||||
export function getPackageTemplates(): PackageTemplate[] {
|
||||
const packageTemplates = PACKAGE_TEMPLATE_CONFIGS.map((config) => buildPackageTemplate(config))
|
||||
const reactTemplate = buildReactAppTemplate(REACT_APP_TEMPLATE_CONFIG)
|
||||
return [reactTemplate, ...packageTemplates]
|
||||
}
|
||||
Reference in New Issue
Block a user