@khester/create-dynamics-app 1.1.0 → 2.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 (210) hide show
  1. package/README.md +74 -0
  2. package/dist/artifacts/registry.d.ts +18 -0
  3. package/dist/artifacts/registry.d.ts.map +1 -0
  4. package/dist/artifacts/registry.js +340 -0
  5. package/dist/artifacts/registry.js.map +1 -0
  6. package/dist/artifacts/types.d.ts +122 -0
  7. package/dist/artifacts/types.d.ts.map +1 -0
  8. package/dist/artifacts/types.js +7 -0
  9. package/dist/artifacts/types.js.map +1 -0
  10. package/dist/artifacts/validators.d.ts +16 -0
  11. package/dist/artifacts/validators.d.ts.map +1 -0
  12. package/dist/artifacts/validators.js +45 -0
  13. package/dist/artifacts/validators.js.map +1 -0
  14. package/dist/fromDesign.d.ts +5 -0
  15. package/dist/fromDesign.d.ts.map +1 -0
  16. package/dist/fromDesign.js +98 -0
  17. package/dist/fromDesign.js.map +1 -0
  18. package/dist/index.js +129 -177
  19. package/dist/index.js.map +1 -1
  20. package/dist/injectDevTools.d.ts +28 -0
  21. package/dist/injectDevTools.d.ts.map +1 -0
  22. package/dist/injectDevTools.js +148 -0
  23. package/dist/injectDevTools.js.map +1 -0
  24. package/dist/scaffold.d.ts +48 -0
  25. package/dist/scaffold.d.ts.map +1 -0
  26. package/dist/scaffold.js +180 -0
  27. package/dist/scaffold.js.map +1 -0
  28. package/dist/templatePlan.d.ts +3 -0
  29. package/dist/templatePlan.d.ts.map +1 -0
  30. package/dist/templatePlan.js +43 -0
  31. package/dist/templatePlan.js.map +1 -0
  32. package/dist/utils/copyTemplate.d.ts +13 -1
  33. package/dist/utils/copyTemplate.d.ts.map +1 -1
  34. package/dist/utils/copyTemplate.js +98 -4
  35. package/dist/utils/copyTemplate.js.map +1 -1
  36. package/dist/utils/updatePackageJson.d.ts +11 -1
  37. package/dist/utils/updatePackageJson.d.ts.map +1 -1
  38. package/dist/utils/updatePackageJson.js +12 -10
  39. package/dist/utils/updatePackageJson.js.map +1 -1
  40. package/package.json +10 -7
  41. package/templates/_shared/dev-tools/auth/get-token.js +72 -0
  42. package/templates/_shared/dev-tools/dev/mock-xrm.js +42 -0
  43. package/templates/_shared/dev-tools/metadata-sync/index.js +152 -0
  44. package/templates/_shared/dev-tools/smoke/test-retrieve.js +44 -0
  45. package/templates/dialog-form/README.md +27 -0
  46. package/templates/dialog-form/_variants/App.v8.tsx +39 -0
  47. package/templates/dialog-form/_variants/App.v9.tsx +41 -0
  48. package/templates/dialog-form/gitignore +5 -0
  49. package/templates/dialog-form/package.json +27 -0
  50. package/templates/dialog-form/public/index.html +11 -0
  51. package/templates/dialog-form/src/index.tsx +10 -0
  52. package/templates/dialog-form/src/services/dataverse.ts +30 -0
  53. package/templates/dialog-form/tsconfig.json +15 -0
  54. package/templates/dialog-form/webpack.config.js +17 -0
  55. package/templates/grid-customizer/README.md +28 -0
  56. package/templates/grid-customizer/gitignore +4 -0
  57. package/templates/grid-customizer/package.json +25 -0
  58. package/templates/grid-customizer/src/GridCustomizer.ts +28 -0
  59. package/templates/grid-customizer/src/cell-renderers.tsx +35 -0
  60. package/templates/grid-customizer/src/index.ts +4 -0
  61. package/templates/grid-customizer/src/types/grid-types.ts +30 -0
  62. package/templates/grid-customizer/src/utils/color-utils.ts +24 -0
  63. package/templates/grid-customizer/tsconfig.json +15 -0
  64. package/templates/grid-customizer/webpack.config.js +17 -0
  65. package/templates/pcf-dataset/ControlManifest.Input.xml +16 -0
  66. package/templates/pcf-dataset/README.md +21 -0
  67. package/templates/pcf-dataset/gitignore +5 -0
  68. package/templates/pcf-dataset/index.ts +39 -0
  69. package/templates/pcf-dataset/package.json +30 -0
  70. package/templates/pcf-dataset/strings/{{componentName}}.1033.resx +47 -0
  71. package/templates/pcf-dataset/tsconfig.json +8 -0
  72. package/templates/pcf-dataset/{{componentName}}Component.tsx +39 -0
  73. package/templates/pcf-field/ControlManifest.Input.xml +17 -0
  74. package/templates/pcf-field/README.md +95 -0
  75. package/templates/pcf-field/_variants/ValueInput.boolean.tsx +24 -0
  76. package/templates/pcf-field/_variants/ValueInput.date.tsx +27 -0
  77. package/templates/pcf-field/_variants/ValueInput.number.tsx +35 -0
  78. package/templates/pcf-field/_variants/ValueInput.text.tsx +27 -0
  79. package/templates/pcf-field/gitignore +5 -0
  80. package/templates/pcf-field/index.ts +61 -0
  81. package/templates/pcf-field/package.json +30 -0
  82. package/templates/pcf-field/strings/{{componentName}}.1033.resx +47 -0
  83. package/templates/pcf-field/tsconfig.json +8 -0
  84. package/templates/pcf-field/{{componentName}}Component.tsx +35 -0
  85. package/templates/power-pages-starter/gitignore +5 -0
  86. package/templates/react-custom-page/gitignore +5 -0
  87. package/templates/{dynamics-365-starter → react-custom-page}/package.json +3 -3
  88. package/templates/react-custom-page/tools/metadata-sync/index.js +152 -0
  89. package/templates/static-web-app/README.md +36 -0
  90. package/templates/static-web-app/_variants/App.v8.tsx +32 -0
  91. package/templates/static-web-app/_variants/App.v9.tsx +31 -0
  92. package/templates/static-web-app/api/host.json +12 -0
  93. package/templates/static-web-app/api/package.json +19 -0
  94. package/templates/static-web-app/api/src/functions/hello.ts +16 -0
  95. package/templates/static-web-app/api/tsconfig.json +14 -0
  96. package/templates/static-web-app/frontend/index.html +12 -0
  97. package/templates/static-web-app/frontend/package.json +23 -0
  98. package/templates/static-web-app/frontend/src/index.tsx +8 -0
  99. package/templates/static-web-app/frontend/tsconfig.json +16 -0
  100. package/templates/static-web-app/frontend/vite.config.ts +13 -0
  101. package/templates/static-web-app/gitignore +8 -0
  102. package/templates/static-web-app/package.json +15 -0
  103. package/templates/static-web-app/staticwebapp.config.json +7 -0
  104. package/templates/teams-app/README.md +27 -0
  105. package/templates/teams-app/_variants/graph.off.ts +7 -0
  106. package/templates/teams-app/_variants/graph.on.ts +22 -0
  107. package/templates/teams-app/appPackage/manifest.json +26 -0
  108. package/templates/teams-app/gitignore +5 -0
  109. package/templates/teams-app/index.html +12 -0
  110. package/templates/teams-app/package.json +26 -0
  111. package/templates/teams-app/src/App.tsx +25 -0
  112. package/templates/teams-app/src/index.tsx +8 -0
  113. package/templates/teams-app/tsconfig.json +16 -0
  114. package/templates/teams-app/vite.config.ts +9 -0
  115. package/templates/web-resource/README.md +39 -0
  116. package/templates/web-resource/_variants/App.v8.tsx +29 -0
  117. package/templates/web-resource/_variants/App.v9.tsx +28 -0
  118. package/templates/web-resource/gitignore +5 -0
  119. package/templates/web-resource/package.json +27 -0
  120. package/templates/web-resource/public/index.html +11 -0
  121. package/templates/web-resource/src/index.tsx +10 -0
  122. package/templates/web-resource/src/services/dataverse.ts +30 -0
  123. package/templates/web-resource/tsconfig.json +15 -0
  124. package/templates/web-resource/webpack.config.js +17 -0
  125. package/dist/utils/consultingHelpers.d.ts +0 -13
  126. package/dist/utils/consultingHelpers.d.ts.map +0 -1
  127. package/dist/utils/consultingHelpers.js +0 -569
  128. package/dist/utils/consultingHelpers.js.map +0 -1
  129. package/templates/dynamics-365-starter/INTEGRATION_TEST_RESULTS.md +0 -302
  130. package/templates/dynamics-365-starter/PHASE_4_COMPLETION_SUMMARY.md +0 -305
  131. package/templates/dynamics-365-starter/deployment/QUICKSTART-MAC.md +0 -507
  132. package/templates/dynamics-365-starter/deployment/QUICKSTART-WINDOWS.md +0 -372
  133. package/templates/dynamics-365-starter/deployment/pipelines/README.md +0 -375
  134. package/templates/dynamics-365-starter/deployment/pipelines/azure-pipelines.yml +0 -330
  135. package/templates/dynamics-365-starter/deployment/pipelines/github-actions.yml +0 -422
  136. package/templates/dynamics-365-starter/deployment/pipelines/jenkins.groovy +0 -636
  137. package/templates/dynamics-365-starter/deployment/scripts/deploy.ps1 +0 -417
  138. package/templates/dynamics-365-starter/deployment/scripts/deploy.sh +0 -582
  139. package/templates/dynamics-365-starter/deployment/scripts/team-onboarding.ps1 +0 -486
  140. package/templates/dynamics-365-starter/deployment/scripts/team-onboarding.sh +0 -567
  141. package/templates/dynamics-365-starter/deployment/scripts/validate-setup.ps1 +0 -703
  142. package/templates/dynamics-365-starter/deployment/scripts/validate-setup.sh +0 -671
  143. package/templates/dynamics-365-starter/docs/team-standards/README.md +0 -273
  144. package/templates/dynamics-365-starter/docs/team-standards/client-onboarding.md +0 -577
  145. package/templates/dynamics-365-starter/docs/team-standards/code-review-checklist.md +0 -359
  146. package/templates/dynamics-365-starter/docs/team-standards/coding-standards.md +0 -700
  147. package/templates/dynamics-365-starter/docs/team-standards/cross-platform-team-guide.md +0 -736
  148. package/templates/dynamics-365-starter/docs/team-standards/development-workflows.md +0 -727
  149. package/templates/dynamics-365-starter/docs/troubleshooting/common-errors.md +0 -758
  150. package/templates/dynamics-365-starter/docs/troubleshooting/platform-specific-issues.md +0 -878
  151. package/templates/dynamics-365-starter/src/client-project-template/README.md +0 -234
  152. package/templates/dynamics-365-starter/src/client-project-template/config/client.template.json +0 -114
  153. package/templates/dynamics-365-starter/src/client-project-template/config/environments/template.json +0 -186
  154. package/templates/dynamics-365-starter/src/client-project-template/scripts/client-setup.js +0 -667
  155. package/templates/dynamics-365-starter/src/examples/README.md +0 -52
  156. package/templates/dynamics-365-starter/src/examples/component-examples/opportunity-management.tsx +0 -625
  157. package/templates/dynamics-365-starter/src/examples/entity-examples/opportunity-model.ts +0 -545
  158. package/templates/dynamics-365-starter/src/examples/integration-examples/custom-pcf-wrapper.tsx +0 -722
  159. package/templates/dynamics-365-starter/src/examples/workflow-examples/sales-workflow.ts +0 -662
  160. package/templates/dynamics-365-starter/src/page-templates/EntityDashboard.tsx +0 -519
  161. package/templates/dynamics-365-starter/src/page-templates/EntityDetailPage.tsx +0 -456
  162. package/templates/dynamics-365-starter/src/page-templates/EntityListPage.tsx +0 -406
  163. package/templates/dynamics-365-starter/src/page-templates/RelatedEntitiesPage.tsx +0 -578
  164. package/templates/dynamics-365-starter/src/page-templates/SearchPage.tsx +0 -629
  165. package/templates/dynamics-365-starter/tools/entity-generator/index.js +0 -168
  166. package/templates/dynamics-365-starter/tools/entity-generator/templates/constants.template.ts +0 -124
  167. package/templates/dynamics-365-starter/tools/entity-generator/templates/form.template.css +0 -283
  168. package/templates/dynamics-365-starter/tools/entity-generator/templates/form.template.tsx +0 -275
  169. package/templates/dynamics-365-starter/tools/entity-generator/templates/management.template.css +0 -204
  170. package/templates/dynamics-365-starter/tools/entity-generator/templates/management.template.tsx +0 -413
  171. package/templates/dynamics-365-starter/tools/entity-generator/templates/model.template.ts +0 -250
  172. package/templates/dynamics-365-starter/tools/metadata-sync/d365-client.js +0 -410
  173. package/templates/dynamics-365-starter/tools/metadata-sync/index.js +0 -512
  174. package/templates/dynamics-365-starter/tools/metadata-sync/type-generator.js +0 -675
  175. /package/templates/{dynamics-365-starter → react-custom-page}/README.md +0 -0
  176. /package/templates/{dynamics-365-starter → react-custom-page}/deployment/README.md +0 -0
  177. /package/templates/{dynamics-365-starter → react-custom-page}/docs/ARCHITECTURE_OVERVIEW.md +0 -0
  178. /package/templates/{dynamics-365-starter → react-custom-page}/docs/BEST_PRACTICES.md +0 -0
  179. /package/templates/{dynamics-365-starter → react-custom-page}/docs/MIGRATION_GUIDE.md +0 -0
  180. /package/templates/{dynamics-365-starter → react-custom-page}/public/index.html +0 -0
  181. /package/templates/{dynamics-365-starter → react-custom-page}/scripts/custom-build.js +0 -0
  182. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/AccountForm.css +0 -0
  183. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/AccountForm.tsx +0 -0
  184. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/AccountManagement.css +0 -0
  185. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/AccountManagement.tsx +0 -0
  186. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/ContactForm.css +0 -0
  187. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/ContactForm.tsx +0 -0
  188. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/ContactManagement.css +0 -0
  189. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/ContactManagement.tsx +0 -0
  190. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/Logging/LogDialog.tsx +0 -0
  191. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/Logging/LoggingContext.tsx +0 -0
  192. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/Logging/LoggingDebugPanel.css +0 -0
  193. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/Logging/LoggingDebugPanel.tsx +0 -0
  194. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/Logging/LoggingProvider.tsx +0 -0
  195. /package/templates/{dynamics-365-starter → react-custom-page}/src/components/Logging/logger.ts +0 -0
  196. /package/templates/{dynamics-365-starter → react-custom-page}/src/constants/account.ts +0 -0
  197. /package/templates/{dynamics-365-starter → react-custom-page}/src/constants/contact.ts +0 -0
  198. /package/templates/{dynamics-365-starter → react-custom-page}/src/index.tsx +0 -0
  199. /package/templates/{dynamics-365-starter → react-custom-page}/src/models/Account.ts +0 -0
  200. /package/templates/{dynamics-365-starter → react-custom-page}/src/models/BaseEntity.ts +0 -0
  201. /package/templates/{dynamics-365-starter → react-custom-page}/src/models/Contact.ts +0 -0
  202. /package/templates/{dynamics-365-starter → react-custom-page}/src/pcf/ContactControlWrapper.tsx +0 -0
  203. /package/templates/{dynamics-365-starter → react-custom-page}/src/pcf/MultiEntityControlWrapper.tsx +0 -0
  204. /package/templates/{dynamics-365-starter → react-custom-page}/src/providers/DynamicsProvider.tsx +0 -0
  205. /package/templates/{dynamics-365-starter → react-custom-page}/src/services/MockApiService.ts +0 -0
  206. /package/templates/{dynamics-365-starter → react-custom-page}/src/services/ServiceFactory.ts +0 -0
  207. /package/templates/{dynamics-365-starter → react-custom-page}/src/services/XrmApiService.ts +0 -0
  208. /package/templates/{dynamics-365-starter → react-custom-page}/src/styles/index.css +0 -0
  209. /package/templates/{dynamics-365-starter → react-custom-page}/tsconfig.json +0 -0
  210. /package/templates/{dynamics-365-starter → react-custom-page}/webpack.config.js +0 -0
