create-next-java 1.0.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.
Files changed (2) hide show
  1. package/bin/index.js +304 -0
  2. package/package.json +21 -0
package/bin/index.js ADDED
@@ -0,0 +1,304 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+
6
+ const banner = `
7
+ _ _ _ _
8
+ | \\ | | | | | |
9
+ | \\| | _____ _| |_ | | __ ___ ____ _
10
+ | . \` |/ _ \\ \\/ / __| _ | |/ _\` \\ \\ / / _\` |
11
+ | |\\ | __/> <| |_ | |__| | (_| |\\ V / (_| |
12
+ |_| \\_|\\___/_/\\_\\\\__| \\____/ \\__,_| \\_/ \\__,_|
13
+
14
+ šŸš€ Next.java Project Generator (v1.0.0)
15
+ `;
16
+
17
+ console.log(banner);
18
+
19
+ const args = process.argv.slice(2);
20
+ const projectName = args[0] || 'my-nextjava-app';
21
+ const targetDir = path.resolve(process.cwd(), projectName);
22
+
23
+ if (fs.existsSync(targetDir)) {
24
+ console.error(`āŒ Directory '${projectName}' already exists. Please choose another name or empty the directory.`);
25
+ process.exit(1);
26
+ }
27
+
28
+ console.log(`Creating a new Next.java full-stack application in ${targetDir}...\n`);
29
+
30
+ // Create directory tree
31
+ const dirs = [
32
+ 'app',
33
+ 'app/api/health',
34
+ 'components',
35
+ 'middleware',
36
+ 'models',
37
+ 'database/migrations',
38
+ 'database/seed',
39
+ 'jobs',
40
+ 'test',
41
+ 'wasm'
42
+ ];
43
+
44
+ dirs.forEach(d => fs.mkdirSync(path.join(targetDir, d), { recursive: true }));
45
+
46
+ // 1. app/layout.java
47
+ fs.writeFileSync(path.join(targetDir, 'app', 'layout.java'), `package app;
48
+
49
+ import com.nextjava.ui.Layout;
50
+ import com.nextjava.ui.UI;
51
+ import static com.nextjava.ui.Components.*;
52
+
53
+ public class layout implements Layout {
54
+ @Override
55
+ public UI render(UI children) {
56
+ return Html(
57
+ Head(
58
+ Title("Next.java App"),
59
+ Meta("viewport", "width=device-width, initial-scale=1")
60
+ ),
61
+ Body(
62
+ Navbar(
63
+ Heading(2, "Next.java").style("color: #0070f3;"),
64
+ Div(Link("/", "Home"))
65
+ ),
66
+ Main(children),
67
+ Footer(Paragraph("Powered by Next.java v1.0"))
68
+ )
69
+ );
70
+ }
71
+ }
72
+ `);
73
+
74
+ // 2. app/page.java & app/page.jsx (In-Process React SSR)
75
+ fs.writeFileSync(path.join(targetDir, 'app', 'page.java'), `package app;
76
+
77
+ import com.nextjava.ui.Page;
78
+ import com.nextjava.ui.UI;
79
+ import static com.nextjava.ui.Components.*;
80
+
81
+ public class page implements Page {
82
+ @Override
83
+ public UI render() {
84
+ return Column(
85
+ Heading(1, "Welcome to Next.java šŸš€"),
86
+ Paragraph("The Full-Stack Java Framework with in-process React SSR and Virtual Threads.")
87
+ );
88
+ }
89
+ }
90
+ `);
91
+
92
+ fs.writeFileSync(path.join(targetDir, 'app', 'page.jsx'), `export default function HomePage({ title }) {
93
+ return (
94
+ <section style={{ padding: '2rem 0' }}>
95
+ <h1>Welcome to Next.java šŸš€</h1>
96
+ <p>The Full-Stack Java Framework with in-process React SSR and Virtual Threads.</p>
97
+ </section>
98
+ );
99
+ }
100
+ `);
101
+
102
+ // 3. app/api/health/route.java
103
+ fs.writeFileSync(path.join(targetDir, 'app', 'api', 'health', 'route.java'), `package app.api.health;
104
+
105
+ import com.nextjava.http.Response;
106
+ import com.nextjava.observability.HealthIndicator;
107
+ import com.nextjava.server.annotation.GET;
108
+
109
+ public class route {
110
+ @GET
111
+ public Response checkHealth() {
112
+ return Response.json(HealthIndicator.toJson());
113
+ }
114
+ }
115
+ `);
116
+
117
+ // 4. middleware/middleware.java
118
+ fs.writeFileSync(path.join(targetDir, 'middleware', 'middleware.java'), `package middleware;
119
+
120
+ import com.nextjava.http.Request;
121
+ import com.nextjava.http.Response;
122
+
123
+ public class middleware {
124
+ public Response handle(Request request) {
125
+ return null; // Proceed to route handler
126
+ }
127
+ }
128
+ `);
129
+
130
+ // 5. models/Product.java
131
+ fs.writeFileSync(path.join(targetDir, 'models', 'Product.java'), `package models;
132
+
133
+ import com.nextjava.data.annotation.Entity;
134
+ import com.nextjava.data.annotation.Id;
135
+ import com.nextjava.data.annotation.Table;
136
+
137
+ @Entity
138
+ @Table(name = "products")
139
+ public record Product(
140
+ @Id String id,
141
+ String name,
142
+ double price
143
+ ) {}
144
+ `);
145
+
146
+ // 6. database/migrations/001_init.sql & database/seed/seed.sql
147
+ fs.writeFileSync(path.join(targetDir, 'database', 'migrations', '001_init.sql'), `-- Initial Migration
148
+ CREATE TABLE IF NOT EXISTS products (
149
+ id VARCHAR(64) PRIMARY KEY,
150
+ name VARCHAR(255) NOT NULL,
151
+ price DOUBLE NOT NULL,
152
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
153
+ );
154
+ `);
155
+
156
+ fs.writeFileSync(path.join(targetDir, 'database', 'seed', 'seed.sql'), `-- Seed Data
157
+ INSERT INTO products (id, name, price) VALUES ('p1', 'Enterprise Server License', 499.00);
158
+ INSERT INTO products (id, name, price) VALUES ('p2', 'Developer Toolkit', 99.00);
159
+ `);
160
+
161
+ // 7. jobs/MetricsJob.java
162
+ fs.writeFileSync(path.join(targetDir, 'jobs', 'MetricsJob.java'), `package jobs;
163
+
164
+ import com.nextjava.jobs.annotation.Scheduled;
165
+
166
+ public class MetricsJob {
167
+ @Scheduled(fixedRate = 30000, initialDelay = 5000)
168
+ public void reportSystemMetrics() {
169
+ // Runs on Java 21 Virtual Threads
170
+ }
171
+ }
172
+ `);
173
+
174
+ // 8. test/AppTest.java
175
+ fs.writeFileSync(path.join(targetDir, 'test', 'AppTest.java'), `package test;
176
+
177
+ import com.nextjava.testing.TestClient;
178
+ import com.nextjava.testing.annotation.NextTest;
179
+ import com.nextjava.testing.annotation.Test;
180
+
181
+ @NextTest("Application Health Suite")
182
+ public class AppTest {
183
+ private final TestClient client = new TestClient("http://localhost:3000");
184
+
185
+ @Test("Health probe is UP")
186
+ public void testHealth() {
187
+ client.get("/api/health")
188
+ .expectStatus(200)
189
+ .expectBodyContains("UP");
190
+ }
191
+ }
192
+ `);
193
+
194
+ // 9. nextjava.config.java
195
+ fs.writeFileSync(path.join(targetDir, 'nextjava.config.java'), `import com.nextjava.core.Config;
196
+
197
+ class NextConfigSetup {
198
+ public static Config configure() {
199
+ return new Config()
200
+ .appName("${projectName}")
201
+ .port(3000)
202
+ .set("jsEngine", "AUTO");
203
+ }
204
+ }
205
+ `);
206
+
207
+ // 10. Dockerfile & docker-compose.yml
208
+ fs.writeFileSync(path.join(targetDir, 'Dockerfile'), `# Next.java Production Multi-Stage Dockerfile
209
+ FROM eclipse-temurin:21-jdk-jammy AS builder
210
+ WORKDIR /app
211
+ COPY . .
212
+ RUN java -jar /usr/local/bin/nextjava.jar build || true
213
+
214
+ FROM eclipse-temurin:21-jre-jammy
215
+ WORKDIR /app
216
+ COPY --from=builder /app/dist/app.jar ./app.jar
217
+ COPY --from=builder /app/.env ./.env
218
+
219
+ ENV PORT=3000
220
+ ENV ENVIRONMENT=production
221
+ EXPOSE 3000
222
+
223
+ ENTRYPOINT ["java", "-XX:+UseZGC", "-XX:+ZGenerational", "-Dfile.encoding=UTF-8", "-jar", "app.jar"]
224
+ `);
225
+
226
+ fs.writeFileSync(path.join(targetDir, 'docker-compose.yml'), `version: '3.8'
227
+ services:
228
+ app:
229
+ build: .
230
+ ports:
231
+ - "3000:3000"
232
+ environment:
233
+ - ENVIRONMENT=production
234
+ - PORT=3000
235
+ restart: always
236
+ `);
237
+
238
+ // 11. package.json, .gitignore, .env, README.md
239
+ fs.writeFileSync(path.join(targetDir, 'package.json'), JSON.stringify({
240
+ name: projectName,
241
+ version: '1.0.0',
242
+ private: true,
243
+ scripts: {
244
+ dev: 'nextjava dev',
245
+ build: 'nextjava build',
246
+ start: 'nextjava start',
247
+ test: 'nextjava test'
248
+ },
249
+ dependencies: {
250
+ nextjava: '^1.0.0',
251
+ react: '^18.2.0',
252
+ 'react-dom': '^18.2.0'
253
+ }
254
+ }, null, 2));
255
+
256
+ fs.writeFileSync(path.join(targetDir, '.gitignore'), `target/
257
+ dist/
258
+ .nextjava/
259
+ *.class
260
+ *.log
261
+ .env.local
262
+ node_modules/
263
+ `);
264
+
265
+ fs.writeFileSync(path.join(targetDir, '.env'), `PORT=3000
266
+ ENVIRONMENT=development
267
+ DATABASE_URL=jdbc:sqlite:./data.db
268
+ SECRET_KEY=nextjava_super_secret_development_key_32_bytes!
269
+ `);
270
+
271
+ fs.writeFileSync(path.join(targetDir, 'README.md'), `# ${projectName}
272
+
273
+ Created with [Next.java](https://nextjava.dev) — The Full-Stack Java Framework.
274
+
275
+ ## šŸš€ Quick Start
276
+
277
+ \`\`\`bash
278
+ # 1. Start development server with live hot-reload
279
+ nextjava dev
280
+
281
+ # 2. Run automated test suites
282
+ nextjava test
283
+
284
+ # 3. Apply database migrations
285
+ nextjava db migrate
286
+
287
+ # 4. Build for production
288
+ nextjava build
289
+ \`\`\`
290
+ `);
291
+
292
+ console.log(`\nšŸ“¦ Installing dependencies (react, react-dom, nextjava)...`);
293
+ import { execSync } from 'child_process';
294
+ try {
295
+ execSync('npm install', { cwd: targetDir, stdio: 'inherit' });
296
+ } catch (e) {
297
+ console.warn(`āš ļø npm install failed. Please run it manually inside the directory.`);
298
+ }
299
+
300
+ console.log(`šŸŽ‰ Successfully initialized Next.java project in '${projectName}'!`);
301
+ console.log(`\nNext steps:`);
302
+ console.log(` 1. cd ${projectName}`);
303
+ console.log(` 2. npm run dev`);
304
+ console.log(`\nHappy coding with Next.java! ā˜•āœØ\n`);
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "create-next-java",
3
+ "version": "1.0.0",
4
+ "description": "Interactive CLI starter to create modern full-stack Next.java applications",
5
+ "bin": {
6
+ "create-next-java": "./bin/index.js"
7
+ },
8
+ "type": "module",
9
+ "keywords": [
10
+ "nextjava",
11
+ "java",
12
+ "react",
13
+ "full-stack",
14
+ "framework",
15
+ "ssr",
16
+ "wasm",
17
+ "virtual-threads"
18
+ ],
19
+ "author": "Next.java Team",
20
+ "license": "Apache-2.0"
21
+ }