wexts 2.0.9 → 3.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 (73) hide show
  1. package/README.md +241 -235
  2. package/dist/chunk-2KAQYLVN.js +1 -0
  3. package/dist/chunk-2KAQYLVN.js.map +1 -0
  4. package/dist/chunk-3OM7CHCA.js +65 -0
  5. package/dist/chunk-3OM7CHCA.js.map +1 -0
  6. package/dist/chunk-667BQCEM.js +375 -0
  7. package/dist/chunk-667BQCEM.js.map +1 -0
  8. package/dist/chunk-FCEZDH42.mjs +20 -0
  9. package/dist/chunk-FCEZDH42.mjs.map +1 -0
  10. package/dist/chunk-KXYLEUSW.mjs +242 -0
  11. package/dist/chunk-KXYLEUSW.mjs.map +1 -0
  12. package/dist/chunk-O42L6HOX.js +242 -0
  13. package/dist/chunk-O42L6HOX.js.map +1 -0
  14. package/dist/chunk-ONXNE2A6.mjs +375 -0
  15. package/dist/chunk-ONXNE2A6.mjs.map +1 -0
  16. package/dist/chunk-STTOPUZ2.mjs +88 -0
  17. package/dist/chunk-STTOPUZ2.mjs.map +1 -0
  18. package/dist/chunk-VMT3LALB.mjs +51 -0
  19. package/dist/chunk-VMT3LALB.mjs.map +1 -0
  20. package/dist/chunk-VNNVLQLJ.mjs +65 -0
  21. package/dist/chunk-VNNVLQLJ.mjs.map +1 -0
  22. package/dist/chunk-WF65EDRZ.js +88 -0
  23. package/dist/chunk-WF65EDRZ.js.map +1 -0
  24. package/dist/chunk-XE4OXN2W.js +12 -0
  25. package/dist/chunk-XE4OXN2W.js.map +1 -0
  26. package/dist/chunk-XVKTIYHY.js +51 -0
  27. package/dist/chunk-XVKTIYHY.js.map +1 -0
  28. package/dist/chunk-YSLEF5C5.mjs +1 -0
  29. package/dist/chunk-YSLEF5C5.mjs.map +1 -0
  30. package/dist/cli/index.js +134 -81
  31. package/dist/cli/index.js.map +1 -1
  32. package/dist/cli/index.mjs +93 -41
  33. package/dist/cli/index.mjs.map +1 -1
  34. package/dist/client/index.js +3 -3
  35. package/dist/client/index.mjs +2 -2
  36. package/dist/codegen/index.js +4 -4
  37. package/dist/codegen/index.mjs +3 -3
  38. package/dist/dev-server/index.js +4 -4
  39. package/dist/dev-server/index.mjs +3 -3
  40. package/dist/index.js +93 -51
  41. package/dist/index.js.map +1 -1
  42. package/dist/index.mjs +75 -33
  43. package/dist/index.mjs.map +1 -1
  44. package/dist/nest/index.js +3 -3
  45. package/dist/nest/index.mjs +2 -2
  46. package/dist/next/index.js +22 -9
  47. package/dist/next/index.js.map +1 -1
  48. package/dist/next/index.mjs +23 -9
  49. package/dist/next/index.mjs.map +1 -1
  50. package/dist/types/index.js +1 -1
  51. package/dist/types/index.mjs +2 -2
  52. package/package.json +126 -112
  53. package/templates/.dockerignore +43 -0
  54. package/templates/.env.example +17 -0
  55. package/templates/Dockerfile +60 -0
  56. package/templates/Procfile +1 -0
  57. package/templates/README.md +58 -0
  58. package/templates/api-sdk.ts +115 -0
  59. package/templates/docker-compose.yml +34 -0
  60. package/templates/nestjs-api/src/auth/auth.controller.ts +4 -7
  61. package/templates/nestjs-api/src/auth/auth.module.ts +4 -1
  62. package/templates/nestjs-api/src/auth/auth.service.ts +8 -13
  63. package/templates/nestjs-api/src/todos/todos.controller.ts +0 -7
  64. package/templates/nestjs-api/src/todos/todos.module.ts +3 -1
  65. package/templates/nestjs-api/src/users/users.controller.ts +0 -3
  66. package/templates/nestjs-api/src/users/users.module.ts +3 -1
  67. package/templates/nextjs-web/app/actions/auth.ts +49 -20
  68. package/templates/nextjs-web/lib/api.ts +115 -0
  69. package/templates/nextjs-web/next-env.d.ts +1 -1
  70. package/templates/nixpacks.toml +11 -0
  71. package/templates/root-package.json +32 -0
  72. package/templates/server.ts +66 -0
  73. package/templates/tsconfig.json +31 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/next/provider.tsx","../../src/client/fetcher.ts","../../src/next/useAuth.ts"],"sourcesContent":["'use client';\r\n\r\nimport React, { createContext, useContext, ReactNode } from 'react';\r\nimport { FusionFetcher } from '../client/fetcher';\r\n\r\ninterface FusionContextType {\r\n client: FusionFetcher;\r\n}\r\n\r\nconst FusionContext = createContext<FusionContextType | null>(null);\r\n\r\nexport interface FusionProviderProps {\r\n children: ReactNode;\r\n baseUrl?: string;\r\n}\r\n\r\n/**\r\n * FusionProvider - Provides API client to React components\r\n * Usage:\r\n * ```tsx\r\n * <FusionProvider baseUrl=\"/api\">\r\n * <App />\r\n * </FusionProvider>\r\n * ```\r\n */\r\nexport function FusionProvider({ children, baseUrl = '/api' }: FusionProviderProps) {\r\n const client = React.useMemo(() => new FusionFetcher(baseUrl), [baseUrl]);\r\n\r\n return (\r\n <FusionContext.Provider value={{ client }}>\r\n {children}\r\n </FusionContext.Provider>\r\n );\r\n}\r\n\r\n/**\r\n * useFusion hook - Access API client in components\r\n * Usage:\r\n * ```tsx\r\n * const { client } = useFusion();\r\n * const data = await client.get('/users');\r\n * ```\r\n */\r\nexport function useFusion(): FusionContextType {\r\n const context = useContext(FusionContext);\r\n if (!context) {\r\n throw new Error('useFusion must be used within FusionProvider');\r\n }\r\n return context;\r\n}\r\n","// packages/api-client/src/fetcher.ts\r\n\r\nexport class FusionFetcher {\r\n private baseUrl: string;\r\n\r\n constructor(baseUrl: string = '/api') {\r\n this.baseUrl = baseUrl;\r\n }\r\n\r\n private async request<T>(method: string, path: string, body?: any): Promise<T> {\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n };\r\n\r\n // Automatically attach Fusion Token if present\r\n if (typeof window !== 'undefined') {\r\n const token = localStorage.getItem('fusion_token');\r\n if (token) headers['Authorization'] = `Bearer ${token}`;\r\n }\r\n\r\n const response = await fetch(`${this.baseUrl}${path}`, {\r\n method,\r\n headers,\r\n body: body ? JSON.stringify(body) : undefined,\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`Fusion API Error: ${response.statusText}`);\r\n }\r\n\r\n return response.json();\r\n }\r\n\r\n get<T>(path: string) { return this.request<T>('GET', path); }\r\n post<T>(path: string, body: any) { return this.request<T>('POST', path, body); }\r\n put<T>(path: string, body: any) { return this.request<T>('PUT', path, body); }\r\n delete<T>(path: string) { return this.request<T>('DELETE', path); }\r\n}\r\n\r\nexport const apiFetcher = new FusionFetcher();\r\n","'use client';\r\n\r\nimport { useState, useEffect } from 'react';\r\nimport { useFusion } from './provider';\r\n\r\nexport interface AuthUser {\r\n id: string;\r\n email: string;\r\n name?: string;\r\n}\r\n\r\nexport interface UseAuthReturn {\r\n user: AuthUser | null;\r\n loading: boolean;\r\n login: (email: string, password: string) => Promise<void>;\r\n logout: () => Promise<void>;\r\n isAuthenticated: boolean;\r\n}\r\n\r\n/**\r\n * useAuth hook - Authentication state management\r\n * Usage:\r\n * ```tsx\r\n * const { user, login, logout, isAuthenticated } = useAuth();\r\n * ```\r\n */\r\nexport function useAuth(): UseAuthReturn {\r\n const { client } = useFusion();\r\n const [user, setUser] = useState<AuthUser | null>(null);\r\n const [loading, setLoading] = useState(true);\r\n\r\n useEffect(() => {\r\n // Check for existing session\r\n const token = localStorage.getItem('fusion_token');\r\n if (token) {\r\n // Validate token and load user\r\n loadUser();\r\n } else {\r\n setLoading(false);\r\n }\r\n }, []);\r\n\r\n const loadUser = async () => {\r\n try {\r\n const userData = await client.get<AuthUser>('/auth/me');\r\n setUser(userData);\r\n } catch (error) {\r\n localStorage.removeItem('fusion_token');\r\n } finally {\r\n setLoading(false);\r\n }\r\n };\r\n\r\n const login = async (email: string, password: string) => {\r\n const response = await client.post<{ token: string; user: AuthUser }>('/auth/login', {\r\n email,\r\n password,\r\n });\r\n localStorage.setItem('fusion_token', response.token);\r\n setUser(response.user);\r\n };\r\n\r\n const logout = async () => {\r\n localStorage.removeItem('fusion_token');\r\n setUser(null);\r\n };\r\n\r\n return {\r\n user,\r\n loading,\r\n login,\r\n logout,\r\n isAuthenticated: !!user,\r\n };\r\n}\r\n"],"mappings":";;;AAEA,OAAO,SAAS,eAAe,kBAA6B;;;ACArD,IAAM,gBAAN,MAAoB;AAAA,EACf;AAAA,EAER,YAAY,UAAkB,QAAQ;AAClC,SAAK,UAAU;AAAA,EACnB;AAAA,EAEA,MAAc,QAAW,QAAgB,MAAc,MAAwB;AAC3E,UAAM,UAAkC;AAAA,MACpC,gBAAgB;AAAA,IACpB;AAGA,QAAI,OAAO,WAAW,aAAa;AAC/B,YAAM,QAAQ,aAAa,QAAQ,cAAc;AACjD,UAAI,MAAO,SAAQ,eAAe,IAAI,UAAU,KAAK;AAAA,IACzD;AAEA,UAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,GAAG,IAAI,IAAI;AAAA,MACnD;AAAA,MACA;AAAA,MACA,MAAM,OAAO,KAAK,UAAU,IAAI,IAAI;AAAA,IACxC,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AACd,YAAM,IAAI,MAAM,qBAAqB,SAAS,UAAU,EAAE;AAAA,IAC9D;AAEA,WAAO,SAAS,KAAK;AAAA,EACzB;AAAA,EAEA,IAAO,MAAc;AAAE,WAAO,KAAK,QAAW,OAAO,IAAI;AAAA,EAAG;AAAA,EAC5D,KAAQ,MAAc,MAAW;AAAE,WAAO,KAAK,QAAW,QAAQ,MAAM,IAAI;AAAA,EAAG;AAAA,EAC/E,IAAO,MAAc,MAAW;AAAE,WAAO,KAAK,QAAW,OAAO,MAAM,IAAI;AAAA,EAAG;AAAA,EAC7E,OAAU,MAAc;AAAE,WAAO,KAAK,QAAW,UAAU,IAAI;AAAA,EAAG;AACtE;AAEO,IAAM,aAAa,IAAI,cAAc;;;AD9B5C,IAAM,gBAAgB,cAAwC,IAAI;AAgB3D,SAAS,eAAe,EAAE,UAAU,UAAU,OAAO,GAAwB;AAChF,QAAM,SAAS,MAAM,QAAQ,MAAM,IAAI,cAAc,OAAO,GAAG,CAAC,OAAO,CAAC;AAExE,SACI,oCAAC,cAAc,UAAd,EAAuB,OAAO,EAAE,OAAO,KACnC,QACL;AAER;AAUO,SAAS,YAA+B;AAC3C,QAAM,UAAU,WAAW,aAAa;AACxC,MAAI,CAAC,SAAS;AACV,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAClE;AACA,SAAO;AACX;;;AE/CA,SAAS,UAAU,iBAAiB;AAwB7B,SAAS,UAAyB;AACrC,QAAM,EAAE,OAAO,IAAI,UAAU;AAC7B,QAAM,CAAC,MAAM,OAAO,IAAI,SAA0B,IAAI;AACtD,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,IAAI;AAE3C,YAAU,MAAM;AAEZ,UAAM,QAAQ,aAAa,QAAQ,cAAc;AACjD,QAAI,OAAO;AAEP,eAAS;AAAA,IACb,OAAO;AACH,iBAAW,KAAK;AAAA,IACpB;AAAA,EACJ,GAAG,CAAC,CAAC;AAEL,QAAM,WAAW,YAAY;AACzB,QAAI;AACA,YAAM,WAAW,MAAM,OAAO,IAAc,UAAU;AACtD,cAAQ,QAAQ;AAAA,IACpB,SAAS,OAAO;AACZ,mBAAa,WAAW,cAAc;AAAA,IAC1C,UAAE;AACE,iBAAW,KAAK;AAAA,IACpB;AAAA,EACJ;AAEA,QAAM,QAAQ,OAAO,OAAe,aAAqB;AACrD,UAAM,WAAW,MAAM,OAAO,KAAwC,eAAe;AAAA,MACjF;AAAA,MACA;AAAA,IACJ,CAAC;AACD,iBAAa,QAAQ,gBAAgB,SAAS,KAAK;AACnD,YAAQ,SAAS,IAAI;AAAA,EACzB;AAEA,QAAM,SAAS,YAAY;AACvB,iBAAa,WAAW,cAAc;AACtC,YAAQ,IAAI;AAAA,EAChB;AAEA,SAAO;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,iBAAiB,CAAC,CAAC;AAAA,EACvB;AACJ;","names":[]}
