build.gradle.kts
3.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// vibe_erp web SPA — Gradle wrapper around the npm build.
//
// **Why no Kotlin/JVM source set.** This subproject has zero JVM
// code: every artifact under src/ is TypeScript/React. The Gradle
// presence is purely so `./gradlew build` runs the npm build as
// part of the standard build pipeline, and so :distribution can
// declare a normal project dependency on the produced static
// bundle instead of a fragile path reference.
//
// **Tasks.**
// - `npmInstall` → runs `npm install` in web/. Inputs:
// package.json + package-lock.json. Output: node_modules/.
// - `npmBuild` → runs `npm run build` in web/. Inputs:
// src/**, index.html, vite.config.ts, tsconfig*.json,
// tailwind.config.js, postcss.config.js. Output: dist/.
// - `assemble` → wired to depend on npmBuild so a normal
// `./gradlew :web:build` produces dist/.
//
// **No npm/node Gradle plugin.** I deliberately avoided
// `com.github.node-gradle.node` to keep the dep surface minimal —
// every plugin is one more thing to keep current with Gradle and
// JDK upgrades. Exec tasks are stable and the inputs/outputs
// declarations give Gradle the same up-to-date checking the plugin
// would.
//
// **Where the bundle goes.** Read by `:distribution` as a normal
// project artifact via the `webStaticBundle` configuration below;
// the consuming module copies dist/ into the Spring Boot
// classpath under `static/` at processResources time so the
// bootJar contains the entire SPA.
import org.gradle.api.tasks.Exec
plugins {
base
}
description = "vibe_erp web SPA — Vite + React + TS, served by Spring Boot at the root path."
// Resolve npm against the system PATH. Same approach as the
// reference plug-in's installToDev task — keeps developer setup
// simple ("you must have node + npm on PATH").
val npmCommand: String = if (org.gradle.internal.os.OperatingSystem.current().isWindows) "npm.cmd" else "npm"
val npmInstall by tasks.registering(Exec::class) {
group = "build"
description = "Run `npm install` in web/."
workingDir = projectDir
commandLine(npmCommand, "install", "--no-audit", "--no-fund", "--silent")
inputs.file("package.json")
inputs.file("package-lock.json").optional()
outputs.dir("node_modules")
}
val npmBuild by tasks.registering(Exec::class) {
group = "build"
description = "Run `npm run build` in web/. Produces dist/."
workingDir = projectDir
commandLine(npmCommand, "run", "build")
dependsOn(npmInstall)
inputs.dir("src")
inputs.file("index.html")
inputs.file("vite.config.ts")
inputs.file("tsconfig.json")
inputs.file("tsconfig.node.json")
inputs.file("tailwind.config.js")
inputs.file("postcss.config.js")
inputs.file("package.json")
outputs.dir("dist")
}
tasks.named("assemble") {
dependsOn(npmBuild)
}
// Outgoing configuration so :distribution can consume the dist
// directory as a normal Gradle artifact. Using a single-element
// `artifacts` block keeps the consumer side trivial.
val webStaticBundle: Configuration by configurations.creating {
isCanBeConsumed = true
isCanBeResolved = false
}
artifacts {
add(webStaticBundle.name, file("dist")) {
builtBy(npmBuild)
}
}