wexts 3.0.2 → 4.1.0

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 (288) hide show
  1. package/README.md +49 -346
  2. package/bin/wexts.cjs +2 -0
  3. package/dist/chunk-2KAQYLVN.js +0 -0
  4. package/dist/chunk-2KAQYLVN.js.map +1 -1
  5. package/dist/{chunk-O42L6HOX.js → chunk-2LJVUMXW.js} +79 -93
  6. package/dist/chunk-2LJVUMXW.js.map +1 -0
  7. package/dist/chunk-342VRT25.mjs +504 -0
  8. package/dist/chunk-342VRT25.mjs.map +1 -0
  9. package/dist/chunk-7HNQWJWV.js +504 -0
  10. package/dist/chunk-7HNQWJWV.js.map +1 -0
  11. package/dist/chunk-7QKLIVRF.js +94 -0
  12. package/dist/chunk-7QKLIVRF.js.map +1 -0
  13. package/dist/chunk-7SSCNCTW.mjs +137 -0
  14. package/dist/chunk-7SSCNCTW.mjs.map +1 -0
  15. package/dist/chunk-7TLSPR65.mjs +95 -0
  16. package/dist/chunk-7TLSPR65.mjs.map +1 -0
  17. package/dist/{chunk-FCEZDH42.mjs → chunk-7WULUGLH.mjs} +5 -3
  18. package/dist/chunk-7WULUGLH.mjs.map +1 -0
  19. package/dist/chunk-AVMQJWYD.js +95 -0
  20. package/dist/chunk-AVMQJWYD.js.map +1 -0
  21. package/dist/{chunk-WF65EDRZ.js → chunk-BG56B4DE.js} +20 -2
  22. package/dist/chunk-BG56B4DE.js.map +1 -0
  23. package/dist/chunk-CLM5PNSG.mjs +496 -0
  24. package/dist/chunk-CLM5PNSG.mjs.map +1 -0
  25. package/dist/chunk-DNLGCKTT.js +31 -0
  26. package/dist/chunk-DNLGCKTT.js.map +1 -0
  27. package/dist/{chunk-VNNVLQLJ.mjs → chunk-JHOVXH3X.mjs} +2 -2
  28. package/dist/chunk-JHOVXH3X.mjs.map +1 -0
  29. package/dist/chunk-MXINIFPC.js +105 -0
  30. package/dist/chunk-MXINIFPC.js.map +1 -0
  31. package/dist/chunk-O4II6N34.js +137 -0
  32. package/dist/chunk-O4II6N34.js.map +1 -0
  33. package/dist/chunk-SE32ZPOZ.js +496 -0
  34. package/dist/chunk-SE32ZPOZ.js.map +1 -0
  35. package/dist/{chunk-STTOPUZ2.mjs → chunk-UAL54DVV.mjs} +21 -3
  36. package/dist/chunk-UAL54DVV.mjs.map +1 -0
  37. package/dist/{chunk-3OM7CHCA.js → chunk-WCKSKU3C.js} +1 -1
  38. package/dist/chunk-WCKSKU3C.js.map +1 -0
  39. package/dist/chunk-WU6FW77M.mjs +105 -0
  40. package/dist/chunk-WU6FW77M.mjs.map +1 -0
  41. package/dist/chunk-XE4OXN2W.js +0 -0
  42. package/dist/chunk-XE4OXN2W.js.map +1 -1
  43. package/dist/chunk-YBM3IJEA.mjs +94 -0
  44. package/dist/chunk-YBM3IJEA.mjs.map +1 -0
  45. package/dist/{chunk-KXYLEUSW.mjs → chunk-YN6WIWNQ.mjs} +69 -83
  46. package/dist/chunk-YN6WIWNQ.mjs.map +1 -0
  47. package/dist/chunk-YSLEF5C5.mjs +0 -0
  48. package/dist/chunk-YSLEF5C5.mjs.map +0 -0
  49. package/dist/chunk-ZX7QIN24.mjs +31 -0
  50. package/dist/chunk-ZX7QIN24.mjs.map +1 -0
  51. package/dist/cli/index.d.mts +22 -0
  52. package/dist/cli/index.d.ts +22 -0
  53. package/dist/cli/index.js +676 -292
  54. package/dist/cli/index.js.map +1 -1
  55. package/dist/cli/index.mjs +678 -293
  56. package/dist/cli/index.mjs.map +1 -1
  57. package/dist/client/index.d.mts +10 -1
  58. package/dist/client/index.d.ts +10 -1
  59. package/dist/client/index.js +5 -2
  60. package/dist/client/index.js.map +1 -1
  61. package/dist/client/index.mjs +7 -4
  62. package/dist/client/index.mjs.map +0 -0
  63. package/dist/codegen/index.d.mts +2 -1
  64. package/dist/codegen/index.d.ts +2 -1
  65. package/dist/codegen/index.js +6 -3
  66. package/dist/codegen/index.js.map +1 -1
  67. package/dist/codegen/index.mjs +8 -5
  68. package/dist/codegen/index.mjs.map +0 -0
  69. package/dist/decorators-BT1FFqN0.d.mts +29 -0
  70. package/dist/decorators-DvS58PqC.d.ts +29 -0
  71. package/dist/dev-server/index.d.mts +1 -1
  72. package/dist/dev-server/index.d.ts +1 -1
  73. package/dist/dev-server/index.js +3 -3
  74. package/dist/dev-server/index.js.map +1 -1
  75. package/dist/dev-server/index.mjs +3 -3
  76. package/dist/dev-server/index.mjs.map +0 -0
  77. package/dist/{index-SjUaHgFr.d.ts → index-7QeQEf37.d.ts} +27 -10
  78. package/dist/{index-tFGPFVfQ.d.mts → index-7RvU-jGE.d.mts} +0 -1
  79. package/dist/{index-tFGPFVfQ.d.ts → index-7RvU-jGE.d.ts} +0 -1
  80. package/dist/{index-SjUaHgFr.d.mts → index-8nzxy0NN.d.mts} +27 -10
  81. package/dist/index-Co5ZsLqq.d.ts +58 -0
  82. package/dist/index-D94W1__r.d.mts +58 -0
  83. package/dist/index-DQmyVp6F.d.mts +27 -0
  84. package/dist/index-KL_1BrQb.d.ts +27 -0
  85. package/dist/index.d.mts +54 -7
  86. package/dist/index.d.ts +54 -7
  87. package/dist/index.js +70 -29
  88. package/dist/index.js.map +1 -1
  89. package/dist/index.mjs +62 -21
  90. package/dist/index.mjs.map +1 -1
  91. package/dist/nest/index.d.mts +3 -1
  92. package/dist/nest/index.d.ts +3 -1
  93. package/dist/nest/index.js +20 -2
  94. package/dist/nest/index.js.map +1 -1
  95. package/dist/nest/index.mjs +21 -3
  96. package/dist/nest/index.mjs.map +0 -0
  97. package/dist/next/index.d.mts +7 -2
  98. package/dist/next/index.d.ts +7 -2
  99. package/dist/next/index.js +135 -5
  100. package/dist/next/index.js.map +1 -1
  101. package/dist/next/index.mjs +133 -4
  102. package/dist/next/index.mjs.map +1 -1
  103. package/dist/rpc/index.d.mts +2 -0
  104. package/dist/rpc/index.d.ts +2 -0
  105. package/dist/rpc/index.js +23 -0
  106. package/dist/rpc/index.js.map +1 -0
  107. package/dist/rpc/index.mjs +23 -0
  108. package/dist/{chunk-7NSRDJ5C.mjs.map → rpc/index.mjs.map} +0 -0
  109. package/dist/runtime/index.d.mts +55 -0
  110. package/dist/runtime/index.d.ts +55 -0
  111. package/dist/runtime/index.js +221 -0
  112. package/dist/runtime/index.js.map +1 -0
  113. package/dist/runtime/index.mjs +221 -0
  114. package/dist/runtime/index.mjs.map +1 -0
  115. package/dist/types/index.d.mts +0 -0
  116. package/dist/types/index.d.ts +0 -0
  117. package/dist/types/index.js +0 -0
  118. package/dist/types/index.js.map +1 -1
  119. package/dist/types/index.mjs +1 -1
  120. package/dist/types/index.mjs.map +0 -0
  121. package/dist/types-7d_fC-C3.d.mts +32 -0
  122. package/dist/types-7d_fC-C3.d.ts +32 -0
  123. package/dist/vercel-builder/index.d.mts +58 -0
  124. package/dist/vercel-builder/index.d.ts +58 -0
  125. package/dist/vercel-builder/index.js +330 -0
  126. package/dist/vercel-builder/index.js.map +1 -0
  127. package/dist/vercel-builder/index.mjs +330 -0
  128. package/dist/vercel-builder/index.mjs.map +1 -0
  129. package/package.json +37 -16
  130. package/templates/.dockerignore +43 -43
  131. package/templates/.env.example +0 -0
  132. package/templates/Dockerfile +60 -60
  133. package/templates/Procfile +1 -1
  134. package/templates/README.md +67 -58
  135. package/templates/api-sdk.ts +115 -115
  136. package/templates/docker-compose.yml +34 -34
  137. package/templates/nestjs-api/.env.example +0 -0
  138. package/templates/nestjs-api/README.md +87 -79
  139. package/templates/nestjs-api/nest-cli.json +6 -6
  140. package/templates/nestjs-api/package.json +40 -40
  141. package/templates/nestjs-api/prisma/dev.db +0 -0
  142. package/templates/nestjs-api/prisma/migrations/20251123205437_init/migration.sql +0 -0
  143. package/templates/nestjs-api/prisma/migrations/migration_lock.toml +0 -0
  144. package/templates/nestjs-api/prisma/schema.prisma +29 -29
  145. package/templates/nestjs-api/src/app.module.ts +17 -17
  146. package/templates/nestjs-api/src/auth/auth.controller.ts +27 -27
  147. package/templates/nestjs-api/src/auth/auth.module.ts +37 -29
  148. package/templates/nestjs-api/src/auth/auth.service.ts +86 -86
  149. package/templates/nestjs-api/src/auth/dto/auth.dto.ts +22 -22
  150. package/templates/nestjs-api/src/auth/guards/jwt-auth.guard.ts +5 -5
  151. package/templates/nestjs-api/src/auth/strategies/jwt.strategy.ts +27 -19
  152. package/templates/nestjs-api/src/main.ts +32 -32
  153. package/templates/nestjs-api/src/prisma/prisma.module.ts +9 -9
  154. package/templates/nestjs-api/src/prisma/prisma.service.ts +14 -14
  155. package/templates/nestjs-api/src/todos/dto/todo.dto.ts +24 -24
  156. package/templates/nestjs-api/src/todos/todos.controller.ts +39 -39
  157. package/templates/nestjs-api/src/todos/todos.module.ts +11 -11
  158. package/templates/nestjs-api/src/todos/todos.service.ts +53 -53
  159. package/templates/nestjs-api/src/users/users.controller.ts +14 -14
  160. package/templates/nestjs-api/src/users/users.module.ts +12 -12
  161. package/templates/nestjs-api/src/users/users.service.ts +19 -19
  162. package/templates/nestjs-api/tsconfig.json +39 -39
  163. package/templates/nextjs-web/README.md +76 -68
  164. package/templates/nextjs-web/app/actions/auth.ts +108 -108
  165. package/templates/nextjs-web/app/dashboard/error.tsx +39 -39
  166. package/templates/nextjs-web/app/dashboard/loading.tsx +14 -14
  167. package/templates/nextjs-web/app/dashboard/page.tsx +5 -5
  168. package/templates/nextjs-web/app/globals.css +93 -93
  169. package/templates/nextjs-web/app/layout.tsx +29 -29
  170. package/templates/nextjs-web/app/login/page.tsx +5 -5
  171. package/templates/nextjs-web/app/page.tsx +28 -28
  172. package/templates/nextjs-web/app/register/page.tsx +5 -5
  173. package/templates/nextjs-web/components/ui/button.tsx +56 -56
  174. package/templates/nextjs-web/components/ui/card.tsx +79 -79
  175. package/templates/nextjs-web/components/ui/input.tsx +25 -25
  176. package/templates/nextjs-web/components/ui/label.tsx +24 -24
  177. package/templates/nextjs-web/features/auth/LoginForm.tsx +140 -140
  178. package/templates/nextjs-web/features/auth/RegisterForm.tsx +159 -159
  179. package/templates/nextjs-web/features/auth/api.ts +35 -35
  180. package/templates/nextjs-web/features/auth/index.ts +3 -3
  181. package/templates/nextjs-web/features/dashboard/DashboardView.tsx +204 -204
  182. package/templates/nextjs-web/features/dashboard/api.ts +9 -9
  183. package/templates/nextjs-web/features/dashboard/components.tsx +74 -74
  184. package/templates/nextjs-web/features/dashboard/index.ts +3 -3
  185. package/templates/nextjs-web/hooks/index.ts +4 -4
  186. package/templates/nextjs-web/lib/api-client.ts +89 -89
  187. package/templates/nextjs-web/lib/api.ts +115 -115
  188. package/templates/nextjs-web/lib/axios-global-config.ts +17 -17
  189. package/templates/nextjs-web/lib/utils.ts +6 -6
  190. package/templates/nextjs-web/lib/wexts-client.ts +4 -4
  191. package/templates/nextjs-web/next-env.d.ts +6 -6
  192. package/templates/nextjs-web/next.config.ts +20 -20
  193. package/templates/nextjs-web/package.json +37 -37
  194. package/templates/nextjs-web/postcss.config.js +6 -6
  195. package/templates/nextjs-web/tailwind.config.ts +69 -69
  196. package/templates/nextjs-web/tsconfig.json +1 -1
  197. package/templates/nixpacks.toml +11 -11
  198. package/templates/root-package.json +31 -31
  199. package/templates/server.ts +66 -66
  200. package/templates/tsconfig.json +30 -30
  201. package/dist/chunk-2MCBBWEA.js +0 -1
  202. package/dist/chunk-2MCBBWEA.js.map +0 -1
  203. package/dist/chunk-3OM7CHCA.js.map +0 -1
  204. package/dist/chunk-63MTCWU2.mjs +0 -361
  205. package/dist/chunk-63MTCWU2.mjs.map +0 -1
  206. package/dist/chunk-667BQCEM.js +0 -375
  207. package/dist/chunk-667BQCEM.js.map +0 -1
  208. package/dist/chunk-67IJ6H4J.mjs +0 -44
  209. package/dist/chunk-67IJ6H4J.mjs.map +0 -1
  210. package/dist/chunk-6SVQEGEX.mjs +0 -44
  211. package/dist/chunk-6SVQEGEX.mjs.map +0 -1
  212. package/dist/chunk-7NSRDJ5C.mjs +0 -1
  213. package/dist/chunk-ASDXAK6G.js +0 -44
  214. package/dist/chunk-ASDXAK6G.js.map +0 -1
  215. package/dist/chunk-CKZ4VSCB.mjs +0 -18
  216. package/dist/chunk-CKZ4VSCB.mjs.map +0 -1
  217. package/dist/chunk-DW6GOKMF.js +0 -57
  218. package/dist/chunk-DW6GOKMF.js.map +0 -1
  219. package/dist/chunk-EFZPSZWO.mjs +0 -1
  220. package/dist/chunk-EFZPSZWO.mjs.map +0 -1
  221. package/dist/chunk-FCEZDH42.mjs.map +0 -1
  222. package/dist/chunk-FYGXL4V7.js +0 -361
  223. package/dist/chunk-FYGXL4V7.js.map +0 -1
  224. package/dist/chunk-GKVPGKAH.js +0 -66
  225. package/dist/chunk-GKVPGKAH.js.map +0 -1
  226. package/dist/chunk-GWP6PNSP.js +0 -225
  227. package/dist/chunk-GWP6PNSP.js.map +0 -1
  228. package/dist/chunk-HQKTXE7E.mjs +0 -225
  229. package/dist/chunk-HQKTXE7E.mjs.map +0 -1
  230. package/dist/chunk-HSFLZUJN.mjs +0 -57
  231. package/dist/chunk-HSFLZUJN.mjs.map +0 -1
  232. package/dist/chunk-HU63F22V.js +0 -361
  233. package/dist/chunk-HU63F22V.js.map +0 -1
  234. package/dist/chunk-J5LGTIGS.mjs +0 -10
  235. package/dist/chunk-J5LGTIGS.mjs.map +0 -1
  236. package/dist/chunk-JMBD6DOP.js +0 -225
  237. package/dist/chunk-JMBD6DOP.js.map +0 -1
  238. package/dist/chunk-K7EIJSYQ.js +0 -1
  239. package/dist/chunk-K7EIJSYQ.js.map +0 -1
  240. package/dist/chunk-KXYLEUSW.mjs.map +0 -1
  241. package/dist/chunk-MTHKZO55.js +0 -44
  242. package/dist/chunk-MTHKZO55.js.map +0 -1
  243. package/dist/chunk-NNQFLD7O.mjs +0 -361
  244. package/dist/chunk-NNQFLD7O.mjs.map +0 -1
  245. package/dist/chunk-NU2UB242.js +0 -82
  246. package/dist/chunk-NU2UB242.js.map +0 -1
  247. package/dist/chunk-NULGSZFE.mjs +0 -57
  248. package/dist/chunk-NULGSZFE.mjs.map +0 -1
  249. package/dist/chunk-O42L6HOX.js.map +0 -1
  250. package/dist/chunk-ONXNE2A6.mjs +0 -375
  251. package/dist/chunk-ONXNE2A6.mjs.map +0 -1
  252. package/dist/chunk-OTBYRUBE.mjs +0 -225
  253. package/dist/chunk-OTBYRUBE.mjs.map +0 -1
  254. package/dist/chunk-OTSAVKLY.mjs +0 -66
  255. package/dist/chunk-OTSAVKLY.mjs.map +0 -1
  256. package/dist/chunk-PZ5AY32C.js +0 -10
  257. package/dist/chunk-PZ5AY32C.js.map +0 -1
  258. package/dist/chunk-QP2TMRLG.js +0 -57
  259. package/dist/chunk-QP2TMRLG.js.map +0 -1
  260. package/dist/chunk-RS23R3ZQ.mjs +0 -82
  261. package/dist/chunk-RS23R3ZQ.mjs.map +0 -1
  262. package/dist/chunk-STTOPUZ2.mjs.map +0 -1
  263. package/dist/chunk-VMT3LALB.mjs +0 -51
  264. package/dist/chunk-VMT3LALB.mjs.map +0 -1
  265. package/dist/chunk-VNNVLQLJ.mjs.map +0 -1
  266. package/dist/chunk-W3YRVEFQ.js +0 -66
  267. package/dist/chunk-W3YRVEFQ.js.map +0 -1
  268. package/dist/chunk-WF65EDRZ.js.map +0 -1
  269. package/dist/chunk-WMHVXEYQ.mjs +0 -66
  270. package/dist/chunk-WMHVXEYQ.mjs.map +0 -1
  271. package/dist/chunk-XVKTIYHY.js +0 -51
  272. package/dist/chunk-XVKTIYHY.js.map +0 -1
  273. package/dist/codegen-MRZDLCYI.js +0 -13
  274. package/dist/codegen-MRZDLCYI.js.map +0 -1
  275. package/dist/codegen-UI5HTMXE.mjs +0 -13
  276. package/dist/codegen-UI5HTMXE.mjs.map +0 -1
  277. package/dist/dev-server-JKRVBWPY.mjs +0 -13
  278. package/dist/dev-server-JKRVBWPY.mjs.map +0 -1
  279. package/dist/dev-server-TLL7UQMR.js +0 -13
  280. package/dist/dev-server-TLL7UQMR.js.map +0 -1
  281. package/dist/index-BsNaOUtH.d.mts +0 -44
  282. package/dist/index-BsNaOUtH.d.ts +0 -44
  283. package/dist/index-CrbXnXsO.d.ts +0 -62
  284. package/dist/index-kEbGExWM.d.mts +0 -62
  285. package/templates/nestjs-api/.env +0 -4
  286. package/templates/nestjs-api/package-lock.json +0 -5623
  287. package/templates/nextjs-web/.env +0 -1
  288. package/templates/nextjs-web/package-lock.json +0 -3254
