create-gardener 2.0.5 โ 2.0.7
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 +187 -0
- package/package.json +1 -1
- package/template/buildHelper.js +5 -4
- package/template/buildHelper.test.js +78 -0
- package/template/jest.config.js +13 -0
- package/template/package.json +4 -1
- package/template/pnpm-lock.yaml +2761 -17
- package/template/src/frontend/static/gardener.test.js +364 -0
- package/template/src/frontend/static/gardenerDev.js +3 -6
- /package/{Readme.md โ Readme.deprecated.md} +0 -0
package/README.md
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# Gardener Web Application Template
|
|
2
|
+
|
|
3
|
+
A modern full-stack web application template created with **create-gardener**. This project provides a production-ready setup with TypeScript, Express.js backend, EJS templating, and Tailwind CSS for styling.
|
|
4
|
+
|
|
5
|
+
## ๐ Features
|
|
6
|
+
|
|
7
|
+
- **TypeScript Backend** - Type-safe Express.js server with modern ES modules
|
|
8
|
+
- **EJS Templating** - Server-side rendering with EJS view engine
|
|
9
|
+
- **Tailwind CSS** - Utility-first CSS framework with JIT compilation
|
|
10
|
+
- **Hot Reload Development** - Live reload for both backend and frontend during development
|
|
11
|
+
- **Production Ready** - Optimized build process with minification
|
|
12
|
+
- **Testing Setup** - Jest configuration for unit and integration tests
|
|
13
|
+
- **Image Processing** - Sharp integration for image optimization
|
|
14
|
+
- **Validation** - Zod schema validation
|
|
15
|
+
- **Environment Configuration** - dotenv support for environment variables
|
|
16
|
+
|
|
17
|
+
## ๐ Prerequisites
|
|
18
|
+
|
|
19
|
+
- Node.js (v18 or higher recommended)
|
|
20
|
+
- pnpm (preferred) or npm
|
|
21
|
+
|
|
22
|
+
## ๐ ๏ธ Installation
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Install dependencies
|
|
26
|
+
pnpm install
|
|
27
|
+
# or
|
|
28
|
+
npm install
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## ๐ Getting Started
|
|
32
|
+
|
|
33
|
+
### Development Mode
|
|
34
|
+
|
|
35
|
+
Start the development server with hot reload:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pnpm dev
|
|
39
|
+
# or
|
|
40
|
+
npm run dev
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
This will:
|
|
44
|
+
- Start the TypeScript backend server with watch mode on port 3000 (or PORT from .env)
|
|
45
|
+
- Run Tailwind CSS in watch mode for live style updates
|
|
46
|
+
|
|
47
|
+
### Production Build
|
|
48
|
+
|
|
49
|
+
Build the application for production:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pnpm build
|
|
53
|
+
# or
|
|
54
|
+
npm run build
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
This will:
|
|
58
|
+
1. Compile and minify Tailwind CSS
|
|
59
|
+
2. Transpile TypeScript to JavaScript
|
|
60
|
+
3. Copy frontend assets to the build directory
|
|
61
|
+
4. Generate production configuration
|
|
62
|
+
|
|
63
|
+
### Start Production Server
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
pnpm start
|
|
67
|
+
# or
|
|
68
|
+
npm start
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Runs the compiled production build from the `build` directory.
|
|
72
|
+
|
|
73
|
+
** Refer to docs.md for full docs **
|
|
74
|
+
|
|
75
|
+
## ๐งช Testing
|
|
76
|
+
|
|
77
|
+
Run tests with Jest:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
pnpm test
|
|
81
|
+
# or
|
|
82
|
+
npm test
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## ๐ Project Structure
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
.
|
|
89
|
+
โโโ src/
|
|
90
|
+
โ โโโ backend/ # Backend TypeScript code
|
|
91
|
+
โ โ โโโ controllers/ # Route controllers
|
|
92
|
+
โ โ โโโ routes/ # Express routes
|
|
93
|
+
โ โ โโโ libs/ # Utility libraries
|
|
94
|
+
โ โ โโโ server.ts # Main server file
|
|
95
|
+
โ โโโ frontend/ # Frontend assets
|
|
96
|
+
โ โโโ views/ # EJS templates
|
|
97
|
+
โ โโโ static/ # Static files (CSS, JS, images)
|
|
98
|
+
โ โโโ assets/ # Source assets
|
|
99
|
+
โ โโโ template/ # Frontend templates
|
|
100
|
+
โ โโโ tailwind.css # Tailwind source file
|
|
101
|
+
โโโ build/ # Production build output
|
|
102
|
+
โโโ buildHelper.js # Build utility script
|
|
103
|
+
โโโ jest.config.js # Jest configuration
|
|
104
|
+
โโโ tsconfig.json # TypeScript configuration
|
|
105
|
+
โโโ package.json # Project dependencies
|
|
106
|
+
โโโ .env # Environment variables
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## โ๏ธ Configuration
|
|
110
|
+
|
|
111
|
+
### Environment Variables
|
|
112
|
+
|
|
113
|
+
Create a `.env` file in the root directory:
|
|
114
|
+
|
|
115
|
+
```env
|
|
116
|
+
PORT=3000
|
|
117
|
+
NODE_ENV=development
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### TypeScript
|
|
121
|
+
|
|
122
|
+
The project uses strict TypeScript configuration with:
|
|
123
|
+
- ES modules (`"module": "nodenext"`)
|
|
124
|
+
- Strict type checking
|
|
125
|
+
- Source maps for debugging
|
|
126
|
+
- Declaration files generation
|
|
127
|
+
|
|
128
|
+
### Tailwind CSS
|
|
129
|
+
|
|
130
|
+
Tailwind CSS v4 is configured with:
|
|
131
|
+
- JIT (Just-In-Time) compilation
|
|
132
|
+
- Minification in production builds
|
|
133
|
+
- Custom styles in `src/frontend/tailwind.css`
|
|
134
|
+
|
|
135
|
+
## ๐ฆ Dependencies
|
|
136
|
+
|
|
137
|
+
### Production
|
|
138
|
+
- **express** - Fast, minimalist web framework
|
|
139
|
+
- **ejs** - Embedded JavaScript templating
|
|
140
|
+
- **tailwindcss** - Utility-first CSS framework
|
|
141
|
+
- **sharp** - High-performance image processing
|
|
142
|
+
- **zod** - TypeScript-first schema validation
|
|
143
|
+
- **dotenv** - Environment variable management
|
|
144
|
+
|
|
145
|
+
### Development
|
|
146
|
+
- **typescript** - TypeScript compiler
|
|
147
|
+
- **tsx** - TypeScript execution and REPL
|
|
148
|
+
- **jest** - Testing framework
|
|
149
|
+
- **concurrently** - Run multiple commands concurrently
|
|
150
|
+
- **cross-env** - Cross-platform environment variables
|
|
151
|
+
|
|
152
|
+
## ๐ง Build Process
|
|
153
|
+
|
|
154
|
+
The `buildHelper.js` script handles:
|
|
155
|
+
1. Copying frontend files to the build directory
|
|
156
|
+
2. Generating production configuration (`gardenerConfig.js`)
|
|
157
|
+
3. Cleaning up unnecessary template files
|
|
158
|
+
|
|
159
|
+
## ๐ Scripts
|
|
160
|
+
|
|
161
|
+
| Script | Description |
|
|
162
|
+
|--------|-------------|
|
|
163
|
+
| `pnpm dev` | Start development server with hot reload |
|
|
164
|
+
| `pnpm build` | Build for production |
|
|
165
|
+
| `pnpm start` | Start production server |
|
|
166
|
+
| `pnpm test` | Run Jest tests |
|
|
167
|
+
|
|
168
|
+
## ๐ค Contributing
|
|
169
|
+
|
|
170
|
+
This is a template project created by create-gardener. Feel free to modify it according to your needs.
|
|
171
|
+
|
|
172
|
+
## ๐ License
|
|
173
|
+
|
|
174
|
+
MIT
|
|
175
|
+
|
|
176
|
+
## ๐ค Author
|
|
177
|
+
|
|
178
|
+
ritishDas
|
|
179
|
+
|
|
180
|
+
## ๐ Links
|
|
181
|
+
|
|
182
|
+
- [Gardener Homepage](https://gardener.ritish.site)
|
|
183
|
+
- [GitHub Repository](https://github.com/ritishDas/gardener)
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
Created with [create-gardener](https://www.npmjs.com/package/create-gardener) ๐ฑ
|
package/package.json
CHANGED
package/template/buildHelper.js
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import fs from 'fs/promises';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
|
|
4
|
-
async function buildHelper() {
|
|
4
|
+
export default async function buildHelper() {
|
|
5
5
|
const src = path.resolve('src', 'frontend');
|
|
6
6
|
const dest = path.resolve('build', 'frontend');
|
|
7
7
|
|
|
8
8
|
await fs.cp(src, dest, { recursive: true });
|
|
9
9
|
|
|
10
|
-
await fs.writeFile(path.join(dest, 'static', 'gardenerConfig.js'), "export const
|
|
11
|
-
mode = 'prod'; ", 'utf8');
|
|
10
|
+
await fs.writeFile(path.join(dest, 'static', 'gardenerConfig.js'), "export const mode = 'prod'; ", 'utf8');
|
|
12
11
|
|
|
13
12
|
await fs.rm(path.join(dest, 'template'), { recursive: true });
|
|
14
13
|
|
|
15
14
|
}
|
|
16
15
|
|
|
17
|
-
|
|
16
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
17
|
+
buildHelper();
|
|
18
|
+
}
|
|
18
19
|
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { jest } from '@jest/globals';
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
5
|
+
jest.mock('fs/promises');
|
|
6
|
+
|
|
7
|
+
describe('buildHelper', () => {
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
jest.clearAllMocks();
|
|
10
|
+
|
|
11
|
+
fs.cp = jest.fn().mockResolvedValue(undefined);
|
|
12
|
+
fs.writeFile = jest.fn().mockResolvedValue(undefined);
|
|
13
|
+
fs.rm = jest.fn().mockResolvedValue(undefined);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test('copies frontend directory', async () => {
|
|
17
|
+
const { default: buildHelper } = await import('./buildHelper.js');
|
|
18
|
+
await buildHelper();
|
|
19
|
+
|
|
20
|
+
expect(fs.cp).toHaveBeenCalledWith(
|
|
21
|
+
path.resolve('src', 'frontend'),
|
|
22
|
+
path.resolve('build', 'frontend'),
|
|
23
|
+
{ recursive: true }
|
|
24
|
+
);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test('writes gardenerConfig.js', async () => {
|
|
28
|
+
const { default: buildHelper } = await import('./buildHelper.js');
|
|
29
|
+
await buildHelper();
|
|
30
|
+
|
|
31
|
+
expect(fs.writeFile).toHaveBeenCalledWith(
|
|
32
|
+
path.join(path.resolve('build', 'frontend'), 'static', 'gardenerConfig.js'),
|
|
33
|
+
"export const mode = 'prod'; ",
|
|
34
|
+
'utf8'
|
|
35
|
+
);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test('removes template directory', async () => {
|
|
39
|
+
const { default: buildHelper } = await import('./buildHelper.js');
|
|
40
|
+
await buildHelper();
|
|
41
|
+
|
|
42
|
+
expect(fs.rm).toHaveBeenCalledWith(
|
|
43
|
+
path.join(path.resolve('build', 'frontend'), 'template'),
|
|
44
|
+
{ recursive: true }
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('runs operations in correct order', async () => {
|
|
49
|
+
const operations = [];
|
|
50
|
+
|
|
51
|
+
fs.cp.mockImplementation(async () => operations.push('cp'));
|
|
52
|
+
fs.writeFile.mockImplementation(async () => operations.push('writeFile'));
|
|
53
|
+
fs.rm.mockImplementation(async () => operations.push('rm'));
|
|
54
|
+
|
|
55
|
+
const { default: buildHelper } = await import('./buildHelper.js');
|
|
56
|
+
await buildHelper();
|
|
57
|
+
|
|
58
|
+
expect(operations).toEqual(['cp', 'writeFile', 'rm']);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test('fails early if copy fails', async () => {
|
|
62
|
+
fs.cp.mockRejectedValue(new Error('Copy failed'));
|
|
63
|
+
|
|
64
|
+
const { default: buildHelper } = await import('./buildHelper.js');
|
|
65
|
+
|
|
66
|
+
await expect(buildHelper()).rejects.toThrow('Copy failed');
|
|
67
|
+
expect(fs.writeFile).not.toHaveBeenCalled();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test('fails if write fails and skips rm', async () => {
|
|
71
|
+
fs.writeFile.mockRejectedValue(new Error('Write failed'));
|
|
72
|
+
|
|
73
|
+
const { default: buildHelper } = await import('./buildHelper.js');
|
|
74
|
+
|
|
75
|
+
await expect(buildHelper()).rejects.toThrow('Write failed');
|
|
76
|
+
expect(fs.rm).not.toHaveBeenCalled();
|
|
77
|
+
});
|
|
78
|
+
});
|
package/template/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"start": "cross-env NODE_ENV=production node build/backend/server.js",
|
|
8
8
|
"dev": "concurrently \"cross-env NODE_ENV=development tsx watch src/backend/server.ts\" \"tailwindcss -w -i src/frontend/tailwind.css -o src/frontend/static/style.css\"",
|
|
9
9
|
"build": "tailwindcss -i src/frontend/tailwind.css -o src/frontend/static/style.css --minify && tsc && node buildHelper.js",
|
|
10
|
-
"test": "
|
|
10
|
+
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js"
|
|
11
11
|
},
|
|
12
12
|
"keywords": [],
|
|
13
13
|
"author": "ritishDas",
|
|
@@ -21,11 +21,14 @@
|
|
|
21
21
|
"zod": "^4.3.6"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
+
"@jest/globals": "^30.3.0",
|
|
24
25
|
"@types/ejs": "^3.1.5",
|
|
25
26
|
"@types/express": "^5.0.6",
|
|
26
27
|
"@types/node": "^25.0.2",
|
|
27
28
|
"concurrently": "^9.2.1",
|
|
28
29
|
"cross-env": "^10.1.0",
|
|
30
|
+
"jest": "^30.3.0",
|
|
31
|
+
"jest-environment-jsdom": "^30.3.0",
|
|
29
32
|
"tailwindcss": "^4.1.18",
|
|
30
33
|
"tsx": "^4.21.0",
|
|
31
34
|
"typescript": "^5.9.3"
|