From 331369462253c1fe63fbe1fb946978ddb6757f3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Petu=C5=A1ka?= Date: Sat, 23 Oct 2021 15:46:00 +0100 Subject: [PATCH] spotless --- build.gradle.kts | 54 +-- buildSrc/build.gradle.kts | 4 + .../main/kotlin/plugin.git-hooks.gradle.kts | 5 + src/main/kotlin/NpmPublishPlugin.kt | 205 +++++----- src/main/kotlin/delegate/ChainedProperty.kt | 4 +- src/main/kotlin/delegate/FallbackDelegate.kt | 10 +- src/main/kotlin/delegate/GradleProperty.kt | 36 +- src/main/kotlin/delegate/PropertyDelegate.kt | 17 +- src/main/kotlin/delegate/builders.kt | 28 +- src/main/kotlin/dsl/NpmAccess.kt | 4 +- src/main/kotlin/dsl/NpmPublication.kt | 199 +++++----- src/main/kotlin/dsl/NpmPublishExtension.kt | 136 +++---- .../kotlin/dsl/NpmPublishExtensionScope.kt | 6 +- src/main/kotlin/dsl/NpmRepository.kt | 53 +-- src/main/kotlin/dsl/NpmShrinkwrapJson.kt | 57 +-- src/main/kotlin/dsl/PackageJson.kt | 349 ++++++----------- src/main/kotlin/task/NpmExecTask.kt | 62 ++- src/main/kotlin/task/NpmPackTask.kt | 39 +- .../kotlin/task/NpmPackageAssembleTask.kt | 366 +++++++++--------- src/main/kotlin/task/NpmPublishTask.kt | 73 ++-- src/main/kotlin/util/general.kt | 12 +- src/test/kotlin/NpmPublishPluginTest.kt | 55 ++- versions.properties | 37 +- 23 files changed, 815 insertions(+), 996 deletions(-) create mode 100644 buildSrc/src/main/kotlin/plugin.git-hooks.gradle.kts diff --git a/build.gradle.kts b/build.gradle.kts index c3b1a798..3bb054c4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,20 +1,22 @@ -import de.fayard.refreshVersions.core.versionFor import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { + if (System.getenv("CI") == null) { + id("plugin.git-hooks") + } kotlin("jvm") version "1.4.31" id("com.gradle.plugin-publish") id("org.jetbrains.dokka") - id("com.github.jakemarsden.git-hooks") - id("org.jlleitschuh.gradle.ktlint") id("io.github.gradle-nexus.publish-plugin") + id("com.diffplug.spotless") `java-gradle-plugin` `maven-publish` signing idea } -description = """ +description = + """ A maven-publish alternative for NPM package publishing. Integrates with kotlin JS/MPP plugins (if applied) to automatically setup publishing to NPM repositories for all JS targets. @@ -27,9 +29,9 @@ idea { } } -ktlint { - version by versionFor("version.ktlint") - additionalEditorconfigFile.set(rootDir.resolve(".editorconfig")) +spotless { + kotlin { ktfmt() } + kotlinGradle { ktfmt() } } gradleEnterprise { @@ -39,15 +41,6 @@ gradleEnterprise { } } -gitHooks { - setHooks( - mapOf( - "pre-commit" to "ktlintFormat", - "pre-push" to "ktlintCheck" - ) - ) -} - repositories { mavenLocal() mavenCentral() @@ -58,11 +51,14 @@ kotlin { dependencies { implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:_") implementation("com.google.code.gson:gson:_") + api("dev.petuska:kon:_") testImplementation("io.kotest:kotest-runner-junit5:_") + testImplementation("dev.petuska:klip:_") } } val pluginId = "dev.petuska.npm.publish" + gradlePlugin { plugins { create(name) { @@ -105,13 +101,7 @@ signing { } } -tasks { - withType { - kotlinOptions { - jvmTarget = "${JavaVersion.VERSION_11}" - } - } -} +tasks { withType { kotlinOptions { jvmTarget = "${JavaVersion.VERSION_11}" } } } publishing { publications { @@ -159,17 +149,15 @@ afterEvaluate { tasks { withType { manifest { - attributes += sortedMapOf( - "Built-By" to System.getProperty("user.name"), - "Build-Jdk" to System.getProperty("java.version"), - "Implementation-Version" to project.version, - "Created-By" to "Gradle v${GradleVersion.current()}", - "Created-From" to Git.headCommitHash - ) + attributes += + sortedMapOf( + "Built-By" to System.getProperty("user.name"), + "Build-Jdk" to System.getProperty("java.version"), + "Implementation-Version" to project.version, + "Created-By" to "Gradle v${GradleVersion.current()}", + "Created-From" to Git.headCommitHash) } } - withType { - useJUnitPlatform() - } + withType { useJUnitPlatform() } } } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index e98dc090..b93ecd65 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -7,3 +7,7 @@ repositories { jcenter() mavenCentral() } + +dependencies { + implementation("com.github.jakemarsden:git-hooks-gradle-plugin:_") +} diff --git a/buildSrc/src/main/kotlin/plugin.git-hooks.gradle.kts b/buildSrc/src/main/kotlin/plugin.git-hooks.gradle.kts new file mode 100644 index 00000000..d7bb8753 --- /dev/null +++ b/buildSrc/src/main/kotlin/plugin.git-hooks.gradle.kts @@ -0,0 +1,5 @@ +plugins { + id("com.github.jakemarsden.git-hooks") +} + +gitHooks { setHooks(mapOf("pre-commit" to "spotlessApply", "pre-push" to "spotlessCheck")) } diff --git a/src/main/kotlin/NpmPublishPlugin.kt b/src/main/kotlin/NpmPublishPlugin.kt index 8188de91..f97773b6 100644 --- a/src/main/kotlin/NpmPublishPlugin.kt +++ b/src/main/kotlin/NpmPublishPlugin.kt @@ -16,9 +16,7 @@ import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsTargetDsl import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsSetupTask import org.jetbrains.kotlin.gradle.targets.js.npm.NpmDependency -/** - * Main entry point for npm-publish plugin - */ +/** Main entry point for npm-publish plugin */ class NpmPublishPlugin : Plugin { override fun apply(project: Project) { val extension = project.createExtension() @@ -45,34 +43,31 @@ class NpmPublishPlugin : Plugin { private const val KOTLIN_MPP_PLUGIN = "org.jetbrains.kotlin.multiplatform" private const val MAVEN_PUBLISH_PLUGIN = "org.gradle.maven-publish" - private fun Project.createExtension() = extensions.findByType(NpmPublishExtension::class.java) ?: extensions.create( - EXTENSION_NAME, - NpmPublishExtension::class.java, - this@createExtension - ) + private fun Project.createExtension() = + extensions.findByType(NpmPublishExtension::class.java) + ?: extensions.create( + EXTENSION_NAME, NpmPublishExtension::class.java, this@createExtension) - private fun Project.configureExtension(extension: NpmPublishExtension, target: KotlinJsTargetDsl) { + private fun Project.configureExtension( + extension: NpmPublishExtension, + target: KotlinJsTargetDsl + ) { target.binaries.find { it.mode == KotlinJsBinaryMode.PRODUCTION }?.let { binary -> - val deps = binary.compilation.relatedConfigurationNames.flatMap { conf -> - val mainName = "${target.name}Main${conf.substringAfter(target.name)}" - val normDeps = configurations.findByName(conf)?.dependencies?.toSet() ?: setOf() - val mainDeps = configurations.findByName(mainName)?.dependencies?.toSet() ?: setOf() - (normDeps + mainDeps).filterIsInstance() - } + val deps = + binary.compilation.relatedConfigurationNames.flatMap { conf -> + val mainName = "${target.name}Main${conf.substringAfter(target.name)}" + val normDeps = configurations.findByName(conf)?.dependencies?.toSet() ?: setOf() + val mainDeps = configurations.findByName(mainName)?.dependencies?.toSet() ?: setOf() + (normDeps + mainDeps).filterIsInstance() + } extension.apply { publications(0) { publication(target.name) { this.binary = binary this.main = compileKotlinTask?.outputFileProperty?.orNull?.name - dependencies { - addAll(deps) - } - packageJson { - bundledDependencies { - -"kotlin-test.*".toRegex() - } - } + dependencies { addAll(deps) } + packageJson { bundledDependencies { -"kotlin-test.*".toRegex() } } } } } @@ -80,84 +75,98 @@ class NpmPublishPlugin : Plugin { } private fun Project.configureTasks(extension: NpmPublishExtension) { - val nodeJsSetupTask = project.rootProject.tasks.findByName("kotlinNodeJsSetup") as NodeJsSetupTask? + val nodeJsSetupTask = + project.rootProject.tasks.findByName("kotlinNodeJsSetup") as NodeJsSetupTask? - val publishTask = tasks.findByName("publish") ?: tasks.create("publish") { - it.group = "publishing" - it.enabled = false - } + val publishTask = + tasks.findByName("publish") + ?: tasks.create("publish") { + it.group = "publishing" + it.enabled = false + } val assembleTask = tasks.findByName("assemble") - val packTask = tasks.findByName("pack") ?: tasks.create("pack") { - it.group = "build" - it.enabled = false - } - - val publications = with(extension) { - pubConfigs.forEach { - publications.configure(it) - } - publications.mapNotNull { pub -> - val needsNode = pub.nodeJsDir == null - pub.validate(nodeJsSetupTask?.destination)?.let { - it to nodeJsSetupTask?.takeIf { needsNode } - } ?: null.also { logger.warn("NPM Publication [${pub.name}] is invalid. Skipping...") } - } - } - - val repositories = with(extension) { - repoConfigs.forEach { - repositories.configure(it) - } - repositories.mapNotNull { repo -> - repo.validate() ?: null.also { logger.warn("NPM Repository [${repo.name}] is invalid. Skipping...") } - } - } + val packTask = + tasks.findByName("pack") + ?: tasks.create("pack") { + it.group = "build" + it.enabled = false + } - val pubTasks = publications.flatMap { (pub, nodeJsTask) -> - val processResourcesTask = pub.binary?.compilation?.let { - val processResourcesTask = project.tasks.findByName(it.processResourcesTaskName) as Copy - pub.kotlinDestinationDir?.let { kotlinDestinationDir -> - pub.files { - from(kotlinDestinationDir) - from(processResourcesTask.destinationDir) + val publications = + with(extension) { + pubConfigs.forEach { publications.configure(it) } + publications.mapNotNull { pub -> + val needsNode = pub.nodeJsDir == null + pub.validate(nodeJsSetupTask?.destination)?.let { + it to nodeJsSetupTask?.takeIf { needsNode } + } + ?: null.also { + logger.warn("NPM Publication [${pub.name}] is invalid. Skipping...") + } } } - processResourcesTask - } - val upperName = GUtil.toCamelCase(pub.name) - val assembleTaskName = "assemble${upperName}NpmPublication" - val packTaskName = "pack${upperName}NpmPublication" - val assemblePackageTask = tasks.findByName(assembleTaskName) as NpmPackageAssembleTask? - ?: tasks.create(assembleTaskName, NpmPackageAssembleTask::class.java, pub).also { task -> - task.onlyIf { pub.compileKotlinTask?.outputFileProperty?.orNull?.exists() ?: true } - task.dependsOn( - *listOfNotNull( - processResourcesTask, - pub.kotlinMainTask, - nodeJsTask - ).toTypedArray() - ) - assembleTask?.dependsOn(task) - } - val npmPackTask = tasks.findByName(packTaskName) as NpmPackTask? - ?: tasks.create(packTaskName, NpmPackTask::class.java, pub).also { - it.onlyIf { assemblePackageTask.didWork } - it.dependsOn(assemblePackageTask) + val repositories = + with(extension) { + repoConfigs.forEach { repositories.configure(it) } + repositories.mapNotNull { repo -> + repo.validate() + ?: null.also { + logger.warn("NPM Repository [${repo.name}] is invalid. Skipping...") + } + } } - packTask.dependsOn(npmPackTask) - packTask.enabled = true - repositories.map { repo -> - val upperRepoName = GUtil.toCamelCase(repo.name) - val publishTaskName = "publish${upperName}NpmPublicationTo$upperRepoName" - tasks.findByName(publishTaskName) - ?: tasks.create(publishTaskName, NpmPublishTask::class.java, pub, repo).also { task -> - task.onlyIf { assemblePackageTask.didWork } - task.dependsOn(assemblePackageTask) - publishTask.dependsOn(task) + + val pubTasks = + publications.flatMap { (pub, nodeJsTask) -> + val processResourcesTask = + pub.binary?.compilation?.let { + val processResourcesTask = + project.tasks.findByName(it.processResourcesTaskName) as Copy + pub.kotlinDestinationDir?.let { kotlinDestinationDir -> + pub.files { + from(kotlinDestinationDir) + from(processResourcesTask.destinationDir) + } + } + processResourcesTask + } + val upperName = GUtil.toCamelCase(pub.name) + + val assembleTaskName = "assemble${upperName}NpmPublication" + val packTaskName = "pack${upperName}NpmPublication" + val assemblePackageTask = + tasks.findByName(assembleTaskName) as NpmPackageAssembleTask? + ?: tasks.create(assembleTaskName, NpmPackageAssembleTask::class.java, pub) + .also { task -> + task.onlyIf { + pub.compileKotlinTask?.outputFileProperty?.orNull?.exists() ?: true + } + task.dependsOn( + *listOfNotNull(processResourcesTask, pub.kotlinMainTask, nodeJsTask) + .toTypedArray()) + assembleTask?.dependsOn(task) + } + val npmPackTask = + tasks.findByName(packTaskName) as NpmPackTask? + ?: tasks.create(packTaskName, NpmPackTask::class.java, pub).also { + it.onlyIf { assemblePackageTask.didWork } + it.dependsOn(assemblePackageTask) + } + packTask.dependsOn(npmPackTask) + packTask.enabled = true + repositories.map { repo -> + val upperRepoName = GUtil.toCamelCase(repo.name) + val publishTaskName = "publish${upperName}NpmPublicationTo$upperRepoName" + tasks.findByName(publishTaskName) + ?: tasks.create(publishTaskName, NpmPublishTask::class.java, pub, repo).also { + task -> + task.onlyIf { assemblePackageTask.didWork } + task.dependsOn(assemblePackageTask) + publishTask.dependsOn(task) + } } - } - } + } if (pubTasks.isNotEmpty()) { publishTask.enabled = true } @@ -166,8 +175,10 @@ class NpmPublishPlugin : Plugin { } internal val Project.npmPublishing: NpmPublishExtension - get() = extensions.getByName(EXTENSION_NAME) as? NpmPublishExtension - ?: throw IllegalStateException("$EXTENSION_NAME is not of the correct type") + get() = + extensions.getByName(EXTENSION_NAME) as? NpmPublishExtension + ?: throw IllegalStateException("$EXTENSION_NAME is not of the correct type") -internal fun Project.npmPublishing(config: NpmPublishExtension.() -> Unit = {}): NpmPublishExtension = - npmPublishing.apply(config) +internal fun Project.npmPublishing( + config: NpmPublishExtension.() -> Unit = {} +): NpmPublishExtension = npmPublishing.apply(config) diff --git a/src/main/kotlin/delegate/ChainedProperty.kt b/src/main/kotlin/delegate/ChainedProperty.kt index dcfc0ca0..308355e3 100644 --- a/src/main/kotlin/delegate/ChainedProperty.kt +++ b/src/main/kotlin/delegate/ChainedProperty.kt @@ -4,8 +4,8 @@ import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty internal class ChainedProperty( - private var main: ReadWriteProperty, - private val fallback: ReadWriteProperty + private var main: ReadWriteProperty, + private val fallback: ReadWriteProperty ) : ReadWriteProperty { override fun getValue(thisRef: R, property: KProperty<*>): V { return main.getValue(thisRef, property) ?: fallback.getValue(thisRef, property) diff --git a/src/main/kotlin/delegate/FallbackDelegate.kt b/src/main/kotlin/delegate/FallbackDelegate.kt index c00ee0c6..91ca5459 100644 --- a/src/main/kotlin/delegate/FallbackDelegate.kt +++ b/src/main/kotlin/delegate/FallbackDelegate.kt @@ -4,13 +4,13 @@ import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty internal class FallbackDelegate( - private val fallbackObj: F, - private val projection: F.() -> V + private val fallbackObj: F, + private val projection: F.() -> V ) : ReadWriteProperty { constructor( - fallbackObj: F, - default: V, - projection: F.() -> V? + fallbackObj: F, + default: V, + projection: F.() -> V? ) : this(fallbackObj, { fallbackObj.projection() ?: default }) private var value: V? = null diff --git a/src/main/kotlin/delegate/GradleProperty.kt b/src/main/kotlin/delegate/GradleProperty.kt index 5ba69184..a18b91bc 100644 --- a/src/main/kotlin/delegate/GradleProperty.kt +++ b/src/main/kotlin/delegate/GradleProperty.kt @@ -1,16 +1,16 @@ package dev.petuska.npm.publish.delegate -import org.gradle.api.Project -import org.gradle.api.provider.Property import kotlin.properties.ReadWriteProperty import kotlin.reflect.KClass import kotlin.reflect.KProperty +import org.gradle.api.Project +import org.gradle.api.provider.Property internal sealed class GradleProperty( - private val property: Property, - private val handleNullable: (V?, KProperty<*>) -> V = { v, p -> - v ?: throw IllegalStateException("Null value on property $p") - } + private val property: Property, + private val handleNullable: (V?, KProperty<*>) -> V = { v, p -> + v ?: throw IllegalStateException("Null value on property $p") + } ) : ReadWriteProperty { override fun getValue(thisRef: Any, property: KProperty<*>): V { return handleNullable(this.property.orNull, property) @@ -20,24 +20,10 @@ internal sealed class GradleProperty( this.property.set(value) } - class Nullable( - project: Project, - type: KClass, - default: V? = null - ) : GradleProperty( - project.objects.property(type.java).apply { - set(default) - }, - { it, _ -> it } - ) + class Nullable(project: Project, type: KClass, default: V? = null) : + GradleProperty( + project.objects.property(type.java).apply { set(default) }, { it, _ -> it }) - class NotNullable( - project: Project, - type: KClass, - default: V - ) : GradleProperty( - project.objects.property(type.java).apply { - set(default) - } - ) + class NotNullable(project: Project, type: KClass, default: V) : + GradleProperty(project.objects.property(type.java).apply { set(default) }) } diff --git a/src/main/kotlin/delegate/PropertyDelegate.kt b/src/main/kotlin/delegate/PropertyDelegate.kt index 31939790..0442ff5d 100644 --- a/src/main/kotlin/delegate/PropertyDelegate.kt +++ b/src/main/kotlin/delegate/PropertyDelegate.kt @@ -1,16 +1,16 @@ package dev.petuska.npm.publish.delegate import dev.petuska.npm.publish.util.propertyOrNull -import org.gradle.api.Project import java.util.Locale import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty +import org.gradle.api.Project internal class PropertyDelegate( - private val project: Project, - private val prefix: String?, - private val converter: (String) -> V?, - private val default: V + private val project: Project, + private val prefix: String?, + private val converter: (String) -> V?, + private val default: V ) : ReadWriteProperty { private var value: V? = null @@ -30,12 +30,13 @@ internal class PropertyDelegate( } private fun KProperty<*>.findEnv(): String? { - return System.getenv(buildPropertyKey().uppercase(Locale.getDefault()).replace("[.\\- ]".toRegex(), "_")) - ?.toString() + return System.getenv( + buildPropertyKey().uppercase(Locale.getDefault()).replace("[.\\- ]".toRegex(), "_")) + ?.toString() } private fun KProperty<*>.buildPropertyKey() = - "$PROP_BASE${ + "$PROP_BASE${ prefix?.removeSuffix(".") ?.removePrefix(".") ?.let { ".$it" } ?: "" diff --git a/src/main/kotlin/delegate/builders.kt b/src/main/kotlin/delegate/builders.kt index e259dcb6..ee171b6a 100644 --- a/src/main/kotlin/delegate/builders.kt +++ b/src/main/kotlin/delegate/builders.kt @@ -1,35 +1,37 @@ package dev.petuska.npm.publish.delegate -import org.gradle.api.Project import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty1 +import org.gradle.api.Project internal infix fun ReadWriteProperty.or(fallback: ReadWriteProperty) = - ChainedProperty(this, fallback) + ChainedProperty(this, fallback) internal fun R.fallbackDelegate(prop: KProperty1) = - FallbackDelegate(this) { prop.get(this) } + FallbackDelegate(this) { prop.get(this) } internal fun R.fallbackDelegate(prop: KProperty1, transform: P.() -> V) = - FallbackDelegate(this) { prop.get(this).transform() } + FallbackDelegate(this) { prop.get(this).transform() } internal fun R.fallbackDelegate(prop: KProperty1, default: V) = - FallbackDelegate(this, default) { prop.get(this) } + FallbackDelegate(this, default) { prop.get(this) } -internal fun R.fallbackDelegate(projection: R.() -> V) = - FallbackDelegate(this, projection) +internal fun R.fallbackDelegate(projection: R.() -> V) = FallbackDelegate(this, projection) internal fun R.fallbackDelegate(default: V, projection: R.() -> V) = - FallbackDelegate(this, default, projection) + FallbackDelegate(this, default, projection) internal fun Project.propertyDelegate(prefix: String? = null, converter: (String) -> V?) = - propertyDelegate(prefix, null, converter) + propertyDelegate(prefix, null, converter) -internal fun Project.propertyDelegate(prefix: String? = null, default: V, converter: (String) -> V?) = - PropertyDelegate(project, prefix, converter, default) +internal fun Project.propertyDelegate( + prefix: String? = null, + default: V, + converter: (String) -> V? +) = PropertyDelegate(project, prefix, converter, default) internal inline fun Project.gradleNullableProperty(default: V? = null) = - GradleProperty.Nullable(this, V::class, default) + GradleProperty.Nullable(this, V::class, default) internal inline fun Project.gradleProperty(default: V) = - GradleProperty.NotNullable(this, V::class, default) + GradleProperty.NotNullable(this, V::class, default) diff --git a/src/main/kotlin/dsl/NpmAccess.kt b/src/main/kotlin/dsl/NpmAccess.kt index 1c3dae92..0916f767 100644 --- a/src/main/kotlin/dsl/NpmAccess.kt +++ b/src/main/kotlin/dsl/NpmAccess.kt @@ -2,9 +2,7 @@ package dev.petuska.npm.publish.dsl import java.util.Locale -/** - * Enum representation of NPM repository access - */ +/** Enum representation of NPM repository access */ enum class NpmAccess { PUBLIC, RESTRICTED; diff --git a/src/main/kotlin/dsl/NpmPublication.kt b/src/main/kotlin/dsl/NpmPublication.kt index 64a2d46a..d886aefb 100644 --- a/src/main/kotlin/dsl/NpmPublication.kt +++ b/src/main/kotlin/dsl/NpmPublication.kt @@ -5,6 +5,7 @@ import dev.petuska.npm.publish.delegate.gradleNullableProperty import dev.petuska.npm.publish.delegate.or import dev.petuska.npm.publish.delegate.propertyDelegate import dev.petuska.npm.publish.util.notFalse +import java.io.File import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.file.CopySpec @@ -14,62 +15,45 @@ import org.jetbrains.kotlin.gradle.targets.js.ir.JsIrBinary import org.jetbrains.kotlin.gradle.targets.js.ir.Library import org.jetbrains.kotlin.gradle.targets.js.npm.NpmDependency import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile -import java.io.File -/** - * NPM publication (package) configuration container - */ -class NpmPublication internal constructor( - /** - * Publication name. Always in lowerCamelCase. - */ - val name: String, - private val project: Project, - extension: NpmPublishExtension, - /** - * A container for package's npm dependencies - */ - val npmDependencies: MutableList = mutableListOf() +/** NPM publication (package) configuration container */ +class NpmPublication +internal constructor( + /** Publication name. Always in lowerCamelCase. */ + val name: String, + private val project: Project, + extension: NpmPublishExtension, + /** A container for package's npm dependencies */ + val npmDependencies: MutableList = mutableListOf() ) { private val propGroup = "$PROP_PREFIX.$name" /** - * Flag to bundle kotlin-only dependencies. - * Defaults to true and only works for autogenerated kotlin publications. + * Flag to bundle kotlin-only dependencies. Defaults to true and only works for autogenerated + * kotlin publications. */ - var bundleKotlinDependencies: Boolean by project - .propertyDelegate(propGroup) { it.notFalse() } or extension.fallbackDelegate( - NpmPublishExtension::bundleKotlinDependencies - ) + var bundleKotlinDependencies: Boolean by project.propertyDelegate(propGroup) { it.notFalse() } or + extension.fallbackDelegate(NpmPublishExtension::bundleKotlinDependencies) - /** - * Flag to add bundled dependencies to npm-shrinkwrap.json. - * Defaults to true. - */ - var shrinkwrapBundledDependencies: Boolean by project - .propertyDelegate(propGroup) { it.notFalse() } or extension.fallbackDelegate( - NpmPublishExtension::shrinkwrapBundledDependencies - ) + /** Flag to add bundled dependencies to npm-shrinkwrap.json. Defaults to true. */ + var shrinkwrapBundledDependencies: Boolean by project.propertyDelegate(propGroup) { + it.notFalse() + } or extension.fallbackDelegate(NpmPublishExtension::shrinkwrapBundledDependencies) /** * Optional npm scope. If set, package name will be constructed as `@{scope}/{moduleName}`. * Defaults to [NpmPublishExtension.organization]. */ - var scope: String? by project - .propertyDelegate(propGroup) { it } or extension.fallbackDelegate(NpmPublishExtension::organization) + var scope: String? by project.propertyDelegate(propGroup) { it } or + extension.fallbackDelegate(NpmPublishExtension::organization) - /** - * NPM module name. - * Defaults to [Project.getName]. - */ - var moduleName: String by project.propertyDelegate(propGroup) { it } or project.fallbackDelegate { this.name } + /** NPM module name. Defaults to [Project.getName]. */ + var moduleName: String by project.propertyDelegate(propGroup) { it } or + project.fallbackDelegate { this.name } - /** - * NPM package version. - * Defaults to [NpmPublishExtension.version]. - */ - var version: String? by project - .propertyDelegate(propGroup) { it } or extension.fallbackDelegate(NpmPublishExtension::version) + /** NPM package version. Defaults to [NpmPublishExtension.version]. */ + var version: String? by project.propertyDelegate(propGroup) { it } or + extension.fallbackDelegate(NpmPublishExtension::version) /** * Main js entry file. Can also be set via [packageJson] DSL. @@ -84,127 +68,124 @@ class NpmPublication internal constructor( var types: String? by project.propertyDelegate(propGroup) { it } /** - * A location of the main README file. - * If set, the file will be moved to package assembly root and renamed to README.MD (regardless of the actual name). - * Defaults to [NpmPublishExtension.readme] + * A location of the main README file. If set, the file will be moved to package assembly root and + * renamed to README.MD (regardless of the actual name). Defaults to [NpmPublishExtension.readme] */ - var readme: File? by project.propertyDelegate(propGroup) { File(it) } or extension.fallbackDelegate( - NpmPublishExtension::readme - ) + var readme: File? by project.propertyDelegate(propGroup) { File(it) } or + extension.fallbackDelegate(NpmPublishExtension::readme) /** - * Base NodeJS directory to be used when building and publishing the publication. - * Defaults to 'NODE_HOME' env variable. + * Base NodeJS directory to be used when building and publishing the publication. Defaults to + * 'NODE_HOME' env variable. */ - var nodeJsDir by project - .propertyDelegate(propGroup, System.getenv("NODE_HOME")?.let(::File)) { File(it) } + var nodeJsDir by project.propertyDelegate(propGroup, System.getenv("NODE_HOME")?.let(::File)) { + File(it) + } /** - * Publication assembly directory. - * Defaults to `${project.buildDir}/publications/npm/${this.name}` + * Publication assembly directory. Defaults to `${project.buildDir}/publications/npm/${this.name}` */ var destinationDir: File by project.propertyDelegate(propGroup) { File(it) } or - project.fallbackDelegate { File("${this.buildDir}/publications/npm/${this@NpmPublication.name}") } + project.fallbackDelegate { + File("${this.buildDir}/publications/npm/${this@NpmPublication.name}") + } internal var binary by project.gradleNullableProperty() internal val kotlinDestinationDir: File? - get() = kotlinMainTask?.let { - when (it) { - is Kotlin2JsCompile -> it.outputFileProperty.orNull?.parentFile - is Copy -> it.destinationDir - else -> null - } - } + get() = + kotlinMainTask?.let { + when (it) { + is Kotlin2JsCompile -> it.outputFileProperty.orNull?.parentFile + is Copy -> it.destinationDir + else -> null + } + } internal val kotlinMainTask: Task? // Kotlin2JsCompile | Copy - get() = binary?.let { - when (it) { - is JsIrBinary -> when (it) { - is Library -> it.linkSyncTask.orNull - else -> null + get() = + binary?.let { + when (it) { + is JsIrBinary -> + when (it) { + is Library -> it.linkSyncTask.orNull + else -> null + } + else -> it.compilation.compileKotlinTask + } } - else -> it.compilation.compileKotlinTask - } - } internal val compileKotlinTask: Kotlin2JsCompile? - get() = binary?.let { - when (it) { - is JsIrBinary -> when (it) { - is Library -> it.linkTask.orNull - else -> null + get() = + binary?.let { + when (it) { + is JsIrBinary -> + when (it) { + is Library -> it.linkTask.orNull + else -> null + } + else -> it.compilation.compileKotlinTask + } } - else -> it.compilation.compileKotlinTask - } - } var fileSpecs = mutableListOf Unit>() internal var packageJsonSpecs = mutableListOf Unit>() /** - * If set, fully disregards [packageJson] DSL configuration and used the specified raw package.json file as-is. + * If set, fully disregards [packageJson] DSL configuration and used the specified raw + * package.json file as-is. */ var packageJsonFile by project.gradleNullableProperty() /** - * Similar to [packageJsonFile] except allows the options to be overridden by the [packageJson] DSL. + * Similar to [packageJsonFile] except allows the options to be overridden by the [packageJson] + * DSL. */ var packageJsonTemplateFile by project.gradleNullableProperty() /** - * If [packageJsonFile] is not set and this property is set, - * ignore any further package.json generation configs produced by DSLs + * If [packageJsonFile] is not set and this property is set, ignore any further package.json + * generation configs produced by DSLs */ var packageJson by project.gradleNullableProperty<(PackageJson.() -> Unit)>() - /** - * DSL builder to configure generated package.json file. - */ + /** DSL builder to configure generated package.json file. */ fun packageJson(config: PackageJson.() -> Unit) { packageJsonSpecs.add(config) } - /** - * DSL Builder to configure the files that compose this publication. - */ + /** DSL Builder to configure the files that compose this publication. */ fun files(config: CopySpec.(destinationDir: File) -> Unit) { fileSpecs.add(config) } - /** - * DSL builder to configure NPM dependencies for this publication. - */ + /** DSL builder to configure NPM dependencies for this publication. */ fun dependencies(config: MutableList.() -> Unit) = npmDependencies.config() - fun MutableList.dependency(name: String, version: String, scope: NpmDependency.Scope) = - NpmDependency(project, name, version, scope, false).also { - add(it) - } + fun MutableList.dependency( + name: String, + version: String, + scope: NpmDependency.Scope + ) = NpmDependency(project, name, version, scope, false).also { add(it) } - /** - * Adds a [regular](https://docs.npmjs.com/files/package.json#dependencies) npm dependency. - */ + /** Adds a [regular](https://docs.npmjs.com/files/package.json#dependencies) npm dependency. */ fun MutableList.npm(name: String, version: String) = - dependency(name, version, NpmDependency.Scope.NORMAL) + dependency(name, version, NpmDependency.Scope.NORMAL) - /** - * Adds a [dev](https://docs.npmjs.com/files/package.json#devdependencies) npm dependency. - */ + /** Adds a [dev](https://docs.npmjs.com/files/package.json#devdependencies) npm dependency. */ fun MutableList.npmDev(name: String, version: String) = - dependency(name, version, NpmDependency.Scope.DEV) + dependency(name, version, NpmDependency.Scope.DEV) /** - * Adds an [optional](https://docs.npmjs.com/files/package.json#optionaldependencies) npm dependency. + * Adds an [optional](https://docs.npmjs.com/files/package.json#optionaldependencies) npm + * dependency. */ fun MutableList.npmOptional(name: String, version: String) = - dependency(name, version, NpmDependency.Scope.OPTIONAL) + dependency(name, version, NpmDependency.Scope.OPTIONAL) - /** - * Adds a [peer](https://docs.npmjs.com/files/package.json#peerdependencies) npm dependency. - */ + /** Adds a [peer](https://docs.npmjs.com/files/package.json#peerdependencies) npm dependency. */ fun MutableList.npmPeer(name: String, version: String) = - dependency(name, version, NpmDependency.Scope.PEER) + dependency(name, version, NpmDependency.Scope.PEER) internal fun validate(alternativeNodeJsDir: File?): NpmPublication? { nodeJsDir = nodeJsDir ?: alternativeNodeJsDir diff --git a/src/main/kotlin/dsl/NpmPublishExtension.kt b/src/main/kotlin/dsl/NpmPublishExtension.kt index f64b87c3..1c1f329e 100644 --- a/src/main/kotlin/dsl/NpmPublishExtension.kt +++ b/src/main/kotlin/dsl/NpmPublishExtension.kt @@ -5,147 +5,134 @@ import dev.petuska.npm.publish.delegate.or import dev.petuska.npm.publish.delegate.propertyDelegate import dev.petuska.npm.publish.util.notFalse import groovy.lang.Closure +import java.io.File import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.Project -import java.io.File -/** - * Extension exposing npm-publish plugin configuration DSLs - */ +/** Extension exposing npm-publish plugin configuration DSLs */ open class NpmPublishExtension(private val project: Project) : NpmPublishExtensionScope { /** - * A location of the default README file. - * If set, the file will be used as a default readme for all publications that do not have one set explicitly. + * A location of the default README file. If set, the file will be used as a default readme for + * all publications that do not have one set explicitly. */ var readme: File? by project.propertyDelegate { File(it) } - /** - * Default [NpmPublication.scope] - */ + /** Default [NpmPublication.scope] */ var organization: String? by project.propertyDelegate { it } - /** - * NPM package version. - * Defaults to [Project.getVersion] or rootProject.version. - */ - var version: String? by project.propertyDelegate { it } or project.fallbackDelegate { version.toString() } + /** NPM package version. Defaults to [Project.getVersion] or rootProject.version. */ + var version: String? by project.propertyDelegate { it } or + project.fallbackDelegate { version.toString() } /** * Default [NpmRepository.access] * * Defaults to [NpmAccess.PUBLIC] */ - var access: NpmAccess by project.propertyDelegate(default = NpmAccess.PUBLIC) { NpmAccess.fromString(it) } + var access: NpmAccess by project.propertyDelegate(default = NpmAccess.PUBLIC) { + NpmAccess.fromString(it) + } /** * Sets global default flag * @see [NpmPublication.bundleKotlinDependencies] */ - var bundleKotlinDependencies: Boolean by project.propertyDelegate(default = true) { it.notFalse() } + var bundleKotlinDependencies: Boolean by project.propertyDelegate(default = true) { + it.notFalse() + } /** * Sets global default flag * @see [NpmPublication.shrinkwrapBundledDependencies] */ - var shrinkwrapBundledDependencies: Boolean by project.propertyDelegate(default = true) { it.notFalse() } + var shrinkwrapBundledDependencies: Boolean by project.propertyDelegate(default = true) { + it.notFalse() + } /** - * Specifies if a dry-run should be added to the npm command arguments. - * Dry run does all the normal run des except actual file uploading. - * Defaults to `npm.publish.dry` project property if set or `false` otherwise. + * Specifies if a dry-run should be added to the npm command arguments. Dry run does all the + * normal run des except actual file uploading. Defaults to `npm.publish.dry` project property if + * set or `false` otherwise. */ var dry: Boolean by project.propertyDelegate(default = false) { it.notFalse() } internal val repoConfigs = mutableListOf>() - internal val repositories: NpmRepositoryContainer = project.container(NpmRepository::class.java) { name -> - NpmRepository(name, project, this) - } + internal val repositories: NpmRepositoryContainer = + project.container(NpmRepository::class.java) { name -> NpmRepository(name, project, this) } private fun repositories(index: Int, config: NpmRepositoryContainer.() -> Unit) { repoConfigs.add( - index, - object : Closure(this, this) { - @Suppress("unused") - fun doCall() { - @Suppress("UNCHECKED_CAST") - (delegate as? NpmRepositoryContainer)?.let { - config(it) + index, + object : Closure(this, this) { + @Suppress("unused") + fun doCall() { + @Suppress("UNCHECKED_CAST") (delegate as? NpmRepositoryContainer)?.let { config(it) } } - } - } - ) + }) } - /** - * DSL exposing [NpmRepository] setup - */ + /** DSL exposing [NpmRepository] setup */ fun repositories(config: NpmRepositoryContainer.() -> Unit) { repositories(repoConfigs.size, config) } - /** - * DSL exposing [NpmRepository] setup for groovy - */ + /** DSL exposing [NpmRepository] setup for groovy */ fun repositories(config: Closure) { repoConfigs.add(config) } - /** - * DSL exposing [NpmRepository] creation and configuration - */ - fun NpmRepositoryContainer.repository(name: String, config: NpmRepository.() -> Unit): NpmRepository { - val pub = NpmRepository(name, this@NpmPublishExtension.project, this@NpmPublishExtension).apply(config) + /** DSL exposing [NpmRepository] creation and configuration */ + fun NpmRepositoryContainer.repository( + name: String, + config: NpmRepository.() -> Unit + ): NpmRepository { + val pub = + NpmRepository(name, this@NpmPublishExtension.project, this@NpmPublishExtension) + .apply(config) add(pub) return pub } internal val pubConfigs = mutableListOf>() - internal val publications: NpmPublicationContainer = project.container(NpmPublication::class.java) { name -> - NpmPublication(name, project, this) - } + internal val publications: NpmPublicationContainer = + project.container(NpmPublication::class.java) { name -> NpmPublication(name, project, this) } internal fun publications(index: Int, config: NpmPublicationContainer.() -> Unit) { pubConfigs.add( - index, - object : Closure(this, this) { - @Suppress("unused") - fun doCall() { - @Suppress("UNCHECKED_CAST") - (delegate as? NpmPublicationContainer)?.let { - config(it) + index, + object : Closure(this, this) { + @Suppress("unused") + fun doCall() { + @Suppress("UNCHECKED_CAST") (delegate as? NpmPublicationContainer)?.let { config(it) } } - } - } - ) + }) } - /** - * DSL exposing [NpmPublication] setup - */ + /** DSL exposing [NpmPublication] setup */ fun publications(config: NpmPublicationContainer.() -> Unit) { publications(pubConfigs.size, config) } - /** - * DSL exposing [NpmPublication] setup for groovy - */ + /** DSL exposing [NpmPublication] setup for groovy */ fun publications(config: Closure) { pubConfigs.add(config) } /** - * DSL exposing [NpmPublication] creation and configuration. - * Will look for existing publication with the same name or create a new one before applying the configuration + * DSL exposing [NpmPublication] creation and configuration. Will look for existing publication + * with the same name or create a new one before applying the configuration */ - fun NpmPublicationContainer.publication(name: String, config: NpmPublication.() -> Unit): NpmPublication { - val pub = findByName(name) - ?: NpmPublication( - name = name, - project = this@NpmPublishExtension.project, - extension = this@NpmPublishExtension - ).also { - add(it) - } + fun NpmPublicationContainer.publication( + name: String, + config: NpmPublication.() -> Unit + ): NpmPublication { + val pub = + findByName(name) + ?: NpmPublication( + name = name, + project = this@NpmPublishExtension.project, + extension = this@NpmPublishExtension) + .also { add(it) } pub.apply(config) return pub } @@ -156,4 +143,5 @@ open class NpmPublishExtension(private val project: Project) : NpmPublishExtensi } internal typealias NpmRepositoryContainer = NamedDomainObjectContainer + internal typealias NpmPublicationContainer = NamedDomainObjectContainer diff --git a/src/main/kotlin/dsl/NpmPublishExtensionScope.kt b/src/main/kotlin/dsl/NpmPublishExtensionScope.kt index 4f00c029..fa9a8047 100644 --- a/src/main/kotlin/dsl/NpmPublishExtensionScope.kt +++ b/src/main/kotlin/dsl/NpmPublishExtensionScope.kt @@ -1,6 +1,8 @@ package dev.petuska.npm.publish.dsl interface NpmPublishExtensionScope { - val PUBLIC: NpmAccess get() = NpmAccess.PUBLIC - val RESTRICTED: NpmAccess get() = NpmAccess.RESTRICTED + val PUBLIC: NpmAccess + get() = NpmAccess.PUBLIC + val RESTRICTED: NpmAccess + get() = NpmAccess.RESTRICTED } diff --git a/src/main/kotlin/dsl/NpmRepository.kt b/src/main/kotlin/dsl/NpmRepository.kt index 22663f86..54062c65 100644 --- a/src/main/kotlin/dsl/NpmRepository.kt +++ b/src/main/kotlin/dsl/NpmRepository.kt @@ -5,55 +5,38 @@ import dev.petuska.npm.publish.delegate.or import dev.petuska.npm.publish.delegate.propertyDelegate import dev.petuska.npm.publish.npmPublishing import dev.petuska.npm.publish.util.notFalse -import org.gradle.api.Project import java.net.URI +import org.gradle.api.Project -/** - * Npm repository (registry) configuration container - */ -class NpmRepository internal constructor( - /** - * Repository name. - */ - val name: String, - private val project: Project, - npmExtension: NpmPublishExtension +/** Npm repository (registry) configuration container */ +class NpmRepository +internal constructor( + /** Repository name. */ + val name: String, + private val project: Project, + npmExtension: NpmPublishExtension ) { private val propGroup = "$PROP_PREFIX.$name" - /** - * Repository access. - */ - var access: NpmAccess by project.propertyDelegate(propGroup) { - NpmAccess.fromString(it) - } or npmExtension.fallbackDelegate(NpmPublishExtension::access) + /** Repository access. */ + var access: NpmAccess by project.propertyDelegate(propGroup) { NpmAccess.fromString(it) } or + npmExtension.fallbackDelegate(NpmPublishExtension::access) - /** - * NPM Registry uri to publish packages to. Should include schema domain and path if required - */ + /** NPM Registry uri to publish packages to. Should include schema domain and path if required */ var registry: URI? by project.propertyDelegate(propGroup) { URI(it) } - /** - * Optional OTP to use when authenticating with the registry. - */ + /** Optional OTP to use when authenticating with the registry. */ var otp: String? by project.propertyDelegate(propGroup) { it } - /** - * Auth token to use when authenticating with the registry - */ + /** Auth token to use when authenticating with the registry */ var authToken: String? by project.propertyDelegate(propGroup) { it } - /** - * Overrides [NpmPublishExtension.dry] option for this repository - */ - var dry: Boolean by project.propertyDelegate(propGroup) { it.notFalse() } or npmExtension.fallbackDelegate( - NpmPublishExtension::dry - ) + /** Overrides [NpmPublishExtension.dry] option for this repository */ + var dry: Boolean by project.propertyDelegate(propGroup) { it.notFalse() } or + npmExtension.fallbackDelegate(NpmPublishExtension::dry) internal fun validate(): NpmRepository? { - return takeIf { - registry != null && (authToken != null || project.npmPublishing.dry) - } + return takeIf { registry != null && (authToken != null || project.npmPublishing.dry) } } companion object { diff --git a/src/main/kotlin/dsl/NpmShrinkwrapJson.kt b/src/main/kotlin/dsl/NpmShrinkwrapJson.kt index e7fc43cc..89168b8c 100644 --- a/src/main/kotlin/dsl/NpmShrinkwrapJson.kt +++ b/src/main/kotlin/dsl/NpmShrinkwrapJson.kt @@ -3,55 +3,37 @@ package dev.petuska.npm.publish.dsl import dev.petuska.npm.publish.util.npmFullName class NpmShrinkwrapJson( - name: String, - version: String, - scope: String? = null, - config: NpmShrinkwrapJson.() -> Unit = {} + name: String, + version: String, + scope: String? = null, + config: NpmShrinkwrapJson.() -> Unit = {} ) : JsonObject() { - /** - * [name](https://docs.npmjs.com/files/package.json#name) - */ + /** [name](https://docs.npmjs.com/files/package.json#name) */ var name: String? by this - /** - * [version](https://docs.npmjs.com/files/package.json#version) - */ + /** [version](https://docs.npmjs.com/files/package.json#version) */ var version: String? by this - /** - * Defaults to 1. - */ + /** Defaults to 1. */ var lockfileVersion: Int? by this - /** - * Defaults to true - */ + /** Defaults to true */ var requires: Boolean? by this - /** - * Shrinkwrap dependencies container. - */ + /** Shrinkwrap dependencies container. */ var dependencies: JsonObject? by this - /** - * Creates or extends shrinkwrap dependencies config. - */ + /** Creates or extends shrinkwrap dependencies config. */ fun dependencies(config: JsonObject.() -> Unit = {}) = - (dependencies ?: JsonObject()).apply(config).also { dependencies = it } + (dependencies ?: JsonObject()).apply(config).also { dependencies = it } - /** - * Creates and adds a shrinkwrap dependency. - */ - fun JsonObject.dependency( - name: String, - version: String, - bundled: Boolean - ) = ShrinkwrapDependency { - this.version = version - this.bundled = bundled - }.also { - this[name] = it - } + /** Creates and adds a shrinkwrap dependency. */ + fun JsonObject.dependency(name: String, version: String, bundled: Boolean) = + ShrinkwrapDependency { + this.version = version + this.bundled = bundled + } + .also { this[name] = it } init { this.name = npmFullName(name, scope) @@ -61,7 +43,8 @@ class NpmShrinkwrapJson( this.apply(config) } - inner class ShrinkwrapDependency(config: ShrinkwrapDependency.() -> Unit = {}) : JsonObject() { + inner class ShrinkwrapDependency(config: ShrinkwrapDependency.() -> Unit = {}) : + JsonObject() { var version: String? by this var bundled: Boolean? by this diff --git a/src/main/kotlin/dsl/PackageJson.kt b/src/main/kotlin/dsl/PackageJson.kt index f9420e7b..1135be8e 100644 --- a/src/main/kotlin/dsl/PackageJson.kt +++ b/src/main/kotlin/dsl/PackageJson.kt @@ -3,258 +3,186 @@ package dev.petuska.npm.publish.dsl import com.google.gson.GsonBuilder import com.google.gson.annotations.Expose import dev.petuska.npm.publish.util.npmFullName -import org.jetbrains.kotlin.gradle.internal.ensureParentDirsCreated import java.io.File import java.io.Serializable import kotlin.reflect.KProperty +import org.jetbrains.kotlin.gradle.internal.ensureParentDirsCreated typealias Record = MutableMap -/** - * Utility class for building Json Trees - */ -open class JsonObject(seed: Record? = null) : Record by seed ?: mutableMapOf(), Serializable { - /** - * Creates a Json Object - */ +/** Utility class for building Json Trees */ +open class JsonObject(seed: Record? = null) : + Record by seed ?: mutableMapOf(), Serializable { + /** Creates a Json Object */ fun jsonObject(block: JsonObject.() -> Unit) = JsonObject(block) - /** - * Creates a Json Array - */ + /** Creates a Json Array */ fun jsonArray(vararg elements: V) = mutableListOf(*elements) - /** - * Creates a Json Set - */ + /** Creates a Json Set */ fun jsonSet(vararg elements: V) = mutableSetOf(*elements) - /** - * Assigns a json value as `[this] = [value]` - */ + /** Assigns a json value as `[this] = [value]` */ infix fun String.to(value: T?) { this@JsonObject[this] = value } - /** - * Stringifies the current state of the object into a Json string - */ + /** Stringifies the current state of the object into a Json string */ override fun toString(): String = gson.toJson(this) companion object { - internal val gson = GsonBuilder() - .setPrettyPrinting() - .create() - - /** - * Creates a Json Object - */ - operator fun invoke(seed: Record? = null, block: JsonObject.() -> Unit) = JsonObject(seed).apply(block) - - /** - * Creates a Json Array - */ + internal val gson = GsonBuilder().setPrettyPrinting().create() + + /** Creates a Json Object */ + operator fun invoke(seed: Record? = null, block: JsonObject.() -> Unit) = + JsonObject(seed).apply(block) + + /** Creates a Json Array */ operator fun invoke(vararg elements: V) = mutableListOf(*elements) } } -/** - * Writes the current state of the object into a file as json string - */ -fun > T.writeTo(packageJsonFile: File) = this.also { - packageJsonFile.ensureParentDirsCreated() - packageJsonFile.writer().use { - JsonObject.gson.toJson(this as MutableMap<*, *>, it) - } -} +/** Writes the current state of the object into a file as json string */ +fun > T.writeTo(packageJsonFile: File) = + this.also { + packageJsonFile.ensureParentDirsCreated() + packageJsonFile.writer().use { JsonObject.gson.toJson(this as MutableMap<*, *>, it) } + } operator fun JsonObject.getValue(thisRef: JsonObject, property: KProperty<*>): R? { - @Suppress("UNCHECKED_CAST") - return thisRef[property.name] as? R + @Suppress("UNCHECKED_CAST") return thisRef[property.name] as? R } -operator fun JsonObject.setValue(thisRef: JsonObject, property: KProperty<*>, value: R?) { +operator fun JsonObject.setValue( + thisRef: JsonObject, + property: KProperty<*>, + value: R? +) { thisRef[property.name] = value } /** - * A class representing [package.json](https://docs.npmjs.com/files/package.json) schema. - * Custom fields can be added as regular map entries. + * A class representing [package.json](https://docs.npmjs.com/files/package.json) schema. Custom + * fields can be added as regular map entries. */ class PackageJson() : JsonObject() { - constructor(name: String, version: String?, scope: String? = null, config: PackageJson.() -> Unit = {}) : this() { + constructor( + name: String, + version: String?, + scope: String? = null, + config: PackageJson.() -> Unit = {} + ) : this() { this.name = npmFullName(name, scope) this.version = version this.apply(config) } - /** - * [name](https://docs.npmjs.com/files/package.json#name) - */ + /** [name](https://docs.npmjs.com/files/package.json#name) */ var name: String? by this - /** - * [version](https://docs.npmjs.com/files/package.json#version) - */ + /** [version](https://docs.npmjs.com/files/package.json#version) */ var version: String? by this - /** - * [description](https://docs.npmjs.com/files/package.json#description-1) - */ + /** [description](https://docs.npmjs.com/files/package.json#description-1) */ var description: String? by this - /** - * [keywords](https://docs.npmjs.com/files/package.json#keywords) - */ + /** [keywords](https://docs.npmjs.com/files/package.json#keywords) */ var keywords: MutableList? by this - /** - * [homepage](https://docs.npmjs.com/files/package.json#homepage) - */ + /** [homepage](https://docs.npmjs.com/files/package.json#homepage) */ var homepage: String? by this - /** - * [bugs](https://docs.npmjs.com/files/package.json#bugs) - */ + /** [bugs](https://docs.npmjs.com/files/package.json#bugs) */ var bugs: Record? by this - /** - * [bugs](https://docs.npmjs.com/files/package.json#bugs) - */ + /** [bugs](https://docs.npmjs.com/files/package.json#bugs) */ fun bugs(config: Bugs.() -> Unit = {}) = Bugs(bugs, config).also { bugs = it } - /** - * [license](https://docs.npmjs.com/files/package.json#license) - */ + /** [license](https://docs.npmjs.com/files/package.json#license) */ var license: String? by this - /** - * [author](https://docs.npmjs.com/files/package.json#people-fields-author-contributors) - */ + /** [author](https://docs.npmjs.com/files/package.json#people-fields-author-contributors) */ var author: Record? by this - /** - * [author](https://docs.npmjs.com/files/package.json#people-fields-author-contributors) - */ + /** [author](https://docs.npmjs.com/files/package.json#people-fields-author-contributors) */ fun author(config: Person.() -> Unit = {}) = Person(author, config).also { author = it } - /** - * [contributors](https://docs.npmjs.com/files/package.json#people-fields-author-contributors) - */ + /** [contributors](https://docs.npmjs.com/files/package.json#people-fields-author-contributors) */ var contributors: MutableList? by this - /** - * [contributors](https://docs.npmjs.com/files/package.json#people-fields-author-contributors) - */ - fun MutableList.contributor(config: Person.() -> Unit = {}) = Person(config = config).also { add(it) } + /** [contributors](https://docs.npmjs.com/files/package.json#people-fields-author-contributors) */ + fun MutableList.contributor(config: Person.() -> Unit = {}) = + Person(config = config).also { add(it) } - /** - * [files](https://docs.npmjs.com/files/package.json#files) - */ + /** [files](https://docs.npmjs.com/files/package.json#files) */ var files: MutableList? by this - /** - * [main](https://docs.npmjs.com/files/package.json#main) - */ + /** [main](https://docs.npmjs.com/files/package.json#main) */ var main: String? by this - /** - * [types](https://www.typescriptlang.org/docs/handbook/declaration-files/publishing.html) - */ + /** [types](https://www.typescriptlang.org/docs/handbook/declaration-files/publishing.html) */ var types: String? by this - /** - * [browser](https://docs.npmjs.com/files/package.json#browser) - */ + /** [browser](https://docs.npmjs.com/files/package.json#browser) */ var browser: String? by this - /** - * [bin](https://docs.npmjs.com/files/package.json#bin) - */ + /** [bin](https://docs.npmjs.com/files/package.json#bin) */ var bin: Record? by this - /** - * [man](https://docs.npmjs.com/files/package.json#man) - */ + /** [man](https://docs.npmjs.com/files/package.json#man) */ var man: Record? by this - /** - * [directories](https://docs.npmjs.com/files/package.json#directories) - */ + /** [directories](https://docs.npmjs.com/files/package.json#directories) */ var directories: Record? by this - /** - * [directories](https://docs.npmjs.com/files/package.json#directories) - */ - fun directories(config: Directories.() -> Unit = {}) = Directories(directories, config).also { directories = it } + /** [directories](https://docs.npmjs.com/files/package.json#directories) */ + fun directories(config: Directories.() -> Unit = {}) = + Directories(directories, config).also { directories = it } - /** - * [repository](https://docs.npmjs.com/files/package.json#repository) - */ + /** [repository](https://docs.npmjs.com/files/package.json#repository) */ var repository: Record? by this - /** - * [repository](https://docs.npmjs.com/files/package.json#repository) - */ - fun repository(config: Repository.() -> Unit = {}) = Repository(repository, config).also { repository = it } + /** [repository](https://docs.npmjs.com/files/package.json#repository) */ + fun repository(config: Repository.() -> Unit = {}) = + Repository(repository, config).also { repository = it } - /** - * [scripts](https://docs.npmjs.com/files/package.json#scripts) - */ + /** [scripts](https://docs.npmjs.com/files/package.json#scripts) */ var scripts: Record? by this - /** - * [config](https://docs.npmjs.com/files/package.json#config) - */ + /** [config](https://docs.npmjs.com/files/package.json#config) */ var config: Record? by this - /** - * [dependencies](https://docs.npmjs.com/files/package.json#dependencies) - */ + /** [dependencies](https://docs.npmjs.com/files/package.json#dependencies) */ var dependencies: Record? by this - /** - * [dependencies](https://docs.npmjs.com/files/package.json#dependencies) - */ + /** [dependencies](https://docs.npmjs.com/files/package.json#dependencies) */ fun dependencies(config: JsonObject.() -> Unit = {}) = - JsonObject(dependencies, config).also { dependencies = it } + JsonObject(dependencies, config).also { dependencies = it } - /** - * [devDependencies](https://docs.npmjs.com/files/package.json#devdependencies) - */ + /** [devDependencies](https://docs.npmjs.com/files/package.json#devdependencies) */ var devDependencies: Record? by this - /** - * [devDependencies](https://docs.npmjs.com/files/package.json#devdependencies) - */ + /** [devDependencies](https://docs.npmjs.com/files/package.json#devdependencies) */ fun devDependencies(config: JsonObject.() -> Unit = {}) = - JsonObject(devDependencies, config).also { devDependencies = it } + JsonObject(devDependencies, config).also { devDependencies = it } - /** - * [peerDependencies](https://docs.npmjs.com/files/package.json#peerdependencies) - */ + /** [peerDependencies](https://docs.npmjs.com/files/package.json#peerdependencies) */ var peerDependencies: Record? by this - /** - * [peerDependencies](https://docs.npmjs.com/files/package.json#peerdependencies) - */ + /** [peerDependencies](https://docs.npmjs.com/files/package.json#peerdependencies) */ fun peerDependencies(config: JsonObject.() -> Unit = {}) = - JsonObject(peerDependencies, config).also { peerDependencies = it } + JsonObject(peerDependencies, config).also { peerDependencies = it } - /** - * [optionalDependencies](https://docs.npmjs.com/files/package.json#optionaldependencies) - */ + /** [optionalDependencies](https://docs.npmjs.com/files/package.json#optionaldependencies) */ var optionalDependencies: Record? by this - /** - * [optionalDependencies](https://docs.npmjs.com/files/package.json#optionaldependencies) - */ + /** [optionalDependencies](https://docs.npmjs.com/files/package.json#optionaldependencies) */ fun optionalDependencies(config: JsonObject.() -> Unit = {}) = - JsonObject(optionalDependencies, config).also { optionalDependencies = it } + JsonObject(optionalDependencies, config).also { optionalDependencies = it } /** - * [bundledDependencies](https://docs.npmjs.com/files/package.json#bundleddependencies) - * Top priority if set, disregards all other configurations + * [bundledDependencies](https://docs.npmjs.com/files/package.json#bundleddependencies) Top + * priority if set, disregards all other configurations */ var bundledDependencies: MutableSet? by this @@ -262,8 +190,7 @@ class PackageJson() : JsonObject() { internal var bundledDependenciesSpec: BundledDependenciesSpec? = null /** - * Appends bundled dependencies configuration. - * Ignored if [bundledDependencies] property is set + * Appends bundled dependencies configuration. Ignored if [bundledDependencies] property is set * For auto-generated publications, kotlin-test* dependencies are excluded by default * * @param mustBundle a list of dependencies to bundle regardless of the config @@ -272,42 +199,28 @@ class PackageJson() : JsonObject() { fun bundledDependencies(vararg mustBundle: String, config: BundledDependenciesSpec.() -> Unit) { val target = bundledDependenciesSpec ?: BundledDependenciesSpec() target.apply(config) - target.apply { - mustBundle.forEach { +it } - } + target.apply { mustBundle.forEach { +it } } bundledDependenciesSpec = target } - /** - * [engines](https://docs.npmjs.com/files/package.json#engines) - */ + /** [engines](https://docs.npmjs.com/files/package.json#engines) */ var engines: Record? by this - /** - * [os](https://docs.npmjs.com/files/package.json#os) - */ + /** [os](https://docs.npmjs.com/files/package.json#os) */ var os: MutableList? by this - /** - * [cpu](https://docs.npmjs.com/files/package.json#cpu) - */ + /** [cpu](https://docs.npmjs.com/files/package.json#cpu) */ var cpu: MutableList? by this - /** - * [private](https://docs.npmjs.com/files/package.json#private) - */ + /** [private](https://docs.npmjs.com/files/package.json#private) */ var private: Boolean? by this - /** - * [publishConfig](https://docs.npmjs.com/files/package.json#publishconfig) - */ + /** [publishConfig](https://docs.npmjs.com/files/package.json#publishconfig) */ var publishConfig: Record? by this - /** - * [publishConfig](https://docs.npmjs.com/files/package.json#publishconfig) - */ + /** [publishConfig](https://docs.npmjs.com/files/package.json#publishconfig) */ fun publishConfig(config: PublishConfig.() -> Unit = {}) = - PublishConfig(publishConfig, config).also { publishConfig = it } + PublishConfig(publishConfig, config).also { publishConfig = it } inner class BundledDependenciesSpec(config: (BundledDependenciesSpec.() -> Unit)? = null) { private val specs: MutableList<(MutableSet) -> Unit> = mutableListOf() @@ -316,46 +229,34 @@ class PackageJson() : JsonObject() { config?.invoke(this) } - /** - * Includes a given dependency - */ + /** Includes a given dependency */ operator fun String.unaryPlus() { specs.add { it.add(this) } } - /** - * Excludes a given dependency - */ + /** Excludes a given dependency */ operator fun String.unaryMinus() { specs.add { it.remove(this) } } - /** - * Includes a given dependencies by regex. Should not be used with regex exclusion. - */ + /** Includes a given dependencies by regex. Should not be used with regex exclusion. */ operator fun Regex.unaryPlus() { specs.add { it.removeIf { dep -> !matches(dep) } } } - /** - * Excludes given dependencies by regex. Should not be used with regex inclusion. - */ + /** Excludes given dependencies by regex. Should not be used with regex inclusion. */ operator fun Regex.unaryMinus() { specs.add { it.removeIf { dep -> matches(dep) } } } - /** - * Applies this spec to the given dependencies set. - */ - fun applyTo(set: MutableSet): MutableSet = set.apply { - specs.forEach { it(this) } - } + /** Applies this spec to the given dependencies set. */ + fun applyTo(set: MutableSet): MutableSet = + set.apply { specs.forEach { it(this) } } } - /** - * [bugs](https://docs.npmjs.com/files/package.json#bugs) - */ - inner class Bugs(seed: Record? = null, config: Bugs.() -> Unit = {}) : JsonObject(seed) { + /** [bugs](https://docs.npmjs.com/files/package.json#bugs) */ + inner class Bugs(seed: Record? = null, config: Bugs.() -> Unit = {}) : + JsonObject(seed) { var url: String? by this var email: String? by this @@ -364,10 +265,9 @@ class PackageJson() : JsonObject() { } } - /** - * [people field](https://docs.npmjs.com/files/package.json#people-fields-author-contributors) - */ - inner class Person(seed: Record? = null, config: Person.() -> Unit = {}) : JsonObject(seed) { + /** [people field](https://docs.npmjs.com/files/package.json#people-fields-author-contributors) */ + inner class Person(seed: Record? = null, config: Person.() -> Unit = {}) : + JsonObject(seed) { var name: String? by this var email: String? by this var url: String? by this @@ -377,38 +277,25 @@ class PackageJson() : JsonObject() { } } - /** - * [directories](https://docs.npmjs.com/files/package.json#directories) - */ - inner class Directories(seed: Record? = null, config: Directories.() -> Unit = {}) : JsonObject(seed) { - /** - * [lib](https://docs.npmjs.com/files/package.json#directorieslib) - */ + /** [directories](https://docs.npmjs.com/files/package.json#directories) */ + inner class Directories(seed: Record? = null, config: Directories.() -> Unit = {}) : + JsonObject(seed) { + /** [lib](https://docs.npmjs.com/files/package.json#directorieslib) */ var lib: String? by this - /** - * [bin](https://docs.npmjs.com/files/package.json#directoriesbin) - */ + /** [bin](https://docs.npmjs.com/files/package.json#directoriesbin) */ var bin: String? by this - /** - * [man](https://docs.npmjs.com/files/package.json#directoriesman) - */ + /** [man](https://docs.npmjs.com/files/package.json#directoriesman) */ var man: String? by this - /** - * [doc](https://docs.npmjs.com/files/package.json#directoriesdoc) - */ + /** [doc](https://docs.npmjs.com/files/package.json#directoriesdoc) */ var doc: String? by this - /** - * [example](https://docs.npmjs.com/files/package.json#directoriesexample) - */ + /** [example](https://docs.npmjs.com/files/package.json#directoriesexample) */ var example: String? by this - /** - * [test](https://docs.npmjs.com/files/package.json#directoriestest) - */ + /** [test](https://docs.npmjs.com/files/package.json#directoriestest) */ var test: String? by this init { @@ -416,10 +303,9 @@ class PackageJson() : JsonObject() { } } - /** - * [repository](https://docs.npmjs.com/files/package.json#repository) - */ - inner class Repository(seed: Record? = null, config: Repository.() -> Unit = {}) : JsonObject(seed) { + /** [repository](https://docs.npmjs.com/files/package.json#repository) */ + inner class Repository(seed: Record? = null, config: Repository.() -> Unit = {}) : + JsonObject(seed) { var type: String? by this var url: String? by this var directory: String? by this @@ -429,10 +315,9 @@ class PackageJson() : JsonObject() { } } - /** - * [publish config](https://docs.npmjs.com/files/package.json#publishconfig) - */ - inner class PublishConfig(seed: Record? = null, config: PublishConfig.() -> Unit = {}) : JsonObject(seed) { + /** [publish config](https://docs.npmjs.com/files/package.json#publishconfig) */ + inner class PublishConfig(seed: Record? = null, config: PublishConfig.() -> Unit = {}) : + JsonObject(seed) { var registry: String? by this var access: String? by this var tag: String? by this diff --git a/src/main/kotlin/task/NpmExecTask.kt b/src/main/kotlin/task/NpmExecTask.kt index 2f506483..ba5b4556 100644 --- a/src/main/kotlin/task/NpmExecTask.kt +++ b/src/main/kotlin/task/NpmExecTask.kt @@ -1,75 +1,63 @@ package dev.petuska.npm.publish.task import dev.petuska.npm.publish.delegate.gradleNullableProperty +import java.io.File +import javax.inject.Inject import org.apache.tools.ant.taskdefs.condition.Os import org.gradle.api.DefaultTask import org.gradle.api.tasks.InputDirectory import org.gradle.api.tasks.InputFile import org.gradle.process.ExecSpec -import java.io.File -import javax.inject.Inject /** * Basic task for executing various npm commands. Provides access to npm and node executables. * * @constructor base NodeJS directory to extract executables from. */ -abstract class NpmExecTask @Inject constructor( - nodeJsDir: File? -) : DefaultTask() { +abstract class NpmExecTask @Inject constructor(nodeJsDir: File?) : DefaultTask() { constructor() : this(null) /** - * Base NodeJS directory used to extract other node executables from. Defaults to 'NODE_HOME' env variable. + * Base NodeJS directory used to extract other node executables from. Defaults to 'NODE_HOME' env + * variable. */ @get:InputDirectory - open val nodeJsDir by project.gradleNullableProperty(nodeJsDir ?: System.getenv("NODE_HOME")?.let(::File)) + open val nodeJsDir by project.gradleNullableProperty( + nodeJsDir ?: System.getenv("NODE_HOME")?.let(::File)) - /** - * Main Node executable. Allows for executing any js script from your builds. - */ + /** Main Node executable. Allows for executing any js script from your builds. */ @get:InputFile val node by lazy { // For some unknown reason, the node distribution's structure is different on Windows and UNIX. if (Os.isFamily(Os.FAMILY_WINDOWS)) { - this.nodeJsDir!! - .resolve("node.exe") + this.nodeJsDir!!.resolve("node.exe") } else { - this.nodeJsDir!! - .resolve("bin") - .resolve("node") + this.nodeJsDir!!.resolve("bin").resolve("node") } } - /** - * NPM CLI executable. Use as argument to node executable as this is a JS script. - */ + /** NPM CLI executable. Use as argument to node executable as this is a JS script. */ @get:InputFile val npm by lazy { if (Os.isFamily(Os.FAMILY_WINDOWS)) { - this.nodeJsDir!! - .resolve("node_modules") - .resolve("npm") - .resolve("bin") - .resolve("npm-cli.js") + this.nodeJsDir!!.resolve("node_modules").resolve("npm").resolve("bin").resolve("npm-cli.js") } else { this.nodeJsDir!! - .resolve("lib") - .resolve("node_modules") - .resolve("npm") - .resolve("bin") - .resolve("npm-cli.js") + .resolve("lib") + .resolve("node_modules") + .resolve("npm") + .resolve("bin") + .resolve("npm-cli.js") } } - fun nodeExec(args: Collection, config: ExecSpec.() -> Unit = {}) = project.exec { - val cmd = listOfNotNull( - node, - *args.toTypedArray() - ).toTypedArray() - it.commandLine(*cmd) - it.config() - } + fun nodeExec(args: Collection, config: ExecSpec.() -> Unit = {}) = + project.exec { + val cmd = listOfNotNull(node, *args.toTypedArray()).toTypedArray() + it.commandLine(*cmd) + it.config() + } - fun npmExec(args: Collection, config: ExecSpec.() -> Unit = {}) = nodeExec(listOf(npm) + args, config) + fun npmExec(args: Collection, config: ExecSpec.() -> Unit = {}) = + nodeExec(listOf(npm) + args, config) } diff --git a/src/main/kotlin/task/NpmPackTask.kt b/src/main/kotlin/task/NpmPackTask.kt index 6a32727a..29e67ee4 100644 --- a/src/main/kotlin/task/NpmPackTask.kt +++ b/src/main/kotlin/task/NpmPackTask.kt @@ -4,40 +4,33 @@ import dev.petuska.npm.publish.delegate.fallbackDelegate import dev.petuska.npm.publish.dsl.NpmPublication import dev.petuska.npm.publish.dsl.NpmPublishExtension import dev.petuska.npm.publish.npmPublishing -import org.gradle.api.tasks.Internal -import org.gradle.api.tasks.TaskAction import java.io.File import javax.inject.Inject +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.TaskAction /** * A publishing task that publishes a given publication to a given repository. * * @constructor A publication and repository configurations. */ -open class NpmPackTask @Inject constructor( - publication: NpmPublication -) : NpmExecTask() { +open class NpmPackTask @Inject constructor(publication: NpmPublication) : NpmExecTask() { override var nodeJsDir by publication.fallbackDelegate(NpmPublication::nodeJsDir) /** - * The directory where the assembled and ready-to-publish package is. - * Defaults to [NpmPublication.destinationDir] + * The directory where the assembled and ready-to-publish package is. Defaults to + * [NpmPublication.destinationDir] */ - @get:Internal - var packageDir: File by publication.fallbackDelegate(NpmPublication::destinationDir) + @get:Internal var packageDir: File by publication.fallbackDelegate(NpmPublication::destinationDir) - /** - * Output directory to pack the publication to. - * Defaults to [NpmPackTask.packageDir] parent - */ + /** Output directory to pack the publication to. Defaults to [NpmPackTask.packageDir] parent */ @get:Internal - var destinationDir: File by fallbackDelegate(NpmPackTask::packageDir) { parentFile } + var destinationDir: File by fallbackDelegate(NpmPackTask::packageDir) { + parentFile + } - /** - * See Also: [dev.petuska.npm.publish.dsl.NpmPublishExtension.dry] - */ - @get:Internal - var dry by project.npmPublishing.fallbackDelegate(NpmPublishExtension::dry) + /** See Also: [dev.petuska.npm.publish.dsl.NpmPublishExtension.dry] */ + @get:Internal var dry by project.npmPublishing.fallbackDelegate(NpmPublishExtension::dry) init { group = "build" @@ -46,13 +39,7 @@ open class NpmPackTask @Inject constructor( @TaskAction private fun doAction() { - npmExec( - listOf( - "pack", - packageDir, - if (dry) "--dry-run" else null - ) - ) { + npmExec(listOf("pack", packageDir, if (dry) "--dry-run" else null)) { workingDir = destinationDir } } diff --git a/src/main/kotlin/task/NpmPackageAssembleTask.kt b/src/main/kotlin/task/NpmPackageAssembleTask.kt index ed97960c..694382ca 100644 --- a/src/main/kotlin/task/NpmPackageAssembleTask.kt +++ b/src/main/kotlin/task/NpmPackageAssembleTask.kt @@ -9,6 +9,8 @@ import dev.petuska.npm.publish.dsl.NpmShrinkwrapJson import dev.petuska.npm.publish.dsl.PackageJson import dev.petuska.npm.publish.dsl.writeTo import dev.petuska.npm.publish.npmPublishing +import java.io.File +import javax.inject.Inject import org.gradle.api.DefaultTask import org.gradle.api.file.CopySpec import org.gradle.api.file.DuplicatesStrategy @@ -16,35 +18,29 @@ import org.gradle.api.tasks.Internal import org.gradle.api.tasks.TaskAction import org.jetbrains.kotlin.gradle.targets.js.ir.JsIrBinary import org.jetbrains.kotlin.gradle.targets.js.npm.NpmDependency -import java.io.File -import javax.inject.Inject /** * A task to assemble all required files for a given [NpmPublication]. * * @constructor publication to assemble */ -open class NpmPackageAssembleTask @Inject constructor( - publication: NpmPublication? -) : DefaultTask() { +open class NpmPackageAssembleTask @Inject constructor(publication: NpmPublication?) : + DefaultTask() { constructor() : this(null) /** - * Main configuration of the publication to assemble. - * If no publication is passed to a constructor, a default one will be constructed with basic project properties. + * Main configuration of the publication to assemble. If no publication is passed to a + * constructor, a default one will be constructed with basic project properties. */ @get:Internal - var publication by project.gradleProperty(publication ?: NpmPublication(name, project, project.npmPublishing)) + var publication by project.gradleProperty( + publication ?: NpmPublication(name, project, project.npmPublishing)) - /** - * Output directory to assemble the publication to. - */ + /** Output directory to assemble the publication to. */ @get:Internal val destinationDir by this.publication.fallbackDelegate(NpmPublication::destinationDir) - /** - * Gson instance to be reused across multiple functions of the task. - */ + /** Gson instance to be reused across multiple functions of the task. */ private val gson = Gson() init { @@ -52,9 +48,7 @@ open class NpmPackageAssembleTask @Inject constructor( description = "Assembles ${this.publication.name} NPM publication." } - /** - * Configuration DSL allowing to modify a given publication config. - */ + /** Configuration DSL allowing to modify a given publication config. */ fun publication(config: NpmPublication.() -> Unit) { publication.config() } @@ -72,190 +66,216 @@ open class NpmPackageAssembleTask @Inject constructor( packageJsonFile?.let { packageJsonFile -> cp.from("$packageJsonFile") cp.rename(packageJsonFile.name, "package.json") - } ?: resolvePackageJson(kotlinDependencies) + } + ?: resolvePackageJson(kotlinDependencies) } } } - private fun CopySpec.resolveFiles() = with(publication) { - readme?.let { rdm -> - fileSpecs.add(0) { - from(rdm) - rename(rdm.name, "README.md") + private fun CopySpec.resolveFiles() = + with(publication) { + readme?.let { rdm -> + fileSpecs.add(0) { + from(rdm) + rename(rdm.name, "README.md") + } + } + fileSpecs.forEach { it(destinationDir) } } - } - fileSpecs.forEach { - it(destinationDir) - } - } - - private fun File.resolveNpmDependencies(): Map = try { - val rawPJS = gson.fromJson(resolve("package.json").readText(), PackageJson::class.java) - rawPJS.dependencies?.mapNotNull { (key, value) -> - if (value != null && !value.startsWith("file:")) { - key to value - } else null - }?.toMap() - } catch (e: Exception) { - project.logger.warn("Error resolving transitive npm dependencies from compilation dependencies.", e) - null - } ?: mapOf() - - private data class KotlinDependency(val name: String, val version: String, val npmDependencies: Map) - private fun File.copyKotlinDependencies(): Map? = try { - val pjsFile = this@copyKotlinDependencies.resolve("../package.json").takeIf { it.exists() } - val rawPJS = gson.fromJson(pjsFile!!.readText(), PackageJson::class.java) - val kotlinDeps = rawPJS.dependencies - ?.filter { it.value?.run { startsWith("file:") && contains("packages_imported") } ?: false } - ?.map { (key, value) -> key to File(value!!.removePrefix("file:")) } + private fun File.resolveNpmDependencies(): Map = + try { + val rawPJS = gson.fromJson(resolve("package.json").readText(), PackageJson::class.java) + rawPJS + .dependencies + ?.mapNotNull { (key, value) -> + if (value != null && !value.startsWith("file:")) { + key to value + } else null + } + ?.toMap() + } catch (e: Exception) { + project.logger.warn( + "Error resolving transitive npm dependencies from compilation dependencies.", e) + null + } ?: mapOf() - val targetNodeModulesDir = this@NpmPackageAssembleTask.destinationDir.resolve("node_modules").apply { - mkdirs() - } + private data class KotlinDependency( + val name: String, + val version: String, + val npmDependencies: Map + ) - kotlinDeps?.forEach { (name, dir) -> - project.copy { cp -> - cp.into(targetNodeModulesDir.resolve(name)) - cp.from(dir) - } - } - kotlinDeps?.map { (n, v) -> n to KotlinDependency(n, v.name, v.resolveNpmDependencies()) }?.toMap() - } catch (e: Exception) { - project.logger.warn("Error preparing node_modules from compilation dependencies.", e) - null - } + private fun File.copyKotlinDependencies(): Map? = + try { + val pjsFile = this@copyKotlinDependencies.resolve("../package.json").takeIf { it.exists() } + val rawPJS = gson.fromJson(pjsFile!!.readText(), PackageJson::class.java) + val kotlinDeps = + rawPJS.dependencies + ?.filter { + it.value?.run { startsWith("file:") && contains("packages_imported") } ?: false + } + ?.map { (key, value) -> key to File(value!!.removePrefix("file:")) } - private fun resolvePackageJson(kotlinDependencies: Map?) = with(publication) { - var npmVersion = this@with.version - if (npmVersion?.endsWith("-SNAPSHOT") == true) { - npmVersion = npmVersion.replace("SNAPSHOT", "${System.currentTimeMillis()}") - } - val packageJson = PackageJson(moduleName, npmVersion, scope) { - if (packageJson != null) { - packageJson!!.invoke(this@PackageJson) - } else { - main = this@with.main - types = this@with.types ?: resolveTypes() + val targetNodeModulesDir = + this@NpmPackageAssembleTask.destinationDir.resolve("node_modules").apply { mkdirs() } - if (binary is JsIrBinary) { - kotlinDependencies?.flatMap { - it.value.npmDependencies.map { (name, version) -> - NpmDependency( - project, - name, - version - ) - } - }?.let { - val deps = npmDependencies.toSet() + it - npmDependencies.clear() - npmDependencies.addAll(deps.distinctBy(NpmDependency::key)) + kotlinDeps?.forEach { (name, dir) -> + project.copy { cp -> + cp.into(targetNodeModulesDir.resolve(name)) + cp.from(dir) } } - val groupedDependencies = resolveDependencies(kotlinDependencies) - groupedDependencies.forEach { (scope, deps) -> - val initialDeps: JsonObject = when (scope) { - NpmDependency.Scope.NORMAL -> JsonObject().also { dependencies = it } - NpmDependency.Scope.DEV -> JsonObject().also { devDependencies = it } - NpmDependency.Scope.OPTIONAL -> JsonObject().also { optionalDependencies = it } - NpmDependency.Scope.PEER -> JsonObject().also { peerDependencies = it } - } + kotlinDeps + ?.map { (n, v) -> n to KotlinDependency(n, v.name, v.resolveNpmDependencies()) } + ?.toMap() + } catch (e: Exception) { + project.logger.warn("Error preparing node_modules from compilation dependencies.", e) + null + } - with(initialDeps) { - deps.forEach { dep -> - dep.name to dep.version - } - } + private fun resolvePackageJson(kotlinDependencies: Map?) = + with(publication) { + var npmVersion = this@with.version + if (npmVersion?.endsWith("-SNAPSHOT") == true) { + npmVersion = npmVersion.replace("SNAPSHOT", "${System.currentTimeMillis()}") } + val packageJson = + PackageJson(moduleName, npmVersion, scope) { + if (packageJson != null) { + packageJson!!.invoke(this@PackageJson) + } else { + main = this@with.main + types = this@with.types ?: resolveTypes() - packageJsonSpecs.forEach { - it() - } - bundledDependencies = resolveBundledDependencies(this, kotlinDependencies) + if (binary is JsIrBinary) { + kotlinDependencies + ?.flatMap { + it.value.npmDependencies.map { (name, version) -> + NpmDependency(project, name, version) + } + } + ?.let { + val deps = npmDependencies.toSet() + it + npmDependencies.clear() + npmDependencies.addAll(deps.distinctBy(NpmDependency::key)) + } + } + val groupedDependencies = resolveDependencies(kotlinDependencies) + groupedDependencies.forEach { (scope, deps) -> + val initialDeps: JsonObject = + when (scope) { + NpmDependency.Scope.NORMAL -> + JsonObject().also { dependencies = it } + NpmDependency.Scope.DEV -> + JsonObject().also { devDependencies = it } + NpmDependency.Scope.OPTIONAL -> + JsonObject().also { optionalDependencies = it } + NpmDependency.Scope.PEER -> + JsonObject().also { peerDependencies = it } + } - // Apply overrides from provided template - publication.packageJsonTemplateFile?.let { - val template = gson.fromJson(it.readText(), PackageJson::class.java) - putAll(template) - } + with(initialDeps) { deps.forEach { dep -> dep.name to dep.version } } + } - packageJsonSpecs.forEach { - it() - } - } - }.writeTo(File(destinationDir, "package.json")) + packageJsonSpecs.forEach { it() } + bundledDependencies = resolveBundledDependencies(this, kotlinDependencies) - if (publication.shrinkwrapBundledDependencies) { - packageJson.generateNpmShrinkwrapJson()?.writeTo(File(destinationDir, "npm-shrinkwrap.json")) - } - } + // Apply overrides from provided template + publication.packageJsonTemplateFile?.let { + val template = gson.fromJson(it.readText(), PackageJson::class.java) + putAll(template) + } - private fun NpmPublication.resolveDependencies(kotlinDependencies: Map?) = - npmDependencies.filter { - binary !is JsIrBinary || kotlinDependencies?.keys?.let { keys -> it.name !in keys } ?: true - }.groupBy { dep -> dep.scope } - .let { deps -> - val dev = deps[NpmDependency.Scope.DEV] - val peer = deps[NpmDependency.Scope.PEER] - val optional = deps[NpmDependency.Scope.OPTIONAL] - fun NpmDependency.id() = "$scope:$name:$version" - fun List?.includes(other: NpmDependency) = this?.any { it.id() == other.id() } ?: false + packageJsonSpecs.forEach { it() } + } + } + .writeTo(File(destinationDir, "package.json")) - deps.entries.map { (scope, deps) -> - scope to deps.filter { dep -> - when (scope) { - NpmDependency.Scope.NORMAL -> !optional.includes(dep) && !peer.includes(dep) && !dev.includes(dep) - NpmDependency.Scope.DEV -> !optional.includes(dep) && !peer.includes(dep) - NpmDependency.Scope.PEER -> !optional.includes(dep) - NpmDependency.Scope.OPTIONAL -> true - } - } + if (publication.shrinkwrapBundledDependencies) { + packageJson + .generateNpmShrinkwrapJson() + ?.writeTo(File(destinationDir, "npm-shrinkwrap.json")) } } - private fun NpmPublication.resolveTypes() = compileKotlinTask?.outputFileProperty?.orNull?.let { - kotlinDestinationDir?.resolve("${it.nameWithoutExtension}.d.ts")?.let { dtsFile -> - if (dtsFile.exists()) { - "${dtsFile.relativeTo(dtsFile.parentFile)}" - } else null - } - } + private fun NpmPublication.resolveDependencies( + kotlinDependencies: Map? + ) = + npmDependencies + .filter { + binary !is JsIrBinary || + kotlinDependencies?.keys?.let { keys -> it.name !in keys } ?: true + } + .groupBy { dep -> dep.scope } + .let { deps -> + val dev = deps[NpmDependency.Scope.DEV] + val peer = deps[NpmDependency.Scope.PEER] + val optional = deps[NpmDependency.Scope.OPTIONAL] + fun NpmDependency.id() = "$scope:$name:$version" + fun List?.includes(other: NpmDependency) = + this?.any { it.id() == other.id() } ?: false - private fun NpmPublication.resolveBundledDependencies( - packageJson: PackageJson, - kotlinDependencies: Map? - ): MutableSet? = with(packageJson) { - ( - bundledDependencies ?: mutableSetOf().also { bd -> - if (bundleKotlinDependencies) { - kotlinDependencies?.keys?.let { keys -> - bd.addAll(keys) + deps.entries.map { (scope, deps) -> + scope to + deps.filter { dep -> + when (scope) { + NpmDependency.Scope.NORMAL -> + !optional.includes(dep) && !peer.includes(dep) && !dev.includes(dep) + NpmDependency.Scope.DEV -> !optional.includes(dep) && !peer.includes(dep) + NpmDependency.Scope.PEER -> !optional.includes(dep) + NpmDependency.Scope.OPTIONAL -> true + } + } + } } + + private fun NpmPublication.resolveTypes() = + compileKotlinTask?.outputFileProperty?.orNull?.let { + kotlinDestinationDir?.resolve("${it.nameWithoutExtension}.d.ts")?.let { dtsFile -> + if (dtsFile.exists()) { + "${dtsFile.relativeTo(dtsFile.parentFile)}" + } else null } - bundledDependenciesSpec?.applyTo(bd) } - ).filter { - binary !is JsIrBinary || kotlinDependencies?.keys?.let { keys -> it !in keys } ?: true - }.toMutableSet().takeIf { it.isNotEmpty() }?.also { bd -> - dependencies { - kotlinDependencies?.forEach { (n, v) -> - if (n in bd) { - n to v.version - } - } + + private fun NpmPublication.resolveBundledDependencies( + packageJson: PackageJson, + kotlinDependencies: Map? + ): MutableSet? = + with(packageJson) { + (bundledDependencies + ?: mutableSetOf().also { bd -> + if (bundleKotlinDependencies) { + kotlinDependencies?.keys?.let { keys -> bd.addAll(keys) } + } + bundledDependenciesSpec?.applyTo(bd) + }) + .filter { + binary !is JsIrBinary || kotlinDependencies?.keys?.let { keys -> it !in keys } ?: true + } + .toMutableSet() + .takeIf { it.isNotEmpty() } + ?.also { bd -> + dependencies { + kotlinDependencies?.forEach { (n, v) -> + if (n in bd) { + n to v.version + } + } + } + } } - } - } - private fun PackageJson.generateNpmShrinkwrapJson() = NpmShrinkwrapJson(name!!, version!!) { - bundledDependencies?.takeIf { it.isNotEmpty() }?.forEach { bundledDependency -> - this@generateNpmShrinkwrapJson.dependencies?.entries?.find { it.key == bundledDependency } - ?.let { (npmName, npmVersion) -> - dependencies { - dependency(npmName, npmVersion!!, true) - } + private fun PackageJson.generateNpmShrinkwrapJson() = + NpmShrinkwrapJson(name!!, version!!) { + bundledDependencies?.takeIf { it.isNotEmpty() }?.forEach { bundledDependency -> + this@generateNpmShrinkwrapJson.dependencies?.entries + ?.find { it.key == bundledDependency } + ?.let { (npmName, npmVersion) -> + dependencies { dependency(npmName, npmVersion!!, true) } + } } - } - }.takeIf { !it.dependencies.isNullOrEmpty() } + } + .takeIf { !it.dependencies.isNullOrEmpty() } } diff --git a/src/main/kotlin/task/NpmPublishTask.kt b/src/main/kotlin/task/NpmPublishTask.kt index b7d37a32..5092e211 100644 --- a/src/main/kotlin/task/NpmPublishTask.kt +++ b/src/main/kotlin/task/NpmPublishTask.kt @@ -5,57 +5,40 @@ import dev.petuska.npm.publish.dsl.NpmPublication import dev.petuska.npm.publish.dsl.NpmPublishExtension import dev.petuska.npm.publish.dsl.NpmRepository import dev.petuska.npm.publish.npmPublishing +import javax.inject.Inject import org.gradle.api.tasks.Internal import org.gradle.api.tasks.TaskAction -import javax.inject.Inject /** * A publishing task that publishes a given publication to a given repository. * * @constructor A publication and repository configurations. */ -open class NpmPublishTask @Inject constructor( - publication: NpmPublication, - repository: NpmRepository -) : NpmExecTask() { +open class NpmPublishTask +@Inject +constructor(publication: NpmPublication, repository: NpmRepository) : NpmExecTask() { override var nodeJsDir by publication.fallbackDelegate(NpmPublication::nodeJsDir) - /** - * @see [NpmRepository.registry] - */ - @get:Internal - var registry by repository.fallbackDelegate(NpmRepository::registry) + /** @see [NpmRepository.registry] */ + @get:Internal var registry by repository.fallbackDelegate(NpmRepository::registry) - /** - * @see [NpmRepository.access] - */ - @get:Internal - var access by repository.fallbackDelegate(NpmRepository::access) + /** @see [NpmRepository.access] */ + @get:Internal var access by repository.fallbackDelegate(NpmRepository::access) - /** - * @see [NpmRepository.authToken] - */ - @get:Internal - var authToken by repository.fallbackDelegate(NpmRepository::authToken) + /** @see [NpmRepository.authToken] */ + @get:Internal var authToken by repository.fallbackDelegate(NpmRepository::authToken) /** - * The directory where the assembled and ready-to-publish package is. - * Defaults to [NpmPublication.destinationDir] + * The directory where the assembled and ready-to-publish package is. Defaults to + * [NpmPublication.destinationDir] */ - @get:Internal - var packageDir by publication.fallbackDelegate(NpmPublication::destinationDir) + @get:Internal var packageDir by publication.fallbackDelegate(NpmPublication::destinationDir) - /** - * @see [NpmRepository.otp] - */ - @get:Internal - var otp by repository.fallbackDelegate(NpmRepository::otp) + /** @see [NpmRepository.otp] */ + @get:Internal var otp by repository.fallbackDelegate(NpmRepository::otp) - /** - * See Also: [dev.petuska.npm.publish.dsl.NpmPublishExtension.dry] - */ - @get:Internal - var dry by project.npmPublishing.fallbackDelegate(NpmPublishExtension::dry) + /** See Also: [dev.petuska.npm.publish.dsl.NpmPublishExtension.dry] */ + @get:Internal var dry by project.npmPublishing.fallbackDelegate(NpmPublishExtension::dry) init { group = "publishing" @@ -66,17 +49,15 @@ open class NpmPublishTask @Inject constructor( private fun doAction() { val repo = "${registry!!.authority.trim()}${registry!!.path.trim()}/" npmExec( - listOf( - "publish", - packageDir, - "--access", "$access", - "--registry", "${registry!!.scheme.trim()}://$repo", - "--//$repo:_authToken=$authToken", - if (otp != null) "--otp $otp" else null, - if (dry) "--dry-run" else null - ) - ) { - workingDir = packageDir - } + listOf( + "publish", + packageDir, + "--access", + "$access", + "--registry", + "${registry!!.scheme.trim()}://$repo", + "--//$repo:_authToken=$authToken", + if (otp != null) "--otp $otp" else null, + if (dry) "--dry-run" else null)) { workingDir = packageDir } } } diff --git a/src/main/kotlin/util/general.kt b/src/main/kotlin/util/general.kt index e2fb6d59..6ba86350 100644 --- a/src/main/kotlin/util/general.kt +++ b/src/main/kotlin/util/general.kt @@ -4,8 +4,10 @@ import org.gradle.api.Project fun String.notFalse() = !equals("false", true) -fun npmFullName(name: String, scope: String?) = "${scope?.let { "@${it.trim()}/" } ?: ""}${name.trim()}" -fun Project.propertyOrNull(name: String): T? = if (hasProperty(name)) { - @Suppress("UNCHECKED_CAST") - property(name) as? T -} else null +fun npmFullName(name: String, scope: String?) = + "${scope?.let { "@${it.trim()}/" } ?: ""}${name.trim()}" + +fun Project.propertyOrNull(name: String): T? = + if (hasProperty(name)) { + @Suppress("UNCHECKED_CAST") property(name) as? T + } else null diff --git a/src/test/kotlin/NpmPublishPluginTest.kt b/src/test/kotlin/NpmPublishPluginTest.kt index 31498b12..2b523e39 100644 --- a/src/test/kotlin/NpmPublishPluginTest.kt +++ b/src/test/kotlin/NpmPublishPluginTest.kt @@ -10,40 +10,39 @@ import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldNotBe import org.gradle.testfixtures.ProjectBuilder -class NpmPublishPluginTest : WordSpec( - { - "Using the Plugin ID" should { - "Apply the Plugin" { - val project = ProjectBuilder.builder().build() - project.pluginManager.apply("dev.petuska.npm.publish") +class NpmPublishPluginTest : + WordSpec({ + "Using the Plugin ID" should + { + "Apply the Plugin" { + val project = ProjectBuilder.builder().build() + project.pluginManager.apply("dev.petuska.npm.publish") - project.plugins.getPlugin("dev.petuska.npm.publish") shouldNotBe null - } - } + project.plugins.getPlugin("dev.petuska.npm.publish") shouldNotBe null + } + } - fun WordSpecTerminalContext.registeringTest(kotlinPlugin: String, registers: Boolean) { - val project = ProjectBuilder.builder().build() - project.pluginManager.apply("dev.petuska.npm.publish") - project.pluginManager.apply(kotlinPlugin) + fun WordSpecTerminalContext.registeringTest(kotlinPlugin: String, registers: Boolean) { + val project = ProjectBuilder.builder().build() + project.pluginManager.apply("dev.petuska.npm.publish") + project.pluginManager.apply(kotlinPlugin) - ( - try { + (try { project.npmPublishing() } catch (e: Exception) { println(e) e.printStackTrace() null - } != null - ) shouldBe registers - } - - "Applying the Plugin" should { - "Register the '$EXTENSION_NAME' extension if JS plugin is applied" { - registeringTest("org.jetbrains.kotlin.js", true) + } != null) shouldBe registers } - "Register the '$EXTENSION_NAME' extension if MPP plugin is applied" { - registeringTest("org.jetbrains.kotlin.multiplatform", true) - } - } - } -) + + "Applying the Plugin" should + { + "Register the '$EXTENSION_NAME' extension if JS plugin is applied" { + registeringTest("org.jetbrains.kotlin.js", true) + } + "Register the '$EXTENSION_NAME' extension if MPP plugin is applied" { + registeringTest("org.jetbrains.kotlin.multiplatform", true) + } + } + }) diff --git a/versions.properties b/versions.properties index 5bd17e0e..62177ba8 100644 --- a/versions.properties +++ b/versions.properties @@ -6,12 +6,37 @@ #### #### suppress inspection "SpellCheckingInspection" for whole file #### suppress inspection "UnusedProperty" for whole file -plugin.com.github.jakemarsden.git-hooks=0.0.2 -plugin.com.gradle.plugin-publish=0.15.0 + +#======================================= Plugins ======================================== +plugin.android=4.2.2 + +plugin.com.gradle.plugin-publish=0.16.0 + plugin.org.jetbrains.dokka=1.5.0 -plugin.org.jlleitschuh.gradle.ktlint=10.1.0 + plugin.io.github.gradle-nexus.publish-plugin=1.1.0 -version.com.google.code.gson..gson=2.8.8 -version.ktlint=0.42.1 + +plugin.com.diffplug.spotless=5.17.0 + +version.com.github.jakemarsden..git-hooks-gradle-plugin=0.0.2 + +version.dev.petuska..klip=0.2.2 + +version.dev.petuska..kon=1.1.1 + +version.org.jetbrains.dokka..dokka-gradle-plugin=1.5.31 + +version.com.github.gmazzo..gradle-buildconfig-plugin=3.0.3 + +#====================================== Libraries ======================================= +version.com.github.tschuchortdev..kotlin-compile-testing=1.4.5 + +version.com.google.auto.service..auto-service=1.0 + +version.com.google.auto.service..auto-service-annotations=1.0 + +version.kotlin=1.5.31 + version.kotest=4.6.2 -version.kotlin=1.5.30 + +version.com.google.code.gson..gson=2.8.8