@@ -0,0 +1,27 @@
1
+ # {{projectName}}
2
+
3
+ A **Microsoft Teams tab** — React + Fluent UI v9 + `@microsoft/teams-js`.
4
+
5
+ ## Develop
6
+
7
+ ```bash
8
+ npm install
9
+ npm run dev # vite on http://localhost:3000 (serve over HTTPS for Teams)
10
+ npm run build # production bundle → dist/
11
+ npm run typecheck # tsc --noEmit
12
+ ```
13
+
14
+ `src/App.tsx` initializes the Teams SDK and shows the signed-in user. Edit `appPackage/manifest.json`
15
+ (and add `color.png` / `outline.png`) before sideloading.
16
+
17
+ ## Microsoft Graph
18
+
19
+ `src/services/graph.ts` is generated based on the Graph option you chose at scaffold time:
20
+
21
+ - **enabled** → a `createGraphClient(getToken)` wrapper (`@microsoft/microsoft-graph-client` is added
22
+ to dependencies).
23
+ - **disabled** → a stub that throws until you re-scaffold with Graph enabled.
24
+
25
+ ## Package & sideload
26
+
27
+ Zip `appPackage/` (manifest + icons) and upload it to Teams (Apps → Manage your apps → Upload a custom app).
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Microsoft Graph integration is disabled for this app. Re-scaffold with Graph
3
+ * enabled (answer "yes" to the Graph prompt, or pass --graph) to wire it up.
4
+ */
5
+ export function createGraphClient(): never {
6
+ throw new Error('Graph integration is disabled. Re-scaffold with Graph enabled to use it.');
7
+ }
@@ -0,0 +1,22 @@
1
+ import { Client } from '@microsoft/microsoft-graph-client';
2
+
3
+ /**
4
+ * Create a Microsoft Graph client. Supply a token getter (e.g. Teams SSO via
5
+ * `authentication.getAuthToken()` exchanged for a Graph token server-side).
6
+ */
7
+ export function createGraphClient(getToken: () => Promise<string>): Client {
8
+ return Client.init({
9
+ authProvider: async (done) => {
10
+ try {
11
+ done(null, await getToken());
12
+ } catch (e) {
13
+ done(e as Error, null);
14
+ }
15
+ },
16
+ });
17
+ }
18
+
19
+ /** Convenience: the signed-in user's profile. */
20
+ export async function getMe(client: Client): Promise<unknown> {
21
+ return client.api('/me').get();
22
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.16/MicrosoftTeams.schema.json",
3
+ "manifestVersion": "1.16",
4
+ "id": "00000000-0000-0000-0000-000000000000",
5
+ "version": "1.0.0",
6
+ "developer": {
7
+ "name": "Contoso",
8
+ "websiteUrl": "https://example.com",
9
+ "privacyUrl": "https://example.com/privacy",
10
+ "termsOfUseUrl": "https://example.com/terms"
11
+ },
12
+ "name": { "short": "{{projectName}}", "full": "{{projectName}}" },
13
+ "description": { "short": "{{projectName}} tab", "full": "{{projectName}} Microsoft Teams tab" },
14
+ "icons": { "color": "color.png", "outline": "outline.png" },
15
+ "accentColor": "#6264A7",
16
+ "staticTabs": [
17
+ {
18
+ "entityId": "home",
19
+ "name": "{{projectName}}",
20
+ "contentUrl": "https://localhost:3000/",
21
+ "scopes": ["personal"]
22
+ }
23
+ ],
24
+ "permissions": ["identity"],
25
+ "validDomains": ["localhost"]
26
+ }
@@ -0,0 +1,5 @@
1
+ node_modules/
2
+ dist/
3
+ .env
4
+ .env.local
5
+ *.log
@@ -0,0 +1,12 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>{{projectName}}</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ <script type="module" src="/src/index.tsx"></script>
11
+ </body>
12
+ </html>
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "{{projectName}}",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "description": "{{projectName}} — Microsoft Teams tab (React, Fluent v9)",
7
+ "scripts": {
8
+ "dev": "vite",
9
+ "build": "tsc && vite build",
10
+ "preview": "vite preview",
11
+ "typecheck": "tsc --noEmit"
12
+ },
13
+ "dependencies": {
14
+ "react": "^18.2.0",
15
+ "react-dom": "^18.2.0",
16
+ "@fluentui/react-components": "^9.46.2",
17
+ "@microsoft/teams-js": "^2.19.0"
18
+ },
19
+ "devDependencies": {
20
+ "@types/react": "^18.2.0",
21
+ "@types/react-dom": "^18.2.0",
22
+ "@vitejs/plugin-react": "^4.2.1",
23
+ "typescript": "^5.3.3",
24
+ "vite": "^5.1.4"
25
+ }
26
+ }
@@ -0,0 +1,25 @@
1
+ import * as React from 'react';
2
+ import { FluentProvider, teamsLightTheme, Text, Spinner } from '@fluentui/react-components';
3
+ import { app } from '@microsoft/teams-js';
4
+
5
+ export const App: React.FC = () => {
6
+ const [status, setStatus] = React.useState<string | null>(null);
7
+
8
+ React.useEffect(() => {
9
+ app
10
+ .initialize()
11
+ .then(() => app.getContext())
12
+ .then((ctx) => setStatus(ctx.user?.userPrincipalName ?? 'unknown user'))
13
+ .catch((e) => setStatus(`Not running in Teams: ${String(e)}`));
14
+ }, []);
15
+
16
+ return (
17
+ <FluentProvider theme={teamsLightTheme}>
18
+ <div style={{ display: 'flex', flexDirection: 'column', gap: 12, padding: 16 }}>
19
+ <Text size={600} weight="semibold">{{projectName}}</Text>
20
+ <Text>Microsoft Teams tab — Fluent UI v9.</Text>
21
+ {status === null ? <Spinner label="Initializing Teams…" /> : <Text>Signed in as: {status}</Text>}
22
+ </div>
23
+ </FluentProvider>
24
+ );
25
+ };
@@ -0,0 +1,8 @@
1
+ import * as React from 'react';
2
+ import { createRoot } from 'react-dom/client';
3
+ import { App } from './App';
4
+
5
+ const container = document.getElementById('root');
6
+ if (container) {
7
+ createRoot(container).render(<App />);
8
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "useDefineForClassFields": true,
5
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
6
+ "module": "ESNext",
7
+ "moduleResolution": "bundler",
8
+ "jsx": "react-jsx",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "noEmit": true,
13
+ "isolatedModules": true
14
+ },
15
+ "include": ["src"]
16
+ }
@@ -0,0 +1,9 @@
1
+ import { defineConfig } from 'vite';
2
+ import react from '@vitejs/plugin-react';
3
+
4
+ export default defineConfig({
5
+ plugins: [react()],
6
+ // Teams tabs must be served over HTTPS; `vite --https` or a tunnel in dev.
7
+ server: { port: 3000 },
8
+ build: { outDir: 'dist' },
9
+ });
@@ -0,0 +1,39 @@
1
+ # {{projectName}}
2
+
3
+ A Dynamics 365 **web resource** built with React + Fluent UI ({{componentLibrary}}), bundled to a
4
+ single JS file you can upload as a web resource.
5
+
6
+ ## Develop
7
+
8
+ ```bash
9
+ npm install
10
+ npm run dev # webpack dev server on http://localhost:8080
11
+ npm run build # production bundle → dist/{{projectName}}.js
12
+ npm run typecheck # tsc --noEmit
13
+ ```
14
+
15
+ ## Local data access
16
+
17
+ `src/services/dataverse.ts` wraps `Xrm.WebApi`. Outside a model-driven host (e.g. `npm run dev`),
18
+ stub it with the `serve` dev-tool's mock:
19
+
20
+ ```ts
21
+ import { installMockXrm } from '../tools/dev/mock-xrm.js';
22
+ if (location.hostname === 'localhost') installMockXrm();
23
+ ```
24
+
25
+ ## Acquire a token (for codegen / live calls)
26
+
27
+ ```bash
28
+ npm run auth:token -- --url https://YOUR_ORG.crm.dynamics.com
29
+ ```
30
+
31
+ ## Generate typed entities from a live org
32
+
33
+ ```bash
34
+ npm run metadata:pull -- --entities account,contact
35
+ ```
36
+
37
+ ## Deploy
38
+
39
+ Upload `dist/{{projectName}}.js` (and the bundled HTML if needed) as a web resource in your solution.
@@ -0,0 +1,29 @@
1
+ import * as React from 'react';
2
+ import { ThemeProvider } from '@fluentui/react/lib/Theme';
3
+ import { Stack } from '@fluentui/react/lib/Stack';
4
+ import { Text } from '@fluentui/react/lib/Text';
5
+ import { PrimaryButton } from '@fluentui/react/lib/Button';
6
+ import { retrieveMultiple } from './services/dataverse';
7
+
8
+ export const App: React.FC = () => {
9
+ const onClick = async () => {
10
+ try {
11
+ const rows = await retrieveMultiple('account', '?$select=name&$top=5');
12
+ alert(`Retrieved ${rows.length} account(s).`);
13
+ } catch (e) {
14
+ alert(`Xrm.WebApi not available here: ${String(e)}`);
15
+ }
16
+ };
17
+
18
+ return (
19
+ <ThemeProvider>
20
+ <Stack tokens={{ childrenGap: 12, padding: 16 }}>
21
+ <Text variant="xLarge">{{projectName}}</Text>
22
+ <Text>Dynamics 365 web resource — Fluent UI v8.</Text>
23
+ <Stack.Item>
24
+ <PrimaryButton text="Retrieve accounts" onClick={onClick} />
25
+ </Stack.Item>
26
+ </Stack>
27
+ </ThemeProvider>
28
+ );
29
+ };
@@ -0,0 +1,28 @@
1
+ import * as React from 'react';
2
+ import { FluentProvider, webLightTheme, Text, Button } from '@fluentui/react-components';
3
+ import { retrieveMultiple } from './services/dataverse';
4
+
5
+ export const App: React.FC = () => {
6
+ const onClick = async () => {
7
+ try {
8
+ const rows = await retrieveMultiple('account', '?$select=name&$top=5');
9
+ alert(`Retrieved ${rows.length} account(s).`);
10
+ } catch (e) {
11
+ alert(`Xrm.WebApi not available here: ${String(e)}`);
12
+ }
13
+ };
14
+
15
+ return (
16
+ <FluentProvider theme={webLightTheme}>
17
+ <div style={{ display: 'flex', flexDirection: 'column', gap: 12, padding: 16 }}>
18
+ <Text size={600} weight="semibold">{{projectName}}</Text>
19
+ <Text>Dynamics 365 web resource — Fluent UI v9.</Text>
20
+ <div>
21
+ <Button appearance="primary" onClick={onClick}>
22
+ Retrieve accounts
23
+ </Button>
24
+ </div>
25
+ </div>
26
+ </FluentProvider>
27
+ );
28
+ };
@@ -0,0 +1,5 @@
1
+ node_modules/
2
+ dist/
3
+ .env
4
+ .env.local
5
+ *.log
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "{{projectName}}",
3
+ "version": "1.0.0",
4
+ "description": "{{projectName}} — Dynamics 365 web resource (React, Fluent {{componentLibrary}})",
5
+ "private": true,
6
+ "scripts": {
7
+ "dev": "webpack serve --mode development",
8
+ "build": "webpack --mode production",
9
+ "typecheck": "tsc --noEmit",
10
+ "lint": "eslint src --ext .ts,.tsx"
11
+ },
12
+ "dependencies": {
13
+ "react": "^18.2.0",
14
+ "react-dom": "^18.2.0"
15
+ },
16
+ "devDependencies": {
17
+ "@types/react": "^18.2.0",
18
+ "@types/react-dom": "^18.2.0",
19
+ "@types/xrm": "^9.0.74",
20
+ "html-webpack-plugin": "^5.5.3",
21
+ "ts-loader": "^9.5.1",
22
+ "typescript": "^5.3.3",
23
+ "webpack": "^5.89.0",
24
+ "webpack-cli": "^5.1.4",
25
+ "webpack-dev-server": "^4.15.1"
26
+ }
27
+ }
@@ -0,0 +1,11 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>{{projectName}}</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ </body>
11
+ </html>
@@ -0,0 +1,10 @@
1
+ import * as React from 'react';
2
+ import { createRoot } from 'react-dom/client';
3
+ import { App } from './App';
4
+
5
+ // On localhost, `tools/dev/mock-xrm.js` (from the `serve` dev-tool) can be loaded
6
+ // to stub the Xrm global so this resource runs outside a model-driven host.
7
+ const container = document.getElementById('root');
8
+ if (container) {
9
+ createRoot(container).render(<App />);
10
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Thin wrapper over Xrm.WebApi for this web resource's data access. The Xrm global
3
+ * is typed via @types/xrm; on localhost, stub it with tools/dev/mock-xrm.js.
4
+ */
5
+
6
+ export type DataverseRecord = Record<string, unknown>;
7
+
8
+ export async function retrieveMultiple(
9
+ entityLogicalName: string,
10
+ options = ''
11
+ ): Promise<DataverseRecord[]> {
12
+ const result = await Xrm.WebApi.retrieveMultipleRecords(entityLogicalName, options);
13
+ return result.entities;
14
+ }
15
+
16
+ export async function retrieveRecord(
17
+ entityLogicalName: string,
18
+ id: string,
19
+ options = ''
20
+ ): Promise<DataverseRecord> {
21
+ return Xrm.WebApi.retrieveRecord(entityLogicalName, id, options);
22
+ }
23
+
24
+ export async function createRecord(
25
+ entityLogicalName: string,
26
+ data: Record<string, unknown>
27
+ ): Promise<string> {
28
+ const res = await Xrm.WebApi.createRecord(entityLogicalName, data);
29
+ return res.id;
30
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2018",
4
+ "module": "ESNext",
5
+ "moduleResolution": "node",
6
+ "jsx": "react-jsx",
7
+ "strict": true,
8
+ "esModuleInterop": true,
9
+ "forceConsistentCasingInFileNames": true,
10
+ "skipLibCheck": true,
11
+ "lib": ["DOM", "DOM.Iterable", "ES2018"],
12
+ "types": ["xrm"]
13
+ },
14
+ "include": ["src"]
15
+ }
@@ -0,0 +1,17 @@
1
+ const path = require('path');
2
+ const HtmlWebpackPlugin = require('html-webpack-plugin');
3
+
4
+ module.exports = {
5
+ entry: './src/index.tsx',
6
+ output: {
7
+ path: path.resolve(__dirname, 'dist'),
8
+ filename: '{{projectName}}.js',
9
+ clean: true,
10
+ },
11
+ resolve: { extensions: ['.ts', '.tsx', '.js'] },
12
+ module: {
13
+ rules: [{ test: /\.tsx?$/, use: 'ts-loader', exclude: /node_modules/ }],
14
+ },
15
+ plugins: [new HtmlWebpackPlugin({ template: './public/index.html' })],
16
+ devServer: { static: './dist', port: 8080, hot: true },
17
+ };
@@ -1,13 +0,0 @@
1
- /**
2
- * Generate entities using the entity generator
3
- */
4
- export declare function generateEntities(projectPath: string, entities?: string, generateSample?: boolean): Promise<void>;
5
- /**
6
- * Generate page templates based on selection
7
- */
8
- export declare function generatePageTemplates(projectPath: string, pageType: string, entities?: string, generateSample?: boolean): Promise<void>;
9
- /**
10
- * Customize project for deployment target
11
- */
12
- export declare function customizeForDeployment(projectPath: string, deploymentTarget: string): Promise<void>;
13
- //# sourceMappingURL=consultingHelpers.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"consultingHelpers.d.ts","sourceRoot":"","sources":["../../src/utils/consultingHelpers.ts"],"names":[],"mappings":"AAQA;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,MAAM,EACnB,QAAQ,CAAC,EAAE,MAAM,EACjB,cAAc,CAAC,EAAE,OAAO,GACvB,OAAO,CAAC,IAAI,CAAC,CAgDf;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM,EACjB,cAAc,CAAC,EAAE,OAAO,GACvB,OAAO,CAAC,IAAI,CAAC,CA0Bf;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,MAAM,EACnB,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,IAAI,CAAC,CA4Cf"}