Module (NXM)
Ihr erstes Modul
Sie bauen ein kleines NXM-Modul von Grund auf, mit einem Fachobjekt, einer Liste, einem Dialog, einer eigenen Seite und Beispieldaten. Dann paketieren Sie es, installieren es in einem Mandanten und liefern ein Update mit Datenmigration aus.
Brandt & Söhne verleiht Laptops, Monitore und Telefone an die eigenen Leute. Die Liste dazu steckt heute in einer Tabelle, der niemand traut: Wer hat das MacBook, und bis wann? In diesem Tutorial bauen Sie Leihgeräte, ein NXM-Modul mit einem eigenen Fachobjekt für Geräte, einer Liste mit Filtern, einem Dialog zum Ausleihen, einer Seite mit allen fälligen Rückgaben und Werkzeugen für den KI-Assistenten. Zum Schluss liefern Sie Version 1.1.0 aus und sehen zu, wie nexxus die gespeicherten Daten umstellt.
Sie schreiben fünf Dateien, packen sie in eine .nxm-Datei und laden sie hoch. Alles, was das Modul zeigt, steht in diesen Dateien. In nexxus selbst läuft kein Code des Moduls.
Schreiben
module.json, ein Changelog, zwei HTML-Ansichten, Beispieldaten.
Bauen
Das Paketier-Skript macht aus dem Ordner eine .nxm-Datei.
Hochladen
nexxus prüft das Paket und zeigt, was es mitbringt.
Installieren
Sie stimmen zu, vergeben Rollen, und das Modul steht im Menü.
Aktualisieren
Version 1.1.0 benennt einen Wert um und ergänzt ein Feld.
Bevor Sie beginnen
Abschnitt betitelt „Bevor Sie beginnen“- Ein Administratorkonto in einer nexxus-Instanz. Nur Administratoren laden Pakete hoch und installieren sie.
- Eine Instanz, die Ihr Paket annimmt. Das Paket aus diesem Tutorial ist nicht signiert. Instanzen mit dem Spring-Profil
development,localoderdemonehmen unsignierte Pakete an. Anderswo schaltet ein Administrator des Mandanten im Reiter Herausgeber Unsignierte Pakete zulassen ein, oder Sie signieren das Paket. Beides steht unter Paketieren, installieren und aktualisieren. - Node.js für das Paketier-Skript
module-package.mjs. Es liegt in den nexxus-Quellen unterbackend/scripts/und braucht keine weiteren Pakete. Kopieren Sie es neben Ihren Paketordner. - Einen Texteditor.
Das Modul planen
Abschnitt betitelt „Das Modul planen“Bevor Sie die erste Zeile schreiben, legen Sie vier Dinge fest. Sie landen im Manifest und lassen sich später nur schwer ändern.
| Entscheidung | Wahl in diesem Tutorial | Warum |
|---|---|---|
| Schlüssel | acme.leihgeraete | <herausgeber>.<name>, klein geschrieben. Der Schlüssel ändert sich nie. Rechte, Werkzeugnamen und Routen leiten sich davon ab. |
| Bereich | projekte | Der Fachbereich des Moduls. projekte erscheint in der linken Leiste unter Organisation. |
| Fachobjekte | eines, geraet | Jedes Fachobjekt bekommt eine eigene Liste und eigene Datensatzseiten. |
| Wer darf was | Rollen verwaltung (verwalten und verleihen) und einsicht (nur lesen) | Die Rollen entstehen bei der Installation. Niemand hat sie, bis ein Administrator sie vergibt. |
Den Ordner anlegen
Abschnitt betitelt „Den Ordner anlegen“Jede Version bekommt einen eigenen Ordner, und der Ordner heißt wie die Version. Sonst meldet das Skript Hinweis: Der Ordner heißt nicht wie die Version 1.0.0.
Ordneracme.leihgeraete/
Ordner1.0.0/
- module.json das Manifest
- CHANGELOG.md
Ordnerui/
- ausleihen.html Dialog zum Ausleihen
- faellig.html Seite mit fälligen Rückgaben
Ordnerdemo/
- geraet.json Beispieldaten, auf Wunsch installiert
Das Manifest schreiben
Abschnitt betitelt „Das Manifest schreiben“module.json beschreibt alles: das Fachobjekt mit seinen Feldern, Rechte, Rollen, Ansichten, Menüeinträge, Aktionen und was der KI-Assistent tun darf. Legen Sie die Datei mit diesem Inhalt an.
{ "key": "acme.leihgeraete", "kind": "package", "publisher": "acme", "name": {"de": "Leihgeräte", "en": "Loan equipment"}, "description": {"de": "Geräte, die das Team ausleiht: wer hat was, bis wann.", "en": "Equipment the team borrows: who has what, until when."}, "icon": "devices", "area": "projekte", "version": "1.0.0", "platform": ">=0.2.0 <1.0.0", "permissions": [ {"key": "verleihen", "label": {"de": "Geräte verleihen", "en": "Lend equipment"}, "description": {"de": "Darf Geräte ausleihen und zurücknehmen.", "en": "May lend equipment and take it back."}} ], "roles": [ {"key": "verwaltung", "label": {"de": "Geräteverwaltung", "en": "Equipment management"}, "permissions": ["geraet.read", "geraet.write", "verleihen"]}, {"key": "einsicht", "label": {"de": "Einsicht", "en": "View"}, "permissions": ["geraet.read"]} ], "entities": [ { "key": "geraet", "label": {"de": "Gerät", "en": "Device"}, "labelPlural": {"de": "Geräte", "en": "Devices"}, "icon": "devices", "titleField": "bezeichnung", "searchFields": ["bezeichnung", "inventarnummer"], "fields": [ {"key": "inventarnummer", "type": "string", "sequence": "GER-{n:4}", "label": {"de": "Inventarnummer", "en": "Inventory no."}}, {"key": "bezeichnung", "type": "string", "required": true, "maxLength": 120, "label": {"de": "Bezeichnung", "en": "Name"}}, {"key": "kategorie", "type": "enum", "indexed": true, "default": "laptop", "label": {"de": "Kategorie", "en": "Category"}, "values": [ {"key": "laptop", "label": {"de": "Laptop", "en": "Laptop"}}, {"key": "monitor", "label": {"de": "Monitor", "en": "Monitor"}}, {"key": "telefon", "label": {"de": "Telefon", "en": "Phone"}}, {"key": "sonstiges", "label": {"de": "Sonstiges", "en": "Other"}}]}, {"key": "status", "type": "enum", "indexed": true, "readonly": true, "default": "verfuegbar", "label": {"de": "Status", "en": "Status"}, "values": [ {"key": "verfuegbar", "label": {"de": "Verfügbar", "en": "Available"}}, {"key": "verliehen", "label": {"de": "Verliehen", "en": "On loan"}}]}, {"key": "ausgeliehen_an", "type": "ref", "target": "core:user", "label": {"de": "Ausgeliehen an", "en": "Lent to"}}, {"key": "rueckgabe_am", "type": "date", "indexed": true, "label": {"de": "Rückgabe am", "en": "Due back"}}, {"key": "notiz", "type": "text", "label": {"de": "Notiz", "en": "Note"}} ] } ], "views": [ {"key": "geraet.list", "type": "list", "entity": "geraet", "label": {"de": "Geräte", "en": "Devices"}, "columns": [{"field": "inventarnummer"}, {"field": "bezeichnung"}, {"field": "kategorie"}, {"field": "status", "display": "badge"}, {"field": "ausgeliehen_an"}, {"field": "rueckgabe_am"}], "filters": ["kategorie", "status", "ausgeliehen_an"], "sort": {"field": "inventarnummer", "dir": "asc"}, "create": true}, {"key": "geraet.record", "type": "record", "entity": "geraet", "label": {"de": "Daten", "en": "Data"}, "sections": [ {"key": "geraet", "label": {"de": "Gerät", "en": "Device"}, "fields": ["inventarnummer", "bezeichnung", "kategorie", "status"]}, {"key": "ausleihe", "label": {"de": "Ausleihe", "en": "Loan"}, "fields": ["ausgeliehen_an", "rueckgabe_am", "notiz"]}], "actions": ["ausleihen-dialog", "zurueckgeben"]}, {"key": "ausleihen-dialog", "type": "custom", "slot": "record.action", "target": "geraet", "html": "ui/ausleihen.html", "label": {"de": "Ausleihen", "en": "Lend"}, "icon": "assignment_ind", "when": {"field": "status", "in": ["verfuegbar"]}}, {"key": "faellig", "type": "custom", "slot": "page", "html": "ui/faellig.html", "label": {"de": "Fällige Rückgaben", "en": "Due returns"}} ], "menu": [ {"key": "geraete", "label": {"de": "Geräte", "en": "Devices"}, "icon": "devices", "view": "geraet.list", "order": 1}, {"key": "faellig", "label": {"de": "Fällige Rückgaben", "en": "Due returns"}, "icon": "assignment_late", "view": "faellig", "order": 2} ], "actions": [ {"key": "ausleihen", "entity": "geraet", "type": "update", "label": {"de": "Ausleihen", "en": "Lend"}, "icon": "assignment_ind", "permission": "verleihen", "when": {"field": "status", "in": ["verfuegbar"]}, "set": {"status": "verliehen", "ausgeliehen_an": "{{payload.ausgeliehen_an}}", "rueckgabe_am": "{{payload.rueckgabe_am}}"}}, {"key": "zurueckgeben", "entity": "geraet", "type": "update", "label": {"de": "Zurückgeben", "en": "Return"}, "icon": "assignment_return", "permission": "verleihen", "when": {"field": "status", "in": ["verliehen"]}, "confirm": {"de": "Gerät als zurückgegeben buchen?", "en": "Book the device as returned?"}, "set": {"status": "verfuegbar", "ausgeliehen_an": null, "rueckgabe_am": null}, "aiTool": true} ], "aiTools": {"entities": ["geraet"]}, "assistant": { "instructions": {"de": "Du hilfst bei den Leihgeräten des Teams. Den Status ändern nur die Aktionen „Ausleihen“ und „Zurückgeben“.", "en": "You help with the team's loan equipment. Only the actions Lend and Return change the status."}, "prompts": [ {"view": "geraet.list", "label": {"de": "Wer hat welches Gerät?", "en": "Who has which device?"}, "prompt": {"de": "Liste alle verliehenen Geräte mit Person und Rückgabedatum.", "en": "List every device on loan with person and due date."}}, {"view": "faellig", "label": {"de": "Erinnerung entwerfen", "en": "Draft a reminder"}, "prompt": {"de": "Entwirf eine freundliche Erinnerung an alle, deren Rückgabe fällig ist.", "en": "Draft a friendly reminder to everyone whose return is due."}} ] }}Warum das Manifest so aussieht
Abschnitt betitelt „Warum das Manifest so aussieht“Einige Entscheidungen in dieser Datei lohnen sich auch für Ihre eigenen Module:
statusistreadonly. Niemand setzt ein Gerät über das Formular auf „verliehen“. Nur die beiden Aktionen ändern den Status, und jede prüft auf dem Server ihr Rechtverleihenund ihrewhen-Bedingung. Ein Formular, das den Wert unverändert zurückschickt, speichert trotzdem.- Ausleihen braucht Eingaben, Zurückgeben nicht. Die Aktion
ausleihenbraucht eine Person und ein Datum. Deshalb läuft sie über die Dialog-Ansichtausleihen-dialog, die beides abfragt und dann die Aktion aufruft. Die Aktionzurueckgebenbraucht nichts und steht direkt in der Aktionsleiste des Datensatzes, mit einer Rückfrage vorab. Welche Einträge die Leiste zeigt, legt die Listeactionsder Datensatz-Ansicht fest. inventarnummerist einesequence. Wird ein Gerät ohne Nummer angelegt, vergibt nexxus die nächste:GER-0001,GER-0002und so weiter. Ein Sequenzfeld ist per Definition eindeutig und schreibgeschützt, und Sie können danach sortieren.- Jedes Filter- und Sortierfeld ist indiziert.
kategorie,statusundrueckgabe_amtragen"indexed": true. Verweise wieausgeliehen_ansind automatisch indiziert. Wer nach einem nicht indizierten Feld filtert oder sortiert, bekommt das Paket beim Hochladen zurück. - Der KI-Assistent kann mit Geräten arbeiten.
aiTools.entitiesgibt ihm Werkzeuge zum Suchen und Lesen vongeraetund die Aktionen zum Anlegen und Ändern (acme.leihgeraete:geraet.create,acme.leihgeraete:geraet.update)."aiTool": trueanzurueckgebenergänzt die Aktionacme.leihgeraete:zurueckgeben. Ausführen tut der KI-Assistent keine Aktion selbst: Er schlägt sie als Karte im Chat vor, und erst der Klick der Person führt sie aus.
Alle Felder und Optionen finden Sie unter Paketaufbau.
Den Changelog ergänzen
Abschnitt betitelt „Den Changelog ergänzen“Jedes Paket bringt einen Changelog mit einer Überschrift für die eigene Version mit. nexxus zeigt ihn auf der Paketseite und im Dialog zum Aktualisieren.
# Changelog: Leihgeräte
## [1.0.0] - 2026-10-12
- Geräte mit Inventarnummer, Kategorie und Status; ausleihen und zurückgeben mit Rückgabedatum.- Seite „Fällige Rückgaben“.Die Dialog-Ansicht schreiben
Abschnitt betitelt „Die Dialog-Ansicht schreiben“ui/ausleihen.html ist eine eigene Ansicht im Slot record.action. nexxus zeigt sie als Dialog auf der Seite eines Geräts und zeichnet den Kopf des Dialogs selbst. Die Ansicht zeichnet nur die Felder und ihre Schaltfläche. Sie läuft abgeschottet und spricht mit nexxus über das View-SDK window.nx, das schon geladen ist, wenn das erste Skript der Ansicht startet.
<!doctype html><html><head><meta charset="utf-8"></head><body> <div class="nx-stack"> <label class="nx-field"> <span class="nx-field__label" id="l-person"></span> <select class="nx-select" id="person"></select> </label> <label class="nx-field"> <span class="nx-field__label" id="l-datum"></span> <input class="nx-input" type="date" id="datum"> </label> <div class="nx-row"><span class="nx-spacer"></span><button class="nx-btn nx-btn--primary" id="ok"></button></div> </div> <script> (async () => { const ctx = await nx.ready(); const $ = id => document.getElementById(id); $('l-person').textContent = nx.t({de: 'Ausleihen an', en: 'Lend to'}); $('l-datum').textContent = nx.t({de: 'Rückgabe am', en: 'Due back'}); $('ok').textContent = nx.t({de: 'Ausleihen', en: 'Lend'}); for (const person of await nx.lookup('core:user', {})) { // die ersten 20; mit {q} suchen const option = document.createElement('option'); option.value = String(person.id); option.textContent = person.label; $('person').append(option); } $('ok').onclick = async () => { try { const {record} = await nx.invoke('ausleihen', { recordId: ctx.record.id, payload: {ausgeliehen_an: Number($('person').value), rueckgabe_am: $('datum').value || null}, }); nx.dialog.close(record); } catch (e) { nx.ui.toast(e.message, {kind: 'error'}); } }; })(); </script></body></html>Was hier passiert:
nx.ready()liefert den Kontext. In einem Dialog an einem Datensatz steht inctx.recorddas Fachobjekt und die Id des Geräts.nx.lookup('core:user', {})listet Personen des Mandanten, ohne Suchbegriff die ersten 20. Dienst- und Systemkonten fehlen in der Liste. Ein echter Dialog sucht mit{q}, während die Person tippt.nx.invoke('ausleihen', ...)führt die Aktion als die Person aus, die geklickt hat. nexxus prüft Recht undwhen-Bedingung noch einmal. Lehnt der Server ab, erscheint die Meldung als Hinweis.nx.dialog.close(record)schließt den Dialog. Die Datensatzseite liest das Gerät neu und zeigt den neuen Stand.- Die Beschriftungen kommen aus
nx.t, die Ansicht spricht also die Sprache der Person. Text kommt übertextContentin die Seite, nie überinnerHTML. - Die Klassen
nx-*stammen aus dem UI-Kit, das nexxus in jede Ansicht einsetzt. So sieht der Dialog aus wie der Rest der Anwendung, im hellen wie im dunklen Modus.
Alle Funktionen des SDK stehen unter Ansichten und das View-SDK.
Die Seiten-Ansicht schreiben
Abschnitt betitelt „Die Seiten-Ansicht schreiben“ui/faellig.html ist eine eigene Seite (Slot page). Der Menüeintrag „Fällige Rückgaben“ führt dorthin. Sie sucht verliehene Geräte, deren Rückgabe heute oder früher fällig ist.
<!doctype html><html><head><meta charset="utf-8"><style>body { padding: 16px; }</style></head><body> <p class="nx-muted" id="hint"></p> <div class="nx-list" id="list"></div> <div class="nx-empty" id="empty" hidden><div class="nx-empty__title" id="empty-title"></div></div> <script> (async () => { await nx.ready(); const $ = id => document.getElementById(id); $('hint').textContent = nx.t({de: 'Verliehene Geräte, deren Rückgabe heute oder früher fällig ist.', en: 'Devices on loan due back today or earlier.'}); $('empty-title').textContent = nx.t({de: 'Alles zurück.', en: 'Everything is back.'}); const today = new Date().toLocaleDateString('sv-SE'); // JJJJ-MM-TT in Ortszeit const {items} = await nx.records.search('geraet', { filter: {status: 'verliehen', rueckgabe_am: {to: today}}, sort: 'rueckgabe_am', size: 100, }); $('empty').hidden = items.length > 0; for (const g of items) { const item = document.createElement('button'); item.className = 'nx-list__item'; item.textContent = `${g.title} · ${g.refs?.ausgeliehen_an?.label ?? '-'} · ${g.data.rueckgabe_am}`; item.onclick = () => nx.nav.open({entity: 'geraet', id: g.id}); $('list').append(item); } nx.assistant.setContext({ summary: nx.t({de: `${items.length} fällige Rückgaben`, en: `${items.length} due returns`}), records: items.map(g => ({entity: 'geraet', id: g.id})), }); })(); </script></body></html>Die Suche filtert auf zwei indizierte Felder. Ein Datumsbereich nur mit to schließt diesen Tag ein. g.title ist die bezeichnung des Geräts (sein titleField), und g.refs enthält den Anzeigenamen jeder verwiesenen Person. nx.nav.open öffnet die Seite des Geräts. nx.assistant.setContext sagt dem KI-Assistenten, welche Geräte die Person gerade sieht. Eine Bitte wie „Erinnere sie“ trifft dann die richtigen Leute.
Beispieldaten ergänzen
Abschnitt betitelt „Beispieldaten ergänzen“Beispieldaten sind freiwillig. Setzt der Administrator bei der Installation den Haken Beispieldaten anlegen, legt nexxus diese Zeilen an. Platzhalter füllen Werte ein, die es erst im Zielmandanten gibt.
[ {"key": "thinkpad", "data": {"bezeichnung": "ThinkPad T14", "kategorie": "laptop", "status": "verfuegbar"}}, {"key": "macbook", "data": {"bezeichnung": "MacBook Air", "kategorie": "laptop", "status": "verliehen", "ausgeliehen_an": {"$currentUser": true}, "rueckgabe_am": {"$date": "-2wd"}}}, {"key": "monitor", "data": {"bezeichnung": "Monitor 27 Zoll", "kategorie": "monitor", "status": "verliehen", "ausgeliehen_an": {"$currentUser": true}, "rueckgabe_am": {"$date": "+1w"}}}]{"$currentUser": true}wird zum Administrator, der installiert.{"$date": "-2wd"}liegt zwei Werktage vor dem Installationstag,"+1w"eine Woche danach. Das MacBook ist also immer überfällig, wenn jemand das Modul ausprobiert, der Monitor nie.- Beispieldaten dürfen
statussetzen, obwohl das Feld schreibgeschützt ist: Datendateien schreibt der Installer, keine Person.
Alle Platzhalter beschreibt Daten und Aktualisierungen.
Das Paket bauen
Abschnitt betitelt „Das Paket bauen“-
Öffnen Sie ein Terminal in dem Ordner, in dem
acme.leihgeraete/undmodule-package.mjsliegen. -
Bauen Sie das Archiv:
Terminal-Fenster node module-package.mjs build acme.leihgeraete/1.0.0Das Skript prüft, ob
module.jsondie Angabenkind,keyundversionhat und obCHANGELOG.mddie Überschrift## [1.0.0]enthält. Es schreibtacme.leihgeraete-1.0.0.nxmsamt einer DateiMANIFEST.sha256mit dem Hash jeder Datei und meldet Dateiname,5 Dateien, Größe undunsigniert. -
Wenn Sie möchten, lesen Sie das Archiv zur Kontrolle zurück:
Terminal-Fenster node module-package.mjs verify acme.leihgeraete-1.0.0.nxmGeprüft werden die Hashes und die Changelog-Überschrift. Den Inhalt des Manifests prüft erst nexxus beim Hochladen.
Derselbe Ordner ergibt immer dasselbe Archiv, Byte für Byte.
Hochladen und installieren
Abschnitt betitelt „Hochladen und installieren“-
Melden Sie sich als Administrator an und öffnen Sie AdministrationBetriebModule. Wechseln Sie auf den Reiter Pakete.
-
Klicken Sie auf Paket hochladen (.nxm) und wählen Sie
acme.leihgeraete-1.0.0.nxm. nexxus lädt die Datei hoch und prüft sie. Danach erscheint der Hinweis Leihgeräte 1.0.0 hochgeladen. und die Paketseite öffnet sich. -
Lesen Sie die Karte Was das Paket mitbringt. Für Leihgeräte steht dort:
Zeile Inhalt Fachobjekte Gerät Menüeinträge Geräte, Fällige Rückgaben Ansichten Geräte · Liste, Daten · Datenreiter, Ausleihen · Dialog am Datensatz, Fällige Rückgaben · Seite Rollen Geräteverwaltung, Einsicht, jeweils mit ihren Rechten Daten außerhalb des Pakets keine Externe Dienste keine Werkzeuge für den Assistenten nx_acme_leihgeraete_geraet_search,_get,acme.leihgeraete:geraet.create,.updateundacme.leihgeraete:zurueckgebenRechte Geräte lesen ( acme.leihgeraete.geraet.read), Geräte bearbeiten (acme.leihgeraete.geraet.write), Geräte verleihen (acme.leihgeraete.verleihen)Weil das Paket nicht signiert ist, steht darüber ein gelber Hinweis: Nicht signiert. Prüfen Sie die Herkunft, bevor Sie es installieren.

Was das Tutorial-Paket mitbringt, gelesen aus seinem Manifest. -
Klicken Sie in der Aktionsleiste auf Installieren. Der Dialog Leihgeräte installieren öffnet sich. Unter Ihre Zustimmung steht Das Paket nutzt keine Daten außerhalb seiner eigenen., denn Leihgeräte fragt weder nach Kerndaten noch nach einem externen Dienst.
-
Wählen Sie unter Rollen zuweisen die Personen für jede Rolle und bestätigen Sie jede Auswahl mit Anwenden. Bei Brandt & Söhne bekommt Tom Keller aus der IT die Rolle Geräteverwaltung und Mia Schulz die Rolle Einsicht. Sie können beide Felder leer lassen und die Rollen später im Rolleneditor vergeben.
-
Setzen Sie den Haken bei Beispieldaten anlegen und klicken Sie auf Installieren. Der Hinweis Leihgeräte ist installiert. bestätigt es.

Keine Daten außerhalb der eigenen, also gibt es nichts zuzustimmen.
Ausprobieren
Abschnitt betitelt „Ausprobieren“-
Öffnen Sie in der linken Leiste den Bereich Organisation. Unter den eingebauten Abschnitten steht jetzt ein neuer Abschnitt Leihgeräte mit den Einträgen Geräte und Fällige Rückgaben. Neu laden müssen Sie dafür nicht.

Das Modul erscheint ohne Neuladen im Menü. -
Klicken Sie auf Geräte (Route
/x/acme.leihgeraete/geraet). Die Liste zeigt die drei Beispielgeräte mit Nummern abGER-0001, das Suchfeld Geräte durchsuchen, die Menüs Filter (Kategorie, Status, Person) und Sortieren und die Schaltfläche Gerät anlegen.
Die Liste entsteht aus der Listenansicht im Manifest. -
Klicken Sie auf Gerät anlegen. Der Reiter Daten zeigt die Abschnitte Gerät und Ausleihe. Bei der Inventarnummer steht Wird beim Anlegen vergeben. Tragen Sie eine Bezeichnung ein und klicken Sie auf Anlegen.
-
Klicken Sie am neuen Gerät in der Aktionsleiste auf Ausleihen. Der Dialog aus
ausleihen.htmlöffnet sich. Wählen Sie eine Person, etwa Mia Schulz, und ein Datum und klicken Sie auf Ausleihen. Der Dialog schließt sich, der Status zeigt Verliehen, und die Aktionsleiste bietet jetzt Zurückgeben an.
Der Dialog ist eine eigene Ansicht; den Kopf zeichnet nexxus. -
Klicken Sie auf Zurückgeben. nexxus fragt Gerät als zurückgegeben buchen?. Klicken Sie auf Ausführen. Der Hinweis lautet „Zurückgeben“ ausgeführt.
-
Öffnen Sie Fällige Rückgaben (Route
/x/acme.leihgeraete/p/faellig). Das Beispiel-MacBook steht dort, weil sein Rückgabedatum zwei Werktage zurückliegt.
Eine eigene Seite, die Geräte mit fälliger Rückgabe sucht. -
Öffnen Sie den KI-Assistenten auf der Geräteliste. Die Beispiel-Anweisung Wer hat welches Gerät? erscheint als Chip. Bitten Sie den KI-Assistenten, das MacBook als zurückgegeben zu buchen: Bevor sich etwas ändert, zeigt der Chat eine Aktionskarte mit den drei Prüfungen Eingaben, Zustand und Berechtigung und der Schaltfläche Ausführen. Geprüft hat der Server schon; eine rote Prüfung nennt, was fehlt, und die Schaltfläche bleibt aus. Je nach Formulierung wählt der KI-Assistent auch eine andere Aktion des Moduls, etwa das Ändern des Geräts; die Karte zeigt dann diese. Bitten Sie um zwei Änderungen auf einmal, trägt eine Karte beide, mit Alle 2 ausführen.
Wer keine Administratorrolle hat, sieht das Modul erst mit einer seiner Rollen: Geräteverwaltung für alles, Einsicht zum Lesen. Mehr dazu unter Rollen.
Version 1.1.0 ausliefern
Abschnitt betitelt „Version 1.1.0 ausliefern“Brandt & Söhne wünscht sich zwei Änderungen: „Telefon“ soll „Smartphone“ heißen, und jedes Gerät braucht einen Standort. Eine ausgelieferte Version ändert sich nie. Deshalb legen Sie Version 1.1.0 daneben an.
-
Kopieren Sie den Ordner
acme.leihgeraete/1.0.0nachacme.leihgeraete/1.1.0. -
Setzen Sie in der Kopie von
module.jsonden Wert"version": "1.1.0". Ersetzen Sie im Feldkategorieden Werttelefondurch:{"key": "smartphone", "label": {"de": "Smartphone", "en": "Smartphone"}} -
Fügen Sie hinter
statusein neues Feld ein und nehmen Sie"standort"in diefieldsdes Abschnittsgeraetingeraet.recordauf:{"key": "standort", "type": "enum", "indexed": true, "default": "buero", "label": {"de": "Standort", "en": "Location"},"values": [{"key": "buero", "label": {"de": "Büro", "en": "Office"}},{"key": "homeoffice", "label": {"de": "Homeoffice", "en": "Home office"}}]} -
Sagen Sie nexxus, wie die gespeicherten Daten umziehen. Ergänzen Sie auf oberster Ebene von
module.json:"migrations": {"1.1.0": {"pre": [{"op": "renameValue", "entity": "geraet", "field": "kategorie", "from": "telefon", "to": "smartphone"}],"post": [{"op": "setDefault", "entity": "geraet", "field": "standort", "value": "buero"}]}}pre-Schritte laufen, bevor nexxus auf die neue Version umschaltet,post-Schritte danach.renameValuemacht aus jedem gespeichertentelefoneinsmartphone.setDefaultgibt jedem vorhandenen Gerät den Standortbuero. -
Stellen Sie in
CHANGELOG.mdeinen neuen Abschnitt nach oben:## [1.1.0] - 2026-10-19- Kategorie „Telefon“ heißt jetzt „Smartphone“; bestehende Geräte werden umgestellt.- Neues Feld Standort (Büro oder Homeoffice); bestehende Geräte stehen im Büro. -
Bauen Sie mit
node module-package.mjs build acme.leihgeraete/1.1.0und laden Sieacme.leihgeraete-1.1.0.nxmauf dem Reiter Pakete hoch. -
Die Paketseite zeigt den Chip Update auf 1.1.0. Klicken Sie auf Auf 1.1.0 aktualisieren. Der Dialog Leihgeräte aktualisieren zeigt Von 1.0.0 auf 1.1.0, unter Was sich ändert den neuen Changelog-Abschnitt und unter Datenanpassungen einen Probelauf auf den heutigen Daten:
renameValueaufgeraet.kategorie(vor dem Wechsel) undsetDefaultaufgeraet.standort(nach dem Wechsel), jeweils mit der Zahl der Datensätze, die sich ändern. Mit nur den Beispieldaten sind das 0 und 3, dazu das Gerät, das Sie selbst angelegt haben. Einen Abschnitt Neu zuzustimmen gibt es nicht, denn 1.1.0 verlangt keinen neuen Datenzugriff.
Der Probelauf zählt die Datensätze, die jeder Schritt ändert. -
Klicken Sie auf Aktualisieren. Der Hinweis lautet Leihgeräte ist auf 1.1.0 aktualisiert.
Nicht jede Änderung ist in einer Nebenversion erlaubt. Hätten Sie standort zur Pflicht gemacht, ohne einen Standardwert anzugeben, hätte der Dialog abgelehnt: Das neue Pflichtfeld ‘geraet.standort’ hat keinen Standardwert. Die Regeln stehen unter Daten und Aktualisierungen.
Was im Hintergrund passiert
Abschnitt betitelt „Was im Hintergrund passiert“Beim Hochladen entpackt nexxus das Archiv und prüft module.json gegen das Paketschema. Danach folgen die Regeln, die ein Schema nicht ausdrücken kann: Jede Spalte, jeder Filter, jeder Abschnitt und jede Aktion nennt ein vorhandenes Feld, Menüeinträge zeigen auf Listen oder Seiten, Rollen nennen vorhandene Rechte, und jede Datei, die das Manifest nennt, liegt im Archiv. nexxus meldet alle Probleme auf einmal. Zuletzt prüft es MANIFEST.sha256 und die Signatur. Gespeichert wird das Paket nur für Ihren Mandanten.
Bei der Installation erledigt nexxus in einer Transaktion:
- Es legt die Installation mit dem Stand Aktiv an und hält Ihre Zustimmung fest.
- Es legt je Manifest-Rolle eine Zugriffsrolle an, benannt nach Modul und Rolle: Leihgeräte – Geräteverwaltung und Leihgeräte – Einsicht. Die gewählten Personen bekommen sie sofort.
- Es legt aus
assistant.instructionseinen firmenweiten Skill für den KI-Assistenten an, Leihgeräte: Arbeitsweise. - Es schreibt die Beispieldaten, löst die Platzhalter auf und vergibt die Inventarnummern.
Nach dem Abschluss stehen Menü, Routen und die Werkzeuge des KI-Assistenten allen zur Verfügung, die die nötigen Rechte haben. Im Rolleneditor erscheinen die Rechte als Geräte lesen, Geräte bearbeiten und Geräte verleihen.
Im Betrieb laufen jede Liste, jedes Formular und jede Aktion durch dieselben Prüfungen auf dem Server, egal ob eine Person klickt, eine Ansicht das SDK aufruft oder der KI-Assistent ein Werkzeug benutzt. Die Ansichten laufen abgeschottet, ohne Netzwerkzugriff und ohne Zugriff auf die Seite um sie herum.
Beim Aktualisieren laufen die pre-Schritte, der Wechsel auf 1.1.0 und die post-Schritte in einer Transaktion. Scheitert ein Schritt, wird alles zurückgerollt, und das Modul bleibt auf 1.0.0. Rollen, die es schon in 1.0.0 gab, bekommen die Rechte, die in 1.1.0 neu sind. Rechte, die ein Administrator entfernt hat, bleiben entfernt.
Wenn etwas schiefgeht
Abschnitt betitelt „Wenn etwas schiefgeht“Lehnt nexxus ein Paket ab, zeigt der Katalog „acme.leihgeraete-1.0.0.nxm“ wurde nicht angenommen. mit dem Grund des Servers und einer Zeile je Problem. Diese Meldungen begegnen Ihnen beim Bauen am häufigsten:
| Meldung | Ursache und Lösung |
|---|---|
module.json menu.faellig: nur Listen und Seiten (slot page) gehören ins Menü | Ein Menüeintrag zeigt auf eine Ansicht, die weder eine list noch eine custom-Ansicht mit Slot page ist. Verweisen Sie auf eine solche Ansicht. |
module.json views.geraet.list: Filter 'notiz' ist nicht indexed | Sie filtern oder sortieren nach einem Feld ohne "indexed": true. Ergänzen Sie die Angabe. Felder vom Typ text und json lassen sich nicht indizieren. |
module.json views.geraet.list: sort 'bezeichnung' ist nicht indexed | Dasselbe für die Sortierung der Liste. |
module.json entities.geraet: searchFields 'rueckgabe_am' muss Text sein | Suchfelder müssen vom Typ string, text oder enum sein. |
CHANGELOG.md: keine Überschrift '## [1.0.0]' für die Version aus module.json | Der Changelog hat keine Überschrift für die Version aus dem Manifest. Ergänzen Sie ## [1.0.0]. Das Skript bricht schon vorher ab mit CHANGELOG.md: Überschrift "## [1.0.0]" fehlt. |
module.json: area 'lager' ist kein Menübereich (...) | area muss einer der Fachbereiche sein, die die Meldung aufzählt. |
Das Archiv enthält kein module.json. | module.json liegt weder ganz oben im Archiv noch in einem einzigen obersten Ordner. Bauen Sie mit dem Skript oder packen Sie den Versionsordner selbst. |
Das Paket ist nicht signiert. Unsignierte Pakete sind auf dieser Plattform nicht zugelassen. | Die Instanz nimmt keine unsignierten Pakete an. Signieren Sie das Paket, siehe Paketieren, installieren und aktualisieren. |
acme.leihgeraete 1.0.0 gibt es schon mit anderem Inhalt; eine neue Fassung braucht eine neue Versionsnummer. | Sie haben Dateien einer Version geändert, die schon hochgeladen war. Ausgelieferte Versionen sind unveränderlich: Erhöhen Sie die Versionsnummer in module.json und im Changelog, mit einem neuen Versionsordner oder, in einem Paketordner mit Git-Tags, mit einem neuen Tag. Dieselbe Datei noch einmal hochzuladen ist kein Problem. |
Fehler im Betrieb:
- Mia Schulz hat nur die Rolle Einsicht, öffnet den Dialog Ausleihen und bekommt den Hinweis
Keine Berechtigung: Ihnen fehlt das Recht 'acme.leihgeraete.verleihen'.Eigene Ansichten sieht jeder, der das Fachobjekt lesen darf, und sie kennen die Rechte der Person noch nicht. Der Server lehnt die Aktion ab. Geben Sie Mia Schulz die Rolle Geräteverwaltung, oder nehmen Sie hin, dass Lesende die Schaltfläche sehen. - Der Menüabschnitt fehlt: Die Person hat keine Rolle des Moduls, oder das Modul ist deaktiviert. Administratoren sehen ihn immer, solange das Modul aktiv ist. Das Abschalten des Fachbereichs
projekteverbirgt ihn nicht.