@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.
Files changed (107) hide show
  1. package/bin/create-dynamics-app.js +1 -1
  2. package/dist/index.js +140 -15
  3. package/dist/index.js.map +1 -1
  4. package/dist/utils/consultingHelpers.d.ts +13 -0
  5. package/dist/utils/consultingHelpers.d.ts.map +1 -0
  6. package/dist/utils/consultingHelpers.js +569 -0
  7. package/dist/utils/consultingHelpers.js.map +1 -0
  8. package/dist/utils/copyTemplate.d.ts.map +1 -1
  9. package/dist/utils/copyTemplate.js.map +1 -1
  10. package/dist/utils/initGit.d.ts.map +1 -1
  11. package/dist/utils/initGit.js.map +1 -1
  12. package/dist/utils/installDependencies.d.ts.map +1 -1
  13. package/dist/utils/installDependencies.js +3 -2
  14. package/dist/utils/installDependencies.js.map +1 -1
  15. package/dist/utils/updatePackageJson.d.ts +1 -1
  16. package/dist/utils/updatePackageJson.d.ts.map +1 -1
  17. package/dist/utils/updatePackageJson.js +11 -1
  18. package/dist/utils/updatePackageJson.js.map +1 -1
  19. package/package.json +1 -1
  20. package/templates/dynamics-365-starter/INTEGRATION_TEST_RESULTS.md +302 -0
  21. package/templates/dynamics-365-starter/PHASE_4_COMPLETION_SUMMARY.md +305 -0
  22. package/templates/dynamics-365-starter/README.md +566 -137
  23. package/templates/dynamics-365-starter/deployment/QUICKSTART-MAC.md +507 -0
  24. package/templates/dynamics-365-starter/deployment/QUICKSTART-WINDOWS.md +372 -0
  25. package/templates/dynamics-365-starter/deployment/README.md +484 -0
  26. package/templates/dynamics-365-starter/deployment/pipelines/README.md +375 -0
  27. package/templates/dynamics-365-starter/deployment/pipelines/azure-pipelines.yml +330 -0
  28. package/templates/dynamics-365-starter/deployment/pipelines/github-actions.yml +422 -0
  29. package/templates/dynamics-365-starter/deployment/pipelines/jenkins.groovy +636 -0
  30. package/templates/dynamics-365-starter/deployment/scripts/deploy.ps1 +417 -0
  31. package/templates/dynamics-365-starter/deployment/scripts/deploy.sh +582 -0
  32. package/templates/dynamics-365-starter/deployment/scripts/team-onboarding.ps1 +486 -0
  33. package/templates/dynamics-365-starter/deployment/scripts/team-onboarding.sh +567 -0
  34. package/templates/dynamics-365-starter/deployment/scripts/validate-setup.ps1 +703 -0
  35. package/templates/dynamics-365-starter/deployment/scripts/validate-setup.sh +671 -0
  36. package/templates/dynamics-365-starter/docs/ARCHITECTURE_OVERVIEW.md +506 -0
  37. package/templates/dynamics-365-starter/docs/BEST_PRACTICES.md +723 -0
  38. package/templates/dynamics-365-starter/docs/MIGRATION_GUIDE.md +447 -0
  39. package/templates/dynamics-365-starter/docs/team-standards/README.md +273 -0
  40. package/templates/dynamics-365-starter/docs/team-standards/client-onboarding.md +577 -0
  41. package/templates/dynamics-365-starter/docs/team-standards/code-review-checklist.md +359 -0
  42. package/templates/dynamics-365-starter/docs/team-standards/coding-standards.md +700 -0
  43. package/templates/dynamics-365-starter/docs/team-standards/cross-platform-team-guide.md +736 -0
  44. package/templates/dynamics-365-starter/docs/team-standards/development-workflows.md +727 -0
  45. package/templates/dynamics-365-starter/docs/troubleshooting/common-errors.md +758 -0
  46. package/templates/dynamics-365-starter/docs/troubleshooting/platform-specific-issues.md +878 -0
  47. package/templates/dynamics-365-starter/package.json +22 -1
  48. package/templates/dynamics-365-starter/public/index.html +8 -11
  49. package/templates/dynamics-365-starter/scripts/custom-build.js +255 -0
  50. package/templates/dynamics-365-starter/src/client-project-template/README.md +234 -0
  51. package/templates/dynamics-365-starter/src/client-project-template/config/client.template.json +114 -0
  52. package/templates/dynamics-365-starter/src/client-project-template/config/environments/template.json +186 -0
  53. package/templates/dynamics-365-starter/src/client-project-template/scripts/client-setup.js +667 -0
  54. package/templates/dynamics-365-starter/src/components/AccountForm.css +71 -0
  55. package/templates/dynamics-365-starter/src/components/AccountForm.tsx +541 -0
  56. package/templates/dynamics-365-starter/src/components/AccountManagement.css +86 -0
  57. package/templates/dynamics-365-starter/src/components/AccountManagement.tsx +370 -0
  58. package/templates/dynamics-365-starter/src/components/ContactForm.tsx +149 -63
  59. package/templates/dynamics-365-starter/src/components/ContactManagement.tsx +153 -63
  60. package/templates/dynamics-365-starter/src/components/Logging/LogDialog.tsx +291 -0
  61. package/templates/dynamics-365-starter/src/components/Logging/LoggingContext.tsx +166 -0
  62. package/templates/dynamics-365-starter/src/components/Logging/LoggingDebugPanel.css +192 -0
  63. package/templates/dynamics-365-starter/src/components/Logging/LoggingDebugPanel.tsx +177 -0
  64. package/templates/dynamics-365-starter/src/components/Logging/LoggingProvider.tsx +3 -0
  65. package/templates/dynamics-365-starter/src/components/Logging/logger.ts +193 -0
  66. package/templates/dynamics-365-starter/src/constants/account.ts +410 -0
  67. package/templates/dynamics-365-starter/src/constants/contact.ts +362 -0
  68. package/templates/dynamics-365-starter/src/examples/README.md +52 -0
  69. package/templates/dynamics-365-starter/src/examples/component-examples/opportunity-management.tsx +625 -0
  70. package/templates/dynamics-365-starter/src/examples/entity-examples/opportunity-model.ts +545 -0
  71. package/templates/dynamics-365-starter/src/examples/integration-examples/custom-pcf-wrapper.tsx +722 -0
  72. package/templates/dynamics-365-starter/src/examples/workflow-examples/sales-workflow.ts +662 -0
  73. package/templates/dynamics-365-starter/src/index.tsx +107 -19
  74. package/templates/dynamics-365-starter/src/models/Account.ts +480 -0
  75. package/templates/dynamics-365-starter/src/models/BaseEntity.ts +204 -0
  76. package/templates/dynamics-365-starter/src/models/Contact.ts +580 -0
  77. package/templates/dynamics-365-starter/src/page-templates/EntityDashboard.tsx +519 -0
  78. package/templates/dynamics-365-starter/src/page-templates/EntityDetailPage.tsx +456 -0
  79. package/templates/dynamics-365-starter/src/page-templates/EntityListPage.tsx +406 -0
  80. package/templates/dynamics-365-starter/src/page-templates/RelatedEntitiesPage.tsx +578 -0
  81. package/templates/dynamics-365-starter/src/page-templates/SearchPage.tsx +629 -0
  82. package/templates/dynamics-365-starter/src/pcf/ContactControlWrapper.tsx +75 -22
  83. package/templates/dynamics-365-starter/src/pcf/MultiEntityControlWrapper.tsx +205 -0
  84. package/templates/dynamics-365-starter/src/providers/DynamicsProvider.tsx +297 -80
  85. package/templates/dynamics-365-starter/src/services/MockApiService.ts +260 -0
  86. package/templates/dynamics-365-starter/src/services/ServiceFactory.ts +65 -0
  87. package/templates/dynamics-365-starter/src/services/XrmApiService.ts +213 -0
  88. package/templates/dynamics-365-starter/src/styles/index.css +74 -7
  89. package/templates/dynamics-365-starter/tools/entity-generator/index.js +168 -0
  90. package/templates/dynamics-365-starter/tools/entity-generator/templates/constants.template.ts +124 -0
  91. package/templates/dynamics-365-starter/tools/entity-generator/templates/form.template.css +283 -0
  92. package/templates/dynamics-365-starter/tools/entity-generator/templates/form.template.tsx +275 -0
  93. package/templates/dynamics-365-starter/tools/entity-generator/templates/management.template.css +204 -0
  94. package/templates/dynamics-365-starter/tools/entity-generator/templates/management.template.tsx +413 -0
  95. package/templates/dynamics-365-starter/tools/entity-generator/templates/model.template.ts +250 -0
  96. package/templates/dynamics-365-starter/tools/metadata-sync/d365-client.js +410 -0
  97. package/templates/dynamics-365-starter/tools/metadata-sync/index.js +512 -0
  98. package/templates/dynamics-365-starter/tools/metadata-sync/type-generator.js +675 -0
  99. package/templates/dynamics-365-starter/tsconfig.json +11 -8
  100. package/templates/dynamics-365-starter/webpack.config.js +8 -9
  101. package/templates/power-pages-starter/README.md +7 -1
  102. package/templates/power-pages-starter/public/index.html +8 -11
  103. package/templates/power-pages-starter/src/components/ContactForm.tsx +60 -41
  104. package/templates/power-pages-starter/src/index.tsx +3 -3
  105. package/templates/power-pages-starter/src/providers/PowerPagesProvider.tsx +46 -23
  106. package/templates/power-pages-starter/tsconfig.json +3 -9
  107. package/templates/power-pages-starter/webpack.config.js +8 -3
