@iconsulting-dev/forgekit 1.4.2 → 1.6.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 (55) hide show
  1. package/README.md +26 -13
  2. package/dist/commands/new.d.ts.map +1 -1
  3. package/dist/commands/new.js +44 -6
  4. package/dist/commands/new.js.map +1 -1
  5. package/dist/generators/backend/index.d.ts.map +1 -1
  6. package/dist/generators/backend/index.js +18 -5
  7. package/dist/generators/backend/index.js.map +1 -1
  8. package/dist/generators/ci/index.d.ts.map +1 -1
  9. package/dist/generators/ci/index.js +5 -1
  10. package/dist/generators/ci/index.js.map +1 -1
  11. package/dist/generators/claude-code/index.d.ts.map +1 -1
  12. package/dist/generators/claude-code/index.js +15 -2
  13. package/dist/generators/claude-code/index.js.map +1 -1
  14. package/dist/generators/docker/index.d.ts.map +1 -1
  15. package/dist/generators/docker/index.js +3 -1
  16. package/dist/generators/docker/index.js.map +1 -1
  17. package/dist/generators/fastapi/index.d.ts +3 -0
  18. package/dist/generators/fastapi/index.d.ts.map +1 -0
  19. package/dist/generators/fastapi/index.js +32 -0
  20. package/dist/generators/fastapi/index.js.map +1 -0
  21. package/dist/generators/frontend/index.d.ts.map +1 -1
  22. package/dist/generators/frontend/index.js +62 -1
  23. package/dist/generators/frontend/index.js.map +1 -1
  24. package/dist/generators/root/index.js +1 -1
  25. package/dist/generators/root/index.js.map +1 -1
  26. package/dist/prompts/project.d.ts.map +1 -1
  27. package/dist/prompts/project.js +110 -38
  28. package/dist/prompts/project.js.map +1 -1
  29. package/dist/templates/backend/application.yml.hbs +5 -1
  30. package/dist/templates/backend/pom.xml.hbs +12 -0
  31. package/dist/templates/ci/ci.yml.hbs +25 -1
  32. package/dist/templates/claude-code/CLAUDE.md.hbs +66 -22
  33. package/dist/templates/claude-code/settings.json.hbs +3 -2
  34. package/dist/templates/docker/docker-compose.yml.hbs +11 -0
  35. package/dist/templates/fastapi/Dockerfile.hbs +12 -0
  36. package/dist/templates/fastapi/config.py.hbs +12 -0
  37. package/dist/templates/fastapi/gitignore.hbs +13 -0
  38. package/dist/templates/fastapi/health.py.hbs +8 -0
  39. package/dist/templates/fastapi/main.py.hbs +6 -0
  40. package/dist/templates/fastapi/python-version.hbs +1 -0
  41. package/dist/templates/fastapi/requirements.txt.hbs +5 -0
  42. package/dist/templates/fastapi/test_health.py.hbs +11 -0
  43. package/dist/templates/frontend/app.config.ts.hbs +6 -2
  44. package/dist/templates/frontend/ngrx-app-store.ts.hbs +14 -0
  45. package/dist/templates/frontend/styles.scss.hbs +17 -0
  46. package/dist/types.d.ts +10 -1
  47. package/dist/types.d.ts.map +1 -1
  48. package/dist/utils/template-engine.d.ts.map +1 -1
  49. package/dist/utils/template-engine.js +1 -0
  50. package/dist/utils/template-engine.js.map +1 -1
  51. package/dist/versions.d.ts +3 -1
  52. package/dist/versions.d.ts.map +1 -1
  53. package/dist/versions.js +5 -1
  54. package/dist/versions.js.map +1 -1
  55. package/package.json +1 -1
@@ -1,10 +1,11 @@
1
- import { input, confirm, checkbox } from "@inquirer/prompts";
1
+ import { input, confirm, checkbox, select } from "@inquirer/prompts";
2
2
  import path from "node:path";
3
3
  import { loadConfig } from "../config.js";
4
4
  import { validateProjectName, validateGroupId } from "../utils/validation.js";
