@ahmadubaidillah/cli 1.1.7 → 1.1.9
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 +35 -1
- package/dist/plugins/admin-panel/files/src/modules/admin/routes/admin.routes.tsx +26 -0
- package/dist/plugins/admin-panel/plugin.config.json +6 -1
- package/dist/plugins/auth/plugin.config.json +5 -0
- package/dist/plugins/cms/plugin.config.json +6 -1
- package/dist/plugins/openapi/plugin.config.json +6 -1
- package/dist/plugins/payments/plugin.config.json +5 -0
- package/dist/templates/saas/files/package.json +3 -3
- package/dist/templates/saas/files/src/{app.ts → app.tsx} +12 -8
- package/dist/templates/saas/files/src/core/LandingPage.tsx +89 -0
- package/dist/templates/saas/files/tsconfig.json +16 -0
- package/package.json +2 -2
package/dist/bin.js
CHANGED
|
@@ -14928,7 +14928,12 @@ var init_plugin_loader = __esm(() => {
|
|
|
14928
14928
|
compatibleTemplates: z.array(z.string()),
|
|
14929
14929
|
dependencies: z.array(z.string()).default([]),
|
|
14930
14930
|
packageDependencies: z.record(z.string()).default({}),
|
|
14931
|
-
packageDevDependencies: z.record(z.string()).default({})
|
|
14931
|
+
packageDevDependencies: z.record(z.string()).default({}),
|
|
14932
|
+
routeInfo: z.object({
|
|
14933
|
+
path: z.string(),
|
|
14934
|
+
importFile: z.string(),
|
|
14935
|
+
exportName: z.string()
|
|
14936
|
+
}).optional()
|
|
14932
14937
|
});
|
|
14933
14938
|
});
|
|
14934
14939
|
|
|
@@ -32393,6 +32398,35 @@ async function installPlugin(pluginName, projectDir, options) {
|
|
|
32393
32398
|
throw new Error(`Failed to parse target package.json during plugin installation: ${e.message}`);
|
|
32394
32399
|
}
|
|
32395
32400
|
}
|
|
32401
|
+
if (config.routeInfo) {
|
|
32402
|
+
const appPathTsx = join7(projectDir, "src", "app.tsx");
|
|
32403
|
+
const appPathTs = join7(projectDir, "src", "app.ts");
|
|
32404
|
+
const appPath = existsSync6(appPathTsx) ? appPathTsx : existsSync6(appPathTs) ? appPathTs : null;
|
|
32405
|
+
if (appPath) {
|
|
32406
|
+
let appContent = readFileSync4(appPath, "utf8");
|
|
32407
|
+
const importStmt = `import { ${config.routeInfo.exportName} } from '${config.routeInfo.importFile}';
|
|
32408
|
+
`;
|
|
32409
|
+
if (!appContent.includes(config.routeInfo.importFile)) {
|
|
32410
|
+
appContent = importStmt + appContent;
|
|
32411
|
+
}
|
|
32412
|
+
const routeStmt = `api.route('${config.routeInfo.path}', ${config.routeInfo.exportName});
|
|
32413
|
+
`;
|
|
32414
|
+
if (!appContent.includes(routeStmt)) {
|
|
32415
|
+
const marker = "// [PLUGIN_ROUTES_INJECTION_POINT]";
|
|
32416
|
+
const injectionRegex = /\/\/ \[PLUGIN_ROUTES_INJECTION_POINT\].*$/m;
|
|
32417
|
+
if (injectionRegex.test(appContent)) {
|
|
32418
|
+
appContent = appContent.replace(injectionRegex, `${marker}
|
|
32419
|
+
${routeStmt}`);
|
|
32420
|
+
} else {
|
|
32421
|
+
appContent += `
|
|
32422
|
+
// Auto-injected route
|
|
32423
|
+
api.route('${config.routeInfo.path}', ${config.routeInfo.exportName});
|
|
32424
|
+
`;
|
|
32425
|
+
}
|
|
32426
|
+
}
|
|
32427
|
+
writeFileSync4(appPath, appContent);
|
|
32428
|
+
}
|
|
32429
|
+
}
|
|
32396
32430
|
return {
|
|
32397
32431
|
success: true,
|
|
32398
32432
|
pluginName
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** @jsx jsx */
|
|
2
|
+
import { Hono } from 'hono';
|
|
3
|
+
import { jsx } from 'hono/jsx';
|
|
4
|
+
import { AdminDashboard } from '../views/AdminDashboard';
|
|
5
|
+
|
|
6
|
+
export const adminRoutes = new Hono();
|
|
7
|
+
|
|
8
|
+
adminRoutes.get('/', (c) => {
|
|
9
|
+
return c.html(
|
|
10
|
+
<html lang="en">
|
|
11
|
+
<head>
|
|
12
|
+
<meta charset="UTF-8" />
|
|
13
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
14
|
+
<title>Admin Dashboard | DevForge</title>
|
|
15
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
16
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet" />
|
|
17
|
+
<style>{`
|
|
18
|
+
body { font-family: 'Inter', sans-serif; }
|
|
19
|
+
`}</style>
|
|
20
|
+
</head>
|
|
21
|
+
<body>
|
|
22
|
+
<AdminDashboard />
|
|
23
|
+
</body>
|
|
24
|
+
</html>
|
|
25
|
+
);
|
|
26
|
+
});
|
|
@@ -5,5 +5,10 @@
|
|
|
5
5
|
"packageDependencies": {
|
|
6
6
|
"drizzle-orm": "latest"
|
|
7
7
|
},
|
|
8
|
-
"pluginDependencies": ["auth", "file_upload"]
|
|
8
|
+
"pluginDependencies": ["auth", "file_upload"],
|
|
9
|
+
"routeInfo": {
|
|
10
|
+
"path": "/cms",
|
|
11
|
+
"importFile": "./modules/cms/routes/cms.routes",
|
|
12
|
+
"exportName": "cmsRoutes"
|
|
13
|
+
}
|
|
9
14
|
}
|
|
@@ -6,5 +6,10 @@
|
|
|
6
6
|
"@hono/swagger-ui": "^0.4.0",
|
|
7
7
|
"@hono/zod-openapi": "^0.15.1"
|
|
8
8
|
},
|
|
9
|
-
"packageDevDependencies": {}
|
|
9
|
+
"packageDevDependencies": {},
|
|
10
|
+
"routeInfo": {
|
|
11
|
+
"path": "/platform",
|
|
12
|
+
"importFile": "./modules/openapi/openapi.routes",
|
|
13
|
+
"exportName": "openApiApp"
|
|
14
|
+
}
|
|
10
15
|
}
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
"version": "1.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
|
-
"dev": "bun run --hot src/app.
|
|
7
|
-
"start": "bun run src/app.
|
|
8
|
-
"build": "bun build ./src/app.
|
|
6
|
+
"dev": "bun run --hot src/app.tsx",
|
|
7
|
+
"start": "bun run src/app.tsx",
|
|
8
|
+
"build": "bun build ./src/app.tsx --outdir ./dist",
|
|
9
9
|
"db:push": "drizzle-kit push",
|
|
10
10
|
"db:studio": "drizzle-kit studio",
|
|
11
11
|
"test:e2e": "playwright test"
|
|
@@ -5,23 +5,27 @@ import { env } from './core/env';
|
|
|
5
5
|
import { errorHandler } from './core/errors';
|
|
6
6
|
import { userRoutes } from './modules/users/routes/user.routes';
|
|
7
7
|
|
|
8
|
+
// Core Modules
|
|
9
|
+
import { LandingPage } from './core/LandingPage';
|
|
10
|
+
|
|
8
11
|
const app = new Hono();
|
|
9
12
|
|
|
10
13
|
// Global Middleware
|
|
11
14
|
app.use('*', logger());
|
|
12
15
|
app.use('*', cors());
|
|
13
16
|
|
|
14
|
-
//
|
|
17
|
+
// UI - Landing Page
|
|
15
18
|
app.get('/', (c) => {
|
|
16
|
-
return c.
|
|
17
|
-
message: 'Welcome to {{PROJECT_NAME}} - Powered by DevForge',
|
|
18
|
-
status: 'running',
|
|
19
|
-
version: '1.0.0'
|
|
20
|
-
});
|
|
19
|
+
return c.html(<LandingPage projectName="{{PROJECT_NAME}}" />);
|
|
21
20
|
});
|
|
22
21
|
|
|
23
|
-
// Feature Routes
|
|
24
|
-
|
|
22
|
+
// Feature Routes (Registry)
|
|
23
|
+
const api = new Hono();
|
|
24
|
+
api.route('/users', userRoutes);
|
|
25
|
+
|
|
26
|
+
// [PLUGIN_ROUTES_INJECTION_POINT]
|
|
27
|
+
|
|
28
|
+
app.route('/api', api);
|
|
25
29
|
|
|
26
30
|
// Error Handling
|
|
27
31
|
app.onError(errorHandler);
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/** @jsx jsx */
|
|
2
|
+
import { jsx } from 'hono/jsx';
|
|
3
|
+
|
|
4
|
+
export const LandingPage = ({ projectName }: { projectName: string }) => (
|
|
5
|
+
<html lang="en">
|
|
6
|
+
<head>
|
|
7
|
+
<meta charset="UTF-8" />
|
|
8
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
9
|
+
<title>{projectName} | Built with DevForge</title>
|
|
10
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
11
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;800&display=swap" rel="stylesheet" />
|
|
12
|
+
<style>{`
|
|
13
|
+
body { font-family: 'Inter', sans-serif; }
|
|
14
|
+
.glass { background: rgba(255, 255, 255, 0.7); backdrop-filter: blur(10px); }
|
|
15
|
+
`}</style>
|
|
16
|
+
</head>
|
|
17
|
+
<body className="bg-slate-50 text-slate-900 overflow-x-hidden">
|
|
18
|
+
{/* Header */}
|
|
19
|
+
<nav className="fixed w-full z-50 glass border-b border-slate-200 py-4 px-6 flex justify-between items-center">
|
|
20
|
+
<div className="text-2xl font-extrabold tracking-tighter text-blue-600">
|
|
21
|
+
{projectName.toUpperCase()}
|
|
22
|
+
</div>
|
|
23
|
+
<div className="space-x-8 font-semibold text-slate-600 hidden md:flex">
|
|
24
|
+
<a href="#features" className="hover:text-blue-600 transition">Features</a>
|
|
25
|
+
<a href="#api" className="hover:text-blue-600 transition">API docs</a>
|
|
26
|
+
<a href="/admin" className="hover:text-blue-600 transition">Admin Panel</a>
|
|
27
|
+
</div>
|
|
28
|
+
<button className="bg-blue-600 text-white px-5 py-2 rounded-full font-bold hover:bg-blue-700 transition shadow-lg shadow-blue-200">
|
|
29
|
+
Get Started
|
|
30
|
+
</button>
|
|
31
|
+
</nav>
|
|
32
|
+
|
|
33
|
+
{/* Hero */}
|
|
34
|
+
<section className="pt-32 pb-20 px-6 text-center">
|
|
35
|
+
<div className="max-w-4xl mx-auto">
|
|
36
|
+
<span className="inline-block bg-blue-100 text-blue-700 px-4 py-1.5 rounded-full text-sm font-bold mb-6 animate-bounce">
|
|
37
|
+
✨ v1.0.0 Now Live
|
|
38
|
+
</span>
|
|
39
|
+
<h1 className="text-6xl md:text-7xl font-extrabold tracking-tight mb-8 bg-clip-text text-transparent bg-gradient-to-r from-slate-900 to-slate-600">
|
|
40
|
+
The Future of SaaS is <span className="text-blue-600">Modular.</span>
|
|
41
|
+
</h1>
|
|
42
|
+
<p className="text-xl text-slate-500 mb-10 max-w-2xl mx-auto leading-relaxed">
|
|
43
|
+
Welcome to your new powerhouse application. Scaffolded with <strong>Elite Standards</strong>,
|
|
44
|
+
built for <strong>Big O Performance</strong>, and optimized for <strong>Agentic AI</strong>.
|
|
45
|
+
</p>
|
|
46
|
+
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
|
47
|
+
<a href="/api/users/1" className="bg-slate-900 text-white px-8 py-4 rounded-xl font-bold hover:bg-slate-800 transition shadow-xl">
|
|
48
|
+
Explorer API
|
|
49
|
+
</a>
|
|
50
|
+
<a href="https://github.com/ahmad-ubaidillah/devforge" target="_blank" className="bg-white border border-slate-200 text-slate-900 px-8 py-4 rounded-xl font-bold hover:bg-slate-50 transition shadow-sm">
|
|
51
|
+
View Documentation
|
|
52
|
+
</a>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
</section>
|
|
56
|
+
|
|
57
|
+
{/* Feature Grid */}
|
|
58
|
+
<section id="features" className="py-20 bg-white border-y border-slate-200">
|
|
59
|
+
<div className="max-w-6xl mx-auto px-6">
|
|
60
|
+
<div className="text-center mb-16">
|
|
61
|
+
<h2 className="text-3xl font-bold mb-4">Everything you need to scale</h2>
|
|
62
|
+
<p className="text-slate-500">Pre-configured modules ready for production in seconds.</p>
|
|
63
|
+
</div>
|
|
64
|
+
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
|
65
|
+
<FeatureCard title="Modular Auth" desc="Stateless JWT sessions with Better Auth & Drizzle ORM." icon="🔐" />
|
|
66
|
+
<FeatureCard title="Global Billing" desc="Stripe-powered subscriptions and multi-tenant billing loops." icon="💳" />
|
|
67
|
+
<FeatureCard title="Auto-Analytics" desc="Server-side PostHog event tracking built into every route." icon="📊" />
|
|
68
|
+
<FeatureCard title="Search Engine" desc="Meilisearch integration for unified search abstraction." icon="🔍" />
|
|
69
|
+
<FeatureCard title="Queue Engine" desc="Asynchronous BullMQ task processing with Redis." icon="⚡" />
|
|
70
|
+
<FeatureCard title="Premium Admin" desc="God-mode dashboard with real-time websocket metrics." icon="🛠️" />
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
</section>
|
|
74
|
+
|
|
75
|
+
{/* Footer */}
|
|
76
|
+
<footer className="py-12 text-center text-slate-400 text-sm">
|
|
77
|
+
<p>© 2026 {projectName}. Built with <a href="https://github.com/ahmad-ubaidillah/devforge" className="text-blue-600 font-bold hover:underline">DevForge CLI</a>.</p>
|
|
78
|
+
</footer>
|
|
79
|
+
</body>
|
|
80
|
+
</html>
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
const FeatureCard = ({ title, desc, icon }: { title: string, desc: string, icon: string }) => (
|
|
84
|
+
<div className="p-8 rounded-2xl border border-slate-100 bg-slate-50/50 hover:border-blue-200 hover:bg-white transition-all group">
|
|
85
|
+
<div className="text-4xl mb-6">{icon}</div>
|
|
86
|
+
<h3 className="text-xl font-bold mb-3 group-hover:text-blue-600 transition">{title}</h3>
|
|
87
|
+
<p className="text-slate-500 leading-relaxed">{desc}</p>
|
|
88
|
+
</div>
|
|
89
|
+
);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"allowSyntheticDefaultImports": true,
|
|
10
|
+
"forceConsistentCasingInFileNames": true,
|
|
11
|
+
"allowJs": true,
|
|
12
|
+
"jsx": "react-jsx",
|
|
13
|
+
"jsxImportSource": "hono/jsx",
|
|
14
|
+
"types": ["bun"]
|
|
15
|
+
}
|
|
16
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ahmadubaidillah/cli",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.9",
|
|
4
4
|
"description": "The elite modular boilerplate engine for agentic applications.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"devforge-cli": "dist/bin.js"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@ahmadubaidillah/core": "^1.1.
|
|
19
|
+
"@ahmadubaidillah/core": "^1.1.9",
|
|
20
20
|
"@inquirer/prompts": "latest",
|
|
21
21
|
"chalk": "latest",
|
|
22
22
|
"commander": "latest",
|