agent-workflow-kit-cli 1.3.4 → 1.3.6

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 (50) hide show
  1. package/README.md +158 -9
  2. package/dist/cli/commands/create.js +162 -0
  3. package/dist/cli/commands/ui.js +192 -0
  4. package/dist/cli/index.js +29 -1
  5. package/package.json +4 -2
  6. package/templates/react-ts/project/.gitignore.hbs +24 -0
  7. package/templates/react-ts/project/eslint.config.js.hbs +34 -0
  8. package/templates/react-ts/project/index.html.hbs +17 -0
  9. package/templates/react-ts/project/package.json.hbs +28 -0
  10. package/templates/react-ts/project/src/App.tsx.hbs +60 -0
  11. package/templates/react-ts/project/src/components/Counter.tsx.hbs +16 -0
  12. package/templates/react-ts/project/src/components/ThemeToggle.tsx.hbs +29 -0
  13. package/templates/react-ts/project/src/hooks/useLocalStorage.ts.hbs +25 -0
  14. package/templates/react-ts/project/src/main.tsx.hbs +10 -0
  15. package/templates/react-ts/project/src/services/api.ts.hbs +16 -0
  16. package/templates/react-ts/project/src/styles/App.css.hbs +143 -0
  17. package/templates/react-ts/project/src/styles/index.css.hbs +34 -0
  18. package/templates/react-ts/project/src/vite-env.d.ts.hbs +1 -0
  19. package/templates/react-ts/project/tsconfig.app.json.hbs +26 -0
  20. package/templates/react-ts/project/tsconfig.json.hbs +7 -0
  21. package/templates/react-ts/project/tsconfig.node.json.hbs +24 -0
  22. package/templates/react-ts/project/vite.config.ts.hbs +7 -0
  23. package/templates/spring-boot/project/.gitignore.hbs +28 -0
  24. package/templates/spring-boot/project/pom.xml.hbs +69 -0
  25. package/templates/spring-boot/project/src/main/java/com/example/packageName/DemoApplication.java.hbs +13 -0
  26. package/templates/spring-boot/project/src/main/java/com/example/packageName/controller/UserController.java.hbs +37 -0
  27. package/templates/spring-boot/project/src/main/java/com/example/packageName/dto/UserDTO.java.hbs +16 -0
  28. package/templates/spring-boot/project/src/main/java/com/example/packageName/entity/User.java.hbs +27 -0
  29. package/templates/spring-boot/project/src/main/java/com/example/packageName/repository/UserRepository.java.hbs +9 -0
  30. package/templates/spring-boot/project/src/main/java/com/example/packageName/service/UserService.java.hbs +11 -0
  31. package/templates/spring-boot/project/src/main/java/com/example/packageName/service/impl/UserServiceImpl.java.hbs +55 -0
  32. package/templates/spring-boot/project/src/main/resources/application.yml.hbs +20 -0
  33. package/templates/spring-boot/project/src/test/java/com/example/packageName/DemoApplicationTests.java.hbs +13 -0
  34. package/ui-dist/assets/Antigravity-IRHfUNd0.webp +0 -0
  35. package/ui-dist/assets/Codex-B3jt494H.png +0 -0
  36. package/ui-dist/assets/Logo-DARneFJW.png +0 -0
  37. package/ui-dist/assets/ReactTS-Cv7D5v-r.png +0 -0
  38. package/ui-dist/assets/devops-DfKGji1l.png +0 -0
  39. package/ui-dist/assets/drawio-D1K35acK.png +0 -0
  40. package/ui-dist/assets/expressjs-cjiJ1MIq.png +0 -0
  41. package/ui-dist/assets/fastapi-x75ez5Tf.png +0 -0
  42. package/ui-dist/assets/golang-DWpOzDNa.png +0 -0
  43. package/ui-dist/assets/index-BhHU4Khx.js +372 -0
  44. package/ui-dist/assets/index-C0BHmZv8.css +1 -0
  45. package/ui-dist/assets/nestjs-CZk_FY6t.png +0 -0
  46. package/ui-dist/assets/nextjs-DIQjv1J3.png +0 -0
  47. package/ui-dist/assets/python-CfV_cs4B.png +0 -0
  48. package/ui-dist/assets/rust-A_NnBwqP.png +0 -0
  49. package/ui-dist/assets/springbootjava--7jHXzq_.jpg +0 -0
  50. package/ui-dist/index.html +47 -0