5
5
  export async function promptProjectConfig(defaults = {}) {
6
6
  const saved = await loadConfig();
7
7
  const currentDir = path.basename(process.cwd());
8
+ // ── Section 1: Projet ─────────────────────────────────────────────────────
8
9
  const name = defaults.name ??
9
10
  (await input({
10
11
  message: "Nom du projet",
@@ -16,18 +17,25 @@ export async function promptProjectConfig(defaults = {}) {
16
17
  message: "Description",
17
18
  default: "Mon application",
18
19
  }));
19
- const stacks = defaults.backend !== undefined && defaults.frontend !== undefined
20
- ? []
21
- : await checkbox({
22
- message: "Que voulez-vous générer ?",
20
+ // ── Section 2: Stack ──────────────────────────────────────────────────────
21
+ const backendType = defaults.backendType !== undefined
22
+ ? defaults.backendType
23
+ : await select({
24
+ message: "Backend",
23
25
  choices: [
24
- { name: "Backend (Spring Boot)", value: "backend", checked: true },
25
- { name: "Frontend (Angular)", value: "frontend", checked: true },
26
+ { name: "Spring Boot (Java 21)", value: "spring-boot" },
27
+ { name: "FastAPI (Python)", value: "fastapi" },
28
+ { name: "Aucun", value: null },
26
29
  ],
30
+ default: "spring-boot",
27
31
  });
28
- const backend = defaults.backend ?? stacks.includes("backend");
29
- const frontend = defaults.frontend ?? stacks.includes("frontend");
30
- const groupId = backend
32
+ const frontend = defaults.frontend !== undefined
33
+ ? defaults.frontend
34
+ : await confirm({
35
+ message: "Inclure le frontend Angular ?",
36
+ default: true,
37
+ });
38
+ const groupId = backendType === "spring-boot"
31
39
  ? (defaults.groupId ??
32
40
  (await input({
33
41
  message: "Group ID",
@@ -35,42 +43,106 @@ export async function promptProjectConfig(defaults = {}) {
35
43
  validate: validateGroupId,
36
44
  })))
37
45
  : "com.example";
38
- const auth = defaults.auth ??
39
- (backend || frontend
40
- ? await confirm({
41
- message: "Inclure l'authentification (Spring Security + interceptors Angular) ?",
46
+ // ── Section 3: Backend features ───────────────────────────────────────────
47
+ let flyway = defaults.flyway ?? true;
48
+ let openapi = defaults.openapi ?? true;
49
+ let auth = defaults.auth ?? false;
50
+ let mapstruct = defaults.mapstruct ?? true;
51
+ if (backendType === "spring-boot" &&
52
+ defaults.flyway === undefined &&
53
+ defaults.openapi === undefined &&
54
+ defaults.auth === undefined &&
55
+ defaults.mapstruct === undefined) {
56
+ const backendFeatures = await checkbox({
57
+ message: "Fonctionnalités backend",
58
+ choices: [
59
+ { name: "Flyway (migrations SQL)", value: "flyway", checked: true },
60
+ { name: "OpenAPI / Swagger UI", value: "openapi", checked: true },
61
+ { name: "JWT / Spring Security", value: "auth", checked: false },
62
+ { name: "MapStruct (mappers)", value: "mapstruct", checked: true },
63
+ ],
64
+ });
65
+ flyway = backendFeatures.includes("flyway");
66
+ openapi = backendFeatures.includes("openapi");
67
+ auth = backendFeatures.includes("auth");
68
+ mapstruct = backendFeatures.includes("mapstruct");
69
+ }
70
+ // ── Section 4: Frontend features ──────────────────────────────────────────
71
+ let uiFramework = defaults.uiFramework ?? "primeng";
72
+ let primeNGPreset = defaults.primeNGPreset ?? "Aura";
73
+ let ngrx = defaults.ngrx ?? false;
74
+ if (frontend) {
75
+ if (defaults.uiFramework === undefined) {
76
+ uiFramework = await select({
77
+ message: "Framework UI",
78
+ choices: [
79
+ { name: "PrimeNG (recommandé)", value: "primeng" },
80
+ { name: "Tailwind CSS v4", value: "tailwind" },
81
+ { name: "Aucun (minimal)", value: "none" },
82
+ ],
83
+ default: "primeng",
84
+ });
85
+ }
86
+ if (uiFramework === "primeng" && defaults.primeNGPreset === undefined) {
87
+ primeNGPreset = await select({
88
+ message: "Preset PrimeNG",
89
+ choices: [
90
+ { name: "Aura (recommandé)", value: "Aura" },
91
+ { name: "Lara", value: "Lara" },
92
+ { name: "Nora", value: "Nora" },
93
+ ],
94
+ default: "Aura",
95
+ });
96
+ }
97
+ if (defaults.ngrx === undefined) {
98
+ ngrx = await confirm({
99
+ message: "Inclure NgRx SignalStore ?",
42
100
  default: false,
43
- })
44
- : false);
45
- const ci = defaults.ci ??
46
- (await confirm({
47
- message: "Configurer GitHub Actions CI ?",
48
- default: true,
49
- }));
50
- const docker = defaults.docker ??
51
- (await confirm({
52
- message: "Configurer Docker Compose ?",
53
- default: true,
54
- }));
55
- const claudeCode = defaults.claudeCode ??
56
- (await confirm({
57
- message: "Configurer Claude Code ?",
58
- default: true,
59
- }));
60
- const gitInit = defaults.gitInit ??
61
- (await confirm({
62
- message: "Initialiser Git ?",
63
- default: true,
64
- }));
101
+ });
102
+ }
103
+ }
104
+ // ── Section 5: Infrastructure ─────────────────────────────────────────────
105
+ let docker = defaults.docker ?? true;
106
+ let ci = defaults.ci ?? true;
107
+ let claudeCode = defaults.claudeCode ?? true;
108
+ let gitInit = defaults.gitInit ?? true;
109
+ if (defaults.docker === undefined &&
110
+ defaults.ci === undefined &&
111
+ defaults.claudeCode === undefined &&
112
+ defaults.gitInit === undefined) {
113
+ const infra = await checkbox({
114
+ message: "Infrastructure",
115
+ choices: [
116
+ {
117
+ name: "Docker Compose (PostgreSQL + pgAdmin)",
118
+ value: "docker",
119
+ checked: true,
120
+ },
121
+ { name: "GitHub Actions CI", value: "ci", checked: true },
122
+ { name: "Claude Code", value: "claudeCode", checked: true },
123
+ { name: "Initialiser Git", value: "gitInit", checked: true },
124
+ ],
125
+ });
126
+ docker = infra.includes("docker");
127
+ ci = infra.includes("ci");
128
+ claudeCode = infra.includes("claudeCode");
129
+ gitInit = infra.includes("gitInit");
130
+ }
65
131
  return {
66
132
  name,
67
133
  groupId,
68
134
  description,
69
- backend,
135
+ backendType,
70
136
  frontend,
137
+ flyway,
138
+ openapi,
71
139
  auth,
72
- ci,
140
+ mapstruct,
141
+ uiFramework,
142
+ primeNGPreset,
143
+ ngrx,
73
144
  docker,
145
+ ci,
74
146
  claudeCode,
75
147
  gitInit,
76
148
  };
@@ -1 +1 @@
1
- {"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/prompts/project.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/prompts/project.ts"],"names":[],"mappings":"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"}
@@ -11,16 +11,18 @@ spring:
11
11
 
12
12
  jpa:
13
13
  hibernate:
14
- ddl-auto: validate
14
+ ddl-auto: {{#if flyway}}validate{{else}}update{{/if}}
15
15
  open-in-view: false
16
16
  properties:
17
17
  hibernate:
18
18
  format_sql: true
19
19
 
20
+ {{#if flyway}}
20
21
  flyway:
21
22
  enabled: true
22
23
  locations: classpath:db/migration
23
24
 
25
+ {{/if}}
24
26
  server:
25
27
  port: 8080
26
28
 
@@ -30,8 +32,10 @@ management:
30
32
  exposure:
31
33
  include: health,info,metrics
32
34
 
35
+ {{#if openapi}}
33
36
  springdoc:
34
37
  api-docs:
35
38
  path: /v3/api-docs
36
39
  swagger-ui:
37
40
  path: /swagger-ui.html
41
+ {{/if}}
@@ -19,8 +19,12 @@
19
19
 
20
20
  <properties>
21
21
  <java.version>21</java.version>
22
+ {{#if mapstruct}}
22
23
  <mapstruct.version>{{versions.mapstruct}}</mapstruct.version>
24
+ {{/if}}
25
+ {{#if openapi}}
23
26
  <springdoc.version>{{versions.springDoc}}</springdoc.version>
27
+ {{/if}}
24
28
  </properties>
25
29
 
26
30
  <dependencies>
@@ -54,6 +58,7 @@
54
58
  <artifactId>postgresql</artifactId>
55
59
  <scope>runtime</scope>
56
60
  </dependency>
61
+ {{#if flyway}}
57
62
  <dependency>
58
63
  <groupId>org.flywaydb</groupId>
59
64
  <artifactId>flyway-core</artifactId>
@@ -62,13 +67,16 @@
62
67
  <groupId>org.flywaydb</groupId>
63
68
  <artifactId>flyway-database-postgresql</artifactId>
64
69
  </dependency>
70
+ {{/if}}
65
71
 
72
+ {{#if openapi}}
66
73
  <!-- OpenAPI -->
67
74
  <dependency>
68
75
  <groupId>org.springdoc</groupId>
69
76
  <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
70
77
  <version>${springdoc.version}</version>
71
78
  </dependency>
79
+ {{/if}}
72
80
 
73
81
  <!-- Lombok -->
74
82
  <dependency>
@@ -77,12 +85,14 @@
77
85
  <optional>true</optional>
78
86
  </dependency>
79
87
 
88
+ {{#if mapstruct}}
80
89
  <!-- MapStruct -->
81
90
  <dependency>
82
91
  <groupId>org.mapstruct</groupId>
83
92
  <artifactId>mapstruct</artifactId>
84
93
  <version>${mapstruct.version}</version>
85
94
  </dependency>
95
+ {{/if}}
86
96
 
87
97
  <!-- Test -->
88
98
  <dependency>
@@ -122,6 +132,7 @@
122
132
  <groupId>org.projectlombok</groupId>
123
133
  <artifactId>lombok</artifactId>
124
134
  </path>
135
+ {{#if mapstruct}}
125
136
  <path>
126
137
  <groupId>org.mapstruct</groupId>
127
138
  <artifactId>mapstruct-processor</artifactId>
@@ -132,6 +143,7 @@
132
143
  <artifactId>lombok-mapstruct-binding</artifactId>
133
144
  <version>0.2.0</version>
134
145
  </path>
146
+ {{/if}}
135
147
  </annotationProcessorPaths>
136
148
  </configuration>
137
149
  </plugin>
@@ -33,7 +33,7 @@ jobs:
33
33
  - 'frontend/**'
34
34
  {{/if}}
35
35
 
36
- {{#if backend}}
36
+ {{#if springBoot}}
37
37
  backend:
38
38
  needs: changes
39
39
  if: needs.changes.outputs.backend == 'true'
@@ -55,6 +55,30 @@ jobs:
55
55
  run: ./mvnw verify --batch-mode --no-transfer-progress
56
56
  {{/if}}
57
57
 
58
+ {{#if fastapi}}
59
+ backend:
60
+ needs: changes
61
+ if: needs.changes.outputs.backend == 'true'
62
+ runs-on: ubuntu-latest
63
+ defaults:
64
+ run:
65
+ working-directory: backend
66
+ steps:
67
+ - uses: actions/checkout@v4
68
+
69
+ - name: Set up Python 3.12
70
+ uses: actions/setup-python@v5
71
+ with:
72
+ python-version: '3.12'
73
+ cache: pip
74
+
75
+ - name: Install dependencies
76
+ run: pip install -r requirements.txt
77
+
78
+ - name: Test
79
+ run: pytest
80
+ {{/if}}
81
+
58
82
  {{#if frontend}}
59
83
  frontend:
60
84
  needs: changes
@@ -7,7 +7,7 @@
7
7
  ```
8
8
  {{name}}/
9
9
  {{#if backend}}
10
- ├── backend/ # Spring Boot API
10
+ ├── backend/ # Backend API
11
11
  {{/if}}
12
12
  {{#if frontend}}
13
13
  ├── frontend/ # Angular SPA
@@ -18,44 +18,63 @@
18
18
  └── README.md
19
19
  ```
20
20
 
21
- {{#if backend}}
21
+ {{#if springBoot}}
22
22
  ## Backend — Spring Boot {{versions.springBoot}}
23
23
 
24
- - **Java 21** with records, pattern matching, sealed classes
25
- - **Architecture:** Feature-based package structure
26
- - **DB:** PostgreSQL, Flyway migrations in `backend/src/main/resources/db/migration/`
27
- - **Conventions:** Records for DTOs, Lombok where useful, MapStruct for mappings
28
- - **Validation:** Jakarta Bean Validation
29
- - **Logging:** SLF4J
24
+ - **Java 21** records, pattern matching, sealed classes, virtual threads
25
+ - **Architecture:** Feature-based packages — `com.<groupId>.<feature>.{domain,application,infrastructure}`
26
+ - **DB:** PostgreSQL{{#if flyway}}, Flyway migrations in `backend/src/main/resources/db/migration/`{{/if}}
27
+ - **Conventions:** Records for DTOs, Lombok, MapStruct for mappings
28
+ - **Validation:** Jakarta Bean Validation | **Logging:** `@Slf4j`
29
+ - **Skill:** apply `applying-java-conventions` for all Java code
30
30
 
31
31
  ### Commands
32
32
 
33
33
  ```bash
34
34
  cd backend
35
35
  ./mvnw spring-boot:run # Start dev server
36
- ./mvnw test # Run tests
37
- ./mvnw package -DskipTests # Build JAR
36
+ ./mvnw test # Run tests
37
+ ./mvnw package -DskipTests # Build JAR
38
+ ```
39
+
40
+ {{/if}}
41
+ {{#if fastapi}}
42
+ ## Backend — FastAPI (Python 3.12)
43
+
44
+ - **FastAPI** with uvicorn, pydantic-settings
45
+ - **Architecture:** `app/routers/`, `app/config.py`, `tests/`
46
+ - **Conventions:** Pydantic models, async endpoints, dependency injection
47
+ - **Skill:** apply `applying-python-conventions` for all Python code
48
+
49
+ ### Commands
50
+
51
+ ```bash
52
+ cd backend
53
+ uvicorn app.main:app --reload # Start dev server (port 8000)
54
+ pytest # Run tests
55
+ pip install -r requirements.txt # Install dependencies
38
56
  ```
39
57
 
40
58
  {{/if}}
41
59
  {{#if frontend}}
42
- ## Frontend — Angular
60
+ ## Frontend — Angular {{versions.angular}}
43
61
 
44
- - **Angular {{versions.angular}}** with strict mode, standalone components, signals
62
+ - **Angular {{versions.angular}}** strict mode, standalone components, signals
45
63
  - **UI:** PrimeNG {{versions.primeng}}, theme Aura, PrimeFlex
64
+ {{#if ngrx}}
46
65
  - **State:** NgRx SignalStore
47
- - **Conventions:** OnPush change detection, `input()`/`output()` functions, `inject()` for DI
48
- - **Control flow:** `@if`, `@for` (not *ngIf/*ngFor)
49
- - **Indentation:** 2 spaces
66
+ {{/if}}
67
+ - **Conventions:** OnPush, `input()`/`output()`, `inject()`, `@if`/`@for` control flow
68
+ - **Skill:** apply `applying-angular-conventions` for all Angular/TypeScript code
50
69
 
51
70
  ### Commands
52
71
 
53
72
  ```bash
54
73
  cd frontend
55
- npm install # Install dependencies
56
- ng serve # Start dev server (port 4200)
57
- ng build # Production build
58
- ng test # Run tests
74
+ npm install # Install dependencies
75
+ ng serve # Start dev server (port 4200)
76
+ ng build # Production build
77
+ ng test # Run tests
59
78
  ```
60
79
 
61
80
  {{/if}}
@@ -63,17 +82,42 @@ ng test # Run tests
63
82
  ## Infrastructure
64
83
 
65
84
  ```bash
66
- docker compose up -d # Start PostgreSQL + pgAdmin
67
- docker compose down # Stop services
85
+ docker compose up -d # Start PostgreSQL + pgAdmin
86
+ docker compose down # Stop services
68
87
  ```
69
88
 
70
89
  - **PostgreSQL:** localhost:5432
71
90
  - **pgAdmin:** localhost:5050 (admin@admin.com / admin)
72
91
 
73
92
  {{/if}}
93
+ ## Workflow
94
+
95
+ | Scenario | Action |
96
+ |---|---|
97
+ | New feature | `/speckit.workflow` — routes automatiquement (fast track ou full workflow spec→PR) |
98
+ | Bug | Describe to Claude → apply `superpowers:systematic-debugging` |
99
+ | UI component | Apply `frontend-design:frontend-design` skill |
100
+ | Commit / PR | Use `commit-commands:commit-push-pr` skill |
101
+
102
+ ## TDD
103
+
104
+ Write the failing test first — no implementation code before a red test.
105
+ **Red → Green → Refactor.** This is not optional.
106
+
107
+ ## Source of Truth
108
+
109
+ {{#if springBoot}}
110
+ - **API contract:** OpenAPI annotations on controllers (Springdoc)
111
+ {{#if flyway}}
112
+ - **DB schema:** Flyway migrations — never modify existing migration files
113
+ {{/if}}
114
+ {{/if}}
115
+ - **Config:** `application.yml` (never `application.properties`)
116
+ - **Secrets:** environment variables only — never committed
117
+
74
118
  ## Conventions
75
119
 
76
120
  - **Git:** Conventional commits (`feat:`, `fix:`, `refactor:`, `chore:`)
77
121
  - **Branches:** `feature/`, `fix/`, `refactor/`, `chore/`
78
122
  - **DB:** snake_case naming
79
- - **Security:** Never commit secrets, use environment variables
123
+ - **Security:** Never commit secrets use environment variables
@@ -4,6 +4,7 @@
4
4
  {{#each allowedCommands}}
5
5
  "{{this}}"{{#unless @last}},{{/unless}}
6
6
  {{/each}}
7
- ]
7
+ ],
8
+ "defaultMode": "dontAsk"
8
9
  }
9
- }
10
+ }
@@ -29,6 +29,17 @@ services:
29
29
  depends_on:
30
30
  postgres:
31
31
  condition: service_healthy
32
+ {{#if fastapi}}
33
+
34
+ api:
35
+ build: ./backend
36
+ container_name: {{name}}_api
37
+ restart: unless-stopped
38
+ ports:
39
+ - "8000:8000"
40
+ environment:
41
+ DEBUG: "false"
42
+ {{/if}}
32
43
 
33
44
  volumes:
34
45
  postgres_data:
@@ -0,0 +1,12 @@
1
+ FROM python:3.12-slim
2
+
3
+ WORKDIR /app
4
+
5
+ COPY requirements.txt .
6
+ RUN pip install --no-cache-dir -r requirements.txt
7
+
8
+ COPY . .
9
+
10
+ EXPOSE 8000
11
+
12
+ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
@@ -0,0 +1,12 @@
1
+ from pydantic_settings import BaseSettings
2
+
3
+
4
+ class Settings(BaseSettings):
5
+ app_name: str = "{{name}}"
6
+ debug: bool = False
7
+
8
+ class Config:
9
+ env_file = ".env"
10
+
11
+
12
+ settings = Settings()
@@ -0,0 +1,13 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.pyo
4
+ .venv/
5
+ venv/
6
+ env/
7
+ .env
8
+ dist/
9
+ build/
10
+ *.egg-info/
11
+ .pytest_cache/
12
+ .mypy_cache/
13
+ .ruff_cache/
@@ -0,0 +1,8 @@
1
+ from fastapi import APIRouter
2
+
3
+ router = APIRouter()
4
+
5
+
6
+ @router.get("/health")
7
+ def health_check():
8
+ return {"status": "ok"}
@@ -0,0 +1,6 @@
1
+ from fastapi import FastAPI
2
+ from app.routers import health
3
+
4
+ app = FastAPI(title="{{name}}", version="0.1.0")
5
+
6
+ app.include_router(health.router)
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,5 @@
1
+ fastapi==0.115.0
2
+ uvicorn[standard]==0.32.0
3
+ pydantic-settings==2.6.0
4
+ pytest==8.3.0
5
+ httpx==0.28.0
@@ -0,0 +1,11 @@
1
+ from fastapi.testclient import TestClient
2
+
3
+ from app.main import app
4
+
5
+ client = TestClient(app)
6
+
7
+
8
+ def test_health():
9
+ response = client.get("/health")
10
+ assert response.status_code == 200
11
+ assert response.json() == {"status": "ok"}
@@ -1,9 +1,11 @@
1
1
  import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
2
2
  import { provideRouter, withComponentInputBinding } from '@angular/router';
3
3
  import { provideHttpClient{{#if auth}}, withInterceptors{{/if}} } from '@angular/common/http';
4
+ {{#if uiPrimeNG}}
4
5
  import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
5
6
  import { providePrimeNG } from 'primeng/config';
6
- import Aura from '@primeuix/themes/aura';
7
+ import {{primeNGPreset}} from '@primeuix/themes/{{lowerCase primeNGPreset}}';
8
+ {{/if}}
7
9
  import { routes } from './app.routes';
8
10
  {{#if auth}}
9
11
  import { authInterceptor } from './core/interceptors/auth.interceptor';
@@ -19,14 +21,16 @@ export const appConfig: ApplicationConfig = {
19
21
  {{else}}
20
22
  provideHttpClient(),
21
23
  {{/if}}
24
+ {{#if uiPrimeNG}}
22
25
  provideAnimationsAsync(),
23
26
  providePrimeNG({
24
27
  theme: {
25
- preset: Aura,
28
+ preset: {{primeNGPreset}},
26
29
  options: {
27
30
  darkModeSelector: false,
28
31
  },
29
32
  },
30
33
  }),
34
+ {{/if}}
31
35
  ],
32
36
  };
@@ -0,0 +1,14 @@
1
+ import { signalStore, withState } from '@ngrx/signals';
2
+
3
+ export type AppState = {
4
+ loading: boolean;
5
+ };
6
+
7
+ const initialState: AppState = {
8
+ loading: false,
9
+ };
10
+
11
+ export const AppStore = signalStore(
12
+ { providedIn: 'root' },
13
+ withState(initialState),
14
+ );
@@ -1,3 +1,4 @@
1
+ {{#if uiPrimeNG}}
1
2
  @import "primeicons/primeicons.css";
2
3
 
3
4
  html, body {
@@ -7,3 +8,19 @@ html, body {
7
8
  background: var(--p-surface-ground);
8
9
  color: var(--p-text-color);
9
10
  }
11
+ {{/if}}
12
+ {{#if uiTailwind}}
13
+ @import "tailwindcss";
14
+
15
+ html, body {
16
+ height: 100%;
17
+ margin: 0;
18
+ }
19
+ {{/if}}
20
+ {{#if uiNone}}
21
+ html, body {
22
+ height: 100%;
23
+ margin: 0;
24
+ font-family: sans-serif;
25
+ }
26
+ {{/if}}