create-laju-app 1.0.15 → 1.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 (3) hide show
  1. package/README.md +106 -266
  2. package/bin/cli.js +174 -53
  3. package/package.json +22 -8
package/README.md CHANGED
@@ -1,309 +1,149 @@
1
1
  # Laju
2
2
 
3
- A high-performance TypeScript web framework combining HyperExpress, Svelte 5, and Inertia.js for building modern full-stack applications. Features server-side rendering, real-time capabilities, and seamless client-server state management.
3
+ **High-performance TypeScript web framework** - 11x faster than Express.js
4
4
 
5
- Visit [laju.dev](https://laju.dev)
5
+ Build modern full-stack applications with HyperExpress, Svelte 5, and Inertia.js.
6
6
 
7
- ## Features
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
+ [![Node.js Version](https://img.shields.io/badge/node-20--22-brightgreen)](https://nodejs.org)
9
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue?logo=typescript)](https://www.typescriptlang.org/)
10
+ [![GitHub stars](https://img.shields.io/github/stars/maulanashalihin/laju?style=social)](https://github.com/maulanashalihin/laju)
8
11
 
9
- - Fast server-side rendering with HyperExpress
10
- - Modern frontend with Svelte 5
11
- - TypeScript support for better type safety
12
- - Inertia.js integration for seamless client-server communication
13
- - Built-in authentication system
14
- - SQLite database with Knex query builder
15
- - Email support with Nodemailer
16
- - Google APIs integration
17
- - Redis caching support
18
- - Asset bundling with Vite
19
- - TailwindCSS for styling
12
+ ## 🚀 Quick Start
20
13
 
21
- ## Prerequisites
22
-
23
- - Node.js (Latest LTS version recommended)
24
- - npm or yarn
25
- - Redis server (optional, for caching)
26
-
27
- ## Installation
28
-
29
- Run the following command
30
14
  ```bash
31
- npx create-laju-app project-name
32
- ```
33
- ## Development
15
+ # Create new project
16
+ npx create-laju-app my-project
17
+ cd my-project
34
18
 
35
- To start the development server:
19
+ # Setup database
20
+ cp .env.example .env
21
+ npx knex migrate:latest
36
22
 
37
- ```bash
23
+ # Start development
38
24
  npm run dev
39
25
  ```
40
26
 
41
- This will:
42
- - Start the Vite development server for frontend assets
43
- - Run the backend server with nodemon for auto-reloading
44
-
45
- ## Building for Production
46
-
47
- To build the application for production:
48
-
49
- ```bash
50
- npm run build
51
- ```
52
-
53
- This command will:
54
- - Clean the build directory
55
- - Build frontend assets with Vite
56
- - Compile TypeScript files
57
- - Copy necessary files to the build directory
58
-
59
- ## Project Structure
60
-
61
- - `/app` - Core application files
62
- - `/middlewares` - Custom middleware functions
63
- - `/services` - Service layer implementations
64
- - `/controllers` - Application controllers
65
- - `/resources` - Frontend resources
66
- - `/views` - Svelte components and views
67
- - `/js` - JavaScript assets and modules
68
- - `/routes` - Route definitions
69
- - `/migrations` - Database migrations
70
- - `/public` - Static files
71
- - `/dist` - Compiled assets (generated)
72
- - `/build` - Production build output
73
-
74
- ## Key Dependencies
75
-
76
- ### Backend
77
- - HyperExpress - High-performance web server
78
- - Knex - SQL query builder
79
- - SQLite3 - Database
80
- - Nodemailer - Email sending
81
- - Redis - Caching (optional)
82
-
83
- ### Frontend
84
- - Svelte 5 - UI framework
85
- - Inertia.js - Client-server communication
86
- - TailwindCSS - Utility-first CSS framework
87
- - Vite - Build tool and dev server
88
-
89
- ## Scripts
90
-
91
- - `npm run dev` - Start development server
92
- - `npm run build` - Build for production
93
-
94
- ## Contributing
95
-
96
- 1. Fork the repository
97
- 2. Create your feature branch
98
- 3. Commit your changes
99
- 4. Push to the branch
100
- 5. Create a new Pull Request
101
-
102
- ## License
103
-
104
- ISC License
105
-
106
- ## Tutorial: Building Your First App
27
+ Visit `http://localhost:5555`
107
28
 
108
- This tutorial will guide you through building a simple application using this framework.
29
+ ## Features
109
30
 
110
- ### 1. Setting Up a New Route and Controller
31
+ ### Performance First
32
+ - **258,611 req/sec** - HyperExpress server (11x faster than Express)
33
+ - **19.9x faster writes** - SQLite with WAL mode
34
+ - **Zero-config caching** - Database cache included (optional Redis)
111
35
 
112
- First, let's create a new route and controller for a blog post feature.
36
+ ### Modern Stack
37
+ - **Svelte 5** - Reactive UI with runes
38
+ - **Inertia.js** - SPA without client-side routing
39
+ - **TailwindCSS 4** - Utility-first CSS with Vite
40
+ - **TypeScript** - Full type safety
113
41
 
114
- 1. Create a new controller file `app/controllers/PostController.ts`:
42
+ ### Built-in Services
43
+ - **Authentication** - Sessions, OAuth (Google), password reset
44
+ - **Storage** - S3/Wasabi with presigned URLs
45
+ - **Email** - Nodemailer (SMTP) or Resend (API)
46
+ - **Caching** - Database cache or Redis
47
+ - **Templates** - Eta for SSR
115
48
 
116
- ```typescript
117
- import { Request, Response } from "../../type";
118
- import DB from "../services/DB";
49
+ ## 📊 Performance
119
50
 
120
- class Controller {
121
- public async index(request: Request, response: Response) {
122
- const posts = await DB.from("posts");
123
- return response.inertia("posts/index", { posts });
124
- }
51
+ | Framework | Requests/sec | Comparison |
52
+ |-----------|--------------|------------|
53
+ | **Laju** | **258,611** | Baseline |
54
+ | Pure Node.js | 124,024 | 2x slower |
55
+ | Express.js | 22,590 | 11x slower |
56
+ | Laravel | 80 | 3,232x slower |
125
57
 
126
- public async create(request: Request, response: Response) {
127
- return response.inertia("posts/create");
128
- }
58
+ *Benchmark: Simple JSON response on same hardware*
129
59
 
130
- public async store(request: Request, response: Response) {
131
- const { title, content } = request.body;
132
-
133
- await DB.table("posts").insert({
134
- title,
135
- content,
136
- created_at: Date.now(),
137
- updated_at: Date.now()
138
- });
60
+ ## 📚 Documentation
139
61
 
140
- return response.redirect("/posts");
141
- }
142
- }
62
+ **[Complete Documentation →](https://github.com/maulanashalihin/laju/tree/main/docs)**
143
63
 
144
- export default new Controller();
145
- ```
146
-
147
- 2. Add routes in `routes/web.ts`:
148
-
149
- ```typescript
150
- import PostController from "../app/controllers/PostController";
151
-
152
- // Add these routes with your existing routes
153
- Route.get("/posts", PostController.index);
154
- Route.get("/posts/create", PostController.create);
155
- Route.post("/posts", PostController.store);
156
- ```
64
+ Documentation is organized for progressive learning from beginner to advanced.
157
65
 
158
- ### 2. Creating the Database Migration
66
+ ### Getting Started
67
+ - [Introduction](https://github.com/maulanashalihin/laju/blob/main/docs/01-INTRODUCTION.md) - Framework overview, quick start
68
+ - [Project Structure](https://github.com/maulanashalihin/laju/blob/main/docs/02-PROJECT-STRUCTURE.md) - Directory layout
69
+ - [Database](https://github.com/maulanashalihin/laju/blob/main/docs/03-DATABASE.md) - Knex.js + SQLite
159
70
 
160
- Create a migration for the posts table:
71
+ ### Core Features
72
+ - [Routing & Controllers](https://github.com/maulanashalihin/laju/blob/main/docs/04-ROUTING-CONTROLLERS.md) - Handle requests
73
+ - [Frontend (Svelte 5)](https://github.com/maulanashalihin/laju/blob/main/docs/05-FRONTEND-SVELTE.md) - Build reactive UI
74
+ - [Authentication](https://github.com/maulanashalihin/laju/blob/main/docs/06-AUTHENTICATION.md) - Sessions + OAuth
75
+ - [Middleware](https://github.com/maulanashalihin/laju/blob/main/docs/07-MIDDLEWARE.md) - Auth, rate limiting
76
+ - [Validation](https://github.com/maulanashalihin/laju/blob/main/docs/08-VALIDATION.md) - Input validation
77
+ - [Email](https://github.com/maulanashalihin/laju/blob/main/docs/09-EMAIL.md) - Send emails
161
78
 
162
- ```bash
163
- npx knex migrate:make create_posts_table
164
- ```
165
-
166
- In the generated migration file:
79
+ ### Advanced Features
80
+ - [Storage (S3)](https://github.com/maulanashalihin/laju/blob/main/docs/10-STORAGE.md) - File uploads
81
+ - [Caching](https://github.com/maulanashalihin/laju/blob/main/docs/11-CACHING.md) - Redis + Database cache
82
+ - [Background Jobs](https://github.com/maulanashalihin/laju/blob/main/docs/12-BACKGROUND-JOBS.md) - Cron jobs, Scheduling
83
+ - [CSRF Protection](https://github.com/maulanashalihin/laju/blob/main/docs/13-CSRF.md) - Security
84
+ - [Translation](https://github.com/maulanashalihin/laju/blob/main/docs/14-TRANSLATION.md) - Multi-language
167
85
 
168
- ```typescript
169
- import { Knex } from "knex";
86
+ ### Production
87
+ - [Best Practices](https://github.com/maulanashalihin/laju/blob/main/docs/16-BEST-PRACTICES.md) - Code quality
88
+ - [Security Guide](https://github.com/maulanashalihin/laju/blob/main/docs/17-SECURITY.md) - Secure your app
89
+ - [Testing](https://github.com/maulanashalihin/laju/blob/main/docs/19-TESTING.md) - Unit + Integration tests
90
+ - [Deployment](https://github.com/maulanashalihin/laju/blob/main/docs/20-DEPLOYMENT.md) - Production setup
170
91
 
171
- export async function up(knex: Knex): Promise<void> {
172
- await knex.schema.createTable('posts', function (table) {
173
- table.increments('id').primary();
174
- table.string('title').notNullable();
175
- table.text('content').notNullable();
176
- table.bigInteger('created_at');
177
- table.bigInteger('updated_at');
178
- });
179
- }
180
-
181
- export async function down(knex: Knex): Promise<void> {
182
- await knex.schema.dropTable('posts');
183
- }
184
- ```
185
-
186
- Run the migration:
187
-
188
- ```bash
189
- npx knex migrate:latest
190
- ```
92
+ ## Project Structure
191
93
 
192
- ### 3. Creating Svelte Components
193
-
194
- 1. Create `resources/views/posts/index.svelte`:
195
-
196
- ```svelte
197
- <script>
198
- export let posts = [];
199
- </script>
200
-
201
- <div class="max-w-4xl mx-auto p-4">
202
- <div class="flex justify-between items-center mb-6">
203
- <h1 class="text-2xl font-bold">Blog Posts</h1>
204
- <a
205
- href="/posts/create"
206
- class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"
207
- >
208
- Create Post
209
- </a>
210
- </div>
211
-
212
- <div class="space-y-4">
213
- {#each posts as post}
214
- <div class="border p-4 rounded">
215
- <h2 class="text-xl font-semibold">{post.title}</h2>
216
- <p class="mt-2 text-gray-600">{post.content}</p>
217
- </div>
218
- {/each}
219
- </div>
220
- </div>
221
94
  ```
222
-
223
- 2. Create `resources/views/posts/create.svelte`:
224
-
225
- ```svelte
226
- <script>
227
- import { router } from '@inertiajs/svelte';
228
-
229
- let form = {
230
- title: '',
231
- content: ''
232
- };
233
-
234
- function handleSubmit() {
235
- router.post('/posts', form);
236
- }
237
- </script>
238
-
239
- <div class="max-w-4xl mx-auto p-4">
240
- <h1 class="text-2xl font-bold mb-6">Create New Post</h1>
241
-
242
- <form on:submit|preventDefault={handleSubmit} class="space-y-4">
243
- <div>
244
- <label class="block text-sm font-medium mb-1">Title</label>
245
- <input
246
- type="text"
247
- bind:value={form.title}
248
- class="w-full px-3 py-2 border rounded"
249
- />
250
- </div>
251
-
252
- <div>
253
- <label class="block text-sm font-medium mb-1">Content</label>
254
- <textarea
255
- bind:value={form.content}
256
- class="w-full px-3 py-2 border rounded h-32"
257
- ></textarea>
258
- </div>
259
-
260
- <div>
261
- <button
262
- type="submit"
263
- class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"
264
- >
265
- Create Post
266
- </button>
267
- </div>
268
- </form>
269
- </div>
95
+ app/
96
+ ├── controllers/ # Request handlers
97
+ ├── middlewares/ # Auth, rate limiting
98
+ ├── services/ # DB, Mailer, Storage
99
+ └── validators/ # Input validation
100
+
101
+ resources/
102
+ ├── js/
103
+ │ ├── Pages/ # Svelte/Inertia pages
104
+ │ ├── Components/ # Reusable components
105
+ │ └── index.css # TailwindCSS 4
106
+ └── views/ # Eta templates
107
+
108
+ routes/ # Route definitions
109
+ migrations/ # Database migrations
270
110
  ```
271
111
 
272
- ### 4. Testing Your Application
112
+ ## Commands
273
113
 
274
- 1. Start the development server:
275
114
  ```bash
276
- npm run dev
115
+ npm run dev # Development
116
+ npm run build # Production build
117
+ node laju make:controller UserController # Generate controller
118
+ npx knex migrate:make create_posts # Create migration
119
+ npx knex migrate:latest # Run migrations
277
120
  ```
278
121
 
279
- 2. Visit `http://localhost:5555/posts` in your browser
280
- 3. Try creating a new post using the form
281
- 4. View the list of posts on the index page
122
+ ## Tech Stack
282
123
 
283
- ### Key Concepts
124
+ | Layer | Technology |
125
+ |-------|------------|
126
+ | Server | HyperExpress |
127
+ | Database | BetterSQLite3 + Knex |
128
+ | Frontend | Svelte 5 + Inertia.js |
129
+ | Styling | TailwindCSS 4 |
130
+ | Build | Vite |
131
+ | Templates | Eta |
284
132
 
285
- 1. **Routing**: Routes are defined in `routes/web.ts` using the HyperExpress router
286
- 2. **Controllers**: Handle business logic and return Inertia responses
287
- 3. **Database**: Use Knex.js for database operations and migrations
288
- 4. **Frontend**: Svelte components with Inertia.js for seamless page transitions
289
- 5. **Styling**: TailwindCSS for utility-first styling
133
+ ## Author
290
134
 
291
- ### Best Practices
135
+ **Maulana Shalihin** - [maulana@drip.id](mailto:maulana@drip.id)
292
136
 
293
- 1. **File Organization**
294
- - Keep controllers in `app/controllers`
295
- - Place Svelte components in `resources/views`
296
- - Database migrations in `migrations`
137
+ - [tapsite.ai](https://tapsite.ai) - AI website builder
138
+ - [dripsender.id](https://dripsender.id) - Email marketing
139
+ - [laju.dev](https://laju.dev) - This framework
297
140
 
298
- 2. **Code Structure**
299
- - Use TypeScript types for better type safety
300
- - Keep controllers focused on single responsibilities
301
- - Use Inertia.js for state management between server and client
141
+ ## Support
302
142
 
303
- 3. **Database**
304
- - Always use migrations for database changes
305
- - Use the Query Builder for complex queries
306
- - Include timestamps for tracking record changes
143
+ - Star this repository
144
+ - [Become a Sponsor](https://github.com/sponsors/maulanashalihin)
145
+ - Report bugs via [GitHub Issues](https://github.com/maulanashalihin/laju/issues)
307
146
 
308
- Need help with anything specific? Feel free to ask!
147
+ ## License
309
148
 
149
+ MIT License
package/bin/cli.js CHANGED
@@ -7,22 +7,99 @@ const path = require('path');
7
7
  const fs = require('fs');
8
8
  const { execSync } = require('child_process');
9
9
 
10
- const ASCII_ART = ` -
11
- :+===+ =+
12
- ++++++++++++++
13
- =++++= =+++
14
- +++= +++=
15
- ++= +++++
16
- ++ ++++++ +
17
- == =++++++++++++ -=
18
- = =++++++++++++ ++
19
- = ++++++ ++
20
- - =++++ =+=
21
- =++++ +++
22
- =++= -+++=
23
- ++++++++++++++=
24
- ++=+++++++++=
25
- == `;
10
+ function detectAvailablePackageManagers() {
11
+ const { execSync } = require('child_process');
12
+ const packageManagers = ['bun', 'yarn', 'npm'];
13
+ const available = [];
14
+
15
+ for (const pm of packageManagers) {
16
+ try {
17
+ execSync(`${pm} --version`, { stdio: 'ignore' });
18
+ available.push(pm);
19
+ } catch (e) {
20
+ continue;
21
+ }
22
+ }
23
+ return available.length > 0 ? available : ['npm'];
24
+ }
25
+
26
+ async function selectPackageManager(available) {
27
+ if (available.length === 1) {
28
+ return available[0];
29
+ }
30
+
31
+ console.log('');
32
+ console.log('\x1b[36m Which package manager would you like to use?\x1b[0m');
33
+
34
+ const response = await prompts({
35
+ type: 'select',
36
+ name: 'packageManager',
37
+ message: '',
38
+ choices: available.map(pm => ({
39
+ title: pm === 'npm' ? 'npm (stable ✓)' : pm === 'yarn' ? 'yarn (fast ✓)' : 'bun (experimental ⚠️)',
40
+ value: pm
41
+ }))
42
+ });
43
+
44
+ const selected = response.packageManager || 'npm';
45
+
46
+ if (selected === 'bun') {
47
+ console.log('\x1b[90m Note: Bun is experimental. If you encounter issues, try npm or yarn.\x1b[0m');
48
+ console.log('');
49
+ }
50
+
51
+ return selected;
52
+ }
53
+
54
+ function getInstallCommand(packageManager) {
55
+ switch (packageManager) {
56
+ case 'bun':
57
+ return 'bun install';
58
+ case 'yarn':
59
+ return 'yarn';
60
+ case 'npm':
61
+ default:
62
+ return 'npm install';
63
+ }
64
+ }
65
+
66
+ function getRunCommand(packageManager) {
67
+ switch (packageManager) {
68
+ case 'bun':
69
+ return 'bun run';
70
+ case 'yarn':
71
+ return 'yarn';
72
+ case 'npm':
73
+ default:
74
+ return 'npm run';
75
+ }
76
+ }
77
+
78
+ const ASCII_ART = `
79
+ \x1b[38;5;208m
80
+ ++++++++++++++++++
81
+ +++++++++++++++++++
82
+ +++++++++++++++++++
83
+ +++++++++++++++++++
84
+ +++++++++++++++++++
85
+ ++++++++++++++++++++
86
+ +++++++++++++++++++
87
+ +++++++++++++++++++
88
+ +++++++++++++++++++
89
+ +++++++++++++++++++
90
+ +++++++++++++++++++
91
+
92
+ +++++++++++++++++++++++++++++++++
93
+ ++++++++++++++++++++++++++++++++++
94
+ +++++++++++++++++++++++++++++++++
95
+ ++++++++++++++++++++++++++++++++++
96
+ ++++++++++++++++++++++++++++++++++
97
+ ++++++++++++++++++++++++++++++++++
98
+ +++++++++++++++++++++++++++++++++
99
+ +++++++++++++++++++++++++++++++++
100
+ ++++++++++++++++++++++++++++++++
101
+ \x1b[0m
102
+ `;
26
103
 
27
104
  program
28
105
  .name('create-laju-app')
@@ -31,22 +108,48 @@ program
31
108
 
32
109
  program
33
110
  .argument('[project-directory]', 'Project directory name')
34
- .action(async (projectDirectory) => {
111
+ .option('--package-manager <pm>', 'Package manager to use (npm, yarn, bun)')
112
+ .action(async (projectDirectory, options) => {
35
113
  try {
36
- console.log(ASCII_ART); // Tambahkan ini
37
- console.log('\n'); // Tambah baris kosong setelah ASCII art
114
+ console.log('');
115
+ console.log(ASCII_ART);
116
+ console.log('\x1b[36m Create a new project with Laju Framework\x1b[0m');
117
+ console.log('');
118
+
119
+ let packageManager;
120
+ if (options.packageManager) {
121
+ packageManager = options.packageManager;
122
+ if (!['npm', 'yarn', 'bun'].includes(packageManager)) {
123
+ console.log('\x1b[1;31m✖\x1b[0m \x1b[1;91mError:\x1b[0m Invalid package manager. Use npm, yarn, or bun.');
124
+ process.exit(1);
125
+ }
126
+ } else {
127
+ const availablePackageManagers = detectAvailablePackageManagers();
128
+ packageManager = await selectPackageManager(availablePackageManagers);
129
+ }
130
+ console.log('\x1b[36m Using ' + packageManager + '\x1b[0m');
131
+ console.log('');
132
+
38
133
  // If no project name, ask user
39
134
  if (!projectDirectory) {
135
+ console.log('\x1b[36m Project name:\x1b[0m');
40
136
  const response = await prompts({
41
137
  type: 'text',
42
138
  name: 'projectDirectory',
43
- message: 'Enter project name:'
139
+ message: ''
44
140
  });
45
141
  projectDirectory = response.projectDirectory;
46
142
  }
47
143
 
48
144
  if (!projectDirectory) {
49
- console.log('Project name is required to continue.');
145
+ console.log('\x1b[1;31m✖\x1b[0m \x1b[1;91mError:\x1b[0m Project name is required to continue.');
146
+ process.exit(1);
147
+ }
148
+
149
+ // Validate project name (npm package name rules)
150
+ const nameRegex = /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
151
+ if (!nameRegex.test(projectDirectory)) {
152
+ console.log('\x1b[1;31m✖\x1b[0m \x1b[1;91mError:\x1b[0m Invalid project name. Use lowercase letters, numbers, and hyphens only.');
50
153
  process.exit(1);
51
154
  }
52
155
 
@@ -54,15 +157,17 @@ program
54
157
 
55
158
  // Check if directory exists
56
159
  if (fs.existsSync(targetPath)) {
57
- console.log(`Directory ${projectDirectory} already exists. Choose another name.`);
160
+ console.log('\x1b[1;31m✖\x1b[0m \x1b[1;91mError:\x1b[0m Directory \x1b[36m' + projectDirectory + '\x1b[0m already exists. Choose another name.');
58
161
  process.exit(1);
59
162
  }
60
163
 
61
- console.log(`Creating a new project in ${targetPath}...`);
164
+ console.log('');
165
+ console.log('\x1b[90m Creating project at \x1b[36m' + targetPath + '\x1b[0m');
166
+ console.log('');
62
167
 
63
168
  // Clone template from GitHub
64
169
  const emitter = degit('maulanashalihin/laju');
65
-
170
+
66
171
  await emitter.clone(targetPath);
67
172
 
68
173
  // Read package.json from template
@@ -72,6 +177,18 @@ program
72
177
  // Update project name in package.json
73
178
  packageJson.name = projectDirectory;
74
179
 
180
+ // Update scripts for Windows before writing package.json
181
+ if (process.platform === 'win32') {
182
+ packageJson.scripts = {
183
+ "dev": "cls && if exist dist rmdir /s /q dist && if exist build rmdir /s /q build && npx concurrently \"vite\" \"timeout /t 1 >nul && npx nodemon --config nodemon.json\"",
184
+ "build": "if exist build rmdir /s /q build && vite build && tsc && tsc-alias -p tsconfig.json && if not exist dist\\views mkdir dist\\views && xcopy /s /e /i resources\\views dist\\views",
185
+ "refresh": "if exist data rmdir /s /q data && npx knex migrate:latest",
186
+ "test:ui": "npx vitest --ui",
187
+ "test:run": "npx vitest run",
188
+ "test:coverage": "npx vitest run --coverage"
189
+ };
190
+ }
191
+
75
192
  // Write back package.json
76
193
  fs.writeFileSync(
77
194
  packageJsonPath,
@@ -79,41 +196,45 @@ program
79
196
  );
80
197
 
81
198
  // Change directory and run setup commands
199
+ const originalDir = process.cwd();
82
200
  process.chdir(targetPath);
83
- console.log('📦 Installing dependencies...');
84
- execSync('npm install', { stdio: 'inherit' });
85
- console.log('📝 Copying environment file...');
86
-
87
- execSync(process.platform === 'win32' ? 'copy .env.example .env' : 'cp .env.example .env', { stdio: 'inherit' });
88
- console.log('🔄 Running migrations...');
89
- execSync('npx knex migrate:latest', { stdio: 'inherit' });
90
- // Update scripts in package.json for Windows
91
- if (process.platform === 'win32') {
92
- packageJson.scripts = {
93
- "dev": "cls && npx concurrently \"vite\" \"npx nodemon\"",
94
- "build": "if exist build rmdir /s /q build && vite build && tsc && xcopy /s /e /i dist build && xcopy /s /e /i public build"
95
- };
96
-
97
- // Write updated package.json
98
- fs.writeFileSync(
99
- packageJsonPath,
100
- JSON.stringify(packageJson, null, 2)
101
- );
102
- }
103
-
104
- console.log('🎉 Project created successfully!');
201
+
202
+ try {
203
+ console.log('\x1b[36m Installing dependencies...\x1b[0m');
204
+ console.log('');
205
+ execSync(getInstallCommand(packageManager), { stdio: 'inherit', timeout: 300000 });
206
+ console.log('\x1b[32m ✓ Dependencies installed\x1b[0m');
207
+ console.log('');
208
+
209
+ console.log('\x1b[36m Setting up environment...\x1b[0m');
210
+ execSync(process.platform === 'win32' ? 'copy .env.example .env' : 'cp .env.example .env', { stdio: 'inherit', timeout: 10000 });
211
+ console.log('\x1b[32m ✓ Environment configured\x1b[0m');
212
+ console.log('');
213
+
214
+ console.log('\x1b[36m Preparing database...\x1b[0m');
215
+ execSync('npx knex migrate:latest', { stdio: 'inherit', timeout: 60000 });
216
+ console.log('\x1b[32m ✓ Database ready\x1b[0m');
217
+ } finally {
218
+ process.chdir(originalDir);
219
+ }
220
+
105
221
  console.log('');
106
- console.log('🚀 Your project is ready! You can now start developing.');
107
-
222
+ console.log('\x1b[1;36m ✓ Project created successfully!\x1b[0m');
108
223
  console.log('');
109
- console.log('👉 Next steps:');
110
- console.log('1. 📁 cd ' + projectDirectory);
111
- console.log('2. 🔥 run "npm run dev" to start the development server.');
112
- console.log('3. 💻 enjoy coding !!!.');
224
+ console.log('\x1b[90m Next steps:\x1b[0m');
113
225
  console.log('');
114
-
226
+ console.log(' cd ' + projectDirectory);
227
+ console.log(' ' + getRunCommand(packageManager) + ' dev');
228
+ console.log('');
229
+ console.log('\x1b[90m Learn more: https://laju.dev\x1b[0m');
230
+ console.log('\x1b[90m Docs: https://github.com/maulanashalihin/laju/tree/main/docs\x1b[0m');
231
+ console.log('');
232
+
115
233
  } catch (error) {
116
234
  console.error('Error:', error.message);
235
+ if (process.env.DEBUG) {
236
+ console.error(error.stack);
237
+ }
117
238
  process.exit(1);
118
239
  }
119
240
  });
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "create-laju-app",
3
- "version": "1.0.15",
3
+ "version": "1.1.2",
4
+ "description": "CLI tool to scaffold new Laju framework projects",
4
5
  "keywords": [
5
6
  "laju",
6
7
  "svelte",
@@ -9,20 +10,33 @@
9
10
  "sqlite",
10
11
  "boilerplate",
11
12
  "template",
12
- "generator"
13
+ "generator",
14
+ "cli"
13
15
  ],
16
+ "author": "Maulana Shalihin <maulana@drip.id>",
17
+ "license": "MIT",
18
+ "homepage": "https://laju.dev",
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/arghoritma/create-laju-app.git"
22
+ },
23
+ "bugs": {
24
+ "url": "https://github.com/maulanashalihin/laju/issues"
25
+ },
26
+ "engines": {
27
+ "node": ">=20.0.0"
28
+ },
14
29
  "bin": {
15
30
  "create-laju-app": "./bin/cli.js"
16
31
  },
32
+ "files": [
33
+ "bin",
34
+ "README.md",
35
+ "LICENSE"
36
+ ],
17
37
  "dependencies": {
18
- "child_process": "^1.0.2",
19
38
  "commander": "^11.0.0",
20
39
  "degit": "^2.8.4",
21
40
  "prompts": "^2.4.2"
22
- },
23
- "homepage": "https://laju.dev",
24
- "repository": {
25
- "type": "git",
26
- "url": "git+https://github.com/maulanashalihin/laju.git"
27
41
  }
28
42
  }