@xrmforge/typegen 0.8.3 → 0.8.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/MIGRATION.md +194 -194
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/docs/architecture/00-README.md +26 -26
- package/docs/architecture/01-executive-summary.md +11 -11
- package/docs/architecture/02-packages.md +110 -110
- package/docs/architecture/03-generated-types.md +172 -172
- package/docs/architecture/04-cli.md +58 -58
- package/docs/architecture/05-build.md +50 -50
- package/docs/architecture/06-incremental.md +42 -42
- package/docs/architecture/07-http-client.md +59 -59
- package/docs/architecture/08-authentication.md +18 -18
- package/docs/architecture/09-testing.md +55 -55
- package/docs/architecture/10-eslint-plugin.md +82 -82
- package/docs/architecture/11-agent-md.md +38 -38
- package/docs/architecture/12-xrm-pitfalls.md +14 -14
- package/docs/architecture/13-helpers.md +50 -50
- package/docs/architecture/14-showcases.md +21 -21
- package/docs/architecture/15-ci-cd.md +49 -49
- package/docs/architecture/16-technical-debt.md +17 -17
- package/docs/architecture/17-roadmap.md +25 -25
- package/docs/architecture/18-design-principles.md +22 -22
- package/docs/architektur/00-README.md +26 -26
- package/docs/architektur/01-zusammenfassung.md +11 -11
- package/docs/architektur/02-packages.md +110 -110
- package/docs/architektur/03-generierte-typen.md +172 -172
- package/docs/architektur/04-cli.md +58 -58
- package/docs/architektur/05-build.md +50 -50
- package/docs/architektur/06-inkrementell.md +42 -42
- package/docs/architektur/07-http-client.md +59 -59
- package/docs/architektur/08-authentifizierung.md +18 -18
- package/docs/architektur/09-testing.md +55 -55
- package/docs/architektur/10-eslint-plugin.md +82 -82
- package/docs/architektur/11-agent-md.md +38 -38
- package/docs/architektur/12-xrm-fallstricke.md +14 -14
- package/docs/architektur/13-helpers.md +50 -50
- package/docs/architektur/14-showcases.md +21 -21
- package/docs/architektur/15-ci-cd.md +49 -49
- package/docs/architektur/16-technische-schulden.md +17 -17
- package/docs/architektur/17-roadmap.md +25 -25
- package/docs/architektur/18-designprinzipien.md +22 -22
- package/package.json +1 -1
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
# XrmForge Architektur
|
|
2
|
-
|
|
3
|
-
> **Status:** Lebendes Dokument, das den aktuellen Implementierungsstand beschreibt.
|
|
4
|
-
> **Letztes Update:** 2026-04-04 (Session 10)
|
|
5
|
-
> **Version:** 7 Packages, 666+ Tests über alle Packages.
|
|
6
|
-
|
|
7
|
-
## Kapitel
|
|
8
|
-
|
|
9
|
-
1. [Zusammenfassung](01-zusammenfassung.md)
|
|
10
|
-
2. [Package-Architektur](02-packages.md)
|
|
11
|
-
3. [Generierte Typen](03-generierte-typen.md)
|
|
12
|
-
4. [CLI-Befehle](04-cli.md)
|
|
13
|
-
5. [Build-Architektur](05-build.md)
|
|
14
|
-
6. [Inkrementelle Generierung](06-inkrementell.md)
|
|
15
|
-
7. [HTTP-Client](07-http-client.md)
|
|
16
|
-
8. [Authentifizierung](08-authentifizierung.md)
|
|
17
|
-
9. [Test-Framework](09-testing.md)
|
|
18
|
-
10. [ESLint-Plugin](10-eslint-plugin.md)
|
|
19
|
-
11. [AGENT.md-System](11-agent-md.md)
|
|
20
|
-
12. [@types/xrm-Fallstricke](12-xrm-fallstricke.md)
|
|
21
|
-
13. [@xrmforge/helpers Package](13-helpers.md)
|
|
22
|
-
14. [Showcases](14-showcases.md)
|
|
23
|
-
15. [CI/CD](15-ci-cd.md)
|
|
24
|
-
16. [Technische Schulden](16-technische-schulden.md)
|
|
25
|
-
17. [Roadmap](17-roadmap.md)
|
|
26
|
-
18. [Designprinzipien](18-designprinzipien.md)
|
|
1
|
+
# XrmForge Architektur
|
|
2
|
+
|
|
3
|
+
> **Status:** Lebendes Dokument, das den aktuellen Implementierungsstand beschreibt.
|
|
4
|
+
> **Letztes Update:** 2026-04-04 (Session 10)
|
|
5
|
+
> **Version:** 7 Packages, 666+ Tests über alle Packages.
|
|
6
|
+
|
|
7
|
+
## Kapitel
|
|
8
|
+
|
|
9
|
+
1. [Zusammenfassung](01-zusammenfassung.md)
|
|
10
|
+
2. [Package-Architektur](02-packages.md)
|
|
11
|
+
3. [Generierte Typen](03-generierte-typen.md)
|
|
12
|
+
4. [CLI-Befehle](04-cli.md)
|
|
13
|
+
5. [Build-Architektur](05-build.md)
|
|
14
|
+
6. [Inkrementelle Generierung](06-inkrementell.md)
|
|
15
|
+
7. [HTTP-Client](07-http-client.md)
|
|
16
|
+
8. [Authentifizierung](08-authentifizierung.md)
|
|
17
|
+
9. [Test-Framework](09-testing.md)
|
|
18
|
+
10. [ESLint-Plugin](10-eslint-plugin.md)
|
|
19
|
+
11. [AGENT.md-System](11-agent-md.md)
|
|
20
|
+
12. [@types/xrm-Fallstricke](12-xrm-fallstricke.md)
|
|
21
|
+
13. [@xrmforge/helpers Package](13-helpers.md)
|
|
22
|
+
14. [Showcases](14-showcases.md)
|
|
23
|
+
15. [CI/CD](15-ci-cd.md)
|
|
24
|
+
16. [Technische Schulden](16-technische-schulden.md)
|
|
25
|
+
17. [Roadmap](17-roadmap.md)
|
|
26
|
+
18. [Designprinzipien](18-designprinzipien.md)
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
# 1. Zusammenfassung
|
|
2
|
-
|
|
3
|
-
XrmForge ist ein quelloffenes TypeScript-Toolkit für typsichere Dynamics 365 / Dataverse WebResource-Entwicklung. Es generiert TypeScript-Deklarationen aus Live-Dataverse-Metadaten und verwandelt Laufzeit-String-Fehler in Kompilierzeit-Typfehler.
|
|
4
|
-
|
|
5
|
-
**Kernnutzenversprechen:** Jeder Feldname, OptionSet-Wert, Tab-Name, Entitätsname und Subgrid-Name wird zu einer typisierten Konstante mit IDE-Autovervollständigung und Kompilierzeit-Validierung.
|
|
6
|
-
|
|
7
|
-
**Zielgruppe:** D365-Entwickler, die Formularskripte (WebResources) in JavaScript/TypeScript schreiben und Kompilierzeit-Sicherheit, null Magic Strings und moderne Werkzeuge (esbuild, vitest, ESLint) wollen.
|
|
8
|
-
|
|
9
|
-
**Technologie-Stack:** TypeScript, pnpm-Monorepo mit Turborepo, esbuild für IIFE-Bundles, vitest für Tests, @azure/identity für Authentifizierung, fast-xml-parser für FormXml-Parsing.
|
|
10
|
-
|
|
11
|
-
**npm-Organisation:** [@xrmforge](https://www.npmjs.com/org/xrmforge)
|
|
1
|
+
# 1. Zusammenfassung
|
|
2
|
+
|
|
3
|
+
XrmForge ist ein quelloffenes TypeScript-Toolkit für typsichere Dynamics 365 / Dataverse WebResource-Entwicklung. Es generiert TypeScript-Deklarationen aus Live-Dataverse-Metadaten und verwandelt Laufzeit-String-Fehler in Kompilierzeit-Typfehler.
|
|
4
|
+
|
|
5
|
+
**Kernnutzenversprechen:** Jeder Feldname, OptionSet-Wert, Tab-Name, Entitätsname und Subgrid-Name wird zu einer typisierten Konstante mit IDE-Autovervollständigung und Kompilierzeit-Validierung.
|
|
6
|
+
|
|
7
|
+
**Zielgruppe:** D365-Entwickler, die Formularskripte (WebResources) in JavaScript/TypeScript schreiben und Kompilierzeit-Sicherheit, null Magic Strings und moderne Werkzeuge (esbuild, vitest, ESLint) wollen.
|
|
8
|
+
|
|
9
|
+
**Technologie-Stack:** TypeScript, pnpm-Monorepo mit Turborepo, esbuild für IIFE-Bundles, vitest für Tests, @azure/identity für Authentifizierung, fast-xml-parser für FormXml-Parsing.
|
|
10
|
+
|
|
11
|
+
**npm-Organisation:** [@xrmforge](https://www.npmjs.com/org/xrmforge)
|
|
@@ -1,110 +1,110 @@
|
|
|
1
|
-
# 2. Package-Architektur
|
|
2
|
-
|
|
3
|
-
## 2.1 Package-Übersicht
|
|
4
|
-
|
|
5
|
-
| Package | Version | Tests | Beschreibung |
|
|
6
|
-
|---------|---------|-------|--------------|
|
|
7
|
-
| @xrmforge/typegen | 0.8.0 | 444 | Kern: Typgenerierungs-Engine, Metadaten-Client, HTTP-Client, Hilfsfunktionen |
|
|
8
|
-
| @xrmforge/cli | 0.4.2 | 10 | CLI: generate-, build-, init-Befehle |
|
|
9
|
-
| @xrmforge/testing | 0.2.0 | 76 | Test-Hilfsmittel: createFormMock, fireOnChange, setupXrmMock |
|
|
10
|
-
| @xrmforge/helpers | 0.1.0 | 59 | Browsersichere Laufzeit: select(), parseLookup(), typedForm(), Xrm-Konstanten, Action-Executors |
|
|
11
|
-
| @xrmforge/webapi | 0.1.0 | 45 | Typsicherer Xrm.WebApi-Client mit QueryBuilder |
|
|
12
|
-
| @xrmforge/devkit | 0.4.0 | 42 | Build-Orchestrierung, Scaffolding, AGENT.md-Generierung |
|
|
13
|
-
| @xrmforge/eslint-plugin | 0.2.0 | 32 | 5 D365-spezifische ESLint-Regeln |
|
|
14
|
-
|
|
15
|
-
**Gesamt:** 708 Tests über 7 Packages.
|
|
16
|
-
|
|
17
|
-
## 2.2 Abhängigkeitsgraph
|
|
18
|
-
|
|
19
|
-
```
|
|
20
|
-
@xrmforge/cli
|
|
21
|
-
|-- @xrmforge/typegen (generate-Befehl)
|
|
22
|
-
|-- @xrmforge/devkit (build- + init-Befehle)
|
|
23
|
-
'-- commander (CLI-Framework)
|
|
24
|
-
|
|
25
|
-
@xrmforge/typegen
|
|
26
|
-
|-- @azure/identity (Authentifizierung)
|
|
27
|
-
'-- fast-xml-parser (FormXml-Parsing)
|
|
28
|
-
|
|
29
|
-
@xrmforge/devkit
|
|
30
|
-
'-- esbuild (IIFE-Bundling)
|
|
31
|
-
|
|
32
|
-
@xrmforge/testing (keine Laufzeit-Abhängigkeiten)
|
|
33
|
-
@xrmforge/helpers (keine Laufzeit-Abhängigkeiten)
|
|
34
|
-
@xrmforge/webapi (keine Laufzeit-Abhängigkeiten)
|
|
35
|
-
@xrmforge/eslint-plugin (ESLint Peer-Abhängigkeit)
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## 2.3 Package-Details
|
|
39
|
-
|
|
40
|
-
### @xrmforge/typegen
|
|
41
|
-
|
|
42
|
-
Das Kern-Package. Enthält:
|
|
43
|
-
|
|
44
|
-
- **TypeGenerationOrchestrator** - Koordiniert die gesamte Generierungs-Pipeline
|
|
45
|
-
- **MetadataClient** - Fragt Dataverse-Metadaten ab (Entitäten, Formulare, OptionSets, Custom APIs)
|
|
46
|
-
- **DataverseHttpClient** - Belastbarer REST-Client mit Retry, Rate Limiting, Nebenläufigkeitssteuerung
|
|
47
|
-
- **ChangeDetector** - Inkrementelle Generierung über RetrieveMetadataChanges
|
|
48
|
-
- **MetadataCache** - Dateisystem-basiertes Caching mit Versionsstempeln
|
|
49
|
-
- **Generators** - Entitäts-Interfaces, Formular-Interfaces, OptionSet-Enums, Fields-Enums, EntityNames, Navigations-Properties, Action/Function-Executors
|
|
50
|
-
- **Helpers** - select(), parseLookup(), parseFormattedValue() (verschoben nach @xrmforge/helpers)
|
|
51
|
-
- **Xrm-Konstanten** - DisplayState, FormNotificationLevel, RequiredLevel, SubmitMode, SaveMode, ClientType, ClientState (verschoben nach @xrmforge/helpers)
|
|
52
|
-
- **Authentifizierung** - createCredential()-Factory für 4 Authentifizierungsmethoden
|
|
53
|
-
- **Logging** - Scope-basierte Logger mit austauschbaren Senken (Console, JSON, Silent)
|
|
54
|
-
- **Fehler** - Strukturierte Fehlerhierarchie mit ErrorCode-Enum (AUTH_1xxx, API_2xxx, META_3xxx, GEN_4xxx, CONFIG_5xxx)
|
|
55
|
-
|
|
56
|
-
### @xrmforge/cli
|
|
57
|
-
|
|
58
|
-
Kommandozeilen-Interface basierend auf commander.js. Drei Befehle:
|
|
59
|
-
- `xrmforge generate` - Orchestriert den TypeGenerationOrchestrator
|
|
60
|
-
- `xrmforge build` - Delegiert an devkit build()
|
|
61
|
-
- `xrmforge init` - Delegiert an devkit scaffoldProject()
|
|
62
|
-
|
|
63
|
-
### @xrmforge/testing
|
|
64
|
-
|
|
65
|
-
FormContext-Mocking für Unit-Tests:
|
|
66
|
-
- `createFormMock<TForm>(values)` - Erstellt einen vollständigen Mock aus einfachen Schlüssel-Wert-Paaren
|
|
67
|
-
- `MockAttribute` - getValue/setValue, Dirty-Tracking, onChange-Handler, Required Level, Submit Mode
|
|
68
|
-
- `MockControl` - Sichtbar, Deaktiviert, Label, Benachrichtigungen
|
|
69
|
-
- `MockUi` - Formular-Benachrichtigungen, Tab/Section-Stubs
|
|
70
|
-
- `MockEntity` - Entitäts-ID, Name, Primärattribut
|
|
71
|
-
- `fireOnChange(fieldName)` - Löst registrierte onChange-Handler aus
|
|
72
|
-
- `setupXrmMock(options)` / `teardownXrmMock()` - Globaler Xrm-Mock mit WebApi/Navigation-Stubs
|
|
73
|
-
|
|
74
|
-
### @xrmforge/helpers
|
|
75
|
-
|
|
76
|
-
Bündelt allen browsersicheren Laufzeitcode. Keine Node.js-Abhängigkeiten. Enthält:
|
|
77
|
-
- **Web-API-Helpers** - select(), parseLookup(), parseFormattedValue()
|
|
78
|
-
- **Xrm-Konstanten** - DisplayState, SubmitMode, RequiredLevel, SaveMode, ClientType, ClientState, FormNotificationLevel, OperationType
|
|
79
|
-
- **Action/Function-Executors** - createBoundAction(), executeRequest(), withProgress()
|
|
80
|
-
- **typedForm()-Proxy** - Proxy-basierter FormContext-Wrapper, bei dem `form.name` an `getAttribute('name')` delegiert
|
|
81
|
-
|
|
82
|
-
### @xrmforge/webapi
|
|
83
|
-
|
|
84
|
-
Typsicherer Wrapper um Xrm.WebApi:
|
|
85
|
-
- `retrieve<T>(entityName, id, query)` - Einzelner Datensatz
|
|
86
|
-
- `retrieveMultiple<T>(entityName, query, options)` - Mit Paginierung (maxPages)
|
|
87
|
-
- `create(entityName, data)` - Gibt Datensatz-ID zurück
|
|
88
|
-
- `update(entityName, id, data)` - Void
|
|
89
|
-
- `remove(entityName, id)` - Void
|
|
90
|
-
- `QueryBuilder` - Fluent API: `.select().filter().orderBy().top().expand().build()`
|
|
91
|
-
- `WebApiError` - Strukturierte Fehler mit statusCode, errorCode, innerMessage
|
|
92
|
-
|
|
93
|
-
### @xrmforge/devkit
|
|
94
|
-
|
|
95
|
-
Build-Orchestrierung und Projekt-Scaffolding:
|
|
96
|
-
- `build(config)` - Parallele esbuild-IIFE-Builds über Promise.allSettled
|
|
97
|
-
- `watch(config)` - esbuild-Watch-Modus mit Rebuild-Callbacks
|
|
98
|
-
- `scaffoldProject(config)` - Generiert 11 Projektdateien aus Vorlagen
|
|
99
|
-
- `validateBuildConfig(config)` / `resolveBuildConfig(config)` - Konfigurationsvalidierung
|
|
100
|
-
- `BuildError` mit Codes: CONFIG_INVALID, ENTRY_NOT_FOUND, BUILD_FAILED, WATCH_ERROR
|
|
101
|
-
- Vorlagensystem: 7 Textvorlagen in `src/scaffold/templates/`, geladen über `template-loader.ts`
|
|
102
|
-
|
|
103
|
-
### @xrmforge/eslint-plugin
|
|
104
|
-
|
|
105
|
-
5 Regeln für D365-Formularskripte (ESLint v9 Flat Config):
|
|
106
|
-
- `no-xrm-page` (error) - Verbietet die veraltete Xrm.Page-API
|
|
107
|
-
- `no-magic-optionset` (warn) - Verbietet Magic Numbers in OptionSet-Vergleichen
|
|
108
|
-
- `no-sync-webapi` (error) - Verbietet synchrone XMLHttpRequest
|
|
109
|
-
- `require-error-handling` (warn) - Verlangt try/catch in asynchronen on*-Event-Handlern
|
|
110
|
-
- `require-namespace` (warn) - Verbietet window/globalThis-Zuweisungen
|
|
1
|
+
# 2. Package-Architektur
|
|
2
|
+
|
|
3
|
+
## 2.1 Package-Übersicht
|
|
4
|
+
|
|
5
|
+
| Package | Version | Tests | Beschreibung |
|
|
6
|
+
|---------|---------|-------|--------------|
|
|
7
|
+
| @xrmforge/typegen | 0.8.0 | 444 | Kern: Typgenerierungs-Engine, Metadaten-Client, HTTP-Client, Hilfsfunktionen |
|
|
8
|
+
| @xrmforge/cli | 0.4.2 | 10 | CLI: generate-, build-, init-Befehle |
|
|
9
|
+
| @xrmforge/testing | 0.2.0 | 76 | Test-Hilfsmittel: createFormMock, fireOnChange, setupXrmMock |
|
|
10
|
+
| @xrmforge/helpers | 0.1.0 | 59 | Browsersichere Laufzeit: select(), parseLookup(), typedForm(), Xrm-Konstanten, Action-Executors |
|
|
11
|
+
| @xrmforge/webapi | 0.1.0 | 45 | Typsicherer Xrm.WebApi-Client mit QueryBuilder |
|
|
12
|
+
| @xrmforge/devkit | 0.4.0 | 42 | Build-Orchestrierung, Scaffolding, AGENT.md-Generierung |
|
|
13
|
+
| @xrmforge/eslint-plugin | 0.2.0 | 32 | 5 D365-spezifische ESLint-Regeln |
|
|
14
|
+
|
|
15
|
+
**Gesamt:** 708 Tests über 7 Packages.
|
|
16
|
+
|
|
17
|
+
## 2.2 Abhängigkeitsgraph
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
@xrmforge/cli
|
|
21
|
+
|-- @xrmforge/typegen (generate-Befehl)
|
|
22
|
+
|-- @xrmforge/devkit (build- + init-Befehle)
|
|
23
|
+
'-- commander (CLI-Framework)
|
|
24
|
+
|
|
25
|
+
@xrmforge/typegen
|
|
26
|
+
|-- @azure/identity (Authentifizierung)
|
|
27
|
+
'-- fast-xml-parser (FormXml-Parsing)
|
|
28
|
+
|
|
29
|
+
@xrmforge/devkit
|
|
30
|
+
'-- esbuild (IIFE-Bundling)
|
|
31
|
+
|
|
32
|
+
@xrmforge/testing (keine Laufzeit-Abhängigkeiten)
|
|
33
|
+
@xrmforge/helpers (keine Laufzeit-Abhängigkeiten)
|
|
34
|
+
@xrmforge/webapi (keine Laufzeit-Abhängigkeiten)
|
|
35
|
+
@xrmforge/eslint-plugin (ESLint Peer-Abhängigkeit)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## 2.3 Package-Details
|
|
39
|
+
|
|
40
|
+
### @xrmforge/typegen
|
|
41
|
+
|
|
42
|
+
Das Kern-Package. Enthält:
|
|
43
|
+
|
|
44
|
+
- **TypeGenerationOrchestrator** - Koordiniert die gesamte Generierungs-Pipeline
|
|
45
|
+
- **MetadataClient** - Fragt Dataverse-Metadaten ab (Entitäten, Formulare, OptionSets, Custom APIs)
|
|
46
|
+
- **DataverseHttpClient** - Belastbarer REST-Client mit Retry, Rate Limiting, Nebenläufigkeitssteuerung
|
|
47
|
+
- **ChangeDetector** - Inkrementelle Generierung über RetrieveMetadataChanges
|
|
48
|
+
- **MetadataCache** - Dateisystem-basiertes Caching mit Versionsstempeln
|
|
49
|
+
- **Generators** - Entitäts-Interfaces, Formular-Interfaces, OptionSet-Enums, Fields-Enums, EntityNames, Navigations-Properties, Action/Function-Executors
|
|
50
|
+
- **Helpers** - select(), parseLookup(), parseFormattedValue() (verschoben nach @xrmforge/helpers)
|
|
51
|
+
- **Xrm-Konstanten** - DisplayState, FormNotificationLevel, RequiredLevel, SubmitMode, SaveMode, ClientType, ClientState (verschoben nach @xrmforge/helpers)
|
|
52
|
+
- **Authentifizierung** - createCredential()-Factory für 4 Authentifizierungsmethoden
|
|
53
|
+
- **Logging** - Scope-basierte Logger mit austauschbaren Senken (Console, JSON, Silent)
|
|
54
|
+
- **Fehler** - Strukturierte Fehlerhierarchie mit ErrorCode-Enum (AUTH_1xxx, API_2xxx, META_3xxx, GEN_4xxx, CONFIG_5xxx)
|
|
55
|
+
|
|
56
|
+
### @xrmforge/cli
|
|
57
|
+
|
|
58
|
+
Kommandozeilen-Interface basierend auf commander.js. Drei Befehle:
|
|
59
|
+
- `xrmforge generate` - Orchestriert den TypeGenerationOrchestrator
|
|
60
|
+
- `xrmforge build` - Delegiert an devkit build()
|
|
61
|
+
- `xrmforge init` - Delegiert an devkit scaffoldProject()
|
|
62
|
+
|
|
63
|
+
### @xrmforge/testing
|
|
64
|
+
|
|
65
|
+
FormContext-Mocking für Unit-Tests:
|
|
66
|
+
- `createFormMock<TForm>(values)` - Erstellt einen vollständigen Mock aus einfachen Schlüssel-Wert-Paaren
|
|
67
|
+
- `MockAttribute` - getValue/setValue, Dirty-Tracking, onChange-Handler, Required Level, Submit Mode
|
|
68
|
+
- `MockControl` - Sichtbar, Deaktiviert, Label, Benachrichtigungen
|
|
69
|
+
- `MockUi` - Formular-Benachrichtigungen, Tab/Section-Stubs
|
|
70
|
+
- `MockEntity` - Entitäts-ID, Name, Primärattribut
|
|
71
|
+
- `fireOnChange(fieldName)` - Löst registrierte onChange-Handler aus
|
|
72
|
+
- `setupXrmMock(options)` / `teardownXrmMock()` - Globaler Xrm-Mock mit WebApi/Navigation-Stubs
|
|
73
|
+
|
|
74
|
+
### @xrmforge/helpers
|
|
75
|
+
|
|
76
|
+
Bündelt allen browsersicheren Laufzeitcode. Keine Node.js-Abhängigkeiten. Enthält:
|
|
77
|
+
- **Web-API-Helpers** - select(), parseLookup(), parseFormattedValue()
|
|
78
|
+
- **Xrm-Konstanten** - DisplayState, SubmitMode, RequiredLevel, SaveMode, ClientType, ClientState, FormNotificationLevel, OperationType
|
|
79
|
+
- **Action/Function-Executors** - createBoundAction(), executeRequest(), withProgress()
|
|
80
|
+
- **typedForm()-Proxy** - Proxy-basierter FormContext-Wrapper, bei dem `form.name` an `getAttribute('name')` delegiert
|
|
81
|
+
|
|
82
|
+
### @xrmforge/webapi
|
|
83
|
+
|
|
84
|
+
Typsicherer Wrapper um Xrm.WebApi:
|
|
85
|
+
- `retrieve<T>(entityName, id, query)` - Einzelner Datensatz
|
|
86
|
+
- `retrieveMultiple<T>(entityName, query, options)` - Mit Paginierung (maxPages)
|
|
87
|
+
- `create(entityName, data)` - Gibt Datensatz-ID zurück
|
|
88
|
+
- `update(entityName, id, data)` - Void
|
|
89
|
+
- `remove(entityName, id)` - Void
|
|
90
|
+
- `QueryBuilder` - Fluent API: `.select().filter().orderBy().top().expand().build()`
|
|
91
|
+
- `WebApiError` - Strukturierte Fehler mit statusCode, errorCode, innerMessage
|
|
92
|
+
|
|
93
|
+
### @xrmforge/devkit
|
|
94
|
+
|
|
95
|
+
Build-Orchestrierung und Projekt-Scaffolding:
|
|
96
|
+
- `build(config)` - Parallele esbuild-IIFE-Builds über Promise.allSettled
|
|
97
|
+
- `watch(config)` - esbuild-Watch-Modus mit Rebuild-Callbacks
|
|
98
|
+
- `scaffoldProject(config)` - Generiert 11 Projektdateien aus Vorlagen
|
|
99
|
+
- `validateBuildConfig(config)` / `resolveBuildConfig(config)` - Konfigurationsvalidierung
|
|
100
|
+
- `BuildError` mit Codes: CONFIG_INVALID, ENTRY_NOT_FOUND, BUILD_FAILED, WATCH_ERROR
|
|
101
|
+
- Vorlagensystem: 7 Textvorlagen in `src/scaffold/templates/`, geladen über `template-loader.ts`
|
|
102
|
+
|
|
103
|
+
### @xrmforge/eslint-plugin
|
|
104
|
+
|
|
105
|
+
5 Regeln für D365-Formularskripte (ESLint v9 Flat Config):
|
|
106
|
+
- `no-xrm-page` (error) - Verbietet die veraltete Xrm.Page-API
|
|
107
|
+
- `no-magic-optionset` (warn) - Verbietet Magic Numbers in OptionSet-Vergleichen
|
|
108
|
+
- `no-sync-webapi` (error) - Verbietet synchrone XMLHttpRequest
|
|
109
|
+
- `require-error-handling` (warn) - Verlangt try/catch in asynchronen on*-Event-Handlern
|
|
110
|
+
- `require-namespace` (warn) - Verbietet window/globalThis-Zuweisungen
|
|
@@ -1,172 +1,172 @@
|
|
|
1
|
-
# 3. Generierte Typen
|
|
2
|
-
|
|
3
|
-
Die Ausführung von `xrmforge generate` erzeugt die folgenden TypeScript-ES-Module:
|
|
4
|
-
|
|
5
|
-
## 3.1 Entitäts-Interfaces (`entities/{entity}.ts`)
|
|
6
|
-
|
|
7
|
-
```typescript
|
|
8
|
-
// generated/entities/account.ts
|
|
9
|
-
/** Account | Konto */
|
|
10
|
-
export interface Account {
|
|
11
|
-
/** Account Name | Kontoname */
|
|
12
|
-
name: string | null;
|
|
13
|
-
accountid: string | null;
|
|
14
|
-
revenue: number | null;
|
|
15
|
-
_parentaccountid_value: string | null; // Lookup GUID
|
|
16
|
-
// ...
|
|
17
|
-
}
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
**Typ-Zuordnung:** String/Memo/EntityName zu `string`, Integer/BigInt/Decimal/Double/Money zu `number`, Boolean zu `boolean`, DateTime/Uniqueidentifier/Lookup zu `string`, Picklist/State/Status zu `number`.
|
|
21
|
-
|
|
22
|
-
## 3.2 Entity Fields Enums (`fields/{entity}.ts`)
|
|
23
|
-
|
|
24
|
-
```typescript
|
|
25
|
-
// generated/fields/account.ts
|
|
26
|
-
export const enum AccountFields {
|
|
27
|
-
/** Account Name | Kontoname */
|
|
28
|
-
Name = 'name',
|
|
29
|
-
Telephone1 = 'telephone1',
|
|
30
|
-
Revenue = 'revenue',
|
|
31
|
-
// alle Entitätsattribute für $select-Abfragen
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export const enum AccountNavigationProperties {
|
|
35
|
-
PrimaryContact = 'primarycontactid',
|
|
36
|
-
ContactCustomerAccounts = 'contact_customer_accounts',
|
|
37
|
-
// alle Lookup-Navigations-Properties
|
|
38
|
-
}
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
Verwendet für Web API `$select`: `select(AccountFields.Name, AccountFields.Revenue)`.
|
|
42
|
-
|
|
43
|
-
## 3.3 Navigations-Properties (`fields/{entity}.ts`)
|
|
44
|
-
|
|
45
|
-
Navigations-Property-Enums befinden sich zusammen mit den Fields-Enums in derselben Datei (siehe 3.2 oben). Beispielverwendung:
|
|
46
|
-
|
|
47
|
-
```typescript
|
|
48
|
-
import { AccountNavigationProperties } from '../generated/fields/account';
|
|
49
|
-
// verwendet für $expand-Abfragen
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
## 3.4 Formular-Interfaces (`forms/{entity}.ts`)
|
|
53
|
-
|
|
54
|
-
```typescript
|
|
55
|
-
// generated/forms/account.ts
|
|
56
|
-
|
|
57
|
-
// Union-Typ, der gültige Feldnamen einschränkt
|
|
58
|
-
export type AccountMainFormFields = 'name' | 'telephone1' | 'revenue';
|
|
59
|
-
|
|
60
|
-
// Gemappter Typ: Feldname zu Xrm-Attributtyp
|
|
61
|
-
export type AccountMainFormAttributeMap = {
|
|
62
|
-
name: Xrm.Attributes.StringAttribute;
|
|
63
|
-
telephone1: Xrm.Attributes.StringAttribute;
|
|
64
|
-
revenue: Xrm.Attributes.NumberAttribute;
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
// Gemappter Typ: Feldname zu Xrm-Steuerelementtyp
|
|
68
|
-
export type AccountMainFormControlMap = {
|
|
69
|
-
name: Xrm.Controls.StringControl;
|
|
70
|
-
telephone1: Xrm.Controls.StringControl;
|
|
71
|
-
revenue: Xrm.Controls.NumberControl;
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
// Fields-Enum für Autovervollständigung
|
|
75
|
-
export const enum AccountMainFormFieldsEnum {
|
|
76
|
-
/** Account Name | Kontoname */
|
|
77
|
-
AccountName = 'name',
|
|
78
|
-
Telephone1 = 'telephone1',
|
|
79
|
-
Revenue = 'revenue',
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Typsicherer FormContext mit überladenen getAttribute/getControl
|
|
83
|
-
export interface AccountMainForm extends Omit<Xrm.FormContext, 'getAttribute' | 'getControl'> {
|
|
84
|
-
getAttribute<K extends AccountMainFormFields>(name: K): AccountMainFormAttributeMap[K];
|
|
85
|
-
getAttribute(index: number): Xrm.Attributes.Attribute;
|
|
86
|
-
getAttribute(): Xrm.Attributes.Attribute[];
|
|
87
|
-
|
|
88
|
-
getControl<K extends AccountMainFormFields>(name: K): AccountMainFormControlMap[K];
|
|
89
|
-
getControl(index: number): Xrm.Controls.Control;
|
|
90
|
-
getControl(): Xrm.Controls.Control[];
|
|
91
|
-
}
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
**Spezielle Steuerelemente** werden anhand ihrer FormXml-ClassID typisiert:
|
|
95
|
-
- Subgrid: `Xrm.Controls.GridControl`
|
|
96
|
-
- Editierbares Grid: `Xrm.Controls.GridControl`
|
|
97
|
-
- Quick View: `Xrm.Controls.QuickFormControl`
|
|
98
|
-
- Web Resource / iFrame: `Xrm.Controls.IframeControl`
|
|
99
|
-
|
|
100
|
-
## 3.5 Tabs/Sections/Subgrids/QuickViews Enums
|
|
101
|
-
|
|
102
|
-
```typescript
|
|
103
|
-
const enum AccountMainFormTabs { Summary = 'SUMMARY_TAB', Details = 'DETAILS_TAB' }
|
|
104
|
-
const enum AccountMainFormSections { General = 'GENERAL', Address = 'ADDRESS' }
|
|
105
|
-
const enum AccountMainFormSubgrids { Contacts = 'Contacts_Subgrid' }
|
|
106
|
-
const enum AccountMainFormQuickViews { ContactPreview = 'ContactQuickView' }
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
## 3.6 OptionSet Enums (`optionsets/{entity}.ts`)
|
|
110
|
-
|
|
111
|
-
```typescript
|
|
112
|
-
// generated/optionsets/account.ts
|
|
113
|
-
/** Account Category Code | Kontokategoriecode */
|
|
114
|
-
export const enum AccountCategoryCode {
|
|
115
|
-
/** Preferred Customer | Bevorzugter Kunde */
|
|
116
|
-
PreferredCustomer = 1,
|
|
117
|
-
Standard = 2,
|
|
118
|
-
}
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
Umfasst Picklist-, Status-, State- und MultiSelectPicklist-Attribute. Doppelte Labels werden mit dem Suffix `_{Value}` disambiguiert.
|
|
122
|
-
|
|
123
|
-
## 3.7 EntityNames Enum (`entity-names.ts`)
|
|
124
|
-
|
|
125
|
-
```typescript
|
|
126
|
-
// generated/entity-names.ts
|
|
127
|
-
export const enum EntityNames {
|
|
128
|
-
Account = 'account',
|
|
129
|
-
Contact = 'contact',
|
|
130
|
-
// alle Entitäten im Scope
|
|
131
|
-
}
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
## 3.8 MockValues-Typen (in Formular-Interfaces)
|
|
135
|
-
|
|
136
|
-
```typescript
|
|
137
|
-
type AccountMainFormMockValues = {
|
|
138
|
-
name?: string | null;
|
|
139
|
-
telephone1?: string | null;
|
|
140
|
-
revenue?: number | null;
|
|
141
|
-
};
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
Verwendet mit `createFormMock<AccountMainForm, AccountMainFormMockValues>({ name: 'Test' })`.
|
|
145
|
-
|
|
146
|
-
## 3.9 Action/Function Executors (`actions/{entity|global}.ts`)
|
|
147
|
-
|
|
148
|
-
```typescript
|
|
149
|
-
// generated/actions/global.ts
|
|
150
|
-
import { createUnboundAction } from '@xrmforge/helpers';
|
|
151
|
-
|
|
152
|
-
export interface NormalizePhoneParams { Input: string; AllowSuspicious?: boolean; }
|
|
153
|
-
export interface NormalizePhoneResult { Normalized: string; Status: number; }
|
|
154
|
-
|
|
155
|
-
export const NormalizePhone = createUnboundAction<NormalizePhoneParams, NormalizePhoneResult>(
|
|
156
|
-
'markant_NormalizePhone',
|
|
157
|
-
{ Input: { typeName: 'String', structuralProperty: 1 } }
|
|
158
|
-
);
|
|
159
|
-
// Verwendung: const result = await NormalizePhone.execute({ Input: '123' });
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
Factory-Funktionen: `createBoundAction`, `createUnboundAction`, `createBoundFunction`, `createUnboundFunction`. Batch-Ausführung über `executeMultiple()`, Fortschritts-UI über `withProgress()`.
|
|
163
|
-
|
|
164
|
-
## 3.10 Zweisprachige Labels
|
|
165
|
-
|
|
166
|
-
Alle generierten JSDoc-Kommentare unterstützen zweisprachige Labels:
|
|
167
|
-
```typescript
|
|
168
|
-
/** Account Name | Kontoname */
|
|
169
|
-
Name = 'name',
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
Deutsche Umlaute werden in Bezeichnern transliteriert: ae, oe, ue, ss (z.B. "Übergeordnet" wird zu `Uebergeordnet`).
|
|
1
|
+
# 3. Generierte Typen
|
|
2
|
+
|
|
3
|
+
Die Ausführung von `xrmforge generate` erzeugt die folgenden TypeScript-ES-Module:
|
|
4
|
+
|
|
5
|
+
## 3.1 Entitäts-Interfaces (`entities/{entity}.ts`)
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
// generated/entities/account.ts
|
|
9
|
+
/** Account | Konto */
|
|
10
|
+
export interface Account {
|
|
11
|
+
/** Account Name | Kontoname */
|
|
12
|
+
name: string | null;
|
|
13
|
+
accountid: string | null;
|
|
14
|
+
revenue: number | null;
|
|
15
|
+
_parentaccountid_value: string | null; // Lookup GUID
|
|
16
|
+
// ...
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Typ-Zuordnung:** String/Memo/EntityName zu `string`, Integer/BigInt/Decimal/Double/Money zu `number`, Boolean zu `boolean`, DateTime/Uniqueidentifier/Lookup zu `string`, Picklist/State/Status zu `number`.
|
|
21
|
+
|
|
22
|
+
## 3.2 Entity Fields Enums (`fields/{entity}.ts`)
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
// generated/fields/account.ts
|
|
26
|
+
export const enum AccountFields {
|
|
27
|
+
/** Account Name | Kontoname */
|
|
28
|
+
Name = 'name',
|
|
29
|
+
Telephone1 = 'telephone1',
|
|
30
|
+
Revenue = 'revenue',
|
|
31
|
+
// alle Entitätsattribute für $select-Abfragen
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const enum AccountNavigationProperties {
|
|
35
|
+
PrimaryContact = 'primarycontactid',
|
|
36
|
+
ContactCustomerAccounts = 'contact_customer_accounts',
|
|
37
|
+
// alle Lookup-Navigations-Properties
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Verwendet für Web API `$select`: `select(AccountFields.Name, AccountFields.Revenue)`.
|
|
42
|
+
|
|
43
|
+
## 3.3 Navigations-Properties (`fields/{entity}.ts`)
|
|
44
|
+
|
|
45
|
+
Navigations-Property-Enums befinden sich zusammen mit den Fields-Enums in derselben Datei (siehe 3.2 oben). Beispielverwendung:
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { AccountNavigationProperties } from '../generated/fields/account';
|
|
49
|
+
// verwendet für $expand-Abfragen
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## 3.4 Formular-Interfaces (`forms/{entity}.ts`)
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
// generated/forms/account.ts
|
|
56
|
+
|
|
57
|
+
// Union-Typ, der gültige Feldnamen einschränkt
|
|
58
|
+
export type AccountMainFormFields = 'name' | 'telephone1' | 'revenue';
|
|
59
|
+
|
|
60
|
+
// Gemappter Typ: Feldname zu Xrm-Attributtyp
|
|
61
|
+
export type AccountMainFormAttributeMap = {
|
|
62
|
+
name: Xrm.Attributes.StringAttribute;
|
|
63
|
+
telephone1: Xrm.Attributes.StringAttribute;
|
|
64
|
+
revenue: Xrm.Attributes.NumberAttribute;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// Gemappter Typ: Feldname zu Xrm-Steuerelementtyp
|
|
68
|
+
export type AccountMainFormControlMap = {
|
|
69
|
+
name: Xrm.Controls.StringControl;
|
|
70
|
+
telephone1: Xrm.Controls.StringControl;
|
|
71
|
+
revenue: Xrm.Controls.NumberControl;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// Fields-Enum für Autovervollständigung
|
|
75
|
+
export const enum AccountMainFormFieldsEnum {
|
|
76
|
+
/** Account Name | Kontoname */
|
|
77
|
+
AccountName = 'name',
|
|
78
|
+
Telephone1 = 'telephone1',
|
|
79
|
+
Revenue = 'revenue',
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Typsicherer FormContext mit überladenen getAttribute/getControl
|
|
83
|
+
export interface AccountMainForm extends Omit<Xrm.FormContext, 'getAttribute' | 'getControl'> {
|
|
84
|
+
getAttribute<K extends AccountMainFormFields>(name: K): AccountMainFormAttributeMap[K];
|
|
85
|
+
getAttribute(index: number): Xrm.Attributes.Attribute;
|
|
86
|
+
getAttribute(): Xrm.Attributes.Attribute[];
|
|
87
|
+
|
|
88
|
+
getControl<K extends AccountMainFormFields>(name: K): AccountMainFormControlMap[K];
|
|
89
|
+
getControl(index: number): Xrm.Controls.Control;
|
|
90
|
+
getControl(): Xrm.Controls.Control[];
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**Spezielle Steuerelemente** werden anhand ihrer FormXml-ClassID typisiert:
|
|
95
|
+
- Subgrid: `Xrm.Controls.GridControl`
|
|
96
|
+
- Editierbares Grid: `Xrm.Controls.GridControl`
|
|
97
|
+
- Quick View: `Xrm.Controls.QuickFormControl`
|
|
98
|
+
- Web Resource / iFrame: `Xrm.Controls.IframeControl`
|
|
99
|
+
|
|
100
|
+
## 3.5 Tabs/Sections/Subgrids/QuickViews Enums
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
const enum AccountMainFormTabs { Summary = 'SUMMARY_TAB', Details = 'DETAILS_TAB' }
|
|
104
|
+
const enum AccountMainFormSections { General = 'GENERAL', Address = 'ADDRESS' }
|
|
105
|
+
const enum AccountMainFormSubgrids { Contacts = 'Contacts_Subgrid' }
|
|
106
|
+
const enum AccountMainFormQuickViews { ContactPreview = 'ContactQuickView' }
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## 3.6 OptionSet Enums (`optionsets/{entity}.ts`)
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
// generated/optionsets/account.ts
|
|
113
|
+
/** Account Category Code | Kontokategoriecode */
|
|
114
|
+
export const enum AccountCategoryCode {
|
|
115
|
+
/** Preferred Customer | Bevorzugter Kunde */
|
|
116
|
+
PreferredCustomer = 1,
|
|
117
|
+
Standard = 2,
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Umfasst Picklist-, Status-, State- und MultiSelectPicklist-Attribute. Doppelte Labels werden mit dem Suffix `_{Value}` disambiguiert.
|
|
122
|
+
|
|
123
|
+
## 3.7 EntityNames Enum (`entity-names.ts`)
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
// generated/entity-names.ts
|
|
127
|
+
export const enum EntityNames {
|
|
128
|
+
Account = 'account',
|
|
129
|
+
Contact = 'contact',
|
|
130
|
+
// alle Entitäten im Scope
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## 3.8 MockValues-Typen (in Formular-Interfaces)
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
type AccountMainFormMockValues = {
|
|
138
|
+
name?: string | null;
|
|
139
|
+
telephone1?: string | null;
|
|
140
|
+
revenue?: number | null;
|
|
141
|
+
};
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Verwendet mit `createFormMock<AccountMainForm, AccountMainFormMockValues>({ name: 'Test' })`.
|
|
145
|
+
|
|
146
|
+
## 3.9 Action/Function Executors (`actions/{entity|global}.ts`)
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
// generated/actions/global.ts
|
|
150
|
+
import { createUnboundAction } from '@xrmforge/helpers';
|
|
151
|
+
|
|
152
|
+
export interface NormalizePhoneParams { Input: string; AllowSuspicious?: boolean; }
|
|
153
|
+
export interface NormalizePhoneResult { Normalized: string; Status: number; }
|
|
154
|
+
|
|
155
|
+
export const NormalizePhone = createUnboundAction<NormalizePhoneParams, NormalizePhoneResult>(
|
|
156
|
+
'markant_NormalizePhone',
|
|
157
|
+
{ Input: { typeName: 'String', structuralProperty: 1 } }
|
|
158
|
+
);
|
|
159
|
+
// Verwendung: const result = await NormalizePhone.execute({ Input: '123' });
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Factory-Funktionen: `createBoundAction`, `createUnboundAction`, `createBoundFunction`, `createUnboundFunction`. Batch-Ausführung über `executeMultiple()`, Fortschritts-UI über `withProgress()`.
|
|
163
|
+
|
|
164
|
+
## 3.10 Zweisprachige Labels
|
|
165
|
+
|
|
166
|
+
Alle generierten JSDoc-Kommentare unterstützen zweisprachige Labels:
|
|
167
|
+
```typescript
|
|
168
|
+
/** Account Name | Kontoname */
|
|
169
|
+
Name = 'name',
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Deutsche Umlaute werden in Bezeichnern transliteriert: ae, oe, ue, ss (z.B. "Übergeordnet" wird zu `Uebergeordnet`).
|