bhooai-nexus 0.1.2

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 (219) hide show
  1. package/README.md +184 -0
  2. package/apps/admin/index.html +12 -0
  3. package/apps/admin/package.json +25 -0
  4. package/apps/admin/postcss.config.js +6 -0
  5. package/apps/admin/public/anime-girl.svg +84 -0
  6. package/apps/admin/public/bhooai-nexus-logo.png +0 -0
  7. package/apps/admin/public/bhooai-nexus-logo.svg +135 -0
  8. package/apps/admin/public/favicon.ico +0 -0
  9. package/apps/admin/src/main.tsx +10 -0
  10. package/apps/admin/src/vite-env.d.ts +18 -0
  11. package/apps/admin/tailwind.config.js +10 -0
  12. package/apps/admin/tsconfig.json +17 -0
  13. package/apps/admin/vite.config.ts +68 -0
  14. package/bin/nexus.js +52 -0
  15. package/package.json +108 -0
  16. package/packages/nexus-admin/package.json +32 -0
  17. package/packages/nexus-admin/src/App.tsx +4878 -0
  18. package/packages/nexus-admin/src/alertCenter.tsx +150 -0
  19. package/packages/nexus-admin/src/api.ts +601 -0
  20. package/packages/nexus-admin/src/assets/bhooai-nexus-logo.svg +25 -0
  21. package/packages/nexus-admin/src/index.css +3635 -0
  22. package/packages/nexus-admin/src/vite-env.d.ts +19 -0
  23. package/packages/nexus-ads/package.json +20 -0
  24. package/packages/nexus-ads/src/GaqlBuilder.ts +72 -0
  25. package/packages/nexus-ads/src/GoogleAdsClient.ts +121 -0
  26. package/packages/nexus-ads/src/fetchTransport.ts +10 -0
  27. package/packages/nexus-ads/src/index.ts +20 -0
  28. package/packages/nexus-ads/src/types.ts +41 -0
  29. package/packages/nexus-ai-client/package.json +18 -0
  30. package/packages/nexus-ai-client/src/client.ts +159 -0
  31. package/packages/nexus-ai-client/src/errors.ts +21 -0
  32. package/packages/nexus-ai-client/src/index.ts +4 -0
  33. package/packages/nexus-ai-client/src/sse.ts +53 -0
  34. package/packages/nexus-ai-client/src/types.ts +174 -0
  35. package/packages/nexus-auth/package.json +22 -0
  36. package/packages/nexus-auth/src/auth.ts +116 -0
  37. package/packages/nexus-auth/src/bcryptjs.d.ts +10 -0
  38. package/packages/nexus-auth/src/cors.ts +91 -0
  39. package/packages/nexus-auth/src/csrf.ts +158 -0
  40. package/packages/nexus-auth/src/headers.ts +55 -0
  41. package/packages/nexus-auth/src/index.ts +11 -0
  42. package/packages/nexus-auth/src/jwt.ts +65 -0
  43. package/packages/nexus-auth/src/middleware.ts +94 -0
  44. package/packages/nexus-auth/src/oauth.ts +199 -0
  45. package/packages/nexus-auth/src/password.ts +33 -0
  46. package/packages/nexus-auth/src/rateLimit.ts +59 -0
  47. package/packages/nexus-auth/src/rbac.ts +94 -0
  48. package/packages/nexus-auth/src/session.ts +91 -0
  49. package/packages/nexus-cache/package.json +21 -0
  50. package/packages/nexus-cache/src/Cache.ts +155 -0
  51. package/packages/nexus-cache/src/PubSub.ts +98 -0
  52. package/packages/nexus-cache/src/RateLimiter.ts +43 -0
  53. package/packages/nexus-cache/src/index.ts +9 -0
  54. package/packages/nexus-cache/src/types.ts +47 -0
  55. package/packages/nexus-cli/package.json +25 -0
  56. package/packages/nexus-cli/src/commands/cluster.ts +133 -0
  57. package/packages/nexus-cli/src/commands/dev.ts +200 -0
  58. package/packages/nexus-cli/src/commands/doctor.ts +199 -0
  59. package/packages/nexus-cli/src/commands/init.ts +1009 -0
  60. package/packages/nexus-cli/src/commands/node.ts +106 -0
  61. package/packages/nexus-cli/src/commands/pysetup.ts +142 -0
  62. package/packages/nexus-cli/src/commands/sync.ts +116 -0
  63. package/packages/nexus-cli/src/commands/uninstall.ts +287 -0
  64. package/packages/nexus-cli/src/config-sync.ts +384 -0
  65. package/packages/nexus-cli/src/dotenv.ts +39 -0
  66. package/packages/nexus-cli/src/index.ts +94 -0
  67. package/packages/nexus-cli/src/supervisor.ts +394 -0
  68. package/packages/nexus-cli/src/util.ts +132 -0
  69. package/packages/nexus-cli/src/wizard.ts +149 -0
  70. package/packages/nexus-cli/templates/Dockerfile +60 -0
  71. package/packages/nexus-cli/templates/README.md +69 -0
  72. package/packages/nexus-cli/templates/apps/admin/index.html +12 -0
  73. package/packages/nexus-cli/templates/apps/admin/package.json +24 -0
  74. package/packages/nexus-cli/templates/apps/admin/postcss.config.js +6 -0
  75. package/packages/nexus-cli/templates/apps/admin/src/main.tsx +10 -0
  76. package/packages/nexus-cli/templates/apps/admin/src/vite-env.d.ts +18 -0
  77. package/packages/nexus-cli/templates/apps/admin/tailwind.config.js +9 -0
  78. package/packages/nexus-cli/templates/apps/admin/tsconfig.json +17 -0
  79. package/packages/nexus-cli/templates/apps/admin/vite.config.ts +64 -0
  80. package/packages/nexus-cli/templates/apps/ai-server/main.py +43 -0
  81. package/packages/nexus-cli/templates/apps/ai-server/providers/__init__.py +3 -0
  82. package/packages/nexus-cli/templates/apps/ai-server/providers/base.py +111 -0
  83. package/packages/nexus-cli/templates/apps/ai-server/requirements.txt +3 -0
  84. package/packages/nexus-cli/templates/apps/ai-server/routers/__init__.py +3 -0
  85. package/packages/nexus-cli/templates/apps/ai-server/routers/chat.py +47 -0
  86. package/packages/nexus-cli/templates/apps/ai-server/routers/embeddings.py +30 -0
  87. package/packages/nexus-cli/templates/apps/ai-server/routers/lint.py +167 -0
  88. package/packages/nexus-cli/templates/apps/ai-server/routers/models.py +23 -0
  89. package/packages/nexus-cli/templates/apps/ai-server/routers/preflight.py +169 -0
  90. package/packages/nexus-cli/templates/apps/ai-server/settings.py +48 -0
  91. package/packages/nexus-cli/templates/apps/backend/package.json +34 -0
  92. package/packages/nexus-cli/templates/apps/backend/src/main.ts +375 -0
  93. package/packages/nexus-cli/templates/apps/backend/src/modules/admin/adminRoutes.ts +732 -0
  94. package/packages/nexus-cli/templates/apps/backend/src/modules/admin/clusterRoutes.ts +391 -0
  95. package/packages/nexus-cli/templates/apps/backend/src/modules/admin/databaseRoutes.ts +161 -0
  96. package/packages/nexus-cli/templates/apps/backend/src/modules/admin/lintProxy.ts +89 -0
  97. package/packages/nexus-cli/templates/apps/backend/src/modules/admin/preflightProxy.ts +242 -0
  98. package/packages/nexus-cli/templates/apps/backend/src/modules/admin/roleCatalog.ts +78 -0
  99. package/packages/nexus-cli/templates/apps/backend/src/modules/admin/schemaRoutes.ts +449 -0
  100. package/packages/nexus-cli/templates/apps/backend/src/modules/ai/aiProxy.ts +265 -0
  101. package/packages/nexus-cli/templates/apps/backend/src/modules/auth/authRoutes.ts +220 -0
  102. package/packages/nexus-cli/templates/apps/backend/src/modules/payments/paymentRoutes.ts +100 -0
  103. package/packages/nexus-cli/templates/apps/backend/src/modules/payments/paymentStore.ts +172 -0
  104. package/packages/nexus-cli/templates/apps/backend/src/modules/requests/requestLog.ts +175 -0
  105. package/packages/nexus-cli/templates/apps/backend/src/modules/users/userGraph.ts +83 -0
  106. package/packages/nexus-cli/templates/apps/backend/src/modules/users/userModel.ts +88 -0
  107. package/packages/nexus-cli/templates/apps/backend/src/plugins/CronScheduler.ts +69 -0
  108. package/packages/nexus-cli/templates/apps/backend/src/plugins/loadPlugins.ts +107 -0
  109. package/packages/nexus-cli/templates/apps/backend/tsconfig.json +14 -0
  110. package/packages/nexus-cli/templates/apps/frontend/index.html +12 -0
  111. package/packages/nexus-cli/templates/apps/frontend/package.json +19 -0
  112. package/packages/nexus-cli/templates/apps/frontend/src/main.tsx +64 -0
  113. package/packages/nexus-cli/templates/apps/frontend/vite.config.ts +72 -0
  114. package/packages/nexus-cli/templates/bin/nexus.js +35 -0
  115. package/packages/nexus-cli/templates/bin/serve-all.mjs +45 -0
  116. package/packages/nexus-cli/templates/dockerignore +15 -0
  117. package/packages/nexus-cli/templates/gitignore +12 -0
  118. package/packages/nexus-cli/templates/nexus.config.ts +69 -0
  119. package/packages/nexus-cli/templates/package.json +47 -0
  120. package/packages/nexus-cli/templates/tsconfig.json +17 -0
  121. package/packages/nexus-cli/templates/uploads/.gitkeep +0 -0
  122. package/packages/nexus-core/package.json +38 -0
  123. package/packages/nexus-core/src/config/ConfigLoader.ts +161 -0
  124. package/packages/nexus-core/src/config/defaults.ts +155 -0
  125. package/packages/nexus-core/src/config/env.ts +113 -0
  126. package/packages/nexus-core/src/config/index.ts +6 -0
  127. package/packages/nexus-core/src/config/merge.ts +28 -0
  128. package/packages/nexus-core/src/config/schema.ts +184 -0
  129. package/packages/nexus-core/src/config/types.ts +352 -0
  130. package/packages/nexus-core/src/di/Container.ts +98 -0
  131. package/packages/nexus-core/src/di/index.ts +1 -0
  132. package/packages/nexus-core/src/errors.ts +62 -0
  133. package/packages/nexus-core/src/http/Router.ts +149 -0
  134. package/packages/nexus-core/src/http/Server.ts +145 -0
  135. package/packages/nexus-core/src/http/bodyParser.ts +129 -0
  136. package/packages/nexus-core/src/http/context.ts +112 -0
  137. package/packages/nexus-core/src/http/index.ts +6 -0
  138. package/packages/nexus-core/src/http/static.ts +85 -0
  139. package/packages/nexus-core/src/http/uploads.ts +94 -0
  140. package/packages/nexus-core/src/index.ts +4 -0
  141. package/packages/nexus-crypto/package.json +18 -0
  142. package/packages/nexus-crypto/src/csr.ts +165 -0
  143. package/packages/nexus-crypto/src/der.ts +262 -0
  144. package/packages/nexus-crypto/src/https.ts +36 -0
  145. package/packages/nexus-crypto/src/index.ts +5 -0
  146. package/packages/nexus-crypto/src/keypair.ts +59 -0
  147. package/packages/nexus-crypto/src/x509.ts +156 -0
  148. package/packages/nexus-data/package.json +27 -0
  149. package/packages/nexus-data/src/connection/Connection.ts +57 -0
  150. package/packages/nexus-data/src/connection/ConnectionManager.ts +37 -0
  151. package/packages/nexus-data/src/errors.ts +17 -0
  152. package/packages/nexus-data/src/index.ts +66 -0
  153. package/packages/nexus-data/src/model/Document.ts +126 -0
  154. package/packages/nexus-data/src/model/Model.ts +189 -0
  155. package/packages/nexus-data/src/model/hydrate.ts +12 -0
  156. package/packages/nexus-data/src/populate/populate.ts +114 -0
  157. package/packages/nexus-data/src/projects.ts +185 -0
  158. package/packages/nexus-data/src/query/Query.ts +158 -0
  159. package/packages/nexus-data/src/schema/Schema.ts +173 -0
  160. package/packages/nexus-data/src/schema/SchemaType.ts +80 -0
  161. package/packages/nexus-data/src/schema/validators.ts +88 -0
  162. package/packages/nexus-email/package.json +22 -0
  163. package/packages/nexus-email/src/EmailService.ts +76 -0
  164. package/packages/nexus-email/src/TemplateEngine.ts +62 -0
  165. package/packages/nexus-email/src/index.ts +37 -0
  166. package/packages/nexus-email/src/providers.ts +63 -0
  167. package/packages/nexus-email/src/queue.ts +103 -0
  168. package/packages/nexus-email/src/types.ts +49 -0
  169. package/packages/nexus-graphql/package.json +24 -0
  170. package/packages/nexus-graphql/src/federation/composeSupergraph.ts +153 -0
  171. package/packages/nexus-graphql/src/federation/createFederatedGateway.ts +36 -0
  172. package/packages/nexus-graphql/src/federation/executor.ts +305 -0
  173. package/packages/nexus-graphql/src/federation/parseMetadata.ts +87 -0
  174. package/packages/nexus-graphql/src/gateway/createGateway.ts +77 -0
  175. package/packages/nexus-graphql/src/gateway/fieldResolver.ts +45 -0
  176. package/packages/nexus-graphql/src/gateway/graphqlHttpHandler.ts +90 -0
  177. package/packages/nexus-graphql/src/gateway/publicSchema.ts +26 -0
  178. package/packages/nexus-graphql/src/index.ts +14 -0
  179. package/packages/nexus-graphql/src/subgraph/defineSubgraph.ts +115 -0
  180. package/packages/nexus-graphql/src/subgraph/federationDirectives.ts +47 -0
  181. package/packages/nexus-graphql/src/subgraph/parseKeys.ts +25 -0
  182. package/packages/nexus-graphql/src/subscriptions/PubSub.ts +64 -0
  183. package/packages/nexus-graphql/src/subscriptions/SubscriptionServer.ts +203 -0
  184. package/packages/nexus-graphql/src/types.ts +77 -0
  185. package/packages/nexus-payments/package.json +20 -0
  186. package/packages/nexus-payments/src/errors.ts +15 -0
  187. package/packages/nexus-payments/src/http.ts +53 -0
  188. package/packages/nexus-payments/src/index.ts +106 -0
  189. package/packages/nexus-payments/src/providers/PayPalProvider.ts +192 -0
  190. package/packages/nexus-payments/src/providers/PayUProvider.ts +164 -0
  191. package/packages/nexus-payments/src/providers/PayoneerProvider.ts +122 -0
  192. package/packages/nexus-payments/src/providers/RazorpayProvider.ts +184 -0
  193. package/packages/nexus-payments/src/providers/SkrillProvider.ts +117 -0
  194. package/packages/nexus-payments/src/signature.ts +24 -0
  195. package/packages/nexus-payments/src/types.ts +150 -0
  196. package/packages/nexus-payments/src/webhooks.ts +58 -0
  197. package/packages/nexus-plugins/package.json +20 -0
  198. package/packages/nexus-plugins/src/HookBus.ts +42 -0
  199. package/packages/nexus-plugins/src/admin/adminExtensions.ts +53 -0
  200. package/packages/nexus-plugins/src/host.ts +105 -0
  201. package/packages/nexus-plugins/src/index.ts +8 -0
  202. package/packages/nexus-plugins/src/manifest.ts +73 -0
  203. package/packages/nexus-plugins/src/registry.ts +123 -0
  204. package/packages/nexus-plugins/src/runtime/TrustedPlugin.ts +134 -0
  205. package/packages/nexus-plugins/src/sandbox/SandboxedPlugin.ts +279 -0
  206. package/packages/nexus-plugins/src/sandbox/capabilityPolicy.ts +68 -0
  207. package/packages/nexus-plugins/src/sandbox/workerBootstrap.mjs +211 -0
  208. package/packages/nexus-realtime/package.json +26 -0
  209. package/packages/nexus-realtime/src/adapter/PubSubAdapter.ts +42 -0
  210. package/packages/nexus-realtime/src/adapter/RedisPubSubAdapter.ts +59 -0
  211. package/packages/nexus-realtime/src/index.ts +5 -0
  212. package/packages/nexus-realtime/src/mediasoup/MediasoupAdapter.ts +176 -0
  213. package/packages/nexus-realtime/src/server/RealtimeServer.ts +252 -0
  214. package/packages/nexus-realtime/src/types.ts +52 -0
  215. package/packages/nexus-telemetry/package.json +20 -0
  216. package/packages/nexus-telemetry/src/index.ts +3 -0
  217. package/packages/nexus-telemetry/src/logger/Logger.ts +178 -0
  218. package/packages/nexus-telemetry/src/metrics/Metrics.ts +123 -0
  219. package/packages/nexus-telemetry/src/trace.ts +28 -0
