Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,17 @@ public class BuildDevBundleMojo extends AbstractMojo
+ Constants.DEFAULT_REQUIRE_HOME_NODE_EXECUTABLE)
private boolean requireHomeNodeExec;

/**
* Custom folder containing a pre-installed node executable. When specified,
* Vaadin will use the node installation from this folder exclusively with
* no fallback. If the specified folder does not contain a valid node
* binary, the build will fail with no fallback.
* <p>
* Example: {@code /usr/local/custom-node} or {@code C:\custom\node}
*/
@Parameter(property = InitParameters.NODE_FOLDER)
private String nodeFolder;

/**
* Build directory for the project.
*/
Expand Down Expand Up @@ -453,6 +464,11 @@ public boolean requireHomeNodeExec() {
return requireHomeNodeExec;
}

@Override
public String nodeFolder() {
return nodeFolder;
}

@Override
public File servletResourceOutputDirectory() {
return new File(project.getBuild().getOutputDirectory(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@ internal class GradlePluginAdapter private constructor(
override fun requireHomeNodeExec(): Boolean =
config.requireHomeNodeExec.get()

override fun nodeFolder(): String? =
config.nodeFolder.orNull

override fun servletResourceOutputDirectory(): File {
// when running a task which runs before processResources, we need to
// generate stuff to build/vaadin-generated.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,18 @@ public abstract class VaadinFlowPluginExtension @Inject constructor(private val
*/
public abstract val requireHomeNodeExec: Property<Boolean>

/**
* The folder containing the Node.js executable to use.
*
* When specified, Node.js will be exclusively used from this folder.
* If the binary is not found, the build will fail with no fallback.
*
* Example: "/usr/local/custom-node" or "C:\custom\node"
*
* Defaults to null (use default node resolution).
*/
public abstract val nodeFolder: Property<String>

/**
* Whether or not insert the initial Uidl object in the bootstrap index.html. Defaults to false.
* Responds to the `-Pvaadin.eagerServerLoad` property.
Expand Down Expand Up @@ -483,6 +495,10 @@ public class PluginEffectiveConfiguration(
extension.requireHomeNodeExec
.convention(false)

public val nodeFolder: Property<String> =
extension.nodeFolder
.convention(null as String?)

public val eagerServerLoad: Provider<Boolean> = extension.eagerServerLoad
.convention(false)
.overrideWithSystemPropertyFlag(project, "vaadin.eagerServerLoad")
Expand Down Expand Up @@ -632,6 +648,7 @@ public class PluginEffectiveConfiguration(
frontendToolsSettings.nodeVersion = nodeVersion.get()
frontendToolsSettings.isUseGlobalPnpm = useGlobalPnpm.get()
frontendToolsSettings.isForceAlternativeNode = requireHomeNodeExec.get()
frontendToolsSettings.nodeFolder = nodeFolder.orNull
frontendToolsSettings.isIgnoreVersionChecks = frontendIgnoreVersionChecks.get()

frontendToolsSettings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,17 @@ public abstract class FlowModeAbstractMojo extends AbstractMojo
+ Constants.DEFAULT_REQUIRE_HOME_NODE_EXECUTABLE)
private boolean requireHomeNodeExec;

/**
* The folder containing the Node.js executable to use.
* <p>
* When specified, Node.js will be exclusively used from this folder. If the
* binary is not found, the build will fail with no fallback.
* <p>
* Example: {@code /usr/local/custom-node} or {@code C:\custom\node}
*/
@Parameter(property = InitParameters.NODE_FOLDER)
private String nodeFolder;

/**
* Defines the output directory for generated non-served resources, such as
* the token file.
Expand Down Expand Up @@ -625,6 +636,11 @@ public boolean requireHomeNodeExec() {
return requireHomeNodeExec;
}

@Override
public String nodeFolder() {
return nodeFolder;
}

@Override
public File servletResourceOutputDirectory() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ public static void prepareFrontend(PluginAdapterBase adapter)
.withNodeVersion(adapter.nodeVersion())
.withNodeDownloadRoot(nodeDownloadRootURI)
.withHomeNodeExecRequired(adapter.requireHomeNodeExec())
.withNodeFolder(adapter.nodeFolder())
.setJavaResourceFolder(adapter.javaResourceFolder())
.withProductionMode(false).withReact(adapter.isReactEnabled())
.withFrontendExtraFileExtensions(
Expand Down Expand Up @@ -209,6 +210,7 @@ private static FrontendToolsSettings getFrontendToolsSettings(
settings.setNodeVersion(adapter.nodeVersion());
settings.setUseGlobalPnpm(adapter.useGlobalPnpm());
settings.setForceAlternativeNode(adapter.requireHomeNodeExec());
settings.setNodeFolder(adapter.nodeFolder());
settings.setIgnoreVersionChecks(
adapter.isFrontendIgnoreVersionChecks());

Expand Down Expand Up @@ -264,6 +266,9 @@ public static File propagateBuildInfo(PluginAdapterBase adapter) {
adapter.bunEnable());
buildInfo.put(InitParameters.REQUIRE_HOME_NODE_EXECUTABLE,
adapter.requireHomeNodeExec());
if (adapter.nodeFolder() != null) {
buildInfo.put(InitParameters.NODE_FOLDER, adapter.nodeFolder());
}

buildInfo.put(InitParameters.BUILD_FOLDER, adapter.buildFolder());

Expand Down Expand Up @@ -355,6 +360,7 @@ public static void runNodeUpdater(PluginAdapterBuild adapter,
.withFrontendGeneratedFolder(
getGeneratedFrontendDirectory(adapter))
.withHomeNodeExecRequired(adapter.requireHomeNodeExec())
.withNodeFolder(adapter.nodeFolder())
.withNodeVersion(adapter.nodeVersion())
.withNodeDownloadRoot(nodeDownloadRootURI)
.setJavaResourceFolder(adapter.javaResourceFolder())
Expand Down Expand Up @@ -429,6 +435,7 @@ public static void runDevBuildNodeUpdater(PluginAdapterBuild adapter)
.withFrontendGeneratedFolder(
getGeneratedFrontendDirectory(adapter))
.withHomeNodeExecRequired(adapter.requireHomeNodeExec())
.withNodeFolder(adapter.nodeFolder())
.withNodeVersion(adapter.nodeVersion())
.withNodeDownloadRoot(nodeDownloadRootURI)
.setJavaResourceFolder(adapter.javaResourceFolder())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ private FrontendToolsSettings getFrontendToolsSettings()
settings.setNodeVersion(adapter.nodeVersion());
settings.setUseGlobalPnpm(adapter.useGlobalPnpm());
settings.setForceAlternativeNode(adapter.requireHomeNodeExec());
settings.setNodeFolder(adapter.nodeFolder());
settings.setIgnoreVersionChecks(
adapter.isFrontendIgnoreVersionChecks());
return settings;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,16 @@ default Lookup createLookup(ClassFinder classFinder) {
*/
boolean requireHomeNodeExec();

/**
* The folder containing the Node.js executable.
* <p>
* When returned value is non-null and non-empty, Node.js will be
* exclusively used from this folder. If not found, build will fail.
*
* @return the node folder path, or null to use default resolution
*/
String nodeFolder();

/**
* Defines the output directory for generated non-served resources, such as
* the token file.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,19 @@ public class InitParameters implements Serializable {
*/
public static final String REQUIRE_HOME_NODE_EXECUTABLE = "require.home.node";

/**
* Configuration parameter name for specifying the folder containing the
* Node.js executable.
* <p>
* When this parameter is set to a non-empty value, the Node.js binary will
* be exclusively used from the specified folder. If the binary is not found
* in this folder, an exception will be thrown with no fallback to global or
* alternative installations.
* <p>
* Example: "/usr/local/custom-node" or "C:\\custom\\node"
*/
public static final String NODE_FOLDER = "node.folder";

/**
* Configuration name for the parameter that sets the compiled web
* components path. The path should be the same as
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ String getScript() {
private final boolean ignoreVersionChecks;
private final boolean forceAlternativeNode;
private final boolean useGlobalPnpm;
private final String nodeFolder;

/**
* Creates an instance of the class using the {@code baseDir} as a base
Expand All @@ -197,6 +198,7 @@ public FrontendTools(FrontendToolsSettings settings) {
this.ignoreVersionChecks = settings.isIgnoreVersionChecks();
this.forceAlternativeNode = settings.isForceAlternativeNode();
this.useGlobalPnpm = settings.isUseGlobalPnpm();
this.nodeFolder = settings.getNodeFolder();
}

/**
Expand Down Expand Up @@ -254,20 +256,21 @@ public FrontendTools(String baseDir, Supplier<String> alternativeDirGetter,
this(baseDir, alternativeDirGetter, nodeVersion, nodeDownloadRoot,
"true".equalsIgnoreCase(System.getProperty(
FrontendUtils.PARAM_IGNORE_VERSION_CHECKS)),
forceAlternativeNode, useGlobalPnpm);
forceAlternativeNode, useGlobalPnpm, null);
}

FrontendTools(String baseDir, Supplier<String> alternativeDirGetter,
String nodeVersion, URI nodeDownloadRoot,
boolean ignoreVersionChecks, boolean forceAlternativeNode,
boolean useGlobalPnpm) {
boolean useGlobalPnpm, String nodeFolder) {
this.baseDir = Objects.requireNonNull(baseDir);
this.alternativeDirGetter = alternativeDirGetter;
this.nodeVersion = Objects.requireNonNull(nodeVersion);
this.nodeDownloadRoot = Objects.requireNonNull(nodeDownloadRoot);
this.ignoreVersionChecks = ignoreVersionChecks;
this.forceAlternativeNode = forceAlternativeNode;
this.useGlobalPnpm = useGlobalPnpm;
this.nodeFolder = nodeFolder;
}

private static FrontendToolsSettings createSettings(
Expand All @@ -277,6 +280,8 @@ private static FrontendToolsSettings createSettings(
InitParameters.REQUIRE_HOME_NODE_EXECUTABLE, false);
boolean useGlobalPnpm = applicationConfiguration.getBooleanProperty(
InitParameters.SERVLET_PARAMETER_GLOBAL_PNPM, false);
String nodeFolder = applicationConfiguration
.getStringProperty(InitParameters.NODE_FOLDER, null);
final String nodeVersion = applicationConfiguration.getStringProperty(
NODE_VERSION, FrontendTools.DEFAULT_NODE_VERSION);
final String nodeDownloadRoot = applicationConfiguration
Expand All @@ -288,6 +293,7 @@ private static FrontendToolsSettings createSettings(
() -> FrontendUtils.getVaadinHomeDirectory().getAbsolutePath());
settings.setForceAlternativeNode(useHomeNodeExec);
settings.setUseGlobalPnpm(useGlobalPnpm);
settings.setNodeFolder(nodeFolder);
settings.setNodeVersion(nodeVersion);
settings.setNodeDownloadRoot(URI.create(nodeDownloadRoot));
settings.setIgnoreVersionChecks(false);
Expand Down Expand Up @@ -330,7 +336,7 @@ private NodeResolver.ActiveNodeInstallation ensureNodeResolved() {

NodeResolver resolver = new NodeResolver(getAlternativeDir(),
nodeVersion, nodeDownloadRoot, forceAlternativeNode,
getProxies());
getProxies(), nodeFolder);
activeNodeInstallation = resolver.resolve();
return activeNodeInstallation;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public class FrontendToolsSettings implements Serializable {
private boolean ignoreVersionChecks;
private boolean forceAlternativeNode = Constants.DEFAULT_REQUIRE_HOME_NODE_EXECUTABLE;
private boolean useGlobalPnpm = Constants.GLOBAL_PNPM_DEFAULT;
private String nodeFolder = null;

/**
* Create a tools configuration object.
Expand Down Expand Up @@ -152,6 +153,19 @@ public void setForceAlternativeNode(boolean forceAlternativeNode) {
this.forceAlternativeNode = forceAlternativeNode;
}

/**
* Set the folder containing the Node.js executable.
* <p>
* When set to a non-null/non-empty value, Node.js will be exclusively used
* from this folder. If not found, an exception is thrown with no fallback.
*
* @param nodeFolder
* the folder path, or null to use default resolution
*/
public void setNodeFolder(String nodeFolder) {
this.nodeFolder = nodeFolder;
}

/**
* Force usage of global pnpm.
*
Expand Down Expand Up @@ -217,6 +231,15 @@ public boolean isForceAlternativeNode() {
return forceAlternativeNode;
}

/**
* Get the configured node folder.
*
* @return the node folder path, or null if not configured
*/
public String getNodeFolder() {
return nodeFolder;
}

/**
* Check if global pnpm should be used.
*
Expand Down
Loading
Loading