@yosr-ai/template-spring 0.0.0-stage → 0.2.5

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 (68) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/LICENSE +21 -0
  3. package/README.md +14 -2
  4. package/features/auth-api-key/files/src/main/java/com/yosr/app/core/ApiKeyFilter.java +52 -0
  5. package/features/auth-api-key/files/src/test/java/com/yosr/app/ApiKeyTest.java +45 -0
  6. package/features/auth-api-key/snippets/application-api-key.yaml +1 -0
  7. package/features/data-jpa/files/dependencies-lock.json +811 -0
  8. package/features/data-jpa/files/pom.xml +91 -0
  9. package/features/data-jpa/files/src/main/java/com/yosr/app/core/AppConfig.java +34 -0
  10. package/features/data-jpa/files/src/main/java/com/yosr/app/core/AppSettings.java +40 -0
  11. package/features/data-jpa/files/src/main/java/com/yosr/app/core/DataSourceUrl.java +33 -0
  12. package/features/data-jpa/files/src/main/java/com/yosr/app/features/notes/JpaNoteStore.java +59 -0
  13. package/features/data-jpa/files/src/main/java/com/yosr/app/features/notes/NoteEntity.java +68 -0
  14. package/features/data-jpa/files/src/main/java/com/yosr/app/features/notes/NoteRepository.java +5 -0
  15. package/features/data-jpa/files/src/main/resources/application.yml +14 -0
  16. package/features/data-jpa/files/src/test/java/com/yosr/app/JpaTestConfig.java +7 -0
  17. package/features/data-jpa/files/src/test/java/com/yosr/app/NotesApiTest.java +119 -0
  18. package/features/data-jpa/snippets/readme-db.md +3 -0
  19. package/features/deploy-docker/files/.dockerignore +5 -0
  20. package/features/deploy-docker/files/Dockerfile +20 -0
  21. package/features/deploy-docker/files/compose.yaml +12 -0
  22. package/features/deploy-docker/snippets/readme-docker.md +3 -0
  23. package/features/deploy-docker-postgres/snippets/app-config.yaml +3 -0
  24. package/features/deploy-docker-postgres/snippets/app-env.yaml +1 -0
  25. package/features/deploy-docker-postgres/snippets/compose-header.yaml +1 -0
  26. package/features/deploy-docker-postgres/snippets/compose-volumes.yaml +3 -0
  27. package/features/deploy-docker-postgres/snippets/postgres-service.yaml +13 -0
  28. package/features/deploy-docker-postgres/snippets/readme-docker.md +3 -0
  29. package/features/errors-result/files/src/main/java/com/yosr/app/features/notes/NotesController.java +64 -0
  30. package/features/errors-result/files/src/main/java/com/yosr/app/features/notes/NotesService.java +55 -0
  31. package/features/errors-result/files/src/main/java/com/yosr/app/shared/Result.java +8 -0
  32. package/features/errors-result/files/src/test/java/com/yosr/app/NotesServiceTest.java +46 -0
  33. package/files/.env.example +7 -0
  34. package/files/.java-version +1 -0
  35. package/files/README.md +22 -0
  36. package/files/dependencies-lock.json +547 -0
  37. package/files/gitignore +9 -0
  38. package/files/pom.xml +77 -0
  39. package/files/src/main/java/com/yosr/app/AppApplication.java +12 -0
  40. package/files/src/main/java/com/yosr/app/core/AppConfig.java +21 -0
  41. package/files/src/main/java/com/yosr/app/core/AppSettings.java +32 -0
  42. package/files/src/main/java/com/yosr/app/core/HealthController.java +14 -0
  43. package/files/src/main/java/com/yosr/app/core/RestExceptionHandler.java +22 -0
  44. package/files/src/main/java/com/yosr/app/core/WebConfig.java +27 -0
  45. package/files/src/main/java/com/yosr/app/features/notes/MemoryNoteStore.java +71 -0
  46. package/files/src/main/java/com/yosr/app/features/notes/Note.java +53 -0
  47. package/files/src/main/java/com/yosr/app/features/notes/NoteDtos.java +21 -0
  48. package/files/src/main/java/com/yosr/app/features/notes/NoteStore.java +15 -0
  49. package/files/src/main/java/com/yosr/app/features/notes/NotesController.java +47 -0
  50. package/files/src/main/java/com/yosr/app/features/notes/NotesService.java +43 -0
  51. package/files/src/main/java/com/yosr/app/shared/NotFoundException.java +8 -0
  52. package/files/src/main/resources/application.yml +7 -0
  53. package/files/src/test/java/com/yosr/app/NotesApiTest.java +102 -0
  54. package/files/src/test/java/com/yosr/app/NotesServiceTest.java +42 -0
  55. package/package.json +26 -4
  56. package/rules/architecture.md +5 -0
  57. package/rules/auth-api-key.md +3 -0
  58. package/rules/commands.md +7 -0
  59. package/rules/data-jpa.md +3 -0
  60. package/rules/data-none.md +3 -0
  61. package/rules/errors-result.md +3 -0
  62. package/rules/errors-throw.md +3 -0
  63. package/rules/layout-feature.md +5 -0
  64. package/rules/layout-flat.md +3 -0
  65. package/rules/layout-layer.md +3 -0
  66. package/rules/project-overview.md +5 -0
  67. package/seed.template.json +711 -0
  68. package/style/.gitkeep +0 -0