@@ -0,0 +1,34 @@
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/eslint-plugin'
6
+ import tsparser from '@typescript-eslint/parser'
7
+
8
+ export default [
9
+ { ignores: ['dist'] },
10
+ {
11
+ files: ['**/*.{ts,tsx}'],
12
+ languageOptions: {
13
+ ecmaVersion: 2020,
14
+ globals: globals.browser,
15
+ parser: tsparser,
16
+ parserOptions: {
17
+ project: ['./tsconfig.app.json', './tsconfig.node.json'],
18
+ },
19
+ },
20
+ plugins: {
21
+ 'react-hooks': reactHooks,
22
+ 'react-refresh': reactRefresh,
23
+ '@typescript-eslint': tseslint,
24
+ },
25
+ rules: {
26
+ ...js.configs.recommended.rules,
27
+ ...tseslint.configs.recommended.rules,
28
+ 'react-refresh/only-export-components': [
29
+ 'warn',
30
+ { allowConstantExport: true },
31
+ ],
32
+ },
33
+ },
34
+ ]
@@ -0,0 +1,17 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>⚛️</text></svg>" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>{{projectName}}</title>
8
+ <!-- Modern Outfit typography from Google Fonts -->
9
+ <link rel="preconnect" href="https://fonts.googleapis.com">
10
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
+ <link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;600;800&display=swap" rel="stylesheet">
12
+ </head>
13
+ <body>
14
+ <div id="root"></div>
15
+ <script type="module" src="/src/main.tsx"></script>
16
+ </body>
17
+ </html>
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "{{projectName}}",
3
+ "private": true,
4
+ "version": "0.1.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "tsc && vite build",
9
+ "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10
+ "preview": "vite preview"
11
+ },
12
+ "dependencies": {
13
+ "react": "^18.3.1",
14
+ "react-dom": "^18.3.1"
15
+ },
16
+ "devDependencies": {
17
+ "@types/react": "^18.3.12",
18
+ "@types/react-dom": "^18.3.1",
19
+ "@typescript-eslint/eslint-plugin": "^7.15.0",
20
+ "@typescript-eslint/parser": "^7.15.0",
21
+ "@vitejs/plugin-react": "^4.3.4",
22
+ "eslint": "^8.57.0",
23
+ "eslint-plugin-react-hooks": "^4.6.2",
24
+ "eslint-plugin-react-refresh": "^0.4.7",
25
+ "typescript": "^5.5.2",
26
+ "vite": "^5.4.11"
27
+ }
28
+ }
@@ -0,0 +1,60 @@
1
+ import { useEffect, useState } from 'react'
2
+ import { Counter } from './components/Counter'
3
+ import { ThemeToggle } from './components/ThemeToggle'
4
+ import { fetchSystemStatus, SystemStatus } from './services/api'
5
+ import './styles/App.css'
6
+
7
+ function App() {
8
+ const [systemStatus, setSystemStatus] = useState<SystemStatus | null>(null)
9
+ const [loading, setLoading] = useState(true)
10
+
11
+ useEffect(() => {
12
+ fetchSystemStatus()
13
+ .then((status) => {
14
+ setSystemStatus(status)
15
+ setLoading(false)
16
+ })
17
+ .catch((err) => {
18
+ console.error('Failed to load system status:', err)
19
+ setLoading(false)
20
+ })
21
+ }, [])
22
+
23
+ return (
24
+ <div className="container">
25
+ <div className="logo-container">
26
+ <span className="logo react" style={{ fontSize: '4rem', userSelect: 'none' }}>⚛️</span>
27
+ </div>
28
+
29
+ <h1 className="title">{{projectName}}</h1>
30
+ <p className="subtitle">
31
+ Your AI-Ready React, Vite, and TypeScript project generated with Agent Workflow Kit.
32
+ </p>
33
+
34
+ {/* Standalone Interactive Component */}
35
+ <Counter />
36
+
37
+ {/* Component utilizing custom hooks */}
38
+ <ThemeToggle />
39
+
40
+ {/* Service layer display */}
41
+ <div className="api-status-card">
42
+ {loading ? (
43
+ <span>Loading system API status...</span>
44
+ ) : systemStatus ? (
45
+ <div>
46
+ API Status: <span className="status-badge online">{systemStatus.status}</span> (v{systemStatus.version})
47
+ </div>
48
+ ) : (
49
+ <span>API Status: <span className="status-badge" style={{ backgroundColor: 'rgba(239, 68, 68, 0.15)', color: '#f87171' }}>OFFLINE</span></span>
50
+ )}
51
+ </div>
52
+
53
+ <p className="footer">
54
+ Workflow guidelines and skills are configured in the <code>.agents/</code> directory.
55
+ </p>
56
+ </div>
57
+ )
58
+ }
59
+
60
+ export default App
@@ -0,0 +1,16 @@
1
+ import { useState } from 'react'
2
+
3
+ export function Counter() {
4
+ const [count, setCount] = useState(0)
5
+
6
+ return (
7
+ <div className="card">
8
+ <button className="counter-btn" onClick={() => setCount((c) => c + 1)}>
9
+ Count is {count}
10
+ </button>
11
+ <p className="instruction">
12
+ Edit <code>src/components/Counter.tsx</code> to test stateful hot updates.
13
+ </p>
14
+ </div>
15
+ )
16
+ }
@@ -0,0 +1,29 @@
1
+ import { useEffect } from 'react'
2
+ import { useLocalStorage } from '../hooks/useLocalStorage'
3
+
4
+ export function ThemeToggle() {
5
+ const [theme, setTheme] = useLocalStorage<'light' | 'dark'>('theme', 'dark')
6
+
7
+ useEffect(() => {
8
+ document.documentElement.setAttribute('data-theme', theme)
9
+ if (theme === 'light') {
10
+ document.body.style.backgroundColor = '#f8fafc'
11
+ document.body.style.color = '#0f172a'
12
+ } else {
13
+ document.body.style.backgroundColor = '#0b0f19'
14
+ document.body.style.color = '#e2e8f0'
15
+ }
16
+ }, [theme])
17
+
18
+ const toggleTheme = () => {
19
+ setTheme((prev) => (prev === 'light' ? 'dark' : 'light'))
20
+ }
21
+
22
+ return (
23
+ <div className="theme-toggle-container">
24
+ <button className="theme-btn" onClick={toggleTheme}>
25
+ {theme === 'light' ? '🌙 Dark Mode' : '☀️ Light Mode'}
26
+ </button>
27
+ </div>
28
+ )
29
+ }
@@ -0,0 +1,25 @@
1
+ import { useState, Dispatch, SetStateAction } from 'react'
2
+
3
+ export function useLocalStorage<T>(key: string, initialValue: T): [T, Dispatch<SetStateAction<T>>] {
4
+ const [storedValue, setStoredValue] = useState<T>(() => {
5
+ try {
6
+ const item = window.localStorage.getItem(key)
7
+ return item ? JSON.parse(item) : initialValue
8
+ } catch (error) {
9
+ console.warn(`Error reading localStorage key "${key}":`, error)
10
+ return initialValue
11
+ }
12
+ })
13
+
14
+ const setValue: Dispatch<SetStateAction<T>> = (value) => {
15
+ try {
16
+ const valueToStore = value instanceof Function ? value(storedValue) : value
17
+ setStoredValue(valueToStore)
18
+ window.localStorage.setItem(key, JSON.stringify(valueToStore))
19
+ } catch (error) {
20
+ console.warn(`Error setting localStorage key "${key}":`, error)
21
+ }
22
+ }
23
+
24
+ return [storedValue, setValue]
25
+ }
@@ -0,0 +1,10 @@
1
+ import React from 'react'
2
+ import ReactDOM from 'react-dom/client'
3
+ import App from './App.tsx'
4
+ import './styles/index.css'
5
+
6
+ ReactDOM.createRoot(document.getElementById('root')!).render(
7
+ <React.StrictMode>
8
+ <App />
9
+ </React.StrictMode>,
10
+ )
@@ -0,0 +1,16 @@
1
+ export interface SystemStatus {
2
+ status: string;
3
+ version: string;
4
+ uptime: number;
5
+ }
6
+
7
+ export async function fetchSystemStatus(): Promise<SystemStatus> {
8
+ // Mock asynchronous API call delay
9
+ await new Promise((resolve) => setTimeout(resolve, 800));
10
+
11
+ return {
12
+ status: 'ONLINE',
13
+ version: '1.0.0',
14
+ uptime: Math.floor(process.uptime ? process.uptime() : performance.now() / 1000)
15
+ };
16
+ }
@@ -0,0 +1,143 @@
1
+ .container {
2
+ display: flex;
3
+ flex-direction: column;
4
+ align-items: center;
5
+ justify-content: center;
6
+ gap: 1.5rem;
7
+ }
8
+
9
+ .logo-container {
10
+ display: flex;
11
+ gap: 2rem;
12
+ margin-bottom: 0.5rem;
13
+ }
14
+
15
+ .logo {
16
+ font-size: 4rem;
17
+ user-select: none;
18
+ display: inline-block;
19
+ transition: transform 0.3s;
20
+ }
21
+
22
+ .logo:hover {
23
+ transform: scale(1.15) rotate(10deg);
24
+ }
25
+
26
+ .title {
27
+ font-size: 3.2rem;
28
+ line-height: 1.1;
29
+ font-weight: 800;
30
+ margin: 0;
31
+ background: linear-gradient(135deg, #a5b4fc, #6366f1, #ec4899);
32
+ -webkit-background-clip: text;
33
+ -webkit-text-fill-color: transparent;
34
+ background-clip: text;
35
+ text-shadow: 0 4px 20px rgba(99, 102, 241, 0.15);
36
+ }
37
+
38
+ .subtitle {
39
+ font-size: 1.25rem;
40
+ color: #94a3b8;
41
+ max-width: 600px;
42
+ margin: 0 auto;
43
+ }
44
+
45
+ .card {
46
+ padding: 2.5rem;
47
+ background: rgba(30, 41, 59, 0.4);
48
+ border: 1px solid rgba(255, 255, 255, 0.08);
49
+ border-radius: 1.5rem;
50
+ backdrop-filter: blur(16px);
51
+ -webkit-backdrop-filter: blur(16px);
52
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
53
+ transition: border-color 0.3s, box-shadow 0.3s, transform 0.3s;
54
+ max-width: 480px;
55
+ width: 100%;
56
+ box-sizing: border-box;
57
+ }
58
+
59
+ .card:hover {
60
+ border-color: rgba(99, 102, 241, 0.4);
61
+ box-shadow: 0 15px 35px rgba(99, 102, 241, 0.1);
62
+ transform: translateY(-4px);
63
+ }
64
+
65
+ .counter-btn {
66
+ background: linear-gradient(135deg, #4f46e5, #6366f1);
67
+ color: white;
68
+ border: none;
69
+ padding: 0.75rem 2rem;
70
+ font-size: 1rem;
71
+ font-weight: 600;
72
+ border-radius: 9999px;
73
+ cursor: pointer;
74
+ transition: transform 0.2s, box-shadow 0.2s;
75
+ font-family: inherit;
76
+ box-shadow: 0 4px 12px rgba(79, 70, 229, 0.3);
77
+ }
78
+
79
+ .counter-btn:hover {
80
+ transform: scale(1.05);
81
+ box-shadow: 0 6px 16px rgba(79, 70, 229, 0.5);
82
+ }
83
+
84
+ .theme-toggle-container {
85
+ margin-top: 1rem;
86
+ }
87
+
88
+ .theme-btn {
89
+ background: rgba(255, 255, 255, 0.05);
90
+ border: 1px solid rgba(255, 255, 255, 0.1);
91
+ color: inherit;
92
+ padding: 0.5rem 1.25rem;
93
+ border-radius: 0.5rem;
94
+ cursor: pointer;
95
+ transition: background 0.2s, border-color 0.2s;
96
+ font-family: inherit;
97
+ font-size: 0.9rem;
98
+ }
99
+
100
+ .theme-btn:hover {
101
+ background: rgba(255, 255, 255, 0.1);
102
+ border-color: rgba(255, 255, 255, 0.2);
103
+ }
104
+
105
+ .api-status-card {
106
+ margin-top: 1rem;
107
+ font-size: 0.9rem;
108
+ color: #94a3b8;
109
+ }
110
+
111
+ .status-badge {
112
+ display: inline-block;
113
+ padding: 0.25rem 0.75rem;
114
+ border-radius: 9999px;
115
+ font-size: 0.8rem;
116
+ font-weight: bold;
117
+ }
118
+
119
+ .status-badge.online {
120
+ background-color: rgba(34, 197, 94, 0.15);
121
+ color: #4ade80;
122
+ border: 1px solid rgba(34, 197, 94, 0.3);
123
+ }
124
+
125
+ .instruction {
126
+ margin-top: 1.5rem;
127
+ font-size: 0.875rem;
128
+ color: #64748b;
129
+ }
130
+
131
+ .instruction code {
132
+ background: rgba(15, 23, 42, 0.6);
133
+ padding: 0.2rem 0.5rem;
134
+ border-radius: 0.25rem;
135
+ font-family: monospace;
136
+ color: #a5b4fc;
137
+ }
138
+
139
+ .footer {
140
+ font-size: 0.875rem;
141
+ color: #475569;
142
+ margin-top: 2rem;
143
+ }
@@ -0,0 +1,34 @@
1
+ :root {
2
+ font-family: 'Outfit', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
3
+ line-height: 1.5;
4
+ font-weight: 400;
5
+
6
+ color-scheme: dark;
7
+ color: #e2e8f0;
8
+ background-color: #0b0f19;
9
+
10
+ font-synthesis: none;
11
+ text-rendering: optimizeLegibility;
12
+ -webkit-font-smoothing: antialiased;
13
+ -moz-osx-font-smoothing: grayscale;
14
+ }
15
+
16
+ body {
17
+ margin: 0;
18
+ display: flex;
19
+ place-items: center;
20
+ min-width: 320px;
21
+ min-height: 100vh;
22
+ background: radial-gradient(circle at top right, rgba(99, 102, 241, 0.15), transparent 40%),
23
+ radial-gradient(circle at bottom left, rgba(236, 72, 153, 0.12), transparent 40%),
24
+ #070a13;
25
+ transition: background-color 0.3s, color 0.3s;
26
+ }
27
+
28
+ #root {
29
+ max-width: 1280px;
30
+ margin: 0 auto;
31
+ padding: 2rem;
32
+ text-align: center;
33
+ width: 100%;
34
+ }
@@ -0,0 +1 @@
1
+ /// <reference types="vite/client" />
@@ -0,0 +1,26 @@
1
+ {
2
+ "compilerOptions": {
3
+ "composite": true,
4
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
5
+ "target": "ES2020",
6
+ "useDefineForClassFields": true,
7
+ "lib": ["DOM", "DOM.Iterable", "ES2020"],
8
+ "module": "ESNext",
9
+ "skipLibCheck": true,
10
+
11
+ /* Bundler mode */
12
+ "moduleResolution": "bundler",
13
+ "allowImportingTsExtensions": true,
14
+ "resolveJsonModule": true,
15
+ "isolatedModules": true,
16
+ "noEmit": true,
17
+ "jsx": "react-jsx",
18
+
19
+ /* Linting */
20
+ "strict": true,
21
+ "noUnusedLocals": true,
22
+ "noUnusedParameters": true,
23
+ "noFallthroughCasesInSwitch": true
24
+ },
25
+ "include": ["src"]
26
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "files": [],
3
+ "references": [
4
+ { "path": "./tsconfig.app.json" },
5
+ { "path": "./tsconfig.node.json" }
6
+ ]
7
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "compilerOptions": {
3
+ "composite": true,
4
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
5
+ "target": "ES2022",
6
+ "lib": ["ES2022"],
7
+ "module": "ESNext",
8
+ "skipLibCheck": true,
9
+
10
+ /* Bundler mode */
11
+ "moduleResolution": "bundler",
12
+ "allowImportingTsExtensions": true,
13
+ "resolveJsonModule": true,
14
+ "isolatedModules": true,
15
+ "noEmit": true,
16
+
17
+ /* Linting */
18
+ "strict": true,
19
+ "noUnusedLocals": true,
20
+ "noUnusedParameters": true,
21
+ "noFallthroughCasesInSwitch": true
22
+ },
23
+ "include": ["vite.config.ts"]
24
+ }
@@ -0,0 +1,7 @@
1
+ import { defineConfig } from 'vite'
2
+ import react from '@vitejs/plugin-react'
3
+
4
+ // https://vitejs.dev/config/
5
+ export default defineConfig({
6
+ plugins: [react()],
7
+ })
@@ -0,0 +1,28 @@
1
+ target/
2
+ !.mvn/wrapper/maven-wrapper.jar
3
+ !**/src/main/resources/components/
4
+
5
+ ### STS ###
6
+ .apt_generated
7
+ .classpath
8
+ .factorypath
9
+ .project
10
+ .settings
11
+ .springBeans
12
+ .sts4-cache
13
+
14
+ ### IntelliJ IDEA ###
15
+ .idea
16
+ *.iws
17
+ *.iml
18
+ *.ipr
19
+
20
+ ### NetBeans ###
21
+ /nbproject/private/
22
+ /nbbuild/
23
+ /dist/
24
+ /nbdist/
25
+ /.nb-gradle/
26
+
27
+ ### VS Code ###
28
+ .vscode/
@@ -0,0 +1,69 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4
+ <modelVersion>4.0.0</modelVersion>
5
+ <parent>
6
+ <groupId>org.springframework.boot</groupId>
7
+ <artifactId>spring-boot-starter-parent</artifactId>
8
+ <version>3.3.5</version>
9
+ <relativePath/> <!-- lookup parent from repository -->
10
+ </parent>
11
+ <groupId>com.example</groupId>
12
+ <artifactId>{{projectName}}</artifactId>
13
+ <version>0.0.1-SNAPSHOT</version>
14
+ <name>{{projectName}}</name>
15
+ <description>Demo project for Spring Boot and Agent Workflow Kit</description>
16
+ <properties>
17
+ <java.version>17</java.version>
18
+ </properties>
19
+ <dependencies>
20
+ <dependency>
21
+ <groupId>org.springframework.boot</groupId>
22
+ <artifactId>spring-boot-starter-web</artifactId>
23
+ </dependency>
24
+ <dependency>
25
+ <groupId>org.springframework.boot</groupId>
26
+ <artifactId>spring-boot-starter-data-jpa</artifactId>
27
+ </dependency>
28
+ <dependency>
29
+ <groupId>com.h2database</groupId>
30
+ <artifactId>h2</artifactId>
31
+ <scope>runtime</scope>
32
+ </dependency>
33
+
34
+ <dependency>
35
+ <groupId>org.springframework.boot</groupId>
36
+ <artifactId>spring-boot-devtools</artifactId>
37
+ <scope>runtime</scope>
38
+ <optional>true</optional>
39
+ </dependency>
40
+ <dependency>
41
+ <groupId>org.projectlombok</groupId>
42
+ <artifactId>lombok</artifactId>
43
+ <optional>true</optional>
44
+ </dependency>
45
+ <dependency>
46
+ <groupId>org.springframework.boot</groupId>
47
+ <artifactId>spring-boot-starter-test</artifactId>
48
+ <scope>test</scope>
49
+ </dependency>
50
+ </dependencies>
51
+
52
+ <build>
53
+ <plugins>
54
+ <plugin>
55
+ <groupId>org.springframework.boot</groupId>
56
+ <artifactId>spring-boot-maven-plugin</artifactId>
57
+ <configuration>
58
+ <excludes>
59
+ <exclude>
60
+ <groupId>org.projectlombok</groupId>
61
+ <artifactId>lombok</artifactId>
62
+ </exclude>
63
+ </excludes>
64
+ </configuration>
65
+ </plugin>
66
+ </plugins>
67
+ </build>
68
+
69
+ </project>
@@ -0,0 +1,13 @@
1
+ package com.example.{{safePackageName}};
2
+
3
+ import org.springframework.boot.SpringApplication;
4
+ import org.springframework.boot.autoconfigure.SpringBootApplication;
5
+
6
+ @SpringBootApplication
7
+ public class DemoApplication {
8
+
9
+ public static void main(String[] args) {
10
+ SpringApplication.run(DemoApplication.class, args);
11
+ }
12
+
13
+ }
@@ -0,0 +1,37 @@
1
+ package com.example.{{safePackageName}}.controller;
2
+
3
+ import com.example.{{safePackageName}}.dto.UserDTO;
4
+ import com.example.{{safePackageName}}.service.UserService;
5
+ import lombok.RequiredArgsConstructor;
6
+ import org.springframework.http.ResponseEntity;
7
+ import org.springframework.web.bind.annotation.GetMapping;
8
+ import org.springframework.web.bind.annotation.PathVariable;
9
+ import org.springframework.web.bind.annotation.PostMapping;
10
+ import org.springframework.web.bind.annotation.RequestBody;
11
+ import org.springframework.web.bind.annotation.RequestMapping;
12
+ import org.springframework.web.bind.annotation.RestController;
13
+
14
+ import java.util.List;
15
+
16
+ @RestController
17
+ @RequestMapping("/api/users")
18
+ @RequiredArgsConstructor
19
+ public class UserController {
20
+
21
+ private final UserService userService;
22
+
23
+ @GetMapping
24
+ public ResponseEntity<List<UserDTO>> getAllUsers() {
25
+ return ResponseEntity.ok(userService.getAllUsers());
26
+ }
27
+
28
+ @PostMapping
29
+ public ResponseEntity<UserDTO> createUser(@RequestBody UserDTO userDTO) {
30
+ return ResponseEntity.ok(userService.createUser(userDTO));
31
+ }
32
+
33
+ @GetMapping("/{id}")
34
+ public ResponseEntity<UserDTO> getUserById(@PathVariable Long id) {
35
+ return ResponseEntity.ok(userService.getUserById(id));
36
+ }
37
+ }
@@ -0,0 +1,16 @@
1
+ package com.example.{{safePackageName}}.dto;
2
+
3
+ import lombok.AllArgsConstructor;
4
+ import lombok.Builder;
5
+ import lombok.Data;
6
+ import lombok.NoArgsConstructor;
7
+
8
+ @Data
9
+ @Builder
10
+ @NoArgsConstructor
11
+ @AllArgsConstructor
12
+ public class UserDTO {
13
+ private Long id;
14
+ private String name;
15
+ private String email;
16
+ }