polyforge-cli 0.1.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/LICENSE +21 -0
- package/README.md +65 -0
- package/dist/commands/create.js +46 -0
- package/dist/commands/doctor.js +136 -0
- package/dist/commands/list.js +32 -0
- package/dist/core/git.js +25 -0
- package/dist/core/installer.js +64 -0
- package/dist/core/prompts.js +147 -0
- package/dist/core/renderer.js +175 -0
- package/dist/core/validator.js +86 -0
- package/dist/index.js +47 -0
- package/dist/templates/backend/go-gin/apps/api/Makefile +10 -0
- package/dist/templates/backend/go-gin/apps/api/cmd/server/main.go +29 -0
- package/dist/templates/backend/go-gin/apps/api/go.mod +5 -0
- package/dist/templates/backend/go-gin/apps/api/internal/config/config.go +22 -0
- package/dist/templates/backend/go-gin/apps/api/internal/handler/health.go +27 -0
- package/dist/templates/backend/go-gin/apps/api/internal/handler/helpers.go +8 -0
- package/dist/templates/backend/go-gin/apps/api/internal/handler/ping.go +15 -0
- package/dist/templates/backend/go-gin/apps/api/internal/middleware/logger.go +18 -0
- package/dist/templates/backend/go-gin/apps/api/internal/middleware/recovery.go +23 -0
- package/dist/templates/backend/go-gin/apps/api/internal/middleware/trace.go +28 -0
- package/dist/templates/backend/go-gin/apps/api/internal/repository/ping.go +11 -0
- package/dist/templates/backend/go-gin/apps/api/internal/service/ping.go +17 -0
- package/dist/templates/backend/go-gin/apps/api/pkg/response/response.go +35 -0
- package/dist/templates/backend/go-gin/apps/api/pkg/response/response_test.go +21 -0
- package/dist/templates/backend/springboot/apps/api/pom.xml +44 -0
- package/dist/templates/backend/springboot/apps/api/src/main/java/com/scaffold/api/Application.java +11 -0
- package/dist/templates/backend/springboot/apps/api/src/main/java/com/scaffold/api/common/ApiResponse.java +19 -0
- package/dist/templates/backend/springboot/apps/api/src/main/java/com/scaffold/api/common/GlobalExceptionHandler.java +22 -0
- package/dist/templates/backend/springboot/apps/api/src/main/java/com/scaffold/api/common/TraceIdHolder.java +19 -0
- package/dist/templates/backend/springboot/apps/api/src/main/java/com/scaffold/api/config/TraceIdFilter.java +38 -0
- package/dist/templates/backend/springboot/apps/api/src/main/java/com/scaffold/api/controller/HealthController.java +17 -0
- package/dist/templates/backend/springboot/apps/api/src/main/java/com/scaffold/api/controller/PingController.java +23 -0
- package/dist/templates/backend/springboot/apps/api/src/main/java/com/scaffold/api/repository/PingRepository.java +10 -0
- package/dist/templates/backend/springboot/apps/api/src/main/java/com/scaffold/api/service/PingService.java +17 -0
- package/dist/templates/backend/springboot/apps/api/src/main/resources/application-dev.yml +2 -0
- package/dist/templates/backend/springboot/apps/api/src/main/resources/application-prod.yml +2 -0
- package/dist/templates/backend/springboot/apps/api/src/main/resources/application-test.yml +2 -0
- package/dist/templates/backend/springboot/apps/api/src/main/resources/application.yml +8 -0
- package/dist/templates/backend/springboot/apps/api/src/test/java/com/scaffold/api/ApplicationTests.java +12 -0
- package/dist/templates/base/.env.example +5 -0
- package/dist/templates/base/docs/ARCHITECTURE.md +9 -0
- package/dist/templates/base/infra/scripts/build.sh +39 -0
- package/dist/templates/base/infra/scripts/check.sh +58 -0
- package/dist/templates/base/infra/scripts/dev.sh +32 -0
- package/dist/templates/base/infra/scripts/test.sh +41 -0
- package/dist/templates/base/package.json +11 -0
- package/dist/templates/data/mongodb/infra/data/mongodb/README.md +4 -0
- package/dist/templates/data/mysql/infra/data/mysql/README.md +4 -0
- package/dist/templates/data/mysql/infra/data/mysql/schema.sql +5 -0
- package/dist/templates/data/postgresql/infra/data/postgresql/README.md +4 -0
- package/dist/templates/data/postgresql/infra/data/postgresql/schema.sql +5 -0
- package/dist/templates/data/redis/infra/data/redis/README.md +4 -0
- package/dist/templates/data/sqlite/infra/data/sqlite/README.md +4 -0
- package/dist/templates/frontend/react/apps/web/.env.example +4 -0
- package/dist/templates/frontend/react/apps/web/index.html +12 -0
- package/dist/templates/frontend/react/apps/web/package.json +23 -0
- package/dist/templates/frontend/react/apps/web/src/App.test.tsx +7 -0
- package/dist/templates/frontend/react/apps/web/src/App.tsx +59 -0
- package/dist/templates/frontend/react/apps/web/src/api/client.ts +20 -0
- package/dist/templates/frontend/react/apps/web/src/api/request.ts +104 -0
- package/dist/templates/frontend/react/apps/web/src/api/services/api.ts +15 -0
- package/dist/templates/frontend/react/apps/web/src/api/services/bff.ts +11 -0
- package/dist/templates/frontend/react/apps/web/src/main.tsx +9 -0
- package/dist/templates/frontend/react/apps/web/tsconfig.json +12 -0
- package/dist/templates/frontend/react/apps/web/vite.config.ts +22 -0
- package/dist/templates/frontend/vue/apps/web/.env.example +4 -0
- package/dist/templates/frontend/vue/apps/web/index.html +12 -0
- package/dist/templates/frontend/vue/apps/web/package.json +20 -0
- package/dist/templates/frontend/vue/apps/web/src/App.test.ts +7 -0
- package/dist/templates/frontend/vue/apps/web/src/App.vue +59 -0
- package/dist/templates/frontend/vue/apps/web/src/api/client.ts +20 -0
- package/dist/templates/frontend/vue/apps/web/src/api/request.ts +104 -0
- package/dist/templates/frontend/vue/apps/web/src/api/services/api.ts +15 -0
- package/dist/templates/frontend/vue/apps/web/src/api/services/bff.ts +11 -0
- package/dist/templates/frontend/vue/apps/web/src/env.d.ts +3 -0
- package/dist/templates/frontend/vue/apps/web/src/main.ts +4 -0
- package/dist/templates/frontend/vue/apps/web/tsconfig.json +11 -0
- package/dist/templates/frontend/vue/apps/web/vite.config.ts +22 -0
- package/dist/templates/modules/auth-center/apps/auth-center/.env.example +3 -0
- package/dist/templates/modules/auth-center/apps/auth-center/README.md +5 -0
- package/dist/templates/modules/auth-center/apps/auth-center/package.json +14 -0
- package/dist/templates/modules/auth-center/apps/auth-center/server.js +21 -0
- package/dist/templates/modules/cache-redis/infra/cache/README.md +5 -0
- package/dist/templates/modules/cache-redis/infra/cache/policies.md +5 -0
- package/dist/templates/modules/gateway-bff/apps/gateway-bff/README.md +5 -0
- package/dist/templates/modules/gateway-bff/apps/gateway-bff/package.json +13 -0
- package/dist/templates/modules/gateway-bff/apps/gateway-bff/server.js +17 -0
- package/dist/templates/modules/grpc-service/apps/grpc-service/README.md +5 -0
- package/dist/templates/modules/grpc-service/contracts/proto/greeter.proto +17 -0
- package/dist/templates/modules/grpc-service/infra/scripts/gen-proto.sh +9 -0
- package/dist/templates/modules/mq/infra/mq/README.md +5 -0
- package/dist/templates/modules/mq/infra/mq/kafka-topics.md +5 -0
- package/dist/templates/modules/mq/infra/mq/nats-subjects.md +4 -0
- package/dist/templates/modules/mq/infra/mq/rabbitmq-exchanges.md +5 -0
- package/dist/templates/modules/observability/infra/observability/README.md +5 -0
- package/dist/templates/modules/observability/infra/observability/grafana/README.md +3 -0
- package/dist/templates/modules/observability/infra/observability/otel-collector.yaml +15 -0
- package/dist/templates/modules/observability/infra/observability/prometheus/prometheus.yml +7 -0
- package/dist/templates/modules/python-ai/apps/python-ai/README.md +5 -0
- package/dist/templates/modules/python-ai/apps/python-ai/app/main.py +27 -0
- package/dist/templates/modules/python-ai/apps/python-ai/requirements.txt +2 -0
- package/dist/templates/modules/python-ai/apps/python-ai/scripts/batch_infer.py +6 -0
- package/dist/templates/modules/python-worker/apps/worker-python/README.md +5 -0
- package/dist/templates/modules/python-worker/apps/worker-python/requirements.txt +1 -0
- package/dist/templates/modules/python-worker/apps/worker-python/tasks/sample_task.py +6 -0
- package/dist/templates/modules/python-worker/apps/worker-python/tests/test_worker.py +13 -0
- package/dist/templates/modules/python-worker/apps/worker-python/worker.py +10 -0
- package/dist/templates/modules/worker-go/apps/worker-go/README.md +5 -0
- package/dist/templates/modules/worker-go/apps/worker-go/cmd/worker/main.go +16 -0
- package/dist/templates/modules/worker-go/apps/worker-go/go.mod +3 -0
- package/dist/templates/modules/worker-go/apps/worker-go/internal/tasks/heartbeat.go +7 -0
- package/dist/types/config.js +18 -0
- package/package.json +52 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
package com.scaffold.api.common;
|
|
2
|
+
|
|
3
|
+
import org.springframework.http.HttpStatus;
|
|
4
|
+
import org.springframework.http.ResponseEntity;
|
|
5
|
+
import org.springframework.web.bind.MethodArgumentNotValidException;
|
|
6
|
+
import org.springframework.web.bind.annotation.ControllerAdvice;
|
|
7
|
+
import org.springframework.web.bind.annotation.ExceptionHandler;
|
|
8
|
+
|
|
9
|
+
@ControllerAdvice
|
|
10
|
+
public class GlobalExceptionHandler {
|
|
11
|
+
|
|
12
|
+
@ExceptionHandler(MethodArgumentNotValidException.class)
|
|
13
|
+
public ResponseEntity<ApiResponse<Void>> handleValidation(MethodArgumentNotValidException ex) {
|
|
14
|
+
return ResponseEntity.badRequest().body(ApiResponse.error(10001, "validation error", TraceIdHolder.get()));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@ExceptionHandler(Exception.class)
|
|
18
|
+
public ResponseEntity<ApiResponse<Void>> handleException(Exception ex) {
|
|
19
|
+
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
|
20
|
+
.body(ApiResponse.error(10000, "internal server error", TraceIdHolder.get()));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
package com.scaffold.api.common;
|
|
2
|
+
|
|
3
|
+
public final class TraceIdHolder {
|
|
4
|
+
private static final ThreadLocal<String> HOLDER = new ThreadLocal<>();
|
|
5
|
+
|
|
6
|
+
private TraceIdHolder() {}
|
|
7
|
+
|
|
8
|
+
public static void set(String traceId) {
|
|
9
|
+
HOLDER.set(traceId);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
public static String get() {
|
|
13
|
+
return HOLDER.get();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
public static void clear() {
|
|
17
|
+
HOLDER.remove();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
package com.scaffold.api.config;
|
|
2
|
+
|
|
3
|
+
import com.scaffold.api.common.TraceIdHolder;
|
|
4
|
+
import jakarta.servlet.FilterChain;
|
|
5
|
+
import jakarta.servlet.ServletException;
|
|
6
|
+
import jakarta.servlet.http.HttpServletRequest;
|
|
7
|
+
import jakarta.servlet.http.HttpServletResponse;
|
|
8
|
+
import org.slf4j.MDC;
|
|
9
|
+
import org.springframework.stereotype.Component;
|
|
10
|
+
import org.springframework.web.filter.OncePerRequestFilter;
|
|
11
|
+
|
|
12
|
+
import java.io.IOException;
|
|
13
|
+
import java.util.UUID;
|
|
14
|
+
|
|
15
|
+
@Component
|
|
16
|
+
public class TraceIdFilter extends OncePerRequestFilter {
|
|
17
|
+
private static final String TRACE_HEADER = "X-Trace-Id";
|
|
18
|
+
|
|
19
|
+
@Override
|
|
20
|
+
protected void doFilterInternal(HttpServletRequest request,
|
|
21
|
+
HttpServletResponse response,
|
|
22
|
+
FilterChain filterChain) throws ServletException, IOException {
|
|
23
|
+
String traceId = request.getHeader(TRACE_HEADER);
|
|
24
|
+
if (traceId == null || traceId.isBlank()) {
|
|
25
|
+
traceId = UUID.randomUUID().toString().replace("-", "").substring(0, 16);
|
|
26
|
+
}
|
|
27
|
+
TraceIdHolder.set(traceId);
|
|
28
|
+
MDC.put("traceId", traceId);
|
|
29
|
+
response.setHeader(TRACE_HEADER, traceId);
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
filterChain.doFilter(request, response);
|
|
33
|
+
} finally {
|
|
34
|
+
TraceIdHolder.clear();
|
|
35
|
+
MDC.remove("traceId");
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
package com.scaffold.api.controller;
|
|
2
|
+
|
|
3
|
+
import com.scaffold.api.common.ApiResponse;
|
|
4
|
+
import com.scaffold.api.common.TraceIdHolder;
|
|
5
|
+
import org.springframework.web.bind.annotation.GetMapping;
|
|
6
|
+
import org.springframework.web.bind.annotation.RestController;
|
|
7
|
+
|
|
8
|
+
import java.util.Map;
|
|
9
|
+
|
|
10
|
+
@RestController
|
|
11
|
+
public class HealthController {
|
|
12
|
+
|
|
13
|
+
@GetMapping("/health")
|
|
14
|
+
public ApiResponse<Map<String, String>> health() {
|
|
15
|
+
return ApiResponse.success(Map.of("status", "ok"), TraceIdHolder.get());
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
package com.scaffold.api.controller;
|
|
2
|
+
|
|
3
|
+
import com.scaffold.api.common.ApiResponse;
|
|
4
|
+
import com.scaffold.api.common.TraceIdHolder;
|
|
5
|
+
import com.scaffold.api.service.PingService;
|
|
6
|
+
import org.springframework.web.bind.annotation.GetMapping;
|
|
7
|
+
import org.springframework.web.bind.annotation.RestController;
|
|
8
|
+
|
|
9
|
+
import java.util.Map;
|
|
10
|
+
|
|
11
|
+
@RestController
|
|
12
|
+
public class PingController {
|
|
13
|
+
private final PingService pingService;
|
|
14
|
+
|
|
15
|
+
public PingController(PingService pingService) {
|
|
16
|
+
this.pingService = pingService;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@GetMapping("/api/v1/ping")
|
|
20
|
+
public ApiResponse<Map<String, String>> ping() {
|
|
21
|
+
return ApiResponse.success(Map.of("message", pingService.ping()), TraceIdHolder.get());
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
package com.scaffold.api.service;
|
|
2
|
+
|
|
3
|
+
import com.scaffold.api.repository.PingRepository;
|
|
4
|
+
import org.springframework.stereotype.Service;
|
|
5
|
+
|
|
6
|
+
@Service
|
|
7
|
+
public class PingService {
|
|
8
|
+
private final PingRepository pingRepository;
|
|
9
|
+
|
|
10
|
+
public PingService(PingRepository pingRepository) {
|
|
11
|
+
this.pingRepository = pingRepository;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
public String ping() {
|
|
15
|
+
return pingRepository.message();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Architecture Notes
|
|
2
|
+
|
|
3
|
+
- Unified response payload: code/message/data/traceId/timestamp
|
|
4
|
+
- Health endpoint: `/health`
|
|
5
|
+
- Trace propagation header: `X-Trace-Id`
|
|
6
|
+
- Backend main stack: `{{BACKEND_MAIN}}`
|
|
7
|
+
- Frontend: `{{FRONTEND}}`
|
|
8
|
+
- Data modules: `{{DATA_MODULES}}`
|
|
9
|
+
- Extra modules: `{{EXTRA_MODULES}}`
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
echo "[build] building project"
|
|
5
|
+
if [[ -d apps/web && -f apps/web/package.json ]]; then
|
|
6
|
+
if command -v npm >/dev/null 2>&1; then
|
|
7
|
+
(cd apps/web && npm run build || true)
|
|
8
|
+
fi
|
|
9
|
+
fi
|
|
10
|
+
|
|
11
|
+
if [[ -f apps/api/go.mod ]]; then
|
|
12
|
+
if command -v go >/dev/null 2>&1; then
|
|
13
|
+
(cd apps/api && go mod tidy && go build ./...)
|
|
14
|
+
fi
|
|
15
|
+
elif [[ -f apps/api/pom.xml ]]; then
|
|
16
|
+
if command -v mvn >/dev/null 2>&1; then
|
|
17
|
+
(cd apps/api && mvn -q -DskipTests package)
|
|
18
|
+
fi
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
if [[ -f apps/worker-go/go.mod ]]; then
|
|
22
|
+
if command -v go >/dev/null 2>&1; then
|
|
23
|
+
(cd apps/worker-go && go mod tidy && go build ./...)
|
|
24
|
+
fi
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
if [[ -f apps/gateway-bff/package.json ]]; then
|
|
28
|
+
if command -v npm >/dev/null 2>&1; then
|
|
29
|
+
(cd apps/gateway-bff && npm run build || true)
|
|
30
|
+
fi
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
if [[ -f apps/auth-center/package.json ]]; then
|
|
34
|
+
if command -v npm >/dev/null 2>&1; then
|
|
35
|
+
(cd apps/auth-center && npm run build || true)
|
|
36
|
+
fi
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
echo "[build] done"
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
echo "[check] workspace sanity"
|
|
5
|
+
if [[ ! -f package.json ]]; then
|
|
6
|
+
echo "[check] package.json missing at repo root" >&2
|
|
7
|
+
exit 1
|
|
8
|
+
fi
|
|
9
|
+
|
|
10
|
+
if [[ -d apps/api ]]; then
|
|
11
|
+
if [[ -f apps/api/go.mod ]]; then
|
|
12
|
+
if command -v go >/dev/null 2>&1; then
|
|
13
|
+
(cd apps/api && go mod tidy && go test ./...)
|
|
14
|
+
else
|
|
15
|
+
echo "[check] go missing, skip go test"
|
|
16
|
+
fi
|
|
17
|
+
elif [[ -f apps/api/pom.xml ]]; then
|
|
18
|
+
if command -v mvn >/dev/null 2>&1; then
|
|
19
|
+
(cd apps/api && mvn -q -DskipTests verify)
|
|
20
|
+
else
|
|
21
|
+
echo "[check] maven missing, skip spring verify"
|
|
22
|
+
fi
|
|
23
|
+
fi
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
if [[ -f apps/worker-go/go.mod ]]; then
|
|
27
|
+
if command -v go >/dev/null 2>&1; then
|
|
28
|
+
(cd apps/worker-go && go mod tidy && go test ./...)
|
|
29
|
+
else
|
|
30
|
+
echo "[check] go missing, skip worker-go tests"
|
|
31
|
+
fi
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
if [[ -f apps/gateway-bff/server.js ]]; then
|
|
35
|
+
if command -v node >/dev/null 2>&1; then
|
|
36
|
+
node --check apps/gateway-bff/server.js
|
|
37
|
+
else
|
|
38
|
+
echo "[check] node missing, skip gateway-bff syntax check"
|
|
39
|
+
fi
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
if [[ -f apps/auth-center/server.js ]]; then
|
|
43
|
+
if command -v node >/dev/null 2>&1; then
|
|
44
|
+
node --check apps/auth-center/server.js
|
|
45
|
+
else
|
|
46
|
+
echo "[check] node missing, skip auth-center syntax check"
|
|
47
|
+
fi
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
if [[ -f apps/python-ai/app/main.py ]]; then
|
|
51
|
+
if command -v python3 >/dev/null 2>&1; then
|
|
52
|
+
python3 -m py_compile apps/python-ai/app/main.py
|
|
53
|
+
else
|
|
54
|
+
echo "[check] python3 missing, skip python-ai compile check"
|
|
55
|
+
fi
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
echo "[check] done"
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
echo "[dev] starting minimal development flow"
|
|
5
|
+
|
|
6
|
+
if [[ -d apps/web ]]; then
|
|
7
|
+
echo "[dev] frontend available at apps/web"
|
|
8
|
+
fi
|
|
9
|
+
|
|
10
|
+
if [[ -f apps/api/go.mod ]]; then
|
|
11
|
+
if command -v go >/dev/null 2>&1; then
|
|
12
|
+
echo "[dev] running go api"
|
|
13
|
+
(cd apps/api && go mod tidy && go run ./cmd/server)
|
|
14
|
+
else
|
|
15
|
+
echo "[dev] go missing, skip api startup"
|
|
16
|
+
fi
|
|
17
|
+
elif [[ -f apps/api/pom.xml ]]; then
|
|
18
|
+
if command -v mvn >/dev/null 2>&1; then
|
|
19
|
+
echo "[dev] running spring api"
|
|
20
|
+
(cd apps/api && mvn spring-boot:run)
|
|
21
|
+
else
|
|
22
|
+
echo "[dev] maven missing, skip api startup"
|
|
23
|
+
fi
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
if [[ -f apps/gateway-bff/server.js ]]; then
|
|
27
|
+
echo "[dev] gateway-bff available at apps/gateway-bff"
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
if [[ -f apps/python-ai/app/main.py ]]; then
|
|
31
|
+
echo "[dev] python-ai available at apps/python-ai"
|
|
32
|
+
fi
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
echo "[test] running tests"
|
|
5
|
+
if [[ -d apps/web && -f apps/web/package.json ]]; then
|
|
6
|
+
if command -v npm >/dev/null 2>&1; then
|
|
7
|
+
(cd apps/web && npm run test -- --run || true)
|
|
8
|
+
fi
|
|
9
|
+
fi
|
|
10
|
+
|
|
11
|
+
if [[ -f apps/api/go.mod ]]; then
|
|
12
|
+
if command -v go >/dev/null 2>&1; then
|
|
13
|
+
(cd apps/api && go mod tidy && go test ./...)
|
|
14
|
+
fi
|
|
15
|
+
elif [[ -f apps/api/pom.xml ]]; then
|
|
16
|
+
if command -v mvn >/dev/null 2>&1; then
|
|
17
|
+
(cd apps/api && mvn -q test)
|
|
18
|
+
fi
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
if [[ -d apps/worker-python ]]; then
|
|
22
|
+
if command -v python3 >/dev/null 2>&1; then
|
|
23
|
+
(cd apps/worker-python && python3 -m unittest -q)
|
|
24
|
+
else
|
|
25
|
+
echo "[test] python missing, skip worker tests"
|
|
26
|
+
fi
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
if [[ -f apps/worker-go/go.mod ]]; then
|
|
30
|
+
if command -v go >/dev/null 2>&1; then
|
|
31
|
+
(cd apps/worker-go && go mod tidy && go test ./...)
|
|
32
|
+
fi
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
if [[ -f apps/python-ai/app/main.py ]]; then
|
|
36
|
+
if command -v python3 >/dev/null 2>&1; then
|
|
37
|
+
python3 -m py_compile apps/python-ai/app/main.py
|
|
38
|
+
fi
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
echo "[test] done"
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>{{PROJECT_NAME}} web</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<div id="root"></div>
|
|
10
|
+
<script type="module" src="/src/main.tsx"></script>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{PROJECT_NAME}}-web",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite",
|
|
8
|
+
"build": "vite build",
|
|
9
|
+
"test": "vitest"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"react": "^18.3.1",
|
|
13
|
+
"react-dom": "^18.3.1"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@types/react": "^18.3.8",
|
|
17
|
+
"@types/react-dom": "^18.3.0",
|
|
18
|
+
"@vitejs/plugin-react": "^4.4.0",
|
|
19
|
+
"typescript": "^5.9.2",
|
|
20
|
+
"vite": "^5.4.8",
|
|
21
|
+
"vitest": "^2.1.3"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import {
|
|
3
|
+
availableServices,
|
|
4
|
+
getApiBase,
|
|
5
|
+
getBffBase,
|
|
6
|
+
hasBffEnabled,
|
|
7
|
+
pingApi,
|
|
8
|
+
pingBff,
|
|
9
|
+
type ApiPayload,
|
|
10
|
+
} from "./api/client";
|
|
11
|
+
|
|
12
|
+
const HAS_BFF = hasBffEnabled();
|
|
13
|
+
|
|
14
|
+
export function App() {
|
|
15
|
+
const [apiResult, setApiResult] = useState<ApiPayload | null>(null);
|
|
16
|
+
const [apiError, setApiError] = useState<string>("");
|
|
17
|
+
const [bffResult, setBffResult] = useState<ApiPayload | null>(null);
|
|
18
|
+
const [bffError, setBffError] = useState<string>("");
|
|
19
|
+
|
|
20
|
+
const callApi = async () => {
|
|
21
|
+
setApiError("");
|
|
22
|
+
try {
|
|
23
|
+
setApiResult(await pingApi());
|
|
24
|
+
} catch (error) {
|
|
25
|
+
setApiError(error instanceof Error ? error.message : String(error));
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const callBff = async () => {
|
|
30
|
+
if (!HAS_BFF) return;
|
|
31
|
+
setBffError("");
|
|
32
|
+
try {
|
|
33
|
+
setBffResult(await pingBff());
|
|
34
|
+
} catch (error) {
|
|
35
|
+
setBffError(error instanceof Error ? error.message : String(error));
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<main style={{ fontFamily: "sans-serif", padding: 24, maxWidth: 900 }}>
|
|
41
|
+
<h1>{{PROJECT_NAME}} - React</h1>
|
|
42
|
+
<p>API base: <code>{getApiBase()}</code> | BFF base: <code>{getBffBase()}</code></p>
|
|
43
|
+
<p>Available services: <code>{availableServices.join(", ")}</code></p>
|
|
44
|
+
|
|
45
|
+
<section style={{ marginBottom: 20 }}>
|
|
46
|
+
<button onClick={callApi}>Call API /api/v1/ping</button>
|
|
47
|
+
{apiError ? <p style={{ color: "crimson" }}>{apiError}</p> : null}
|
|
48
|
+
{apiResult ? <pre>{JSON.stringify(apiResult, null, 2)}</pre> : null}
|
|
49
|
+
</section>
|
|
50
|
+
|
|
51
|
+
<section>
|
|
52
|
+
<button onClick={callBff} disabled={!HAS_BFF}>Call BFF /bff/ping</button>
|
|
53
|
+
{!HAS_BFF ? <p>BFF module not selected. Enable <code>gateway-bff</code> to use this call.</p> : null}
|
|
54
|
+
{bffError ? <p style={{ color: "crimson" }}>{bffError}</p> : null}
|
|
55
|
+
{bffResult ? <pre>{JSON.stringify(bffResult, null, 2)}</pre> : null}
|
|
56
|
+
</section>
|
|
57
|
+
</main>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type ApiPayload } from "./request";
|
|
2
|
+
import { getApiBase, healthApi, pingApi } from "./services/api";
|
|
3
|
+
import { getBffBase, pingBff as pingBffService } from "./services/bff";
|
|
4
|
+
|
|
5
|
+
const HAS_BFF = "{{HAS_GATEWAY_BFF}}" === "true";
|
|
6
|
+
|
|
7
|
+
export { type ApiPayload, getApiBase, healthApi, pingApi, getBffBase };
|
|
8
|
+
|
|
9
|
+
export const availableServices = HAS_BFF ? ["api", "bff"] as const : ["api"] as const;
|
|
10
|
+
|
|
11
|
+
export async function pingBff(): Promise<ApiPayload<{ message: string }>> {
|
|
12
|
+
if (!HAS_BFF) {
|
|
13
|
+
throw new Error("gateway-bff module not enabled");
|
|
14
|
+
}
|
|
15
|
+
return pingBffService();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function hasBffEnabled(): boolean {
|
|
19
|
+
return HAS_BFF;
|
|
20
|
+
}
|