@@ -0,0 +1,55 @@
1
+ package com.yosr.app.features.notes;
2
+
3
+ import com.yosr.app.shared.Result;
4
+ import java.util.List;
5
+
6
+ public final class NotesService {
7
+
8
+ private final NoteStore store;
9
+
10
+ public NotesService(NoteStore store) {
11
+ this.store = store;
12
+ }
13
+
14
+ public List<Note> list() {
15
+ return store.list();
16
+ }
17
+
18
+ public Result<Note> get(int id) {
19
+ return store
20
+ .get(id)
21
+ .<Result<Note>>map(Result.Ok::new)
22
+ .orElse(new Result.Err<>("Note " + id + " was not found."));
23
+ }
24
+
25
+ public Result<Note> create(NoteDtos.NoteCreate input) {
26
+ try {
27
+ String title = requireTitle(input.title());
28
+ return new Result.Ok<>(store.add(title, input.body()));
29
+ } catch (IllegalArgumentException ex) {
30
+ return new Result.Err<>(ex.getMessage());
31
+ }
32
+ }
33
+
34
+ public Result<Note> update(int id, NoteDtos.NoteUpdate input) {
35
+ try {
36
+ if (input.title() != null) {
37
+ requireTitle(input.title());
38
+ }
39
+ } catch (IllegalArgumentException ex) {
40
+ return new Result.Err<>(ex.getMessage());
41
+ }
42
+ return store
43
+ .update(id, input.title(), input.body())
44
+ .<Result<Note>>map(Result.Ok::new)
45
+ .orElse(new Result.Err<>("Note " + id + " was not found."));
46
+ }
47
+
48
+ private static String requireTitle(String title) {
49
+ String trimmed = title == null ? "" : title.trim();
50
+ if (trimmed.isEmpty()) {
51
+ throw new IllegalArgumentException("Title must not be blank.");
52
+ }
53
+ return trimmed;
54
+ }
55
+ }
@@ -0,0 +1,8 @@
1
+ package com.yosr.app.shared;
2
+
3
+ public sealed interface Result<T> permits Result.Ok, Result.Err {
4
+
5
+ record Ok<T>(T value) implements Result<T> {}
6
+
7
+ record Err<T>(String message) implements Result<T> {}
8
+ }
@@ -0,0 +1,46 @@
1
+ package com.yosr.app;
2
+
3
+ import static org.junit.jupiter.api.Assertions.assertEquals;
4
+ import static org.junit.jupiter.api.Assertions.assertInstanceOf;
5
+
6
+ import com.yosr.app.features.notes.MemoryNoteStore;
7
+ import com.yosr.app.features.notes.Note;
8
+ import com.yosr.app.features.notes.NoteDtos.NoteCreate;
9
+ import com.yosr.app.features.notes.NoteDtos.NoteUpdate;
10
+ import com.yosr.app.features.notes.NotesService;
11
+ import com.yosr.app.shared.Result;
12
+ import org.junit.jupiter.api.Test;
13
+
14
+ class NotesServiceTest {
15
+
16
+ private static NotesService service() {
17
+ return new NotesService(new MemoryNoteStore());
18
+ }
19
+
20
+ @Test
21
+ void createThenGetReturnsTheNote() {
22
+ NotesService notes = service();
23
+ Result.Ok<Note> created =
24
+ assertInstanceOf(Result.Ok.class, notes.create(new NoteCreate("Hello", "Body")));
25
+ Result.Ok<Note> found = assertInstanceOf(Result.Ok.class, notes.get(created.value().id()));
26
+ assertEquals("Hello", found.value().title());
27
+ }
28
+
29
+ @Test
30
+ void getMissingNoteReturnsErr() {
31
+ NotesService notes = service();
32
+ assertInstanceOf(Result.Err.class, notes.get(99));
33
+ }
34
+
35
+ @Test
36
+ void updateChangesOnlyGivenFields() {
37
+ NotesService notes = service();
38
+ Result.Ok<Note> created =
39
+ assertInstanceOf(Result.Ok.class, notes.create(new NoteCreate("Hello", "Body")));
40
+ Result.Ok<Note> updated =
41
+ assertInstanceOf(
42
+ Result.Ok.class, notes.update(created.value().id(), new NoteUpdate("Hi", null)));
43
+ assertEquals("Hi", updated.value().title());
44
+ assertEquals("Body", updated.value().body());
45
+ }
46
+ }
@@ -0,0 +1,7 @@
1
+ # Application display name
2
+ APP_NAME=__seed_projectName__
3
+
4
+ # Comma-separated browser origins allowed by CORS (Vite default included)
5
+ CORS_ORIGINS=http://localhost:5173
6
+
7
+ # @seed:anchor env-vars
@@ -0,0 +1 @@
1
+ 25
@@ -0,0 +1,22 @@
1
+ # __seed_projectName__
2
+
3
+ Generated by [Yosr Seed](https://seed.yosr.ai) from the `__seed_templateName__@__seed_templateVersion__` template. API-only Spring Boot service on Java 25: JUnit 5, MockMvc, Spotless. Data: __seed_storageLabel__.
4
+
5
+ ## Commands
6
+
7
+ | Task | Command |
8
+ | --- | --- |
9
+ | Install (locked) | `mvn -B -q dependency:resolve dependency-lock:check` |
10
+ | Run | `mvn -B -q spring-boot:run` |
11
+ | Format check | `mvn -B -q spotless:check` |
12
+ | Compile | `mvn -B -q compile` |
13
+ | Tests | `mvn -B -q test` |
14
+
15
+ ## Layout
16
+
17
+ - `src/main/java/com/yosr/app/` — app (`core`, `features`, `shared`)
18
+ - `src/test/java/com/yosr/app/` — unit + in-process HTTP tests (`MockMvc`)
19
+
20
+ Maven coordinates stay fixed: `com.yosr:app`.
21
+
22
+ <!-- @seed:anchor readme-sections -->