@khester/create-dynamics-app 1.0.8 → 1.1.0
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/bin/create-dynamics-app.js +1 -1
- package/dist/index.js +140 -15
- package/dist/index.js.map +1 -1
- package/dist/utils/consultingHelpers.d.ts +13 -0
- package/dist/utils/consultingHelpers.d.ts.map +1 -0
- package/dist/utils/consultingHelpers.js +569 -0
- package/dist/utils/consultingHelpers.js.map +1 -0
- package/dist/utils/copyTemplate.d.ts.map +1 -1
- package/dist/utils/copyTemplate.js.map +1 -1
- package/dist/utils/initGit.d.ts.map +1 -1
- package/dist/utils/initGit.js.map +1 -1
- package/dist/utils/installDependencies.d.ts.map +1 -1
- package/dist/utils/installDependencies.js +3 -2
- package/dist/utils/installDependencies.js.map +1 -1
- package/dist/utils/updatePackageJson.d.ts +1 -1
- package/dist/utils/updatePackageJson.d.ts.map +1 -1
- package/dist/utils/updatePackageJson.js +11 -1
- package/dist/utils/updatePackageJson.js.map +1 -1
- package/package.json +1 -1
- package/templates/dynamics-365-starter/INTEGRATION_TEST_RESULTS.md +302 -0
- package/templates/dynamics-365-starter/PHASE_4_COMPLETION_SUMMARY.md +305 -0
- package/templates/dynamics-365-starter/README.md +566 -137
- package/templates/dynamics-365-starter/deployment/QUICKSTART-MAC.md +507 -0
- package/templates/dynamics-365-starter/deployment/QUICKSTART-WINDOWS.md +372 -0
- package/templates/dynamics-365-starter/deployment/README.md +484 -0
- package/templates/dynamics-365-starter/deployment/pipelines/README.md +375 -0
- package/templates/dynamics-365-starter/deployment/pipelines/azure-pipelines.yml +330 -0
- package/templates/dynamics-365-starter/deployment/pipelines/github-actions.yml +422 -0
- package/templates/dynamics-365-starter/deployment/pipelines/jenkins.groovy +636 -0
- package/templates/dynamics-365-starter/deployment/scripts/deploy.ps1 +417 -0
- package/templates/dynamics-365-starter/deployment/scripts/deploy.sh +582 -0
- package/templates/dynamics-365-starter/deployment/scripts/team-onboarding.ps1 +486 -0
- package/templates/dynamics-365-starter/deployment/scripts/team-onboarding.sh +567 -0
- package/templates/dynamics-365-starter/deployment/scripts/validate-setup.ps1 +703 -0
- package/templates/dynamics-365-starter/deployment/scripts/validate-setup.sh +671 -0
- package/templates/dynamics-365-starter/docs/ARCHITECTURE_OVERVIEW.md +506 -0
- package/templates/dynamics-365-starter/docs/BEST_PRACTICES.md +723 -0
- package/templates/dynamics-365-starter/docs/MIGRATION_GUIDE.md +447 -0
- package/templates/dynamics-365-starter/docs/team-standards/README.md +273 -0
- package/templates/dynamics-365-starter/docs/team-standards/client-onboarding.md +577 -0
- package/templates/dynamics-365-starter/docs/team-standards/code-review-checklist.md +359 -0
- package/templates/dynamics-365-starter/docs/team-standards/coding-standards.md +700 -0
- package/templates/dynamics-365-starter/docs/team-standards/cross-platform-team-guide.md +736 -0
- package/templates/dynamics-365-starter/docs/team-standards/development-workflows.md +727 -0
- package/templates/dynamics-365-starter/docs/troubleshooting/common-errors.md +758 -0
- package/templates/dynamics-365-starter/docs/troubleshooting/platform-specific-issues.md +878 -0
- package/templates/dynamics-365-starter/package.json +22 -1
- package/templates/dynamics-365-starter/public/index.html +8 -11
- package/templates/dynamics-365-starter/scripts/custom-build.js +255 -0
- package/templates/dynamics-365-starter/src/client-project-template/README.md +234 -0
- package/templates/dynamics-365-starter/src/client-project-template/config/client.template.json +114 -0
- package/templates/dynamics-365-starter/src/client-project-template/config/environments/template.json +186 -0
- package/templates/dynamics-365-starter/src/client-project-template/scripts/client-setup.js +667 -0
- package/templates/dynamics-365-starter/src/components/AccountForm.css +71 -0
- package/templates/dynamics-365-starter/src/components/AccountForm.tsx +541 -0
- package/templates/dynamics-365-starter/src/components/AccountManagement.css +86 -0
- package/templates/dynamics-365-starter/src/components/AccountManagement.tsx +370 -0
- package/templates/dynamics-365-starter/src/components/ContactForm.tsx +149 -63
- package/templates/dynamics-365-starter/src/components/ContactManagement.tsx +153 -63
- package/templates/dynamics-365-starter/src/components/Logging/LogDialog.tsx +291 -0
- package/templates/dynamics-365-starter/src/components/Logging/LoggingContext.tsx +166 -0
- package/templates/dynamics-365-starter/src/components/Logging/LoggingDebugPanel.css +192 -0
- package/templates/dynamics-365-starter/src/components/Logging/LoggingDebugPanel.tsx +177 -0
- package/templates/dynamics-365-starter/src/components/Logging/LoggingProvider.tsx +3 -0
- package/templates/dynamics-365-starter/src/components/Logging/logger.ts +193 -0
- package/templates/dynamics-365-starter/src/constants/account.ts +410 -0
- package/templates/dynamics-365-starter/src/constants/contact.ts +362 -0
- package/templates/dynamics-365-starter/src/examples/README.md +52 -0
- package/templates/dynamics-365-starter/src/examples/component-examples/opportunity-management.tsx +625 -0
- package/templates/dynamics-365-starter/src/examples/entity-examples/opportunity-model.ts +545 -0
- package/templates/dynamics-365-starter/src/examples/integration-examples/custom-pcf-wrapper.tsx +722 -0
- package/templates/dynamics-365-starter/src/examples/workflow-examples/sales-workflow.ts +662 -0
- package/templates/dynamics-365-starter/src/index.tsx +107 -19
- package/templates/dynamics-365-starter/src/models/Account.ts +480 -0
- package/templates/dynamics-365-starter/src/models/BaseEntity.ts +204 -0
- package/templates/dynamics-365-starter/src/models/Contact.ts +580 -0
- package/templates/dynamics-365-starter/src/page-templates/EntityDashboard.tsx +519 -0
- package/templates/dynamics-365-starter/src/page-templates/EntityDetailPage.tsx +456 -0
- package/templates/dynamics-365-starter/src/page-templates/EntityListPage.tsx +406 -0
- package/templates/dynamics-365-starter/src/page-templates/RelatedEntitiesPage.tsx +578 -0
- package/templates/dynamics-365-starter/src/page-templates/SearchPage.tsx +629 -0
- package/templates/dynamics-365-starter/src/pcf/ContactControlWrapper.tsx +75 -22
- package/templates/dynamics-365-starter/src/pcf/MultiEntityControlWrapper.tsx +205 -0
- package/templates/dynamics-365-starter/src/providers/DynamicsProvider.tsx +297 -80
- package/templates/dynamics-365-starter/src/services/MockApiService.ts +260 -0
- package/templates/dynamics-365-starter/src/services/ServiceFactory.ts +65 -0
- package/templates/dynamics-365-starter/src/services/XrmApiService.ts +213 -0
- package/templates/dynamics-365-starter/src/styles/index.css +74 -7
- package/templates/dynamics-365-starter/tools/entity-generator/index.js +168 -0
- package/templates/dynamics-365-starter/tools/entity-generator/templates/constants.template.ts +124 -0
- package/templates/dynamics-365-starter/tools/entity-generator/templates/form.template.css +283 -0
- package/templates/dynamics-365-starter/tools/entity-generator/templates/form.template.tsx +275 -0
- package/templates/dynamics-365-starter/tools/entity-generator/templates/management.template.css +204 -0
- package/templates/dynamics-365-starter/tools/entity-generator/templates/management.template.tsx +413 -0
- package/templates/dynamics-365-starter/tools/entity-generator/templates/model.template.ts +250 -0
- package/templates/dynamics-365-starter/tools/metadata-sync/d365-client.js +410 -0
- package/templates/dynamics-365-starter/tools/metadata-sync/index.js +512 -0
- package/templates/dynamics-365-starter/tools/metadata-sync/type-generator.js +675 -0
- package/templates/dynamics-365-starter/tsconfig.json +11 -8
- package/templates/dynamics-365-starter/webpack.config.js +8 -9
- package/templates/power-pages-starter/README.md +7 -1
- package/templates/power-pages-starter/public/index.html +8 -11
- package/templates/power-pages-starter/src/components/ContactForm.tsx +60 -41
- package/templates/power-pages-starter/src/index.tsx +3 -3
- package/templates/power-pages-starter/src/providers/PowerPagesProvider.tsx +46 -23
- package/templates/power-pages-starter/tsconfig.json +3 -9
- package/templates/power-pages-starter/webpack.config.js +8 -3
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { IApiService } from '@khester/dynamics-ui-api-client';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Abstract base class for all entity models in the system.
|
|
5
|
+
* Provides common CRUD operations and validation patterns.
|
|
6
|
+
*/
|
|
7
|
+
export abstract class BaseEntity {
|
|
8
|
+
/**
|
|
9
|
+
* Validates the entity instance.
|
|
10
|
+
* @returns True if valid, throws error if invalid
|
|
11
|
+
*/
|
|
12
|
+
abstract validate(): boolean;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Creates a new entity record in Dynamics 365.
|
|
16
|
+
* @param apiService The API service instance
|
|
17
|
+
* @param entity The entity instance to create
|
|
18
|
+
* @param entityName The entity collection name
|
|
19
|
+
* @param loggerContext Optional logger context for debugging
|
|
20
|
+
* @returns Promise resolving to the created entity
|
|
21
|
+
*/
|
|
22
|
+
protected static async createEntity<T extends BaseEntity>(
|
|
23
|
+
apiService: IApiService,
|
|
24
|
+
entity: T,
|
|
25
|
+
entityName: string,
|
|
26
|
+
loggerContext?: string
|
|
27
|
+
): Promise<T> {
|
|
28
|
+
try {
|
|
29
|
+
entity.validate();
|
|
30
|
+
|
|
31
|
+
const result = await apiService.createRecord(entityName, entity);
|
|
32
|
+
|
|
33
|
+
if (loggerContext) {
|
|
34
|
+
console.log(`${loggerContext}: Entity created successfully`, result);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return result as T;
|
|
38
|
+
} catch (error) {
|
|
39
|
+
const errorMessage = `Error creating ${entityName}: ${error}`;
|
|
40
|
+
if (loggerContext) {
|
|
41
|
+
console.error(`${loggerContext}: ${errorMessage}`);
|
|
42
|
+
}
|
|
43
|
+
throw new Error(errorMessage);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Updates an existing entity record in Dynamics 365.
|
|
49
|
+
* @param apiService The API service instance
|
|
50
|
+
* @param entityId The ID of the entity to update
|
|
51
|
+
* @param entity The entity instance with updated values
|
|
52
|
+
* @param entityName The entity collection name
|
|
53
|
+
* @param primaryKey The primary key field name
|
|
54
|
+
* @param loggerContext Optional logger context for debugging
|
|
55
|
+
* @returns Promise resolving to the updated entity
|
|
56
|
+
*/
|
|
57
|
+
protected static async updateEntity<T extends BaseEntity>(
|
|
58
|
+
apiService: IApiService,
|
|
59
|
+
entityId: string,
|
|
60
|
+
entity: T,
|
|
61
|
+
entityName: string,
|
|
62
|
+
primaryKey: string,
|
|
63
|
+
loggerContext?: string
|
|
64
|
+
): Promise<T> {
|
|
65
|
+
try {
|
|
66
|
+
entity.validate();
|
|
67
|
+
|
|
68
|
+
// Remove the primary key from the update payload
|
|
69
|
+
const updatePayload = { ...entity };
|
|
70
|
+
delete (updatePayload as any)[primaryKey];
|
|
71
|
+
|
|
72
|
+
await apiService.updateRecord(entityName, entityId, updatePayload);
|
|
73
|
+
|
|
74
|
+
if (loggerContext) {
|
|
75
|
+
console.log(`${loggerContext}: Entity updated successfully`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Return the entity with the ID set
|
|
79
|
+
(entity as any)[primaryKey] = entityId;
|
|
80
|
+
return entity;
|
|
81
|
+
} catch (error) {
|
|
82
|
+
const errorMessage = `Error updating ${entityName}: ${error}`;
|
|
83
|
+
if (loggerContext) {
|
|
84
|
+
console.error(`${loggerContext}: ${errorMessage}`);
|
|
85
|
+
}
|
|
86
|
+
throw new Error(errorMessage);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Deletes an entity record from Dynamics 365.
|
|
92
|
+
* @param apiService The API service instance
|
|
93
|
+
* @param entityId The ID of the entity to delete
|
|
94
|
+
* @param entityName The entity collection name
|
|
95
|
+
* @param loggerContext Optional logger context for debugging
|
|
96
|
+
* @returns Promise resolving when deletion is complete
|
|
97
|
+
*/
|
|
98
|
+
protected static async deleteEntity(
|
|
99
|
+
apiService: IApiService,
|
|
100
|
+
entityId: string,
|
|
101
|
+
entityName: string,
|
|
102
|
+
loggerContext?: string
|
|
103
|
+
): Promise<void> {
|
|
104
|
+
try {
|
|
105
|
+
await apiService.deleteRecord(entityName, entityId);
|
|
106
|
+
|
|
107
|
+
if (loggerContext) {
|
|
108
|
+
console.log(`${loggerContext}: Entity deleted successfully`);
|
|
109
|
+
}
|
|
110
|
+
} catch (error) {
|
|
111
|
+
const errorMessage = `Error deleting ${entityName}: ${error}`;
|
|
112
|
+
if (loggerContext) {
|
|
113
|
+
console.error(`${loggerContext}: ${errorMessage}`);
|
|
114
|
+
}
|
|
115
|
+
throw new Error(errorMessage);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Retrieves entities based on a FetchXML filter.
|
|
121
|
+
* @param apiService The API service instance
|
|
122
|
+
* @param entityName The entity collection name
|
|
123
|
+
* @param fetchXml The FetchXML query
|
|
124
|
+
* @param EntityClass The entity class constructor
|
|
125
|
+
* @param loggerContext Optional logger context for debugging
|
|
126
|
+
* @returns Promise resolving to an array of entities
|
|
127
|
+
*/
|
|
128
|
+
protected static async retrieveEntitiesByFilter<T extends BaseEntity>(
|
|
129
|
+
apiService: IApiService,
|
|
130
|
+
entityName: string,
|
|
131
|
+
fetchXml: string,
|
|
132
|
+
EntityClass: new (data: any) => T,
|
|
133
|
+
loggerContext?: string
|
|
134
|
+
): Promise<T[]> {
|
|
135
|
+
try {
|
|
136
|
+
const result = await apiService.retrieveMultipleRecords(
|
|
137
|
+
entityName,
|
|
138
|
+
fetchXml
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
const entities = result.entities.map(
|
|
142
|
+
(record: any) => new EntityClass(record)
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
if (loggerContext) {
|
|
146
|
+
console.log(`${loggerContext}: Retrieved ${entities.length} entities`);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return entities;
|
|
150
|
+
} catch (error) {
|
|
151
|
+
const errorMessage = `Error retrieving ${entityName} records: ${error}`;
|
|
152
|
+
if (loggerContext) {
|
|
153
|
+
console.error(`${loggerContext}: ${errorMessage}`);
|
|
154
|
+
}
|
|
155
|
+
throw new Error(errorMessage);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Builds a FetchXML query with proper escaping.
|
|
161
|
+
* @param entityName The entity name
|
|
162
|
+
* @param attributes Array of attribute names to retrieve
|
|
163
|
+
* @param filter Optional filter XML string
|
|
164
|
+
* @param orderBy Optional order by configuration
|
|
165
|
+
* @returns FetchXML string
|
|
166
|
+
*/
|
|
167
|
+
protected static buildFetchXml(
|
|
168
|
+
entityName: string,
|
|
169
|
+
attributes: string[],
|
|
170
|
+
filter?: string,
|
|
171
|
+
orderBy?: { attribute: string; descending?: boolean }
|
|
172
|
+
): string {
|
|
173
|
+
const attributesXml = attributes
|
|
174
|
+
.map((attr) => `<attribute name="${attr}" />`)
|
|
175
|
+
.join('\n ');
|
|
176
|
+
const orderXml = orderBy
|
|
177
|
+
? `<order attribute="${orderBy.attribute}" descending="${orderBy.descending || false}" />`
|
|
178
|
+
: '';
|
|
179
|
+
|
|
180
|
+
return `<fetch mapping="logical">
|
|
181
|
+
<entity name="${entityName}">
|
|
182
|
+
${attributesXml}
|
|
183
|
+
${orderXml}
|
|
184
|
+
${filter || ''}
|
|
185
|
+
</entity>
|
|
186
|
+
</fetch>`;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Escapes XML special characters in a string.
|
|
191
|
+
* @param value The string to escape
|
|
192
|
+
* @returns Escaped string safe for XML
|
|
193
|
+
*/
|
|
194
|
+
protected static escapeXml(value: string): string {
|
|
195
|
+
if (!value) return value;
|
|
196
|
+
|
|
197
|
+
return value
|
|
198
|
+
.replace(/&/g, '&')
|
|
199
|
+
.replace(/</g, '<')
|
|
200
|
+
.replace(/>/g, '>')
|
|
201
|
+
.replace(/"/g, '"')
|
|
202
|
+
.replace(/'/g, ''');
|
|
203
|
+
}
|
|
204
|
+
}
|