1
+ {"version":3,"sources":["../../src/next/provider.tsx","../../src/client/fetcher.ts","../../src/next/useAuth.ts"],"sourcesContent":["'use client';\r\n\r\nimport React, { createContext, useContext, ReactNode } from 'react';\r\nimport { FusionFetcher } from '../client/fetcher';\r\n\r\ninterface FusionContextType {\r\n client: FusionFetcher;\r\n}\r\n\r\nconst FusionContext = createContext<FusionContextType | null>(null);\r\n\r\nexport interface FusionProviderProps {\r\n children: ReactNode;\r\n baseUrl?: string;\r\n}\r\n\r\n/**\r\n * FusionProvider - Provides API client to React components\r\n * Usage:\r\n * ```tsx\r\n * <FusionProvider baseUrl=\"/api\">\r\n * <App />\r\n * </FusionProvider>\r\n * ```\r\n */\r\nexport function FusionProvider({ children, baseUrl = '/api' }: FusionProviderProps) {\r\n const client = React.useMemo(() => new FusionFetcher(baseUrl), [baseUrl]);\r\n\r\n return (\r\n <FusionContext.Provider value={{ client }}>\r\n {children}\r\n </FusionContext.Provider>\r\n );\r\n}\r\n\r\n/**\r\n * useFusion hook - Access API client in components\r\n * Usage:\r\n * ```tsx\r\n * const { client } = useFusion();\r\n * const data = await client.get('/users');\r\n * ```\r\n */\r\nexport function useFusion(): FusionContextType {\r\n const context = useContext(FusionContext);\r\n if (!context) {\r\n throw new Error('useFusion must be used within FusionProvider');\r\n }\r\n return context;\r\n}\r\n","// packages/api-client/src/fetcher.ts\r\n\r\nexport class FusionFetcher {\r\n private baseUrl: string;\r\n\r\n constructor(baseUrl: string = '/api') {\r\n this.baseUrl = baseUrl;\r\n }\r\n\r\n private async request<T>(method: string, path: string, body?: any): Promise<T> {\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/json',\r\n };\r\n\r\n // Automatically attach Fusion Token if present\r\n if (typeof window !== 'undefined') {\r\n const token = localStorage.getItem('fusion_token');\r\n if (token) headers['Authorization'] = `Bearer ${token}`;\r\n }\r\n\r\n const response = await fetch(`${this.baseUrl}${path}`, {\r\n method,\r\n headers,\r\n body: body ? JSON.stringify(body) : undefined,\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`Fusion API Error: ${response.statusText}`);\r\n }\r\n\r\n return response.json();\r\n }\r\n\r\n get<T>(path: string) { return this.request<T>('GET', path); }\r\n post<T>(path: string, body: any) { return this.request<T>('POST', path, body); }\r\n put<T>(path: string, body: any) { return this.request<T>('PUT', path, body); }\r\n delete<T>(path: string) { return this.request<T>('DELETE', path); }\r\n}\r\n\r\nexport const apiFetcher = new FusionFetcher();\r\n","'use client';\r\n\r\nimport { useState, useEffect } from 'react';\r\nimport { useFusion } from './provider';\r\n\r\nexport interface AuthUser {\r\n id: string;\r\n email: string;\r\n name?: string;\r\n}\r\n\r\nexport interface UseAuthReturn {\r\n user: AuthUser | null;\r\n loading: boolean;\r\n login: (email: string, password: string) => Promise<void>;\r\n logout: () => Promise<void>;\r\n isAuthenticated: boolean;\r\n}\r\n\r\n/**\r\n * useAuth hook - Authentication state management\r\n * Usage:\r\n * ```tsx\r\n * const { user, login, logout, isAuthenticated } = useAuth();\r\n * ```\r\n */\r\nexport function useAuth(): UseAuthReturn {\r\n const { client } = useFusion();\r\n const [user, setUser] = useState<AuthUser | null>(null);\r\n const [loading, setLoading] = useState(true);\r\n\r\n useEffect(() => {\r\n // Check for existing session\r\n const token = localStorage.getItem('fusion_token');\r\n if (token) {\r\n // Validate token and load user\r\n loadUser();\r\n } else {\r\n setLoading(false);\r\n }\r\n }, []);\r\n\r\n const loadUser = async () => {\r\n try {\r\n const userData = await client.get<AuthUser>('/auth/me');\r\n setUser(userData);\r\n } catch (error) {\r\n localStorage.removeItem('fusion_token');\r\n } finally {\r\n setLoading(false);\r\n }\r\n };\r\n\r\n const login = async (email: string, password: string) => {\r\n const response = await client.post<{ token: string; user: AuthUser }>('/auth/login', {\r\n email,\r\n password,\r\n });\r\n localStorage.setItem('fusion_token', response.token);\r\n setUser(response.user);\r\n };\r\n\r\n const logout = async () => {\r\n localStorage.removeItem('fusion_token');\r\n setUser(null);\r\n };\r\n\r\n return {\r\n user,\r\n loading,\r\n login,\r\n logout,\r\n isAuthenticated: !!user,\r\n };\r\n}\r\n"],"mappings":";;;;;AAEA,OAAOA,SAASC,eAAeC,kBAA6B;;;ACArD,IAAMC,gBAAN,MAAMA;EAFb,OAEaA;;;EACDC;EAER,YAAYA,UAAkB,QAAQ;AAClC,SAAKA,UAAUA;EACnB;EAEA,MAAcC,QAAWC,QAAgBC,MAAcC,MAAwB;AAC3E,UAAMC,UAAkC;MACpC,gBAAgB;IACpB;AAGA,QAAI,OAAOC,WAAW,aAAa;AAC/B,YAAMC,QAAQC,aAAaC,QAAQ,cAAA;AACnC,UAAIF,MAAOF,SAAQ,eAAA,IAAmB,UAAUE,KAAAA;IACpD;AAEA,UAAMG,WAAW,MAAMC,MAAM,GAAG,KAAKX,OAAO,GAAGG,IAAAA,IAAQ;MACnDD;MACAG;MACAD,MAAMA,OAAOQ,KAAKC,UAAUT,IAAAA,IAAQU;IACxC,CAAA;AAEA,QAAI,CAACJ,SAASK,IAAI;AACd,YAAM,IAAIC,MAAM,qBAAqBN,SAASO,UAAU,EAAE;IAC9D;AAEA,WAAOP,SAASQ,KAAI;EACxB;EAEAC,IAAOhB,MAAc;AAAE,WAAO,KAAKF,QAAW,OAAOE,IAAAA;EAAO;EAC5DiB,KAAQjB,MAAcC,MAAW;AAAE,WAAO,KAAKH,QAAW,QAAQE,MAAMC,IAAAA;EAAO;EAC/EiB,IAAOlB,MAAcC,MAAW;AAAE,WAAO,KAAKH,QAAW,OAAOE,MAAMC,IAAAA;EAAO;EAC7EkB,OAAUnB,MAAc;AAAE,WAAO,KAAKF,QAAW,UAAUE,IAAAA;EAAO;AACtE;AAEO,IAAMoB,aAAa,IAAIxB,cAAAA;;;AD9B9B,IAAMyB,gBAAgBC,8BAAwC,IAAA;AAgBvD,SAASC,eAAe,EAAEC,UAAUC,UAAU,OAAM,GAAuB;AAC9E,QAAMC,SAASC,MAAMC,QAAQ,MAAM,IAAIC,cAAcJ,OAAAA,GAAU;IAACA;GAAQ;AAExE,SACI,sBAAA,cAACJ,cAAcS,UAAQ;IAACC,OAAO;MAAEL;IAAO;KACnCF,QAAAA;AAGb;AARgBD;AAkBT,SAASS,YAAAA;AACZ,QAAMC,UAAUC,WAAWb,aAAAA;AAC3B,MAAI,CAACY,SAAS;AACV,UAAM,IAAIE,MAAM,8CAAA;EACpB;AACA,SAAOF;AACX;AANgBD;;;AEzChB,SAASI,UAAUC,iBAAiB;AAwB7B,SAASC,UAAAA;AACZ,QAAM,EAAEC,OAAM,IAAKC,UAAAA;AACnB,QAAM,CAACC,MAAMC,OAAAA,IAAWC,SAA0B,IAAA;AAClD,QAAM,CAACC,SAASC,UAAAA,IAAcF,SAAS,IAAA;AAEvCG,YAAU,MAAA;AAEN,UAAMC,QAAQC,aAAaC,QAAQ,cAAA;AACnC,QAAIF,OAAO;AAEPG,eAAAA;IACJ,OAAO;AACHL,iBAAW,KAAA;IACf;EACJ,GAAG,CAAA,CAAE;AAEL,QAAMK,WAAW,mCAAA;AACb,QAAI;AACA,YAAMC,WAAW,MAAMZ,OAAOa,IAAc,UAAA;AAC5CV,cAAQS,QAAAA;IACZ,SAASE,OAAO;AACZL,mBAAaM,WAAW,cAAA;IAC5B,UAAA;AACIT,iBAAW,KAAA;IACf;EACJ,GATiB;AAWjB,QAAMU,QAAQ,8BAAOC,OAAeC,aAAAA;AAChC,UAAMC,WAAW,MAAMnB,OAAOoB,KAAwC,eAAe;MACjFH;MACAC;IACJ,CAAA;AACAT,iBAAaY,QAAQ,gBAAgBF,SAASX,KAAK;AACnDL,YAAQgB,SAASjB,IAAI;EACzB,GAPc;AASd,QAAMoB,SAAS,mCAAA;AACXb,iBAAaM,WAAW,cAAA;AACxBZ,YAAQ,IAAA;EACZ,GAHe;AAKf,SAAO;IACHD;IACAG;IACAW;IACAM;IACAC,iBAAiB,CAAC,CAACrB;EACvB;AACJ;AAhDgBH;","names":["React","createContext","useContext","FusionFetcher","baseUrl","request","method","path","body","headers","window","token","localStorage","getItem","response","fetch","JSON","stringify","undefined","ok","Error","statusText","json","get","post","put","delete","apiFetcher","FusionContext","createContext","FusionProvider","children","baseUrl","client","React","useMemo","FusionFetcher","Provider","value","useFusion","context","useContext","Error","useState","useEffect","useAuth","client","useFusion","user","setUser","useState","loading","setLoading","useEffect","token","localStorage","getItem","loadUser","userData","get","error","removeItem","login","email","password","response","post","setItem","logout","isAuthenticated"]}
@@ -1,2 +1,2 @@
1
- "use strict";require('../chunk-K7EIJSYQ.js');
1
+ "use strict";require('../chunk-2KAQYLVN.js');
2
2
  //# sourceMappingURL=index.js.map
