Direkt zum Hauptinhalt

Lösungspaket

Schema-ID: solution-package@1 Maschinenlesbares Schema: solution-package.schema.json

Die maßgebliche Klartextdarstellung einer exportierten Lösung. Ein Lösungspaket ist die Einheit, mit der Arbeit von einer Umgebung in die nächste übertragen wird: Es entsteht durch den Export einer Lösung aus einer Quellumgebung und wird durch den Import in eine Zielumgebung verarbeitet. Das Paket ist selbstbeschreibend – es enthält sowohl das Manifest (welche Komponenten die Lösung umfasst) als auch die eingebetteten maßgeblichen Definitionen jeder modellgesteuerten Komponente, sodass ein Import echte Tabellen, Formulare, Ansichten und Plug-in-Schritte neu erstellt statt ins Leere zeigender Verweise.

Die Validierung wird für jede Herkunft identisch durchgesetzt: Ein Paket, das vom Exportwerkzeug gebaut, per API-Aufruf übermittelt oder von einem KI-Assistenten generiert wurde, wird gegen genau dieses Schema validiert, bevor die Bereitstellungspipeline die Zielumgebung anrührt. Eine handgeschriebene oder generierte Datei, die diesem Schema entspricht, kann gefahrlos importiert werden.

Aufbau​

Ein Paket ist ein JSON-Objekt mit diesen Membern:

FeldTypPflichtHinweise
formatVersionintegerjaDie Version des Paketformats. Derzeit 1.
publisherNamestringjaDer Anzeigename des besitzenden Herausgebers.
publisherPrefixstringjaDas kurze Präfix des Herausgebers in Kleinbuchstaben (z. B. par). Wird beim Import neu angelegt, wenn es im Zielmandanten fehlt.
solutionNamestringjaDer Name der Lösung.
versionstringjaSemantische Version major.minor.patch (z. B. 1.0.0).
descriptionstring | nullneinOptionale Beschreibung der Lösung.
requiresarray | nullneinDie Lösungen, auf denen diese aufbaut: { solutionName, minVersion? }. Vor jedem Schreiben gegen die Zielumgebung geprüft; eine fehlende oder ältere lehnt den Import ab.
componentsarrayjaDas Manifest: ein Eintrag pro Komponente (Typ + logischer Name).
modelComponentsobjectjaDie eingebetteten maßgeblichen Definitionen, nach Typ gruppiert.
customAppsarray | nullneinEingebettete Manifeste benutzerdefinierter Apps. Optional, damit Pakete, die vor der Einführung benutzerdefinierter Apps erstellt wurden, weiterhin gültig sind; jedes Element wird bei der Materialisierung zusätzlich gegen custom-app-manifest@1 validiert.
webResourcesarray | nullneinEingebettete Webressourcen (Abschnitt 6.15): in der Datenbank gespeicherte Anwendungsdateien, jeweils mit ihrem content (UTF-8-Text für Texttypen, Base64 für Binärdaten). Optional, damit ältere Pakete weiterhin gültig sind; die Metadaten jedes Elements werden bei der Materialisierung erneut gegen web-resource-manifest@1 validiert und sein Inhalt per Hash geprüft.
customControlsarray | nullneinEingebettete benutzerdefinierte Steuerelemente (§28), jeweils mit ihrem vollständigen Build-Archiv in Base64-Kodierung, sodass der Code eines Steuerelements mit der Lösung wandert, statt von einem externen Host abgerufen zu werden. Das Manifest jedes Elements wird bei der Materialisierung zusätzlich gegen custom-control-manifest@1 validiert und sein Archiv gegen den deklarierten contentHash geprüft – der Punkt, an dem sich zeigt, dass der geprüfte Code und der ausgeführte Code derselbe sind.

Manifestkomponente (components[])​

FeldTypPflichtHinweise
componentTypestringjaEiner von Entity, Form, View, App, CustomApp, CustomControl, Process, Report, WebResource, PolicyDefinition, SecurityRole, SavedQuery, Dashboard, BusinessRule, Script. (App ist die Sitemap einer modellgesteuerten App; CustomApp ist eine handgeschriebene React-App.)
logicalNamestringjaMit Herausgeberpräfix; Kleinbuchstaben, wobei _, ., /, - für pfadartige Namen von Webressourcen zulässig sind (z. B. par_invoice, par_/dashboard/app.js).
componentReferenceIdstring | nullneinDie eigene ID der Komponente in ihrem Subsystem, falls vorhanden.

