heliumts 0.2.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.
- package/LICENSE +21 -0
- package/README.md +356 -0
- package/dist/bin/helium.d.ts +3 -0
- package/dist/bin/helium.d.ts.map +1 -0
- package/dist/bin/helium.js +236 -0
- package/dist/bin/helium.js.map +1 -0
- package/dist/client/Router.d.ts +83 -0
- package/dist/client/Router.d.ts.map +1 -0
- package/dist/client/Router.js +329 -0
- package/dist/client/Router.js.map +1 -0
- package/dist/client/cache.d.ts +8 -0
- package/dist/client/cache.d.ts.map +1 -0
- package/dist/client/cache.js +82 -0
- package/dist/client/cache.js.map +1 -0
- package/dist/client/index.d.ts +10 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +9 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/prefetch.d.ts +12 -0
- package/dist/client/prefetch.d.ts.map +1 -0
- package/dist/client/prefetch.js +33 -0
- package/dist/client/prefetch.js.map +1 -0
- package/dist/client/routerManifest.d.ts +28 -0
- package/dist/client/routerManifest.d.ts.map +1 -0
- package/dist/client/routerManifest.js +242 -0
- package/dist/client/routerManifest.js.map +1 -0
- package/dist/client/rpcClient.d.ts +33 -0
- package/dist/client/rpcClient.d.ts.map +1 -0
- package/dist/client/rpcClient.js +383 -0
- package/dist/client/rpcClient.js.map +1 -0
- package/dist/client/transitions.d.ts +85 -0
- package/dist/client/transitions.d.ts.map +1 -0
- package/dist/client/transitions.js +92 -0
- package/dist/client/transitions.js.map +1 -0
- package/dist/client/types.d.ts +6 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +2 -0
- package/dist/client/types.js.map +1 -0
- package/dist/client/useCall.d.ts +31 -0
- package/dist/client/useCall.d.ts.map +1 -0
- package/dist/client/useCall.js +40 -0
- package/dist/client/useCall.js.map +1 -0
- package/dist/client/useFetch.d.ts +34 -0
- package/dist/client/useFetch.d.ts.map +1 -0
- package/dist/client/useFetch.js +152 -0
- package/dist/client/useFetch.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime/protocol.d.ts +25 -0
- package/dist/runtime/protocol.d.ts.map +1 -0
- package/dist/runtime/protocol.js +2 -0
- package/dist/runtime/protocol.js.map +1 -0
- package/dist/server/config.d.ts +216 -0
- package/dist/server/config.d.ts.map +1 -0
- package/dist/server/config.js +130 -0
- package/dist/server/config.js.map +1 -0
- package/dist/server/context.d.ts +38 -0
- package/dist/server/context.d.ts.map +1 -0
- package/dist/server/context.js +2 -0
- package/dist/server/context.js.map +1 -0
- package/dist/server/defineHTTPRequest.d.ts +49 -0
- package/dist/server/defineHTTPRequest.d.ts.map +1 -0
- package/dist/server/defineHTTPRequest.js +34 -0
- package/dist/server/defineHTTPRequest.js.map +1 -0
- package/dist/server/defineMethod.d.ts +20 -0
- package/dist/server/defineMethod.d.ts.map +1 -0
- package/dist/server/defineMethod.js +23 -0
- package/dist/server/defineMethod.js.map +1 -0
- package/dist/server/devServer.d.ts +15 -0
- package/dist/server/devServer.d.ts.map +1 -0
- package/dist/server/devServer.js +219 -0
- package/dist/server/devServer.js.map +1 -0
- package/dist/server/handlerLoader.d.ts +1 -0
- package/dist/server/handlerLoader.d.ts.map +1 -0
- package/dist/server/handlerLoader.js +2 -0
- package/dist/server/handlerLoader.js.map +1 -0
- package/dist/server/httpRouter.d.ts +17 -0
- package/dist/server/httpRouter.d.ts.map +1 -0
- package/dist/server/httpRouter.js +227 -0
- package/dist/server/httpRouter.js.map +1 -0
- package/dist/server/index.d.ts +11 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +13 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/middleware.d.ts +30 -0
- package/dist/server/middleware.d.ts.map +1 -0
- package/dist/server/middleware.js +23 -0
- package/dist/server/middleware.js.map +1 -0
- package/dist/server/prodServer.d.ts +27 -0
- package/dist/server/prodServer.d.ts.map +1 -0
- package/dist/server/prodServer.js +301 -0
- package/dist/server/prodServer.js.map +1 -0
- package/dist/server/rateLimiter.d.ts +36 -0
- package/dist/server/rateLimiter.d.ts.map +1 -0
- package/dist/server/rateLimiter.js +113 -0
- package/dist/server/rateLimiter.js.map +1 -0
- package/dist/server/rpcRegistry.d.ts +34 -0
- package/dist/server/rpcRegistry.d.ts.map +1 -0
- package/dist/server/rpcRegistry.js +231 -0
- package/dist/server/rpcRegistry.js.map +1 -0
- package/dist/server/security.d.ts +5 -0
- package/dist/server/security.d.ts.map +1 -0
- package/dist/server/security.js +59 -0
- package/dist/server/security.js.map +1 -0
- package/dist/server/serializer.d.ts +9 -0
- package/dist/server/serializer.d.ts.map +1 -0
- package/dist/server/serializer.js +40 -0
- package/dist/server/serializer.js.map +1 -0
- package/dist/utils/envLoader.d.ts +27 -0
- package/dist/utils/envLoader.d.ts.map +1 -0
- package/dist/utils/envLoader.js +68 -0
- package/dist/utils/envLoader.js.map +1 -0
- package/dist/utils/ipExtractor.d.ts +59 -0
- package/dist/utils/ipExtractor.d.ts.map +1 -0
- package/dist/utils/ipExtractor.js +126 -0
- package/dist/utils/ipExtractor.js.map +1 -0
- package/dist/utils/logger.d.ts +2 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +24 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/vite/heliumPlugin.d.ts +3 -0
- package/dist/vite/heliumPlugin.d.ts.map +1 -0
- package/dist/vite/heliumPlugin.js +294 -0
- package/dist/vite/heliumPlugin.js.map +1 -0
- package/dist/vite/index.d.ts +3 -0
- package/dist/vite/index.d.ts.map +1 -0
- package/dist/vite/index.js +3 -0
- package/dist/vite/index.js.map +1 -0
- package/dist/vite/paths.d.ts +8 -0
- package/dist/vite/paths.d.ts.map +1 -0
- package/dist/vite/paths.js +8 -0
- package/dist/vite/paths.js.map +1 -0
- package/dist/vite/scanner.d.ts +35 -0
- package/dist/vite/scanner.d.ts.map +1 -0
- package/dist/vite/scanner.js +167 -0
- package/dist/vite/scanner.js.map +1 -0
- package/dist/vite/ssg.d.ts +22 -0
- package/dist/vite/ssg.d.ts.map +1 -0
- package/dist/vite/ssg.js +547 -0
- package/dist/vite/ssg.js.map +1 -0
- package/dist/vite/virtualServerModule.d.ts +6 -0
- package/dist/vite/virtualServerModule.d.ts.map +1 -0
- package/dist/vite/virtualServerModule.js +82 -0
- package/dist/vite/virtualServerModule.js.map +1 -0
- package/package.json +103 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Helio Bentes
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
[]()
|
|
2
|
+
[](https://github.com/heliobentes/heliumjs/issues)
|
|
3
|
+
[](https://github.com/heliobentes/heliumjs/pulls)
|
|
4
|
+
[](/LICENSE)
|
|
5
|
+
|
|
6
|
+
# HeliumTS
|
|
7
|
+
|
|
8
|
+
HeliumTS is a blazing fast 🚀 and opinionated full-stack React + Vite framework designed for simplicity and type safety. It provides seamless RPC communication and file-based routing.
|
|
9
|
+
|
|
10
|
+
## Table of Contents
|
|
11
|
+
|
|
12
|
+
1. [Getting Started](#1-getting-started)
|
|
13
|
+
- [Installation](#11-installation)
|
|
14
|
+
- [Running the Development Server](#12-running-the-development-server)
|
|
15
|
+
- [Building for Production](#13-building-for-production)
|
|
16
|
+
- [Starting the Production Server](#14-starting-the-production-server)
|
|
17
|
+
2. [Project Structure](#2-project-structure)
|
|
18
|
+
3. [Core Concepts](#3-core-concepts)
|
|
19
|
+
- [RPC (Remote Procedure Calls)](#31-rpc-remote-procedure-calls)
|
|
20
|
+
- [Routing](#32-routing)
|
|
21
|
+
- [Custom HTTP Handlers](#33-custom-http-handlers)
|
|
22
|
+
- [Middleware](#34-middleware)
|
|
23
|
+
- [Configuration](#35-heliumconfigts)
|
|
24
|
+
- [Static Site Generation (SSG)](#36-static-site-generation-ssg)
|
|
25
|
+
4. [CLI Reference](#4-cli-reference)
|
|
26
|
+
5. [More Documentation](#5-more-documentation)
|
|
27
|
+
6. [Contributing](#6-contributing)
|
|
28
|
+
7. [License](#7-license)
|
|
29
|
+
|
|
30
|
+
## 1. Getting Started
|
|
31
|
+
|
|
32
|
+
### 1.1. Installation
|
|
33
|
+
|
|
34
|
+
An installation script is coming soon! Meanwhile, follow these steps to set up a new HeliumTS project.
|
|
35
|
+
|
|
36
|
+
#### 1.1.1. Install React + Vite
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm create vite@latest my-helium-app -- --template react-ts
|
|
40
|
+
```
|
|
41
|
+
#### 1.1.2. Install HeliumJS
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npm install heliumts
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
#### 1.1.3. Setup Vite Config
|
|
48
|
+
Create or update `vite.config.ts` in the project root to include Helium's Vite plugin:
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import react from '@vitejs/plugin-react';
|
|
52
|
+
import helium from 'heliumts/vite';
|
|
53
|
+
import { defineConfig } from 'vite';
|
|
54
|
+
|
|
55
|
+
export default defineConfig({
|
|
56
|
+
plugins: [react(), helium()]
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
#### 1.1.4. Delete **main.tsx**
|
|
61
|
+
Delete the `src/main.tsx` file created by Vite, as HeliumTS handles the client entry point automatically.
|
|
62
|
+
Also, remove its reference from `index.html` if present.
|
|
63
|
+
```html
|
|
64
|
+
<!-- Remove this from index.html -->
|
|
65
|
+
<script type="module" src="/src/main.tsx"></script>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
#### 1.1.5. Update `src/App.tsx`
|
|
69
|
+
Replace the contents of `src/App.tsx` with the following content:
|
|
70
|
+
```tsx
|
|
71
|
+
import { type AppShellProps } from "heliumts/client";
|
|
72
|
+
|
|
73
|
+
export default function App({ Component, pageProps }: AppShellProps) {
|
|
74
|
+
return <Component {...pageProps} />;
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 1.2. Running the Development Server
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
npx helium dev
|
|
82
|
+
```
|
|
83
|
+
### 1.3. Building for Production
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
npx helium build
|
|
87
|
+
```
|
|
88
|
+
### 1.4. Starting the Production Server
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
npx helium start
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Check the working Example APP at: [https://github.com/heliobentes/heliumjs-example-app](https://github.com/heliobentes/heliumjs-example-app)
|
|
95
|
+
|
|
96
|
+
## 2. Project Structure
|
|
97
|
+
|
|
98
|
+
A typical HeliumTS project looks like this:
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
src/
|
|
102
|
+
pages/ # Client-side pages (Next.js pages router style)
|
|
103
|
+
index.tsx
|
|
104
|
+
[id].tsx # Dynamic routes
|
|
105
|
+
[...slug].tsx # Catch-all routes
|
|
106
|
+
_layout.tsx # Root layout
|
|
107
|
+
(protected)/ # Route group (e.g., for auth)
|
|
108
|
+
dashboard.tsx
|
|
109
|
+
server/ # Server-side logic
|
|
110
|
+
tasks.ts # RPC methods for tasks
|
|
111
|
+
auth.ts # Auth-related methods
|
|
112
|
+
webhooks.ts # Webhook HTTP handlers
|
|
113
|
+
_middleware.ts # Server middleware
|
|
114
|
+
components/ # React components
|
|
115
|
+
types/ # Shared types
|
|
116
|
+
helium.config.ts # Helium configuration
|
|
117
|
+
package.json # NPM package file
|
|
118
|
+
vite.config.ts # Vite configuration
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## 3. Core Concepts
|
|
122
|
+
|
|
123
|
+
Using HeliumTS makes it easy to build full-stack applications with minimal boilerplate. It removes the need for separate API routes and REST endpoints by enabling direct RPC calls from the client to server methods using websocket.
|
|
124
|
+
|
|
125
|
+
No more `Axios` or `fetch` calls! Just define your server methods and call them directly from your React components with full type safety.
|
|
126
|
+
|
|
127
|
+
### 3.1. RPC (Remote Procedure Calls)
|
|
128
|
+
|
|
129
|
+
Define server-side functions using `defineMethod` and call them from the client using `useCall` or `useFetch`.
|
|
130
|
+
|
|
131
|
+
**Server (`src/server/tasks.ts`):**
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
import { defineMethod } from "heliumts/server";
|
|
135
|
+
|
|
136
|
+
// Getting tasks
|
|
137
|
+
export const getTasks = defineMethod(async (args: { status: string }) => {
|
|
138
|
+
// Add your own database logic here
|
|
139
|
+
return [{ id: 1, name: "Task 1", status: args.status }];
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// Creating a new task
|
|
143
|
+
export const createTask = defineMethod(async (args: { name: string }) => {
|
|
144
|
+
// Add your own create task logic
|
|
145
|
+
return { id: 2, name: args.name };
|
|
146
|
+
});
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Client (`src/pages/tasks.tsx`):**
|
|
150
|
+
|
|
151
|
+
```tsx
|
|
152
|
+
import { useFetch, useCall } from "heliumts/client";
|
|
153
|
+
import { getTasks, createTask } from "heliumts/server";
|
|
154
|
+
|
|
155
|
+
export default function TasksPage() {
|
|
156
|
+
// Fetch data (auto-runs on mount)
|
|
157
|
+
// Data is typed based on server method return type
|
|
158
|
+
const { data, isLoading } = useFetch(getTasks, { status: "open" });
|
|
159
|
+
|
|
160
|
+
// Mutation (callable function)
|
|
161
|
+
// The call function is typed based on server method args and return type
|
|
162
|
+
const { call: add, isCalling } = useCall(createTask, {
|
|
163
|
+
invalidate: [getTasks] // Auto-refresh getTasks after success everywhere it's used
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
return (
|
|
167
|
+
<div>
|
|
168
|
+
<button onClick={() => add({ name: "New Task" })}>
|
|
169
|
+
{isCalling ? "Adding..." : "Add Task"}
|
|
170
|
+
</button>
|
|
171
|
+
{data?.map(task => <div key={task.id}>{task.name}</div>)}
|
|
172
|
+
</div>
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### 3.2. Routing
|
|
178
|
+
|
|
179
|
+
Helium uses file-based routing in the `src/pages` directory similar to
|
|
180
|
+
[**Next.js Pages Router**](https://nextjs.org/docs/pages).
|
|
181
|
+
|
|
182
|
+
- `src/pages/index.tsx` -> `/`
|
|
183
|
+
- `src/pages/about.tsx` -> `/about`
|
|
184
|
+
- `src/pages/users/[id].tsx` -> `/users/:id` (dynamic routes)
|
|
185
|
+
- `src/pages/_layout.tsx` -> Wraps all pages
|
|
186
|
+
- `src/pages/(protected)/dashboard.tsx` -> `/dashboard` (route group)
|
|
187
|
+
- `src/pages/[...slug].tsx` -> Catch-all route
|
|
188
|
+
|
|
189
|
+
**Link Component:**
|
|
190
|
+
|
|
191
|
+
Helium provides a `Link` component for client-side navigation:
|
|
192
|
+
|
|
193
|
+
```tsx
|
|
194
|
+
import { Link } from "heliumts/client";
|
|
195
|
+
|
|
196
|
+
<Link href="/about">Go to About</Link>
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
**useRouter Hook:**
|
|
200
|
+
|
|
201
|
+
Access routing information and navigation methods:
|
|
202
|
+
|
|
203
|
+
```tsx
|
|
204
|
+
import { useRouter } from "heliumts/client";
|
|
205
|
+
|
|
206
|
+
function MyComponent() {
|
|
207
|
+
const router = useRouter();
|
|
208
|
+
|
|
209
|
+
// Access current route
|
|
210
|
+
console.log(router.path); // "/users/123"
|
|
211
|
+
console.log(router.params.id); // "123"
|
|
212
|
+
console.log(router.searchParams); // URLSearchParams
|
|
213
|
+
console.log(router.status); // 200 | 404
|
|
214
|
+
|
|
215
|
+
// Navigate programmatically
|
|
216
|
+
router.push("/dashboard");
|
|
217
|
+
router.replace("/login");
|
|
218
|
+
|
|
219
|
+
// Listen to route changes
|
|
220
|
+
router.on("navigation", (event) => {
|
|
221
|
+
console.log(`Navigated to ${event.to}`);
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
See [Routing Documentation](./docs/routing.md) for detailed information including dynamic routes, layouts, and navigation.
|
|
227
|
+
|
|
228
|
+
### 3.3. Custom HTTP Handlers
|
|
229
|
+
|
|
230
|
+
For cases when you need to listen to webhooks or create REST endpoints, use `defineHTTPRequest`.
|
|
231
|
+
|
|
232
|
+
Useful for integrating with third-party services like Stripe, GitHub, and Auth clients.
|
|
233
|
+
|
|
234
|
+
#### 3.3.1. Stripe Webhook Example
|
|
235
|
+
**Server (`src/server/webhooks.ts`):**
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
import { defineHTTPRequest } from "heliumts/server";
|
|
239
|
+
|
|
240
|
+
export const stripeWebhook = defineHTTPRequest("POST", "/webhooks/stripe", async (req, ctx) => {
|
|
241
|
+
const body = await req.json();
|
|
242
|
+
// Handle webhook
|
|
243
|
+
return { received: true };
|
|
244
|
+
});
|
|
245
|
+
```
|
|
246
|
+
#### 3.3.2. Better Auth Example
|
|
247
|
+
**Server (`src/server/auth.ts`):**
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
import { defineHTTPRequest } from "heliumts/server";
|
|
251
|
+
|
|
252
|
+
export const authHandler = defineHTTPRequest("ALL", "/auth/:provider", async (req, ctx) => {
|
|
253
|
+
// Call the better-auth handler directly
|
|
254
|
+
return auth.handler(await req.toWebRequest());
|
|
255
|
+
});
|
|
256
|
+
```
|
|
257
|
+
***`toWebRequest()`** converts Helium's `Request` to a standard web `Request` object.
|
|
258
|
+
|
|
259
|
+
### 3.4. Middleware
|
|
260
|
+
|
|
261
|
+
You can define a middleware to intercept requests to the server.
|
|
262
|
+
|
|
263
|
+
**Server (`src/server/_middleware.ts`):**
|
|
264
|
+
|
|
265
|
+
```typescript
|
|
266
|
+
import { middleware } from "heliumts/server";
|
|
267
|
+
|
|
268
|
+
export default middleware(async (ctx, next) => {
|
|
269
|
+
console.log("Request received");
|
|
270
|
+
// Add your database connection or auth logic here
|
|
271
|
+
return next();
|
|
272
|
+
});
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### 3.5. helium.config.ts
|
|
276
|
+
Helium's configuration file allows you to customize server settings including RPC encoding, compression, security, and proxy configuration.
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
import type { HeliumConfig } from "heliumts/server";
|
|
280
|
+
|
|
281
|
+
const config: HeliumConfig = {
|
|
282
|
+
trustProxyDepth: 1, // Trust 1 proxy level (e.g., Vercel)
|
|
283
|
+
rpc: {
|
|
284
|
+
encoding: "msgpack", // or "json"
|
|
285
|
+
compression: {
|
|
286
|
+
enabled: true,
|
|
287
|
+
threshold: 1024,
|
|
288
|
+
},
|
|
289
|
+
security: {
|
|
290
|
+
maxConnectionsPerIP: 10,
|
|
291
|
+
maxMessagesPerWindow: 100,
|
|
292
|
+
rateLimitWindowMs: 60000,
|
|
293
|
+
tokenValidityMs: 30000,
|
|
294
|
+
},
|
|
295
|
+
},
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
export default config;
|
|
299
|
+
```
|
|
300
|
+
See [Configuration Documentation](./docs/helium-config.md) for detailed options.
|
|
301
|
+
|
|
302
|
+
### 3.6 Static Site Generation (SSG)
|
|
303
|
+
HeliumTS supports Static Site Generation (SSG) through pre-rendering pages at build time.
|
|
304
|
+
|
|
305
|
+
Add a `"use ssg";` directive at the top of your page component to enable SSG:
|
|
306
|
+
|
|
307
|
+
**SSG page: (`src/pages/about.tsx`)**
|
|
308
|
+
```tsx
|
|
309
|
+
"use ssg";
|
|
310
|
+
|
|
311
|
+
import React from "react";
|
|
312
|
+
|
|
313
|
+
export default function AboutPage() {
|
|
314
|
+
return (
|
|
315
|
+
<div>
|
|
316
|
+
<h1>About Us</h1>
|
|
317
|
+
<p>This page is statically generated at build time.</p>
|
|
318
|
+
</div>
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
During build, Helium validates SSG pages and generates optimized static HTML files.
|
|
324
|
+
|
|
325
|
+
See [SSG Documentation](./docs/ssg.md) for detailed information including limitations, hybrid rendering, and best practices.
|
|
326
|
+
|
|
327
|
+
## 4.CLI Reference
|
|
328
|
+
|
|
329
|
+
- `helium dev`: Starts Vite in development mode.
|
|
330
|
+
- `helium build`:
|
|
331
|
+
1. Builds the client using Vite.
|
|
332
|
+
2. Scans `src/server` for exports.
|
|
333
|
+
3. Bundles the server using esbuild.
|
|
334
|
+
4. Transpiles `helium.config.ts` to `dist/helium.config.js` (if present).
|
|
335
|
+
- `helium start`: Runs the bundled server (`dist/server.js`).
|
|
336
|
+
|
|
337
|
+
## 5. More Documentation
|
|
338
|
+
|
|
339
|
+
### Core Features
|
|
340
|
+
- [Routing & useRouter](./docs/routing.md) - File-based routing, dynamic routes, navigation, and the useRouter hook
|
|
341
|
+
- [Configuration](./docs/helium-config.md) - Configure RPC encoding, compression, security, and proxy settings
|
|
342
|
+
- [Static Site Generation](./docs/ssg.md) - Pre-render pages at build time for better performance
|
|
343
|
+
- [Route Groups](./docs/route-groups.md) - Organize routes with shared layouts without affecting URLs
|
|
344
|
+
|
|
345
|
+
### Deployment & Advanced
|
|
346
|
+
- [Context API](./docs/context-api.md) - Access request metadata including client IPs and headers
|
|
347
|
+
- [Proxy Configuration](./docs/proxy-configuration.md) - Configure IP detection for rate limiting behind proxies
|
|
348
|
+
- [HTTP Handlers & Webhooks](./docs/http-handlers.md) - Create custom HTTP endpoints for webhooks and REST APIs
|
|
349
|
+
- [Production Deployment](./docs/production-deployment.md) - Deploy to production platforms (Digital Ocean, Docker, etc.)
|
|
350
|
+
|
|
351
|
+
## 6. Contributing
|
|
352
|
+
|
|
353
|
+
Contributions are welcome! Please read the [contributing guide](./CONTRIBUTING.md) for details.
|
|
354
|
+
|
|
355
|
+
## 7. License
|
|
356
|
+
This project is licensed under the MIT License. See the [LICENSE](./LICENSE) file for details.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helium.d.ts","sourceRoot":"","sources":["../../src/bin/helium.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { cac } from "cac";
|
|
3
|
+
import { spawn } from "child_process";
|
|
4
|
+
import { build as esbuild } from "esbuild";
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import { build as viteBuild } from "vite";
|
|
8
|
+
import { log } from "../utils/logger.js";
|
|
9
|
+
import { scanServerExports } from "../vite/scanner.js";
|
|
10
|
+
import { generateStaticPages } from "../vite/ssg.js";
|
|
11
|
+
import { generateServerManifest } from "../vite/virtualServerModule.js";
|
|
12
|
+
const cli = cac("helium");
|
|
13
|
+
const root = process.cwd();
|
|
14
|
+
cli.command("dev", "Start development server").action(async () => {
|
|
15
|
+
const vite = spawn("vite", [], { stdio: "inherit", shell: true });
|
|
16
|
+
vite.on("close", (code) => {
|
|
17
|
+
process.exit(code || 0);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
cli.command("build", "Build for production").action(async () => {
|
|
21
|
+
log("info", "--------------------------------");
|
|
22
|
+
log("info", "Building client...");
|
|
23
|
+
try {
|
|
24
|
+
const result = await viteBuild({
|
|
25
|
+
root,
|
|
26
|
+
logLevel: "silent",
|
|
27
|
+
build: {
|
|
28
|
+
outDir: "dist",
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
// Display build output
|
|
32
|
+
if (result && "output" in result) {
|
|
33
|
+
const outputs = result.output;
|
|
34
|
+
const zlib = await import("zlib");
|
|
35
|
+
for (const chunk of outputs) {
|
|
36
|
+
if (chunk.type === "asset" || chunk.type === "chunk") {
|
|
37
|
+
const fileName = chunk.fileName;
|
|
38
|
+
const content = "code" in chunk ? chunk.code : chunk.source;
|
|
39
|
+
const size = Buffer.byteLength(content, "utf-8");
|
|
40
|
+
const sizeKB = (size / 1024).toFixed(2);
|
|
41
|
+
// Calculate gzipped size
|
|
42
|
+
const gzipped = zlib.gzipSync(content);
|
|
43
|
+
const gzipSizeKB = (gzipped.length / 1024).toFixed(2);
|
|
44
|
+
log("info", ` ${fileName.padEnd(35)} ${sizeKB.padStart(8)} kB │ gzip: ${gzipSizeKB.padStart(7)} kB`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
log("info", "Client build complete.");
|
|
49
|
+
// Generate static pages for SSG
|
|
50
|
+
log("info", "--------------------------------");
|
|
51
|
+
try {
|
|
52
|
+
// Read the generated index.html as a template for SSG
|
|
53
|
+
const distDir = path.join(root, "dist");
|
|
54
|
+
const htmlPath = path.join(distDir, "index.html");
|
|
55
|
+
if (fs.existsSync(htmlPath)) {
|
|
56
|
+
let htmlTemplate = fs.readFileSync(htmlPath, "utf-8");
|
|
57
|
+
// Clean up the template for SSG:
|
|
58
|
+
// 1. Remove the build-time HELIUM_CONNECTION_TOKEN (SSG pages don't need it)
|
|
59
|
+
htmlTemplate = htmlTemplate.replace(/<script>window\.HELIUM_CONNECTION_TOKEN = "build-time-placeholder";<\/script>/g, "");
|
|
60
|
+
// 2. Clear any existing content in root div from SPA build
|
|
61
|
+
htmlTemplate = htmlTemplate.replace(/<div\s+id="root"[^>]*>.*?<\/div>/s, '<div id="root"></div>');
|
|
62
|
+
await generateStaticPages(null, root, htmlTemplate, distDir);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
log("warn", "index.html not found in dist, skipping SSG");
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (e) {
|
|
69
|
+
log("warn", "SSG generation failed:", e);
|
|
70
|
+
// Don't fail the build if SSG fails
|
|
71
|
+
}
|
|
72
|
+
log("info", "--------------------------------");
|
|
73
|
+
}
|
|
74
|
+
catch (e) {
|
|
75
|
+
log("error", "Client build failed:", e);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
log("info", "Building server...");
|
|
79
|
+
// Generate server entry
|
|
80
|
+
const serverExports = scanServerExports(root);
|
|
81
|
+
const manifestCode = generateServerManifest(serverExports.methods, serverExports.httpHandlers, serverExports.middleware);
|
|
82
|
+
// Create the main server module that will be imported after env is loaded
|
|
83
|
+
const serverModuleCode = `
|
|
84
|
+
import { startProdServer, loadConfig } from 'heliumts/server';
|
|
85
|
+
${manifestCode}
|
|
86
|
+
|
|
87
|
+
export async function start() {
|
|
88
|
+
const config = await loadConfig();
|
|
89
|
+
|
|
90
|
+
startProdServer({
|
|
91
|
+
config,
|
|
92
|
+
registerHandlers: (registry, httpRouter) => {
|
|
93
|
+
registerAll(registry);
|
|
94
|
+
httpRouter.registerRoutes(httpHandlers);
|
|
95
|
+
if (middlewareHandler) {
|
|
96
|
+
registry.setMiddleware(middlewareHandler);
|
|
97
|
+
httpRouter.setMiddleware(middlewareHandler);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
`;
|
|
103
|
+
// Create the entry loader that loads env first, then imports the server module
|
|
104
|
+
const entryCode = `
|
|
105
|
+
// Load environment variables FIRST, before any other imports
|
|
106
|
+
import './env-loader.js';
|
|
107
|
+
// Now import and start the server (this ensures handlers load after env)
|
|
108
|
+
import { start } from './server-module.js';
|
|
109
|
+
await start();
|
|
110
|
+
`;
|
|
111
|
+
const envLoaderCode = `
|
|
112
|
+
import { loadEnvFiles, injectEnvToProcess, log } from 'heliumts/server';
|
|
113
|
+
const envRoot = process.cwd();
|
|
114
|
+
log('info', \`Loading .env files from: \${envRoot}\`);
|
|
115
|
+
const envVars = loadEnvFiles({ mode: 'production' });
|
|
116
|
+
injectEnvToProcess(envVars);
|
|
117
|
+
if (Object.keys(envVars).length > 0) {
|
|
118
|
+
log('info', \`Loaded \${Object.keys(envVars).length} environment variable(s) from .env files\`);
|
|
119
|
+
} else {
|
|
120
|
+
log('info', 'No .env files found (using platform environment variables if available)');
|
|
121
|
+
}
|
|
122
|
+
`;
|
|
123
|
+
const heliumDir = path.join(root, "node_modules", ".helium");
|
|
124
|
+
if (!fs.existsSync(heliumDir)) {
|
|
125
|
+
fs.mkdirSync(heliumDir, { recursive: true });
|
|
126
|
+
}
|
|
127
|
+
const entryPath = path.join(heliumDir, "server-entry.ts");
|
|
128
|
+
const envLoaderPath = path.join(heliumDir, "env-loader.ts");
|
|
129
|
+
const serverModuleSrcPath = path.join(heliumDir, "server-module.ts");
|
|
130
|
+
fs.writeFileSync(entryPath, entryCode);
|
|
131
|
+
fs.writeFileSync(envLoaderPath, envLoaderCode);
|
|
132
|
+
fs.writeFileSync(serverModuleSrcPath, serverModuleCode);
|
|
133
|
+
// Bundle with esbuild
|
|
134
|
+
try {
|
|
135
|
+
const serverBuild = await esbuild({
|
|
136
|
+
entryPoints: [entryPath],
|
|
137
|
+
outfile: path.join(root, "dist", "server.js"),
|
|
138
|
+
bundle: true,
|
|
139
|
+
platform: "node",
|
|
140
|
+
format: "esm",
|
|
141
|
+
external: [
|
|
142
|
+
// External common database and heavy dependencies
|
|
143
|
+
"mongodb",
|
|
144
|
+
"mongoose",
|
|
145
|
+
"pg",
|
|
146
|
+
"mysql",
|
|
147
|
+
"mysql2",
|
|
148
|
+
"sqlite3",
|
|
149
|
+
"better-sqlite3",
|
|
150
|
+
"redis",
|
|
151
|
+
// Node.js built-ins are automatically external, but let's be explicit
|
|
152
|
+
"crypto",
|
|
153
|
+
"fs",
|
|
154
|
+
"path",
|
|
155
|
+
"http",
|
|
156
|
+
"https",
|
|
157
|
+
"stream",
|
|
158
|
+
"zlib",
|
|
159
|
+
"util",
|
|
160
|
+
],
|
|
161
|
+
target: "node18",
|
|
162
|
+
metafile: true,
|
|
163
|
+
banner: {
|
|
164
|
+
js: "import { createRequire } from 'module'; const require = createRequire(import.meta.url);",
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
// Display server build output
|
|
168
|
+
const serverOutputPath = path.relative(root, path.join(root, "dist", "server.js"));
|
|
169
|
+
const serverStats = fs.statSync(path.join(root, "dist", "server.js"));
|
|
170
|
+
const serverSizeKB = (serverStats.size / 1024).toFixed(2);
|
|
171
|
+
log("info", ` ${serverOutputPath.padEnd(35)} ${serverSizeKB.padStart(8)} kB`);
|
|
172
|
+
log("info", "Server build complete.");
|
|
173
|
+
// Transpile helium.config.ts to helium.config.js if it exists
|
|
174
|
+
const configTsPath = path.join(root, "helium.config.ts");
|
|
175
|
+
if (fs.existsSync(configTsPath)) {
|
|
176
|
+
log("info", "Transpiling helium.config.ts...");
|
|
177
|
+
try {
|
|
178
|
+
await esbuild({
|
|
179
|
+
entryPoints: [configTsPath],
|
|
180
|
+
outfile: path.join(root, "dist", "helium.config.js"),
|
|
181
|
+
bundle: false,
|
|
182
|
+
platform: "node",
|
|
183
|
+
format: "esm",
|
|
184
|
+
target: "node18",
|
|
185
|
+
});
|
|
186
|
+
log("info", "Config file transpiled to dist/helium.config.js");
|
|
187
|
+
}
|
|
188
|
+
catch (e) {
|
|
189
|
+
log("warn", "Failed to transpile config file:", e);
|
|
190
|
+
log("warn", "You may need to manually rename helium.config.ts to helium.config.js");
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
// Check if .js or .mjs config exists and copy it to dist
|
|
195
|
+
const configJsPath = path.join(root, "helium.config.js");
|
|
196
|
+
const configMjsPath = path.join(root, "helium.config.mjs");
|
|
197
|
+
if (fs.existsSync(configJsPath)) {
|
|
198
|
+
fs.copyFileSync(configJsPath, path.join(root, "dist", "helium.config.js"));
|
|
199
|
+
log("info", "Copied helium.config.js to dist/");
|
|
200
|
+
}
|
|
201
|
+
else if (fs.existsSync(configMjsPath)) {
|
|
202
|
+
fs.copyFileSync(configMjsPath, path.join(root, "dist", "helium.config.mjs"));
|
|
203
|
+
log("info", "Copied helium.config.mjs to dist/");
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
log("info", "--------------------------------");
|
|
207
|
+
log("info", "✓ Build finished successfully.");
|
|
208
|
+
log("info", "▶ Run 'helium start' to start the production server.");
|
|
209
|
+
// Exit cleanly after build completes
|
|
210
|
+
process.exit(0);
|
|
211
|
+
}
|
|
212
|
+
catch (e) {
|
|
213
|
+
log("error", "Server build failed:", e);
|
|
214
|
+
process.exit(1);
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
cli.command("start", "Start production server").action(async () => {
|
|
218
|
+
const serverPath = path.join(root, "dist", "server.js");
|
|
219
|
+
if (!fs.existsSync(serverPath)) {
|
|
220
|
+
log("error", 'Server build not found. Run "helium build" first.');
|
|
221
|
+
process.exit(1);
|
|
222
|
+
}
|
|
223
|
+
// When running in production, look for config in dist directory first
|
|
224
|
+
// This allows the transpiled config to be found
|
|
225
|
+
const server = spawn("node", [serverPath], {
|
|
226
|
+
stdio: "inherit",
|
|
227
|
+
shell: true,
|
|
228
|
+
env: { ...process.env, HELIUM_CONFIG_DIR: path.join(root, "dist") },
|
|
229
|
+
});
|
|
230
|
+
server.on("close", (code) => {
|
|
231
|
+
process.exit(code || 0);
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
cli.help();
|
|
235
|
+
cli.parse();
|
|
236
|
+
//# sourceMappingURL=helium.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helium.js","sourceRoot":"","sources":["../../src/bin/helium.ts"],"names":[],"mappings":"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"}
|