@@ -1,3 +1,3 @@
1
- import "../chunk-7NSRDJ5C.mjs";
2
- import "../chunk-CKZ4VSCB.mjs";
1
+ import "../chunk-YSLEF5C5.mjs";
2
+ import "../chunk-FCEZDH42.mjs";
3
3
  //# sourceMappingURL=index.mjs.map
package/package.json CHANGED
@@ -1,113 +1,127 @@
1
- {
2
- "name": "wexts",
3
- "version": "2.0.9",
4
- "description": "Modern full-stack framework combining NestJS 11 and Next.js 16",
5
- "main": "./dist/index.js",
6
- "module": "./dist/index.mjs",
7
- "types": "./dist/index.d.ts",
8
- "bin": {
9
- "wexts": "./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
- "test:watch": "vitest",
47
- "lint": "eslint src",
48
- "typecheck": "tsc --noEmit",
49
- "release": "npm run build && npm publish --access public"
50
- },
51
- "keywords": [
52
- "wexts",
53
- "framework",
54
- "fullstack",
55
- "nestjs",
56
- "nextjs",
57
- "monorepo",
58
- "typescript",
59
- "react"
60
- ],
61
- "author": "wexts Team",
62
- "license": "MIT",
63
- "repository": {
64
- "type": "git",
65
- "url": "https://github.com/ziadmustafa1/wexts.git",
66
- "directory": "packages/fusionjs"
67
- },
68
- "engines": {
69
- "node": ">=20.9.0",
70
- "pnpm": ">=10.0.0"
71
- },
72
- "devDependencies": {
73
- "tsup": "^8.3.5",
74
- "vitest": "^2.1.8",
75
- "@types/node": "^22.10.2",
76
- "@types/react": "^19.0.6",
77
- "@types/http-proxy": "^1.17.15",
78
- "eslint": "^9.17.0"
79
- },
80
- "dependencies": {
81
- "commander": "^12.1.0",
82
- "inquirer": "^12.4.0",
83
- "chokidar": "^4.0.3",
84
- "picocolors": "^1.1.1",
85
- "reflect-metadata": "^0.2.2",
86
- "typescript": "^5.9.3",
87
- "http-proxy": "^1.18.1",
88
- "consola": "^3.2.3"
89
- },
90
- "peerDependencies": {
91
- "@nestjs/common": "^11.0.0",
92
- "@nestjs/core": "^11.0.0",
93
- "react": "^19.0.0",
94
- "next": "^16.0.0"
95
- },
96
- "peerDependenciesMeta": {
97
- "@nestjs/common": {
98
- "optional": true
99
- },
100
- "@nestjs/core": {
101
- "optional": true
102
- },
103
- "react": {
104
- "optional": true
105
- },
106
- "next": {
107
- "optional": true
108
- }
109
- },
110
- "publishConfig": {
111
- "access": "public"
112
- }
1
+ {
2
+ "name": "wexts",
3
+ "version": "3.0.1",
4
+ "description": "Build production-ready full-stack apps with Next.js 16 + NestJS 11 in a unified runtime. Zero URLs. Zero configuration.",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "wexts": "./dist/cli/index.js"
10
+ },
11
+ "files": [
12
+ "dist",
13
+ "templates",
14
+ "README.md",
15
+ "LICENSE"
16
+ ],
17
+ "exports": {
18
+ ".": {
19
+ "types": "./dist/index.d.ts",
20
+ "import": "./dist/index.mjs",
21
+ "require": "./dist/index.js"
22
+ },
23
+ "./client": {
24
+ "types": "./dist/client/index.d.ts",
25
+ "import": "./dist/client/index.mjs",
26
+ "require": "./dist/client/index.js"
27
+ },
28
+ "./types": {
29
+ "types": "./dist/types/index.d.ts",
30
+ "import": "./dist/types/index.mjs",
31
+ "require": "./dist/types/index.js"
32
+ },
33
+ "./nest": {
34
+ "types": "./dist/nest/index.d.ts",
35
+ "import": "./dist/nest/index.mjs",
36
+ "require": "./dist/nest/index.js"
37
+ },
38
+ "./next": {
39
+ "types": "./dist/next/index.d.ts",
40
+ "import": "./dist/next/index.mjs",
41
+ "require": "./dist/next/index.js"
42
+ }
43
+ },
44
+ "scripts": {
45
+ "build": "tsup",
46
+ "dev": "tsup --watch",
47
+ "test": "vitest run",
48
+ "test:watch": "vitest",
49
+ "lint": "eslint src",
50
+ "typecheck": "tsc --noEmit",
51
+ "release": "npm run build && npm publish --access public"
52
+ },
53
+ "keywords": [
54
+ "wexts",
55
+ "framework",
56
+ "fullstack",
57
+ "nestjs",
58
+ "nextjs",
59
+ "monorepo",
60
+ "typescript",
61
+ "react",
62
+ "unified-runtime",
63
+ "zero-config",
64
+ "type-safe",
65
+ "prisma",
66
+ "jwt-auth",
67
+ "docker",
68
+ "next.js",
69
+ "nest.js"
70
+ ],
71
+ "author": "WEXTS Team",
72
+ "license": "MIT",
73
+ "repository": {
74
+ "type": "git",
75
+ "url": "https://github.com/ziadmustafa1/wexts.git"
76
+ },
77
+ "homepage": "https://github.com/ziadmustafa1/wexts#readme",
78
+ "bugs": {
79
+ "url": "https://github.com/ziadmustafa1/wexts/issues"
80
+ },
81
+ "engines": {
82
+ "node": ">=20.9.0",
83
+ "pnpm": ">=10.0.0"
84
+ },
85
+ "devDependencies": {
86
+ "@swc/core": "^1.15.3",
87
+ "@types/http-proxy": "^1.17.15",
88
+ "@types/node": "^22.10.2",
89
+ "@types/react": "^19.0.6",
90
+ "eslint": "^9.17.0",
91
+ "tsup": "^8.3.5",
92
+ "vitest": "^2.1.8"
93
+ },
94
+ "dependencies": {
95
+ "chokidar": "^4.0.3",
96
+ "commander": "^12.1.0",
97
+ "consola": "^3.2.3",
98
+ "http-proxy": "^1.18.1",
99
+ "inquirer": "^12.4.0",
100
+ "picocolors": "^1.1.1",
101
+ "reflect-metadata": "^0.2.2",
102
+ "typescript": "^5.9.3"
103
+ },
104
+ "peerDependencies": {
105
+ "@nestjs/common": "^11.0.0",
106
+ "@nestjs/core": "^11.0.0",
107
+ "next": "^16.0.0",
108
+ "react": "^19.0.0"
109
+ },
110
+ "peerDependenciesMeta": {
111
+ "@nestjs/common": {
112
+ "optional": true
113
+ },
114
+ "@nestjs/core": {
115
+ "optional": true
116
+ },
117
+ "react": {
118
+ "optional": true
119
+ },
120
+ "next": {
121
+ "optional": true
122
+ }
123
+ },
124
+ "publishConfig": {
125
+ "access": "public"
126
+ }
113
127
  }
