stoix 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,147 @@
1
+ # Stoix
2
+
3
+ Stoix is a TypeScript-first framework starter that scaffolds a Node + Express + React app with Vite.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ npx stoix create my-app
9
+ cd my-app
10
+ npm run dev
11
+ ```
12
+
13
+ App URL: `http://localhost:3000`
14
+
15
+ ## CLI
16
+
17
+ ### Create a project
18
+
19
+ ```bash
20
+ npx stoix create <project-name>
21
+ ```
22
+
23
+ ### Help and version
24
+
25
+ ```bash
26
+ npx stoix --help
27
+ npx stoix --version
28
+ ```
29
+
30
+ Project names must start with a letter and may contain letters, numbers, `.`, `_`, and `-`.
31
+
32
+ ## What Stoix Generates
33
+
34
+ - Express server with auto-loaded API route modules
35
+ - React 18 client with Vite HMR in development
36
+ - Shared TypeScript setup across server, client, and config
37
+ - Production build pipeline for client and server output
38
+
39
+ ## Generated Project Structure
40
+
41
+ ```text
42
+ my-app/
43
+ ├── package.json # Dependencies and scripts
44
+ ├── stoix.config.ts # Stoix framework configuration
45
+ ├── tsconfig.json # TypeScript config (shared)
46
+ ├── tsconfig.server.json # TypeScript config (server)
47
+ ├── vite.config.ts # Vite build configuration
48
+ ├── vite-env.d.ts # Vite environment types
49
+ ├── index.html # HTML entry point
50
+ ├── .env # Environment variables
51
+ ├── server/ # Express server
52
+ │ ├── server.ts # Server entry point
53
+ │ └── routes/ # Auto-loaded API routes
54
+ │ └── example.ts # Example API route
55
+ ├── src/ # React client source
56
+ │ ├── App.tsx # Root React component
57
+ │ ├── main.tsx # Client entry point
58
+ │ └── styles.css # Global styles
59
+ ├── pages/ # SSR pages (if enabled)
60
+ │ └── index.tsx # Home page
61
+ └── public/ # Static assets
62
+ └── favicon.svg # Favicon
63
+ ```
64
+
65
+ ## Generated Scripts
66
+
67
+ | Script | Description |
68
+ | --- | --- |
69
+ | `npm run dev` | Runs the Express server with Vite middleware in development (`tsx server/server.ts`). |
70
+ | `npm run build` | Runs TS checks, builds client assets with Vite, then compiles server output. |
71
+ | `npm start` | Starts the production server from compiled files. |
72
+ | `npm run typecheck` | Runs TypeScript checks without emit. |
73
+
74
+ ## Configuration
75
+
76
+ Edit `stoix.config.ts`:
77
+
78
+ ```ts
79
+ export interface StoixConfig {
80
+ port: number;
81
+ framework: 'react';
82
+ server: {
83
+ apiPrefix: string;
84
+ cors: string | string[] | false;
85
+ };
86
+ }
87
+ ```
88
+
89
+ Default values:
90
+
91
+ - `port`: `3000`
92
+ - `server.apiPrefix`: `"/api"`
93
+ - `server.cors`: `false`
94
+
95
+ ## API Routes
96
+
97
+ Any file in `server/routes/` that default-exports an Express router is auto-mounted at:
98
+
99
+ `<apiPrefix>/<path-to-file>`
100
+
101
+ Examples:
102
+
103
+ - `server/routes/users.ts` -> `/api/users`
104
+ - `server/routes/auth/me.ts` -> `/api/auth/me`
105
+ - `server/routes/user/profile.ts` -> `/api/user/profile`
106
+ - `server/routes/try/get.ts` -> `/api/try/get`
107
+ - `server/routes/auth/index.ts` -> `/api/auth`
108
+
109
+ ## Environment Variables
110
+
111
+ `template/.env` includes:
112
+
113
+ ```env
114
+ PORT=3000
115
+ NODE_ENV=development
116
+ ```
117
+
118
+ `PORT` overrides the port in `stoix.config.ts`.
119
+
120
+ ## Development and Production Flow
121
+
122
+ - Development: Express runs first, then mounts Vite as middleware for client HMR.
123
+ - Production: Express serves static files from `dist/client` and handles SPA fallback to `index.html`.
124
+
125
+ ## Framework Development (this repo)
126
+
127
+ From this repository:
128
+
129
+ ```bash
130
+ npm run build
131
+ ```
132
+
133
+ `prepack` runs:
134
+
135
+ ```bash
136
+ npm run clean && npm run build
137
+ ```
138
+
139
+ This removes template build artifacts (`template/node_modules`, `template/dist`, `template/.vite`) before packaging.
140
+
141
+ ## Current Limitations
142
+
143
+ - Route modules are expected to `export default` an Express router.
144
+
145
+ ## License
146
+
147
+ MIT
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env node
2
+ import { execSync } from 'node:child_process';
3
+ import fs from 'fs-extra';
4
+ import path from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+ import chalk from 'chalk';
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = path.dirname(__filename);
9
+ const STOIX_VERSION = fs.readJsonSync(path.resolve(__dirname, '..', '..', 'package.json')).version || '0.1.0';
10
+ const args = process.argv.slice(2);
11
+ const command = args[0];
12
+ const projectName = args[1];
13
+ function printBanner() {
14
+ console.log(chalk.cyan(`
15
+ ===================================
16
+ Stoix v${STOIX_VERSION}
17
+ Node + Express + React + Vite
18
+ ===================================
19
+ `));
20
+ }
21
+ function printUsage() {
22
+ printBanner();
23
+ console.log(`${chalk.bold('Usage:')}
24
+ npx stoix create <project-name>
25
+
26
+ ${chalk.bold('Commands:')}
27
+ create <name> Scaffold a new Stoix project
28
+
29
+ ${chalk.bold('Examples:')}
30
+ npx stoix create my-app
31
+ npx stoix create blog-api
32
+ `);
33
+ }
34
+ function validateProjectName(name) {
35
+ const validPattern = /^[a-zA-Z][a-zA-Z0-9._-]*$/;
36
+ return validPattern.test(name);
37
+ }
38
+ async function createProject(name) {
39
+ const targetDir = path.resolve(process.cwd(), name);
40
+ if (fs.existsSync(targetDir)) {
41
+ console.error(chalk.red(`\n Error: Directory "${name}" already exists.\n`));
42
+ process.exit(1);
43
+ }
44
+ printBanner();
45
+ console.log(chalk.cyan(` Creating Stoix project: ${chalk.bold(name)}\n`));
46
+ // Resolve template directory (relative to compiled dist/bin/index.js -> ../../template)
47
+ const templateDir = path.resolve(__dirname, '..', '..', 'template');
48
+ if (!fs.existsSync(templateDir)) {
49
+ console.error(chalk.red(' Error: Template directory not found.'));
50
+ console.error(chalk.dim(` Expected at: ${templateDir}`));
51
+ process.exit(1);
52
+ }
53
+ fs.copySync(templateDir, targetDir, { overwrite: false });
54
+ console.log(chalk.green(' + Project files created'));
55
+ const gitignoreSrc = path.join(targetDir, 'gitignore');
56
+ const gitignoreDest = path.join(targetDir, '.gitignore');
57
+ if (fs.existsSync(gitignoreSrc)) {
58
+ fs.renameSync(gitignoreSrc, gitignoreDest);
59
+ }
60
+ const pkgPath = path.join(targetDir, 'package.json');
61
+ const pkg = fs.readJsonSync(pkgPath);
62
+ pkg.name = name;
63
+ fs.writeJsonSync(pkgPath, pkg, { spaces: 2 });
64
+ console.log(chalk.green(' + package.json configured'));
65
+ console.log(chalk.cyan('\n Installing dependencies...\n'));
66
+ let dependenciesInstalled = true;
67
+ try {
68
+ execSync('npm install', {
69
+ cwd: targetDir,
70
+ stdio: 'inherit',
71
+ });
72
+ }
73
+ catch {
74
+ dependenciesInstalled = false;
75
+ console.error(chalk.yellow('\n Warning: npm install failed. Run it manually.'));
76
+ }
77
+ const statusLine = dependenciesInstalled
78
+ ? chalk.green.bold(' + Stoix project is ready!')
79
+ : chalk.yellow.bold(' ! Stoix project files are ready (dependencies not installed)');
80
+ const installStep = dependenciesInstalled ? '' : ` ${chalk.cyan('npm install')}\n`;
81
+ console.log(`
82
+ ${statusLine}
83
+
84
+ ${chalk.bold(' Next steps:')}
85
+ ${chalk.cyan(`cd ${name}`)}
86
+ ${installStep} ${chalk.cyan('npm run dev')}
87
+
88
+ ${chalk.dim(' Stoix app will run at http://localhost:3000')}
89
+ `);
90
+ }
91
+ async function main() {
92
+ if (!command || command === '--help' || command === '-h') {
93
+ printUsage();
94
+ process.exit(0);
95
+ }
96
+ if (command === '--version' || command === '-v') {
97
+ console.log(`stoix v${STOIX_VERSION}`);
98
+ process.exit(0);
99
+ }
100
+ if (command !== 'create') {
101
+ console.error(chalk.red(`\n Unknown command: "${command}"\n`));
102
+ printUsage();
103
+ process.exit(1);
104
+ }
105
+ if (!projectName) {
106
+ console.error(chalk.red('\n Error: Please provide a project name.\n'));
107
+ console.log(chalk.dim(' npx stoix create <project-name>\n'));
108
+ process.exit(1);
109
+ }
110
+ if (!validateProjectName(projectName)) {
111
+ console.error(chalk.red('\n Error: Project name must start with a letter and contain only letters, numbers, hyphens, dots, or underscores.\n'));
112
+ process.exit(1);
113
+ }
114
+ await createProject(projectName);
115
+ }
116
+ main().catch((err) => {
117
+ console.error(chalk.red('\n Error:'), err.message);
118
+ process.exit(1);
119
+ });
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "stoix",
3
+ "version": "0.1.0",
4
+ "description": "Stoix — A Node + Express + React framework with Vite, fully written in TypeScript",
5
+ "type": "module",
6
+ "bin": {
7
+ "stoix": "dist/bin/index.js"
8
+ },
9
+ "scripts": {
10
+ "clean": "node -e \"const fs=require('fs');['template/node_modules','template/dist','template/.vite'].forEach(d=>{if(fs.existsSync(d)){fs.rmSync(d,{recursive:true,force:true});console.log('removed',d)}})\"",
11
+ "build": "tsc",
12
+ "prepack": "npm run clean && npm run build"
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "template",
17
+ "!template/node_modules",
18
+ "!template/dist",
19
+ "!template/.vite"
20
+ ],
21
+ "keywords": [
22
+ "stoix",
23
+ "react",
24
+ "express",
25
+ "vite",
26
+ "typescript",
27
+ "framework",
28
+ "cli",
29
+ "scaffolding"
30
+ ],
31
+ "author": "Patrick",
32
+ "engines": {
33
+ "node": ">=18"
34
+ },
35
+ "license": "MIT",
36
+ "dependencies": {
37
+ "chalk": "^5.3.0",
38
+ "fs-extra": "^11.2.0"
39
+ },
40
+ "devDependencies": {
41
+ "@types/fs-extra": "^11.0.4",
42
+ "@types/node": "^20.11.0",
43
+ "typescript": "^5.3.3"
44
+ }
45
+ }
package/template/.env ADDED
@@ -0,0 +1,2 @@
1
+ PORT=3000
2
+ NODE_ENV=development
@@ -0,0 +1,2 @@
1
+ PORT=3000
2
+ NODE_ENV=development
@@ -0,0 +1,6 @@
1
+ node_modules/
2
+ dist/
3
+ *.tsbuildinfo
4
+ .DS_Store
5
+ .env
6
+ .env.local
@@ -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="/favicon.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>Stoix App</title>
8
+ </head>
9
+ <body>
10
+ <div id="root"></div>
11
+ <script type="module" src="/src/main.tsx"></script>
12
+ </body>
13
+ </html>