@shakil-dev/shakil-stack 2.2.5 → 2.2.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/dist/index.js +16 -17
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{Command as le}from"commander";import te from"fs-extra";import T from"path";import{fileURLToPath as
|
|
2
|
+
import{Command as le}from"commander";import te from"fs-extra";import T from"path";import{fileURLToPath as me}from"url";import s from"fs-extra";import r from"path";import n from"chalk";import ne from"ora";import _ from"inquirer";import{execSync as oe}from"child_process";import ye from"fs-extra";var i=(e,o=process.cwd())=>{try{return oe(e,{stdio:"inherit",cwd:o}),!0}catch{return!1}},f=()=>{let e=process.env.npm_config_user_agent||"";return e.includes("pnpm")?"pnpm":e.includes("yarn")?"yarn":"npm"};var k=e=>`import { Server } from 'http';
|
|
3
3
|
import app from './app.js';
|
|
4
4
|
import config from './app/config/index.js';
|
|
5
5
|
|
|
@@ -205,7 +205,6 @@ const sendResponse = <T>(res: Response, data: IResponse<T>) => {
|
|
|
205
205
|
export default sendResponse;
|
|
206
206
|
`,$=`generator client {
|
|
207
207
|
provider = "prisma-client-js"
|
|
208
|
-
previewFeatures = ["prismaSchemaFolder"]
|
|
209
208
|
output = "../../generated/prisma"
|
|
210
209
|
}
|
|
211
210
|
|
|
@@ -407,23 +406,23 @@ ${e}/
|
|
|
407
406
|
|
|
408
407
|
---
|
|
409
408
|
Built with \u26A1 by **Shakil Ahmed Billal**
|
|
410
|
-
`;var x=async e=>{let
|
|
411
|
-
\u{1F680} Initializing ${n.bold(
|
|
412
|
-
`));let d=
|
|
413
|
-
\u{1F5BC}\uFE0F Scaffolding Next.js frontend...`)),i(`npx create-next-app@latest frontend --ts --tailwind --eslint --app --src-dir --import-alias "@/*" --use-${a}`,t);let
|
|
414
|
-
\u{1F3A8} Setting up shadcn/ui...`));try{i("npx shadcn@latest init -d",
|
|
415
|
-
\u26A0\uFE0F Warning: Failed to automate shadcn/ui init. You can run "npx shadcn@latest init" in the frontend folder.`))}}await s.outputFile(
|
|
409
|
+
`;var x=async e=>{let o=e;o||(o=(await _.prompt([{type:"input",name:"projectName",message:"What is your project name?",default:"shakil-stack-app"}])).projectName),o||(console.log(n.red("\u274C Error: Project name is required.")),process.exit(1));let{packageManager:a,useShadcn:g,installDeps:c}=await _.prompt([{type:"list",name:"packageManager",message:"Which package manager do you want to use?",choices:["pnpm","npm","yarn"],default:f()},{type:"confirm",name:"useShadcn",message:"Would you like to use shadcn/ui?",default:!0},{type:"confirm",name:"installDeps",message:"Do you want to install dependencies automatically?",default:!0}]),t=r.join(process.cwd(),o);s.existsSync(t)&&(console.log(n.red(`\u274C Error: Directory ${o} already exists.`)),process.exit(1)),console.log(n.cyan(`
|
|
410
|
+
\u{1F680} Initializing ${n.bold(o)}...
|
|
411
|
+
`));let d=ne("\u{1F6E0}\uFE0F Creating project structure...").start();try{await s.ensureDir(t),await s.ensureDir(r.join(t,"backend","src","app","config")),await s.ensureDir(r.join(t,"backend","src","app","lib")),await s.ensureDir(r.join(t,"backend","src","app","module")),await s.ensureDir(r.join(t,"backend","src","app","routes")),await s.ensureDir(r.join(t,"backend","src","app","middleware")),await s.ensureDir(r.join(t,"backend","src","app","utils")),await s.ensureDir(r.join(t,"backend","src","app","errorHelpers")),await s.ensureDir(r.join(t,"backend","prisma","schema")),console.log(n.cyan(`
|
|
412
|
+
\u{1F5BC}\uFE0F Scaffolding Next.js frontend...`)),i(`npx create-next-app@latest frontend --ts --tailwind --eslint --app --src-dir --import-alias "@/*" --use-${a}`,t);let l=["config","hooks","lib","services","types"];for(let y of l)await s.ensureDir(r.join(t,"frontend","src",y));if(g){console.log(n.cyan(`
|
|
413
|
+
\u{1F3A8} Setting up shadcn/ui...`));try{i("npx shadcn@latest init -d",r.join(t,"frontend")),console.log(n.cyan("\u{1F4E6} Adding common shadcn/ui components...")),i(`npx shadcn@latest add ${["button","card","input","label","textarea","dialog","dropdown-menu","table","tabs","checkbox"].join(" ")} -y`,r.join(t,"frontend")),console.log(n.green("\u2705 shadcn/ui and common components initialized successfully!\u2728"))}catch{console.log(n.yellow(`
|
|
414
|
+
\u26A0\uFE0F Warning: Failed to automate shadcn/ui init. You can run "npx shadcn@latest init" in the frontend folder.`))}}await s.outputFile(r.join(t,"backend","src","server.ts"),k(o)),await s.outputFile(r.join(t,"backend","src","app.ts"),j(o)),await s.outputFile(r.join(t,"backend","src","app","config","index.ts"),v),await s.outputFile(r.join(t,"backend","src","app","lib","prisma.ts"),R),await s.outputFile(r.join(t,"backend","src","app","lib","auth.ts"),S),await s.outputFile(r.join(t,"backend","src","app","routes","index.ts"),E),await s.outputFile(r.join(t,"backend","src","app","middleware","globalErrorHandler.ts"),A),await s.outputFile(r.join(t,"backend","src","app","middleware","notFound.ts"),C),await s.outputFile(r.join(t,"backend","src","app","middleware","sanitizeRequest.ts"),P),await s.outputFile(r.join(t,"backend","src","app","utils","catchAsync.ts"),D),await s.outputFile(r.join(t,"backend","src","app","utils","sendResponse.ts"),I),await s.outputFile(r.join(t,"backend","src","app","utils","sanitizer.ts"),O),await s.outputFile(r.join(t,"backend","src","app","errorHelpers","ApiError.ts"),F),await s.outputFile(r.join(t,"backend","prisma","schema","schema.prisma"),$),await s.outputFile(r.join(t,"backend","prisma","schema","auth.prisma"),N),await s.outputFile(r.join(t,"backend","prisma.config.ts"),q),await s.outputFile(r.join(t,"backend","tsconfig.json"),H),await s.outputFile(r.join(t,".gitignore"),M),await s.outputFile(r.join(t,"LICENSE"),L),await s.outputFile(r.join(t,"README.md"),U(o)),await s.outputFile(r.join(t,"CODE_OF_CONDUCT.md"),z),await s.outputFile(r.join(t,".env"),`DATABASE_URL="postgresql://postgres:postgres@localhost:5432/${o}"
|
|
416
415
|
JWT_SECRET="your-secret-key"
|
|
417
416
|
NODE_ENV="development"
|
|
418
|
-
PORT=8000`);let
|
|
417
|
+
PORT=8000`);let b={name:`${o}-backend`,version:"1.0.0",type:"module",scripts:{test:'echo "Error: no test specified" && exit 1',dev:"nodemon --exec tsx src/server.ts",build:"prisma generate && tsup src/server.ts --format esm --platform node --target node20 --outDir dist --external pg-native",postinstall:"prisma generate",start:"node dist/server.js","prisma:generate":"prisma generate","prisma:migrate":"prisma migrate dev","prisma:studio":"prisma studio",seed:"tsx prisma/seed.ts",setup:"pnpm install && pnpm add @prisma/adapter-pg pg && pnpm add -D @types/pg && pnpm prisma:generate",predev:"pnpm run prisma:generate",init:"pnpm run prisma:generate && pnpm run prisma:migrate --name init",lint:"eslint src/**/*.ts","lint:fix":"eslint src/**/*.ts --fix",format:"prettier --write .",push:"prisma db push",pull:"prisma db pull"},dependencies:{"@prisma/adapter-pg":"^7.5.0","@prisma/client":"^7.5.0","better-auth":"^1.5.6","cookie-parser":"^1.4.7",cors:"^2.8.6",dompurify:"^3.3.3",dotenv:"^17.3.1",express:"^5.2.1","express-rate-limit":"^8.3.1",helmet:"^8.1.0","http-status":"^2.1.0",jsdom:"^29.0.1",jsonwebtoken:"^9.0.3",morgan:"^1.10.1",pg:"^8.20.0",winston:"^3.19.0",zod:"^4.3.6"},devDependencies:{"@types/cookie-parser":"^1.4.10","@types/cors":"^2.8.19","@types/express":"^5.0.6","@types/node":"^20.19.37","@types/pg":"^8.20.0","@types/morgan":"^1.9.10","@types/jsdom":"^21.1.7",prisma:"^7.5.0",tsx:"^4.21.0",nodemon:"^3.1.14",tsup:"^8.5.1",typescript:"^5.9.3",eslint:"^9.21.0",prettier:"^3.5.2"}};await s.writeJson(r.join(t,"backend","package.json"),b,{spaces:2}),d.succeed(n.green("\u2705 Project structure created! \u2728")),c&&(console.log(n.yellow(`
|
|
419
418
|
\u{1F4E6} Finalizing dependencies with ${a}...
|
|
420
|
-
`)),i(`${a} install`,
|
|
419
|
+
`)),i(`${a} install`,r.join(t,"backend"))),console.log(n.cyan("To get started:")),console.log(n.white(` cd ${o}`)),console.log(n.white(` cd backend && ${a} dev
|
|
421
420
|
`)),console.log(n.white(` cd frontend && ${a} dev
|
|
422
|
-
`))}catch(
|
|
421
|
+
`))}catch(l){d.fail(n.red("\u274C Failed to initialize project.")),console.error(l),process.exit(1)}};import m from"fs-extra";import h from"path";import p from"chalk";import ie from"ora";var B=(e,o)=>`import { Request, Response } from 'express';
|
|
423
422
|
import httpStatus from 'http-status';
|
|
424
423
|
import catchAsync from '../../utils/catchAsync.js';
|
|
425
424
|
import sendResponse from '../../utils/sendResponse.js';
|
|
426
|
-
import { ${e}Service } from './${
|
|
425
|
+
import { ${e}Service } from './${o}.service.js';
|
|
427
426
|
|
|
428
427
|
const create${e} = catchAsync(async (req: Request, res: Response) => {
|
|
429
428
|
const result = await ${e}Service.create${e}IntoDB(req.body);
|
|
@@ -438,7 +437,7 @@ const create${e} = catchAsync(async (req: Request, res: Response) => {
|
|
|
438
437
|
export const ${e}Controller = {
|
|
439
438
|
create${e},
|
|
440
439
|
};
|
|
441
|
-
`,W=(e,
|
|
440
|
+
`,W=(e,o)=>`import { ${e} } from '@prisma/client';
|
|
442
441
|
import prisma from '../../lib/prisma.js';
|
|
443
442
|
|
|
444
443
|
const create${e}IntoDB = async (payload: any) => {
|
|
@@ -449,12 +448,12 @@ const create${e}IntoDB = async (payload: any) => {
|
|
|
449
448
|
export const ${e}Service = {
|
|
450
449
|
create${e}IntoDB,
|
|
451
450
|
};
|
|
452
|
-
`,G=(e,
|
|
453
|
-
import { ${e}Controller } from './${
|
|
451
|
+
`,G=(e,o)=>`import { Router } from 'express';
|
|
452
|
+
import { ${e}Controller } from './${o}.controller.js';
|
|
454
453
|
|
|
455
454
|
const router = Router();
|
|
456
455
|
|
|
457
|
-
router.post('/create-${
|
|
456
|
+
router.post('/create-${o}', ${e}Controller.create${e});
|
|
458
457
|
|
|
459
458
|
export const ${e}Routes = router;
|
|
460
459
|
`,V=e=>`export type I${e} = {
|
|
@@ -478,4 +477,4 @@ export const ${e}Validations = {
|
|
|
478
477
|
createdAt DateTime @default(now())
|
|
479
478
|
updatedAt DateTime @updatedAt
|
|
480
479
|
}
|
|
481
|
-
`;var X=async e=>{e||(console.log(p.red("\u274C Error: Module name is required.")),process.exit(1));let
|
|
480
|
+
`;var X=async e=>{e||(console.log(p.red("\u274C Error: Module name is required.")),process.exit(1));let o=e.charAt(0).toUpperCase()+e.slice(1),a=e.toLowerCase(),g=m.existsSync("backend")?"backend":".",c=h.join(g,"src","app","module",o);m.existsSync(h.join(g,"src","app","module"))||(console.log(p.red("\u274C Error: This command must be run inside your shakil-stack project root or backend directory.")),process.exit(1)),m.existsSync(c)&&(console.log(p.red(`\u274C Error: Module ${o} already exists.`)),process.exit(1));let t=ie(`\u{1F6E0}\uFE0F Generating module: ${p.cyan(o)}...`).start();try{await m.ensureDir(c);let d={"controller.ts":B(o,a),"service.ts":W(o,a),"route.ts":G(o,a),"interface.ts":V(o),"validation.ts":J(o),"constant.ts":Y(o)};await m.outputFile(h.join(g,"prisma","schema",`${a}.prisma`),K(o));for(let[l,b]of Object.entries(d))await m.outputFile(h.join(c,`${a}.${l}`),b);t.succeed(p.green(`\u2705 Module ${o} generated successfully! \u2728`)),console.log(p.gray(`Created at: ${c}`))}catch(d){t.fail(p.red("\u274C Failed to generate module.")),console.error(d)}};import pe from"fs-extra";import ce from"chalk";var Q=async()=>{let e=f(),o=pe.existsSync("backend")?"backend":".";console.log(ce.cyan(`\u{1F3D7}\uFE0F Building backend with ${e}...`)),i(`${e} run build`,o)};import de from"fs-extra";import w from"chalk";var Z=async e=>{let o=de.existsSync("backend")?"backend":".";e==="generate"?(console.log(w.cyan("\u{1F504} Generating Prisma client...")),i("npx prisma generate",o)):e==="migrate"?(console.log(w.cyan("\u{1F680} Running Prisma migrations...")),i("npx prisma migrate dev",o)):console.log(w.red(`\u274C Error: Unknown prisma subcommand: ${e}`))};var ue=me(import.meta.url),ee=T.dirname(ue),ge=T.resolve(ee,te.existsSync(T.resolve(ee,"../../package.json"))?"../../package.json":"../package.json"),fe=te.readJsonSync(ge),u=new le;u.name("shakil-stack").description("Full-stack EchoNet-style project generator CLI").version(fe.version);u.command("init").description("Initialize a new full-stack project").argument("[projectName]","Name of the project").action(e=>{x(e)});u.command("generate").alias("g").description("Generate a new module").argument("<type>","Type of generation (module)").argument("<name>","Name of the module").action((e,o)=>{e==="module"?X(o):console.log(`\u274C Error: Unknown generation type: ${e}`)});u.command("build").description("Build the backend for production").action(()=>{Q()});u.command("prisma").description("Prisma utilities").argument("<subcommand>","generate | migrate").action(e=>{Z(e)});process.argv.slice(2).length?u.parse(process.argv):x();
|