mirror of https://github.com/halo-dev/halo
Refactor project structure for a better development (#3552)
#### What type of PR is this? /kind cleanup /area core #### What this PR does / why we need it: This PR totally refactor project structure for a better plugin development. Now we can maintain and publish api and platform modules at Halo application side, which will be references by plugins. Currently, we can execute command `./gradlew clean publish` to publish api and platform modules into **local** Maven repository, so that we can refer these dependencies (`run.halo.tools.platform:plugin:2.4.0-SNAPSHOT` and `run.halo.app:api:2.4.0-SNAPSHOT`) in plugin projects. I will make another pull request to publish api library and platforms into Maven central repository. **Modules explanation**: - API module contains common classes which might be used by plugins. - Plugin Platform module contains dependency declarations of other plugin API modules. - Application Platform module contains dependency declarations application module might uses. If we want to build application only(exclude check and jar), we have to execute the command below: ```bash ./gradlew clean :application:build -x :application:check -x :application:jar ``` The executable Jar will be generated at folder `application/build/libs/`. If we want to build a Docker image, we could execute the command below: ```bash docker build -t johnniang/halo:project-structure . # Test the Docker image docker run -it --rm -p8090:8090 johnniang/halo:project-structure ``` #### Which issue(s) this PR fixes: Fixes https://github.com/halo-dev/halo/issues/2730 #### Special notes for your reviewer: #### Does this PR introduce a user-facing change? ```release-note 重构项目结构 ```pull/3506/head^2
parent
7ca5270238
commit
c400c85922
|
@ -0,0 +1,3 @@
|
||||||
|
console
|
||||||
|
.github
|
||||||
|
.git
|
|
@ -5,8 +5,8 @@ logs/
|
||||||
|
|
||||||
### Gradle
|
### Gradle
|
||||||
.gradle
|
.gradle
|
||||||
/build/
|
build/
|
||||||
/out/
|
out/
|
||||||
!gradle/wrapper/gradle-wrapper.jar
|
!gradle/wrapper/gradle-wrapper.jar
|
||||||
bin/
|
bin/
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ application-local.yaml
|
||||||
application-local.properties
|
application-local.properties
|
||||||
|
|
||||||
### Zip file for test
|
### Zip file for test
|
||||||
!src/test/resources/themes/*.zip
|
!application/src/test/resources/themes/*.zip
|
||||||
!src/main/resources/themes/*.zip
|
!application/src/main/resources/themes/*.zip
|
||||||
src/main/resources/console/
|
application/src/main/resources/console/
|
||||||
src/main/resources/presets/
|
application/src/main/resources/presets/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
FROM eclipse-temurin:17-jre as builder
|
FROM eclipse-temurin:17-jre as builder
|
||||||
WORKDIR application
|
WORKDIR application
|
||||||
ARG JAR_FILE=build/libs/halo-*.jar
|
ARG JAR_FILE=application/build/libs/*.jar
|
||||||
COPY ${JAR_FILE} application.jar
|
COPY ${JAR_FILE} application.jar
|
||||||
RUN java -Djarmode=layertools -jar application.jar extract
|
RUN java -Djarmode=layertools -jar application.jar extract
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
plugins {
|
||||||
|
id 'java-library'
|
||||||
|
id 'maven-publish'
|
||||||
|
id "io.freefair.lombok" version "8.0.0-rc2"
|
||||||
|
}
|
||||||
|
|
||||||
|
group = 'run.halo.app'
|
||||||
|
description = 'API of halo project, connecting by other projects.'
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api platform(project(':platform:application'))
|
||||||
|
|
||||||
|
api 'org.springframework.boot:spring-boot-starter-actuator'
|
||||||
|
api 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||||
|
api 'org.springframework.boot:spring-boot-starter-mail'
|
||||||
|
api 'org.springframework.boot:spring-boot-starter-thymeleaf'
|
||||||
|
api 'org.springframework.boot:spring-boot-starter-webflux'
|
||||||
|
api 'org.springframework.boot:spring-boot-starter-validation'
|
||||||
|
api 'org.springframework.boot:spring-boot-starter-data-r2dbc'
|
||||||
|
|
||||||
|
// Spring Security
|
||||||
|
api 'org.springframework.boot:spring-boot-starter-security'
|
||||||
|
api 'org.springframework.security:spring-security-oauth2-jose'
|
||||||
|
api 'org.springframework.security:spring-security-oauth2-client'
|
||||||
|
api 'org.springframework.security:spring-security-oauth2-resource-server'
|
||||||
|
|
||||||
|
api "org.springdoc:springdoc-openapi-starter-webflux-ui"
|
||||||
|
api 'org.openapi4j:openapi-schema-validator'
|
||||||
|
api "net.bytebuddy:byte-buddy"
|
||||||
|
|
||||||
|
// Apache Lucene
|
||||||
|
api "org.apache.lucene:lucene-core"
|
||||||
|
api "org.apache.lucene:lucene-queryparser"
|
||||||
|
api "org.apache.lucene:lucene-highlighter"
|
||||||
|
api "org.apache.lucene:lucene-backward-codecs"
|
||||||
|
api 'cn.shenyanchao.ik-analyzer:ik-analyzer'
|
||||||
|
|
||||||
|
api "org.apache.commons:commons-lang3"
|
||||||
|
api "io.seruco.encoding:base62"
|
||||||
|
api "org.pf4j:pf4j"
|
||||||
|
api "com.google.guava:guava"
|
||||||
|
api "org.jsoup:jsoup"
|
||||||
|
api "io.github.java-diff-utils:java-diff-utils"
|
||||||
|
api "org.springframework.integration:spring-integration-core"
|
||||||
|
api "com.github.java-json-tools:json-patch"
|
||||||
|
api "org.thymeleaf.extras:thymeleaf-extras-springsecurity6"
|
||||||
|
|
||||||
|
runtimeOnly 'io.r2dbc:r2dbc-h2'
|
||||||
|
runtimeOnly 'org.postgresql:postgresql'
|
||||||
|
runtimeOnly 'org.postgresql:r2dbc-postgresql'
|
||||||
|
runtimeOnly 'org.mariadb:r2dbc-mariadb'
|
||||||
|
runtimeOnly 'com.github.jasync-sql:jasync-r2dbc-mysql'
|
||||||
|
|
||||||
|
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||||
|
testImplementation 'org.springframework.security:spring-security-test'
|
||||||
|
testImplementation 'io.projectreactor:reactor-test'
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
withSourcesJar()
|
||||||
|
withJavadocJar()
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.named('test') {
|
||||||
|
useJUnitPlatform()
|
||||||
|
}
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
library(MavenPublication) {
|
||||||
|
from components.java
|
||||||
|
}
|
||||||
|
}
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ package run.halo.app.content.comment;
|
||||||
|
|
||||||
import org.pf4j.ExtensionPoint;
|
import org.pf4j.ExtensionPoint;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
import run.halo.app.extension.AbstractExtension;
|
import run.halo.app.extension.Extension;
|
||||||
import run.halo.app.extension.Ref;
|
import run.halo.app.extension.Ref;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11,7 +11,7 @@ import run.halo.app.extension.Ref;
|
||||||
* @author guqing
|
* @author guqing
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
public interface CommentSubject<T extends AbstractExtension> extends ExtensionPoint {
|
public interface CommentSubject<T extends Extension> extends ExtensionPoint {
|
||||||
|
|
||||||
Mono<T> get(String name);
|
Mono<T> get(String name);
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
package run.halo.app.core.extension;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import run.halo.app.extension.AbstractExtension;
|
||||||
|
import run.halo.app.extension.GVK;
|
||||||
|
import run.halo.app.extension.Metadata;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A counter for number of requests by extension resource name.
|
||||||
|
*
|
||||||
|
* @author guqing
|
||||||
|
* @since 2.0.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@GVK(group = "metrics.halo.run", version = "v1alpha1", kind = "Counter", plural = "counters",
|
||||||
|
singular = "counter")
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class Counter extends AbstractExtension {
|
||||||
|
|
||||||
|
private Integer visit;
|
||||||
|
|
||||||
|
private Integer upvote;
|
||||||
|
|
||||||
|
private Integer downvote;
|
||||||
|
|
||||||
|
private Integer totalComment;
|
||||||
|
|
||||||
|
private Integer approvedComment;
|
||||||
|
|
||||||
|
public static Counter emptyCounter(String name) {
|
||||||
|
Counter counter = new Counter();
|
||||||
|
counter.setMetadata(new Metadata());
|
||||||
|
counter.getMetadata().setName(name);
|
||||||
|
counter.setUpvote(0);
|
||||||
|
counter.setTotalComment(0);
|
||||||
|
counter.setApprovedComment(0);
|
||||||
|
counter.setVisit(0);
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,10 +13,10 @@ import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import run.halo.app.extension.AbstractExtension;
|
import run.halo.app.extension.AbstractExtension;
|
||||||
import run.halo.app.extension.ExtensionUtil;
|
|
||||||
import run.halo.app.extension.GVK;
|
import run.halo.app.extension.GVK;
|
||||||
import run.halo.app.extension.GroupVersionKind;
|
import run.halo.app.extension.GroupVersionKind;
|
||||||
import run.halo.app.extension.MetadataOperator;
|
import run.halo.app.extension.MetadataOperator;
|
||||||
|
import run.halo.app.extension.MetadataUtil;
|
||||||
import run.halo.app.infra.ConditionList;
|
import run.halo.app.infra.ConditionList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -255,11 +255,6 @@ public class Post extends AbstractExtension {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Build compact post.
|
|
||||||
*
|
|
||||||
* @return a compact post
|
|
||||||
*/
|
|
||||||
public CompactPost build() {
|
public CompactPost build() {
|
||||||
CompactPost compactPost = new CompactPost();
|
CompactPost compactPost = new CompactPost();
|
||||||
compactPost.setName(name);
|
compactPost.setName(name);
|
||||||
|
@ -271,7 +266,7 @@ public class Post extends AbstractExtension {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void changePublishedState(Post post, boolean value) {
|
public static void changePublishedState(Post post, boolean value) {
|
||||||
Map<String, String> labels = ExtensionUtil.nullSafeLabels(post);
|
Map<String, String> labels = MetadataUtil.nullSafeLabels(post);
|
||||||
labels.put(PUBLISHED_LABEL, String.valueOf(value));
|
labels.put(PUBLISHED_LABEL, String.valueOf(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -9,9 +9,9 @@ import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import run.halo.app.extension.AbstractExtension;
|
import run.halo.app.extension.AbstractExtension;
|
||||||
import run.halo.app.extension.ExtensionUtil;
|
|
||||||
import run.halo.app.extension.GVK;
|
import run.halo.app.extension.GVK;
|
||||||
import run.halo.app.extension.GroupVersionKind;
|
import run.halo.app.extension.GroupVersionKind;
|
||||||
|
import run.halo.app.extension.MetadataUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Single page extension.</p>
|
* <p>Single page extension.</p>
|
||||||
|
@ -112,7 +112,7 @@ public class SinglePage extends AbstractExtension {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void changePublishedState(SinglePage page, boolean value) {
|
public static void changePublishedState(SinglePage page, boolean value) {
|
||||||
Map<String, String> labels = ExtensionUtil.nullSafeLabels(page);
|
Map<String, String> labels = MetadataUtil.nullSafeLabels(page);
|
||||||
labels.put(PUBLISHED_LABEL, String.valueOf(value));
|
labels.put(PUBLISHED_LABEL, String.valueOf(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
package run.halo.app.core.extension.content;
|
package run.halo.app.core.extension.content;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
|
@ -8,10 +7,7 @@ import java.util.Set;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import run.halo.app.content.ContentWrapper;
|
|
||||||
import run.halo.app.content.PatchUtils;
|
|
||||||
import run.halo.app.extension.AbstractExtension;
|
import run.halo.app.extension.AbstractExtension;
|
||||||
import run.halo.app.extension.GVK;
|
import run.halo.app.extension.GVK;
|
||||||
import run.halo.app.extension.Ref;
|
import run.halo.app.extension.Ref;
|
||||||
|
@ -69,27 +65,4 @@ public class Snapshot extends AbstractExtension {
|
||||||
contributors.add(name);
|
contributors.add(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
public ContentWrapper applyPatch(Snapshot baseSnapshot) {
|
|
||||||
Assert.notNull(baseSnapshot, "The baseSnapshot must not be null.");
|
|
||||||
String baseSnapshotName = baseSnapshot.getMetadata().getName();
|
|
||||||
if (StringUtils.equals(getMetadata().getName(), baseSnapshotName)) {
|
|
||||||
return ContentWrapper.builder()
|
|
||||||
.snapshotName(this.getMetadata().getName())
|
|
||||||
.raw(this.spec.rawPatch)
|
|
||||||
.content(this.spec.contentPatch)
|
|
||||||
.rawType(this.spec.rawType)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
String patchedContent =
|
|
||||||
PatchUtils.applyPatch(baseSnapshot.getSpec().getContentPatch(), this.spec.contentPatch);
|
|
||||||
String patchedRaw =
|
|
||||||
PatchUtils.applyPatch(baseSnapshot.getSpec().getRawPatch(), this.spec.rawPatch);
|
|
||||||
return ContentWrapper.builder()
|
|
||||||
.snapshotName(this.getMetadata().getName())
|
|
||||||
.raw(patchedRaw)
|
|
||||||
.content(patchedContent)
|
|
||||||
.rawType(this.spec.rawType)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -8,20 +8,21 @@ import java.util.function.Predicate;
|
||||||
/**
|
/**
|
||||||
* ExtensionClient is an interface which contains some operations on Extension instead of
|
* ExtensionClient is an interface which contains some operations on Extension instead of
|
||||||
* ExtensionStore.
|
* ExtensionStore.
|
||||||
|
* <br/><br/>
|
||||||
|
* Please note that this client can only use in non-reactive environment. If you want to
|
||||||
|
* use Extension client in reactive environment, please use {@link ReactiveExtensionClient} instead.
|
||||||
*
|
*
|
||||||
* @author johnniang
|
* @author johnniang
|
||||||
* @apiNote Please note that this client can only use in non-reactive environment. If you want to
|
|
||||||
* use Extension client in reactive environment, please use {@link ReactiveExtensionClient} instead.
|
|
||||||
*/
|
*/
|
||||||
public interface ExtensionClient {
|
public interface ExtensionClient {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lists Extensions by Extension type, filter and sorter.
|
* Lists Extensions by Extension type, filter and sorter.
|
||||||
*
|
*
|
||||||
* @param type is the class type of Extension.
|
* @param type is the class type of Extension.
|
||||||
* @param predicate filters the reEnqueue.
|
* @param predicate filters the reEnqueue.
|
||||||
* @param comparator sorts the reEnqueue.
|
* @param comparator sorts the reEnqueue.
|
||||||
* @param <E> is Extension type.
|
* @param <E> is Extension type.
|
||||||
* @return all filtered and sorted Extensions.
|
* @return all filtered and sorted Extensions.
|
||||||
*/
|
*/
|
||||||
<E extends Extension> List<E> list(Class<E> type, Predicate<E> predicate,
|
<E extends Extension> List<E> list(Class<E> type, Predicate<E> predicate,
|
||||||
|
@ -30,12 +31,12 @@ public interface ExtensionClient {
|
||||||
/**
|
/**
|
||||||
* Lists Extensions by Extension type, filter, sorter and page info.
|
* Lists Extensions by Extension type, filter, sorter and page info.
|
||||||
*
|
*
|
||||||
* @param type is the class type of Extension.
|
* @param type is the class type of Extension.
|
||||||
* @param predicate filters the reEnqueue.
|
* @param predicate filters the reEnqueue.
|
||||||
* @param comparator sorts the reEnqueue.
|
* @param comparator sorts the reEnqueue.
|
||||||
* @param page is page number which starts from 0.
|
* @param page is page number which starts from 0.
|
||||||
* @param size is page size.
|
* @param size is page size.
|
||||||
* @param <E> is Extension type.
|
* @param <E> is Extension type.
|
||||||
* @return a list of Extensions.
|
* @return a list of Extensions.
|
||||||
*/
|
*/
|
||||||
<E extends Extension> ListResult<E> list(Class<E> type, Predicate<E> predicate,
|
<E extends Extension> ListResult<E> list(Class<E> type, Predicate<E> predicate,
|
||||||
|
@ -46,7 +47,7 @@ public interface ExtensionClient {
|
||||||
*
|
*
|
||||||
* @param type is Extension type.
|
* @param type is Extension type.
|
||||||
* @param name is Extension name.
|
* @param name is Extension name.
|
||||||
* @param <E> is Extension type.
|
* @param <E> is Extension type.
|
||||||
* @return an optional Extension.
|
* @return an optional Extension.
|
||||||
*/
|
*/
|
||||||
<E extends Extension> Optional<E> fetch(Class<E> type, String name);
|
<E extends Extension> Optional<E> fetch(Class<E> type, String name);
|
||||||
|
@ -58,8 +59,8 @@ public interface ExtensionClient {
|
||||||
* Creates an Extension.
|
* Creates an Extension.
|
||||||
*
|
*
|
||||||
* @param extension is fresh Extension to be created. Please make sure the Extension name does
|
* @param extension is fresh Extension to be created. Please make sure the Extension name does
|
||||||
* not exist.
|
* not exist.
|
||||||
* @param <E> is Extension type.
|
* @param <E> is Extension type.
|
||||||
*/
|
*/
|
||||||
<E extends Extension> void create(E extension);
|
<E extends Extension> void create(E extension);
|
||||||
|
|
||||||
|
@ -67,8 +68,8 @@ public interface ExtensionClient {
|
||||||
* Updates an Extension.
|
* Updates an Extension.
|
||||||
*
|
*
|
||||||
* @param extension is an Extension to be updated. Please make sure the resource version is
|
* @param extension is an Extension to be updated. Please make sure the resource version is
|
||||||
* latest.
|
* latest.
|
||||||
* @param <E> is Extension type.
|
* @param <E> is Extension type.
|
||||||
*/
|
*/
|
||||||
<E extends Extension> void update(E extension);
|
<E extends Extension> void update(E extension);
|
||||||
|
|
||||||
|
@ -76,8 +77,8 @@ public interface ExtensionClient {
|
||||||
* Deletes an Extension.
|
* Deletes an Extension.
|
||||||
*
|
*
|
||||||
* @param extension is an Extension to be deleted. Please make sure the resource version is
|
* @param extension is an Extension to be deleted. Please make sure the resource version is
|
||||||
* latest.
|
* latest.
|
||||||
* @param <E> is Extension type.
|
* @param <E> is Extension type.
|
||||||
*/
|
*/
|
||||||
<E extends Extension> void delete(E extension);
|
<E extends Extension> void delete(E extension);
|
||||||
|
|
|
@ -1,22 +1,21 @@
|
||||||
package run.halo.app.extension;
|
package run.halo.app.extension;
|
||||||
|
|
||||||
import static run.halo.app.infra.utils.GenericClassUtils.generateConcreteClass;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Stream;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import net.bytebuddy.ByteBuddy;
|
import net.bytebuddy.ByteBuddy;
|
||||||
import net.bytebuddy.description.type.TypeDescription;
|
import net.bytebuddy.description.type.TypeDescription;
|
||||||
import org.springframework.data.util.Streamable;
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import run.halo.app.infra.utils.GenericClassUtils;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class ListResult<T> implements Streamable<T> {
|
public class ListResult<T> implements Iterable<T>, Supplier<Stream<T>> {
|
||||||
|
|
||||||
@Schema(description = "Page number, starts from 1. If not set or equal to 0, it means no "
|
@Schema(description = "Page number, starts from 1. If not set or equal to 0, it means no "
|
||||||
+ "pagination.", required = true)
|
+ "pagination.", required = true)
|
||||||
|
@ -83,12 +82,6 @@ public class ListResult<T> implements Streamable<T> {
|
||||||
return items.iterator();
|
return items.iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@JsonIgnore
|
|
||||||
public boolean isEmpty() {
|
|
||||||
return Streamable.super.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Schema(description = "Indicates total pages.", required = true)
|
@Schema(description = "Indicates total pages.", required = true)
|
||||||
@JsonProperty("totalPages")
|
@JsonProperty("totalPages")
|
||||||
public long getTotalPages() {
|
public long getTotalPages() {
|
||||||
|
@ -122,7 +115,7 @@ public class ListResult<T> implements Streamable<T> {
|
||||||
* @return generic ListResult class.
|
* @return generic ListResult class.
|
||||||
*/
|
*/
|
||||||
public static <T> Class<?> generateGenericClass(Class<T> type) {
|
public static <T> Class<?> generateGenericClass(Class<T> type) {
|
||||||
return generateConcreteClass(ListResult.class, type,
|
return GenericClassUtils.generateConcreteClass(ListResult.class, type,
|
||||||
() -> type.getSimpleName() + "List");
|
() -> type.getSimpleName() + "List");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,4 +139,9 @@ public class ListResult<T> implements Streamable<T> {
|
||||||
}
|
}
|
||||||
return listSort;
|
return listSort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<T> get() {
|
||||||
|
return items.stream();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -3,44 +3,9 @@ package run.halo.app.extension;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
/**
|
public enum MetadataUtil {
|
||||||
* Extension utilities.
|
;
|
||||||
*
|
|
||||||
* @author johnniang
|
|
||||||
*/
|
|
||||||
public final class ExtensionUtil {
|
|
||||||
|
|
||||||
private ExtensionUtil() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds the name prefix of ExtensionStore.
|
|
||||||
*
|
|
||||||
* @param scheme is scheme of an Extension.
|
|
||||||
* @return name prefix of ExtensionStore.
|
|
||||||
*/
|
|
||||||
public static String buildStoreNamePrefix(Scheme scheme) {
|
|
||||||
// rule of key: /registry/[group]/plural-name/extension-name
|
|
||||||
StringBuilder builder = new StringBuilder("/registry/");
|
|
||||||
if (StringUtils.hasText(scheme.groupVersionKind().group())) {
|
|
||||||
builder.append(scheme.groupVersionKind().group()).append('/');
|
|
||||||
}
|
|
||||||
builder.append(scheme.plural());
|
|
||||||
return builder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds full name of ExtensionStore.
|
|
||||||
*
|
|
||||||
* @param scheme is scheme of an Extension.
|
|
||||||
* @param name the exact name of Extension.
|
|
||||||
* @return full name of ExtensionStore.
|
|
||||||
*/
|
|
||||||
public static String buildStoreName(Scheme scheme, String name) {
|
|
||||||
return buildStoreNamePrefix(scheme) + "/" + name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets extension metadata labels null safe.
|
* Gets extension metadata labels null safe.
|
|
@ -1,10 +1,9 @@
|
||||||
package run.halo.app.infra.utils;
|
package run.halo.app.infra.utils;
|
||||||
|
|
||||||
import static net.bytebuddy.description.type.TypeDescription.Generic.Builder.parameterizedType;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import net.bytebuddy.ByteBuddy;
|
import net.bytebuddy.ByteBuddy;
|
||||||
|
import net.bytebuddy.description.type.TypeDescription;
|
||||||
import reactor.core.Exceptions;
|
import reactor.core.Exceptions;
|
||||||
|
|
||||||
public enum GenericClassUtils {
|
public enum GenericClassUtils {
|
||||||
|
@ -34,7 +33,8 @@ public enum GenericClassUtils {
|
||||||
*/
|
*/
|
||||||
public static <T> Class<?> generateConcreteClass(Class<?> rawClass, Class<T> parameterType,
|
public static <T> Class<?> generateConcreteClass(Class<?> rawClass, Class<T> parameterType,
|
||||||
Supplier<String> nameGenerator) {
|
Supplier<String> nameGenerator) {
|
||||||
var concreteType = parameterizedType(rawClass, parameterType).build();
|
var concreteType =
|
||||||
|
TypeDescription.Generic.Builder.parameterizedType(rawClass, parameterType).build();
|
||||||
try (var unloaded = new ByteBuddy()
|
try (var unloaded = new ByteBuddy()
|
||||||
.subclass(concreteType)
|
.subclass(concreteType)
|
||||||
.name(nameGenerator.get())
|
.name(nameGenerator.get())
|
|
@ -52,10 +52,11 @@ public class PathUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Combine paths based on the passed in path segments parameters.
|
* Combine paths based on the passed in path segments parameters.
|
||||||
|
* <br/><br/>
|
||||||
|
* This method doesn't work for Windows system currently.
|
||||||
*
|
*
|
||||||
* @param pathSegments Path segments to be combined
|
* @param pathSegments Path segments to be combined
|
||||||
* @return the combined path
|
* @return the combined path
|
||||||
* @apiNote This method doesn't work for Windows system currently.
|
|
||||||
*/
|
*/
|
||||||
public static String combinePath(String... pathSegments) {
|
public static String combinePath(String... pathSegments) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
|
@ -17,6 +17,7 @@ public class BasePlugin extends Plugin {
|
||||||
|
|
||||||
public BasePlugin(PluginWrapper wrapper) {
|
public BasePlugin(PluginWrapper wrapper) {
|
||||||
super(wrapper);
|
super(wrapper);
|
||||||
|
log.info("Initialized plugin {}", wrapper.getPluginId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private PluginManager getPluginManager() {
|
private PluginManager getPluginManager() {
|
|
@ -0,0 +1,15 @@
|
||||||
|
package run.halo.app.plugin;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public interface SettingFetcher {
|
||||||
|
|
||||||
|
<T> Optional<T> fetch(String group, Class<T> clazz);
|
||||||
|
|
||||||
|
JsonNode get(String group);
|
||||||
|
|
||||||
|
Map<String, JsonNode> getValues();
|
||||||
|
|
||||||
|
}
|
|
@ -2,7 +2,6 @@ package run.halo.app.search.post;
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import run.halo.app.theme.finders.vo.PostVo;
|
|
||||||
|
|
||||||
public record PostDoc(String name,
|
public record PostDoc(String name,
|
||||||
String title,
|
String title,
|
||||||
|
@ -20,15 +19,4 @@ public record PostDoc(String name,
|
||||||
Assert.notNull(publishTimestamp, "PublishTimestamp must not be null");
|
Assert.notNull(publishTimestamp, "PublishTimestamp must not be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Move this static method to other place.
|
|
||||||
public static PostDoc from(PostVo postVo) {
|
|
||||||
return new PostDoc(
|
|
||||||
postVo.getMetadata().getName(),
|
|
||||||
postVo.getSpec().getTitle(),
|
|
||||||
postVo.getStatus().getExcerpt(),
|
|
||||||
postVo.getContent().getContent(),
|
|
||||||
postVo.getSpec().getPublishTime(),
|
|
||||||
postVo.getStatus().getPermalink()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -7,7 +7,6 @@ import static org.mockito.ArgumentMatchers.same;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
import static run.halo.app.extension.FakeExtension.createFake;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
@ -46,7 +45,7 @@ class RequestSynchronizerTest {
|
||||||
@Test
|
@Test
|
||||||
void shouldStartCorrectlyWhenSyncingAllOnStart() {
|
void shouldStartCorrectlyWhenSyncingAllOnStart() {
|
||||||
when(client.list(same(FakeExtension.class), any(), any())).thenReturn(
|
when(client.list(same(FakeExtension.class), any(), any())).thenReturn(
|
||||||
List.of(createFake("fake-01"), createFake("fake-02")));
|
List.of(FakeExtension.createFake("fake-01"), FakeExtension.createFake("fake-02")));
|
||||||
|
|
||||||
synchronizer.start();
|
synchronizer.start();
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
plugins {
|
||||||
|
id 'org.springframework.boot' version '3.0.4'
|
||||||
|
id 'io.spring.dependency-management' version '1.1.0'
|
||||||
|
id "com.gorylenko.gradle-git-properties" version "2.3.2"
|
||||||
|
id "checkstyle"
|
||||||
|
id 'java'
|
||||||
|
id 'jacoco'
|
||||||
|
id "de.undercouch.download" version "5.3.1"
|
||||||
|
id "io.freefair.lombok" version "8.0.0-rc2"
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "run.halo.app"
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
|
|
||||||
|
checkstyle {
|
||||||
|
toolVersion = "9.3"
|
||||||
|
showViolations = false
|
||||||
|
ignoreFailures = false
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
|
||||||
|
maven { url 'https://repo.spring.io/milestone' }
|
||||||
|
mavenLocal()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
compileOnly {
|
||||||
|
extendsFrom annotationProcessor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
springBoot {
|
||||||
|
buildInfo()
|
||||||
|
}
|
||||||
|
|
||||||
|
bootJar {
|
||||||
|
manifest {
|
||||||
|
attributes "Implementation-Title": "Halo Application",
|
||||||
|
"Implementation-Version": archiveVersion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.named('jar') {
|
||||||
|
enabled = false
|
||||||
|
}
|
||||||
|
|
||||||
|
ext {
|
||||||
|
commonsLang3 = "3.12.0"
|
||||||
|
base62 = "0.1.3"
|
||||||
|
pf4j = '3.9.0'
|
||||||
|
javaDiffUtils = "4.12"
|
||||||
|
guava = "31.1-jre"
|
||||||
|
jsoup = '1.15.3'
|
||||||
|
jsonPatch = "1.13"
|
||||||
|
springDocOpenAPI = "2.0.2"
|
||||||
|
lucene = "9.5.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation project(':api')
|
||||||
|
|
||||||
|
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
|
||||||
|
annotationProcessor "org.springframework:spring-context-indexer"
|
||||||
|
|
||||||
|
developmentOnly 'org.springframework.boot:spring-boot-devtools'
|
||||||
|
|
||||||
|
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||||
|
testImplementation 'org.springframework.security:spring-security-test'
|
||||||
|
testImplementation 'io.projectreactor:reactor-test'
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.named('test') {
|
||||||
|
useJUnitPlatform()
|
||||||
|
finalizedBy jacocoTestReport
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.named('jacocoTestReport') {
|
||||||
|
reports {
|
||||||
|
xml.required = true
|
||||||
|
html.required = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register('downloadPluginPresets', Download) {
|
||||||
|
doFirst {
|
||||||
|
delete 'src/main/resources/presets/plugins'
|
||||||
|
}
|
||||||
|
src([
|
||||||
|
'https://github.com/halo-sigs/plugin-comment-widget/releases/download/v1.3.0/plugin-comment-widget-1.3.0.jar',
|
||||||
|
'https://github.com/halo-sigs/plugin-search-widget/releases/download/v1.0.0/plugin-search-widget-1.0.0.jar',
|
||||||
|
'https://github.com/halo-sigs/plugin-sitemap/releases/download/v1.0.1/plugin-sitemap-1.0.1.jar',
|
||||||
|
'https://github.com/halo-sigs/plugin-feed/releases/download/v1.1.0-beta.1/plugin-feed-1.1.0-beta.1.jar'
|
||||||
|
])
|
||||||
|
dest 'src/main/resources/presets/plugins'
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue