This commit is contained in:
Guillaume Dugas
2026-02-19 09:58:13 +01:00
commit 7ad05e5b14
16 changed files with 414 additions and 0 deletions

43
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,43 @@
name: Maven build
run-name: Build application with maven
on: [ push ]
jobs:
build:
runs-on: ubuntu-latest
env:
MAVEN_ACCESS_TOKEN: ${{ secrets.CI_TOKEN }}
MAVEN_REPO_OWNER: ${{ gitea.actor }}
RELEASE_VERSION_BASE: 1.0
steps:
- name: Check out latest repository code
uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
- name: Set versions
run: |
VERSION_BASE=$RELEASE_VERSION_BASE
if [ "$GITHUB_REF_TYPE" = "tag" ]; then
VERSION_BASE="${GITHUB_REF_NAME}"
elif echo "$GITHUB_REF_NAME" | grep -qE '^release/'; then
VERSION_BASE="${GITHUB_REF_NAME#release/}"
fi
if [ "$GITHUB_REF_TYPE" = "branch" ]; then
BUILD_VERSION="${VERSION_BASE}-SNAPSHOT"
else
BUILD_VERSION="${VERSION_BASE}"
fi
./mvnw versions:set -DnewVersion=${BUILD_VERSION} -DprocessAllModules=true
- name: Build project
run: ./mvnw -s .mvn/settings.xml clean install -DskipTests
- name: Run tests
run: ./mvnw -s .mvn/settings.xml test
- name: Deploy project
run: ./mvnw -s .mvn/settings.xml deploy

52
bom/pom.xml Normal file
View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>fr.cnd.compositor</groupId>
<version>1.0-SNAPSHOT</version>
<artifactId>root</artifactId>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>bom</artifactId>
<name>Bom</name>
<packaging>pom</packaging>
<properties>
<compiler-plugin.version>3.14.1</compiler-plugin.version>
<failsafe-plugin.version>${surefire-plugin.version}</failsafe-plugin.version>
<maven.compiler.release>21</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
<quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
<quarkus.platform.version>3.31.3</quarkus.platform.version>
<quarkus.version>${quarkus.platform.version}</quarkus.version>
<skipITs>true</skipITs>
<surefire-plugin.version>3.5.4</surefire-plugin.version>
<!-- APP PROPS -->
<lombok.version>1.18.42</lombok.version>
<pebble.version>4.1.0</pebble.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.pebbletemplates</groupId>
<artifactId>pebble</artifactId>
<version>${pebble.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>

76
builder/pom.xml Normal file
View File

@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>fr.cnd.compositor</groupId>
<artifactId>bom</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../bom/pom.xml</relativePath>
</parent>
<packaging>pom</packaging>
<artifactId>builder</artifactId>
<name>Builder - Ext</name>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-bom</artifactId>
<version>${quarkus.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.version}</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire-plugin.version}</version>
<configuration>
<systemPropertyVariables>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
<maven.home>${maven.home}</maven.home>
<maven.repo>${settings.localRepository}</maven.repo>
</systemPropertyVariables>
</configuration>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${failsafe-plugin.version}</version>
<configuration>
<systemPropertyVariables>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
<maven.home>${maven.home}</maven.home>
<maven.repo>${settings.localRepository}</maven.repo>
</systemPropertyVariables>
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>${compiler-plugin.version}</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
</annotationProcessorPaths>
<parameters>true</parameters>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

View File

@@ -0,0 +1,17 @@
package fr.cnd.compositor.blocks.models;
import lombok.*;
import java.util.List;
import java.util.Map;
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class BlockRenderDefinition {
String name;
Map<String, Object> inputs;
Map<String, List<BlockRenderDefinition>> slots;
}

View File

@@ -0,0 +1,15 @@
package fr.cnd.compositor.blocks.models;
import lombok.*;
import java.util.List;
import java.util.Map;
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class BlockRenderRequest {
Map<String, List<BlockRenderDefinition>> definitions;
}

View File

@@ -0,0 +1,15 @@
package fr.cnd.compositor.blocks.models;
import lombok.*;
import java.util.List;
import java.util.Map;
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class BlockRenderResult {
Map<String, List<String>> result;
}

View File

@@ -0,0 +1,28 @@
package fr.cnd.compositor.blocks.pebble;
import fr.cnd.compositor.blocks.models.BlockRenderDefinition;
import fr.cnd.compositor.blocks.specs.BlockTemplate;
import io.smallrye.mutiny.Uni;
import jakarta.inject.Inject;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public abstract class AbstractPebbleBlockTemplate implements BlockTemplate {
@Inject
PebbleBlockEngine engine;
public void setEngine(PebbleBlockEngine engine) {
this.engine = engine;
}
public abstract Uni<String> getTemplate();
@Override
public Uni<String> render(BlockRenderDefinition definition) {
final Map<String, Object> context = new HashMap<>(Optional.ofNullable(definition.getInputs()).orElse(new HashMap<>()));
return getTemplate()
.chain(template -> engine.render(template, context));
}
}

