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:
| Feld | Typ | Pflicht | Hinweise |
|---|---|---|---|
formatVersion | integer | ja | Die Version des Paketformats. Derzeit 1. |
publisherName | string | ja | Der Anzeigename des besitzenden Herausgebers. |
publisherPrefix | string | ja | Das kurze Präfix des Herausgebers in Kleinbuchstaben (z. B. par). Wird beim Import neu angelegt, wenn es im Zielmandanten fehlt. |
solutionName | string | ja | Der Name der Lösung. |
version | string | ja | Semantische Version major.minor.patch (z. B. 1.0.0). |
description | string | null | nein | Optionale Beschreibung der Lösung. |
requires | array | null | nein | Die Lösungen, auf denen diese aufbaut: { solutionName, minVersion? }. Vor jedem Schreiben gegen die Zielumgebung geprüft; eine fehlende oder ältere lehnt den Import ab. |
components | array | ja | Das Manifest: ein Eintrag pro Komponente (Typ + logischer Name). |
modelComponents | object | ja | Die eingebetteten maßgeblichen Definitionen, nach Typ gruppiert. |
customApps | array | null | nein | Eingebettete 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. |
webResources | array | null | nein | Eingebettete 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. |
customControls | array | null | nein | Eingebettete 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[])
| Feld | Typ | Pflicht | Hinweise |
|---|---|---|---|
componentType | string | ja | Einer 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.) |
logicalName | string | ja | Mit Herausgeberpräfix; Kleinbuchstaben, wobei _, ., /, - für pfadartige Namen von Webressourcen zulässig sind (z. B. par_invoice, par_/dashboard/app.js). |
componentReferenceId | string | null | nein | Die 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.
| Feld | Typ | Pflicht | Hinweise |
|---|---|---|---|
logicalName | string | ja | Der logische Name der Komponente. |
entity | string | ja | Der logische Name der besitzenden Tabelle (bei einer Tabelle deren eigener Name). |
json | string | ja | Die 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). |
isDefault | boolean | nein | Fü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.