@@ -0,0 +1,14 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "rootDir": "src",
5
+ "outDir": "dist",
6
+ "module": "ESNext",
7
+ "moduleResolution": "Bundler",
8
+ "target": "ES2022",
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "types": ["node"]
12
+ },
13
+ "include": ["src"]
14
+ }
@@ -0,0 +1,12 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>My Nexus App</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ <script type="module" src="/src/main.tsx"></script>
11
+ </body>
12
+ </html>
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "my-nexus-frontend",
3
+ "private": true,
4
+ "type": "module",
5
+ "scripts": {
6
+ "dev": "vite",
7
+ "build": "vite build",
8
+ "preview": "vite preview"
9
+ },
10
+ "dependencies": {
11
+ "react": "^18.3.0",
12
+ "react-dom": "^18.3.0"
13
+ },
14
+ "devDependencies": {
15
+ "@vitejs/plugin-react": "^4.3.0",
16
+ "typescript": "^5.6.0",
17
+ "vite": "^5.4.0"
18
+ }
19
+ }
@@ -0,0 +1,64 @@
1
+ import React from 'react';
2
+ import { createRoot } from 'react-dom/client';
3
+
4
+ // Generated placeholder frontend. The framework's own apps/frontend has the full
5
+ // auth / GraphQL / streaming / checkout UI — copy what you need from there.
6
+ async function pingHealth() {
7
+ try {
8
+ const res = await fetch('/health');
9
+ const body = await res.json();
10
+ document.getElementById('status')!.textContent = `${body.status} @ ${new Date(body.time).toLocaleTimeString()}`;
11
+ } catch {
12
+ document.getElementById('status')!.textContent = 'backend not reachable';
13
+ }
14
+ }
15
+
16
+ function App() {
17
+ const [file, setFile] = React.useState<File | null>(null);
18
+ const [uploadStatus, setUploadStatus] = React.useState('');
19
+
20
+ React.useEffect(() => {
21
+ pingHealth();
22
+ const id = setInterval(pingHealth, 5000);
23
+ return () => clearInterval(id);
24
+ }, []);
25
+
26
+ async function uploadFile() {
27
+ if (!file) return;
28
+ setUploadStatus('uploading...');
29
+ try {
30
+ const csrfResponse = await fetch('/csrf-token', { credentials: 'include' });
31
+ const { token } = await csrfResponse.json() as { token: string };
32
+ const form = new FormData();
33
+ form.append('file', file);
34
+ const response = await fetch('/uploads', {
35
+ method: 'POST',
36
+ body: form,
37
+ credentials: 'include',
38
+ headers: { 'x-csrf-token': token },
39
+ });
40
+ const body = await response.json() as { files?: Array<{ url: string }>; error?: { message?: string } };
41
+ if (!response.ok) throw new Error(body.error?.message ?? 'upload failed');
42
+ setUploadStatus(`uploaded: ${body.files?.[0]?.url ?? 'ok'}`);
43
+ } catch (error) {
44
+ setUploadStatus(error instanceof Error ? error.message : 'upload failed');
45
+ }
46
+ }
47
+
48
+ return (
49
+ <main style={{ fontFamily: 'system-ui, sans-serif', padding: '2rem' }}>
50
+ <h1>My Nexus App</h1>
51
+ <p>Backend health: <span id="status">checking…</span></p>
52
+ <h2>Upload a file</h2>
53
+ <input type="file" onChange={(event) => setFile(event.target.files?.[0] ?? null)} />
54
+ <button type="button" onClick={uploadFile} disabled={!file}>Upload</button>
55
+ <p>{uploadStatus}</p>
56
+ </main>
57
+ );
58
+ }
59
+
60
+ createRoot(document.getElementById('root')!).render(
61
+ <React.StrictMode>
62
+ <App />
63
+ </React.StrictMode>,
64
+ );
@@ -0,0 +1,72 @@
1
+ import { defineConfig } from 'vite';
2
+ import react from '@vitejs/plugin-react';
3
+ import { existsSync } from 'node:fs';
4
+ import { dirname, join, resolve } from 'node:path';
5
+ import { fileURLToPath, pathToFileURL } from 'node:url';
6
+
7
+ const PROJECT_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..', '..');
8
+
9
+ // Read the merged host/port values from the project's single nexus config file
10
+ // (ts/js/mjs/cjs, discovery order matches the backend loader) plus NEXUS_*
11
+ // env overrides, so this Vite dev server and its proxy stay in one source of
12
+ // truth: nexus.config.js.
13
+ async function loadConfig() {
14
+ const exts = ['ts', 'js', 'mjs', 'cjs'];
15
+ let user: Record<string, any> = {};
16
+ for (const ext of exts) {
17
+ const file = join(PROJECT_ROOT, `nexus.config.${ext}`);
18
+ if (existsSync(file)) {
19
+ const mod = (await import(pathToFileURL(file).href + `?v=${Date.now()}`)) as Record<string, any>;
20
+ user = mod.default ?? mod.config ?? {};
21
+ break;
22
+ }
23
+ }
24
+ const num = (v: string | undefined, fallback: number) => (v !== undefined && Number.isFinite(Number(v)) ? Number(v) : fallback);
25
+ const str = (v: string | undefined, fallback: string) => (v !== undefined && v !== '' ? v : fallback);
26
+
27
+ return {
28
+ server: {
29
+ host: str(process.env.NEXUS_SERVER_HOST, user.server?.host ?? '0.0.0.0'),
30
+ port: num(process.env.NEXUS_SERVER_PORT, user.server?.port ?? 4000),
31
+ },
32
+ frontend: {
33
+ host: str(process.env.NEXUS_FRONTEND_HOST, user.frontend?.host ?? 'localhost'),
34
+ port: num(process.env.NEXUS_FRONTEND_PORT, user.frontend?.port ?? 3000),
35
+ enabled: user.frontend?.enabled ?? true,
36
+ },
37
+ cluster: {
38
+ enabled: user.cluster?.enabled ?? false,
39
+ lbPort: num(process.env.NEXUS_CLUSTER_LBPORT, user.cluster?.lbPort ?? 8080),
40
+ },
41
+ };
42
+ }
43
+
44
+ export default defineConfig(async () => {
45
+ const cfg = await loadConfig();
46
+ const backendHost = cfg.server.host === '0.0.0.0' || cfg.server.host === '::' ? '127.0.0.1' : cfg.server.host;
47
+ const backend = `http://${backendHost}:${cfg.server.port}`;
48
+ const backendWs = `ws://${backendHost}:${cfg.server.port}`;
49
+ // When the cluster is enabled, route /uploads through the load balancer so
50
+ // path-pin routing (/uploads/images -> slave-1, /uploads/files -> slave-2)
51
+ // actually applies. Otherwise fall back to the local backend directly.
52
+ const lbTarget = `http://${backendHost}:${cfg.cluster.lbPort}`;
53
+ const uploadsTarget = cfg.cluster.enabled ? lbTarget : backend;
54
+
55
+ return {
56
+ plugins: [react()],
57
+ server: {
58
+ port: cfg.frontend.port,
59
+ host: cfg.frontend.host,
60
+ proxy: {
61
+ '/health': { target: backend, changeOrigin: true },
62
+ '/auth': { target: backend, changeOrigin: true },
63
+ '/csrf-token': { target: backend, changeOrigin: true },
64
+ '/graphql': { target: backend, changeOrigin: true, ws: true },
65
+ '/ai': { target: backend, changeOrigin: true },
66
+ '/payments': { target: backend, changeOrigin: true },
67
+ '/uploads': { target: uploadsTarget, changeOrigin: true },
68
+ '/ws': { target: backendWs, ws: true, changeOrigin: true },
69
+ },
70
+ },
71
+ };
72
+ });
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Generated Nexus CLI entry. Resolves the `@bhooai/nexus-cli` package and
4
+ * dispatches the command. The CLI package's main points at TypeScript source
5
+ * (run via tsx) so there is no build step; if a compiled dist is present it is
6
+ * used directly.
7
+ */
8
+ import { existsSync } from 'node:fs';
9
+ import { extname } from 'node:path';
10
+ import { pathToFileURL } from 'node:url';
11
+ import { createRequire } from 'node:module';
12
+
13
+ const require = createRequire(import.meta.url);
14
+
15
+ async function main() {
16
+ // Resolve the CLI through the installed package exports. In a freshly init'd
17
+ // project the CLI is vendored under packages/nexus-cli, so this resolves to
18
+ // the vendored TypeScript source (no junction into the framework required).
19
+ const cliEntry = require.resolve('@bhooai/nexus-cli');
20
+ let mod;
21
+ if (existsSync(cliEntry) && extname(cliEntry) === '.js') {
22
+ mod = await import(pathToFileURL(cliEntry).href);
23
+ } else {
24
+ const { tsImport } = await import('tsx/esm/api');
25
+ mod = await tsImport(pathToFileURL(cliEntry).href, import.meta.url);
26
+ }
27
+ const cmd = process.argv[2] ?? 'help';
28
+ const rest = process.argv.slice(3);
29
+ await mod.run(cmd, rest);
30
+ }
31
+
32
+ main().catch((err) => {
33
+ console.error(err?.stack ?? err);
34
+ process.exit(1);
35
+ });
@@ -0,0 +1,45 @@
1
+ // Runs the whole Nexus stack in one process tree (used as the Docker CMD):
2
+ // backend -> nexus node serve --role=backend --port=<NEXUS_NODE_PORT|7575>
3
+ // (cluster node agent on :7575 + backend role service)
4
+ // frontend -> vite preview on :3000 (built SPA, proxies API)
5
+ // admin -> vite preview on :3300 (built admin SPA, proxies API)
6
+ // Forwards signals / reaps children so `docker stop` shuts down cleanly.
7
+ import { spawn } from 'node:child_process';
8
+ import { join, dirname } from 'node:path';
9
+ import { fileURLToPath } from 'node:url';
10
+
11
+ const root = join(dirname(fileURLToPath(import.meta.url)), '..');
12
+ const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm';
13
+ const node = process.execPath;
14
+ const nodePort = process.env.NEXUS_NODE_PORT ?? '7575';
15
+ const children = [];
16
+ let shuttingDown = false;
17
+
18
+ function run(name, cwd, cmd, args) {
19
+ const p = spawn(cmd, args, { cwd, stdio: ['ignore', 'inherit', 'inherit'], env: process.env });
20
+ children.push(p);
21
+ p.on('exit', (code) => {
22
+ if (shuttingDown) return;
23
+ console.error(`[serve-all] ${name} exited with code ${code ?? 1}`);
24
+ shutdown(code ?? 1);
25
+ });
26
+ p.on('error', (err) => {
27
+ if (shuttingDown) return;
28
+ console.error(`[serve-all] ${name} failed to start: ${err.message}`);
29
+ shutdown(1);
30
+ });
31
+ }
32
+
33
+ function shutdown(code) {
34
+ if (shuttingDown) return;
35
+ shuttingDown = true;
36
+ for (const c of children) c.kill('SIGTERM');
37
+ setTimeout(() => process.exit(code), 3000);
38
+ }
39
+
40
+ process.on('SIGINT', () => shutdown(0));
41
+ process.on('SIGTERM', () => shutdown(0));
42
+
43
+ run('backend', root, node, ['bin/nexus.js', 'node', 'serve', '--role=backend', `--port=${nodePort}`]);
44
+ run('frontend', join(root, 'apps', 'frontend'), npm, ['run', 'preview', '--', '--host', '0.0.0.0', '--port', '3000']);
45
+ run('admin', join(root, 'apps', 'admin'), npm, ['run', 'preview', '--', '--host', '0.0.0.0', '--port', '3300']);
@@ -0,0 +1,15 @@
1
+ node_modules/
2
+ **/node_modules/
3
+ dist/
4
+ logs/
5
+ *.log
6
+ .env
7
+ nexus.runtime.json
8
+ .nexus-sync.json
9
+ .git/
10
+ .DS_Store
11
+ README.md
12
+ PROGRESS.md
13
+ .dockerignore
14
+ Dockerfile
15
+ *.tsbuildinfo
@@ -0,0 +1,12 @@
1
+ node_modules/
2
+ dist/
3
+ .env
4
+ nexus.runtime.json
5
+ .nexus-sync.json
6
+ cluster.runtime.json
7
+ logs/
8
+ certs/
9
+ uploads/*
10
+ !uploads/.gitkeep
11
+ __pycache__/
12
+ .venv/
@@ -0,0 +1,69 @@
1
+ import type { NexusConfig } from '@bhooai/nexus-core';
2
+
3
+ /**
4
+ * THE single, human-edited config file for every server host/port.
5
+ *
6
+ * Precedence (low → high): code defaults < this file < nexus.runtime.json
7
+ * (admin, gitignored) < NEXUS_* env vars < CLI flags. Admin writes only
8
+ * `nexus.runtime.json`, so this file stays clean.
9
+ *
10
+ * The backend, MongoDB, Redis, the AI server, the frontend and admin Vite
11
+ * dev servers, and the node mesh all read their host/port from here. The
12
+ * Vite dev servers (apps/admin/vite.config.ts, apps/frontend/vite.config.ts)
13
+ * open the SAME file, so change host/port in ONE place.
14
+ */
15
+ const config: Partial<NexusConfig> = {
16
+ env: 'development',
17
+
18
+ // The HTTP API server the browser/cluster proxy to.
19
+ server: { port: 4000, host: '0.0.0.0', https: false, trustProxy: false, bodyLimit: 12 * 1024 * 1024 },
20
+ // Vite dev server for the frontend — hosts guests visit.
21
+ frontend: { port: 3000, host: 'localhost', enabled: true },
22
+ // Python AI server (first /ai/* proxy hops to this).
23
+ ai: { serverUrl: 'http://localhost:8000', timeoutMs: 60_000, defaultProvider: 'auto', schemaModel: 'llama3:latest' },
24
+ // Vite dev server for the admin app.
25
+ admin: { port: 3300, host: 'localhost', enabled: true },
26
+ // Node mesh: set kind via —as=root|node at init (this file stays minimal).
27
+ cluster: { enabled: false, failOpenSingleNode: true, lbHost: '0.0.0.0', lbPort: 8080, nodeAgentHost: '0.0.0.0', nodeAgentPort: 7575, registryFile: 'cluster.runtime.json', token: '' },
28
+
29
+ // File uploads.
30
+ uploads: { dir: 'uploads', path: '/uploads', maxFileSize: 10 * 1024 * 1024, maxFiles: 20, allowedTypes: [] },
31
+ // MongoDB host/port/database.
32
+ db: { uri: 'mongodb://localhost:27017/acme-app', maxPoolSize: 10, autoIndex: true },
33
+ // Redis host/port.
34
+ redis: { url: 'redis://localhost:6379', keyPrefix: 'acme:' },
35
+ // GraphQL API server (first /graphql proxy hops to this).
36
+ graphql: { path: '/graphql', federation: 'in-process', subscriptions: true, introspection: true },
37
+ //Web Socket server for the browser/cluster proxy to.
38
+ ws: { path: '/ws', heartbeatMs: 30_000, requireCsrf: true },
39
+
40
+ auth: {
41
+ // JWT secret comes ONLY from NEXUS_AUTH_JWT_SECRET in .env — never here.
42
+ jwt: { accessTtl: 60 * 15, refreshTtl: 60 * 60 * 24 * 30 },
43
+ cookieName: 'nexus_sid',
44
+ refreshCookieName: 'nexus_rid',
45
+ requireEmailVerification: false,
46
+ },
47
+
48
+ payments: { webhookPath: '/payments/webhook/:provider', currency: 'INR',
49
+ razorpay: { enabled: false, sandbox: true },
50
+ paypal: { enabled: false, sandbox: true },
51
+ payu: { enabled: false, sandbox: true },
52
+ skrill: { enabled: false, sandbox: true },
53
+ payoneer: { enabled: false, sandbox: true },
54
+ },
55
+ email: { provider: 'log', from: 'no-reply@acme.local' },
56
+ // Certificates for HTTPS, WebRTC, etc.
57
+ certs: { dir: 'certs', keyType: 'rsa', rsaModulus: 2048, ecCurve: 'prime256v1', validityDays: 365 },
58
+ // Google Ads API (first /ads proxy hops to this).
59
+ ads: { enabled: false, developerToken: '', clientId: '', clientSecret: '', refreshToken: '', customerId: '' },
60
+ // WebRTC server (first /webrtc proxy hops to this).
61
+ webrtc: { rtcMinPort: 40000, rtcMaxPort: 40100, announceIp: '127.0.0.1' },
62
+
63
+
64
+ // Logging and plugins.
65
+ logging: { level: 'info', format: 'pretty', console: true, dir: 'logs', maxFileSize: 10 * 1024 * 1024, maxFiles: 7 },
66
+ plugins: { dir: 'plugins', entries: [] },
67
+ };
68
+
69
+ export default config;
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "my-nexus-app",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "workspaces": [
7
+ "../bhooai-nexus/packages/*",
8
+ "apps/backend",
9
+ "apps/admin",
10
+ "apps/frontend"
11
+ ],
12
+ "scripts": {
13
+ "init": "nexus init .",
14
+ "dev": "nexus dev",
15
+ "build": "nexus build",
16
+ "test": "nexus test",
17
+ "doctor": "nexus doctor",
18
+ "pysetup": "nexus pysetup",
19
+ "uninstall": "nexus uninstall",
20
+ "start": "tsx apps/backend/src/main.ts"
21
+ },
22
+ "dependencies": {
23
+ "bhooai-nexus": "file:../bhooai-nexus",
24
+ "@bhooai/admin": "*",
25
+ "@bhooai/nexus-cli": "*",
26
+ "@bhooai/nexus-core": "*",
27
+ "@bhooai/nexus-auth": "*",
28
+ "@bhooai/nexus-data": "*",
29
+ "@bhooai/nexus-telemetry": "*",
30
+ "@bhooai/nexus-realtime": "*",
31
+ "@bhooai/nexus-graphql": "*",
32
+ "@bhooai/nexus-cache": "*",
33
+ "@bhooai/nexus-email": "*",
34
+ "@bhooai/nexus-payments": "*",
35
+ "@bhooai/nexus-crypto": "*",
36
+ "@bhooai/nexus-cluster": "*",
37
+ "@bhooai/nexus-ads": "*",
38
+ "@bhooai/nexus-plugins": "*",
39
+ "@bhooai/nexus-ai-client": "*"
40
+ },
41
+ "devDependencies": {
42
+ "tsx": "^4.19.0",
43
+ "typescript": "^5.6.0",
44
+ "@types/node": "^22.0.0",
45
+ "vitest": "^2.1.0"
46
+ }
47
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "Bundler",
6
+ "lib": ["ES2022", "DOM"],
7
+ "jsx": "react-jsx",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "resolveJsonModule": true,
12
+ "allowImportingTsExtensions": true,
13
+ "noEmit": true,
14
+ "types": ["node"]
15
+ },
16
+ "include": ["apps/**/*", "nexus.config.ts"]
17
+ }
File without changes
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@bhooai/nexus-core",
3
+ "version": "0.1.0",
4
+ "publishConfig": { "access": "public" },
5
+ "type": "module",
6
+ "main": "./src/index.ts",
7
+ "types": "./src/index.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./src/index.ts",
11
+ "import": "./src/index.ts"
12
+ },
13
+ "./config": {
14
+ "types": "./src/config/index.ts",
15
+ "import": "./src/config/index.ts"
16
+ },
17
+ "./di": {
18
+ "types": "./src/di/index.ts",
19
+ "import": "./src/di/index.ts"
20
+ },
21
+ "./http": {
22
+ "types": "./src/http/index.ts",
23
+ "import": "./src/http/index.ts"
24
+ }
25
+ },
26
+ "scripts": {
27
+ "build": "tsc -p tsconfig.json",
28
+ "test": "vitest run"
29
+ },
30
+ "dependencies": {
31
+ "zod": "^3.23.8"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^22.5.0",
35
+ "typescript": "^5.6.2",
36
+ "vitest": "^2.1.1"
37
+ }
38
+ }
@@ -0,0 +1,161 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { dirname, join, resolve } from 'node:path';
3
+ import { fileURLToPath, pathToFileURL } from 'node:url';
4
+ import { defaults } from './defaults.js';
5
+ import { deepMerge } from './merge.js';
6
+ import { configFromEnv, loadEnvFile } from './env.js';
7
+ import { nexusConfigSchema } from './schema.js';
8
+ import type { DeepPartial, NexusConfig, UserNexusConfig } from './types.js';
9
+
10
+ export interface LoadOptions {
11
+ /** The imported user config object (from `nexus.config.ts`). */
12
+ userConfig?: UserNexusConfig;
13
+ /** Path to a `nexus.config.ts`/`.js` to import dynamically if `userConfig` not given. */
14
+ userConfigPath?: string;
15
+ /** Path to a shipped default config (the framework's `nexus/nexus.config.ts`) merged right
16
+ * after the code defaults and before the user config. */
17
+ defaultConfigPath?: string;
18
+ /** Path to `nexus.runtime.json` (admin write-back). Defaults to `<root>/nexus.runtime.json`. */
19
+ runtimePath?: string;
20
+ /** Project root used to resolve relative paths. Defaults to cwd. */
21
+ root?: string;
22
+ /** Env override (for tests). */
23
+ env?: NodeJS.ProcessEnv;
24
+ /** CLI flag overrides (highest precedence). */
25
+ cli?: DeepPartial<NexusConfig>;
26
+ }
27
+
28
+ /**
29
+ * Load and merge configuration in precedence order:
30
+ * defaults < userConfig (nexus.config.ts) < runtime.json < env < cli
31
+ * Then validate with the zod schema and return a frozen, typed config.
32
+ */
33
+ export async function loadConfig(opts: LoadOptions = {}): Promise<NexusConfig> {
34
+ const root = resolve(opts.root ?? process.cwd());
35
+ const env = opts.env ?? process.env;
36
+
37
+ // 0. project .env — merged into the env object BEFORE env-var mapping below.
38
+ // Skipped when a caller passes its own env (tests), which must stay pure.
39
+ if (!opts.env) loadEnvFile(root, env);
40
+
41
+ // 1. defaults
42
+ let merged: unknown = defaults;
43
+
44
+ // 1b. shipped default config (the framework's nexus.config.ts) — base layer above code defaults
45
+ if (opts.defaultConfigPath && existsSync(resolve(opts.defaultConfigPath))) {
46
+ const defaultConfig = await importUserConfig(resolve(opts.defaultConfigPath));
47
+ merged = deepMerge(merged, defaultConfig);
48
+ }
49
+
50
+ // 2. user config (nexus.config.ts / nexus.config.js)
51
+ let userConfig = opts.userConfig;
52
+ if (!userConfig && opts.userConfigPath) {
53
+ userConfig = await importUserConfig(resolve(opts.userConfigPath));
54
+ }
55
+ if (userConfig) merged = deepMerge(merged, userConfig);
56
+
57
+ // 3. runtime.json (admin write-back, gitignored)
58
+ const runtimePath = opts.runtimePath ?? resolve(root, 'nexus.runtime.json');
59
+ if (existsSync(runtimePath)) {
60
+ try {
61
+ const runtime = JSON.parse(readFileSync(runtimePath, 'utf8')) as DeepPartial<NexusConfig>;
62
+ merged = deepMerge(merged, runtime);
63
+ } catch {
64
+ // A corrupt runtime file must not crash boot; ignore it.
65
+ }
66
+ }
67
+
68
+ // 4. env
69
+ merged = deepMerge(merged, configFromEnv(env));
70
+
71
+ // 5. cli flags (highest)
72
+ if (opts.cli) merged = deepMerge(merged, opts.cli);
73
+
74
+ // validate
75
+ const parsed = nexusConfigSchema.parse(merged);
76
+ return Object.freeze(parsed) as NexusConfig;
77
+ }
78
+
79
+ async function importUserConfig(absPath: string): Promise<UserNexusConfig> {
80
+ const url = pathToFileURL(absPath).href;
81
+ const mod = (await import(url)) as Record<string, unknown>;
82
+ const cfg = (mod.default ?? mod.config) as UserNexusConfig | undefined;
83
+ if (!cfg) {
84
+ throw new Error(
85
+ `Expected ${absPath} to export a config object as the default export or named "config".`,
86
+ );
87
+ }
88
+ return cfg;
89
+ }
90
+
91
+ /** Resolve a path relative to the project root. */
92
+ export function resolvePath(cfg: NexusConfig, rel: string): string {
93
+ return resolve(rel);
94
+ }
95
+
96
+ const CONFIG_EXTENSIONS = ['ts', 'js', 'mjs', 'cjs'] as const;
97
+
98
+ /**
99
+ * Path to the framework's own shipped `nexus.config.ts` (at the framework workspace root).
100
+ * Resolved relative to THIS file so it works from both `src/` (run via tsx) and `dist/`
101
+ * (compiled). When `@bhooai/nexus-core` is installed inside a user app's `node_modules/`,
102
+ * this resolves to a non-existent path under `node_modules/` — so it is simply skipped there
103
+ * (a user app does not inherit the framework's example config).
104
+ */
105
+ export function frameworkDefaultConfigPath(): string {
106
+ const here = dirname(fileURLToPath(import.meta.url));
107
+ // src/config/ -> src -> <pkg> -> packages -> <framework root> (4 levels up)
108
+ return resolve(here, '..', '..', '..', '..', 'nexus.config.ts');
109
+ }
110
+
111
+ /**
112
+ * First `nexus.config.{ts,js,mjs,cjs}` found walking UP from `root`, skipping `exclude`.
113
+ * Standard find-first discovery; stops at the filesystem root.
114
+ */
115
+ export function discoverUserConfigPath(root: string, exclude?: string): string | undefined {
116
+ let dir = resolve(root);
117
+ const excl = exclude ? resolve(exclude) : undefined;
118
+ for (let i = 0; i < 24; i++) {
119
+ for (const ext of CONFIG_EXTENSIONS) {
120
+ const cand = join(dir, `nexus.config.${ext}`);
121
+ if (existsSync(cand) && (!excl || resolve(cand) !== excl)) return cand;
122
+ }
123
+ const parent = dirname(dir);
124
+ if (parent === dir) break; // filesystem root
125
+ dir = parent;
126
+ }
127
+ return undefined;
128
+ }
129
+
130
+ /**
131
+ * Auto-discover and load config with the framework's two-level model:
132
+ * defaults < framework default (`nexus/nexus.config.ts`) < user config < runtime.json < env < cli
133
+ *
134
+ * The framework default is located via `frameworkDefaultConfigPath()` (the shipped
135
+ * `nexus/nexus.config.ts`). The user config is the nearest `nexus.config.{ts,js,...}` walking
136
+ * up from `root`, SKIPPING that default — so when running the framework's own app (cwd =
137
+ * `nexus/`), the discovery walks past `nexus/nexus.config.ts` and finds the user-editable
138
+ * `nexus.config.js` at the project root, which overrides the default. When running a user app,
139
+ * the framework default path does not exist, so only that app's own config is loaded.
140
+ */
141
+ export async function loadConfigAuto(
142
+ opts: Omit<LoadOptions, 'userConfig' | 'userConfigPath' | 'defaultConfigPath'> = {},
143
+ ): Promise<NexusConfig> {
144
+ const root = resolve(opts.root ?? process.cwd());
145
+ const defaultPath = frameworkDefaultConfigPath();
146
+ const defaultExists = existsSync(defaultPath);
147
+ const userPath = defaultExists
148
+ ? discoverUserConfigPath(root, defaultPath)
149
+ : discoverUserConfigPath(root);
150
+ return loadConfig({
151
+ ...opts,
152
+ root,
153
+ defaultConfigPath: defaultExists ? defaultPath : undefined,
154
+ userConfigPath: userPath,
155
+ });
156
+ }
157
+
158
+ /** Read-only accessor for tests / bootstrap that don't need file loading. */
159
+ export function mergeConfig(...sources: DeepPartial<NexusConfig>[]): NexusConfig {
160
+ return Object.freeze(nexusConfigSchema.parse(deepMerge(defaults, ...sources))) as NexusConfig;
161
+ }