View File

@@ -0,0 +1,19 @@
package fr.cnd.compositor.blocks.pebble;
import io.pebbletemplates.pebble.extension.AbstractExtension;
import io.pebbletemplates.pebble.extension.Function;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import java.util.Map;
@ApplicationScoped
public class PebbleBlocksExtension extends AbstractExtension {
@Inject
PebbleSlotFunction pebbleSlotFunction;
public Map<String, Function> getFunctions() {
return Map.of("slot", pebbleSlotFunction);
}
}

View File

@@ -0,0 +1,33 @@
package fr.cnd.compositor.blocks.pebble;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.pebbletemplates.pebble.extension.Function;
import io.pebbletemplates.pebble.extension.escaper.SafeString;
import io.pebbletemplates.pebble.template.EvaluationContext;
import io.pebbletemplates.pebble.template.PebbleTemplate;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import java.util.List;
import java.util.Map;
@ApplicationScoped
public class PebbleSlotFunction implements Function {
@Inject
ObjectMapper objectMapper;
@Override
public SafeString execute(Map<String, Object> args, PebbleTemplate self, EvaluationContext context, int lineNumber) {
final Object slotsVar = context.getVariable("__slots__");
final Map<String, String> slots = objectMapper.convertValue(slotsVar, new TypeReference<>() {});
final String slotName = (String) args.get("name");
return slots != null && slots.containsKey(slotName) ? new SafeString(slots.get(slotName)) : new SafeString("");
}
@Override
public List<String> getArgumentNames() {
return List.of("name");
}
}

View File

@@ -0,0 +1,10 @@
package fr.cnd.compositor.blocks.specs;
import io.smallrye.mutiny.Uni;
import java.util.Map;
public interface BlockConfiguration {
Uni<String> getBlockTemplateName();
Uni<Map<String, Object>> mapInputs(Map<String, Object> inputs);
}

View File

@@ -0,0 +1,19 @@
package fr.cnd.compositor.blocks.specs;
import io.smallrye.mutiny.Uni;
import java.util.Map;
/**
* Maps user-provided inputs to the final template context.
*/
public interface ContextMapping {
/**
* Transforms the given user inputs into the context that will be passed to the template engine.
*
* @param inputs the raw user-provided input entries
* @return a {@link Uni} emitting the resulting template context
*/
Uni<Map<String, Object>> map(Map<String, Object> inputs);
}

View File

@@ -0,0 +1,8 @@
package fr.cnd.compositor.blocks.specs;
import io.smallrye.mutiny.Uni;
public interface ContextMappingResolver {
Uni<ContextMapping> resolveContextMapping(String contextMappingIdentifier);
}

View File

@@ -0,0 +1,24 @@
package fr.cnd.compositor.blocks.templates;
import fr.cnd.compositor.blocks.pebble.AbstractPebbleBlockTemplate;
import io.smallrye.common.annotation.Identifier;
import io.smallrye.mutiny.Uni;
import jakarta.enterprise.context.ApplicationScoped;
@Identifier("html")
@ApplicationScoped
public class HtmlBlockTemplate extends AbstractPebbleBlockTemplate {
@Override
public Uni<String> getTemplate() {
return Uni.createFrom().item("""
<html>
<head>
<title>{{title}}</title>
</head>
<body>
{{content}}
</body>
</html>
""");
}
}

View File

@@ -0,0 +1,35 @@
package fr.cnd.compositor.blocks.templates;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import fr.cnd.compositor.blocks.specs.BlockConfiguration;
import io.smallrye.common.annotation.Identifier;
import io.smallrye.mutiny.Uni;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import java.util.HashMap;
import java.util.Map;
@Identifier("product")
@ApplicationScoped
public class HtmlProductConfiguration implements BlockConfiguration {
@Inject
ObjectMapper objectMapper;
@Override
public Uni<String> getBlockTemplateName() {
return Uni.createFrom().item("html");
}
@Override
public Uni<Map<String, Object>> mapInputs(Map<String, Object> inputs) {
Map<String, String> product = objectMapper.convertValue(inputs.getOrDefault("product", new HashMap<>()), new TypeReference<>() {});
return Uni.createFrom().item(Map.of(
"title", product.getOrDefault("title", ""),
"content", product.getOrDefault("name", "")
));
}
}

20
pom.xml Normal file
View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>fr.cnd.compositor</groupId>
<artifactId>root</artifactId>
<version>1.0-SNAPSHOT</version>
<name>Blocks</name>
<packaging>pom</packaging>
<modules>
<module>bom</module>
<module>builder</module>
<module>modules/core</module>
</modules>
</project>