javi-forge 1.2.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 +20 -8
- package/package.json +1 -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,340 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: analytics-spring
|
|
3
|
-
description: >
|
|
4
|
-
Spring Boot analytics with multi-provider support. GA4, Mixpanel, Amplitude, Segment.
|
|
5
|
-
Trigger: apigen-analytics, AnalyticsService, provider, tracking, Spring analytics
|
|
6
|
-
tools:
|
|
7
|
-
- Read
|
|
8
|
-
- Write
|
|
9
|
-
- Edit
|
|
10
|
-
- Bash
|
|
11
|
-
- Grep
|
|
12
|
-
metadata:
|
|
13
|
-
author: apigen-team
|
|
14
|
-
version: "1.0"
|
|
15
|
-
tags: [analytics, spring-boot, providers, java]
|
|
16
|
-
scope: ["apigen-analytics/**"]
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
# Analytics Spring Boot (apigen-analytics)
|
|
20
|
-
|
|
21
|
-
## Configuration
|
|
22
|
-
|
|
23
|
-
```yaml
|
|
24
|
-
apigen:
|
|
25
|
-
analytics:
|
|
26
|
-
enabled: true
|
|
27
|
-
default-provider: segment
|
|
28
|
-
|
|
29
|
-
providers:
|
|
30
|
-
google-analytics:
|
|
31
|
-
enabled: true
|
|
32
|
-
measurement-id: G-XXXXXXXXXX
|
|
33
|
-
api-secret: ${GA_API_SECRET}
|
|
34
|
-
|
|
35
|
-
mixpanel:
|
|
36
|
-
enabled: true
|
|
37
|
-
token: ${MIXPANEL_TOKEN}
|
|
38
|
-
api-secret: ${MIXPANEL_SECRET}
|
|
39
|
-
|
|
40
|
-
amplitude:
|
|
41
|
-
enabled: true
|
|
42
|
-
api-key: ${AMPLITUDE_API_KEY}
|
|
43
|
-
|
|
44
|
-
segment:
|
|
45
|
-
enabled: true
|
|
46
|
-
write-key: ${SEGMENT_WRITE_KEY}
|
|
47
|
-
|
|
48
|
-
batching:
|
|
49
|
-
enabled: true
|
|
50
|
-
size: 100
|
|
51
|
-
flush-interval: 10s
|
|
52
|
-
|
|
53
|
-
async:
|
|
54
|
-
enabled: true
|
|
55
|
-
pool-size: 4
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
## Provider Pattern
|
|
59
|
-
|
|
60
|
-
```java
|
|
61
|
-
public interface AnalyticsProvider {
|
|
62
|
-
String getProviderId();
|
|
63
|
-
|
|
64
|
-
TrackingResult track(AnalyticsEvent event);
|
|
65
|
-
IdentifyResult identify(IdentifyRequest request);
|
|
66
|
-
AliasResult alias(AliasRequest request);
|
|
67
|
-
void setUserProperties(UserPropertiesRequest request);
|
|
68
|
-
|
|
69
|
-
CompletableFuture<BatchTrackingResult> trackBatch(List<AnalyticsEvent> events);
|
|
70
|
-
ProviderHealth healthCheck();
|
|
71
|
-
void flush();
|
|
72
|
-
}
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
## Abstract Provider Base
|
|
76
|
-
|
|
77
|
-
```java
|
|
78
|
-
public abstract class AbstractAnalyticsProvider implements AnalyticsProvider {
|
|
79
|
-
|
|
80
|
-
protected final RestClient restClient;
|
|
81
|
-
protected final MeterRegistry meterRegistry;
|
|
82
|
-
|
|
83
|
-
@Override
|
|
84
|
-
public TrackingResult track(AnalyticsEvent event) {
|
|
85
|
-
Timer.Sample sample = Timer.start(meterRegistry);
|
|
86
|
-
try {
|
|
87
|
-
TrackingResult result = doTrack(event);
|
|
88
|
-
recordSuccess(sample);
|
|
89
|
-
return result;
|
|
90
|
-
} catch (Exception e) {
|
|
91
|
-
recordFailure(sample, e);
|
|
92
|
-
throw new EventTrackingException("Failed to track event", e);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
protected abstract TrackingResult doTrack(AnalyticsEvent event);
|
|
97
|
-
|
|
98
|
-
// Common retry logic
|
|
99
|
-
protected <T> T withRetry(Supplier<T> operation) {
|
|
100
|
-
return Retry.decorateSupplier(retry, operation).get();
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
## Service Layer
|
|
106
|
-
|
|
107
|
-
```java
|
|
108
|
-
@Service
|
|
109
|
-
@RequiredArgsConstructor
|
|
110
|
-
public class AnalyticsService {
|
|
111
|
-
|
|
112
|
-
private final List<AnalyticsProvider> providers;
|
|
113
|
-
private final AnalyticsEventRepository eventRepository;
|
|
114
|
-
|
|
115
|
-
@Async("analyticsExecutor")
|
|
116
|
-
public CompletableFuture<Void> track(String eventName,
|
|
117
|
-
String userId,
|
|
118
|
-
Map<String, Object> properties) {
|
|
119
|
-
|
|
120
|
-
AnalyticsEvent event = AnalyticsEvent.builder()
|
|
121
|
-
.eventName(eventName)
|
|
122
|
-
.userId(userId)
|
|
123
|
-
.properties(properties)
|
|
124
|
-
.timestamp(Instant.now())
|
|
125
|
-
.build();
|
|
126
|
-
|
|
127
|
-
// Persist locally
|
|
128
|
-
eventRepository.save(event);
|
|
129
|
-
|
|
130
|
-
// Fan-out to all enabled providers
|
|
131
|
-
List<CompletableFuture<TrackingResult>> futures = providers.stream()
|
|
132
|
-
.filter(AnalyticsProvider::isEnabled)
|
|
133
|
-
.map(provider -> CompletableFuture.supplyAsync(
|
|
134
|
-
() -> provider.track(event)))
|
|
135
|
-
.toList();
|
|
136
|
-
|
|
137
|
-
return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
public void identify(String userId, Map<String, Object> traits) {
|
|
141
|
-
IdentifyRequest request = new IdentifyRequest(userId, traits);
|
|
142
|
-
providers.forEach(p -> p.identify(request));
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
## Funnel Service
|
|
148
|
-
|
|
149
|
-
```java
|
|
150
|
-
@Service
|
|
151
|
-
public class FunnelService {
|
|
152
|
-
|
|
153
|
-
private final FunnelRepository funnelRepository;
|
|
154
|
-
private final FunnelConversionRepository conversionRepository;
|
|
155
|
-
|
|
156
|
-
public FunnelAnalysis analyzeFunnel(UUID funnelId,
|
|
157
|
-
Instant startDate,
|
|
158
|
-
Instant endDate) {
|
|
159
|
-
|
|
160
|
-
Funnel funnel = funnelRepository.findById(funnelId)
|
|
161
|
-
.orElseThrow(() -> new FunnelNotFoundException(funnelId));
|
|
162
|
-
|
|
163
|
-
List<FunnelStep> steps = funnel.getSteps();
|
|
164
|
-
List<StepAnalysis> analysis = new ArrayList<>();
|
|
165
|
-
|
|
166
|
-
long previousCount = 0;
|
|
167
|
-
for (FunnelStep step : steps) {
|
|
168
|
-
long count = conversionRepository.countByFunnelAndStep(
|
|
169
|
-
funnelId, step.getOrder(), startDate, endDate);
|
|
170
|
-
|
|
171
|
-
double conversionRate = previousCount > 0
|
|
172
|
-
? (double) count / previousCount * 100
|
|
173
|
-
: 100.0;
|
|
174
|
-
|
|
175
|
-
analysis.add(new StepAnalysis(step, count, conversionRate));
|
|
176
|
-
previousCount = count;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
return new FunnelAnalysis(funnel, analysis);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
## Cohort Service
|
|
185
|
-
|
|
186
|
-
```java
|
|
187
|
-
@Service
|
|
188
|
-
public class CohortService {
|
|
189
|
-
|
|
190
|
-
public RetentionMatrix calculateRetention(UUID cohortId,
|
|
191
|
-
TemporalUnit period,
|
|
192
|
-
int periods) {
|
|
193
|
-
|
|
194
|
-
Cohort cohort = cohortRepository.findById(cohortId)
|
|
195
|
-
.orElseThrow(() -> new CohortNotFoundException(cohortId));
|
|
196
|
-
|
|
197
|
-
List<CohortMembership> members = membershipRepository
|
|
198
|
-
.findByCohortId(cohortId);
|
|
199
|
-
|
|
200
|
-
double[][] matrix = new double[periods][periods];
|
|
201
|
-
|
|
202
|
-
for (int i = 0; i < periods; i++) {
|
|
203
|
-
Instant periodStart = cohort.getCreatedAt().plus(i, period);
|
|
204
|
-
Instant periodEnd = periodStart.plus(1, period);
|
|
205
|
-
|
|
206
|
-
long cohortSize = members.stream()
|
|
207
|
-
.filter(m -> m.getJoinedAt().isBefore(periodEnd))
|
|
208
|
-
.count();
|
|
209
|
-
|
|
210
|
-
for (int j = i; j < periods; j++) {
|
|
211
|
-
long activeCount = countActiveUsers(members,
|
|
212
|
-
periodStart.plus(j - i, period));
|
|
213
|
-
matrix[i][j] = cohortSize > 0
|
|
214
|
-
? (double) activeCount / cohortSize * 100
|
|
215
|
-
: 0;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
return new RetentionMatrix(cohort, matrix, period);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
```
|
|
223
|
-
|
|
224
|
-
## Domain Entities
|
|
225
|
-
|
|
226
|
-
```java
|
|
227
|
-
@Entity
|
|
228
|
-
@Table(name = "analytics_events")
|
|
229
|
-
public class AnalyticsEvent {
|
|
230
|
-
@Id
|
|
231
|
-
@GeneratedValue(strategy = GenerationType.UUID)
|
|
232
|
-
private UUID id;
|
|
233
|
-
|
|
234
|
-
@Column(nullable = false)
|
|
235
|
-
private String eventName;
|
|
236
|
-
|
|
237
|
-
private String userId;
|
|
238
|
-
private String anonymousId;
|
|
239
|
-
private String sessionId;
|
|
240
|
-
|
|
241
|
-
@Type(JsonType.class)
|
|
242
|
-
@Column(columnDefinition = "jsonb")
|
|
243
|
-
private Map<String, Object> properties;
|
|
244
|
-
|
|
245
|
-
@Column(nullable = false)
|
|
246
|
-
private Instant timestamp;
|
|
247
|
-
|
|
248
|
-
@Enumerated(EnumType.STRING)
|
|
249
|
-
private TrackingStatus status = TrackingStatus.PENDING;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
@Entity
|
|
253
|
-
@Table(name = "funnels")
|
|
254
|
-
public class Funnel {
|
|
255
|
-
@Id
|
|
256
|
-
private UUID id;
|
|
257
|
-
private String name;
|
|
258
|
-
|
|
259
|
-
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
|
|
260
|
-
@OrderBy("stepOrder")
|
|
261
|
-
private List<FunnelStep> steps;
|
|
262
|
-
}
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
## Auto Configuration
|
|
266
|
-
|
|
267
|
-
```java
|
|
268
|
-
@AutoConfiguration
|
|
269
|
-
@ConditionalOnProperty(prefix = "apigen.analytics", name = "enabled", havingValue = "true")
|
|
270
|
-
@EnableConfigurationProperties(AnalyticsProperties.class)
|
|
271
|
-
public class AnalyticsAutoConfiguration {
|
|
272
|
-
|
|
273
|
-
@Bean
|
|
274
|
-
@ConditionalOnProperty(prefix = "apigen.analytics.providers.google-analytics",
|
|
275
|
-
name = "enabled", havingValue = "true")
|
|
276
|
-
public GoogleAnalyticsProvider googleAnalyticsProvider(
|
|
277
|
-
AnalyticsProperties props, RestClient.Builder builder) {
|
|
278
|
-
return new GoogleAnalyticsProvider(
|
|
279
|
-
props.getProviders().getGoogleAnalytics(), builder);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
@Bean
|
|
283
|
-
@ConditionalOnProperty(prefix = "apigen.analytics.providers.mixpanel",
|
|
284
|
-
name = "enabled", havingValue = "true")
|
|
285
|
-
public MixpanelProvider mixpanelProvider(
|
|
286
|
-
AnalyticsProperties props, RestClient.Builder builder) {
|
|
287
|
-
return new MixpanelProvider(
|
|
288
|
-
props.getProviders().getMixpanel(), builder);
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
@Bean
|
|
292
|
-
public AnalyticsService analyticsService(
|
|
293
|
-
List<AnalyticsProvider> providers,
|
|
294
|
-
AnalyticsEventRepository repository) {
|
|
295
|
-
return new AnalyticsService(providers, repository);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
## Testing
|
|
301
|
-
|
|
302
|
-
```java
|
|
303
|
-
@SpringBootTest
|
|
304
|
-
@Testcontainers
|
|
305
|
-
class AnalyticsServiceIT {
|
|
306
|
-
|
|
307
|
-
@Container
|
|
308
|
-
@ServiceConnection
|
|
309
|
-
static PostgreSQLContainer<?> postgres =
|
|
310
|
-
new PostgreSQLContainer<>("postgres:16-alpine");
|
|
311
|
-
|
|
312
|
-
@MockBean
|
|
313
|
-
private MixpanelProvider mixpanelProvider;
|
|
314
|
-
|
|
315
|
-
@Autowired
|
|
316
|
-
private AnalyticsService analyticsService;
|
|
317
|
-
|
|
318
|
-
@Test
|
|
319
|
-
void shouldTrackEventToAllProviders() {
|
|
320
|
-
when(mixpanelProvider.track(any()))
|
|
321
|
-
.thenReturn(new TrackingResult(true, "ok"));
|
|
322
|
-
|
|
323
|
-
analyticsService.track("user_signed_up", "user-123",
|
|
324
|
-
Map.of("plan", "premium")).join();
|
|
325
|
-
|
|
326
|
-
verify(mixpanelProvider).track(argThat(event ->
|
|
327
|
-
event.getEventName().equals("user_signed_up") &&
|
|
328
|
-
event.getUserId().equals("user-123")
|
|
329
|
-
));
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
## Related Skills
|
|
335
|
-
|
|
336
|
-
- `analytics-concepts`: General analytics concepts
|
|
337
|
-
- `spring-boot-4`: Spring Boot 4.0 patterns
|
|
338
|
-
- `testcontainers`: Integration testing
|
|
339
|
-
|
|
340
|
-
|