-
-
Notifications
You must be signed in to change notification settings - Fork 120
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for Bun
- Loading branch information
Showing
23 changed files
with
1,504 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
99 changes: 99 additions & 0 deletions
99
src/main/kotlin/com/github/gradle/node/bun/exec/BunExecRunner.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
package com.github.gradle.node.bun.exec | ||
|
||
import com.github.gradle.node.NodeExtension | ||
import com.github.gradle.node.exec.ExecConfiguration | ||
import com.github.gradle.node.exec.ExecRunner | ||
import com.github.gradle.node.exec.NodeExecConfiguration | ||
import com.github.gradle.node.npm.exec.NpmExecConfiguration | ||
import com.github.gradle.node.npm.proxy.NpmProxy | ||
import com.github.gradle.node.util.ProjectApiHelper | ||
import com.github.gradle.node.util.zip | ||
import com.github.gradle.node.variant.VariantComputer | ||
import com.github.gradle.node.variant.computeNodeExec | ||
import org.gradle.api.provider.Provider | ||
import org.gradle.api.provider.ProviderFactory | ||
import org.gradle.process.ExecResult | ||
import javax.inject.Inject | ||
|
||
abstract class BunExecRunner { | ||
@get:Inject | ||
abstract val providers: ProviderFactory | ||
|
||
fun executeBunCommand(project: ProjectApiHelper, extension: NodeExtension, nodeExecConfiguration: NodeExecConfiguration, variants: VariantComputer): ExecResult { | ||
val bunExecConfiguration = NpmExecConfiguration("bun" | ||
) { variantComputer, nodeExtension, binDir -> variantComputer.computeBunExec(nodeExtension, binDir) } | ||
|
||
val enhancedNodeExecConfiguration = NpmProxy.addProxyEnvironmentVariables(extension.nodeProxySettings.get(), nodeExecConfiguration) | ||
val execConfiguration = computeExecConfiguration(extension, bunExecConfiguration, enhancedNodeExecConfiguration, variants).get() | ||
return ExecRunner().execute(project, extension, execConfiguration) | ||
} | ||
|
||
fun executeBunxCommand(project: ProjectApiHelper, extension: NodeExtension, nodeExecConfiguration: NodeExecConfiguration, variants: VariantComputer): ExecResult { | ||
val bunExecConfiguration = NpmExecConfiguration("bunx") { variantComputer, nodeExtension, bunBinDir -> | ||
variantComputer.computeBunxExec(nodeExtension, bunBinDir) | ||
} | ||
|
||
val enhancedNodeExecConfiguration = NpmProxy.addProxyEnvironmentVariables(extension.nodeProxySettings.get(), nodeExecConfiguration) | ||
val execConfiguration = computeExecConfiguration(extension, bunExecConfiguration, enhancedNodeExecConfiguration, variants).get() | ||
return ExecRunner().execute(project, extension, execConfiguration) | ||
} | ||
|
||
private fun computeExecConfiguration(extension: NodeExtension, bunExecConfiguration: NpmExecConfiguration, | ||
nodeExecConfiguration: NodeExecConfiguration, | ||
variantComputer: VariantComputer): Provider<ExecConfiguration> { | ||
val additionalBinPathProvider = computeAdditionalBinPath(extension, variantComputer) | ||
val executableAndScriptProvider = computeExecutable(extension, bunExecConfiguration, variantComputer) | ||
return zip(additionalBinPathProvider, executableAndScriptProvider) | ||
.map { (additionalBinPath, executableAndScript) -> | ||
val argsPrefix = | ||
if (executableAndScript.script != null) listOf(executableAndScript.script) else listOf() | ||
val args = argsPrefix.plus(nodeExecConfiguration.command) | ||
ExecConfiguration(executableAndScript.executable, args, additionalBinPath, | ||
nodeExecConfiguration.environment, nodeExecConfiguration.workingDir, | ||
nodeExecConfiguration.ignoreExitValue, nodeExecConfiguration.execOverrides) | ||
} | ||
} | ||
|
||
private fun computeExecutable( | ||
nodeExtension: NodeExtension, | ||
bunExecConfiguration: NpmExecConfiguration, | ||
variantComputer: VariantComputer | ||
): | ||
Provider<ExecutableAndScript> { | ||
val nodeDirProvider = nodeExtension.resolvedNodeDir | ||
val bunDirProvider = variantComputer.computeBunDir(nodeExtension) | ||
val nodeBinDirProvider = variantComputer.computeNodeBinDir(nodeDirProvider, nodeExtension.resolvedPlatform) | ||
val bunBinDirProvider = variantComputer.computeBunBinDir(bunDirProvider, nodeExtension.resolvedPlatform) | ||
val nodeExecProvider = computeNodeExec(nodeExtension, nodeBinDirProvider) | ||
val executableProvider = | ||
bunExecConfiguration.commandExecComputer(variantComputer, nodeExtension, bunBinDirProvider) | ||
|
||
return zip(nodeExtension.download, nodeExtension.nodeProjectDir, executableProvider, nodeExecProvider).map { | ||
val (download, nodeProjectDir, executable, nodeExec) = it | ||
if (download) { | ||
val localCommandScript = nodeProjectDir.dir("node_modules/bun/bin") | ||
.file("${bunExecConfiguration.command}.js").asFile | ||
if (localCommandScript.exists()) { | ||
return@map ExecutableAndScript(nodeExec, localCommandScript.absolutePath) | ||
} | ||
} | ||
return@map ExecutableAndScript(executable) | ||
} | ||
} | ||
|
||
private data class ExecutableAndScript( | ||
val executable: String, | ||
val script: String? = null | ||
) | ||
|
||
private fun computeAdditionalBinPath(nodeExtension: NodeExtension, variantComputer: VariantComputer): Provider<List<String>> { | ||
return nodeExtension.download.flatMap { download -> | ||
if (!download) { | ||
providers.provider { listOf<String>() } | ||
} | ||
val bunDirProvider = variantComputer.computeBunDir(nodeExtension) | ||
val bunBinDirProvider = variantComputer.computeBunBinDir(bunDirProvider, nodeExtension.resolvedPlatform) | ||
bunBinDirProvider.map { file -> listOf(file.asFile.absolutePath) } | ||
} | ||
} | ||
} |
59 changes: 59 additions & 0 deletions
59
src/main/kotlin/com/github/gradle/node/bun/task/BunAbstractTask.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package com.github.gradle.node.bun.task | ||
|
||
import com.github.gradle.node.NodeExtension | ||
import com.github.gradle.node.NodePlugin | ||
import com.github.gradle.node.task.BaseTask | ||
import com.github.gradle.node.util.DefaultProjectApiHelper | ||
import org.gradle.api.Action | ||
import org.gradle.api.model.ObjectFactory | ||
import org.gradle.api.provider.ProviderFactory | ||
import org.gradle.api.tasks.Input | ||
import org.gradle.api.tasks.Internal | ||
import org.gradle.api.tasks.Optional | ||
import org.gradle.kotlin.dsl.listProperty | ||
import org.gradle.kotlin.dsl.mapProperty | ||
import org.gradle.kotlin.dsl.newInstance | ||
import org.gradle.kotlin.dsl.property | ||
import org.gradle.process.ExecSpec | ||
import javax.inject.Inject | ||
|
||
abstract class BunAbstractTask : BaseTask() { | ||
@get:Inject | ||
abstract val objects: ObjectFactory | ||
|
||
@get:Inject | ||
abstract val providers: ProviderFactory | ||
|
||
@get:Optional | ||
@get:Input | ||
val args = objects.listProperty<String>() | ||
|
||
@get:Input | ||
val ignoreExitValue = objects.property<Boolean>().convention(false) | ||
|
||
@get:Input | ||
val environment = objects.mapProperty<String, String>() | ||
|
||
@get:Internal | ||
val workingDir = objects.directoryProperty() | ||
|
||
@get:Internal | ||
val execOverrides = objects.property<Action<ExecSpec>>() | ||
|
||
@get:Internal | ||
val projectHelper = project.objects.newInstance<DefaultProjectApiHelper>() | ||
|
||
@get:Internal | ||
val nodeExtension = NodeExtension[project] | ||
|
||
init { | ||
group = NodePlugin.BUN_GROUP | ||
dependsOn(BunSetupTask.NAME) | ||
} | ||
|
||
// For DSL | ||
@Suppress("unused") | ||
fun execOverrides(execOverrides: Action<ExecSpec>) { | ||
this.execOverrides.set(execOverrides) | ||
} | ||
} |
88 changes: 88 additions & 0 deletions
88
src/main/kotlin/com/github/gradle/node/bun/task/BunInstallTask.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package com.github.gradle.node.bun.task | ||
|
||
import com.github.gradle.node.NodePlugin | ||
import com.github.gradle.node.util.zip | ||
import org.gradle.api.Action | ||
import org.gradle.api.file.ConfigurableFileTree | ||
import org.gradle.api.file.Directory | ||
import org.gradle.api.file.FileTree | ||
import org.gradle.api.provider.Provider | ||
import org.gradle.api.tasks.* | ||
import org.gradle.api.tasks.PathSensitivity.RELATIVE | ||
import org.gradle.kotlin.dsl.property | ||
import java.io.File | ||
|
||
/** | ||
* bun install that only gets executed if gradle decides so. | ||
*/ | ||
abstract class BunInstallTask : BunTask() { | ||
|
||
@get:Internal | ||
val nodeModulesOutputFilter = | ||
objects.property<Action<ConfigurableFileTree>>() | ||
|
||
|
||
init { | ||
group = NodePlugin.BUN_GROUP | ||
description = "Install packages from package.json." | ||
dependsOn(BunSetupTask.NAME) | ||
bunCommand.set(nodeExtension.npmInstallCommand.map { | ||
when(it) { | ||
"ci" -> listOf("install", "--frozen-lockfile") | ||
else -> listOf(it) | ||
} | ||
}) | ||
} | ||
|
||
@PathSensitive(RELATIVE) | ||
@InputFile | ||
protected fun getPackageJsonFile(): File? { | ||
return projectFileIfExists("package.json").orNull | ||
} | ||
|
||
@Optional | ||
@OutputFile | ||
protected fun getBunLockAsOutput(): File? { | ||
return projectFileIfExists("bun.lockb").orNull | ||
} | ||
|
||
private fun projectFileIfExists(name: String): Provider<File?> { | ||
return nodeExtension.nodeProjectDir.map { it.file(name).asFile } | ||
.flatMap { if (it.exists()) providers.provider { it } else providers.provider { null } } | ||
} | ||
|
||
@Optional | ||
@OutputDirectory | ||
@Suppress("unused") | ||
protected fun getNodeModulesDirectory(): Provider<Directory> { | ||
val filter = nodeModulesOutputFilter.orNull | ||
return if (filter == null) nodeExtension.nodeProjectDir.dir("node_modules") | ||
else providers.provider { null } | ||
} | ||
|
||
@Optional | ||
@OutputFiles | ||
@Suppress("unused") | ||
protected fun getNodeModulesFiles(): Provider<FileTree> { | ||
val nodeModulesDirectoryProvider = nodeExtension.nodeProjectDir.dir("node_modules") | ||
return zip(nodeModulesDirectoryProvider, nodeModulesOutputFilter) | ||
.flatMap { (nodeModulesDirectory, nodeModulesOutputFilter) -> | ||
if (nodeModulesOutputFilter != null) { | ||
val fileTree = projectHelper.fileTree(nodeModulesDirectory) | ||
nodeModulesOutputFilter.execute(fileTree) | ||
providers.provider { fileTree } | ||
} else providers.provider { null } | ||
} | ||
} | ||
|
||
// For DSL | ||
@Suppress("unused") | ||
fun nodeModulesOutputFilter(nodeModulesOutputFilter: Action<ConfigurableFileTree>) { | ||
this.nodeModulesOutputFilter.set(nodeModulesOutputFilter) | ||
} | ||
|
||
companion object { | ||
const val NAME = "bunInstall" | ||
} | ||
|
||
} |
53 changes: 53 additions & 0 deletions
53
src/main/kotlin/com/github/gradle/node/bun/task/BunSetupTask.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package com.github.gradle.node.bun.task | ||
|
||
import com.github.gradle.node.NodePlugin | ||
import com.github.gradle.node.npm.task.NpmSetupTask | ||
import com.github.gradle.node.variant.VariantComputer | ||
import org.gradle.api.provider.Provider | ||
import org.gradle.api.tasks.Input | ||
import org.gradle.api.tasks.OutputDirectory | ||
|
||
/** | ||
* bun install that only gets executed if gradle decides so. | ||
*/ | ||
abstract class BunSetupTask : NpmSetupTask() { | ||
|
||
init { | ||
group = NodePlugin.BUN_GROUP | ||
description = "Setup a specific version of Bun to be used by the build." | ||
} | ||
|
||
@Input | ||
override fun getVersion(): Provider<String> { | ||
return nodeExtension.bunVersion | ||
} | ||
|
||
@get:OutputDirectory | ||
val bunDir by lazy { | ||
val variantComputer = VariantComputer() | ||
variantComputer.computeBunDir(nodeExtension) | ||
} | ||
|
||
override fun computeCommand(): List<String> { | ||
val version = nodeExtension.bunVersion.get() | ||
val bunDir = bunDir.get() | ||
val bunPackage = if (version.isNotBlank()) "bun@$version" else "bun" | ||
return listOf( | ||
"install", | ||
"--global", | ||
"--no-save", | ||
"--prefix", | ||
bunDir.asFile.absolutePath, | ||
bunPackage | ||
) + args.get() | ||
} | ||
|
||
override fun isTaskEnabled(): Boolean { | ||
return true | ||
} | ||
|
||
companion object { | ||
const val NAME = "bunSetup" | ||
} | ||
|
||
} |
Oops, something went wrong.