javi-forge 1.1.0 → 1.3.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.
- package/ci-local/ci-local.sh +38 -10
- package/ci-local/hooks/pre-commit +10 -155
- package/ci-local/hooks/pre-push +12 -29
- package/dist/commands/ci.d.ts +33 -0
- package/dist/commands/ci.js +341 -0
- package/dist/commands/init.js +5 -0
- package/dist/index.js +39 -5
- package/dist/lib/docker.d.ts +43 -0
- package/dist/lib/docker.js +223 -0
- package/dist/ui/CI.d.ts +9 -0
- package/dist/ui/CI.js +91 -0
- package/package.json +9 -1
- package/ai-config/.skillignore +0 -15
- package/ai-config/AUTO_INVOKE.md +0 -300
- package/ai-config/agents/_TEMPLATE.md +0 -93
- package/ai-config/agents/business/api-designer.md +0 -1657
- package/ai-config/agents/business/business-analyst.md +0 -1331
- package/ai-config/agents/business/product-strategist.md +0 -206
- package/ai-config/agents/business/project-manager.md +0 -178
- package/ai-config/agents/business/requirements-analyst.md +0 -1277
- package/ai-config/agents/business/technical-writer.md +0 -1679
- package/ai-config/agents/creative/ux-designer.md +0 -205
- package/ai-config/agents/data-ai/ai-engineer.md +0 -487
- package/ai-config/agents/data-ai/analytics-engineer.md +0 -953
- package/ai-config/agents/data-ai/data-engineer.md +0 -173
- package/ai-config/agents/data-ai/data-scientist.md +0 -672
- package/ai-config/agents/data-ai/mlops-engineer.md +0 -814
- package/ai-config/agents/data-ai/prompt-engineer.md +0 -772
- package/ai-config/agents/development/angular-expert.md +0 -620
- package/ai-config/agents/development/backend-architect.md +0 -795
- package/ai-config/agents/development/database-specialist.md +0 -212
- package/ai-config/agents/development/frontend-specialist.md +0 -686
- package/ai-config/agents/development/fullstack-engineer.md +0 -668
- package/ai-config/agents/development/golang-pro.md +0 -338
- package/ai-config/agents/development/java-enterprise.md +0 -400
- package/ai-config/agents/development/javascript-pro.md +0 -422
- package/ai-config/agents/development/nextjs-pro.md +0 -474
- package/ai-config/agents/development/python-pro.md +0 -570
- package/ai-config/agents/development/react-pro.md +0 -487
- package/ai-config/agents/development/rust-pro.md +0 -246
- package/ai-config/agents/development/spring-boot-4-expert.md +0 -326
- package/ai-config/agents/development/typescript-pro.md +0 -336
- package/ai-config/agents/development/vue-specialist.md +0 -605
- package/ai-config/agents/infrastructure/cloud-architect.md +0 -472
- package/ai-config/agents/infrastructure/deployment-manager.md +0 -358
- package/ai-config/agents/infrastructure/devops-engineer.md +0 -455
- package/ai-config/agents/infrastructure/incident-responder.md +0 -519
- package/ai-config/agents/infrastructure/kubernetes-expert.md +0 -705
- package/ai-config/agents/infrastructure/monitoring-specialist.md +0 -674
- package/ai-config/agents/infrastructure/performance-engineer.md +0 -658
- package/ai-config/agents/orchestrator.md +0 -241
- package/ai-config/agents/quality/accessibility-auditor.md +0 -1204
- package/ai-config/agents/quality/code-reviewer-compact.md +0 -123
- package/ai-config/agents/quality/code-reviewer.md +0 -363
- package/ai-config/agents/quality/dependency-manager.md +0 -743
- package/ai-config/agents/quality/e2e-test-specialist.md +0 -1005
- package/ai-config/agents/quality/performance-tester.md +0 -1086
- package/ai-config/agents/quality/security-auditor.md +0 -133
- package/ai-config/agents/quality/test-engineer.md +0 -453
- package/ai-config/agents/specialists/api-designer.md +0 -87
- package/ai-config/agents/specialists/backend-architect.md +0 -73
- package/ai-config/agents/specialists/code-reviewer.md +0 -77
- package/ai-config/agents/specialists/db-optimizer.md +0 -75
- package/ai-config/agents/specialists/devops-engineer.md +0 -83
- package/ai-config/agents/specialists/documentation-writer.md +0 -78
- package/ai-config/agents/specialists/frontend-developer.md +0 -75
- package/ai-config/agents/specialists/performance-analyst.md +0 -82
- package/ai-config/agents/specialists/refactor-specialist.md +0 -74
- package/ai-config/agents/specialists/security-auditor.md +0 -74
- package/ai-config/agents/specialists/test-engineer.md +0 -81
- package/ai-config/agents/specialists/ux-consultant.md +0 -76
- package/ai-config/agents/specialized/agent-generator.md +0 -1190
- package/ai-config/agents/specialized/blockchain-developer.md +0 -149
- package/ai-config/agents/specialized/code-migrator.md +0 -892
- package/ai-config/agents/specialized/context-manager.md +0 -978
- package/ai-config/agents/specialized/documentation-writer.md +0 -1078
- package/ai-config/agents/specialized/ecommerce-expert.md +0 -1756
- package/ai-config/agents/specialized/embedded-engineer.md +0 -1714
- package/ai-config/agents/specialized/error-detective.md +0 -1034
- package/ai-config/agents/specialized/fintech-specialist.md +0 -1659
- package/ai-config/agents/specialized/freelance-project-planner-v2.md +0 -1988
- package/ai-config/agents/specialized/freelance-project-planner-v3.md +0 -2136
- package/ai-config/agents/specialized/freelance-project-planner-v4.md +0 -4503
- package/ai-config/agents/specialized/freelance-project-planner.md +0 -722
- package/ai-config/agents/specialized/game-developer.md +0 -1963
- package/ai-config/agents/specialized/healthcare-dev.md +0 -1620
- package/ai-config/agents/specialized/mobile-developer.md +0 -188
- package/ai-config/agents/specialized/parallel-plan-executor.md +0 -506
- package/ai-config/agents/specialized/plan-executor.md +0 -485
- package/ai-config/agents/specialized/solo-dev-planner-modular/00-INDEX.md +0 -485
- package/ai-config/agents/specialized/solo-dev-planner-modular/01-CORE.md +0 -3493
- package/ai-config/agents/specialized/solo-dev-planner-modular/02-SELF-CORRECTION.md +0 -778
- package/ai-config/agents/specialized/solo-dev-planner-modular/03-PROGRESSIVE-SETUP.md +0 -918
- package/ai-config/agents/specialized/solo-dev-planner-modular/04-DEPLOYMENT.md +0 -1537
- package/ai-config/agents/specialized/solo-dev-planner-modular/05-TESTING.md +0 -2633
- package/ai-config/agents/specialized/solo-dev-planner-modular/06-OPERATIONS.md +0 -5610
- package/ai-config/agents/specialized/solo-dev-planner-modular/INSTALL.md +0 -335
- package/ai-config/agents/specialized/solo-dev-planner-modular/QUICK-REFERENCE.txt +0 -215
- package/ai-config/agents/specialized/solo-dev-planner-modular/README.md +0 -260
- package/ai-config/agents/specialized/solo-dev-planner-modular/START-HERE.md +0 -379
- package/ai-config/agents/specialized/solo-dev-planner-modular/WORKFLOW-DIAGRAM.md +0 -355
- package/ai-config/agents/specialized/solo-dev-planner-modular/solo-dev-planner.md +0 -279
- package/ai-config/agents/specialized/template-writer.md +0 -347
- package/ai-config/agents/specialized/test-runner.md +0 -99
- package/ai-config/agents/specialized/vibekanban-smart-worker.md +0 -244
- package/ai-config/agents/specialized/wave-executor.md +0 -138
- package/ai-config/agents/specialized/workflow-optimizer.md +0 -1114
- package/ai-config/commands/git/changelog.md +0 -32
- package/ai-config/commands/git/ci-local.md +0 -70
- package/ai-config/commands/git/commit.md +0 -35
- package/ai-config/commands/git/fix-issue.md +0 -23
- package/ai-config/commands/git/pr-create.md +0 -42
- package/ai-config/commands/git/pr-review.md +0 -50
- package/ai-config/commands/git/worktree.md +0 -39
- package/ai-config/commands/refactoring/cleanup.md +0 -24
- package/ai-config/commands/refactoring/dead-code.md +0 -40
- package/ai-config/commands/refactoring/extract.md +0 -31
- package/ai-config/commands/testing/e2e.md +0 -30
- package/ai-config/commands/testing/tdd.md +0 -36
- package/ai-config/commands/testing/test-coverage.md +0 -30
- package/ai-config/commands/testing/test-fix.md +0 -24
- package/ai-config/commands/workflow/generate-agents-md.md +0 -85
- package/ai-config/commands/workflow/planning.md +0 -47
- package/ai-config/commands/workflows/compound.md +0 -89
- package/ai-config/commands/workflows/diagnose.md +0 -70
- package/ai-config/commands/workflows/discover.md +0 -86
- package/ai-config/commands/workflows/plan.md +0 -77
- package/ai-config/commands/workflows/review.md +0 -78
- package/ai-config/commands/workflows/work.md +0 -75
- package/ai-config/config.yaml +0 -18
- package/ai-config/hooks/_TEMPLATE.md +0 -96
- package/ai-config/hooks/block-dangerous-commands.md +0 -75
- package/ai-config/hooks/commit-guard.md +0 -90
- package/ai-config/hooks/context-loader.md +0 -73
- package/ai-config/hooks/improve-prompt.md +0 -91
- package/ai-config/hooks/learning-log.md +0 -72
- package/ai-config/hooks/model-router.md +0 -86
- package/ai-config/hooks/secret-scanner.md +0 -64
- package/ai-config/hooks/skill-validator.md +0 -102
- package/ai-config/hooks/task-artifact.md +0 -114
- package/ai-config/hooks/validate-workflow.md +0 -100
- package/ai-config/prompts/base.md +0 -71
- package/ai-config/prompts/modes/debug.md +0 -34
- package/ai-config/prompts/modes/deploy.md +0 -40
- package/ai-config/prompts/modes/research.md +0 -32
- package/ai-config/prompts/modes/review.md +0 -33
- package/ai-config/prompts/review-policy.md +0 -79
- package/ai-config/skills/_TEMPLATE.md +0 -157
- package/ai-config/skills/backend/api-gateway/SKILL.md +0 -254
- package/ai-config/skills/backend/bff-concepts/SKILL.md +0 -239
- package/ai-config/skills/backend/bff-spring/SKILL.md +0 -364
- package/ai-config/skills/backend/chi-router/SKILL.md +0 -396
- package/ai-config/skills/backend/error-handling/SKILL.md +0 -255
- package/ai-config/skills/backend/exceptions-spring/SKILL.md +0 -323
- package/ai-config/skills/backend/fastapi/SKILL.md +0 -302
- package/ai-config/skills/backend/gateway-spring/SKILL.md +0 -390
- package/ai-config/skills/backend/go-backend/SKILL.md +0 -457
- package/ai-config/skills/backend/gradle-multimodule/SKILL.md +0 -274
- package/ai-config/skills/backend/graphql-concepts/SKILL.md +0 -352
- package/ai-config/skills/backend/graphql-spring/SKILL.md +0 -398
- package/ai-config/skills/backend/grpc-concepts/SKILL.md +0 -283
- package/ai-config/skills/backend/grpc-spring/SKILL.md +0 -445
- package/ai-config/skills/backend/jwt-auth/SKILL.md +0 -412
- package/ai-config/skills/backend/notifications-concepts/SKILL.md +0 -259
- package/ai-config/skills/backend/recommendations-concepts/SKILL.md +0 -261
- package/ai-config/skills/backend/search-concepts/SKILL.md +0 -263
- package/ai-config/skills/backend/search-spring/SKILL.md +0 -375
- package/ai-config/skills/backend/spring-boot-4/SKILL.md +0 -172
- package/ai-config/skills/backend/websockets/SKILL.md +0 -532
- package/ai-config/skills/data-ai/ai-ml/SKILL.md +0 -423
- package/ai-config/skills/data-ai/analytics-concepts/SKILL.md +0 -195
- package/ai-config/skills/data-ai/analytics-spring/SKILL.md +0 -340
- package/ai-config/skills/data-ai/duckdb-analytics/SKILL.md +0 -440
- package/ai-config/skills/data-ai/langchain/SKILL.md +0 -238
- package/ai-config/skills/data-ai/mlflow/SKILL.md +0 -302
- package/ai-config/skills/data-ai/onnx-inference/SKILL.md +0 -290
- package/ai-config/skills/data-ai/powerbi/SKILL.md +0 -352
- package/ai-config/skills/data-ai/pytorch/SKILL.md +0 -274
- package/ai-config/skills/data-ai/scikit-learn/SKILL.md +0 -321
- package/ai-config/skills/data-ai/vector-db/SKILL.md +0 -301
- package/ai-config/skills/database/graph-databases/SKILL.md +0 -218
- package/ai-config/skills/database/graph-spring/SKILL.md +0 -361
- package/ai-config/skills/database/pgx-postgres/SKILL.md +0 -512
- package/ai-config/skills/database/redis-cache/SKILL.md +0 -343
- package/ai-config/skills/database/sqlite-embedded/SKILL.md +0 -388
- package/ai-config/skills/database/timescaledb/SKILL.md +0 -320
- package/ai-config/skills/docs/api-documentation/SKILL.md +0 -293
- package/ai-config/skills/docs/docs-spring/SKILL.md +0 -377
- package/ai-config/skills/docs/mustache-templates/SKILL.md +0 -190
- package/ai-config/skills/docs/technical-docs/SKILL.md +0 -447
- package/ai-config/skills/frontend/astro-ssr/SKILL.md +0 -441
- package/ai-config/skills/frontend/frontend-design/SKILL.md +0 -54
- package/ai-config/skills/frontend/frontend-web/SKILL.md +0 -368
- package/ai-config/skills/frontend/mantine-ui/SKILL.md +0 -396
- package/ai-config/skills/frontend/tanstack-query/SKILL.md +0 -439
- package/ai-config/skills/frontend/zod-validation/SKILL.md +0 -417
- package/ai-config/skills/frontend/zustand-state/SKILL.md +0 -350
- package/ai-config/skills/infrastructure/chaos-engineering/SKILL.md +0 -244
- package/ai-config/skills/infrastructure/chaos-spring/SKILL.md +0 -378
- package/ai-config/skills/infrastructure/devops-infra/SKILL.md +0 -435
- package/ai-config/skills/infrastructure/docker-containers/SKILL.md +0 -420
- package/ai-config/skills/infrastructure/kubernetes/SKILL.md +0 -456
- package/ai-config/skills/infrastructure/opentelemetry/SKILL.md +0 -546
- package/ai-config/skills/infrastructure/traefik-proxy/SKILL.md +0 -474
- package/ai-config/skills/infrastructure/woodpecker-ci/SKILL.md +0 -315
- package/ai-config/skills/mobile/ionic-capacitor/SKILL.md +0 -504
- package/ai-config/skills/mobile/mobile-ionic/SKILL.md +0 -448
- package/ai-config/skills/prompt-improver/SKILL.md +0 -125
- package/ai-config/skills/quality/ghagga-review/SKILL.md +0 -216
- package/ai-config/skills/references/hooks-patterns/SKILL.md +0 -238
- package/ai-config/skills/references/mcp-servers/SKILL.md +0 -275
- package/ai-config/skills/references/plugins-reference/SKILL.md +0 -110
- package/ai-config/skills/references/skills-reference/SKILL.md +0 -420
- package/ai-config/skills/references/subagent-templates/SKILL.md +0 -193
- package/ai-config/skills/systems-iot/modbus-protocol/SKILL.md +0 -410
- package/ai-config/skills/systems-iot/mqtt-rumqttc/SKILL.md +0 -408
- package/ai-config/skills/systems-iot/rust-systems/SKILL.md +0 -386
- package/ai-config/skills/systems-iot/tokio-async/SKILL.md +0 -324
- package/ai-config/skills/testing/playwright-e2e/SKILL.md +0 -289
- package/ai-config/skills/testing/testcontainers/SKILL.md +0 -299
- package/ai-config/skills/testing/vitest-testing/SKILL.md +0 -381
- package/ai-config/skills/workflow/ci-local-guide/SKILL.md +0 -118
- package/ai-config/skills/workflow/claude-automation-recommender/SKILL.md +0 -299
- package/ai-config/skills/workflow/claude-md-improver/SKILL.md +0 -158
- package/ai-config/skills/workflow/finishing-a-development-branch/SKILL.md +0 -117
- package/ai-config/skills/workflow/git-github/SKILL.md +0 -334
- package/ai-config/skills/workflow/git-github/references/examples.md +0 -160
- package/ai-config/skills/workflow/git-workflow/SKILL.md +0 -214
- package/ai-config/skills/workflow/ide-plugins/SKILL.md +0 -277
- package/ai-config/skills/workflow/ide-plugins-intellij/SKILL.md +0 -401
- package/ai-config/skills/workflow/obsidian-brain-workflow/SKILL.md +0 -199
- package/ai-config/skills/workflow/using-git-worktrees/SKILL.md +0 -100
- package/ai-config/skills/workflow/verification-before-completion/SKILL.md +0 -73
- package/ai-config/skills/workflow/wave-workflow/SKILL.md +0 -178
- package/schemas/agent.schema.json +0 -34
- package/schemas/ai-config.schema.json +0 -28
- package/schemas/plugin.schema.json +0 -62
- package/schemas/skill.schema.json +0 -44
|
@@ -1,445 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: grpc-spring
|
|
3
|
-
description: >
|
|
4
|
-
Spring Boot gRPC. grpc-spring-boot-starter, service implementation, interceptors.
|
|
5
|
-
Trigger: apigen-grpc, @GrpcService, GrpcServerInterceptor, Protobuf, gRPC Java
|
|
6
|
-
tools:
|
|
7
|
-
- Read
|
|
8
|
-
- Write
|
|
9
|
-
- Edit
|
|
10
|
-
- Bash
|
|
11
|
-
- Grep
|
|
12
|
-
metadata:
|
|
13
|
-
author: apigen-team
|
|
14
|
-
version: "1.0"
|
|
15
|
-
tags: [grpc, spring-boot, protobuf, java]
|
|
16
|
-
scope: ["apigen-grpc/**"]
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
# gRPC Spring Boot (apigen-grpc)
|
|
20
|
-
|
|
21
|
-
## Configuration
|
|
22
|
-
|
|
23
|
-
```yaml
|
|
24
|
-
grpc:
|
|
25
|
-
server:
|
|
26
|
-
port: 9090
|
|
27
|
-
in-process-name: apigen-grpc
|
|
28
|
-
reflection-service-enabled: true
|
|
29
|
-
max-inbound-message-size: 10MB
|
|
30
|
-
|
|
31
|
-
apigen:
|
|
32
|
-
grpc:
|
|
33
|
-
enabled: true
|
|
34
|
-
interceptors:
|
|
35
|
-
logging: true
|
|
36
|
-
metrics: true
|
|
37
|
-
authentication: true
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
## Gradle Configuration
|
|
41
|
-
|
|
42
|
-
```groovy
|
|
43
|
-
plugins {
|
|
44
|
-
id 'com.google.protobuf' version '0.9.4'
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
dependencies {
|
|
48
|
-
implementation 'io.grpc:grpc-netty-shaded:1.72.0'
|
|
49
|
-
implementation 'io.grpc:grpc-protobuf:1.72.0'
|
|
50
|
-
implementation 'io.grpc:grpc-stub:1.72.0'
|
|
51
|
-
implementation 'net.devh:grpc-spring-boot-starter:3.4.0'
|
|
52
|
-
|
|
53
|
-
// For well-known types
|
|
54
|
-
implementation 'com.google.protobuf:protobuf-java-util:4.29.3'
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
protobuf {
|
|
58
|
-
protoc {
|
|
59
|
-
artifact = 'com.google.protobuf:protoc:4.29.3'
|
|
60
|
-
}
|
|
61
|
-
plugins {
|
|
62
|
-
grpc {
|
|
63
|
-
artifact = 'io.grpc:protoc-gen-grpc-java:1.72.0'
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
generateProtoTasks {
|
|
67
|
-
all()*.plugins {
|
|
68
|
-
grpc {}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
## Proto Definition
|
|
75
|
-
|
|
76
|
-
```protobuf
|
|
77
|
-
// src/main/proto/user_service.proto
|
|
78
|
-
syntax = "proto3";
|
|
79
|
-
|
|
80
|
-
package com.jnzader.apigen.grpc;
|
|
81
|
-
|
|
82
|
-
option java_package = "com.jnzader.apigen.grpc.proto";
|
|
83
|
-
option java_multiple_files = true;
|
|
84
|
-
|
|
85
|
-
import "google/protobuf/timestamp.proto";
|
|
86
|
-
import "google/protobuf/empty.proto";
|
|
87
|
-
import "google/protobuf/wrappers.proto";
|
|
88
|
-
|
|
89
|
-
service UserService {
|
|
90
|
-
rpc GetUser(GetUserRequest) returns (UserResponse);
|
|
91
|
-
rpc CreateUser(CreateUserRequest) returns (UserResponse);
|
|
92
|
-
rpc UpdateUser(UpdateUserRequest) returns (UserResponse);
|
|
93
|
-
rpc DeleteUser(DeleteUserRequest) returns (google.protobuf.Empty);
|
|
94
|
-
rpc ListUsers(ListUsersRequest) returns (stream UserResponse);
|
|
95
|
-
rpc BatchCreateUsers(stream CreateUserRequest) returns (BatchCreateResponse);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
message GetUserRequest {
|
|
99
|
-
string user_id = 1;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
message CreateUserRequest {
|
|
103
|
-
string email = 1;
|
|
104
|
-
string name = 2;
|
|
105
|
-
string password = 3;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
message UpdateUserRequest {
|
|
109
|
-
string user_id = 1;
|
|
110
|
-
google.protobuf.StringValue name = 2;
|
|
111
|
-
google.protobuf.StringValue email = 3;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
message DeleteUserRequest {
|
|
115
|
-
string user_id = 1;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
message ListUsersRequest {
|
|
119
|
-
int32 page_size = 1;
|
|
120
|
-
string page_token = 2;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
message UserResponse {
|
|
124
|
-
string id = 1;
|
|
125
|
-
string email = 2;
|
|
126
|
-
string name = 3;
|
|
127
|
-
UserStatus status = 4;
|
|
128
|
-
google.protobuf.Timestamp created_at = 5;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
message BatchCreateResponse {
|
|
132
|
-
int32 created_count = 1;
|
|
133
|
-
repeated string created_ids = 2;
|
|
134
|
-
repeated CreateError errors = 3;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
message CreateError {
|
|
138
|
-
int32 index = 1;
|
|
139
|
-
string message = 2;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
enum UserStatus {
|
|
143
|
-
USER_STATUS_UNSPECIFIED = 0;
|
|
144
|
-
USER_STATUS_ACTIVE = 1;
|
|
145
|
-
USER_STATUS_INACTIVE = 2;
|
|
146
|
-
}
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
## Service Implementation
|
|
150
|
-
|
|
151
|
-
```java
|
|
152
|
-
@GrpcService
|
|
153
|
-
@RequiredArgsConstructor
|
|
154
|
-
public class UserGrpcService extends UserServiceGrpc.UserServiceImplBase {
|
|
155
|
-
|
|
156
|
-
private final UserService userService;
|
|
157
|
-
private final UserMapper userMapper;
|
|
158
|
-
|
|
159
|
-
@Override
|
|
160
|
-
public void getUser(GetUserRequest request,
|
|
161
|
-
StreamObserver<UserResponse> responseObserver) {
|
|
162
|
-
try {
|
|
163
|
-
UUID userId = UUID.fromString(request.getUserId());
|
|
164
|
-
User user = userService.findById(userId)
|
|
165
|
-
.orElseThrow(() -> new StatusRuntimeException(
|
|
166
|
-
Status.NOT_FOUND.withDescription("User not found")));
|
|
167
|
-
|
|
168
|
-
responseObserver.onNext(userMapper.toProto(user));
|
|
169
|
-
responseObserver.onCompleted();
|
|
170
|
-
} catch (IllegalArgumentException e) {
|
|
171
|
-
responseObserver.onError(Status.INVALID_ARGUMENT
|
|
172
|
-
.withDescription("Invalid user ID format")
|
|
173
|
-
.asRuntimeException());
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
@Override
|
|
178
|
-
public void createUser(CreateUserRequest request,
|
|
179
|
-
StreamObserver<UserResponse> responseObserver) {
|
|
180
|
-
try {
|
|
181
|
-
CreateUserDTO dto = new CreateUserDTO(
|
|
182
|
-
request.getEmail(),
|
|
183
|
-
request.getName(),
|
|
184
|
-
request.getPassword()
|
|
185
|
-
);
|
|
186
|
-
|
|
187
|
-
User user = userService.create(dto);
|
|
188
|
-
responseObserver.onNext(userMapper.toProto(user));
|
|
189
|
-
responseObserver.onCompleted();
|
|
190
|
-
} catch (DuplicateEmailException e) {
|
|
191
|
-
responseObserver.onError(Status.ALREADY_EXISTS
|
|
192
|
-
.withDescription("Email already registered")
|
|
193
|
-
.asRuntimeException());
|
|
194
|
-
} catch (ValidationException e) {
|
|
195
|
-
responseObserver.onError(Status.INVALID_ARGUMENT
|
|
196
|
-
.withDescription(e.getMessage())
|
|
197
|
-
.asRuntimeException());
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
@Override
|
|
202
|
-
public void listUsers(ListUsersRequest request,
|
|
203
|
-
StreamObserver<UserResponse> responseObserver) {
|
|
204
|
-
int pageSize = request.getPageSize() > 0 ? request.getPageSize() : 20;
|
|
205
|
-
String pageToken = request.getPageToken();
|
|
206
|
-
|
|
207
|
-
userService.streamAll(pageSize, pageToken)
|
|
208
|
-
.map(userMapper::toProto)
|
|
209
|
-
.forEach(responseObserver::onNext);
|
|
210
|
-
|
|
211
|
-
responseObserver.onCompleted();
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
@Override
|
|
215
|
-
public StreamObserver<CreateUserRequest> batchCreateUsers(
|
|
216
|
-
StreamObserver<BatchCreateResponse> responseObserver) {
|
|
217
|
-
|
|
218
|
-
List<String> createdIds = new ArrayList<>();
|
|
219
|
-
List<CreateError> errors = new ArrayList<>();
|
|
220
|
-
AtomicInteger index = new AtomicInteger(0);
|
|
221
|
-
|
|
222
|
-
return new StreamObserver<>() {
|
|
223
|
-
@Override
|
|
224
|
-
public void onNext(CreateUserRequest request) {
|
|
225
|
-
int currentIndex = index.getAndIncrement();
|
|
226
|
-
try {
|
|
227
|
-
CreateUserDTO dto = new CreateUserDTO(
|
|
228
|
-
request.getEmail(), request.getName(), request.getPassword());
|
|
229
|
-
User user = userService.create(dto);
|
|
230
|
-
createdIds.add(user.getId().toString());
|
|
231
|
-
} catch (Exception e) {
|
|
232
|
-
errors.add(CreateError.newBuilder()
|
|
233
|
-
.setIndex(currentIndex)
|
|
234
|
-
.setMessage(e.getMessage())
|
|
235
|
-
.build());
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
@Override
|
|
240
|
-
public void onError(Throwable t) {
|
|
241
|
-
responseObserver.onError(t);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
@Override
|
|
245
|
-
public void onCompleted() {
|
|
246
|
-
responseObserver.onNext(BatchCreateResponse.newBuilder()
|
|
247
|
-
.setCreatedCount(createdIds.size())
|
|
248
|
-
.addAllCreatedIds(createdIds)
|
|
249
|
-
.addAllErrors(errors)
|
|
250
|
-
.build());
|
|
251
|
-
responseObserver.onCompleted();
|
|
252
|
-
}
|
|
253
|
-
};
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
## Mapper
|
|
259
|
-
|
|
260
|
-
```java
|
|
261
|
-
@Mapper(componentModel = "spring")
|
|
262
|
-
public interface UserMapper {
|
|
263
|
-
|
|
264
|
-
@Mapping(target = "id", source = "id", qualifiedByName = "uuidToString")
|
|
265
|
-
@Mapping(target = "createdAt", source = "createdAt", qualifiedByName = "instantToTimestamp")
|
|
266
|
-
@Mapping(target = "status", source = "status", qualifiedByName = "statusToProto")
|
|
267
|
-
UserResponse toProto(User user);
|
|
268
|
-
|
|
269
|
-
@Named("uuidToString")
|
|
270
|
-
default String uuidToString(UUID uuid) {
|
|
271
|
-
return uuid != null ? uuid.toString() : "";
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
@Named("instantToTimestamp")
|
|
275
|
-
default Timestamp instantToTimestamp(Instant instant) {
|
|
276
|
-
if (instant == null) return Timestamp.getDefaultInstance();
|
|
277
|
-
return Timestamp.newBuilder()
|
|
278
|
-
.setSeconds(instant.getEpochSecond())
|
|
279
|
-
.setNanos(instant.getNano())
|
|
280
|
-
.build();
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
@Named("statusToProto")
|
|
284
|
-
default UserStatus statusToProto(com.jnzader.apigen.domain.UserStatus status) {
|
|
285
|
-
return switch (status) {
|
|
286
|
-
case ACTIVE -> UserStatus.USER_STATUS_ACTIVE;
|
|
287
|
-
case INACTIVE -> UserStatus.USER_STATUS_INACTIVE;
|
|
288
|
-
default -> UserStatus.USER_STATUS_UNSPECIFIED;
|
|
289
|
-
};
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
```
|
|
293
|
-
|
|
294
|
-
## Interceptors
|
|
295
|
-
|
|
296
|
-
### Authentication Interceptor
|
|
297
|
-
|
|
298
|
-
```java
|
|
299
|
-
@GrpcGlobalServerInterceptor
|
|
300
|
-
@RequiredArgsConstructor
|
|
301
|
-
public class AuthenticationInterceptor implements ServerInterceptor {
|
|
302
|
-
|
|
303
|
-
private final JwtService jwtService;
|
|
304
|
-
public static final Context.Key<String> USER_ID_KEY = Context.key("userId");
|
|
305
|
-
|
|
306
|
-
@Override
|
|
307
|
-
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
|
|
308
|
-
ServerCall<ReqT, RespT> call,
|
|
309
|
-
Metadata headers,
|
|
310
|
-
ServerCallHandler<ReqT, RespT> next) {
|
|
311
|
-
|
|
312
|
-
String token = headers.get(Metadata.Key.of("authorization", ASCII_STRING_MARSHALLER));
|
|
313
|
-
|
|
314
|
-
if (token == null || !token.startsWith("Bearer ")) {
|
|
315
|
-
call.close(Status.UNAUTHENTICATED.withDescription("Missing token"), new Metadata());
|
|
316
|
-
return new ServerCall.Listener<>() {};
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
try {
|
|
320
|
-
String userId = jwtService.validateAndGetUserId(token.substring(7));
|
|
321
|
-
Context context = Context.current().withValue(USER_ID_KEY, userId);
|
|
322
|
-
return Contexts.interceptCall(context, call, headers, next);
|
|
323
|
-
} catch (Exception e) {
|
|
324
|
-
call.close(Status.UNAUTHENTICATED.withDescription("Invalid token"), new Metadata());
|
|
325
|
-
return new ServerCall.Listener<>() {};
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
```
|
|
330
|
-
|
|
331
|
-
### Logging Interceptor
|
|
332
|
-
|
|
333
|
-
```java
|
|
334
|
-
@GrpcGlobalServerInterceptor
|
|
335
|
-
@Slf4j
|
|
336
|
-
public class LoggingInterceptor implements ServerInterceptor {
|
|
337
|
-
|
|
338
|
-
@Override
|
|
339
|
-
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
|
|
340
|
-
ServerCall<ReqT, RespT> call,
|
|
341
|
-
Metadata headers,
|
|
342
|
-
ServerCallHandler<ReqT, RespT> next) {
|
|
343
|
-
|
|
344
|
-
String methodName = call.getMethodDescriptor().getFullMethodName();
|
|
345
|
-
long startTime = System.currentTimeMillis();
|
|
346
|
-
|
|
347
|
-
log.info("gRPC request: {}", methodName);
|
|
348
|
-
|
|
349
|
-
return new ForwardingServerCallListener.SimpleForwardingServerCallListener<>(
|
|
350
|
-
next.startCall(call, headers)) {
|
|
351
|
-
|
|
352
|
-
@Override
|
|
353
|
-
public void onComplete() {
|
|
354
|
-
long duration = System.currentTimeMillis() - startTime;
|
|
355
|
-
log.info("gRPC response: {} completed in {}ms", methodName, duration);
|
|
356
|
-
super.onComplete();
|
|
357
|
-
}
|
|
358
|
-
};
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
```
|
|
362
|
-
|
|
363
|
-
## gRPC Client
|
|
364
|
-
|
|
365
|
-
```java
|
|
366
|
-
@Service
|
|
367
|
-
public class UserGrpcClient {
|
|
368
|
-
|
|
369
|
-
private final UserServiceGrpc.UserServiceBlockingStub blockingStub;
|
|
370
|
-
private final UserServiceGrpc.UserServiceStub asyncStub;
|
|
371
|
-
|
|
372
|
-
public UserGrpcClient(@GrpcClient("user-service") ManagedChannel channel) {
|
|
373
|
-
this.blockingStub = UserServiceGrpc.newBlockingStub(channel);
|
|
374
|
-
this.asyncStub = UserServiceGrpc.newStub(channel);
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
public UserResponse getUser(String userId) {
|
|
378
|
-
return blockingStub.getUser(GetUserRequest.newBuilder()
|
|
379
|
-
.setUserId(userId)
|
|
380
|
-
.build());
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
public void listUsersAsync(Consumer<UserResponse> consumer) {
|
|
384
|
-
asyncStub.listUsers(
|
|
385
|
-
ListUsersRequest.newBuilder().setPageSize(100).build(),
|
|
386
|
-
new StreamObserver<>() {
|
|
387
|
-
@Override
|
|
388
|
-
public void onNext(UserResponse value) {
|
|
389
|
-
consumer.accept(value);
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
@Override
|
|
393
|
-
public void onError(Throwable t) {
|
|
394
|
-
log.error("Error streaming users", t);
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
@Override
|
|
398
|
-
public void onCompleted() {
|
|
399
|
-
log.info("User stream completed");
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
);
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
```
|
|
406
|
-
|
|
407
|
-
## Testing
|
|
408
|
-
|
|
409
|
-
```java
|
|
410
|
-
@SpringBootTest
|
|
411
|
-
@DirtiesContext
|
|
412
|
-
class UserGrpcServiceTest {
|
|
413
|
-
|
|
414
|
-
@Autowired
|
|
415
|
-
private UserGrpcService userGrpcService;
|
|
416
|
-
|
|
417
|
-
@MockBean
|
|
418
|
-
private UserService userService;
|
|
419
|
-
|
|
420
|
-
@Test
|
|
421
|
-
void shouldGetUser() {
|
|
422
|
-
User user = new User(UUID.randomUUID(), "test@example.com", "Test");
|
|
423
|
-
when(userService.findById(user.getId())).thenReturn(Optional.of(user));
|
|
424
|
-
|
|
425
|
-
StreamRecorder<UserResponse> responseObserver = StreamRecorder.create();
|
|
426
|
-
userGrpcService.getUser(
|
|
427
|
-
GetUserRequest.newBuilder().setUserId(user.getId().toString()).build(),
|
|
428
|
-
responseObserver
|
|
429
|
-
);
|
|
430
|
-
|
|
431
|
-
assertThat(responseObserver.getError()).isNull();
|
|
432
|
-
assertThat(responseObserver.getValues()).hasSize(1);
|
|
433
|
-
assertThat(responseObserver.getValues().get(0).getEmail())
|
|
434
|
-
.isEqualTo("test@example.com");
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
```
|
|
438
|
-
|
|
439
|
-
## Related Skills
|
|
440
|
-
|
|
441
|
-
- `grpc-concepts`: gRPC concepts
|
|
442
|
-
- `spring-boot-4`: Spring Boot 4.0 patterns
|
|
443
|
-
- `apigen-architecture`: Overall system architecture
|
|
444
|
-
|
|
445
|
-
|