package/README.md CHANGED
@@ -1,346 +1,49 @@
1
- <div align="center">
2
-
3
- ```
4
- ██╗ ██╗███████╗██╗ ██╗████████╗███████╗
5
- ██║ ██║██╔════╝╚██╗██╔╝╚══██╔══╝██╔════╝
6
- ██║ █╗ ██║█████╗ ╚███╔╝ ██║ ███████╗
7
- ██║███╗██║██╔══╝ ██╔██╗ ██║ ╚════██║
8
- ╚███╔███╔╝███████╗██╔╝ ██╗ ██║ ███████║
9
- ╚══╝╚══╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚══════╝
10
- ```
11
-
12
- <h1>WEXTS Framework</h1>
13
-
14
- **Build production-ready full-stack apps with Next.js 16 + NestJS 11 in a unified runtime**
15
-
16
- [![npm version](https://img.shields.io/npm/v/wexts.svg)](https://www.npmjs.com/package/wexts)
17
- [![Downloads](https://img.shields.io/npm/dm/wexts.svg)](https://www.npmjs.com/package/wexts)
18
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
19
- [![TypeScript](https://img.shields.io/badge/TypeScript-5.3-blue.svg)](https://www.typescriptlang.org/)
20
-
21
- [Quick Start](#-quick-start) • [Documentation](https://github.com/ziadmustafa1/wexts#documentation) • [Examples](https://github.com/ziadmustafa1/wexts/tree/main/demo)
22
-
23
- </div>
24
-
25
- ---
26
-
27
- ## ✨ Why WEXTS?
28
-
29
- Stop managing separate Next.js and NestJS servers. **WEXTS runs both in a single Node.js process** with zero configuration.
30
-
31
- **Traditional Approach:**
32
- ```
33
- Two separate servers (Next.js + NestJS)
34
- Complex proxy setup
35
- ❌ CORS configuration nightmare
36
- URLs everywhere in your code
37
- ❌ Two deployments to manage
38
- ```
39
-
40
- **WEXTS:**
41
- ```
42
- One unified server
43
- ✅ Smart routing (automatic)
44
- Zero configuration
45
- Type-safe SDK (no URLs!)
46
- Single deployment
47
- ```
48
-
49
- ---
50
-
51
- ## 🎯 Key Features
52
-
53
- - 🔥 **Unified Runtime** - Single Node.js process for frontend + backend
54
- - 🎨 **Zero URLs** - Call APIs without explicit URLs
55
- - ⚡ **Type-Safe** - End-to-end TypeScript with auto-complete
56
- - 🚀 **Production Ready** - Docker, Railway, Render, Vercel support
57
- - 🔒 **Auth Built-in** - JWT authentication out of the box
58
- - 📦 **Prisma ORM** - Database integration ready
59
- - 🐳 **Docker Ready** - Complete Docker setup included
60
-
61
- ---
62
-
63
- ## 🚀 Quick Start
64
-
65
- ```bash
66
- # Create new project
67
- npx wexts create my-app
68
-
69
- # Start development
70
- cd my-app
71
- pnpm install
72
- pnpm run dev
73
-
74
- # Open http://localhost:3000
75
- ```
76
-
77
- **That's it!** Your unified server is running with:
78
- - ✅ Next.js frontend
79
- - ✅ NestJS backend API
80
- - ✅ Smart routing
81
- - ✅ Hot reload
82
-
83
- ---
84
-
85
- ## 💡 The Magic - Zero URLs!
86
-
87
- ### ❌ Without WEXTS
88
-
89
- ```typescript
90
- // Hardcoded URLs everywhere
91
- const response = await fetch('http://localhost:3001/api/users');
92
- const users = await response.json();
93
-
94
- // Problems:
95
- // - No type safety
96
- // - CORS issues
97
- // - Environment management
98
- // - Proxy configuration
99
- ```
100
-
101
- ### ✅ With WEXTS
102
-
103
- ```typescript
104
- import { api } from '@/lib/api';
105
-
106
- // Type-safe, zero URLs, works everywhere!
107
- const users = await api.users.findAll();
108
- // ✅ Auto-complete
109
- // ✅ Type-safe
110
- // ✅ No configuration
111
- ```
112
-
113
- **The SDK automatically connects to your backend. No URLs needed!**
114
-
115
- ---
116
-
117
- ## 📖 Project Structure
118
-
119
- ```
120
- my-app/
121
- ├── 🚀 server.ts # Unified server
122
- ├── apps/
123
- │ ├── 🔙 api/ # NestJS Backend
124
- │ │ ├── src/
125
- │ │ │ ├── auth/ # JWT Authentication
126
- │ │ │ └── prisma/ # Database ORM
127
- │ │ └── prisma/schema.prisma
128
- │ │
129
- │ └── 🎨 web/ # Next.js Frontend
130
- │ ├── app/ # App Router
131
- │ └── lib/
132
- │ └── api.ts # 🔥 Type-safe SDK
133
-
134
- ├── 🐳 Dockerfile # Production build
135
- └── docker-compose.yml # Docker + PostgreSQL
136
- ```
137
-
138
- ---
139
-
140
- ## 🏗️ How It Works
141
-
142
- ```
143
- ┌─────────────────────────────────────────┐
144
- │ Single Node.js Process │
145
- │ │
146
- │ ┌──────────┐ ┌──────────┐ │
147
- │ │ Next.js │ │ NestJS │ │
148
- │ │ Frontend │ │ Backend │ │
149
- │ └──────────┘ └──────────┘ │
150
- │ │
151
- │ Smart Router Middleware │
152
- │ ┌─────────────────────────────┐ │
153
- │ │ /api/* → NestJS │ │
154
- │ │ /* → Next.js │ │
155
- │ └─────────────────────────────┘ │
156
- └─────────────────────────────────────────┘
157
- ```
158
-
159
- **No proxy. No CORS. Just works.** ✨
160
-
161
- ---
162
-
163
- ## 🔐 Built-in Authentication
164
-
165
- ```typescript
166
- // Register
167
- const { user, access_token } = await api.auth.register({
168
- email: 'user@example.com',
169
- password: 'secure123',
170
- name: 'John Doe'
171
- });
172
-
173
- // Login
174
- const { user, access_token } = await api.auth.login({
175
- email: 'user@example.com',
176
- password: 'secure123'
177
- });
178
-
179
- // Get current user
180
- const user = await api.auth.me();
181
- ```
182
-
183
- **Secure JWT authentication with httpOnly cookies included!**
184
-
185
- ---
186
-
187
- ## 🐳 Deploy Anywhere
188
-
189
- ### Docker (Recommended)
190
-
191
- ```bash
192
- docker-compose up -d
193
- ```
194
-
195
- **Includes PostgreSQL!** Your app is live at `http://localhost:3000`
196
-
197
- ### Railway (Easiest)
198
-
199
- ```bash
200
- # Push to GitHub, connect Railway, done!
201
- ```
202
-
203
- Railway auto-detects WEXTS configuration.
204
-
205
- ### Render / VPS
206
-
207
- ```bash
208
- pnpm run build
209
- pnpm start
210
- ```
211
-
212
- **One build. One deployment. Works everywhere.**
213
-
214
- ---
215
-
216
- ## 📚 Full Example
217
-
218
- ```typescript
219
- // Backend - apps/api/src/posts/posts.controller.ts
220
- @Controller('posts')
221
- @UseGuards(JwtAuthGuard)
222
- export class PostsController {
223
- @Get()
224
- findAll() {
225
- return this.postsService.findAll();
226
- }
227
-
228
- @Post()
229
- create(@Body() dto: CreatePostDto) {
230
- return this.postsService.create(dto);
231
- }
232
- }
233
-
234
- // Frontend - apps/web/lib/api.ts
235
- export const api = {
236
- posts: {
237
- findAll: () => request<Post[]>('GET', '/posts'),
238
- create: (data) => request<Post>('POST', '/posts', data),
239
- },
240
- };
241
-
242
- // Usage - apps/web/app/posts/page.tsx
243
- import { api } from '@/lib/api';
244
-
245
- export default async function PostsPage() {
246
- const posts = await api.posts.findAll(); // Type-safe!
247
-
248
- return (
249
- <div>
250
- {posts.map(post => (
251
- <article key={post.id}>
252
- <h2>{post.title}</h2>
253
- <p>{post.content}</p>
254
- </article>
255
- ))}
256
- </div>
257
- );
258
- }
259
- ```
260
-
261
- **Complete type safety from database to UI!**
262
-
263
- ---
264
-
265
- ## 🛠️ Commands
266
-
267
- ```bash
268
- # Development
269
- pnpm run dev # Start dev server
270
-
271
- # Production
272
- pnpm run build # Build everything
273
- pnpm start # Start production server
274
-
275
- # Database
276
- cd apps/api
277
- npx prisma migrate dev
278
- npx prisma studio
279
- ```
280
-
281
- ---
282
-
283
- ## 📦 What's Included
284
-
285
- - **Next.js 16** - Latest React framework with App Router
286
- - **NestJS 11** - Modern Node.js framework
287
- - **Prisma** - Type-safe database ORM
288
- - **JWT Auth** - Secure authentication
289
- - **TypeScript** - Full type safety
290
- - **Tailwind CSS** - Utility-first CSS
291
- - **Docker** - Production deployment
292
- - **Examples** - Auth, CRUD, and more
293
-
294
- ---
295
-
296
- ## 🎯 Perfect For
297
-
298
- ✅ Full-stack applications
299
- ✅ SaaS products
300
- ✅ Admin dashboards
301
- ✅ API + Web combo
302
- ✅ Production-ready apps
303
- ✅ Rapid prototyping
304
-
305
- ---
306
-
307
- ## 📚 Documentation
308
-
309
- - [Getting Started](https://github.com/ziadmustafa1/wexts/blob/main/docs/getting-started.md)
310
- - [Architecture](https://github.com/ziadmustafa1/wexts/blob/main/docs/architecture.md)
311
- - [API Reference](https://github.com/ziadmustafa1/wexts/blob/main/docs/api-reference.md)
312
- - [Deployment](https://github.com/ziadmustafa1/wexts/blob/main/docs/deployment.md)
313
- - [Examples](https://github.com/ziadmustafa1/wexts/tree/main/demo)
314
-
315
- ---
316
-
317
- ## 🤝 Contributing
318
-
319
- Contributions are welcome! See [CONTRIBUTING.md](https://github.com/ziadmustafa1/wexts/blob/main/CONTRIBUTING.md)
320
-
321
- ---
322
-
323
- ## 📄 License
324
-
325
- MIT © WEXTS Team
326
-
327
- ---
328
-
329
- ## 🙏 Built With
330
-
331
- - [Next.js](https://nextjs.org/) - React framework
332
- - [NestJS](https://nestjs.com/) - Node.js framework
333
- - [Prisma](https://www.prisma.io/) - Database ORM
334
- - [TypeScript](https://www.typescriptlang.org/) - Type safety
335
-
336
- ---
337
-
338
- <div align="center">
339
-
340
- **Stop managing separate servers. Start building with WEXTS.** 🚀
341
-
342
- [GitHub](https://github.com/ziadmustafa1/wexts) • [npm](https://www.npmjs.com/package/wexts) • [Documentation](https://github.com/ziadmustafa1/wexts#readme)
343
-
344
- Made with ❤️ for the TypeScript community
345
-
346
- </div>
1
+ # Wexts Package
2
+
3
+ `wexts` is a production-focused toolkit for running Next.js + NestJS behind one Fastify production runtime with generated typed RPC.
4
+
5
+ ## Stable In This Patch
6
+
7
+ - `wexts generate` creates a deterministic RPC manifest and typed client.
8
+ - `wexts start` starts the Fastify production runtime.
9
+ - `wexts doctor` and `wexts doctor --security` validate common release blockers.
10
+ - `wexts/next` exposes `FusionProvider`, `useFusion`, and `useWexts<T>()`.
11
+ - `wexts/client` exposes `createWextsRpcClient()`.
12
+ - `wexts/rpc` exposes RPC metadata types/decorators.
13
+ - `wexts/runtime` exposes the production runtime helpers.
14
+
15
+ ## Canonical Example
16
+
17
+ Use `examples/hello-rpc` from the repository as the release-verified path.
18
+
19
+ ```bash
20
+ pnpm --filter wexts-example-hello-rpc generate
21
+ pnpm --filter wexts-example-hello-rpc build
22
+ pnpm --filter wexts-example-hello-rpc run doctor
23
+ pnpm --filter wexts-example-hello-rpc run doctor:security
24
+ ```
25
+
26
+ ## Production Runtime
27
+
28
+ Production runtime is single-port:
29
+
30
+ - `/health`
31
+ - `/api/health`
32
+ - `/rpc/:service/:method`
33
+ - optional Nest under `/api`
34
+ - optional Next frontend routes
35
+
36
+ Development mode currently runs separate web/API processes. Use `wexts start` for the supported single-port runtime path.
37
+
38
+ ## Security
39
+
40
+ Use `@wexts/security` / Wexts Shield before runtime routes. It provides application-layer controls. It does not replace Cloudflare/WAF/provider DDoS protection, and its default memory rate limit store is single-process only.
41
+
42
+ ## Deprecated Compatibility Paths
43
+
44
+ - `demo/`
45
+ - `packages/templates/nestjs-api`
46
+ - `packages/templates/nextjs-web`
47
+ - legacy Fusion controller codegen paths
48
+
49
+ These are retained for compatibility and should not be marketed as the recommended production structure.
package/bin/wexts.cjs ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require("../dist/cli/index.js");
File without changes
@@ -1 +1 @@
1
- {"version":3,"sources":["c:\\Users\\ziad\\Desktop\\wexts\\packages\\dist\\chunk-2KAQYLVN.js"],"names":[],"mappings":"AAAA","file":"C:\\Users\\ziad\\Desktop\\wexts\\packages\\dist\\chunk-2KAQYLVN.js"}
1
+ {"version":3,"sources":["/Volumes/Projects/wexts/packages/dist/chunk-2KAQYLVN.js"],"names":[],"mappings":"AAAA","file":"/Volumes/Projects/wexts/packages/dist/chunk-2KAQYLVN.js"}
@@ -1,6 +1,6 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2;
2
2
 
3
- var _chunk3OM7CHCAjs = require('./chunk-3OM7CHCA.js');
3
+ var _chunkWCKSKU3Cjs = require('./chunk-WCKSKU3C.js');
4
4
 
5
5
 
6
6
 
@@ -30,7 +30,7 @@ var ProcessRunner = (_class = class {constructor() { _class.prototype.__init.cal
30
30
  blue: pc.blue
31
31
  }}
32
32
  async run(configs) {
33
- _chunk3OM7CHCAjs.logger.info("\u{1F680} Starting development servers...\n");
33
+ _chunkWCKSKU3Cjs.logger.info("\u{1F680} Starting development servers...\n");
34
34
  for (const config of configs) {
35
35
  this.startProcess(config);
36
36
  }
@@ -41,7 +41,7 @@ var ProcessRunner = (_class = class {constructor() { _class.prototype.__init.cal
41
41
  const { name, command, args, cwd, color, env } = config;
42
42
  const colorFn = this.colors[color];
43
43
  const prefix = colorFn(`[${name}]`);
44
- _chunk3OM7CHCAjs.logger.info(`${prefix} Starting...`);
44
+ _chunkWCKSKU3Cjs.logger.info(`${prefix} Starting...`);
45
45
  const proc = _child_process.spawn.call(void 0, command, args, {
46
46
  cwd,
47
47
  stdio: "pipe",
@@ -66,18 +66,18 @@ var ProcessRunner = (_class = class {constructor() { _class.prototype.__init.cal
66
66
  })]);
67
67
  proc.on("exit", (code) => {
68
68
  if (code !== 0 && code !== null) {
69
- _chunk3OM7CHCAjs.logger.error(`${prefix} Exited with code ${code}`);
69
+ _chunkWCKSKU3Cjs.logger.error(`${prefix} Exited with code ${code}`);
70
70
  }
71
71
  this.processes.delete(name);
72
72
  });
73
73
  proc.on("error", (error) => {
74
- _chunk3OM7CHCAjs.logger.error(`${prefix} Error:`, error.message);
74
+ _chunkWCKSKU3Cjs.logger.error(`${prefix} Error:`, error.message);
75
75
  });
76
76
  }
77
77
  stopAll() {
78
- _chunk3OM7CHCAjs.logger.info("\n\u{1F6D1} Stopping all processes...");
78
+ _chunkWCKSKU3Cjs.logger.info("\n\u{1F6D1} Stopping all processes...");
79
79
  for (const [name, proc] of this.processes.entries()) {
80
- _chunk3OM7CHCAjs.logger.info(`Stopping ${name}...`);
80
+ _chunkWCKSKU3Cjs.logger.info(`Stopping ${name}...`);
81
81
  proc.kill("SIGTERM");
82
82
  }
83
83
  setTimeout(() => {
@@ -89,6 +89,71 @@ var ProcessRunner = (_class = class {constructor() { _class.prototype.__init.cal
89
89
  }
90
90
  }, _class);
91
91
 
92
+ // src/dev-server/dev-server.ts
93
+ var _path = require('path'); var path = _interopRequireWildcard(_path);
94
+ var _fs = require('fs'); var fs = _interopRequireWildcard(_fs);
95
+ var FusionDevServer = class {
96
+ static {
97
+ _chunkXE4OXN2Wjs.__name.call(void 0, this, "FusionDevServer");
98
+ }
99
+
100
+ constructor() {
101
+ this.processRunner = new ProcessRunner();
102
+ }
103
+ async start(config) {
104
+ const { apiPath, webPath, webPort = 3e3, apiPort = 5050, useProxy = false } = config;
105
+ if (useProxy) {
106
+ throw new Error("The legacy dev proxy is disabled because it conflicts with the Next.js port. Use the production runtime for single-port serving.");
107
+ }
108
+ if (!fs.existsSync(apiPath)) {
109
+ throw new Error(`API path not found: ${apiPath}`);
110
+ }
111
+ if (!fs.existsSync(webPath)) {
112
+ throw new Error(`Web path not found: ${webPath}`);
113
+ }
114
+ const processes = [];
115
+ processes.push({
116
+ name: "API",
117
+ command: "npm",
118
+ args: [
119
+ "run",
120
+ "start:dev"
121
+ ],
122
+ cwd: path.resolve(apiPath),
123
+ color: "cyan",
124
+ env: {
125
+ PORT: apiPort.toString()
126
+ }
127
+ });
128
+ processes.push({
129
+ name: "Web",
130
+ command: "npm",
131
+ args: [
132
+ "run",
133
+ "dev",
134
+ "--",
135
+ "-p",
136
+ webPort.toString()
137
+ ],
138
+ cwd: path.resolve(webPath),
139
+ color: "green",
140
+ env: {
141
+ NEXT_PUBLIC_API_URL: `http://localhost:${apiPort}`
142
+ }
143
+ });
144
+ await this.processRunner.run(processes);
145
+ _chunkWCKSKU3Cjs.logger.info("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557");
146
+ _chunkWCKSKU3Cjs.logger.info("\u2551 Fusion Development Server Ready \u2551");
147
+ _chunkWCKSKU3Cjs.logger.info("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n");
148
+ _chunkWCKSKU3Cjs.logger.info(`\u{1F310} Web: http://localhost:${webPort}`);
149
+ _chunkWCKSKU3Cjs.logger.info(`\u{1F50C} API: http://localhost:${apiPort}`);
150
+ _chunkWCKSKU3Cjs.logger.info("\n");
151
+ }
152
+ stop() {
153
+ this.processRunner.stopAll();
154
+ }
155
+ };
156
+
92
157
  // src/dev-server/proxy.ts
93
158
  var _http = require('http'); var _http2 = _interopRequireDefault(_http);
94
159
  var _httpproxy = require('http-proxy'); var _httpproxy2 = _interopRequireDefault(_httpproxy);
@@ -107,7 +172,7 @@ var ProxyServer = (_class2 = class {constructor() { _class2.prototype.__init3.ca
107
172
  ws: true
108
173
  });
109
174
  this.proxy.on("error", (err, req, res) => {
110
- _chunk3OM7CHCAjs.logger.error("Proxy error:", err.message);
175
+ _chunkWCKSKU3Cjs.logger.error("Proxy error:", err.message);
111
176
  if (res && "headersSent" in res && !res.headersSent) {
112
177
  res.writeHead(502, {
113
178
  "Content-Type": "text/plain"
@@ -119,7 +184,7 @@ var ProxyServer = (_class2 = class {constructor() { _class2.prototype.__init3.ca
119
184
  if (_optionalChain([req, 'access', _7 => _7.url, 'optionalAccess', _8 => _8.startsWith, 'call', _9 => _9(apiPrefix)])) {
120
185
  const newUrl = req.url.substring(apiPrefix.length) || "/";
121
186
  req.url = newUrl;
122
- _chunk3OM7CHCAjs.logger.info(pc2.gray(`\u2192 ${req.method} ${apiPrefix}${newUrl}`));
187
+ _chunkWCKSKU3Cjs.logger.info(pc2.gray(`\u2192 ${req.method} ${apiPrefix}${newUrl}`));
123
188
  this.proxy.web(req, res);
124
189
  } else {
125
190
  res.writeHead(404);
@@ -135,8 +200,8 @@ var ProxyServer = (_class2 = class {constructor() { _class2.prototype.__init3.ca
135
200
  });
136
201
  return new Promise((resolve2) => {
137
202
  this.server.listen(port, () => {
138
- _chunk3OM7CHCAjs.logger.success(`\u2705 Proxy server running on port ${port}`);
139
- _chunk3OM7CHCAjs.logger.info(` Forwarding ${pc2.cyan(apiPrefix + "/*")} \u2192 ${pc2.cyan(apiTarget)}
203
+ _chunkWCKSKU3Cjs.logger.success(`\u2705 Proxy server running on port ${port}`);
204
+ _chunkWCKSKU3Cjs.logger.info(` Forwarding ${pc2.cyan(apiPrefix + "/*")} \u2192 ${pc2.cyan(apiTarget)}
140
205
  `);
141
206
  resolve2();
142
207
  });
@@ -154,89 +219,10 @@ var ProxyServer = (_class2 = class {constructor() { _class2.prototype.__init3.ca
154
219
  }
155
220
  }, _class2);
156
221
 
157
- // src/dev-server/dev-server.ts
158
- var _path = require('path'); var path = _interopRequireWildcard(_path);
159
- var _fs = require('fs'); var fs = _interopRequireWildcard(_fs);
160
- var FusionDevServer = (_class3 = class {
161
- static {
162
- _chunkXE4OXN2Wjs.__name.call(void 0, this, "FusionDevServer");
163
- }
164
-
165
- __init5() {this.proxyServer = null}
166
- constructor() {;_class3.prototype.__init5.call(this);
167
- this.processRunner = new ProcessRunner();
168
- }
169
- async start(config) {
170
- const { apiPath, webPath, webPort = 3e3, apiPort = 5050, useProxy = true } = config;
171
- if (!fs.existsSync(apiPath)) {
172
- throw new Error(`API path not found: ${apiPath}`);
173
- }
174
- if (!fs.existsSync(webPath)) {
175
- throw new Error(`Web path not found: ${webPath}`);
176
- }
177
- const processes = [];
178
- processes.push({
179
- name: "API",
180
- command: "npm",
181
- args: [
182
- "run",
183
- "start:dev"
184
- ],
185
- cwd: path.resolve(apiPath),
186
- color: "cyan",
187
- env: {
188
- PORT: apiPort.toString()
189
- }
190
- });
191
- processes.push({
192
- name: "Web",
193
- command: "npm",
194
- args: [
195
- "run",
196
- "dev",
197
- "--",
198
- "-p",
199
- webPort.toString()
200
- ],
201
- cwd: path.resolve(webPath),
202
- color: "green",
203
- env: {
204
- NEXT_PUBLIC_API_URL: useProxy ? `http://localhost:${webPort}/api` : `http://localhost:${apiPort}`
205
- }
206
- });
207
- if (useProxy) {
208
- this.proxyServer = new ProxyServer();
209
- setTimeout(async () => {
210
- await this.proxyServer.start({
211
- port: webPort,
212
- apiTarget: `http://localhost:${apiPort}`,
213
- apiPrefix: "/api"
214
- });
215
- }, 3e3);
216
- }
217
- await this.processRunner.run(processes);
218
- _chunk3OM7CHCAjs.logger.info("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557");
219
- _chunk3OM7CHCAjs.logger.info("\u2551 Fusion Development Server Ready \u2551");
220
- _chunk3OM7CHCAjs.logger.info("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n");
221
- _chunk3OM7CHCAjs.logger.info(`\u{1F310} Web: http://localhost:${webPort}`);
222
- _chunk3OM7CHCAjs.logger.info(`\u{1F50C} API: http://localhost:${apiPort}`);
223
- if (useProxy) {
224
- _chunk3OM7CHCAjs.logger.info(`\u{1F504} Proxy: Enabled (${webPort}/api \u2192 ${apiPort})`);
225
- }
226
- _chunk3OM7CHCAjs.logger.info("\n");
227
- }
228
- stop() {
229
- this.processRunner.stopAll();
230
- if (this.proxyServer) {
231
- this.proxyServer.stop();
232
- }
233
- }
234
- }, _class3);
235
-
236
222
 
237
223
 
238
224
 
239
225
 
240
226
 
241
- exports.ProcessRunner = ProcessRunner; exports.ProxyServer = ProxyServer; exports.FusionDevServer = FusionDevServer; exports.dev_server_exports = dev_server_exports;
242
- //# sourceMappingURL=chunk-O42L6HOX.js.map
227
+ exports.ProcessRunner = ProcessRunner; exports.FusionDevServer = FusionDevServer; exports.ProxyServer = ProxyServer; exports.dev_server_exports = dev_server_exports;
228
+ //# sourceMappingURL=chunk-2LJVUMXW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Volumes/Projects/wexts/packages/dist/chunk-2LJVUMXW.js","../src/dev-server/index.ts","../src/dev-server/process-runner.ts","../src/dev-server/dev-server.ts","../src/dev-server/proxy.ts"],"names":["ProcessRunner","processes","Map","colors","cyan","green","yellow","magenta","blue","run","configs","logger","info","config","startProcess","process","on","stopAll","name","command","args","cwd","color","env","colorFn","prefix","spawn","lines","forEach","log","error","code","exit","path","fs","FusionDevServer","processRunner","apiPath","useProxy","Error","existsSync","push","resolve","apiPort","toString","NEXT_PUBLIC_API_URL","httpProxy","pc","ProxyServer","port","apiTarget","changeOrigin","writeHead","server","url","newUrl","proxy","Promise","success","close"],"mappings":"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","file":"/Volumes/Projects/wexts/packages/dist/chunk-2LJVUMXW.js","sourcesContent":[null,"export * from './dev-server';\nexport * from './process-runner';\nexport * from './proxy';\n","import { spawn, ChildProcess } from 'child_process';\nimport { logger } from '../core/logger';\nimport * as pc from 'picocolors';\n\nexport interface ProcessConfig {\n name: string;\n command: string;\n args: string[];\n cwd: string;\n color: 'cyan' | 'green' | 'yellow' | 'magenta' | 'blue';\n env?: Record<string, string>;\n}\n\n/**\n * Run multiple processes concurrently with colored output\n */\nexport class ProcessRunner {\n private processes: Map<string, ChildProcess> = new Map();\n private colors = {\n cyan: pc.cyan,\n green: pc.green,\n yellow: pc.yellow,\n magenta: pc.magenta,\n blue: pc.blue,\n };\n\n async run(configs: ProcessConfig[]): Promise<void> {\n logger.info('🚀 Starting development servers...\\n');\n\n for (const config of configs) {\n this.startProcess(config);\n }\n\n // Handle graceful shutdown\n process.on('SIGINT', () => this.stopAll());\n process.on('SIGTERM', () => this.stopAll());\n }\n\n private startProcess(config: ProcessConfig): void {\n const { name, command, args, cwd, color, env } = config;\n\n const colorFn = this.colors[color];\n const prefix = colorFn(`[${name}]`);\n\n logger.info(`${prefix} Starting...`);\n\n const proc = spawn(command, args, {\n cwd,\n stdio: 'pipe',\n shell: true,\n env: { ...process.env, ...env },\n });\n\n this.processes.set(name, proc);\n\n // Handle stdout\n proc.stdout?.on('data', (data) => {\n const lines = data.toString().split('\\n').filter((l: string) => l.trim());\n lines.forEach((line: string) => {\n console.log(`${prefix} ${line}`);\n });\n });\n\n // Handle stderr\n proc.stderr?.on('data', (data) => {\n const lines = data.toString().split('\\n').filter((l: string) => l.trim());\n lines.forEach((line: string) => {\n console.error(`${prefix} ${pc.red(line)}`);\n });\n });\n\n // Handle exit\n proc.on('exit', (code) => {\n if (code !== 0 && code !== null) {\n logger.error(`${prefix} Exited with code ${code}`);\n }\n this.processes.delete(name);\n });\n\n // Handle errors\n proc.on('error', (error) => {\n logger.error(`${prefix} Error:`, error.message);\n });\n }\n\n stopAll(): void {\n logger.info('\\n🛑 Stopping all processes...');\n\n for (const [name, proc] of this.processes.entries()) {\n logger.info(`Stopping ${name}...`);\n proc.kill('SIGTERM');\n }\n\n setTimeout(() => {\n process.exit(0);\n }, 1000);\n }\n\n isRunning(name: string): boolean {\n return this.processes.has(name);\n }\n}\n","import { ProcessRunner, ProcessConfig } from './process-runner';\nimport { logger } from '../core/logger';\nimport * as path from 'path';\nimport * as fs from 'fs';\n\nexport interface DevServerConfig {\n apiPath: string;\n webPath: string;\n webPort?: number;\n apiPort?: number;\n useProxy?: boolean;\n}\n\n/**\n * Unified development server for Fusion projects\n */\nexport class FusionDevServer {\n private processRunner: ProcessRunner;\n\n constructor() {\n this.processRunner = new ProcessRunner();\n }\n\n async start(config: DevServerConfig): Promise<void> {\n const {\n apiPath,\n webPath,\n webPort = 3000,\n apiPort = 5050,\n useProxy = false,\n } = config;\n\n if (useProxy) {\n throw new Error('The legacy dev proxy is disabled because it conflicts with the Next.js port. Use the production runtime for single-port serving.');\n }\n\n // Validate paths\n if (!fs.existsSync(apiPath)) {\n throw new Error(`API path not found: ${apiPath}`);\n }\n if (!fs.existsSync(webPath)) {\n throw new Error(`Web path not found: ${webPath}`);\n }\n\n const processes: ProcessConfig[] = [];\n\n // Add API server\n processes.push({\n name: 'API',\n command: 'npm',\n args: ['run', 'start:dev'],\n cwd: path.resolve(apiPath),\n color: 'cyan',\n env: {\n PORT: apiPort.toString(),\n },\n });\n\n // Add Web server\n processes.push({\n name: 'Web',\n command: 'npm',\n args: ['run', 'dev', '--', '-p', webPort.toString()],\n cwd: path.resolve(webPath),\n color: 'green',\n env: {\n NEXT_PUBLIC_API_URL: `http://localhost:${apiPort}`,\n },\n });\n\n // Start processes\n await this.processRunner.run(processes);\n\n // Log info\n logger.info('╔═══════════════════════════════════════╗');\n logger.info('║ Fusion Development Server Ready ║');\n logger.info('╚═══════════════════════════════════════╝\\n');\n logger.info(`🌐 Web: http://localhost:${webPort}`);\n logger.info(`🔌 API: http://localhost:${apiPort}`);\n logger.info('\\n');\n }\n\n stop(): void {\n this.processRunner.stopAll();\n }\n}\n","import http from 'http';\nimport httpProxy from 'http-proxy';\nimport { logger } from '../core/logger';\nimport * as pc from 'picocolors';\n\nexport interface ProxyConfig {\n port: number;\n apiTarget: string;\n apiPrefix: string;\n}\n\n/**\n * Proxy server to forward API requests from Next.js to NestJS\n */\nexport class ProxyServer {\n private server: http.Server | null = null;\n private proxy: httpProxy | null = null;\n\n async start(config: ProxyConfig): Promise<void> {\n const { port, apiTarget, apiPrefix } = config;\n\n this.proxy = httpProxy.createProxyServer({\n target: apiTarget,\n changeOrigin: true,\n ws: true, // WebSocket support\n });\n\n // Handle proxy errors\n this.proxy.on('error', (err, req, res) => {\n logger.error('Proxy error:', err.message);\n if (res && 'headersSent' in res && !(res as any).headersSent) {\n (res as http.ServerResponse).writeHead(502, { 'Content-Type': 'text/plain' });\n (res as http.ServerResponse).end('Bad Gateway - API server unavailable');\n }\n });\n\n this.server = http.createServer((req, res) => {\n // Check if request is for API\n if (req.url?.startsWith(apiPrefix)) {\n // Remove prefix before forwarding\n const newUrl = req.url.substring(apiPrefix.length) || '/';\n req.url = newUrl;\n\n logger.info(pc.gray(`→ ${req.method} ${apiPrefix}${newUrl}`));\n this.proxy!.web(req, res);\n } else {\n // Not an API request - should not happen\n res.writeHead(404);\n res.end('Not Found');\n }\n });\n\n // Handle WebSocket upgrade\n this.server.on('upgrade', (req, socket, head) => {\n if (req.url?.startsWith(apiPrefix)) {\n const newUrl = req.url.substring(apiPrefix.length) || '/';\n req.url = newUrl;\n this.proxy!.ws(req, socket, head);\n }\n });\n\n return new Promise((resolve) => {\n this.server!.listen(port, () => {\n logger.success(`✅ Proxy server running on port ${port}`);\n logger.info(` Forwarding ${pc.cyan(apiPrefix + '/*')} → ${pc.cyan(apiTarget)}\\n`);\n resolve();\n });\n });\n }\n\n stop(): void {\n if (this.server) {\n this.server.close();\n this.server = null;\n }\n if (this.proxy) {\n this.proxy.close();\n this.proxy = null;\n }\n }\n}\n"]}