Creating wrapper task types

To simplify the creation of wrapper tasks, there are two base classes which can be extended:

Extending the wrapper task

This is a minimal example of implementing a wrapper generation task

@CompileStatic
@CacheableTask
class PnpmWrapperTask extends AbstractJseWrapperTask {
    PnpmWrapperTask() {
        super('/gradle-jsecosystem-wrappers/pnpm', PnpmUtils.TOOL_NAME) (1)
    }

    @Override
    protected Map<String, String> getShellWrapperMap() { (2)
        SHELL_WRAPPER
    }

    @Override
    protected Map<String, String> getBatWrapperMap() { (3)
        BAT_WRAPPER
    }

    @Override
    protected Map<String, String> getPs1WrapperMap() { (4)
        PS1_WRAPPER
    }

    private static final Map<String, String> SHELL_WRAPPER = ['pnpm-wrapper-template.sh': 'pnpmw'].asImmutable()
    private static final Map<String, String> BAT_WRAPPER = ['pnpm-wrapper-template.bat': 'pnpmw.bat'].asImmutable()
    private static final Map<String, String> PS1_WRAPPER = ['pnpm-wrapper-template.ps1': 'pnpmw.ps1'].asImmutable()
}
1 Supply a resource to where the templates can be found as well as the name of the tool
2 Return a map of templates within the resource directory that must be used for shell scripts as well as the corresponding shell script names.
3 Return a map of templates within the resource directory that must be used for Windows BAT files as well as the corresponding file names.
4 Return a map of templates within the resource directory that must be used for Windows PowerShell scripts as well as the corresponding file names.

Extending the cache binaries task

This is a minimal example of implementing a wrapper generation task

@CompileStatic
class PnpmCacheBinariesTask extends AbstractJseCacheBinariesTask {

    PnpmCacheBinariesTask() {
        super('pnpm')
        this.binaryLocation = project.objects.property(String)
        this.binaryVersion = project.objects.property(String)
        this.envProperties = project.objects.mapProperty(String, String)
    }

    /**
     * Sets the toolchain for the lifecycle command task.
     *
     * @param tc Toolchain provider
     */
    void setToolchain(Provider<? extends JsePnpmToolchain> tc) { (1)
        this.binaryLocation.set(tc.flatMap { it.executable.map { f -> f.absolutePath } })
        this.binaryVersion.set(tc.flatMap { it.executableVersion })

        final env = tc.flatMap { t -> (2)
            PnpmUtils.minimalPnpmNodeEnv(t, providerTools())
        }.map { m ->
            final loc = m['PNPM_HOME']
            [
                PNPM_HOME    : loc,
                NODE_BIN_PATH: loc
            ]
        }

        this.envProperties.set(env)
    }

    /**
     * Obtains location of executable binary or script
     *
     * @return Location of executable as a string
     */
    @Override
    protected Provider<String> getBinaryLocationProvider() {
        this.binaryVersion
    }

    /**
     * Obtains version of binary or script
     *
     * @return Version as a string. Can be {@code null}.
     */
    @Override
    protected Provider<String> getBinaryVersionProvider() {
        this.binaryLocation
    }

    /**
     * Obtains a description to be added to the cached binary properties file.
     *
     * @return Description. Never {@code null}.
     */
    @Override
    protected String getPropertiesDescription() {
        'Properties for executing pnpm'
    }

    @Override
    protected Map<String, String> getAdditionalProperties() {
        super.additionalProperties + envProperties.get()
    }

    private final Property<String> binaryLocation
    private final Property<String> binaryVersion
    private final MapProperty<String, String> envProperties
}
1 Tying the task to a toolchain is recommended as the toolchain will already know the location of the binaries.
2 When running a wrapper script, additional environment settings might be needed.