@salesforce/ui-bundle-template-feature-react-search 11.3.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 (169) hide show
  1. package/LICENSE.txt +82 -0
  2. package/README.md +692 -0
  3. package/dist/.forceignore +15 -0
  4. package/dist/.husky/pre-commit +4 -0
  5. package/dist/.prettierignore +11 -0
  6. package/dist/.prettierrc +17 -0
  7. package/dist/CHANGELOG.md +3499 -0
  8. package/dist/README.md +28 -0
  9. package/dist/config/project-scratch-def.json +13 -0
  10. package/dist/eslint.config.js +7 -0
  11. package/dist/force-app/main/default/uiBundles/feature-react-search/.forceignore +15 -0
  12. package/dist/force-app/main/default/uiBundles/feature-react-search/.graphqlrc.yml +2 -0
  13. package/dist/force-app/main/default/uiBundles/feature-react-search/.prettierignore +9 -0
  14. package/dist/force-app/main/default/uiBundles/feature-react-search/.prettierrc +11 -0
  15. package/dist/force-app/main/default/uiBundles/feature-react-search/CHANGELOG.md +10 -0
  16. package/dist/force-app/main/default/uiBundles/feature-react-search/README.md +75 -0
  17. package/dist/force-app/main/default/uiBundles/feature-react-search/codegen.yml +95 -0
  18. package/dist/force-app/main/default/uiBundles/feature-react-search/components.json +18 -0
  19. package/dist/force-app/main/default/uiBundles/feature-react-search/e2e/app.spec.ts +17 -0
  20. package/dist/force-app/main/default/uiBundles/feature-react-search/eslint.config.js +169 -0
  21. package/dist/force-app/main/default/uiBundles/feature-react-search/feature-react-search.uibundle-meta.xml +7 -0
  22. package/dist/force-app/main/default/uiBundles/feature-react-search/index.html +12 -0
  23. package/dist/force-app/main/default/uiBundles/feature-react-search/package.json +76 -0
  24. package/dist/force-app/main/default/uiBundles/feature-react-search/playwright.config.ts +24 -0
  25. package/dist/force-app/main/default/uiBundles/feature-react-search/scripts/get-graphql-schema.mjs +71 -0
  26. package/dist/force-app/main/default/uiBundles/feature-react-search/scripts/rewrite-e2e-assets.mjs +23 -0
  27. package/dist/force-app/main/default/uiBundles/feature-react-search/src/api/graphqlClient.ts +44 -0
  28. package/dist/force-app/main/default/uiBundles/feature-react-search/src/app.tsx +17 -0
  29. package/dist/force-app/main/default/uiBundles/feature-react-search/src/appLayout.tsx +83 -0
  30. package/dist/force-app/main/default/uiBundles/feature-react-search/src/assets/icons/book.svg +3 -0
  31. package/dist/force-app/main/default/uiBundles/feature-react-search/src/assets/icons/copy.svg +4 -0
  32. package/dist/force-app/main/default/uiBundles/feature-react-search/src/assets/icons/rocket.svg +3 -0
  33. package/dist/force-app/main/default/uiBundles/feature-react-search/src/assets/icons/star.svg +3 -0
  34. package/dist/force-app/main/default/uiBundles/feature-react-search/src/assets/images/codey-1.png +0 -0
  35. package/dist/force-app/main/default/uiBundles/feature-react-search/src/assets/images/codey-2.png +0 -0
  36. package/dist/force-app/main/default/uiBundles/feature-react-search/src/assets/images/codey-3.png +0 -0
  37. package/dist/force-app/main/default/uiBundles/feature-react-search/src/assets/images/vibe-codey.svg +194 -0
  38. package/dist/force-app/main/default/uiBundles/feature-react-search/src/components/alerts/status-alert.tsx +52 -0
  39. package/dist/force-app/main/default/uiBundles/feature-react-search/src/components/layouts/card-layout.tsx +29 -0
  40. package/dist/force-app/main/default/uiBundles/feature-react-search/src/components/ui/alert.tsx +76 -0
  41. package/dist/force-app/main/default/uiBundles/feature-react-search/src/components/ui/avatar.tsx +109 -0
  42. package/dist/force-app/main/default/uiBundles/feature-react-search/src/components/ui/badge.tsx +48 -0
  43. package/dist/force-app/main/default/uiBundles/feature-react-search/src/components/ui/breadcrumb.tsx +109 -0
  44. package/dist/force-app/main/default/uiBundles/feature-react-search/src/components/ui/button.tsx +67 -0
  45. package/dist/force-app/main/default/uiBundles/feature-react-search/src/components/ui/calendar.tsx +232 -0
  46. package/dist/force-app/main/default/uiBundles/feature-react-search/src/components/ui/card.tsx +103 -0
  47. package/dist/force-app/main/default/uiBundles/feature-react-search/src/components/ui/checkbox.tsx +32 -0
  48. package/dist/force-app/main/default/uiBundles/feature-react-search/src/components/ui/collapsible.tsx +33 -0
  49. package/dist/force-app/main/default/uiBundles/feature-react-search/src/components/ui/datePicker.tsx +127 -0
  50. package/dist/force-app/main/default/uiBundles/feature-react-search/src/components/ui/dialog.tsx +162 -0
  51. package/dist/force-app/main/default/uiBundles/feature-react-search/src/components/ui/dropdown-menu.tsx +257 -0
  52. package/dist/force-app/main/default/uiBundles/feature-react-search/src/components/ui/field.tsx +237 -0
  53. package/dist/force-app/main/default/uiBundles/feature-react-search/src/components/ui/index.ts +109 -0
  54. package/dist/force-app/main/default/uiBundles/feature-react-search/src/components/ui/input.tsx +19 -0
  55. package/dist/force-app/main/default/uiBundles/feature-react-search/src/components/ui/label.tsx +22 -0
  56. package/dist/force-app/main/default/uiBundles/feature-react-search/src/components/ui/pagination.tsx +132 -0
  57. package/dist/force-app/main/default/uiBundles/feature-react-search/src/components/ui/popover.tsx +89 -0
  58. package/dist/force-app/main/default/uiBundles/feature-react-search/src/components/ui/select.tsx +193 -0
  59. package/dist/force-app/main/default/uiBundles/feature-react-search/src/components/ui/separator.tsx +26 -0
  60. package/dist/force-app/main/default/uiBundles/feature-react-search/src/components/ui/skeleton.tsx +14 -0
  61. package/dist/force-app/main/default/uiBundles/feature-react-search/src/components/ui/sonner.tsx +20 -0
  62. package/dist/force-app/main/default/uiBundles/feature-react-search/src/components/ui/spinner.tsx +16 -0
  63. package/dist/force-app/main/default/uiBundles/feature-react-search/src/components/ui/table.tsx +114 -0
  64. package/dist/force-app/main/default/uiBundles/feature-react-search/src/components/ui/tabs.tsx +88 -0
  65. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/api/distinctValuesService.ts +84 -0
  66. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/api/searchService.ts +71 -0
  67. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/Search.tsx +160 -0
  68. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/SearchResults.tsx +77 -0
  69. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/SourceSection.tsx +167 -0
  70. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/controls/PaginationControls.tsx +115 -0
  71. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/controls/ScopeSelector.tsx +55 -0
  72. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/controls/SearchBar.tsx +55 -0
  73. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/controls/SortControl.tsx +62 -0
  74. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/filters/ActiveFilters.tsx +61 -0
  75. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/filters/DefaultFilterPanel.tsx +122 -0
  76. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/filters/FilterContext.tsx +70 -0
  77. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/filters/inputs/BooleanFilter.tsx +50 -0
  78. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/filters/inputs/DateRangeFilter.tsx +50 -0
  79. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/filters/inputs/FilterFieldWrapper.tsx +26 -0
  80. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/filters/inputs/MultiSelectFilter.tsx +47 -0
  81. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/filters/inputs/NumericRangeFilter.tsx +78 -0
  82. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/filters/inputs/SelectFilter.tsx +46 -0
  83. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/filters/inputs/TextFilter.tsx +52 -0
  84. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/results/DefaultResultRow.tsx +109 -0
  85. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/config.json +82 -0
  86. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/hooks/useAsyncData.ts +56 -0
  87. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/hooks/useDistinctValues.ts +59 -0
  88. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/hooks/useSearch.ts +442 -0
  89. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/index.ts +80 -0
  90. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/loadConfig.ts +14 -0
  91. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/queryBuilder.ts +156 -0
  92. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/types.ts +169 -0
  93. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/utils/debounce.ts +17 -0
  94. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/utils/fieldUtils.ts +14 -0
  95. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/utils/filterUtils.ts +272 -0
  96. package/dist/force-app/main/default/uiBundles/feature-react-search/src/features/search/utils/sortUtils.ts +34 -0
  97. package/dist/force-app/main/default/uiBundles/feature-react-search/src/hooks/useAsyncData.ts +67 -0
  98. package/dist/force-app/main/default/uiBundles/feature-react-search/src/lib/utils.ts +6 -0
  99. package/dist/force-app/main/default/uiBundles/feature-react-search/src/navigationMenu.tsx +80 -0
  100. package/dist/force-app/main/default/uiBundles/feature-react-search/src/pages/Home.tsx +11 -0
  101. package/dist/force-app/main/default/uiBundles/feature-react-search/src/pages/NotFound.tsx +18 -0
  102. package/dist/force-app/main/default/uiBundles/feature-react-search/src/router-utils.tsx +35 -0
  103. package/dist/force-app/main/default/uiBundles/feature-react-search/src/routes.tsx +22 -0
  104. package/dist/force-app/main/default/uiBundles/feature-react-search/src/styles/global.css +135 -0
  105. package/dist/force-app/main/default/uiBundles/feature-react-search/tsconfig.json +45 -0
  106. package/dist/force-app/main/default/uiBundles/feature-react-search/tsconfig.node.json +13 -0
  107. package/dist/force-app/main/default/uiBundles/feature-react-search/ui-bundle.json +7 -0
  108. package/dist/force-app/main/default/uiBundles/feature-react-search/vite-env.d.ts +4 -0
  109. package/dist/force-app/main/default/uiBundles/feature-react-search/vite.config.ts +106 -0
  110. package/dist/force-app/main/default/uiBundles/feature-react-search/vitest-env.d.ts +2 -0
  111. package/dist/force-app/main/default/uiBundles/feature-react-search/vitest.config.ts +11 -0
  112. package/dist/force-app/main/default/uiBundles/feature-react-search/vitest.setup.ts +1 -0
  113. package/dist/jest.config.js +6 -0
  114. package/dist/package-lock.json +9995 -0
  115. package/dist/package.json +44 -0
  116. package/dist/scripts/apex/hello.apex +10 -0
  117. package/dist/scripts/gitignore-templates.json +4 -0
  118. package/dist/scripts/graphql-search.sh +191 -0
  119. package/dist/scripts/org-setup-config-schema.mjs +96 -0
  120. package/dist/scripts/org-setup.config.json +5 -0
  121. package/dist/scripts/org-setup.mjs +1392 -0
  122. package/dist/scripts/sf-project-setup.mjs +103 -0
  123. package/dist/scripts/soql/account.soql +6 -0
  124. package/dist/scripts/validate-org-setup-config.mjs +38 -0
  125. package/dist/sfdx-project.json +12 -0
  126. package/package.json +51 -0
  127. package/src/force-app/main/default/uiBundles/feature-react-search/src/__inherit__appLayout.tsx +9 -0
  128. package/src/force-app/main/default/uiBundles/feature-react-search/src/components/ui/__inherit__alert.tsx +39 -0
  129. package/src/force-app/main/default/uiBundles/feature-react-search/src/components/ui/__inherit__button.tsx +45 -0
  130. package/src/force-app/main/default/uiBundles/feature-react-search/src/components/ui/__inherit__checkbox.tsx +8 -0
  131. package/src/force-app/main/default/uiBundles/feature-react-search/src/components/ui/__inherit__input.tsx +5 -0
  132. package/src/force-app/main/default/uiBundles/feature-react-search/src/components/ui/__inherit__label.tsx +8 -0
  133. package/src/force-app/main/default/uiBundles/feature-react-search/src/components/ui/__inherit__pagination.tsx +47 -0
  134. package/src/force-app/main/default/uiBundles/feature-react-search/src/components/ui/__inherit__select.tsx +57 -0
  135. package/src/force-app/main/default/uiBundles/feature-react-search/src/components/ui/__inherit__skeleton.tsx +5 -0
  136. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/api/distinctValuesService.ts +84 -0
  137. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/api/searchService.ts +71 -0
  138. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/Search.tsx +160 -0
  139. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/SearchResults.tsx +77 -0
  140. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/SourceSection.tsx +167 -0
  141. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/controls/PaginationControls.tsx +115 -0
  142. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/controls/ScopeSelector.tsx +55 -0
  143. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/controls/SearchBar.tsx +55 -0
  144. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/controls/SortControl.tsx +62 -0
  145. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/filters/ActiveFilters.tsx +61 -0
  146. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/filters/DefaultFilterPanel.tsx +122 -0
  147. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/filters/FilterContext.tsx +70 -0
  148. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/filters/inputs/BooleanFilter.tsx +50 -0
  149. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/filters/inputs/DateRangeFilter.tsx +50 -0
  150. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/filters/inputs/FilterFieldWrapper.tsx +26 -0
  151. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/filters/inputs/MultiSelectFilter.tsx +47 -0
  152. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/filters/inputs/NumericRangeFilter.tsx +78 -0
  153. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/filters/inputs/SelectFilter.tsx +46 -0
  154. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/filters/inputs/TextFilter.tsx +52 -0
  155. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/components/results/DefaultResultRow.tsx +109 -0
  156. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/config.json +82 -0
  157. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/hooks/useAsyncData.ts +56 -0
  158. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/hooks/useDistinctValues.ts +59 -0
  159. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/hooks/useSearch.ts +442 -0
  160. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/index.ts +80 -0
  161. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/loadConfig.ts +14 -0
  162. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/queryBuilder.ts +156 -0
  163. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/types.ts +169 -0
  164. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/utils/debounce.ts +17 -0
  165. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/utils/fieldUtils.ts +14 -0
  166. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/utils/filterUtils.ts +272 -0
  167. package/src/force-app/main/default/uiBundles/feature-react-search/src/features/search/utils/sortUtils.ts +34 -0
  168. package/src/force-app/main/default/uiBundles/feature-react-search/src/pages/Home.tsx +11 -0
  169. package/src/force-app/main/default/uiBundles/feature-react-search/src/routes.tsx +10 -0
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@salesforce/ui-bundle-template-base-sfdx-project",
3
+ "version": "11.3.0",
4
+ "description": "Base SFDX project template",
5
+ "license": "SEE LICENSE IN LICENSE.txt",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "scripts": {
10
+ "sf-project-setup": "node scripts/sf-project-setup.mjs",
11
+ "build": "echo 'No build required for base-sfdx-project'",
12
+ "clean": "echo 'No clean required for base-sfdx-project'",
13
+ "lint": "eslint --no-error-on-unmatched-pattern **/{aura,lwc}/**/*.js",
14
+ "validate:org-setup-config": "node scripts/validate-org-setup-config.mjs",
15
+ "test": "npm run test:unit",
16
+ "test:coverage": "npm run test",
17
+ "test:unit": "sfdx-lwc-jest -- --passWithNoTests",
18
+ "test:unit:watch": "sfdx-lwc-jest --watch",
19
+ "test:unit:debug": "sfdx-lwc-jest --debug",
20
+ "test:unit:coverage": "sfdx-lwc-jest --coverage",
21
+ "prettier": "prettier --write \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"",
22
+ "prettier:verify": "prettier --check \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"",
23
+ "precommit": "lint-staged",
24
+ "setup": "node scripts/org-setup.mjs"
25
+ },
26
+ "dependencies": {
27
+ "zod": "^3.24.1"
28
+ },
29
+ "devDependencies": {
30
+ "@lwc/eslint-plugin-lwc": "^3.3.0",
31
+ "@prettier/plugin-xml": "^3.2.2",
32
+ "@salesforce/eslint-config-lwc": "^4.1.0",
33
+ "@salesforce/eslint-plugin-aura": "^3.0.0",
34
+ "@salesforce/eslint-plugin-lightning": "^2.0.0",
35
+ "@salesforce/sfdx-lwc-jest": "^7.0.1",
36
+ "eslint": "^9.39.0",
37
+ "eslint-plugin-import": "^2.25.4",
38
+ "eslint-plugin-jest": "^28.8.1",
39
+ "husky": "^9.1.5",
40
+ "lint-staged": "^15.1.0",
41
+ "prettier": "^3.1.0",
42
+ "prettier-plugin-apex": "^2.0.1"
43
+ }
44
+ }
@@ -0,0 +1,10 @@
1
+ // Use .apex files to store anonymous Apex.
2
+ // You can execute anonymous Apex in VS Code by selecting the
3
+ // apex text and running the command:
4
+ // SFDX: Execute Anonymous Apex with Currently Selected Text
5
+ // You can also execute the entire file by running the command:
6
+ // SFDX: Execute Anonymous Apex with Editor Contents
7
+
8
+ string tempvar = 'Enter_your_name_here';
9
+ System.debug('Hello World!');
10
+ System.debug('My name is ' + tempvar);
@@ -0,0 +1,4 @@
1
+ {
2
+ "sfdx": "# This file is used for Git repositories to specify intentionally untracked files that Git should ignore. \n# If you are not using git, you can delete this file. For more information see: https://git-scm.com/docs/gitignore\n# For useful gitignore templates see: https://github.com/github/gitignore\n\n# Salesforce cache\n.sf/\n.sfdx/\n.localdevserver/\ndeploy-options.json\n\n# LWC VSCode autocomplete\n**/lwc/jsconfig.json\n\n# LWC Jest coverage reports\ncoverage/\n\n# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Dependency directories\nnode_modules/\n\n# Eslint cache\n.eslintcache\n\n# MacOS system files\n.DS_Store\n\n# Windows system files\nThumbs.db\nehthumbs.db\n[Dd]esktop.ini\n$RECYCLE.BIN/\n\n# Local environment variables\n.env\n\n# Python Salesforce Functions\n**/__pycache__/\n**/.venv/\n**/venv/\n",
3
+ "webapp": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\nbuild\npackage-lock.json\n*.local\n\n# Playwright\n/test-results/\n/playwright-report/\n/blob-report/\n/playwright/.cache/\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n\n# Un-exclude Cursor AI rules for this SFDX project\n!.a4drules/\n!.cursor/\n"
4
+ }
@@ -0,0 +1,191 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail # exit on error (-e), undefined vars (-u), and propagate pipeline failures (-o pipefail)
3
+ # graphql-search.sh — Look up one or more Salesforce entities in schema.graphql.
4
+ #
5
+ # Run from the SFDX project root (where schema.graphql lives):
6
+ # bash scripts/graphql-search.sh Account
7
+ # bash scripts/graphql-search.sh Account Contact Opportunity
8
+ #
9
+ # Pass a custom schema path with -s / --schema:
10
+ # bash scripts/graphql-search.sh -s /path/to/schema.graphql Account
11
+ # bash scripts/graphql-search.sh --schema ./other/schema.graphql Account Contact
12
+ #
13
+ # Output sections per entity:
14
+ # 1. Type definition — all fields and relationships
15
+ # 2. Filter options — <Entity>_Filter input (for `where:`)
16
+ # 3. Sort options — <Entity>_OrderBy input (for `orderBy:`)
17
+ # 4. Create mutation wrapper — <Entity>CreateInput
18
+ # 5. Create mutation fields — <Entity>CreateRepresentation (for create mutations)
19
+ # 6. Update mutation wrapper — <Entity>UpdateInput
20
+ # 7. Update mutation fields — <Entity>UpdateRepresentation (for update mutations)
21
+
22
+ SCHEMA="./schema.graphql"
23
+
24
+ # ── Argument parsing ─────────────────────────────────────────────────────────
25
+
26
+ while [[ $# -gt 0 ]]; do
27
+ case "$1" in
28
+ -s|--schema)
29
+ if [[ -z "${2-}" || "$2" == -* ]]; then
30
+ echo "ERROR: --schema requires a file path argument"
31
+ exit 1
32
+ fi
33
+ SCHEMA="$2"
34
+ shift 2
35
+ ;;
36
+ --)
37
+ shift
38
+ break
39
+ ;;
40
+ -*)
41
+ echo "ERROR: Unknown option: $1"
42
+ echo "Usage: bash $0 [-s <schema-path>] <EntityName> [EntityName2 ...]"
43
+ exit 1
44
+ ;;
45
+ *)
46
+ break
47
+ ;;
48
+ esac
49
+ done
50
+
51
+ if [ $# -eq 0 ]; then
52
+ echo "Usage: bash $0 [-s <schema-path>] <EntityName> [EntityName2 ...]"
53
+ echo "Example: bash $0 Account"
54
+ echo "Example: bash $0 Account Contact Opportunity"
55
+ echo "Example: bash $0 --schema /path/to/schema.graphql Account"
56
+ exit 1
57
+ fi
58
+
59
+ if [ ! -f "$SCHEMA" ]; then
60
+ echo "ERROR: schema.graphql not found at $SCHEMA"
61
+ echo " Make sure you are running from the SFDX project root, or pass the path explicitly:"
62
+ echo " bash $0 --schema <path/to/schema.graphql> <EntityName>"
63
+ echo " If the file is missing entirely, generate it from the ui-bundle dir:"
64
+ echo " cd force-app/main/default/uiBundles/<app-name> && npm run graphql:schema"
65
+ exit 1
66
+ fi
67
+
68
+ if [ ! -r "$SCHEMA" ]; then
69
+ echo "ERROR: schema.graphql is not readable at $SCHEMA"
70
+ echo " Check file permissions: ls -la $SCHEMA"
71
+ exit 1
72
+ fi
73
+
74
+ if [ ! -s "$SCHEMA" ]; then
75
+ echo "ERROR: schema.graphql is empty at $SCHEMA"
76
+ echo " Regenerate it from the ui-bundle dir:"
77
+ echo " cd force-app/main/default/uiBundles/<app-name> && npm run graphql:schema"
78
+ exit 1
79
+ fi
80
+
81
+ # ── Helper: extract lines from a grep match through the closing brace ────────
82
+ # Prints up to MAX_LINES lines after (and including) the first match of PATTERN.
83
+ # Uses a generous line count — blocks are always closed by a "}" line.
84
+
85
+ extract_block() {
86
+ local label="$1"
87
+ local pattern="$2"
88
+ local max_lines="$3"
89
+
90
+ local match
91
+ local grep_exit=0
92
+ match=$(grep -nE "$pattern" "$SCHEMA" | head -1) || grep_exit=$?
93
+
94
+ if [ "$grep_exit" -eq 2 ]; then
95
+ echo " ERROR: grep failed on pattern: $pattern" >&2
96
+ return 1
97
+ fi
98
+
99
+ if [ -z "$match" ]; then
100
+ echo " (not found: $pattern)"
101
+ return 3
102
+ fi
103
+
104
+ echo "### $label"
105
+ grep -E "$pattern" "$SCHEMA" -A "$max_lines" | \
106
+ awk '/^\}$/{print; exit} {print}' | \
107
+ head -n "$max_lines" || true
108
+ echo ""
109
+ }
110
+
111
+ # ── Main loop ────────────────────────────────────────────────────────────────
112
+
113
+ for ENTITY in "$@"; do
114
+ # Validate entity name: must be a valid PascalCase identifier (letters, digits, underscores)
115
+ if [[ ! "$ENTITY" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]]; then
116
+ echo "ERROR: Invalid entity name: '$ENTITY'"
117
+ echo " Entity names must start with a letter or underscore, followed by letters, digits, or underscores."
118
+ echo " Examples: Account, My_Custom_Object__c"
119
+ continue
120
+ fi
121
+
122
+ echo ""
123
+ echo "======================================================================"
124
+ echo " SCHEMA LOOKUP: $ENTITY"
125
+ echo "======================================================================"
126
+ echo ""
127
+
128
+ found=0
129
+
130
+ # Helper: call extract_block, track matches, surface errors
131
+ try_extract() {
132
+ local rc=0
133
+ extract_block "$@" || rc=$?
134
+ if [ "$rc" -eq 0 ]; then
135
+ found=$((found + 1))
136
+ elif [ "$rc" -eq 1 ]; then
137
+ echo " Aborting lookup for '$ENTITY' due to grep error" >&2
138
+ fi
139
+ # rc=3 is not-found — continue silently (already printed by extract_block)
140
+ }
141
+
142
+ # 1. Type definition — all fields and relationships
143
+ try_extract \
144
+ "Type definition — fields and relationships" \
145
+ "^type ${ENTITY} implements Record" \
146
+ 200
147
+
148
+ # 2. Filter input — used in `where:` arguments
149
+ try_extract \
150
+ "Filter options — use in where: { ... }" \
151
+ "^input ${ENTITY}_Filter" \
152
+ 100
153
+
154
+ # 3. OrderBy input — used in `orderBy:` arguments
155
+ try_extract \
156
+ "Sort options — use in orderBy: { ... }" \
157
+ "^input ${ENTITY}_OrderBy" \
158
+ 60
159
+
160
+ # 4. Create mutation wrapper
161
+ try_extract \
162
+ "Create mutation wrapper — ${ENTITY}CreateInput" \
163
+ "^input ${ENTITY}CreateInput" \
164
+ 10
165
+
166
+ # 5. Create mutation fields
167
+ try_extract \
168
+ "Create mutation fields — ${ENTITY}CreateRepresentation" \
169
+ "^input ${ENTITY}CreateRepresentation" \
170
+ 100
171
+
172
+ # 6. Update mutation wrapper
173
+ try_extract \
174
+ "Update mutation wrapper — ${ENTITY}UpdateInput" \
175
+ "^input ${ENTITY}UpdateInput" \
176
+ 10
177
+
178
+ # 7. Update mutation fields
179
+ try_extract \
180
+ "Update mutation fields — ${ENTITY}UpdateRepresentation" \
181
+ "^input ${ENTITY}UpdateRepresentation" \
182
+ 100
183
+
184
+ if [ "$found" -eq 0 ]; then
185
+ echo "WARNING: No schema entries found for '$ENTITY'."
186
+ echo " - Names are PascalCase (e.g., 'Account' not 'account')"
187
+ echo " - Custom objects may need deployment first"
188
+ fi
189
+
190
+ echo ""
191
+ done
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Shared schema + validator for org-setup.config.json (W-23043729).
3
+ *
4
+ * Authored ONCE, used at TWO moments:
5
+ * (a) build / CI time — `scripts/validate-org-setup-config.mjs` validates every
6
+ * org-setup.config.json this repo ships, failing the build on any violation.
7
+ * (b) setup runtime — `org-setup.mjs` calls `validateConfig` once in main(),
8
+ * before any step runs, to catch the developer's local post-scaffold edits.
9
+ *
10
+ * `validateConfig` is pure: it parses + validates and RETURNS a result. Each call
11
+ * site owns its own print/exit, so the build gate can report every bad file and
12
+ * the runtime can exit immediately — and the validator stays unit-testable.
13
+ *
14
+ * The zod schema uses `.strict()` at every level so unknown keys (e.g. the
15
+ * `permsetAssignment` singular typo) are rejected rather than silently ignored.
16
+ */
17
+
18
+ import { z } from 'zod';
19
+
20
+ /** Closed set of assignee values — no arbitrary usernames. */
21
+ const Assignee = z.enum(['currentUser', 'guestUser', 'skip']);
22
+
23
+ // No siteName: for guestUser the site is derived from the single
24
+ // networks/<siteName>.network-meta.xml the app ships (see spec §5.2).
25
+ const Assignment = z
26
+ .object({
27
+ assignee: Assignee,
28
+ })
29
+ .strict();
30
+
31
+ export const ConfigSchema = z
32
+ .object({
33
+ permsetAssignments: z
34
+ .object({
35
+ // guestUser is valid here — siteName is derived, not per-assignment.
36
+ defaultAssignee: Assignee.default('skip'),
37
+ assignments: z.record(z.string(), Assignment).default({}),
38
+ })
39
+ .strict()
40
+ .optional(),
41
+ role: z
42
+ .object({
43
+ assignee: z.literal('currentUser'), // only value the role code honors
44
+ roleName: z.string().min(1),
45
+ })
46
+ .strict()
47
+ .optional(),
48
+ selfRegistration: z
49
+ .object({
50
+ // No siteName: the site is derived from the single
51
+ // networks/<siteName>.network-meta.xml the app ships (see spec §5.2),
52
+ // exactly like the guestUser permset path.
53
+ selfRegProfile: z.string().min(1),
54
+ accountName: z.string().min(1),
55
+ })
56
+ .strict()
57
+ .optional(),
58
+ })
59
+ .strict();
60
+
61
+ /**
62
+ * Render a single zod issue as a "path: message" line. Empty path (a root-level
63
+ * problem) renders as "<root>: message".
64
+ */
65
+ function formatIssue(issue) {
66
+ const path = issue.path.length > 0 ? issue.path.join('.') : '<root>';
67
+ return `${path}: ${issue.message}`;
68
+ }
69
+
70
+ /**
71
+ * Parse + validate a raw org-setup.config.json string.
72
+ *
73
+ * @param {string} rawText raw file contents (not yet JSON-parsed)
74
+ * @param {string} [configPath] path used only for error messages
75
+ * @returns {{ ok: true, data: object } | { ok: false, errors: string[] }}
76
+ * On success, `data` is the parsed + defaulted config. On failure, `errors`
77
+ * is a non-empty list of human-readable messages (JSON parse error or zod
78
+ * issues). The caller decides whether to print/exit.
79
+ */
80
+ export function validateConfig(rawText, configPath) {
81
+ const where = configPath ? ` (${configPath})` : '';
82
+
83
+ let parsed;
84
+ try {
85
+ parsed = JSON.parse(rawText);
86
+ } catch (err) {
87
+ return { ok: false, errors: [`malformed JSON${where}: ${err.message}`] };
88
+ }
89
+
90
+ const result = ConfigSchema.safeParse(parsed);
91
+ if (!result.success) {
92
+ return { ok: false, errors: result.error.issues.map(formatIssue) };
93
+ }
94
+
95
+ return { ok: true, data: result.data };
96
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "permsetAssignments": {
3
+ "assignments": {}
4
+ }
5
+ }