| name | jarchi-scripting |
| description | This skill should be used when the user asks to "write a JArchi script", "create an Archi script", "build an .ajs script", "add a dialog to a script", "use SWT widgets", "create a JFace dialog", "use Eclipse UI in JArchi", "extend a Java class in JavaScript", "use Java.type()", "work with ArchiMate elements", "use the jArchi API", "create a library module", "use GraalJS", mentions JArchi, Archi scripting, ArchiMate modeling scripts, SWT/JFace UI, or GraalVM JavaScript for Archi. |
JArchi Script Development
Procedural guide for writing JArchi scripts (GraalVM GraalJS, ECMAScript 2024). Requires Archi 5.7+, JArchi 1.11+.
Constraints (NOT Node.js)
- Use
load() for local files — never require() (it resolves to node_modules/)
- No Web Workers, no async I/O, no
setTimeout (unless shimmed)
- No Node.js modules (
fs, path, http) — use Java.type() for Java equivalents
this inside Java.extend() refers to the Java proxy — use the object wrapper pattern below
Creating a Script
Every top-level .ajs script: clear console, load log.js, IIFE, try-catch, "use strict":
console.clear();
console.show();
load(__DIR__ + "lib/log.js");
load(__DIR__ + "lib/swtImports.js");
(function () {
"use strict";
try {
log.header("Script Name");
log.success("Script Name: Complete.");
} catch (error) {
log.error("Script failed: " + error.toString());
window.alert("Error: " + error.message);
}
})();
Use Title Case with spaces for .ajs filenames (e.g., ELK Layout.ajs). __DIR__ already includes trailing separator — don't add /.
Creating a Library Module
To create a reusable module in lib/, use the dual-export IIFE with a double-load guard:
(function() {
"use strict";
if (typeof globalThis !== "undefined" && typeof globalThis.myModule !== "undefined") return;
if (typeof globalThis !== "undefined") globalThis.myModule = myModule;
if (typeof module !== "undefined" && module.exports) module.exports = myModule;
})();
To load a module: load(__DIR__ + "lib/myModule.js"); then destructure from the global.
Working with the Model
To get the active view, use resolveSelection (never $(selection).filter("archimate-diagram-model")):
load(__DIR__ + "lib/resolveSelection.js");
var view = resolveSelection.activeView();
var elements = resolveSelection.selectedConcepts("element");
To query elements: $("business-process"). To create: model.createElement("business-process", "Name"). To create relationships: model.createRelationship("serving-relationship", source, target).
Always handle empty names: element.name && element.name.trim() ? element.name : "-- unnamed --".
Building Dialogs
To create a dialog, use swtImports.ExtendedTitleAreaDialog with the object wrapper pattern. Both isResizable and getShellStyle overrides are required — isResizable alone fails because the Java.extend proxy isn't wired during the Java constructor. Always call setHelpAvailable(false) before open().
load(__DIR__ + "lib/swtImports.js");
var { SWT, Text, GridDataFactory, ExtendedTitleAreaDialog } = swtImports;
var myDialog = {
dialog: new ExtendedTitleAreaDialog(shell, {
configureShell: function(newShell) {
Java.super(myDialog.dialog).configureShell(newShell);
newShell.setText("My Dialog");
},
isResizable: function() { return true; },
getShellStyle: function() {
return SWT.CLOSE | SWT.TITLE | SWT.BORDER | SWT.APPLICATION_MODAL | SWT.RESIZE | SWT.MAX;
},
createDialogArea: function(parent) {
var area = Java.super(myDialog.dialog).createDialogArea(parent);
myDialog.dialog.setMessage("Enter information:");
var text = new Text(area, SWT.BORDER);
GridDataFactory.fillDefaults().grab(true, false).applyTo(text);
myDialog._nameText = text;
return area;
},
okPressed: function() {
var value = myDialog._nameText.getText().trim();
if (!value) { myDialog.dialog.setErrorMessage("Required"); return; }
Java.super(myDialog.dialog).okPressed();
}
})
};
myDialog.dialog.setHelpAvailable(false);
if (myDialog.dialog.open() === 0) { }
For simple prompts: window.prompt("Enter name:"), window.confirm("Sure?"), window.alert("Done.").
Critical Pitfalls
Java.super(this) fails — always use Java.super(myDialog.dialog) via stored object property
require() fails for local files — use load(__DIR__ + "lib/file.js")
- Raw
$(selection) misses cases — use resolveSelection.selectedConcepts() / .activeView()
- Non-resizable dialogs — override both
isResizable() AND getShellStyle()
- Help button showing — call
dialog.setHelpAvailable(false) before open()
- Null element names — always guard with
name && name.trim() check
- Raw console.log — use
log.header/info/detail/success/warn/error from lib/log.js
- Undisposed resources — use try/finally for Color, Font, Image
- Double path separator —
__DIR__ already has trailing separator
Reference Files
For detailed API docs, SWT widget reference, layout patterns, and complete examples:
references/script-development-guide.md — Full guide with dialog patterns, model operations, widget reference, and migration checklist
references/jarchi-api-reference.md — JArchi 1.11 API: collection methods, element types, view operations
references/graaljs-compatibility.md — GraalJS runtime: ECMAScript 2024 features, load() semantics
references/java-interop.md — Java.type(), Java.extend(), Java.super(), type mappings, array conversions