@@ -0,0 +1,667 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Client Project Setup Script
5
+ * Automates the setup of client-specific configurations and branding
6
+ */
7
+
8
+ const fs = require('fs-extra');
9
+ const path = require('path');
10
+ const inquirer = require('inquirer');
11
+ const chalk = require('chalk');
12
+
13
+ async function setupClientProject() {
14
+ console.log(chalk.cyan('\n🎯 Client Project Setup\n'));
15
+
16
+ // Gather client information
17
+ const answers = await inquirer.prompt([
18
+ {
19
+ type: 'input',
20
+ name: 'clientName',
21
+ message: 'Client full name:',
22
+ validate: input => input.length > 0
23
+ },
24
+ {
25
+ type: 'input',
26
+ name: 'clientCode',
27
+ message: 'Client code (3-4 characters):',
28
+ validate: input => input.length >= 3 && input.length <= 4
29
+ },
30
+ {
31
+ type: 'list',
32
+ name: 'industry',
33
+ message: 'Industry:',
34
+ choices: [
35
+ 'Manufacturing',
36
+ 'Healthcare',
37
+ 'Financial Services',
38
+ 'Retail',
39
+ 'Technology',
40
+ 'Education',
41
+ 'Government',
42
+ 'Non-Profit',
43
+ 'Other'
44
+ ]
45
+ },
46
+ {
47
+ type: 'list',
48
+ name: 'timezone',
49
+ message: 'Primary timezone:',
50
+ choices: [
51
+ 'America/New_York',
52
+ 'America/Chicago',
53
+ 'America/Denver',
54
+ 'America/Los_Angeles',
55
+ 'Europe/London',
56
+ 'Europe/Paris',
57
+ 'Asia/Tokyo',
58
+ 'Australia/Sydney'
59
+ ]
60
+ },
61
+ {
62
+ type: 'input',
63
+ name: 'primaryContact',
64
+ message: 'Primary contact name:'
65
+ },
66
+ {
67
+ type: 'input',
68
+ name: 'contactEmail',
69
+ message: 'Primary contact email:',
70
+ validate: input => /\S+@\S+\.\S+/.test(input)
71
+ },
72
+ {
73
+ type: 'input',
74
+ name: 'primaryColor',
75
+ message: 'Primary brand color (hex):',
76
+ default: '#0078d4'
77
+ },
78
+ {
79
+ type: 'input',
80
+ name: 'secondaryColor',
81
+ message: 'Secondary brand color (hex):',
82
+ default: '#106ebe'
83
+ },
84
+ {
85
+ type: 'checkbox',
86
+ name: 'environments',
87
+ message: 'Environments to configure:',
88
+ choices: [
89
+ { name: 'Development', value: 'dev', checked: true },
90
+ { name: 'Testing', value: 'test', checked: true },
91
+ { name: 'Staging', value: 'staging', checked: false },
92
+ { name: 'Production', value: 'prod', checked: true }
93
+ ]
94
+ },
95
+ {
96
+ type: 'confirm',
97
+ name: 'enableAdvancedFeatures',
98
+ message: 'Enable advanced features (custom workflows, reporting, etc.)?',
99
+ default: true
100
+ }
101
+ ]);
102
+
103
+ console.log(chalk.cyan('\n📁 Creating client configuration...\n'));
104
+
105
+ // Create client configuration
106
+ await createClientConfig(answers);
107
+
108
+ // Create environment configurations
109
+ for (const env of answers.environments) {
110
+ await createEnvironmentConfig(env, answers);
111
+ }
112
+
113
+ // Create branding files
114
+ await createBrandingFiles(answers);
115
+
116
+ // Create deployment scripts
117
+ await createDeploymentScripts(answers);
118
+
119
+ // Create documentation
120
+ await createProjectDocumentation(answers);
121
+
122
+ console.log(chalk.green('\n✅ Client project setup completed!\n'));
123
+ console.log(chalk.cyan('📝 Next steps:'));
124
+ console.log(' 1. Review and update configuration files');
125
+ console.log(' 2. Add client logos to src/branding/logos/');
126
+ console.log(' 3. Configure environment-specific settings');
127
+ console.log(' 4. Set up deployment pipelines');
128
+ console.log(' 5. Run initial deployment to dev environment');
129
+ console.log('\n📚 Documentation created in docs/ folder');
130
+ }
131
+
132
+ async function createClientConfig(answers) {
133
+ const configPath = 'config/client.json';
134
+ await fs.ensureDir(path.dirname(configPath));
135
+
136
+ const clientConfig = {
137
+ name: answers.clientName,
138
+ code: answers.clientCode.toUpperCase(),
139
+ industry: answers.industry,
140
+ timezone: answers.timezone,
141
+ locale: 'en-US',
142
+ version: '1.0.0',
143
+ created: new Date().toISOString(),
144
+ lastUpdated: new Date().toISOString(),
145
+ contact: {
146
+ primaryContact: answers.primaryContact,
147
+ email: answers.contactEmail,
148
+ phone: ''
149
+ },
150
+ branding: {
151
+ primaryColor: answers.primaryColor,
152
+ secondaryColor: answers.secondaryColor,
153
+ accentColor: '#ffaa44',
154
+ logoPath: `src/branding/logos/${answers.clientCode.toLowerCase()}-logo.png`,
155
+ faviconPath: `src/branding/logos/${answers.clientCode.toLowerCase()}-favicon.ico`,
156
+ fontFamily: 'Segoe UI, sans-serif',
157
+ customCss: `src/branding/${answers.clientCode.toLowerCase()}-custom.css`
158
+ },
159
+ features: {
160
+ enableAdvancedLogging: answers.enableAdvancedFeatures,
161
+ enableCustomWorkflows: answers.enableAdvancedFeatures,
162
+ enableReporting: answers.enableAdvancedFeatures,
163
+ enableMobileOptimization: true,
164
+ enableOfflineCapability: false,
165
+ enableMultiLanguage: false,
166
+ enableCustomDashboards: answers.enableAdvancedFeatures,
167
+ enableDataExport: true,
168
+ enableBulkOperations: true,
169
+ enableAdvancedSecurity: true
170
+ },
171
+ customEntities: [],
172
+ integrations: {
173
+ sharepoint: { enabled: false, siteUrl: '' },
174
+ teams: { enabled: false, appId: '' },
175
+ powerBI: { enabled: false, workspaceId: '' },
176
+ powerAutomate: { enabled: true },
177
+ externalAPIs: []
178
+ },
179
+ compliance: {
180
+ gdprCompliant: true,
181
+ hipaaCompliant: false,
182
+ soxCompliant: false,
183
+ auditRetentionDays: 365,
184
+ dataClassification: 'Internal'
185
+ },
186
+ deployment: {
187
+ strategy: 'blue-green',
188
+ rollbackEnabled: true,
189
+ approvalRequired: true,
190
+ notificationEmail: answers.contactEmail,
191
+ maintenanceWindow: {
192
+ timezone: answers.timezone,
193
+ startTime: '02:00',
194
+ duration: 120
195
+ }
196
+ }
197
+ };
198
+
199
+ await fs.writeJson(configPath, clientConfig, { spaces: 2 });
200
+ console.log(chalk.green(` ✓ Created ${configPath}`));
201
+ }
202
+
203
+ async function createEnvironmentConfig(environment, answers) {
204
+ const envPath = `config/environments/${environment}.json`;
205
+ await fs.ensureDir(path.dirname(envPath));
206
+
207
+ const environmentConfig = {
208
+ name: environment.charAt(0).toUpperCase() + environment.slice(1),
209
+ type: environment,
210
+ description: `${environment.charAt(0).toUpperCase() + environment.slice(1)} environment for ${answers.clientName}`,
211
+ lastUpdated: new Date().toISOString(),
212
+ dynamics365: {
213
+ orgUrl: `https://${answers.clientCode.toLowerCase()}-${environment}.crm.dynamics.com`,
214
+ webApiUrl: `https://${answers.clientCode.toLowerCase()}-${environment}.api.crm.dynamics.com/api/data/v9.2`,
215
+ version: '9.2',
216
+ region: 'northamerica',
217
+ tenantId: 'your-tenant-id',
218
+ dataverse: {
219
+ environmentId: 'your-environment-id',
220
+ uniqueName: `${answers.clientCode.toLowerCase()}-${environment}`
221
+ }
222
+ },
223
+ authentication: {
224
+ type: 'oauth2',
225
+ clientId: 'your-client-id',
226
+ clientSecret: 'your-client-secret',
227
+ redirectUri: `https://${answers.clientCode.toLowerCase()}-${environment}.dynamics.com/auth/callback`,
228
+ scopes: [`https://${answers.clientCode.toLowerCase()}-${environment}.crm.dynamics.com/user_impersonation`],
229
+ authority: 'https://login.microsoftonline.com/your-tenant-id'
230
+ },
231
+ security: {
232
+ enableAuditLogging: true,
233
+ requireMFA: environment === 'prod',
234
+ sessionTimeout: environment === 'prod' ? 480 : 720,
235
+ enableConditionalAccess: environment === 'prod',
236
+ allowedIPs: [],
237
+ dataLossPreventionEnabled: environment === 'prod',
238
+ encryptionAtRest: true,
239
+ encryptionInTransit: true
240
+ },
241
+ performance: {
242
+ enableCaching: environment !== 'dev',
243
+ cacheTimeout: 300,
244
+ batchSize: environment === 'prod' ? 100 : 50,
245
+ timeoutMs: 30000,
246
+ retryAttempts: 3,
247
+ retryDelayMs: 1000,
248
+ enableCompression: true,
249
+ enableCDN: environment === 'prod'
250
+ },
251
+ monitoring: {
252
+ enableApplicationInsights: true,
253
+ instrumentationKey: 'your-instrumentation-key',
254
+ logLevel: environment === 'prod' ? 'error' : environment === 'test' ? 'warn' : 'debug',
255
+ enableMetrics: true,
256
+ enableTracing: environment !== 'prod',
257
+ enableProfiling: environment === 'dev'
258
+ }
259
+ };
260
+
261
+ await fs.writeJson(envPath, environmentConfig, { spaces: 2 });
262
+ console.log(chalk.green(` ✓ Created ${envPath}`));
263
+ }
264
+
265
+ async function createBrandingFiles(answers) {
266
+ const brandingPath = 'src/branding';
267
+ await fs.ensureDir(brandingPath);
268
+ await fs.ensureDir(path.join(brandingPath, 'logos'));
269
+
270
+ // Create theme file
271
+ const themeContent = `// ${answers.clientName} Theme Configuration
272
+ import { ITheme } from '@fluentui/react';
273
+
274
+ export const ${answers.clientCode.toLowerCase()}Theme: ITheme = {
275
+ palette: {
276
+ themePrimary: '${answers.primaryColor}',
277
+ themeSecondary: '${answers.secondaryColor}',
278
+ themeTertiary: '#71afe5',
279
+ themeLight: '#c7e0f4',
280
+ themeLighter: '#deecf9',
281
+ themeLighterAlt: '#eff6fc',
282
+ black: '#000000',
283
+ blackTranslucent40: 'rgba(0,0,0,.4)',
284
+ neutralDark: '#201f1e',
285
+ neutralPrimary: '#323130',
286
+ neutralPrimaryAlt: '#3b3a39',
287
+ neutralSecondary: '#605e5c',
288
+ neutralTertiary: '#a19f9d',
289
+ neutralTertiaryAlt: '#c8c6c4',
290
+ neutralQuaternary: '#d2d0ce',
291
+ neutralQuaternaryAlt: '#e1dfdd',
292
+ neutralLight: '#edebe9',
293
+ neutralLighter: '#f3f2f1',
294
+ neutralLighterAlt: '#faf9f8',
295
+ white: '#ffffff',
296
+ yellowDark: '#d29200',
297
+ yellow: '#ffb900',
298
+ yellowLight: '#fff4ce',
299
+ orange: '#d83b01',
300
+ orangeLight: '#febf04',
301
+ orangeLighter: '#fcd116',
302
+ redDark: '#a4262c',
303
+ red: '#e81123',
304
+ magentaDark: '#5c2d91',
305
+ magenta: '#b4009e',
306
+ magentaLight: '#e3008c',
307
+ purpleDark: '#32145a',
308
+ purple: '#5c2d91',
309
+ purpleLight: '#b4a0ff',
310
+ blueDark: '#002050',
311
+ blueMid: '#00188f',
312
+ blue: '${answers.primaryColor}',
313
+ blueLight: '#40e0d0',
314
+ tealDark: '#004b50',
315
+ teal: '#008272',
316
+ tealLight: '#00bcf2',
317
+ greenDark: '#004b1c',
318
+ green: '#107c10',
319
+ greenLight: '#bad80a'
320
+ },
321
+ fonts: {
322
+ small: {
323
+ fontSize: '12px',
324
+ lineHeight: '16px'
325
+ },
326
+ medium: {
327
+ fontSize: '14px',
328
+ lineHeight: '20px',
329
+ fontFamily: 'Segoe UI, sans-serif'
330
+ },
331
+ large: {
332
+ fontSize: '18px',
333
+ lineHeight: '24px'
334
+ },
335
+ xLarge: {
336
+ fontSize: '20px',
337
+ lineHeight: '28px'
338
+ },
339
+ xxLarge: {
340
+ fontSize: '28px',
341
+ lineHeight: '36px'
342
+ }
343
+ }
344
+ };`;
345
+
346
+ await fs.writeFile(path.join(brandingPath, 'theme.ts'), themeContent);
347
+
348
+ // Create custom CSS file
349
+ const customCssContent = `/* ${answers.clientName} Custom Styles */
350
+
351
+ :root {
352
+ --client-primary-color: ${answers.primaryColor};
353
+ --client-secondary-color: ${answers.secondaryColor};
354
+ --client-font-family: 'Segoe UI', sans-serif;
355
+ }
356
+
357
+ /* Client-specific component overrides */
358
+ .client-header {
359
+ background-color: var(--client-primary-color);
360
+ color: white;
361
+ }
362
+
363
+ .client-navigation {
364
+ border-bottom: 2px solid var(--client-primary-color);
365
+ }
366
+
367
+ .client-button-primary {
368
+ background-color: var(--client-primary-color);
369
+ border-color: var(--client-primary-color);
370
+ }
371
+
372
+ .client-button-primary:hover {
373
+ background-color: var(--client-secondary-color);
374
+ border-color: var(--client-secondary-color);
375
+ }
376
+
377
+ /* Logo and branding */
378
+ .client-logo {
379
+ max-height: 40px;
380
+ width: auto;
381
+ }
382
+
383
+ /* Custom responsive breakpoints for client */
384
+ @media (max-width: 768px) {
385
+ .client-header {
386
+ padding: 10px;
387
+ }
388
+ }`;
389
+
390
+ await fs.writeFile(path.join(brandingPath, `${answers.clientCode.toLowerCase()}-custom.css`), customCssContent);
391
+
392
+ // Create logo placeholder README
393
+ const logoReadme = `# ${answers.clientName} Logos
394
+
395
+ Please add the following logo files to this directory:
396
+
397
+ - \`${answers.clientCode.toLowerCase()}-logo.png\` - Main logo (recommended: 200x60px)
398
+ - \`${answers.clientCode.toLowerCase()}-logo-white.png\` - White version for dark backgrounds
399
+ - \`${answers.clientCode.toLowerCase()}-favicon.ico\` - Favicon (16x16, 32x32px)
400
+ - \`${answers.clientCode.toLowerCase()}-logo-large.png\` - High resolution logo (400x120px)
401
+
402
+ ## Logo Guidelines
403
+
404
+ - Use PNG format with transparent background
405
+ - Maintain aspect ratio when resizing
406
+ - Ensure logos are optimized for web use
407
+ - Test visibility on both light and dark backgrounds
408
+ `;
409
+
410
+ await fs.writeFile(path.join(brandingPath, 'logos', 'README.md'), logoReadme);
411
+
412
+ console.log(chalk.green(` ✓ Created branding files in ${brandingPath}/`));
413
+ }
414
+
415
+ async function createDeploymentScripts(answers) {
416
+ const scriptsPath = 'scripts';
417
+ await fs.ensureDir(scriptsPath);
418
+
419
+ // Client-specific deployment script
420
+ const deployScript = `#!/bin/bash
421
+ # ${answers.clientName} Deployment Script
422
+ # Generated on ${new Date().toISOString()}
423
+
424
+ CLIENT_NAME="${answers.clientName}"
425
+ CLIENT_CODE="${answers.clientCode.toUpperCase()}"
426
+ PROJECT_ROOT="$(cd "$(dirname "\${BASH_SOURCE[0]}")/.." && pwd)"
427
+
428
+ echo "🚀 Deploying \${CLIENT_NAME} project..."
429
+
430
+ # Validate environment parameter
431
+ if [ -z "$1" ]; then
432
+ echo "❌ Environment parameter required"
433
+ echo "Usage: $0 <environment>"
434
+ echo "Available environments: dev, test, staging, prod"
435
+ exit 1
436
+ fi
437
+
438
+ ENVIRONMENT=$1
439
+
440
+ # Check if environment config exists
441
+ if [ ! -f "\${PROJECT_ROOT}/config/environments/\${ENVIRONMENT}.json" ]; then
442
+ echo "❌ Environment configuration not found: \${ENVIRONMENT}.json"
443
+ exit 1
444
+ fi
445
+
446
+ echo "📋 Deploying to \${ENVIRONMENT} environment for \${CLIENT_NAME}..."
447
+
448
+ # Load environment configuration
449
+ export NODE_ENV=\${ENVIRONMENT}
450
+
451
+ # Run pre-deployment checks
452
+ echo "🔍 Running pre-deployment checks..."
453
+ npm run quality
454
+ if [ $? -ne 0 ]; then
455
+ echo "❌ Quality checks failed"
456
+ exit 1
457
+ fi
458
+
459
+ # Build for target environment
460
+ echo "🔨 Building for \${ENVIRONMENT}..."
461
+ npm run build:prod
462
+ if [ $? -ne 0 ]; then
463
+ echo "❌ Build failed"
464
+ exit 1
465
+ fi
466
+
467
+ # Run deployment
468
+ echo "📦 Deploying to \${ENVIRONMENT}..."
469
+ case \${ENVIRONMENT} in
470
+ "dev")
471
+ echo "🛠️ Deploying to development environment..."
472
+ # Add dev-specific deployment steps
473
+ ;;
474
+ "test")
475
+ echo "🧪 Deploying to test environment..."
476
+ # Add test-specific deployment steps
477
+ ;;
478
+ "prod")
479
+ echo "🚀 Deploying to production environment..."
480
+ # Add production-specific deployment steps
481
+ echo "⚠️ Production deployment requires manual approval"
482
+ ;;
483
+ *)
484
+ echo "❌ Unknown environment: \${ENVIRONMENT}"
485
+ exit 1
486
+ ;;
487
+ esac
488
+
489
+ echo "✅ Deployment completed for \${CLIENT_NAME} - \${ENVIRONMENT}"
490
+ echo "📝 Next steps:"
491
+ echo " 1. Verify deployment in Dynamics 365"
492
+ echo " 2. Run smoke tests"
493
+ echo " 3. Notify stakeholders"
494
+ `;
495
+
496
+ await fs.writeFile(path.join(scriptsPath, 'deploy-client.sh'), deployScript);
497
+ await fs.chmod(path.join(scriptsPath, 'deploy-client.sh'), '755');
498
+
499
+ console.log(chalk.green(` ✓ Created deployment scripts in ${scriptsPath}/`));
500
+ }
501
+
502
+ async function createProjectDocumentation(answers) {
503
+ const docsPath = 'docs';
504
+ await fs.ensureDir(docsPath);
505
+
506
+ // Client requirements document
507
+ const requirementsDoc = `# ${answers.clientName} - Technical Requirements
508
+
509
+ **Project:** ${answers.clientName} Dynamics 365 Implementation
510
+ **Industry:** ${answers.industry}
511
+ **Primary Contact:** ${answers.primaryContact} (${answers.contactEmail})
512
+ **Created:** ${new Date().toLocaleDateString()}
513
+
514
+ ## Overview
515
+
516
+ This document outlines the technical requirements and specifications for the ${answers.clientName} Dynamics 365 implementation.
517
+
518
+ ## Client Information
519
+
520
+ - **Company:** ${answers.clientName}
521
+ - **Industry:** ${answers.industry}
522
+ - **Timezone:** ${answers.timezone}
523
+ - **Primary Contact:** ${answers.primaryContact}
524
+ - **Email:** ${answers.contactEmail}
525
+
526
+ ## Technical Requirements
527
+
528
+ ### Environments
529
+ ${answers.environments.map(env => `- ${env.charAt(0).toUpperCase() + env.slice(1)}`).join('\n')}
530
+
531
+ ### Branding Requirements
532
+ - **Primary Color:** ${answers.primaryColor}
533
+ - **Secondary Color:** ${answers.secondaryColor}
534
+ - **Logo Requirements:** See branding guidelines
535
+
536
+ ### Features
537
+ ${answers.enableAdvancedFeatures ? `- Advanced logging and monitoring
538
+ - Custom workflows and business logic
539
+ - Enhanced reporting and dashboards
540
+ - Mobile optimization` : `- Standard CRM functionality
541
+ - Basic reporting
542
+ - Mobile responsive design`}
543
+
544
+ ## Security Requirements
545
+
546
+ - Multi-factor authentication for production
547
+ - Data encryption at rest and in transit
548
+ - Audit logging enabled
549
+ - Role-based access control
550
+
551
+ ## Compliance Requirements
552
+
553
+ - GDPR compliance required
554
+ - Data retention: 365 days
555
+ - Regular security assessments
556
+
557
+ ## Integration Requirements
558
+
559
+ TBD - To be defined based on client needs
560
+
561
+ ## Deployment Strategy
562
+
563
+ - Blue-green deployment for production
564
+ - Automated rollback capability
565
+ - Maintenance window: 2:00 AM ${answers.timezone}
566
+
567
+ ## Support Requirements
568
+
569
+ - Business hours support during implementation
570
+ - Post-go-live support plan TBD
571
+
572
+ ## Success Criteria
573
+
574
+ TBD - To be defined with client stakeholders
575
+
576
+ ## Next Steps
577
+
578
+ 1. Review and approve requirements
579
+ 2. Define detailed functional specifications
580
+ 3. Create project timeline
581
+ 4. Begin development sprint planning
582
+ `;
583
+
584
+ await fs.writeFile(path.join(docsPath, 'client-requirements.md'), requirementsDoc);
585
+
586
+ // Project README
587
+ const projectReadme = `# ${answers.clientName} - Dynamics 365 Project
588
+
589
+ ${answers.industry} company Dynamics 365 implementation using the Dynamics UI Kit enterprise consulting framework.
590
+
591
+ ## Quick Start
592
+
593
+ \`\`\`bash
594
+ # Install dependencies
595
+ npm install
596
+
597
+ # Start development
598
+ npm run dev
599
+
600
+ # Build for production
601
+ npm run build:prod
602
+
603
+ # Deploy to environment
604
+ ./scripts/deploy-client.sh dev
605
+ \`\`\`
606
+
607
+ ## Project Structure
608
+
609
+ - \`config/\` - Client and environment configurations
610
+ - \`src/branding/\` - Client-specific branding and themes
611
+ - \`src/entities/\` - Custom entity definitions
612
+ - \`src/pages/\` - Custom page templates
613
+ - \`scripts/\` - Deployment and automation scripts
614
+ - \`docs/\` - Project documentation
615
+
616
+ ## Configuration
617
+
618
+ Client configuration is managed in \`config/client.json\`. Environment-specific settings are in \`config/environments/\`.
619
+
620
+ ## Branding
621
+
622
+ Client branding assets should be placed in \`src/branding/logos/\`. The theme is configured in \`src/branding/theme.ts\`.
623
+
624
+ ## Deployment
625
+
626
+ Use the deployment script for environment-specific deployments:
627
+
628
+ \`\`\`bash
629
+ # Deploy to development
630
+ ./scripts/deploy-client.sh dev
631
+
632
+ # Deploy to production (requires approval)
633
+ ./scripts/deploy-client.sh prod
634
+ \`\`\`
635
+
636
+ ## Development Workflow
637
+
638
+ 1. Create feature branch
639
+ 2. Implement changes
640
+ 3. Run quality checks: \`npm run quality\`
641
+ 4. Deploy to dev: \`./scripts/deploy-client.sh dev\`
642
+ 5. Test and get approval
643
+ 6. Deploy to production
644
+
645
+ ## Support
646
+
647
+ For technical issues, contact the development team.
648
+ For client-specific questions, contact ${answers.primaryContact} at ${answers.contactEmail}.
649
+
650
+ ## Documentation
651
+
652
+ - [Client Requirements](docs/client-requirements.md)
653
+ - [Technical Specifications](docs/technical-specifications.md)
654
+ - [Deployment Guide](docs/deployment-guide.md)
655
+ `;
656
+
657
+ await fs.writeFile('README.md', projectReadme);
658
+
659
+ console.log(chalk.green(` ✓ Created project documentation in ${docsPath}/`));
660
+ }
661
+
662
+ // Run the setup if called directly
663
+ if (require.main === module) {
664
+ setupClientProject().catch(console.error);
665
+ }
666
+
667
+ module.exports = { setupClientProject };