Skip to content

Commit

Permalink
feat: element templates runtime versions
Browse files Browse the repository at this point in the history
Config for current runtime platform and version can now be passed to elementTemplates. If template has information about supported engines, compatibility will be verified.

Related to camunda/camunda-modeler#4530
  • Loading branch information
nikku committed Dec 9, 2024
1 parent 856fc0f commit 6169f9d
Show file tree
Hide file tree
Showing 3 changed files with 171 additions and 47 deletions.
153 changes: 108 additions & 45 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
"min-dash": "^4.0.0",
"min-dom": "^4.0.3",
"preact-markup": "^2.1.1",
"semver": "^7.6.3",
"semver-compare": "^1.0.0",
"uuid": "^11.0.0"
},
Expand Down
64 changes: 62 additions & 2 deletions src/element-templates/ElementTemplates.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import {

import { isAny } from 'bpmn-js/lib/util/ModelUtil';

import { valid, satisfies, validRange, coerce } from 'semver';

/**
* Registry for element templates.
*/
Expand All @@ -27,6 +29,7 @@ export default class ElementTemplates {
this._modeling = modeling;

this._templatesById = {};
this._templates = [];
}

/**
Expand Down Expand Up @@ -112,6 +115,7 @@ export default class ElementTemplates {
console.log('elementTemplates#set');

this._templatesById = {};
this._templates = templates;

templates.forEach((template) => {
const id = template.id,
Expand All @@ -125,13 +129,69 @@ export default class ElementTemplates {

this._templatesById[ id ][ version ] = template;

const latestVerions = this._templatesById[ id ].latest.version;
if (isUndefined(latestVerions) || template.version > latestVerions) {
const latest = this._templatesById[ id ].latest;

const isCompat = this.isCompatible(template);
if (!isCompat) {
return;
}

if (isUndefined(latest.version) || latest.version < version || !this.isCompatible(latest)) {
this._templatesById[ id ].latest = template;
}
});
}

/**
* Call elementTemplates#set with previously loaded templates.
*/
reset() {
this.set(this._templates);
}

/**
* Check if template is compatible with currently set engine version.
*
* @param {ElementTemplate} template
*
* @return {boolean} - true if compatible or no engine is set for elementTemplates or template.
*/
isCompatible(template) {
const engines = this._engines;

const exists = (obj) => obj && Object.keys(obj).length > 0;
if (!exists(engines) || !exists(template.engines)) return true;

// We want the template to be compatible with all provided engines - looking for overlap.
const enginesToCheck = Object.keys(template.engines).filter(key => Object.hasOwn(engines, key));

const compatible = enginesToCheck.reduce((isCompatible, engine) => {

// If any engine is incompatible, skip further checks.
if (!isCompatible) return false;

const runtimeVersion = engines[engine];
const templateVersion = template.engines[engine];

const runtimeSemver = valid(coerce(engines[engine]));
const templateSemver = validRange(template.engines[engine]);

if (!runtimeSemver) {
console.error(`Engine '${engine}' version '${runtimeVersion}' is not valid semver`);
return isCompatible;
}

if (!templateSemver) {
console.error(`Template ${template.id} engine '${engine}' version '${templateVersion}' is not valid semver`);
return true;
}

return satisfies(runtimeSemver, templateSemver);
}, true);

return compatible;
}

/**
* @param {object|string|null} id
* @param { { latest?: boolean, deprecated?: boolean } [options]
Expand Down

0 comments on commit 6169f9d

Please sign in to comment.