wexts 1.0.1

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.
Files changed (99) hide show
  1. package/README.md +443 -0
  2. package/dist/chunk-2H7UOFLK.js +11 -0
  3. package/dist/chunk-2H7UOFLK.js.map +1 -0
  4. package/dist/chunk-2ZKONAXC.js +45 -0
  5. package/dist/chunk-2ZKONAXC.js.map +1 -0
  6. package/dist/chunk-57VDULE3.mjs +83 -0
  7. package/dist/chunk-57VDULE3.mjs.map +1 -0
  8. package/dist/chunk-6K3RXN4Y.mjs +45 -0
  9. package/dist/chunk-6K3RXN4Y.mjs.map +1 -0
  10. package/dist/chunk-6KN6UIHT.js +67 -0
  11. package/dist/chunk-6KN6UIHT.js.map +1 -0
  12. package/dist/chunk-A5OZK2TO.mjs +56 -0
  13. package/dist/chunk-A5OZK2TO.mjs.map +1 -0
  14. package/dist/chunk-ELVFG4US.js +83 -0
  15. package/dist/chunk-ELVFG4US.js.map +1 -0
  16. package/dist/chunk-H6XDQJ3N.mjs +11 -0
  17. package/dist/chunk-H6XDQJ3N.mjs.map +1 -0
  18. package/dist/chunk-HE3JQ62E.js +56 -0
  19. package/dist/chunk-HE3JQ62E.js.map +1 -0
  20. package/dist/chunk-HHXRAV67.mjs +229 -0
  21. package/dist/chunk-HHXRAV67.mjs.map +1 -0
  22. package/dist/chunk-J7J2LRG7.js +229 -0
  23. package/dist/chunk-J7J2LRG7.js.map +1 -0
  24. package/dist/chunk-LWNHEPTL.mjs +2 -0
  25. package/dist/chunk-LWNHEPTL.mjs.map +1 -0
  26. package/dist/chunk-MAVJYD6O.js +2 -0
  27. package/dist/chunk-MAVJYD6O.js.map +1 -0
  28. package/dist/chunk-QUV6QXTP.js +363 -0
  29. package/dist/chunk-QUV6QXTP.js.map +1 -0
  30. package/dist/chunk-WZBBQLFT.mjs +363 -0
  31. package/dist/chunk-WZBBQLFT.mjs.map +1 -0
  32. package/dist/chunk-XMPCR7N3.mjs +67 -0
  33. package/dist/chunk-XMPCR7N3.mjs.map +1 -0
  34. package/dist/cli/index.mjs +69 -0
  35. package/dist/cli/index.mjs.map +1 -0
  36. package/dist/client/index.js +11 -0
  37. package/dist/client/index.js.map +1 -0
  38. package/dist/client/index.mjs +11 -0
  39. package/dist/client/index.mjs.map +1 -0
  40. package/dist/codegen-J3XOZCQZ.js +14 -0
  41. package/dist/codegen-J3XOZCQZ.js.map +1 -0
  42. package/dist/codegen-ZZBQIGUQ.mjs +14 -0
  43. package/dist/codegen-ZZBQIGUQ.mjs.map +1 -0
  44. package/dist/dev-server-K5YZAZY2.mjs +14 -0
  45. package/dist/dev-server-K5YZAZY2.mjs.map +1 -0
  46. package/dist/dev-server-X453DBCE.js +14 -0
  47. package/dist/dev-server-X453DBCE.js.map +1 -0
  48. package/dist/index.js +274 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/index.mjs +274 -0
  51. package/dist/index.mjs.map +1 -0
  52. package/dist/nest/index.js +21 -0
  53. package/dist/nest/index.js.map +1 -0
  54. package/dist/nest/index.mjs +21 -0
  55. package/dist/nest/index.mjs.map +1 -0
  56. package/dist/next/index.js +14 -0
  57. package/dist/next/index.js.map +1 -0
  58. package/dist/next/index.mjs +14 -0
  59. package/dist/next/index.mjs.map +1 -0
  60. package/dist/types/index.js +3 -0
  61. package/dist/types/index.js.map +1 -0
  62. package/dist/types/index.mjs +3 -0
  63. package/dist/types/index.mjs.map +1 -0
  64. package/package.json +104 -0
  65. package/templates/nestjs-api/.env.example +4 -0
  66. package/templates/nestjs-api/README.md +79 -0
  67. package/templates/nestjs-api/nest-cli.json +7 -0
  68. package/templates/nestjs-api/package.json +39 -0
  69. package/templates/nestjs-api/prisma/schema.prisma +29 -0
  70. package/templates/nestjs-api/src/app.module.ts +17 -0
  71. package/templates/nestjs-api/src/auth/auth.controller.ts +30 -0
  72. package/templates/nestjs-api/src/auth/auth.module.ts +26 -0
  73. package/templates/nestjs-api/src/auth/auth.service.ts +91 -0
  74. package/templates/nestjs-api/src/auth/dto/auth.dto.ts +22 -0
  75. package/templates/nestjs-api/src/auth/guards/jwt-auth.guard.ts +5 -0
  76. package/templates/nestjs-api/src/auth/strategies/jwt.strategy.ts +19 -0
  77. package/templates/nestjs-api/src/main.ts +32 -0
  78. package/templates/nestjs-api/src/prisma/prisma.module.ts +9 -0
  79. package/templates/nestjs-api/src/prisma/prisma.service.ts +14 -0
  80. package/templates/nestjs-api/src/todos/dto/todo.dto.ts +24 -0
  81. package/templates/nestjs-api/src/todos/todos.controller.ts +46 -0
  82. package/templates/nestjs-api/src/todos/todos.module.ts +9 -0
  83. package/templates/nestjs-api/src/todos/todos.service.ts +53 -0
  84. package/templates/nestjs-api/src/users/users.controller.ts +17 -0
  85. package/templates/nestjs-api/src/users/users.module.ts +10 -0
  86. package/templates/nestjs-api/src/users/users.service.ts +19 -0
  87. package/templates/nestjs-api/tsconfig.json +21 -0
  88. package/templates/nextjs-web/.env.local.example +1 -0
  89. package/templates/nextjs-web/README.md +68 -0
  90. package/templates/nextjs-web/app/dashboard/page.tsx +175 -0
  91. package/templates/nextjs-web/app/globals.css +28 -0
  92. package/templates/nextjs-web/app/layout.tsx +27 -0
  93. package/templates/nextjs-web/app/login/page.tsx +107 -0
  94. package/templates/nextjs-web/app/page.tsx +28 -0
  95. package/templates/nextjs-web/app/register/page.tsx +130 -0
  96. package/templates/nextjs-web/next.config.mjs +4 -0
  97. package/templates/nextjs-web/package.json +28 -0
  98. package/templates/nextjs-web/tailwind.config.ts +15 -0
  99. package/templates/nextjs-web/tsconfig.json +39 -0
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ FusionProvider,
4
+ useAuth,
5
+ useFusion
6
+ } from "../chunk-57VDULE3.mjs";
7
+ import "../chunk-6K3RXN4Y.mjs";
8
+ import "../chunk-H6XDQJ3N.mjs";
9
+ export {
10
+ FusionProvider,
11
+ useAuth,
12
+ useFusion
13
+ };
14
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ "use strict";require('../chunk-MAVJYD6O.js');
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["c:\\Users\\ziad\\Desktop\\FusionJS\\packages\\fusionjs\\dist\\types\\index.js"],"names":[],"mappings":"AAAA;AACA,6CAA6B","file":"C:\\Users\\ziad\\Desktop\\FusionJS\\packages\\fusionjs\\dist\\types\\index.js"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import "../chunk-LWNHEPTL.mjs";
3
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/package.json ADDED
@@ -0,0 +1,104 @@
1
+ {
2
+ "name": "wexts",
3
+ "version": "1.0.1",
4
+ "description": "The all-in-one wexts framework combining NestJS and Next.js",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "fusion": "./dist/cli/index.js"
10
+ },
11
+ "files": [
12
+ "dist",
13
+ "templates"
14
+ ],
15
+ "exports": {
16
+ ".": {
17
+ "types": "./dist/index.d.ts",
18
+ "import": "./dist/index.mjs",
19
+ "require": "./dist/index.js"
20
+ },
21
+ "./client": {
22
+ "types": "./dist/client/index.d.ts",
23
+ "import": "./dist/client/index.mjs",
24
+ "require": "./dist/client/index.js"
25
+ },
26
+ "./types": {
27
+ "types": "./dist/types/index.d.ts",
28
+ "import": "./dist/types/index.mjs",
29
+ "require": "./dist/types/index.js"
30
+ },
31
+ "./nest": {
32
+ "types": "./dist/nest/index.d.ts",
33
+ "import": "./dist/nest/index.mjs",
34
+ "require": "./dist/nest/index.js"
35
+ },
36
+ "./next": {
37
+ "types": "./dist/next/index.d.ts",
38
+ "import": "./dist/next/index.mjs",
39
+ "require": "./dist/next/index.js"
40
+ }
41
+ },
42
+ "scripts": {
43
+ "build": "tsup",
44
+ "dev": "tsup --watch",
45
+ "test": "vitest run",
46
+ "lint": "eslint src",
47
+ "release": "npm run build && npm publish --access public"
48
+ },
49
+ "keywords": [
50
+ "wexts",
51
+ "framework",
52
+ "fullstack",
53
+ "nestjs",
54
+ "nextjs",
55
+ "monorepo",
56
+ "typescript"
57
+ ],
58
+ "author": "wexts Team",
59
+ "license": "MIT",
60
+ "repository": {
61
+ "type": "git",
62
+ "url": "https://github.com/ziadmustafa1/wexts.git",
63
+ "directory": "packages/wexts"
64
+ },
65
+ "devDependencies": {
66
+ "tsup": "^8.0.0",
67
+ "vitest": "^1.0.0",
68
+ "@types/node": "^20.0.0",
69
+ "@types/react": "^18.2.0",
70
+ "@types/http-proxy": "^1.17.14"
71
+ },
72
+ "dependencies": {
73
+ "commander": "^11.1.0",
74
+ "inquirer": "^9.2.12",
75
+ "chokidar": "^3.5.3",
76
+ "picocolors": "^1.0.0",
77
+ "reflect-metadata": "^0.2.1",
78
+ "typescript": "^5.3.0",
79
+ "http-proxy": "^1.18.1"
80
+ },
81
+ "peerDependencies": {
82
+ "@nestjs/common": "^10.0.0",
83
+ "@nestjs/core": "^10.0.0",
84
+ "react": "^18.0.0 || ^19.0.0",
85
+ "next": "^14.0.0 || ^15.0.0 || ^16.0.0"
86
+ },
87
+ "peerDependenciesMeta": {
88
+ "@nestjs/common": {
89
+ "optional": true
90
+ },
91
+ "@nestjs/core": {
92
+ "optional": true
93
+ },
94
+ "react": {
95
+ "optional": true
96
+ },
97
+ "next": {
98
+ "optional": true
99
+ }
100
+ },
101
+ "publishConfig": {
102
+ "access": "public"
103
+ }
104
+ }
@@ -0,0 +1,4 @@
1
+ DATABASE_URL="file:./dev.db"
2
+ JWT_SECRET="your-secret-key-change-in-production"
3
+ JWT_EXPIRES_IN="7d"
4
+ PORT=5050
@@ -0,0 +1,79 @@
1
+ # Fusion NestJS API
2
+
3
+ Complete NestJS 10 backend with authentication, Prisma ORM, and CRUD operations.
4
+
5
+ ## Features
6
+
7
+ - ✅ JWT Authentication
8
+ - ✅ Prisma ORM (SQLite for development)
9
+ - ✅ User Management
10
+ - ✅ Todo CRUD Operations
11
+ - ✅ Fusion Decorators for Auto API Client Generation
12
+ - ✅ Fastify Adapter
13
+ - ✅ Input Validation
14
+
15
+ ## Setup
16
+
17
+ ```bash
18
+ # Install dependencies
19
+ npm install
20
+
21
+ # Copy environment variables
22
+ cp .env.example .env
23
+
24
+ # Generate Prisma client
25
+ npm run prisma:generate
26
+
27
+ # Run migrations
28
+ npm run prisma:migrate
29
+
30
+ # Start development server
31
+ npm run start:dev
32
+ ```
33
+
34
+ ## API Endpoints
35
+
36
+ ### Authentication
37
+ - `POST /auth/register` - Register new user
38
+ - `POST /auth/login` - Login
39
+ - `GET /auth/me` - Get current user (protected)
40
+
41
+ ### Todos
42
+ - `GET /todos` - Get all todos (protected)
43
+ - `GET /todos/:id` - Get single todo (protected)
44
+ - `POST /todos` - Create todo (protected)
45
+ - `PUT /todos/:id` - Update todo (protected)
46
+ - `DELETE /todos/:id` - Delete todo (protected)
47
+
48
+ ### Users
49
+ - `GET /users/me` - Get current user profile (protected)
50
+
51
+ ## Environment Variables
52
+
53
+ ```env
54
+ DATABASE_URL="file:./dev.db"
55
+ JWT_SECRET="your-secret-key"
56
+ JWT_EXPIRES_IN="7d"
57
+ PORT=5050
58
+ ```
59
+
60
+ ## Database
61
+
62
+ Using Prisma with SQLite for development. To create a new migration:
63
+
64
+ ```bash
65
+ npm run prisma:migrate
66
+ ```
67
+
68
+ To view database in Prisma Studio:
69
+
70
+ ```bash
71
+ npm run prisma:studio
72
+ ```
73
+
74
+ ## Building for Production
75
+
76
+ ```bash
77
+ npm run build
78
+ npm run start:prod
79
+ ```
@@ -0,0 +1,7 @@
1
+ {
2
+ "collection": "@nestjs/schematics",
3
+ "sourceRoot": "src",
4
+ "compilerOptions": {
5
+ "deleteOutDir": true
6
+ }
7
+ }
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "fusion-api",
3
+ "version": "0.0.1",
4
+ "description": "wexts NestJS API",
5
+ "scripts": {
6
+ "build": "nest build",
7
+ "start": "nest start",
8
+ "start:dev": "nest start --watch",
9
+ "start:prod": "node dist/main",
10
+ "prisma:generate": "prisma generate",
11
+ "prisma:migrate": "prisma migrate dev",
12
+ "prisma:studio": "prisma studio"
13
+ },
14
+ "dependencies": {
15
+ "@nestjs/common": "^10.3.0",
16
+ "@nestjs/core": "^10.3.0",
17
+ "@nestjs/platform-fastify": "^10.3.0",
18
+ "@nestjs/jwt": "^10.2.0",
19
+ "@nestjs/passport": "^10.0.3",
20
+ "@prisma/client": "^5.9.0",
21
+ "passport": "^0.7.0",
22
+ "passport-jwt": "^4.0.1",
23
+ "bcrypt": "^5.1.1",
24
+ "class-validator": "^0.14.1",
25
+ "class-transformer": "^0.5.1",
26
+ "reflect-metadata": "^0.2.1",
27
+ "rxjs": "^7.8.1",
28
+ "wexts": "^1.0.0"
29
+ },
30
+ "devDependencies": {
31
+ "@nestjs/cli": "^10.3.0",
32
+ "@nestjs/schematics": "^10.1.0",
33
+ "@types/node": "^20.11.0",
34
+ "@types/passport-jwt": "^4.0.1",
35
+ "@types/bcrypt": "^5.0.2",
36
+ "prisma": "^5.9.0",
37
+ "typescript": "^5.3.3"
38
+ }
39
+ }
@@ -0,0 +1,29 @@
1
+ generator client {
2
+ provider = "prisma-client-js"
3
+ }
4
+
5
+ datasource db {
6
+ provider = "sqlite"
7
+ url = env("DATABASE_URL")
8
+ }
9
+
10
+ model User {
11
+ id String @id @default(uuid())
12
+ email String @unique
13
+ name String?
14
+ password String
15
+ createdAt DateTime @default(now())
16
+ updatedAt DateTime @updatedAt
17
+ todos Todo[]
18
+ }
19
+
20
+ model Todo {
21
+ id String @id @default(uuid())
22
+ title String
23
+ description String?
24
+ completed Boolean @default(false)
25
+ userId String
26
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
27
+ createdAt DateTime @default(now())
28
+ updatedAt DateTime @updatedAt
29
+ }
@@ -0,0 +1,17 @@
1
+ import { Module } from '@nestjs/common';
2
+ import { ConfigModule } from '@nestjs/config';
3
+ import { PrismaModule } from './prisma/prisma.module';
4
+ import { AuthModule } from './auth/auth.module';
5
+ import { UsersModule } from './users/users.module';
6
+ import { TodosModule } from './todos/todos.module';
7
+
8
+ @Module({
9
+ imports: [
10
+ ConfigModule.forRoot({ isGlobal: true }),
11
+ PrismaModule,
12
+ AuthModule,
13
+ UsersModule,
14
+ TodosModule,
15
+ ],
16
+ })
17
+ export class AppModule { }
@@ -0,0 +1,30 @@
1
+ import { Controller, Post, Get, Body, UseGuards, Request } from '@nestjs/common';
2
+ import { FusionController, FusionPost, FusionGet } from 'wexts/nest';
3
+ import { AuthService } from './auth.service';
4
+ import { JwtAuthGuard } from './guards/jwt-auth.guard';
5
+ import { RegisterDto, LoginDto } from './dto/auth.dto';
6
+
7
+ @FusionController('auth')
8
+ @Controller('auth')
9
+ export class AuthController {
10
+ constructor(private authService: AuthService) { }
11
+
12
+ @FusionPost()
13
+ @Post('register')
14
+ async register(@Body() dto: RegisterDto) {
15
+ return this.authService.register(dto);
16
+ }
17
+
18
+ @FusionPost()
19
+ @Post('login')
20
+ async login(@Body() dto: LoginDto) {
21
+ return this.authService.login(dto);
22
+ }
23
+
24
+ @FusionGet()
25
+ @Get('me')
26
+ @UseGuards(JwtAuthGuard)
27
+ async getMe(@Request() req) {
28
+ return this.authService.getMe(req.user.userId);
29
+ }
30
+ }
@@ -0,0 +1,26 @@
1
+ import { Module } from '@nestjs/common';
2
+ import { JwtModule } from '@nestjs/jwt';
3
+ import { PassportModule } from '@nestjs/passport';
4
+ import { ConfigService } from '@nestjs/config';
5
+ import { AuthController } from './auth.controller';
6
+ import { AuthService } from './auth.service';
7
+ import { JwtStrategy } from './strategies/jwt.strategy';
8
+
9
+ @Module({
10
+ imports: [
11
+ PassportModule,
12
+ JwtModule.registerAsync({
13
+ inject: [ConfigService],
14
+ useFactory: (config: ConfigService) => ({
15
+ secret: config.get('JWT_SECRET') || 'default-secret',
16
+ signOptions: {
17
+ expiresIn: config.get('JWT_EXPIRES_IN') || '7d',
18
+ },
19
+ }),
20
+ }),
21
+ ],
22
+ controllers: [AuthController],
23
+ providers: [AuthService, JwtStrategy],
24
+ exports: [AuthService],
25
+ })
26
+ export class AuthModule { }
@@ -0,0 +1,91 @@
1
+ import { Injectable, UnauthorizedException } from '@nestjs/common';
2
+ import { JwtService } from '@nestjs/jwt';
3
+ import { PrismaService } from '../prisma/prisma.service';
4
+ import * as bcrypt from 'bcrypt';
5
+ import { RegisterDto, LoginDto } from './dto/auth.dto';
6
+
7
+ @Injectable()
8
+ export class AuthService {
9
+ constructor(
10
+ private prisma: PrismaService,
11
+ private jwtService: JwtService,
12
+ ) { }
13
+
14
+ async register(dto: RegisterDto) {
15
+ // Check if user exists
16
+ const exists = await this.prisma.user.findUnique({
17
+ where: { email: dto.email },
18
+ });
19
+
20
+ if (exists) {
21
+ throw new UnauthorizedException('Email already registered');
22
+ }
23
+
24
+ // Hash password
25
+ const hashedPassword = await bcrypt.hash(dto.password, 10);
26
+
27
+ // Create user
28
+ const user = await this.prisma.user.create({
29
+ data: {
30
+ email: dto.email,
31
+ name: dto.name,
32
+ password: hashedPassword,
33
+ },
34
+ select: {
35
+ id: true,
36
+ email: true,
37
+ name: true,
38
+ createdAt: true,
39
+ },
40
+ });
41
+
42
+ const token = this.generateToken(user.id, user.email);
43
+
44
+ return { user, token };
45
+ }
46
+
47
+ async login(dto: LoginDto) {
48
+ // Find user
49
+ const user = await this.prisma.user.findUnique({
50
+ where: { email: dto.email },
51
+ });
52
+
53
+ if (!user) {
54
+ throw new UnauthorizedException('Invalid credentials');
55
+ }
56
+
57
+ // Verify password
58
+ const valid = await bcrypt.compare(dto.password, user.password);
59
+
60
+ if (!valid) {
61
+ throw new UnauthorizedException('Invalid credentials');
62
+ }
63
+
64
+ const token = this.generateToken(user.id, user.email);
65
+
66
+ return {
67
+ user: {
68
+ id: user.id,
69
+ email: user.email,
70
+ name: user.name,
71
+ },
72
+ token,
73
+ };
74
+ }
75
+
76
+ async getMe(userId: string) {
77
+ return this.prisma.user.findUnique({
78
+ where: { id: userId },
79
+ select: {
80
+ id: true,
81
+ email: true,
82
+ name: true,
83
+ createdAt: true,
84
+ },
85
+ });
86
+ }
87
+
88
+ private generateToken(userId: string, email: string): string {
89
+ return this.jwtService.sign({ sub: userId, email });
90
+ }
91
+ }
@@ -0,0 +1,22 @@
1
+ import { IsEmail, IsString, MinLength, IsOptional } from 'class-validator';
2
+
3
+ export class RegisterDto {
4
+ @IsEmail()
5
+ email: string;
6
+
7
+ @IsString()
8
+ @MinLength(6)
9
+ password: string;
10
+
11
+ @IsString()
12
+ @IsOptional()
13
+ name?: string;
14
+ }
15
+
16
+ export class LoginDto {
17
+ @IsEmail()
18
+ email: string;
19
+
20
+ @IsString()
21
+ password: string;
22
+ }
@@ -0,0 +1,5 @@
1
+ import { Injectable } from '@nestjs/common';
2
+ import { AuthGuard } from '@nestjs/passport';
3
+
4
+ @Injectable()
5
+ export class JwtAuthGuard extends AuthGuard('jwt') { }
@@ -0,0 +1,19 @@
1
+ import { ExtractJwt, Strategy } from 'passport-jwt';
2
+ import { PassportStrategy } from '@nestjs/passport';
3
+ import { Injectable } from '@nestjs/common';
4
+ import { ConfigService } from '@nestjs/config';
5
+
6
+ @Injectable()
7
+ export class JwtStrategy extends PassportStrategy(Strategy) {
8
+ constructor(configService: ConfigService) {
9
+ super({
10
+ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
11
+ ignoreExpiration: false,
12
+ secretOrKey: configService.get('JWT_SECRET') || 'default-secret',
13
+ });
14
+ }
15
+
16
+ async validate(payload: any) {
17
+ return { userId: payload.sub, email: payload.email };
18
+ }
19
+ }
@@ -0,0 +1,32 @@
1
+ import { NestFactory } from '@nestjs/core';
2
+ import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';
3
+ import { ValidationPipe } from '@nestjs/common';
4
+ import { AppModule } from './app.module';
5
+
6
+ async function bootstrap() {
7
+ const app = await NestFactory.create<NestFastifyApplication>(
8
+ AppModule,
9
+ new FastifyAdapter({ logger: true })
10
+ );
11
+
12
+ // Enable CORS
13
+ app.enableCors({
14
+ origin: process.env.FRONTEND_URL || 'http://localhost:3000',
15
+ credentials: true,
16
+ });
17
+
18
+ // Global validation pipe
19
+ app.useGlobalPipes(
20
+ new ValidationPipe({
21
+ whitelist: true,
22
+ transform: true,
23
+ })
24
+ );
25
+
26
+ const port = process.env.PORT || 5050;
27
+ await app.listen(port, '0.0.0.0');
28
+
29
+ console.log(`🚀 Fusion API running on http://localhost:${port}`);
30
+ }
31
+
32
+ bootstrap();
@@ -0,0 +1,9 @@
1
+ import { Module, Global } from '@nestjs/common';
2
+ import { PrismaService } from './prisma.service';
3
+
4
+ @Global()
5
+ @Module({
6
+ providers: [PrismaService],
7
+ exports: [PrismaService],
8
+ })
9
+ export class PrismaModule { }
@@ -0,0 +1,14 @@
1
+ import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common';
2
+ import { PrismaClient } from '@prisma/client';
3
+
4
+ @Injectable()
5
+ export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy {
6
+ async onModuleInit() {
7
+ await this.$connect();
8
+ console.log('✅ Prisma connected');
9
+ }
10
+
11
+ async onModuleDestroy() {
12
+ await this.$disconnect();
13
+ }
14
+ }
@@ -0,0 +1,24 @@
1
+ import { IsString, IsBoolean, IsOptional } from 'class-validator';
2
+
3
+ export class CreateTodoDto {
4
+ @IsString()
5
+ title: string;
6
+
7
+ @IsString()
8
+ @IsOptional()
9
+ description?: string;
10
+ }
11
+
12
+ export class UpdateTodoDto {
13
+ @IsString()
14
+ @IsOptional()
15
+ title?: string;
16
+
17
+ @IsString()
18
+ @IsOptional()
19
+ description?: string;
20
+
21
+ @IsBoolean()
22
+ @IsOptional()
23
+ completed?: boolean;
24
+ }
@@ -0,0 +1,46 @@
1
+ import { Controller, Get, Post, Put, Delete, Body, Param, UseGuards, Request } from '@nestjs/common';
2
+ import { FusionController, FusionGet, FusionPost, FusionPut, FusionDelete } from 'wexts/nest';
3
+ import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
4
+ import { TodosService } from './todos.service';
5
+ import { CreateTodoDto, UpdateTodoDto } from './dto/todo.dto';
6
+
7
+ @FusionController('todos')
8
+ @Controller('todos')
9
+ @UseGuards(JwtAuthGuard)
10
+ export class TodosController {
11
+ constructor(private todosService: TodosService) { }
12
+
13
+ @FusionGet()
14
+ @Get()
15
+ async findAll(@Request() req) {
16
+ return this.todosService.findAll(req.user.userId);
17
+ }
18
+
19
+ @FusionGet()
20
+ @Get(':id')
21
+ async findOne(@Param('id') id: string, @Request() req) {
22
+ return this.todosService.findOne(id, req.user.userId);
23
+ }
24
+
25
+ @FusionPost()
26
+ @Post()
27
+ async create(@Body() dto: CreateTodoDto, @Request() req) {
28
+ return this.todosService.create(dto, req.user.userId);
29
+ }
30
+
31
+ @FusionPut()
32
+ @Put(':id')
33
+ async update(
34
+ @Param('id') id: string,
35
+ @Body() dto: UpdateTodoDto,
36
+ @Request() req,
37
+ ) {
38
+ return this.todosService.update(id, dto, req.user.userId);
39
+ }
40
+
41
+ @FusionDelete()
42
+ @Delete(':id')
43
+ async remove(@Param('id') id: string, @Request() req) {
44
+ return this.todosService.remove(id, req.user.userId);
45
+ }
46
+ }
@@ -0,0 +1,9 @@
1
+ import { Module } from '@nestjs/common';
2
+ import { TodosController } from './todos.controller';
3
+ import { TodosService } from './todos.service';
4
+
5
+ @Module({
6
+ controllers: [TodosController],
7
+ providers: [TodosService],
8
+ })
9
+ export class TodosModule { }