create-heliumts-app 0.2.5

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 (40) hide show
  1. package/README.md +67 -0
  2. package/bin/index.js +5 -0
  3. package/package.json +40 -0
  4. package/src/index.js +245 -0
  5. package/templates/basic/README.md +44 -0
  6. package/templates/basic/eslint.config.js +23 -0
  7. package/templates/basic/helium.config.ts +21 -0
  8. package/templates/basic/index.html +13 -0
  9. package/templates/basic/package-lock.json +3718 -0
  10. package/templates/basic/package.json +30 -0
  11. package/templates/basic/public/helium.png +0 -0
  12. package/templates/basic/src/App.tsx +5 -0
  13. package/templates/basic/src/components/HeliumLogo.tsx +9 -0
  14. package/templates/basic/src/pages/_layout.tsx +3 -0
  15. package/templates/basic/src/pages/index.tsx +69 -0
  16. package/templates/basic/src/server/tasks.ts +26 -0
  17. package/templates/basic/src/styles.css +181 -0
  18. package/templates/basic/src/types/heliumts-server.d.ts +13 -0
  19. package/templates/basic/tsconfig.app.json +28 -0
  20. package/templates/basic/tsconfig.json +7 -0
  21. package/templates/basic/tsconfig.node.json +26 -0
  22. package/templates/basic/vite.config.ts +8 -0
  23. package/templates/tailwind/README.md +49 -0
  24. package/templates/tailwind/eslint.config.js +23 -0
  25. package/templates/tailwind/helium.config.ts +21 -0
  26. package/templates/tailwind/index.html +13 -0
  27. package/templates/tailwind/package-lock.json +4286 -0
  28. package/templates/tailwind/package.json +32 -0
  29. package/templates/tailwind/public/helium.png +0 -0
  30. package/templates/tailwind/src/App.tsx +5 -0
  31. package/templates/tailwind/src/components/HeliumLogo.tsx +11 -0
  32. package/templates/tailwind/src/pages/_layout.tsx +3 -0
  33. package/templates/tailwind/src/pages/index.tsx +87 -0
  34. package/templates/tailwind/src/server/tasks.ts +26 -0
  35. package/templates/tailwind/src/styles.css +7 -0
  36. package/templates/tailwind/src/types/heliumts-server.d.ts +13 -0
  37. package/templates/tailwind/tsconfig.app.json +28 -0
  38. package/templates/tailwind/tsconfig.json +7 -0
  39. package/templates/tailwind/tsconfig.node.json +26 -0
  40. package/templates/tailwind/vite.config.ts +9 -0
