@eventmodelers/cli 1.0.14 → 1.0.18
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/package.json +1 -1
- package/shared/build-kit/lib/adapters/supabase-realtime-adapter.js +1 -1
- package/stacks/axon/templates/.claude/skills/build-automation/SKILL.md +6 -2
- package/stacks/axon/templates/.claude/skills/build-automation-workflow/SKILL.md +13 -7
- package/stacks/axon/templates/.claude/skills/build-state-change/SKILL.md +19 -13
- package/stacks/axon/templates/.claude/skills/build-state-change/references/rest-api-patterns.md +2 -2
- package/stacks/axon/templates/.claude/skills/build-state-view/SKILL.md +6 -2
- package/stacks/axon/templates/build-kit/CLAUDE.md +7 -0
- package/stacks/axon/templates/root/src/main/java/io/axoniq/quickstart/QuickstartApplication.java +0 -106
- package/stacks/axon/templates/root/src/main/resources/application.properties +1 -2
- package/stacks/modeling-kit/templates/.claude/skills/html-screen/SKILL.md +6 -4
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@ export async function createSupabaseRealtimeAdapter(cfg, initialToken) {
|
|
|
10
10
|
await supabase.realtime.setAuth(initialToken);
|
|
11
11
|
|
|
12
12
|
return {
|
|
13
|
-
subscribe(topic, handlers, onStatus) {
|
|
13
|
+
async subscribe(topic, handlers, onStatus) {
|
|
14
14
|
let channel = supabase.channel(topic, { config: { private: true } });
|
|
15
15
|
for (const [event, handler] of Object.entries(handlers)) {
|
|
16
16
|
channel = channel.on('broadcast', { event }, (msg) => handler(msg.payload));
|
|
@@ -38,6 +38,10 @@ Read the target project's `.build-kit/CLAUDE.md` and explore existing slices. Lo
|
|
|
38
38
|
- Feature flag patterns (Step 4 — optional)
|
|
39
39
|
- Spring Boot test annotation: check if the project defines a meta-annotation over `@SpringBootTest`
|
|
40
40
|
|
|
41
|
+
**Determine `{basePackage}`** — every path below is rooted at
|
|
42
|
+
`{basePackage}.slices.{context}.automation.{slicename}`. Resolve `{basePackage}` as documented in
|
|
43
|
+
`.build-kit/CLAUDE.md`'s Structure section.
|
|
44
|
+
|
|
41
45
|
## Step 1: Understand the Input
|
|
42
46
|
|
|
43
47
|
Extract these elements regardless of input format:
|
|
@@ -131,7 +135,7 @@ If a command fails, the event handler fails and the event processor retries.
|
|
|
131
135
|
### Stateless Automation
|
|
132
136
|
|
|
133
137
|
New automation slices live under
|
|
134
|
-
`src/main/java
|
|
138
|
+
`src/main/java/.../slices/{context}/automation/{slicename}/`.
|
|
135
139
|
|
|
136
140
|
#### Strategy interface (if needed)
|
|
137
141
|
|
|
@@ -280,7 +284,7 @@ Add to ALL config files when using `@ConditionalOnProperty`:
|
|
|
280
284
|
**For stateless automations** — pure unit tests with a mocked `CommandDispatcher`:
|
|
281
285
|
|
|
282
286
|
```java
|
|
283
|
-
// File: src/test/java
|
|
287
|
+
// File: src/test/java/.../slices/{context}/automation/{slicename}/{AutomationName}Test.java
|
|
284
288
|
class {AutomationName}ProcessorTest {
|
|
285
289
|
|
|
286
290
|
private {AutomationName}Processor processor;
|
|
@@ -19,7 +19,8 @@ description: >
|
|
|
19
19
|
> **Preview feature** — AF5 Workflow APIs may change without notice and are not yet for production.
|
|
20
20
|
|
|
21
21
|
New workflow slices live under
|
|
22
|
-
`src/main/java
|
|
22
|
+
`src/main/java/.../slices/{context}/automation/{slicename}/` — see Step 0 below for how to resolve the
|
|
23
|
+
`{basePackage}` this path is rooted at.
|
|
23
24
|
|
|
24
25
|
---
|
|
25
26
|
|
|
@@ -32,6 +33,11 @@ Read `.build-kit/CLAUDE.md` and check whether the project already uses AF5 Workf
|
|
|
32
33
|
- A `WorkflowModule` bean in any `@Configuration` class
|
|
33
34
|
- Classes annotated with `@Workflow`
|
|
34
35
|
- Existing `*Workflow.java` files under any slice package
|
|
36
|
+
|
|
37
|
+
**Determine `{basePackage}`** — every path in this skill is rooted at
|
|
38
|
+
`{basePackage}.slices.{context}.automation.{slicename}`. Resolve `{basePackage}` as documented in
|
|
39
|
+
`.build-kit/CLAUDE.md`'s Structure section.
|
|
40
|
+
|
|
35
41
|
- The `WorkflowModule` dependency in `pom.xml`:
|
|
36
42
|
|
|
37
43
|
```xml
|
|
@@ -92,7 +98,7 @@ The simplest way to define a workflow using `@Workflow`:
|
|
|
92
98
|
|
|
93
99
|
```java
|
|
94
100
|
// File: {slicename}/{SliceName}Workflow.java
|
|
95
|
-
package
|
|
101
|
+
package {basePackage}.slices.{context}.automation.{slicename};
|
|
96
102
|
|
|
97
103
|
import org.axonframework.workflow.annotation.Workflow;
|
|
98
104
|
import org.axonframework.workflow.SimpleWorkflowContext;
|
|
@@ -100,7 +106,7 @@ import org.axonframework.workflow.SimpleWorkflowContext;
|
|
|
100
106
|
@Workflow(
|
|
101
107
|
idProperty = "{triggerEventIdField}", // field name on the trigger event that becomes the workflow ID
|
|
102
108
|
startOnEventClass = {TriggerEvent}.class, // event that starts a new workflow instance
|
|
103
|
-
workflowNamespace = "
|
|
109
|
+
workflowNamespace = "{basePackage}.slices.{context}"
|
|
104
110
|
)
|
|
105
111
|
public class {SliceName}Workflow {
|
|
106
112
|
|
|
@@ -333,7 +339,7 @@ public void execute(SimpleWorkflowContext ctx) {
|
|
|
333
339
|
|
|
334
340
|
```java
|
|
335
341
|
@Workflow(idProperty = "id", startOnEventClass = OrderPlaced.class,
|
|
336
|
-
workflowNamespace = "
|
|
342
|
+
workflowNamespace = "{basePackage}.slices.{context}")
|
|
337
343
|
public class {SliceName}Workflow {
|
|
338
344
|
|
|
339
345
|
public void execute(SimpleWorkflowContext ctx) { /* ... */ }
|
|
@@ -476,14 +482,14 @@ class {SliceName}WorkflowIntegrationTest extends AbstractDeclarativeTestBase {
|
|
|
476
482
|
## Files to Create / Modify
|
|
477
483
|
|
|
478
484
|
```
|
|
479
|
-
src/main/java
|
|
485
|
+
src/main/java/.../slices/{context}/automation/{slicename}/
|
|
480
486
|
├── {SliceName}Workflow.java ← @Workflow class (execute method + lifecycle listeners)
|
|
481
487
|
└── {SliceName}WorkflowServices.java ← @Component step handlers (Spring beans)
|
|
482
488
|
|
|
483
|
-
src/main/java
|
|
489
|
+
src/main/java/.../slices/{context}/
|
|
484
490
|
└── WorkflowConfiguration.java ← WorkflowModule bean (one per context, create if missing)
|
|
485
491
|
|
|
486
|
-
src/test/java
|
|
492
|
+
src/test/java/.../slices/{context}/automation/{slicename}/
|
|
487
493
|
└── {SliceName}WorkflowTest.java ← unit tests with mocked context + services
|
|
488
494
|
```
|
|
489
495
|
|
|
@@ -35,12 +35,18 @@ Read `.build-kit/.slices/{context}/{slicename}/slice.json`. Extract, and use **o
|
|
|
35
35
|
|
|
36
36
|
Never invent a field, business rule, or event that isn't in slice.json.
|
|
37
37
|
|
|
38
|
+
## Step 0a: Determine `{basePackage}`
|
|
39
|
+
|
|
40
|
+
Every code example below is rooted at `{basePackage}.slices.{context}.{slicename}`. Resolve
|
|
41
|
+
`{basePackage}` as documented in `.build-kit/CLAUDE.md`'s Structure section — never hardcode
|
|
42
|
+
`io.axoniq.quickstart` (the shipped quickstart scaffold's package) or any other specific package.
|
|
43
|
+
|
|
38
44
|
## Step 1: Command
|
|
39
45
|
|
|
40
46
|
**Exactly one field has `idAttribute: true` in slice.json** — annotate it directly:
|
|
41
47
|
|
|
42
48
|
```java
|
|
43
|
-
package
|
|
49
|
+
package {basePackage}.slices.{context}.{slicename};
|
|
44
50
|
|
|
45
51
|
import org.axonframework.messaging.commandhandling.annotation.Command;
|
|
46
52
|
import org.axonframework.modelling.annotation.TargetEntityId;
|
|
@@ -61,13 +67,13 @@ one field directly.** Instead build a compound id record and put `@TargetEntityI
|
|
|
61
67
|
verified against the `SubscribeToCourse` slice (`email` + `courseId` both `idAttribute: true`):
|
|
62
68
|
|
|
63
69
|
```java
|
|
64
|
-
package
|
|
70
|
+
package {basePackage}.slices.{context}.{slicename};
|
|
65
71
|
|
|
66
72
|
public record {SliceName}Id(String field1, String field2) {}
|
|
67
73
|
```
|
|
68
74
|
|
|
69
75
|
```java
|
|
70
|
-
package
|
|
76
|
+
package {basePackage}.slices.{context}.{slicename};
|
|
71
77
|
|
|
72
78
|
import org.axonframework.messaging.commandhandling.annotation.Command;
|
|
73
79
|
import org.axonframework.modelling.annotation.TargetEntityId;
|
|
@@ -93,7 +99,7 @@ Check `src/main/java/.../{context}/events/` first; add to the existing sealed/ma
|
|
|
93
99
|
than creating a duplicate.
|
|
94
100
|
|
|
95
101
|
```java
|
|
96
|
-
package
|
|
102
|
+
package {basePackage}.slices.{context}.events;
|
|
97
103
|
|
|
98
104
|
import org.axonframework.eventsourcing.annotation.EventTag;
|
|
99
105
|
import org.axonframework.messaging.eventhandling.annotation.Event;
|
|
@@ -119,10 +125,10 @@ Package-private, mutable field(s) — **not** an immutable `State` record with f
|
|
|
119
125
|
check needs, nothing else.
|
|
120
126
|
|
|
121
127
|
```java
|
|
122
|
-
package
|
|
128
|
+
package {basePackage}.slices.{context}.{slicename};
|
|
123
129
|
|
|
124
|
-
import
|
|
125
|
-
import
|
|
130
|
+
import {basePackage}.slices.{context}.events.{EventName};
|
|
131
|
+
import {basePackage}.slices.{context}.events.EventTags;
|
|
126
132
|
import org.axonframework.eventsourcing.annotation.EventCriteriaBuilder;
|
|
127
133
|
import org.axonframework.eventsourcing.annotation.EventSourcingHandler;
|
|
128
134
|
import org.axonframework.eventsourcing.annotation.reflection.EntityCreator;
|
|
@@ -164,7 +170,7 @@ resolved automatically from `Configuration` — pass it plus the event class str
|
|
|
164
170
|
tempting to think `andBeingOneOfTypes(new QualifiedName({EventName}.class))` should work without it,
|
|
165
171
|
since `QualifiedName` has a `Class<?>` constructor. Verified experimentally that it does NOT:
|
|
166
172
|
`QualifiedName(Class<?>)`'s only job is `clazz.getName()` — the raw Java class name
|
|
167
|
-
(`
|
|
173
|
+
(`{basePackage}.slices.foo.events.CustomerRegistered`) — not the `@Event(namespace, name)` value
|
|
168
174
|
the event was actually appended under (`Foo.CustomerRegistered`). Swapping to it in
|
|
169
175
|
`SubscribeToCourseDecisionModel` as a test made 2 of 3 passing tests fail immediately, silently, with
|
|
170
176
|
no exception pointing at the real cause — the criteria just stopped matching anything, identical in
|
|
@@ -220,9 +226,9 @@ itself.
|
|
|
220
226
|
## Step 4: Command handler
|
|
221
227
|
|
|
222
228
|
```java
|
|
223
|
-
package
|
|
229
|
+
package {basePackage}.slices.{context}.{slicename};
|
|
224
230
|
|
|
225
|
-
import
|
|
231
|
+
import {basePackage}.slices.{context}.events.{EventName};
|
|
226
232
|
import org.axonframework.messaging.commandhandling.annotation.CommandHandler;
|
|
227
233
|
import org.axonframework.messaging.core.Metadata;
|
|
228
234
|
import org.axonframework.messaging.eventhandling.gateway.EventAppender;
|
|
@@ -255,7 +261,7 @@ exist as a type in this version.
|
|
|
255
261
|
## Step 5: REST endpoint — only if slice.json shows an inbound `SCREEN` dependency on the command
|
|
256
262
|
|
|
257
263
|
```java
|
|
258
|
-
package
|
|
264
|
+
package {basePackage}.slices.{context}.{slicename};
|
|
259
265
|
|
|
260
266
|
import org.axonframework.messaging.commandhandling.gateway.CommandGateway;
|
|
261
267
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|
@@ -323,9 +329,9 @@ One-time `pom.xml` addition (no version needed — resolved via the project's ex
|
|
|
323
329
|
```
|
|
324
330
|
|
|
325
331
|
```java
|
|
326
|
-
package
|
|
332
|
+
package {basePackage}.slices.{context}.{slicename};
|
|
327
333
|
|
|
328
|
-
import
|
|
334
|
+
import {basePackage}.slices.{context}.events.{EventName};
|
|
329
335
|
import org.axonframework.eventsourcing.configuration.EventSourcedEntityModule;
|
|
330
336
|
import org.axonframework.eventsourcing.configuration.EventSourcingConfigurer;
|
|
331
337
|
import org.axonframework.messaging.commandhandling.configuration.CommandHandlingModule;
|
package/stacks/axon/templates/.claude/skills/build-state-change/references/rest-api-patterns.md
CHANGED
|
@@ -9,7 +9,7 @@ directly, and tests use `WebTestClient`, not `MockMvc`.
|
|
|
9
9
|
## Controller
|
|
10
10
|
|
|
11
11
|
```java
|
|
12
|
-
package
|
|
12
|
+
package {basePackage}.slices.{context}.{slicename};
|
|
13
13
|
|
|
14
14
|
import org.axonframework.messaging.commandhandling.gateway.CommandGateway;
|
|
15
15
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|
@@ -59,7 +59,7 @@ shape for the first one, matching the project's WebFlux stack and the `@Conditio
|
|
|
59
59
|
feature-flag convention (tests disable all slices by default; opt in per test class):
|
|
60
60
|
|
|
61
61
|
```java
|
|
62
|
-
package
|
|
62
|
+
package {basePackage}.slices.{context}.{slicename};
|
|
63
63
|
|
|
64
64
|
import org.axonframework.messaging.commandhandling.gateway.CommandGateway;
|
|
65
65
|
import org.junit.jupiter.api.Test;
|
|
@@ -21,6 +21,10 @@ description: >
|
|
|
21
21
|
|
|
22
22
|
Before writing any code, read the target project's `.build-kit/CLAUDE.md`
|
|
23
23
|
|
|
24
|
+
**Determine `{basePackage}`** — every code example below is rooted at
|
|
25
|
+
`{basePackage}.slices.{context}.{slicename}`. Resolve `{basePackage}` as documented in
|
|
26
|
+
`.build-kit/CLAUDE.md`'s Structure section.
|
|
27
|
+
|
|
24
28
|
## Step 1: Ensure Events Exist
|
|
25
29
|
|
|
26
30
|
Before implementing the read slice, verify that all events the projector handles exist in the
|
|
@@ -70,7 +74,7 @@ comments** — those are only for write slices.
|
|
|
70
74
|
### Slice package structure
|
|
71
75
|
|
|
72
76
|
```
|
|
73
|
-
|
|
77
|
+
.../slices/{context}/{slicename}/ (i.e. {basePackage}.slices.{context}.{slicename} — see Step 0)
|
|
74
78
|
├── Get{SliceName}.java ← query record + nested Result
|
|
75
79
|
├── {SliceName}Summary.java ← read model (projection output shape)
|
|
76
80
|
├── {SliceName}Projector.java ← @Component with @EventHandler + @QueryHandler
|
|
@@ -252,7 +256,7 @@ Pure unit tests — instantiate the projector directly, no Spring context needed
|
|
|
252
256
|
Fast, no container startup.
|
|
253
257
|
|
|
254
258
|
```java
|
|
255
|
-
// File: src/test/java/
|
|
259
|
+
// File: src/test/java/.../slices/{context}/{slicename}/{SliceName}ProjectorTest.java
|
|
256
260
|
class {SliceName}ProjectorTest {
|
|
257
261
|
|
|
258
262
|
private {SliceName}Projector projector;
|
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
Read Events in src/events to understand the global structure.
|
|
4
4
|
|
|
5
|
+
`<basePackage>` in this project's Java code (`src/main/java/<basePackage>/slices/...`) is this
|
|
6
|
+
project's own Java package prefix, not a fixed value — resolve it, in order: (1) the package of the
|
|
7
|
+
project's `@SpringBootApplication` class, (2) the package of any existing slice already under
|
|
8
|
+
`.../slices/{context}/{slicename}/`, (3) only if no code exists yet, Maven's `<groupId>` in `pom.xml`
|
|
9
|
+
or Gradle's `group` property in `build.gradle`/`build.gradle.kts`. Never hardcode
|
|
10
|
+
`io.axoniq.quickstart` (the shipped quickstart scaffold's package) or any other specific package.
|
|
11
|
+
|
|
5
12
|
## File Structure Constraints
|
|
6
13
|
|
|
7
14
|
- **Strict Path Limitation**: if not instructed otherwise, only check `src/slices/{slicename}/*.ts`
|
package/stacks/axon/templates/root/src/main/java/io/axoniq/quickstart/QuickstartApplication.java
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
package io.axoniq.quickstart;
|
|
2
2
|
|
|
3
|
-
import io.axoniq.quickstart.giftcard.domain.GiftCard;
|
|
4
3
|
import org.axonframework.messaging.eventhandling.processing.streaming.token.store.TokenStore;
|
|
5
4
|
import org.axonframework.messaging.eventhandling.processing.streaming.token.store.inmemory.InMemoryTokenStore;
|
|
6
5
|
import org.springframework.boot.SpringApplication;
|
|
@@ -8,115 +7,10 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|
|
8
7
|
import org.springframework.context.annotation.Bean;
|
|
9
8
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
|
10
9
|
|
|
11
|
-
/**
|
|
12
|
-
* Main entry point for the Axoniq Platform Quickstart application.
|
|
13
|
-
*
|
|
14
|
-
* <p>This Spring Boot application demonstrates a complete CQRS/Event Sourcing implementation
|
|
15
|
-
* using Axon Framework and Axon Server, showcasing best practices for building reactive,
|
|
16
|
-
* scalable applications with event-driven architecture.</p>
|
|
17
|
-
*
|
|
18
|
-
* <p><strong>Architecture Overview:</strong></p>
|
|
19
|
-
* <ul>
|
|
20
|
-
* <li><strong>CQRS Implementation</strong>: Separates command and query responsibilities</li>
|
|
21
|
-
* <li><strong>Event Sourcing</strong>: Stores state changes as immutable events</li>
|
|
22
|
-
* <li><strong>Reactive Web Stack</strong>: Uses Spring WebFlux for non-blocking I/O</li>
|
|
23
|
-
* <li><strong>Real-time Updates</strong>: Implements Server-Sent Events for live UI updates</li>
|
|
24
|
-
* <li><strong>In-Memory Projections</strong>: Fast query performance with eventual consistency</li>
|
|
25
|
-
* </ul>
|
|
26
|
-
*
|
|
27
|
-
* <p><strong>Key Components Enabled:</strong></p>
|
|
28
|
-
* <ul>
|
|
29
|
-
* <li><strong>{@code @SpringBootApplication}</strong>: Enables auto-configuration, component scanning, and configuration properties</li>
|
|
30
|
-
* <li><strong>{@code @EnableScheduling}</strong>: Activates scheduled task execution for the {@link io.axoniq.quickstart.giftcard.scheduler.GiftCardScheduler}</li>
|
|
31
|
-
* </ul>
|
|
32
|
-
*
|
|
33
|
-
* <p><strong>Domain Model:</strong></p>
|
|
34
|
-
* <p>The application centers around a Gift Card domain implementing:</p>
|
|
35
|
-
* <ul>
|
|
36
|
-
* <li><strong>EventSourced DCB Model</strong>: {@link GiftCard} - Core business logic and state</li>
|
|
37
|
-
* <li><strong>Commands</strong>: Issue and redeem operations with business validation</li>
|
|
38
|
-
* <li><strong>Events</strong>: Immutable facts about gift card lifecycle changes</li>
|
|
39
|
-
* <li><strong>Queries</strong>: Read operations with subscription query support</li>
|
|
40
|
-
* <li><strong>Projections</strong>: Denormalized read models for efficient querying</li>
|
|
41
|
-
* </ul>
|
|
42
|
-
*
|
|
43
|
-
* <p><strong>Technical Stack:</strong></p>
|
|
44
|
-
* <ul>
|
|
45
|
-
* <li><strong>Axon Framework</strong>: CQRS/Event Sourcing framework</li>
|
|
46
|
-
* <li><strong>Axon Server</strong>: Event store and message routing infrastructure</li>
|
|
47
|
-
* <li><strong>Spring WebFlux</strong>: Reactive web framework with non-blocking I/O</li>
|
|
48
|
-
* <li><strong>Vue.js 3</strong>: Frontend framework with Vuetify UI components</li>
|
|
49
|
-
* <li><strong>Server-Sent Events</strong>: Real-time updates without WebSocket complexity</li>
|
|
50
|
-
* </ul>
|
|
51
|
-
*
|
|
52
|
-
* <p><strong>Educational Value:</strong></p>
|
|
53
|
-
* <p>This quickstart serves as a practical learning resource demonstrating:</p>
|
|
54
|
-
* <ul>
|
|
55
|
-
* <li>Event Sourcing patterns and practices</li>
|
|
56
|
-
* <li>CQRS implementation with separate read/write models</li>
|
|
57
|
-
* <li>Real-time web applications with reactive streams</li>
|
|
58
|
-
* <li>Integration between Axon Framework and Spring Boot</li>
|
|
59
|
-
* <li>Modern UI development with real-time data updates</li>
|
|
60
|
-
* </ul>
|
|
61
|
-
*
|
|
62
|
-
* <p><strong>Production Readiness Notes:</strong></p>
|
|
63
|
-
* <p>While this quickstart demonstrates core patterns, production deployments should consider:</p>
|
|
64
|
-
* <ul>
|
|
65
|
-
* <li>Persistent event store configuration (vs. in-memory)</li>
|
|
66
|
-
* <li>Distributed deployment strategies</li>
|
|
67
|
-
* <li>Monitoring and observability integration</li>
|
|
68
|
-
* <li>Security implementation (authentication, authorization)</li>
|
|
69
|
-
* <li>Error handling and retry mechanisms</li>
|
|
70
|
-
* <li>Performance tuning and resource optimization</li>
|
|
71
|
-
* </ul>
|
|
72
|
-
*
|
|
73
|
-
* <p><strong>Getting Started:</strong></p>
|
|
74
|
-
* <ol>
|
|
75
|
-
* <li>Ensure Axon Server is running on localhost:8124</li>
|
|
76
|
-
* <li>Run this application using Spring Boot</li>
|
|
77
|
-
* <li>Access the web interface at http://localhost:8080</li>
|
|
78
|
-
* <li>Observe real-time gift card operations via the scheduler</li>
|
|
79
|
-
* <li>Interact with the API endpoints at /api/giftcards</li>
|
|
80
|
-
* </ol>
|
|
81
|
-
*
|
|
82
|
-
* @see GiftCard
|
|
83
|
-
* @see io.axoniq.quickstart.giftcard.web.GiftCardController
|
|
84
|
-
* @see io.axoniq.quickstart.giftcard.query.GiftCardProjection
|
|
85
|
-
* @see io.axoniq.quickstart.giftcard.scheduler.GiftCardScheduler
|
|
86
|
-
* @see <a href="https://docs.axoniq.io/reference-guide/">Axon Framework Reference Guide</a>
|
|
87
|
-
*
|
|
88
|
-
* @author AxonIQ Quickstart
|
|
89
|
-
* @version 1.0
|
|
90
|
-
* @since 1.0
|
|
91
|
-
*/
|
|
92
10
|
@SpringBootApplication
|
|
93
11
|
@EnableScheduling
|
|
94
12
|
public class QuickstartApplication {
|
|
95
13
|
|
|
96
|
-
/**
|
|
97
|
-
* Application entry point that starts the Spring Boot application.
|
|
98
|
-
*
|
|
99
|
-
* <p>This method bootstraps the entire application context, including:</p>
|
|
100
|
-
* <ul>
|
|
101
|
-
* <li>Axon Framework auto-configuration</li>
|
|
102
|
-
* <li>Spring WebFlux reactive web server</li>
|
|
103
|
-
* <li>Component scanning and dependency injection</li>
|
|
104
|
-
* <li>Scheduled task initialization</li>
|
|
105
|
-
* <li>Static resource serving configuration</li>
|
|
106
|
-
* </ul>
|
|
107
|
-
*
|
|
108
|
-
* <p><strong>Startup sequence:</strong></p>
|
|
109
|
-
* <ol>
|
|
110
|
-
* <li>Spring Boot application context initialization</li>
|
|
111
|
-
* <li>Axon Server connection establishment</li>
|
|
112
|
-
* <li>Event store and command/query bus configuration</li>
|
|
113
|
-
* <li>EventSourced DCB model and projection registration</li>
|
|
114
|
-
* <li>Web server startup on port 8080</li>
|
|
115
|
-
* <li>Scheduler activation for demo operations</li>
|
|
116
|
-
* </ol>
|
|
117
|
-
*
|
|
118
|
-
* @param args command line arguments passed to the application
|
|
119
|
-
*/
|
|
120
14
|
public static void main(String[] args) {
|
|
121
15
|
SpringApplication.run(QuickstartApplication.class, args);
|
|
122
16
|
}
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
spring.application.name=Platform QuickStart
|
|
2
|
-
axoniq.platform.credentials=${AXONIQ_PLATFORM_CREDENTIALS}
|
|
1
|
+
spring.application.name=Platform QuickStart
|
|
@@ -68,12 +68,14 @@ Guidelines:
|
|
|
68
68
|
|
|
69
69
|
### Marks — only when the user explicitly asks for one
|
|
70
70
|
|
|
71
|
-
The canvas has a native "Marks" feature (outline highlight, optional blur
|
|
71
|
+
The canvas has a native "Marks" feature (outline highlight, plus an optional "blur outside" or "white outside" spotlight) for calling out part of a screen — see `HtmlEditorModal.tsx`'s Highlight tool and `markBlur.ts`/`markStyles.ts` in the main app. **Do not add marks by default.** Only apply the effects below when the request explicitly asks to highlight/mark/call out/circle/spotlight, or blur/obscure/white-out part of the screen (e.g. "highlight the submit button", "blur everything except the email field", "white out everything but the header"). An ordinary "design a screen" request gets no marks.
|
|
72
72
|
|
|
73
|
-
|
|
73
|
+
This skill only has a `pages`/`backgroundColor` field to send (no separate marks API — the native feature persists marks as board metadata, not through this render call), so reproduce the same visual language directly as inline CSS on the target element(s), self-contained in the page HTML same as any other styling in Step 3. No `<script>`/`<style>` tags are needed (and `<script>` is stripped anyway) — inline `style="..."` reproduces the same CSS the native feature injects:
|
|
74
74
|
|
|
75
|
-
- **Mark / highlight an area** — add to the target element's `style`: `outline:4px solid <color> !important;outline-offset:1px;`. Default color `#e74c3c` (red) unless the user names one; other options mirror the app's mark picker: `#1e293b` (dark slate), `#2ecc71` (green), `#3b82f6` (blue), `#f1c40f` (yellow), `#ffffff` (white).
|
|
76
|
-
- **Blur outside / spotlight an area** — add `style="filter:blur(6px) !important;"` to every other top-level sibling/section on the page so only the called-out element stays sharp.
|
|
75
|
+
- **Mark / highlight an area** — add to the target element's `style`: `outline:4px solid <color> !important;outline-offset:1px;`. Default color `#e74c3c` (red) unless the user names one; other options mirror the app's mark picker (`ColorPicker.tsx`): `#1e293b` (dark slate), `#2ecc71` (green), `#3b82f6` (blue), `#f1c40f` (yellow), `#ffffff` (white).
|
|
76
|
+
- **Blur outside / spotlight an area** — add `style="filter:blur(6px) !important;"` to every other top-level sibling/section on the page so only the called-out element stays sharp.
|
|
77
|
+
- **White outside / spotlight an area** — same idea, but instead add `style="filter:brightness(0) invert(1) !important;"` to every other top-level sibling/section (collapses them to solid white — works uniformly across text, shapes, and images, unlike a plain background-color override). Use this only when the user says "white out" / "whiteout" rather than "blur" — the two are mutually exclusive per mark in the native tool, so never apply both blur and white filters to the same sibling.
|
|
78
|
+
- Combine the outline rule with either spotlight rule if the user asked to both mark *and* blur/white-out.
|
|
77
79
|
|
|
78
80
|
Apply these only to the specific element(s) the request describes — don't guess at additional areas to call out.
|
|
79
81
|
|