@@ -0,0 +1,43 @@
1
+ # Environment files
2
+ .env
3
+ .env.local
4
+ .env.*.local
5
+
6
+ # Node modules
7
+ node_modules
8
+ dist
9
+ build
10
+ .next
11
+ .turbo
12
+
13
+ # Database
14
+ *.db
15
+ *.db-journal
16
+
17
+ # Logs
18
+ *.log
19
+ npm-debug.log*
20
+
21
+ # OS
22
+ .DS_Store
23
+ Thumbs.db
24
+
25
+ # IDE
26
+ .vscode
27
+ .idea
28
+ *.swp
29
+
30
+ # Git
31
+ .git
32
+ .gitignore
33
+
34
+ # CI/CD
35
+ .github
36
+
37
+ # Documentation
38
+ *.md
39
+ !README.md
40
+
41
+ # Config files
42
+ .prettierrc
43
+ .eslintrc*
@@ -0,0 +1,17 @@
1
+ # WEXTS Environment Variables
2
+ # Copy this file to .env and update values
3
+
4
+ # JWT Authentication
5
+ JWT_SECRET=your-super-secret-jwt-key-change-in-production
6
+ JWT_EXPIRES_IN=7d
7
+
8
+ # Database (Local Development - SQLite)
9
+ DATABASE_URL="file:./apps/api/dev.db"
10
+
11
+ # Database (Production - PostgreSQL)
12
+ # DATABASE_URL="postgresql://user:password@host:5432/dbname"
13
+ # DIRECT_URL="postgresql://user:password@host:5432/dbname"
14
+
15
+ # Server
16
+ PORT=3000
17
+ NODE_ENV=development
@@ -0,0 +1,60 @@
1
+ # Stage 1: Build
2
+ FROM node:20-alpine AS builder
3
+
4
+ # Install pnpm
5
+ RUN npm install -g pnpm
6
+
7
+ # Set working directory
8
+ WORKDIR /app
9
+
10
+ # Copy package files
11
+ COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
12
+ COPY apps/web/package.json ./apps/web/
13
+ COPY apps/api/package.json ./apps/api/
14
+
15
+ # Install dependencies
16
+ RUN pnpm install --frozen-lockfile
17
+
18
+ # Copy source code
19
+ COPY . .
20
+
21
+ # Generate Prisma Client
22
+ RUN cd apps/api && npx prisma generate
23
+
24
+ # Build all apps
25
+ RUN pnpm run build
26
+
27
+ # Stage 2: Production
28
+ FROM node:20-alpine AS runner
29
+
30
+ # Install pnpm
31
+ RUN npm install -g pnpm
32
+
33
+ WORKDIR /app
34
+
35
+ # Copy package files
36
+ COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
37
+ COPY apps/web/package.json ./apps/web/
38
+ COPY apps/api/package.json ./apps/api/
39
+
40
+ # Install production dependencies only
41
+ RUN pnpm install --prod --frozen-lockfile
42
+
43
+ # Copy built files from builder
44
+ COPY --from=builder /app/dist ./dist
45
+ COPY --from=builder /app/apps/web/.next ./apps/web/.next
46
+ COPY --from=builder /app/apps/web/public ./apps/web/public
47
+ COPY --from=builder /app/apps/api/dist ./apps/api/dist
48
+ COPY --from=builder /app/apps/api/prisma ./apps/api/prisma
49
+ COPY --from=builder /app/node_modules/.prisma ./node_modules/.prisma
50
+ COPY --from=builder /app/server.ts ./server.ts
51
+
52
+ # Expose port
53
+ EXPOSE 3000
54
+
55
+ # Set environment
56
+ ENV NODE_ENV=production
57
+ ENV PORT=3000
58
+
59
+ # Start application
60
+ CMD ["node", "dist/server.js"]
@@ -0,0 +1 @@
1
+ web: pnpm start
@@ -0,0 +1,58 @@
1
+ # WEXTS Templates
2
+
3
+ This directory contains all the templates needed to create a WEXTS unified server application.
4
+
5
+ ## 📁 Files Included
6
+
7
+ ### Core Templates
8
+ - `server.ts` - Unified server that runs Next.js + NestJS in one process
9
+ - `api-sdk.ts` - Type-safe SDK for API calls (zero URLs needed!)
10
+ - `root-package.json` - Root package.json with all scripts
11
+ - `tsconfig.json` - TypeScript configuration
12
+ - `.env.example` - Environment variables template
13
+
14
+ ### Deployment Templates
15
+ - `Dockerfile` - Docker multi-stage build
16
+ - `docker-compose.yml` - Docker Compose with PostgreSQL
17
+ - `.dockerignore` - Docker ignore file
18
+ - `nixpacks.toml` - Railway deployment config
19
+ - `Procfile` - Render/Heroku deployment
20
+
21
+ ### App Templates
22
+ - `nestjs-api/` - NestJS backend template
23
+ - `nextjs-web/` - Next.js frontend template
24
+
25
+ ## 🚀 Usage
26
+
27
+ These templates are used by the WEXTS CLI when creating a new project:
28
+
29
+ ```bash
30
+ npx wexts create my-app
31
+ ```
32
+
33
+ ## ✨ Features
34
+
35
+ ✅ **Unified Server** - Single Node.js process for frontend + backend
36
+ ✅ **Zero URLs** - Type-safe SDK without explicit API URLs
37
+ ✅ **Smart Routing** - Automatic routing between Next.js and NestJS
38
+ ✅ **Docker Ready** - Complete Docker setup included
39
+ ✅ **Multi-Platform Deploy** - Railway, Render, Docker, VPS
40
+
41
+ ## 📦 Template Structure
42
+
43
+ ```
44
+ project/
45
+ ├── server.ts ← Unified server
46
+ ├── package.json ← Root package
47
+ ├── tsconfig.json ← TS config
48
+ ├── .env.example ← Env template
49
+ ├── Dockerfile ← Docker build
50
+ ├── docker-compose.yml ← Docker + DB
51
+ ├── apps/
52
+ │ ├── api/ ← From nestjs-api template
53
+ │ └── web/ ← From nextjs-web template
54
+ ```
55
+
56
+ ## 🔧 Customization
57
+
58
+ Templates can be customized before project creation. See CLI documentation for details.
@@ -0,0 +1,115 @@
1
+ /**
2
+ * WEXTS Internal SDK
3
+ * Type-safe API client - ZERO URLs needed!
4
+ * Works in both Client and Server Components
5
+ */
6
+
7
+ // HTTP client - uses relative paths only
8
+ async function request<T>(method: string, path: string, data?: any): Promise<T> {
9
+ const url = `/api${path}`;
10
+
11
+ const options: RequestInit = {
12
+ method,
13
+ headers: {
14
+ 'Content-Type': 'application/json',
15
+ },
16
+ credentials: 'include',
17
+ };
18
+
19
+ if (data) {
20
+ options.body = JSON.stringify(data);
21
+ }
22
+
23
+ const response = await fetch(url, options);
24
+
25
+ if (!response.ok) {
26
+ const error = await response.json().catch(() => ({ message: response.statusText }));
27
+ throw new Error(error.message || 'Request failed');
28
+ }
29
+
30
+ return response.json();
31
+ }
32
+
33
+ // ==========================================
34
+ // TYPE-SAFE API - NO URLs ANYWHERE!
35
+ // ==========================================
36
+
37
+ export const api = {
38
+ /**
39
+ * Authentication API
40
+ */
41
+ auth: {
42
+ /**
43
+ * Register new user
44
+ * @example await api.auth.register({ email, password, name })
45
+ */
46
+ register: (data: { email: string; password: string; name?: string }) =>
47
+ request<{ user: any; access_token: string }>('POST', '/auth/register', data),
48
+
49
+ /**
50
+ * Login user
51
+ * @example await api.auth.login({ email, password })
52
+ */
53
+ login: (data: { email: string; password: string }) =>
54
+ request<{ user: any; access_token: string }>('POST', '/auth/login', data),
55
+
56
+ /**
57
+ * Get current user
58
+ * @example const user = await api.auth.me()
59
+ */
60
+ me: () => request<any>('GET', '/auth/me'),
61
+ },
62
+
63
+ /**
64
+ * Users API
65
+ */
66
+ users: {
67
+ /**
68
+ * Get current user profile
69
+ * @example const profile = await api.users.me()
70
+ */
71
+ me: () => request<any>('GET', '/users/me'),
72
+ },
73
+
74
+ /**
75
+ * Todos API
76
+ */
77
+ todos: {
78
+ /**
79
+ * Get all todos
80
+ * @example const todos = await api.todos.findAll()
81
+ */
82
+ findAll: () => request<any[]>('GET', '/todos'),
83
+
84
+ /**
85
+ * Get single todo
86
+ * @example const todo = await api.todos.findOne('123')
87
+ */
88
+ findOne: (id: string) => request<any>('GET', `/todos/${id}`),
89
+
90
+ /**
91
+ * Create new todo
92
+ * @example await api.todos.create({ title: 'Task', description: 'Do it' })
93
+ */
94
+ create: (data: { title: string; description?: string }) =>
95
+ request<any>('POST', '/todos', data),
96
+
97
+ /**
98
+ * Update todo
99
+ * @example await api.todos.update('123', { completed: true })
100
+ */
101
+ update: (id: string, data: { title?: string; description?: string; completed?: boolean }) =>
102
+ request<any>('PUT', `/todos/${id}`, data),
103
+
104
+ /**
105
+ * Delete todo
106
+ * @example await api.todos.delete('123')
107
+ */
108
+ delete: (id: string) => request<void>('DELETE', `/todos/${id}`),
109
+ },
110
+ };
111
+
112
+ /**
113
+ * Export type-safe API
114
+ */
115
+ export type API = typeof api;
@@ -0,0 +1,34 @@
1
+ version: '3.8'
2
+
3
+ services:
4
+ # WEXTS Application
5
+ app:
6
+ build:
7
+ context: .
8
+ dockerfile: Dockerfile
9
+ ports:
10
+ - "3000:3000"
11
+ environment:
12
+ - NODE_ENV=production
13
+ - DATABASE_URL=postgresql://wexts:wexts_password@postgres:5432/wexts_db
14
+ - JWT_SECRET=your-super-secret-jwt-key-change-this
15
+ - PORT=3000
16
+ depends_on:
17
+ - postgres
18
+ restart: unless-stopped
19
+
20
+ # PostgreSQL Database
21
+ postgres:
22
+ image: postgres:16-alpine
23
+ ports:
24
+ - "5432:5432"
25
+ environment:
26
+ - POSTGRES_USER=wexts
27
+ - POSTGRES_PASSWORD=wexts_password
28
+ - POSTGRES_DB=wexts_db
29
+ volumes:
30
+ - postgres_data:/var/lib/postgresql/data
31
+ restart: unless-stopped
32
+
33
+ volumes:
34
+ postgres_data: