in libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/web/nodejs/NodeJsRootPluginApplier.kt [48:324]
fun apply(project: Project) {
MultiplePluginDeclarationDetector.detect(project)
check(project == project.rootProject) {
"${this::class.java.name} can be applied only to root project"
}
project.plugins.apply(BasePlugin::class.java)
val nodeJsRoot = project.extensions.create(
nodeJsRootName,
nodeJsRootKlass.java,
project,
{ singleNodeJsPluginApply(project) },
rootDirectoryName,
)
val npm = project.extensions.create(
npmName,
npmKlass.java,
project,
nodeJsRoot,
)
val nodeJs = singleNodeJsPluginApply(project)
npm.nodeJsEnvironment.value(
nodeJs.env
).disallowChanges()
nodeJsRoot.packageManagerExtension.convention(
npm
)
npm.lockFileDirectory.convention(
lockFileDirectory(project.layout.projectDirectory)
)
val gradleNodeModulesProvider: Provider<GradleNodeModulesCache> = GradleNodeModulesCache.registerIfAbsent(
project,
project.projectDir,
nodeJsRoot.nodeModulesGradleCacheDirectory,
platformDisambiguate::extensionName
)
val setupFileHasherTask =
project.registerTask<KotlinNpmCachesSetup>(platformDisambiguate.extensionName(KotlinNpmCachesSetup.NAME)) {
it.description = "Setup file hasher for caches"
it.gradleNodeModules.set(gradleNodeModulesProvider)
}
project.registerTask<Task>(platformDisambiguate.extensionName(PACKAGE_JSON_UMBRELLA_TASK_NAME))
nodeJsRoot.resolver = KotlinRootNpmResolver(
project.name,
project.version.toString(),
TasksRequirements(),
nodeJsRoot.versions,
nodeJsRoot.rootProjectDir,
platformType
)
val objectFactory = project.objects
val npmResolutionManager: Provider<KotlinNpmResolutionManager> = KotlinNpmResolutionManager.registerIfAbsent(
project,
objectFactory.providerWithLazyConvention {
nodeJsRoot.resolver.close()
},
gradleNodeModulesProvider,
nodeJsRoot.projectPackagesDirectory
) {
platformDisambiguate.extensionName(it, prefix = null)
}
val packageJsonUmbrella = nodeJsRoot
.packageJsonUmbrellaTaskProvider
val rootPackageJson =
project.tasks.register(
platformDisambiguate.extensionName(
RootPackageJsonTask.NAME,
prefix = null,
),
RootPackageJsonTask::class.java
) { task ->
task.group = NodeJsRootPlugin.TASKS_GROUP_NAME
task.description = "Create root package.json"
task.configureNodeJsEnvironmentWithNpmResolutionManagerTasks(
setupFileHasherTask,
nodeJsRoot,
nodeJs,
npmResolutionManager,
)
task.rootPackageJsonFile.value(
nodeJsRoot.rootPackageDirectory.map { it.file(NpmProject.PACKAGE_JSON) }
).disallowChanges()
task.onlyIf("Prepare NPM project only in configuring state") {
it as RootPackageJsonTask
it.npmResolutionManager.get().isConfiguringState()
}
task.dependsOn(packageJsonUmbrella)
}
configureRequiresNpmDependencies(project, rootPackageJson)
val npmInstall =
project.registerTask<KotlinNpmInstallTask>(platformDisambiguate.extensionName(KotlinNpmInstallTask.BASE_NAME)) { npmInstall ->
with(nodeJs) {
npmInstall.dependsOn(project.nodeJsSetupTaskProvider)
}
npmInstall.group = NodeJsRootPlugin.TASKS_GROUP_NAME
npmInstall.description = "Find, download and link NPM dependencies and projects"
npmInstall.configureNodeJsEnvironmentWithNpmResolutionManagerTasks(
setupFileHasherTask,
nodeJsRoot,
nodeJs,
npmResolutionManager,
)
npmInstall.nodeModules.value(
nodeJsRoot.rootPackageDirectory.map { it.dir("node_modules") }
).disallowChanges()
npmInstall.additionalFiles.from(
nodeJsRoot.packageManagerExtension.map { it.additionalInstallOutput }
).disallowChanges()
npmInstall.preparedFiles.from(
nodeJsRoot.packageManagerExtension.zip(npmInstall.nodeJsEnvironment) { npmApiExt, nodeJsEnvironment ->
npmApiExt.packageManager.preparedFiles(nodeJsEnvironment)
}
).disallowChanges()
npmInstall.onlyIf("No package.json files for install") { task ->
task as KotlinNpmInstallTask
task.preparedFiles.all { file ->
file.exists()
}
}
npmInstall.outputs.upToDateWhen {
npmInstall.nodeModules.getFile().exists()
}
npmInstall.dependsOn(rootPackageJson)
npmInstall.inputs.property("npmIgnoreScripts", { npm.ignoreScripts })
npmInstall.dependsOn(nodeJsRoot.packageManagerExtension.map { it.preInstallTasks })
}
val upgradeLock = project.tasks.register(
platformDisambiguate.extensionName(LockCopyTask.UPGRADE_PACKAGE_LOCK_BASE_NAME),
LockStoreTask::class.java
) { task ->
task.dependsOn(npmInstall)
task.inputFile.set(nodeJsRoot.rootPackageDirectory.map { it.file(LockCopyTask.PACKAGE_LOCK) })
task.outputDirectory.set(npm.lockFileDirectory)
task.fileName.set(npm.lockFileName)
task.additionalInputFiles.from(
nodeJsRoot.rootPackageDirectory.map { it.file(LockCopyTask.YARN_LOCK) }
)
task.additionalInputFiles.from(
task.outputDirectory.map { it.file(LockCopyTask.YARN_LOCK) }
)
task.lockFileMismatchReport.value(
LockFileMismatchReport.NONE
).disallowChanges()
task.reportNewLockFile.value(
false
).disallowChanges()
task.lockFileAutoReplace.value(
true
).disallowChanges()
}
project.tasks.register(
platformDisambiguate.extensionName(LockCopyTask.STORE_PACKAGE_LOCK_BASE_NAME),
LockStoreTask::class.java
) { task ->
task.dependsOn(npmInstall)
task.inputFile.set(nodeJsRoot.rootPackageDirectory.map { it.file(LockCopyTask.PACKAGE_LOCK) })
task.additionalInputFiles.from(
nodeJsRoot.rootPackageDirectory.map { it.file(LockCopyTask.YARN_LOCK) }
)
task.additionalInputFiles.from(
task.outputDirectory.map { it.file(LockCopyTask.YARN_LOCK) }
)
task.outputDirectory.set(npm.lockFileDirectory)
task.fileName.set(npm.lockFileName)
task.lockFileMismatchReport.value(
project.provider { npm.requireConfigured().packageLockMismatchReport }
).disallowChanges()
task.reportNewLockFile.value(
project.provider { npm.requireConfigured().reportNewPackageLock }
).disallowChanges()
task.lockFileAutoReplace.value(
project.provider { npm.requireConfigured().packageLockAutoReplace }
).disallowChanges()
task.mismatchMessage.value(
LockCopyTask.packageLockMismatchMessage(
upgradeLock.name
)
)
}
project.tasks.register(
platformDisambiguate.extensionName(LockCopyTask.RESTORE_PACKAGE_LOCK_BASE_NAME),
LockCopyTask::class.java
) { task ->
task.inputFile.set(
npm.lockFileDirectory.flatMap { dir ->
dir.file(npm.lockFileName)
}
)
task.additionalInputFiles.from(
npm.lockFileDirectory.map { it.file(LockCopyTask.YARN_LOCK) }
)
task.outputDirectory.set(nodeJsRoot.rootPackageDirectory)
task.fileName.set(LockCopyTask.PACKAGE_LOCK)
task.onlyIf {
val inputFileExists = task.inputFile.getOrNull()?.asFile?.exists() == true
// Workaround for "skip if not exists"
// https://github.com/gradle/gradle/issues/2919
if (!inputFileExists) {
task.inputFile.set(null as RegularFile?)
}
inputFileExists || task.additionalInputFiles.files.any { it.exists() }
}
}
npm.preInstallTasks.value(
listOf(npm.restorePackageLockTaskProvider)
).disallowChanges()
npm.postInstallTasks.value(
listOf(npm.storePackageLockTaskProvider)
).disallowChanges()
@Suppress("DEPRECATION")
project.tasks.register(
platformDisambiguate.extensionName(
"node" + org.jetbrains.kotlin.gradle.tasks.CleanDataTask.NAME_SUFFIX,
prefix = null,
),
org.jetbrains.kotlin.gradle.tasks.CleanDataTask::class.java
) {
it.doFirst {
it.logger.warn(org.jetbrains.kotlin.gradle.tasks.CleanDataTask.Companion.deprecationMessage(it.path))
}
it.cleanableStoreProvider = nodeJs
.installationDirectory
.map { org.jetbrains.kotlin.gradle.tasks.internal.CleanableStore.Companion[it.asFile.path] }
it.group = NodeJsRootPlugin.TASKS_GROUP_NAME
it.description = "Clean unused local node version"
}
beforePackageManager(project)
val propertiesProvider = PropertiesProvider.Companion(project)
if (propertiesProvider.yarn) {
project.plugins.apply(yarnPlugin.java)
}
}