Eingebettete Definitionen (modelComponents)​

Ein Objekt mit Arrays von Komponentendefinitionseinträgen – entities, forms, views, pluginSteps und das optionale apps (modellgesteuerte Apps). Die Reihenfolge drückt Abhängigkeiten aus: Zuerst werden Tabellen materialisiert, dann Formulare/Ansichten/Plug-in-Schritte, dann Apps (deren Navigation Tabellen per logischem Namen referenziert). apps ist optional, damit ein Paket, das erstellt wurde, bevor Apps mitreisten, weiterhin gültig ist und importiert werden kann.

seedData (optional) ist die einzige Liste, deren Einträge Zeilen statt Definitionen sind: ein seed-data@1-Dokument pro Tabelle – der logische Name der Tabelle sowohl in logicalName als auch in entity –, das die Zeilen enthält, die die Seed-Data-Ansicht der Tabelle beim Export geliefert hat. Ein Import materialisiert es ganz zuletzt und fügt jede Zeile per id über den gewöhnlichen Schreibpfad für Datensätze ein oder aktualisiert sie (Upsert); dabei werden nur die Spalten geschrieben, die die Zeile enthält, und nie etwas gelöscht. Eine Zeile, die das Ziel abweist, wird übersprungen und in den Statusdetails des Imports genannt. Siehe Seed-Daten mit einer Lösung ausliefern.

FeldTypPflichtHinweise
logicalNamestringjaDer logische Name der Komponente.
entitystringjaDer logische Name der besitzenden Tabelle (bei einer Tabelle deren eigener Name).
jsonstringjaDie maßgebliche JSON-Definition der Komponente (eine Tabellendefinition, ein Formular, eine Ansicht oder ein Plug-in-Schritt-Rahmen – jeweils bei der Materialisierung gegen das eigene Schema validiert).
isDefaultbooleanneinFür Formulare/Ansichten: ob dies der Standard der Tabelle ist.

Ein Validierungspfad. Die json-Nutzlast jeder eingebetteten Komponente wird von diesem Paketschema nicht erneut validiert; stattdessen wird jede bei ihrer Materialisierung gegen ihr eigenes veröffentlichtes Schema validiert (zum Beispiel Definition einer modellgesteuerten Tabelle, Formular, Ansicht, Plug-in-Schritt) – dieselbe Prüfung, die beim Speichern in einem Designer erfolgt.

Beispiel​

{
"formatVersion": 1,
"publisherName": "Parsware",
"publisherPrefix": "par",
"solutionName": "Sales",
"version": "1.0.0",
"description": "Core sales entities.",
"components": [
{ "componentType": "Entity", "logicalName": "par_invoice" },
{ "componentType": "Form", "logicalName": "par_invoice_main" }
],
"modelComponents": {
"entities": [
{ "logicalName": "par_invoice", "entity": "par_invoice", "json": "{ ...entity definition... }" }
],
"forms": [
{ "logicalName": "par_invoice_main", "entity": "par_invoice", "json": "{ ...form definition... }", "isDefault": true }
],
"views": [],
"pluginSteps": []
}
}

Wie es verwendet wird​

  • Export liest das Manifest und die tatsächlichen Definitionen aus einer Quellumgebung und erzeugt ein Paket unter GET /solutions/{id}/export?sourceEnvironmentId=….
  • Import validiert das Paket gegen dieses Schema, löst Abhängigkeiten auf (jedes Formular/jede Ansicht/jeder Plug-in-Schritt muss auf eine im Paket enthaltene Tabelle zielen), durchläuft eine etwaige Genehmigungsstufe und materialisiert dann die Komponenten im isolierten Schema der Zielumgebung – unter POST /solution-imports.

Versionierung​

Ältere Schemaversionen werden neben neuen aufbewahrt, sodass bereits bereitgestellte Lösungen weiterhin validiert werden, nachdem sich das Schema weiterentwickelt hat. Eine inkompatible Änderung wird als neue Version (solution-package@2) veröffentlicht, statt diese zu bearbeiten; ein Paket trägt seine eigene formatVersion, sodass die Pipeline eine nicht unterstützte Version abweisen kann.