Skip to content
Open
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 @@ -96,10 +96,23 @@ object ModuleGenerator {
writeSettingsFile(context)
writeRootBuildScript(context)
writeGradleWrapperResources(context)
writeVersionCatalog(context)

return context.getRootDirectory()
}

/**
* Writes the gradle version catalog (`gradle/libs.versions.toml`) used by subproject buildscripts,
* matching the layout used by ignition-sdk-examples.
*/
private fun writeVersionCatalog(context: ModuleGeneratorContext) {
val catalogFile = context.getRootDirectory().resolve("gradle/libs.versions.toml")
catalogFile.createAndFillFromResource(
"templates/version-catalog/libs.versions.toml",
context.getTemplateReplacements(),
)
}

/**
* Writes the gradle wrapper, allowing the user to build the module without gradle installed.
*/
Expand Down Expand Up @@ -164,10 +177,11 @@ object ModuleGenerator {
}

val dependencies =
DefaultDependencies.ARTIFACTS[projectScope]?.toDependencyFormat(context.config.buildDsl) ?: ""
DefaultDependencies.CATALOG_LIBS[projectScope]?.toDependencyFormat(context.config.buildDsl) ?: ""

rootBuildScript.toFile().appendText(
"""
|
|dependencies {
| $dependencies
|}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,41 +1,44 @@
package io.ia.ignition.module.generator.api

import io.ia.ignition.module.generator.api.TemplateMarker.SDK_VERSION_PLACEHOLDER

object DefaultDependencies {

// default gradle version
const val GRADLE_VERSION = "9.3.1"

// default Ignition SDK / platform version for generated projects (matches ignition-sdk-examples 8.3 line)
const val IGNITION_SDK_VERSION = "8.3.0"

// default plugin configuration for the root build.gradle
val MODL_PLUGIN: String = "id(\"io.ia.sdk.modl\") version(\"${TemplateMarker.MODL_PLUGIN_VERSION.key}\")"

// example
// "com.inductiveautomation.ignitionsdk:client-api:${'$'}{sdk_version}"
val ARTIFACTS: Map<ProjectScope, Set<String>> = mapOf(
/**
* Version-catalog aliases for each scope, matching entries in
* `templates/version-catalog/libs.versions.toml` (and ignition-sdk-examples).
* Hyphens in the TOML library key become dots: ignition-gateway-api -> libs.ignition.gateway.api
*/
val CATALOG_LIBS: Map<ProjectScope, Set<String>> = mapOf(
ProjectScope.CLIENT to setOf(
"com.inductiveautomation.ignitionsdk:client-api:$SDK_VERSION_PLACEHOLDER",
"com.inductiveautomation.ignitionsdk:vision-client-api:$SDK_VERSION_PLACEHOLDER",
"com.inductiveautomation.ignitionsdk:ignition-common:$SDK_VERSION_PLACEHOLDER",
"libs.ignition.client.api",
"libs.ignition.vision.client.api",
"libs.ignition.common",
),
ProjectScope.COMMON to setOf(
"com.inductiveautomation.ignitionsdk:ignition-common:$SDK_VERSION_PLACEHOLDER",
"libs.ignition.common",
),
ProjectScope.DESIGNER to setOf(
"com.inductiveautomation.ignitionsdk:designer-api:$SDK_VERSION_PLACEHOLDER",
"com.inductiveautomation.ignitionsdk:ignition-common:$SDK_VERSION_PLACEHOLDER",
"libs.ignition.designer.api",
"libs.ignition.common",
),
ProjectScope.GATEWAY to setOf(
"com.inductiveautomation.ignitionsdk:ignition-common:$SDK_VERSION_PLACEHOLDER",
"com.inductiveautomation.ignitionsdk:gateway-api:$SDK_VERSION_PLACEHOLDER",
"libs.ignition.common",
"libs.ignition.gateway.api",
),
)

fun Set<String>.toDependencyFormat(
dsl: GradleDsl,
@Suppress("UNUSED_PARAMETER") dsl: GradleDsl,
configuration: String = "compileOnly",
): String = map { artifact ->
val version = dsl.artifactSdkVersion()
"$configuration(\"${artifact.replace(SDK_VERSION_PLACEHOLDER.toString(), version)}\")"
): String = map { catalogAlias ->
"$configuration($catalogAlias)"
}.joinToString(separator = "\n ")
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ class GeneratorConfigBuilder {
private var customReplacements: Map<String, String> = emptyMap()
private var buildDsl: GradleDsl = GROOVY
private var projectLanguage: SourceFileType = JAVA
private var settingsDsl: GradleDsl = GROOVY

// When null, [build] aligns settings DSL with [buildDsl] (kotlin buildscripts get settings.gradle.kts).
private var settingsDsl: GradleDsl? = null
private var gradleWrapperVersion: String = GRADLE_VERSION
private var debugPluginConfig: Boolean = false
private var rootPluginConfig: String = ""
Expand Down Expand Up @@ -64,7 +66,8 @@ class GeneratorConfigBuilder {
packageName = packageName,
scopes = scopes,
parentDir = parentDir,
settingsDsl = settingsDsl,
// Match settings language to buildscripts unless the caller overrode settingsDsl.
settingsDsl = settingsDsl ?: buildDsl,
buildDsl = buildDsl,
projectLanguage = projectLanguage,
gradleWrapperVersion = gradleWrapperVersion,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ enum class GradleDsl {

fun settingsFilename(): String = when (this) {
GROOVY -> "settings.gradle"
KOTLIN -> "templates/settings.gradle.kts"
KOTLIN -> "settings.gradle.kts"
}

fun mapAssociator(): String = when (this) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class ModuleGeneratorContext(override val config: GeneratorConfig) : GeneratorCo
private fun buildDependencyEntries(scopes: List<ProjectScope>): Map<String, String> = mutableMapOf<String, String>().apply {
scopes.forEach { scope ->
TemplateMarker.dependencyKeyForScope(scope)?.let { tm ->
this[tm.key] = DefaultDependencies.ARTIFACTS[scope]?.toDependencyFormat(config.buildDsl) ?: ""
this[tm.key] = DefaultDependencies.CATALOG_LIBS[scope]?.toDependencyFormat(config.buildDsl) ?: ""
// if not a common scope and there is a common project, add it as a dependency to other scopes
if (scope != COMMON && scopes.size > 1) {
this[tm.key] = "${this[tm.key]}\n compileOnly(project(\":common\"))"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ plugins {
}

ext {
sdk_version = "8.1.20"
// Keep in sync with [versions].ignition in gradle/libs.versions.toml
sdk_version = "8.3.0"
}

allprojects {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ plugins {
<ROOT_PLUGIN_CONFIGURATION>
}

val sdk_version by extra("8.1.20")
// Keep in sync with [versions].ignition in gradle/libs.versions.toml
val sdk_version by extra("8.3.0")

allprojects {
version = "0.0.1-SNAPSHOT"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,15 @@ ignitionModule {
*/
//<SKIP_MODULE_SIGNING>
}

/*
* Convenience task that runs clean on all projects and removes the root .gradle cache directory.
* Mirrors the cleanup helper used in ignition-sdk-examples.
*/
tasks.register("deepClean") {
dependsOn(allprojects.collect { it.path + ":clean" })
description = "Executes clean tasks and removes the root .gradle directory."
doLast {
delete(file(".gradle"))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,15 @@ ignitionModule {
*/
//<SKIP_MODULE_SIGNING>
}

/*
* Convenience task that runs clean on all projects and removes the root .gradle cache directory.
* Mirrors the cleanup helper used in ignition-sdk-examples.
*/
val deepClean by tasks.registering {
dependsOn(allprojects.map { "${it.path}:clean" })
description = "Executes clean tasks and removes the root .gradle directory."
doLast {
delete(file(".gradle"))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,15 @@
*/
public class <MODULE_CLASSNAME>DesignerHook extends AbstractDesignerModuleHook {

// override additonal methods as requried
// override additional methods as required

@Override
public void startup(DesignerContext context, LicenseState activationState) throws Exception {
// implelement functionality as required
// implement functionality as required
}

@Override
public void shutdown() {
// cleanup as required
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@ import com.inductiveautomation.ignition.designer.model.DesignerContext
/**
* This is the Designer-scope module hook. The minimal implementation contains a startup method.
*/
class <MODULE_CLASSNAME>DesignerHook: AbstractDesignerModuleHook() {
class <MODULE_CLASSNAME>DesignerHook : AbstractDesignerModuleHook() {

// override additonal methods as requried
// override additional methods as required

@Throws(Exception)
@Throws(Exception::class)
override fun startup(context: DesignerContext, activationState: LicenseState) {
// implement functionality as required
}

override fun shutdown() {
// cleanup as required
}
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,16 @@
package <PACKAGE_ROOT>.gateway;

import java.util.List;
import java.util.Optional;
import javax.servlet.http.HttpServletResponse;

import com.inductiveautomation.ignition.common.licensing.LicenseState;
import com.inductiveautomation.ignition.common.project.resource.adapter.ResourceTypeAdapterRegistry;
import com.inductiveautomation.ignition.gateway.dataroutes.RouteGroup;
import com.inductiveautomation.ignition.gateway.model.AbstractGatewayModuleHook;
import com.inductiveautomation.ignition.gateway.model.GatewayContext;
import com.inductiveautomation.ignition.gateway.web.models.ConfigCategory;
import com.inductiveautomation.ignition.gateway.web.models.IConfigTab;
import com.inductiveautomation.ignition.gateway.web.models.SystemMap;
import com.inductiveautomation.ignition.gateway.web.pages.config.overviewmeta.ConfigOverviewContributor;
import com.inductiveautomation.ignition.gateway.web.pages.status.overviewmeta.OverviewContributor;

/**
* Class which is instantiated by the Ignition platform when the module is loaded in the gateway scope.
* Override additional AbstractGatewayModuleHook methods as needed for your module.
*/
public class <MODULE_CLASSNAME>GatewayHook extends AbstractGatewayModuleHook {
/**
* Called to before startup. This is the chance for the module to add its extension points and update persistent
* Called before startup. This is the chance for the module to add its extension points and update persistent
* records and schemas. None of the managers will be started up at this point, but the extension point managers will
* accept extension point types.
*/
Expand All @@ -40,115 +30,18 @@ public void startup(LicenseState activationState) {

/**
* Called to shutdown this module. Note that this instance will never be started back up - a new one will be created
* if a restart is desired
* if a restart is desired.
*/
@Override
public void shutdown() {

}

/**
* A list (may be null or empty) of panels to display in the config section. Note that any config panels that are
* part of a category that doesn't exist already or isn't included in {@link #getConfigCategories()} will
* <i>not be shown</i>.
*/
@Override
public List<? extends IConfigTab> getConfigPanels() {
return null;
}

/**
* A list (may be null or empty) of custom config categories needed by any panels returned by {@link
* #getConfigPanels()}
*/
@Override
public List<ConfigCategory> getConfigCategories() {
return null;
}

/**
* @return the path to a folder in one of the module's gateway jar files that should be mounted at
* /res/module-id/foldername
*/
@Override
public Optional<String> getMountedResourceFolder() {
return Optional.empty();
}

/**
* Provides a chance for the module to mount any route handlers it wants. These will be active at
* <tt>/main/data/module-id/*</tt> See {@link RouteGroup} for details. Will be called after startup().
*/
@Override
public void mountRouteHandlers(RouteGroup routes) {

}

/**
* Used by the mounting underneath /res/module-id/* and /main/data/module-id/* as an alternate mounting path instead
* of your module id, if present.
*/
@Override
public Optional<String> getMountPathAlias() {
return Optional.empty();
}

/**
* @return {@code true} if this is a "free" module, i.e. it does not participate in the licensing system. This is
* equivalent to the now defunct FreeModule attribute that could be specified in module.xml.
* @return {@code true} if this is a "free" module, i.e. it does not participate in the licensing system.
*/
@Override
public boolean isFreeModule() {
return false;
}

/**
* Implement this method to contribute meta data to the Status section's Systems / Overview page.
*/
@Override
public Optional<OverviewContributor> getStatusOverviewContributor() {
return Optional.empty();
}

/**
* Implement this method to contribute meta data to the Configure section's Overview page.
*/
@Override
public Optional<ConfigOverviewContributor> getConfigOverviewContributor() {
return Optional.empty();
}

/**
* Register any {@link ResourceTypeAdapter}s this module needs with with {@code registry}.
* <p>
* ResourceTypeAdapters are used to adapt a legacy (7.9 or prior) resource type name or payload into a nicer format
* for the Ignition 8.0 project resource system.Ò Only override this method for modules that aren't known by the
* {@link ResourceTypeAdapterRegistry} already.
* <p>
* <b>This method is called before {@link #setup(GatewayContext)} or {@link #startup(LicenseState)}.</b>
*
* @param registry the shared {@link ResourceTypeAdapterRegistry} instance.
*/
@Override
public void initializeResourceTypeAdapterRegistry(ResourceTypeAdapterRegistry registry) {

}

/**
* Called prior to a 'mounted resource request' being fulfilled by requests to the mounted resource servlet serving
* resources from /res/module-id/ (or /res/alias/ if {@link GatewayModuleHook#getMountPathAlias} is implemented). It
* is called after the target resource has been successfully located.
*
* <p>
* Primarily intended as an opportunity to amend/alter the response's headers for purposes such as establishing
* Cache-Control. By default, Ignition sets no additional headers on a resource request.
* </p>
*
* @param resourcePath path to the resource being returned by the mounted resource request
* @param response the response to read/amend.
*/
@Override
public void onMountedResourceRequest(String resourcePath, HttpServletResponse response) {

return true;
}
}
Loading