package/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # create-heliumts-app
2
+
3
+ Create [HeliumTS](https://github.com/heliobentes/heliumts) apps with one command.
4
+
5
+ ## Usage
6
+
7
+ ```bash
8
+ npx create-heliumts-app my-app
9
+ ```
10
+
11
+ Or to scaffold in the current directory:
12
+
13
+ ```bash
14
+ npx create-heliumts-app .
15
+ ```
16
+
17
+ ### Options
18
+
19
+ | Flag | Description |
20
+ |------|-------------|
21
+ | `--tailwind` | Use Tailwind CSS template (skips prompt) |
22
+ | `--no-tailwind` | Use basic template without Tailwind (skips prompt) |
23
+
24
+ ```bash
25
+ # Use Tailwind CSS (default, skips prompt)
26
+ npx create-heliumts-app my-app --tailwind
27
+
28
+ # Use basic template without Tailwind (skips prompt)
29
+ npx create-heliumts-app my-app --no-tailwind
30
+ ```
31
+
32
+ ## What it does
33
+
34
+ 1. Asks if you want to use **Tailwind CSS** (defaults to Yes)
35
+ 2. Scaffolds a complete HeliumTS project with one of two templates:
36
+ - `tailwind` - HeliumTS with Tailwind CSS pre-configured (default)
37
+ - `basic` - Standard HeliumTS setup
38
+ 3. Automatically runs `npm install`
39
+
40
+ ## Requirements
41
+
42
+ - Node.js 18.0.0 or later
43
+ - npm, yarn, or pnpm
44
+
45
+ ## After Installation
46
+
47
+ ```bash
48
+ cd my-app
49
+ npm run dev
50
+ ```
51
+
52
+ ## Available Scripts
53
+
54
+ | Command | Description |
55
+ |---------|-------------|
56
+ | `npm run dev` | Start development server |
57
+ | `npm run build` | Build for production |
58
+ | `npm run start` | Start production server |
59
+
60
+ ## Learn More
61
+
62
+ - [HeliumTS Documentation](https://heliumts.com/docs)
63
+ - [HeliumTS GitHub](https://github.com/heliobentes/heliumts)
64
+
65
+ ## License
66
+
67
+ MIT
package/bin/index.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { createApp } from '../src/index.js';
4
+
5
+ createApp();
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "create-heliumts-app",
3
+ "version": "0.2.5",
4
+ "description": "Create HeliumTS apps with one command",
5
+ "type": "module",
6
+ "main": "src/index.js",
7
+ "bin": {
8
+ "create-heliumts-app": "./bin/index.js"
9
+ },
10
+ "scripts": {
11
+ "test": "node bin/index.js test-app"
12
+ },
13
+ "keywords": [
14
+ "heliumts",
15
+ "react",
16
+ "vite",
17
+ "fullstack",
18
+ "typescript",
19
+ "cli",
20
+ "create-app"
21
+ ],
22
+ "author": "Helio Bentes",
23
+ "license": "MIT",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/heliobentes/create-heliumts-app.git"
27
+ },
28
+ "bugs": {
29
+ "url": "https://github.com/heliobentes/create-heliumts-app/issues"
30
+ },
31
+ "homepage": "https://heliumts.com",
32
+ "files": [
33
+ "bin",
34
+ "src",
35
+ "templates"
36
+ ],
37
+ "engines": {
38
+ "node": ">=18.0.0"
39
+ }
40
+ }
package/src/index.js ADDED
@@ -0,0 +1,245 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import * as readline from 'readline';
4
+ import { execSync } from 'child_process';
5
+ import { fileURLToPath } from 'url';
6
+
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = path.dirname(__filename);
9
+
10
+ const COLORS = {
11
+ reset: '\x1b[0m',
12
+ bright: '\x1b[1m',
13
+ dim: '\x1b[2m',
14
+ red: '\x1b[31m',
15
+ green: '\x1b[32m',
16
+ yellow: '\x1b[33m',
17
+ blue: '\x1b[34m',
18
+ magenta: '\x1b[35m',
19
+ cyan: '\x1b[36m',
20
+ white: '\x1b[37m'
21
+ };
22
+
23
+ function log(message, color = '') {
24
+ console.log(`${color}${message}${COLORS.reset}`);
25
+ }
26
+
27
+ function logSuccess(message) {
28
+ log(`✓ ${message}`, COLORS.green);
29
+ }
30
+
31
+ function logError(message) {
32
+ log(`✗ ${message}`, COLORS.red);
33
+ }
34
+
35
+ function logInfo(message) {
36
+ log(`ℹ ${message}`, COLORS.cyan);
37
+ }
38
+
39
+ function printBanner() {
40
+ console.log('');
41
+ log('╔═══════════════════════════════════════════╗', COLORS.cyan);
42
+ log('║ ║', COLORS.cyan);
43
+ log('║ 🚀 Create HeliumTS App 🚀 ║', COLORS.cyan);
44
+ log('║ ║', COLORS.cyan);
45
+ log('╚═══════════════════════════════════════════╝', COLORS.cyan);
46
+ console.log('');
47
+ }
48
+
49
+ function askQuestion(rl, question) {
50
+ return new Promise((resolve) => {
51
+ rl.question(question, (answer) => {
52
+ resolve(answer.trim());
53
+ });
54
+ });
55
+ }
56
+
57
+ function copyDirectory(src, dest) {
58
+ fs.mkdirSync(dest, { recursive: true });
59
+
60
+ const entries = fs.readdirSync(src, { withFileTypes: true });
61
+
62
+ for (const entry of entries) {
63
+ const srcPath = path.join(src, entry.name);
64
+ const destPath = path.join(dest, entry.name);
65
+
66
+ if (entry.isDirectory()) {
67
+ copyDirectory(srcPath, destPath);
68
+ } else {
69
+ fs.copyFileSync(srcPath, destPath);
70
+ }
71
+ }
72
+ }
73
+
74
+ function isDirectoryEmpty(dirPath) {
75
+ if (!fs.existsSync(dirPath)) {
76
+ return true;
77
+ }
78
+
79
+ const files = fs.readdirSync(dirPath);
80
+ // Ignore hidden files like .git, .DS_Store
81
+ const visibleFiles = files.filter(f => !f.startsWith('.'));
82
+ return visibleFiles.length === 0;
83
+ }
84
+
85
+ function parseArgs(args) {
86
+ const result = {
87
+ projectName: null,
88
+ tailwind: null // null means ask, true means use tailwind, false means skip tailwind
89
+ };
90
+
91
+ for (const arg of args) {
92
+ if (arg === '--tailwind') {
93
+ result.tailwind = true;
94
+ } else if (arg === '--no-tailwind') {
95
+ result.tailwind = false;
96
+ } else if (!arg.startsWith('-')) {
97
+ result.projectName = arg;
98
+ }
99
+ }
100
+
101
+ return result;
102
+ }
103
+
104
+ export async function createApp() {
105
+ printBanner();
106
+
107
+ // Get project name from command line arguments
108
+ const args = process.argv.slice(2);
109
+ const { projectName, tailwind: tailwindFlag } = parseArgs(args);
110
+
111
+ if (!projectName) {
112
+ logError('Please specify the project directory:');
113
+ console.log('');
114
+ log(' npx create-heliumts-app <project-directory>', COLORS.dim);
115
+ console.log('');
116
+ log('For example:', COLORS.dim);
117
+ log(' npx create-heliumts-app my-helium-app', COLORS.dim);
118
+ log(' npx create-heliumts-app my-helium-app --tailwind', COLORS.dim);
119
+ log(' npx create-heliumts-app .', COLORS.dim);
120
+ console.log('');
121
+ process.exit(1);
122
+ }
123
+
124
+ // Resolve the target directory
125
+ const isCurrentDir = projectName === '.';
126
+ const targetDir = isCurrentDir
127
+ ? process.cwd()
128
+ : path.resolve(process.cwd(), projectName);
129
+
130
+ const displayName = isCurrentDir ? 'current directory' : projectName;
131
+
132
+ // Check if directory is empty
133
+ if (!isDirectoryEmpty(targetDir)) {
134
+ logError(`The directory "${displayName}" is not empty.`);
135
+ log('Please choose an empty directory or remove existing files.', COLORS.dim);
136
+ console.log('');
137
+ process.exit(1);
138
+ }
139
+
140
+ // Create readline interface for user input
141
+ const rl = readline.createInterface({
142
+ input: process.stdin,
143
+ output: process.stdout
144
+ });
145
+
146
+ try {
147
+ // Determine if we should use Tailwind
148
+ let useTailwind;
149
+
150
+ if (tailwindFlag !== null) {
151
+ // Flag was provided, use it directly
152
+ useTailwind = tailwindFlag;
153
+ log(`Creating a new HeliumTS app in ${COLORS.cyan}${targetDir}${COLORS.reset}`);
154
+ console.log('');
155
+ logInfo(`Using ${useTailwind ? 'Tailwind CSS' : 'basic'} template (from flag)...`);
156
+ } else {
157
+ // Ask the user
158
+ log(`Creating a new HeliumTS app in ${COLORS.cyan}${targetDir}${COLORS.reset}`);
159
+ console.log('');
160
+
161
+ const tailwindAnswer = await askQuestion(
162
+ rl,
163
+ `${COLORS.yellow}?${COLORS.reset} Do you want to use Tailwind CSS? ${COLORS.dim}(Y/n)${COLORS.reset} `
164
+ );
165
+
166
+ // Default is YES (Tailwind)
167
+ useTailwind = tailwindAnswer.toLowerCase() !== 'n' && tailwindAnswer.toLowerCase() !== 'no';
168
+ console.log('');
169
+ logInfo(`Using ${useTailwind ? 'Tailwind CSS' : 'basic'} template...`);
170
+ }
171
+
172
+ const templateName = useTailwind ? 'tailwind' : 'basic';
173
+
174
+ // Get template path
175
+ const templatesDir = path.join(__dirname, '..', 'templates');
176
+ const templatePath = path.join(templatesDir, templateName);
177
+
178
+ // Check if template exists
179
+ if (!fs.existsSync(templatePath)) {
180
+ logError(`Template "${templateName}" not found at ${templatePath}`);
181
+ log('Please make sure the templates are properly installed.', COLORS.dim);
182
+ process.exit(1);
183
+ }
184
+
185
+ // Copy template to target directory
186
+ logInfo('Scaffolding project...');
187
+ copyDirectory(templatePath, targetDir);
188
+
189
+ // Update package.json with project name
190
+ const packageJsonPath = path.join(targetDir, 'package.json');
191
+ if (fs.existsSync(packageJsonPath)) {
192
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
193
+ packageJson.name = isCurrentDir ? path.basename(targetDir) : projectName;
194
+ fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n');
195
+ }
196
+
197
+ logSuccess('Project scaffolded successfully!');
198
+
199
+ // Install dependencies
200
+ console.log('');
201
+ logInfo('Installing dependencies...');
202
+ console.log('');
203
+
204
+ try {
205
+ execSync('npm install', {
206
+ cwd: targetDir,
207
+ stdio: 'inherit'
208
+ });
209
+ console.log('');
210
+ logSuccess('Dependencies installed successfully!');
211
+ } catch (error) {
212
+ logError('Failed to install dependencies.');
213
+ log('Please run "npm install" manually in the project directory.', COLORS.dim);
214
+ }
215
+
216
+ // Print success message
217
+ console.log('');
218
+ log('═══════════════════════════════════════════', COLORS.green);
219
+ logSuccess('Your HeliumTS app is ready!');
220
+ log('═══════════════════════════════════════════', COLORS.green);
221
+ console.log('');
222
+
223
+ log('Next steps:', COLORS.bright);
224
+ console.log('');
225
+
226
+ if (!isCurrentDir) {
227
+ log(` cd ${projectName}`, COLORS.cyan);
228
+ }
229
+ log(' npm run dev', COLORS.cyan);
230
+ console.log('');
231
+
232
+ log('Available commands:', COLORS.bright);
233
+ console.log('');
234
+ log(' npm run dev - Start development server', COLORS.dim);
235
+ log(' npm run build - Build for production', COLORS.dim);
236
+ log(' npm run start - Start production server', COLORS.dim);
237
+ console.log('');
238
+
239
+ log('Happy coding! 🎉', COLORS.magenta);
240
+ console.log('');
241
+
242
+ } finally {
243
+ rl.close();
244
+ }
245
+ }
@@ -0,0 +1,44 @@
1
+ # HeliumTS App
2
+
3
+ This is a [HeliumTS](https://heliumts.com) project bootstrapped with `create-heliumts-app`.
4
+
5
+ ## Getting Started
6
+
7
+ First, install the dependencies:
8
+
9
+ ```bash
10
+ npm install
11
+ # or
12
+ yarn
13
+ # or
14
+ pnpm install
15
+ ```
16
+
17
+ Then, run the development server:
18
+
19
+ ```bash
20
+ npm run dev
21
+ # or
22
+ yarn dev
23
+ # or
24
+ pnpm dev
25
+ ```
26
+
27
+ Open [http://localhost:5173](http://localhost:5173) with your browser to see the result.
28
+
29
+ You can start editing the page by modifying `src/pages/index.tsx`. The page auto-updates as you edit the file.
30
+
31
+ ## Project Structure
32
+
33
+ - `src/pages` - File-based routing for your application.
34
+ - `src/server` - Server-side logic and RPC functions.
35
+ - `src/components` - React components.
36
+ - `helium.config.ts` - HeliumTS configuration.
37
+
38
+ ## Learn More
39
+
40
+ To learn more about HeliumTS, take a look at the following resources:
41
+
42
+ - [HeliumTS Documentation](https://heliumts.com/docs) - learn about HeliumTS features and API.
43
+ - [HeliumTS GitHub](https://github.com/heliobentes/heliumts) - check out the source code and contribute.
44
+
@@ -0,0 +1,23 @@
1
+ import js from '@eslint/js'
2
+ import globals from 'globals'
3
+ import reactHooks from 'eslint-plugin-react-hooks'
4
+ import reactRefresh from 'eslint-plugin-react-refresh'
5
+ import tseslint from 'typescript-eslint'
6
+ import { defineConfig, globalIgnores } from 'eslint/config'
7
+
8
+ export default defineConfig([
9
+ globalIgnores(['dist']),
10
+ {
11
+ files: ['**/*.{ts,tsx}'],
12
+ extends: [
13
+ js.configs.recommended,
14
+ tseslint.configs.recommended,
15
+ reactHooks.configs.flat.recommended,
16
+ reactRefresh.configs.vite,
17
+ ],
18
+ languageOptions: {
19
+ ecmaVersion: 2020,
20
+ globals: globals.browser,
21
+ },
22
+ },
23
+ ])
@@ -0,0 +1,21 @@
1
+ import type { HeliumConfig } from "heliumts/server";
2
+
3
+ const config: HeliumConfig = {
4
+ trustProxyDepth: 1, // Trust 1 proxy level (e.g., DigitalOcean, Netlify, etc.)
5
+ rpc: {
6
+ transport: "websocket",
7
+ autoHttpOnMobile: false,
8
+ compression: {
9
+ enabled: true,
10
+ threshold: 1024,
11
+ },
12
+ security: {
13
+ maxConnectionsPerIP: 10,
14
+ maxMessagesPerWindow: 200,
15
+ rateLimitWindowMs: 60000,
16
+ tokenValidityMs: 30000,
17
+ },
18
+ },
19
+ };
20
+
21
+ export default config;
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/helium.png" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>HeliumTS App</title>
8
+ <link href="/src/styles.css" rel="stylesheet" />
9
+ </head>
10
+ <body>
11
+ <div id="root"></div>
12
+ </body>
13
+ </html>