@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
@@ -3,7 +3,7 @@ const HtmlWebpackPlugin = require('html-webpack-plugin');
3
3
 
4
4
  module.exports = (env, argv) => {
5
5
  const isProduction = argv.mode === 'production';
6
-
6
+
7
7
  return {
8
8
  entry: './src/index.tsx',
9
9
  output: {
@@ -11,8 +11,6 @@ module.exports = (env, argv) => {
11
11
  filename: isProduction ? '[name].[contenthash].js' : '[name].js',
12
12
  clean: true,
13
13
  publicPath: '/',
14
- library: 'DynamicsApp',
15
- libraryTarget: 'umd',
16
14
  },
17
15
  resolve: {
18
16
  extensions: ['.tsx', '.ts', '.js', '.jsx'],
@@ -21,7 +19,12 @@ module.exports = (env, argv) => {
21
19
  rules: [
22
20
  {
23
21
  test: /\.tsx?$/,
24
- use: 'ts-loader',
22
+ use: {
23
+ loader: 'ts-loader',
24
+ options: {
25
+ transpileOnly: true,
26
+ },
27
+ },
25
28
  exclude: /node_modules/,
26
29
  },
27
30
  {
@@ -45,14 +48,10 @@ module.exports = (env, argv) => {
45
48
  hot: true,
46
49
  historyApiFallback: true,
47
50
  },
48
- externals: isProduction ? {
49
- 'react': 'React',
50
- 'react-dom': 'ReactDOM'
51
- } : {},
52
51
  optimization: {
53
52
  splitChunks: {
54
53
  chunks: 'all',
55
54
  },
56
55
  },
57
56
  };
58
- };
57
+ };
@@ -5,20 +5,25 @@ This is a Power Pages application built with Dynamics UI Kit components.
5
5
  ## Getting Started
6
6
 
7
7
  1. **Environment Setup**
8
+
8
9
  ```bash
9
10
  cp .env.example .env
10
11
  ```
12
+
11
13
  Edit `.env` and set your `PORTAL_URL` to your Power Pages portal URL.
12
14
 
13
15
  2. **Install Dependencies**
16
+
14
17
  ```bash
15
18
  npm install
16
19
  ```
17
20
 
18
21
  3. **Development**
22
+
19
23
  ```bash
20
24
  npm run dev
21
25
  ```
26
+
22
27
  This starts the development server at http://localhost:3000
23
28
 
24
29
  4. **Build for Production**
@@ -52,6 +57,7 @@ src/
52
57
  To deploy your application to Power Pages:
53
58
 
54
59
  1. Build the application:
60
+
55
61
  ```bash
56
62
  npm run build
57
63
  ```
@@ -86,4 +92,4 @@ To deploy your application to Power Pages:
86
92
 
87
93
  - [Dynamics UI Kit Documentation](https://github.com/your-org/dynamics-ui-kit)
88
94
  - [Power Pages Documentation](https://docs.microsoft.com/power-pages/)
89
- - [React Documentation](https://reactjs.org/)
95
+ - [React Documentation](https://reactjs.org/)
@@ -1,18 +1,15 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="en">
3
- <head>
3
+ <head>
4
4
  <meta charset="utf-8" />
5
- <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
5
+ <link rel="icon" href="data:," />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1" />
7
- <meta name="theme-color" content="#0078d4" />
8
- <meta
9
- name="description"
10
- content="Power Pages application built with Dynamics UI Kit"
11
- />
7
+ <meta name="theme-color" content="#000000" />
8
+ <meta name="description" content="Power Pages Application built with Dynamics UI Kit" />
12
9
  <title>Power Pages App - Dynamics UI Kit</title>
13
- </head>
14
- <body>
10
+ </head>
11
+ <body>
15
12
  <noscript>You need to enable JavaScript to run this app.</noscript>
16
13
  <div id="root"></div>
17
- </body>
18
- </html>
14
+ </body>
15
+ </html>
@@ -1,9 +1,9 @@
1
1
  import React, { useState, useCallback } from 'react';
2
- import {
3
- Button,
4
- TextField,
5
- Dropdown,
6
- DatePicker
2
+ import {
3
+ Button,
4
+ TextField,
5
+ Dropdown,
6
+ DatePicker,
7
7
  } from '@khester/dynamics-ui-components';
8
8
  import { usePowerPagesApi } from '../providers/PowerPagesProvider';
9
9
  import './ContactForm.css';
@@ -20,19 +20,19 @@ interface ContactFormData {
20
20
  const preferredContactOptions = [
21
21
  { key: 'email', text: 'Email' },
22
22
  { key: 'phone', text: 'Phone' },
23
- { key: 'mail', text: 'Mail' }
23
+ { key: 'mail', text: 'Mail' },
24
24
  ];
25
25
 
26
26
  export const ContactForm: React.FC = () => {
27
27
  const { createRecord, isAuthenticated } = usePowerPagesApi();
28
-
28
+
29
29
  const [formData, setFormData] = useState<ContactFormData>({
30
30
  firstname: '',
31
31
  lastname: '',
32
32
  emailaddress1: '',
33
33
  telephone1: '',
34
34
  preferredcontactmethodcode: 1,
35
- birthdate: null
35
+ birthdate: null,
36
36
  });
37
37
 
38
38
  const [errors, setErrors] = useState<Partial<ContactFormData>>({});
@@ -57,7 +57,10 @@ export const ContactForm: React.FC = () => {
57
57
  newErrors.emailaddress1 = 'Please enter a valid email address';
58
58
  }
59
59
 
60
- if (formData.telephone1 && !/^\+?[\d\s\-\(\)]+$/.test(formData.telephone1)) {
60
+ if (
61
+ formData.telephone1 &&
62
+ !/^\+?[\d\s\-\(\)]+$/.test(formData.telephone1)
63
+ ) {
61
64
  newErrors.telephone1 = 'Please enter a valid phone number';
62
65
  }
63
66
 
@@ -65,16 +68,19 @@ export const ContactForm: React.FC = () => {
65
68
  return Object.keys(newErrors).length === 0;
66
69
  }, [formData]);
67
70
 
68
- const handleInputChange = useCallback((field: keyof ContactFormData, value: any) => {
69
- setFormData(prev => ({ ...prev, [field]: value }));
70
-
71
- // Clear error for this field when user starts typing
72
- if (errors[field]) {
73
- setErrors(prev => ({ ...prev, [field]: undefined }));
74
- }
75
- setSubmitError('');
76
- setSubmitSuccess(false);
77
- }, [errors]);
71
+ const handleInputChange = useCallback(
72
+ (field: keyof ContactFormData, value: any) => {
73
+ setFormData((prev) => ({ ...prev, [field]: value }));
74
+
75
+ // Clear error for this field when user starts typing
76
+ if (errors[field]) {
77
+ setErrors((prev) => ({ ...prev, [field]: undefined }));
78
+ }
79
+ setSubmitError('');
80
+ setSubmitSuccess(false);
81
+ },
82
+ [errors]
83
+ );
78
84
 
79
85
  const handleSubmit = useCallback(async () => {
80
86
  if (!isAuthenticated) {
@@ -97,11 +103,11 @@ export const ContactForm: React.FC = () => {
97
103
  emailaddress1: formData.emailaddress1.trim(),
98
104
  telephone1: formData.telephone1.trim() || null,
99
105
  preferredcontactmethodcode: formData.preferredcontactmethodcode,
100
- birthdate: formData.birthdate ? formData.birthdate.toISOString() : null
106
+ birthdate: formData.birthdate ? formData.birthdate.toISOString() : null,
101
107
  };
102
108
 
103
109
  await createRecord('contacts', contactData);
104
-
110
+
105
111
  setSubmitSuccess(true);
106
112
  // Reset form
107
113
  setFormData({
@@ -110,24 +116,26 @@ export const ContactForm: React.FC = () => {
110
116
  emailaddress1: '',
111
117
  telephone1: '',
112
118
  preferredcontactmethodcode: 1,
113
- birthdate: null
119
+ birthdate: null,
114
120
  });
115
121
  } catch (error) {
116
- setSubmitError(error instanceof Error ? error.message : 'An error occurred while saving');
122
+ setSubmitError(
123
+ error instanceof Error
124
+ ? error.message
125
+ : 'An error occurred while saving'
126
+ );
117
127
  } finally {
118
128
  setIsSubmitting(false);
119
129
  }
120
- }, [
121
- formData,
122
- isAuthenticated,
123
- validateForm,
124
- createRecord
125
- ]);
126
-
127
- const handlePreferredContactChange = useCallback((option: any) => {
128
- const code = option.key === 'email' ? 1 : option.key === 'phone' ? 2 : 3;
129
- handleInputChange('preferredcontactmethodcode', code);
130
- }, [handleInputChange]);
130
+ }, [formData, isAuthenticated, validateForm, createRecord]);
131
+
132
+ const handlePreferredContactChange = useCallback(
133
+ (option: any) => {
134
+ const code = option.key === 'email' ? 1 : option.key === 'phone' ? 2 : 3;
135
+ handleInputChange('preferredcontactmethodcode', code);
136
+ },
137
+ [handleInputChange]
138
+ );
131
139
 
132
140
  return (
133
141
  <div className="contact-form">
@@ -154,7 +162,9 @@ export const ContactForm: React.FC = () => {
154
162
  label="First Name"
155
163
  required
156
164
  value={formData.firstname}
157
- onChange={(_, value) => handleInputChange('firstname', value || '')}
165
+ onChange={(_, value) =>
166
+ handleInputChange('firstname', value || '')
167
+ }
158
168
  errorMessage={errors.firstname}
159
169
  disabled={isSubmitting}
160
170
  />
@@ -164,7 +174,9 @@ export const ContactForm: React.FC = () => {
164
174
  label="Last Name"
165
175
  required
166
176
  value={formData.lastname}
167
- onChange={(_, value) => handleInputChange('lastname', value || '')}
177
+ onChange={(_, value) =>
178
+ handleInputChange('lastname', value || '')
179
+ }
168
180
  errorMessage={errors.lastname}
169
181
  disabled={isSubmitting}
170
182
  />
@@ -178,7 +190,9 @@ export const ContactForm: React.FC = () => {
178
190
  type="email"
179
191
  required
180
192
  value={formData.emailaddress1}
181
- onChange={(_, value) => handleInputChange('emailaddress1', value || '')}
193
+ onChange={(_, value) =>
194
+ handleInputChange('emailaddress1', value || '')
195
+ }
182
196
  errorMessage={errors.emailaddress1}
183
197
  disabled={isSubmitting}
184
198
  />
@@ -188,7 +202,9 @@ export const ContactForm: React.FC = () => {
188
202
  label="Phone Number"
189
203
  type="tel"
190
204
  value={formData.telephone1}
191
- onChange={(_, value) => handleInputChange('telephone1', value || '')}
205
+ onChange={(_, value) =>
206
+ handleInputChange('telephone1', value || '')
207
+ }
192
208
  errorMessage={errors.telephone1}
193
209
  disabled={isSubmitting}
194
210
  />
@@ -201,8 +217,11 @@ export const ContactForm: React.FC = () => {
201
217
  label="Preferred Contact Method"
202
218
  options={preferredContactOptions}
203
219
  selectedKey={
204
- formData.preferredcontactmethodcode === 1 ? 'email' :
205
- formData.preferredcontactmethodcode === 2 ? 'phone' : 'mail'
220
+ formData.preferredcontactmethodcode === 1
221
+ ? 'email'
222
+ : formData.preferredcontactmethodcode === 2
223
+ ? 'phone'
224
+ : 'mail'
206
225
  }
207
226
  onChange={handlePreferredContactChange}
208
227
  disabled={isSubmitting}
@@ -236,4 +255,4 @@ export const ContactForm: React.FC = () => {
236
255
  )}
237
256
  </div>
238
257
  );
239
- };
258
+ };
@@ -12,11 +12,11 @@ const App: React.FC = () => {
12
12
  <h1>Power Pages Contact Management</h1>
13
13
  <p>Built with Dynamics UI Kit</p>
14
14
  </header>
15
-
15
+
16
16
  <main className="app-main">
17
17
  <ContactForm />
18
18
  </main>
19
-
19
+
20
20
  <footer className="app-footer">
21
21
  <p>&copy; 2024 Your Organization. Powered by Dynamics UI Kit.</p>
22
22
  </footer>
@@ -29,4 +29,4 @@ const container = document.getElementById('root');
29
29
  if (!container) throw new Error('Failed to find the root element');
30
30
 
31
31
  const root = createRoot(container);
32
- root.render(<App />);
32
+ root.render(<App />);
@@ -5,35 +5,45 @@ interface PowerPagesContextType {
5
5
  apiService: PowerPagesApiService | null;
6
6
  isAuthenticated: boolean;
7
7
  createRecord: (entityName: string, data: any) => Promise<any>;
8
- retrieveRecord: (entityName: string, id: string, select?: string) => Promise<any>;
8
+ retrieveRecord: (
9
+ entityName: string,
10
+ id: string,
11
+ select?: string
12
+ ) => Promise<any>;
9
13
  updateRecord: (entityName: string, id: string, data: any) => Promise<any>;
10
14
  deleteRecord: (entityName: string, id: string) => Promise<void>;
11
15
  retrieveMultiple: (entityName: string, query?: string) => Promise<any>;
12
16
  }
13
17
 
14
- const PowerPagesContext = createContext<PowerPagesContextType | undefined>(undefined);
18
+ const PowerPagesContext = createContext<PowerPagesContextType | undefined>(
19
+ undefined
20
+ );
15
21
 
16
22
  interface PowerPagesProviderProps {
17
23
  children: React.ReactNode;
18
24
  }
19
25
 
20
- export const PowerPagesProvider: React.FC<PowerPagesProviderProps> = ({ children }) => {
21
- const [apiService, setApiService] = useState<PowerPagesApiService | null>(null);
26
+ export const PowerPagesProvider: React.FC<PowerPagesProviderProps> = ({
27
+ children,
28
+ }) => {
29
+ const [apiService, setApiService] = useState<PowerPagesApiService | null>(
30
+ null
31
+ );
22
32
  const [isAuthenticated, setIsAuthenticated] = useState(false);
23
33
 
24
34
  useEffect(() => {
25
35
  // Initialize the API service
26
- const portalUrl = process.env.PORTAL_URL || window.location.origin;
27
-
36
+ const portalUrl = window.location.origin;
37
+
28
38
  // CSRF token function for Power Pages authentication
29
39
  const getCsrfToken = async (): Promise<string> => {
30
40
  // In a real Power Pages implementation, you would fetch the CSRF token
31
41
  // For demo purposes, return empty string
32
42
  return '';
33
43
  };
34
-
44
+
35
45
  const service = new PowerPagesApiService(portalUrl, getCsrfToken);
36
-
46
+
37
47
  setApiService(service);
38
48
 
39
49
  // Check authentication status
@@ -47,11 +57,19 @@ export const PowerPagesProvider: React.FC<PowerPagesProviderProps> = ({ children
47
57
  return await apiService.createRecord(entityName, data);
48
58
  };
49
59
 
50
- const retrieveRecord = async (entityName: string, id: string, select?: string) => {
60
+ const retrieveRecord = async (
61
+ entityName: string,
62
+ id: string,
63
+ select?: string
64
+ ) => {
51
65
  if (!apiService) throw new Error('API service not initialized');
52
66
  // Use retrieveMultipleRecords with FetchXML to get a single record
53
- const selectAttributes = select ? select.split(',').map(attr => attr.trim()) : ['*'];
54
- const attributes = selectAttributes.map(attr => attr === '*' ? '' : `<attribute name="${attr}" />`).join('');
67
+ const selectAttributes = select
68
+ ? select.split(',').map((attr) => attr.trim())
69
+ : ['*'];
70
+ const attributes = selectAttributes
71
+ .map((attr) => (attr === '*' ? '' : `<attribute name="${attr}" />`))
72
+ .join('');
55
73
  const fetchXml = `
56
74
  <fetch top="1">
57
75
  <entity name="${entityName}">
@@ -62,7 +80,10 @@ export const PowerPagesProvider: React.FC<PowerPagesProviderProps> = ({ children
62
80
  </entity>
63
81
  </fetch>
64
82
  `;
65
- const result = await apiService.retrieveMultipleRecords(entityName, fetchXml);
83
+ const result = await apiService.retrieveMultipleRecords(
84
+ entityName,
85
+ fetchXml
86
+ );
66
87
  return result.entities.length > 0 ? result.entities[0] : null;
67
88
  };
68
89
 
@@ -80,36 +101,36 @@ export const PowerPagesProvider: React.FC<PowerPagesProviderProps> = ({ children
80
101
  if (!apiService) throw new Error('API service not initialized');
81
102
  // Convert OData-style query to FetchXML
82
103
  let fetchXml = `<fetch>`;
83
-
104
+
84
105
  if (query) {
85
106
  // Parse basic OData query parameters
86
107
  const selectMatch = query.match(/\$select=([^&]*)/i);
87
108
  const orderByMatch = query.match(/\$orderby=([^&]*)/i);
88
109
  const topMatch = query.match(/\$top=(\d+)/i);
89
-
110
+
90
111
  if (topMatch) {
91
112
  fetchXml = `<fetch top="${topMatch[1]}">`;
92
113
  }
93
-
114
+
94
115
  fetchXml += `<entity name="${entityName}">`;
95
-
116
+
96
117
  if (selectMatch) {
97
- const attributes = selectMatch[1].split(',').map(attr => attr.trim());
98
- attributes.forEach(attr => {
118
+ const attributes = selectMatch[1].split(',').map((attr) => attr.trim());
119
+ attributes.forEach((attr) => {
99
120
  fetchXml += `<attribute name="${attr}" />`;
100
121
  });
101
122
  }
102
-
123
+
103
124
  if (orderByMatch) {
104
125
  const [field, direction] = orderByMatch[1].split(' ');
105
126
  fetchXml += `<order attribute="${field.trim()}" descending="${direction?.toLowerCase() === 'desc'}" />`;
106
127
  }
107
-
128
+
108
129
  fetchXml += `</entity></fetch>`;
109
130
  } else {
110
131
  fetchXml = `<fetch><entity name="${entityName}"></entity></fetch>`;
111
132
  }
112
-
133
+
113
134
  return await apiService.retrieveMultipleRecords(entityName, fetchXml);
114
135
  };
115
136
 
@@ -133,7 +154,9 @@ export const PowerPagesProvider: React.FC<PowerPagesProviderProps> = ({ children
133
154
  export const usePowerPagesApi = (): PowerPagesContextType => {
134
155
  const context = useContext(PowerPagesContext);
135
156
  if (context === undefined) {
136
- throw new Error('usePowerPagesApi must be used within a PowerPagesProvider');
157
+ throw new Error(
158
+ 'usePowerPagesApi must be used within a PowerPagesProvider'
159
+ );
137
160
  }
138
161
  return context;
139
- };
162
+ };
@@ -1,11 +1,7 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "target": "es5",
4
- "lib": [
5
- "dom",
6
- "dom.iterable",
7
- "es6"
8
- ],
4
+ "lib": ["dom", "dom.iterable", "es6"],
9
5
  "allowJs": true,
10
6
  "skipLibCheck": true,
11
7
  "esModuleInterop": true,
@@ -20,7 +16,5 @@
20
16
  "noEmit": true,
21
17
  "jsx": "react-jsx"
22
18
  },
23
- "include": [
24
- "src"
25
- ]
26
- }
19
+ "include": ["src"]
20
+ }
@@ -3,7 +3,7 @@ const HtmlWebpackPlugin = require('html-webpack-plugin');
3
3
 
4
4
  module.exports = (env, argv) => {
5
5
  const isProduction = argv.mode === 'production';
6
-
6
+
7
7
  return {
8
8
  entry: './src/index.tsx',
9
9
  output: {
@@ -19,7 +19,12 @@ module.exports = (env, argv) => {
19
19
  rules: [
20
20
  {
21
21
  test: /\.tsx?$/,
22
- use: 'ts-loader',
22
+ use: {
23
+ loader: 'ts-loader',
24
+ options: {
25
+ transpileOnly: true,
26
+ },
27
+ },
23
28
  exclude: /node_modules/,
24
29
  },
25
30
  {
@@ -49,4 +54,4 @@ module.exports = (env, argv) => {
49
54
  },
50
55
  },
51
56
  };
52
- };
57
+ };