@salesforce/webapp-template-feature-react-authentication-experimental 1.3.4

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 (91) hide show
  1. package/LICENSE.txt +82 -0
  2. package/README.md +77 -0
  3. package/dist/.a4drules/build-validation.md +81 -0
  4. package/dist/.a4drules/code-quality.md +150 -0
  5. package/dist/.a4drules/graphql/tools/knowledge/lds-explore-graphql-schema.md +227 -0
  6. package/dist/.a4drules/graphql/tools/knowledge/lds-generate-graphql-mutationquery.md +211 -0
  7. package/dist/.a4drules/graphql/tools/knowledge/lds-generate-graphql-readquery.md +185 -0
  8. package/dist/.a4drules/graphql/tools/knowledge/lds-guide-graphql.md +205 -0
  9. package/dist/.a4drules/graphql/tools/schemas/shared.graphqls +1150 -0
  10. package/dist/.a4drules/graphql.md +98 -0
  11. package/dist/.a4drules/images.md +13 -0
  12. package/dist/.a4drules/react.md +361 -0
  13. package/dist/.a4drules/react_image_processing.md +45 -0
  14. package/dist/.a4drules/typescript.md +224 -0
  15. package/dist/.forceignore +15 -0
  16. package/dist/.husky/pre-commit +4 -0
  17. package/dist/.prettierignore +11 -0
  18. package/dist/.prettierrc +17 -0
  19. package/dist/CHANGELOG.md +19 -0
  20. package/dist/README.md +18 -0
  21. package/dist/config/project-scratch-def.json +13 -0
  22. package/dist/force-app/main/default/webapplications/feature-react-authentication/.prettierignore +9 -0
  23. package/dist/force-app/main/default/webapplications/feature-react-authentication/.prettierrc +11 -0
  24. package/dist/force-app/main/default/webapplications/feature-react-authentication/eslint.config.js +113 -0
  25. package/dist/force-app/main/default/webapplications/feature-react-authentication/feature-react-authentication.webapplication-meta.xml +7 -0
  26. package/dist/force-app/main/default/webapplications/feature-react-authentication/index.html +13 -0
  27. package/dist/force-app/main/default/webapplications/feature-react-authentication/package.json +42 -0
  28. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/api/graphql-operations-types.ts +127 -0
  29. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/api/utils/query/highRevenueAccountsQuery.graphql +29 -0
  30. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/app.tsx +16 -0
  31. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/appLayout.tsx +9 -0
  32. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/assets/icons/book.svg +3 -0
  33. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/assets/icons/copy.svg +4 -0
  34. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/assets/icons/rocket.svg +3 -0
  35. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/assets/icons/star.svg +3 -0
  36. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/assets/images/codey-1.png +0 -0
  37. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/assets/images/codey-2.png +0 -0
  38. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/assets/images/codey-3.png +0 -0
  39. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/assets/images/vibe-codey.svg +194 -0
  40. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/components/alerts/status-alert.tsx +45 -0
  41. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/components/auth/authentication-route.tsx +21 -0
  42. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/components/auth/private-route.tsx +36 -0
  43. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/components/footers/footer-link.tsx +36 -0
  44. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/components/forms/auth-form.tsx +79 -0
  45. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/components/forms/submit-button.tsx +49 -0
  46. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/components/layout/card-layout.tsx +23 -0
  47. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/components/layout/centered-page-layout.tsx +73 -0
  48. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/components/layout/loading-page.tsx +46 -0
  49. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/components/ui/alert.tsx +65 -0
  50. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/components/ui/button.tsx +56 -0
  51. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/components/ui/card.tsx +77 -0
  52. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/components/ui/field.tsx +111 -0
  53. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/components/ui/index.ts +71 -0
  54. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/components/ui/input.tsx +19 -0
  55. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/components/ui/label.tsx +19 -0
  56. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/components/ui/pagination.tsx +99 -0
  57. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/components/ui/select.tsx +151 -0
  58. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/components/ui/skeleton.tsx +7 -0
  59. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/components/ui/spinner.tsx +21 -0
  60. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/components/ui/table.tsx +114 -0
  61. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/components/ui/tabs.tsx +115 -0
  62. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/context/AuthContext.tsx +83 -0
  63. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/hooks/form.tsx +116 -0
  64. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/lib/utils.ts +6 -0
  65. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/pages/About.tsx +12 -0
  66. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/pages/ChangePassword.tsx +105 -0
  67. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/pages/ForgotPassword.tsx +67 -0
  68. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/pages/Home.tsx +12 -0
  69. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/pages/Login.tsx +84 -0
  70. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/pages/NotFound.tsx +18 -0
  71. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/pages/Profile.tsx +146 -0
  72. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/pages/Register.tsx +117 -0
  73. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/pages/ResetPassword.tsx +101 -0
  74. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/routes.tsx +77 -0
  75. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/styles/global.css +94 -0
  76. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/utils/authenticationConfig.ts +52 -0
  77. package/dist/force-app/main/default/webapplications/feature-react-authentication/src/utils/helpers.ts +161 -0
  78. package/dist/force-app/main/default/webapplications/feature-react-authentication/tsconfig.json +36 -0
  79. package/dist/force-app/main/default/webapplications/feature-react-authentication/tsconfig.node.json +13 -0
  80. package/dist/force-app/main/default/webapplications/feature-react-authentication/vite-env.d.ts +1 -0
  81. package/dist/force-app/main/default/webapplications/feature-react-authentication/vite.config.ts +82 -0
  82. package/dist/force-app/main/default/webapplications/feature-react-authentication/vitest-env.d.ts +2 -0
  83. package/dist/force-app/main/default/webapplications/feature-react-authentication/vitest.config.ts +11 -0
  84. package/dist/force-app/main/default/webapplications/feature-react-authentication/vitest.setup.ts +1 -0
  85. package/dist/force-app/main/default/webapplications/feature-react-authentication/webapplication.json +7 -0
  86. package/dist/jest.config.js +6 -0
  87. package/dist/package.json +37 -0
  88. package/dist/scripts/apex/hello.apex +10 -0
  89. package/dist/scripts/soql/account.soql +6 -0
  90. package/dist/sfdx-project.json +12 -0
  91. package/package.json +31 -0
@@ -0,0 +1,211 @@
1
+ # GraphQL Mutation Query Generation
2
+
3
+ **Triggering conditions**
4
+ 1. Only if the `LDS_Guide_GraphQL` rule completed successfully
5
+ 2. Only if the query to generate is a mutation query
6
+
7
+ ## Your Role
8
+
9
+ You are a GraphQL expert and your role is to help generate Salesforce compatible GraphQL mutation queries once the exploration phase has completed.
10
+
11
+ You will leverage the context provided by the requesting user as well as the validation phase provided by the `LDS_Guide_GraphQL` rule. This tool will also provide you with a method to dynamically query the target org instance that you will use to test the generated query.
12
+
13
+ If the `LDS_Guide_GraphQL` rule has not been executed yet, you **MUST** run it first, and then get back to mutation query generation.
14
+
15
+ ## Mutation Queries General Information
16
+
17
+ **IMPORTANT**:
18
+ 1. **Mutation Types**: The GraphQL engine supports `Create`, `Update` and `Delete` operations
19
+ 2. **Id Based Mutations**: `Update` and `Delete` operations operate on Id-based entity identification
20
+ 3. **Mutation Schema**: Defined in the [mutation query schema](#mutation-query-schema) section
21
+
22
+ ## Mutation Query Generation Workflow
23
+
24
+ Strictly follow the rules below when generating the GraphQL mutation query:
25
+ 1. **Input Fields Validation** - Validate that the set of fields validate [input field constraints](#mutation-queries-input-field-constraints)
26
+ 2. **Output Fields Validation** - Validate that the set of fields used in the select part of the query validate the [output fields constraints](#mutation-queries-output-field-constraints)
27
+ 3. **Type Consistency** - Make sure variables used as query arguments and their related fields share the same GraphQL type
28
+ 4. **Report Phase** - Use the [Mutation Query Report Template](#mutation-query-report-template) below to report on the previous validation phases
29
+ 5. **Input Arguments** - `input` is the default name for the argument, unless otherwise specified
30
+ 6. **Output Field** - For `Create` and `Update` operations, the output field is always named `Record`, and is of type EntityName
31
+ 7. **Query Generation** - Use the [mutation query](#mutation-query-templates) template and adjust it based on the selected operation
32
+ 8. **Output Format** - Use the [standalone](#mutation-standalone-default-output-format---clean-code-only)
33
+ 9. **Test the Query** - Use the [Generated Mutation Query Testing](#generated-mutation-query-testing) workflow to test the generated query
34
+ 1. **Report First** - Always report first, using the proper output format, before testing
35
+
36
+ ## Mutation Query Schema
37
+
38
+ **Important**: In the schema fragments below, replace **EntityName** occurrences by the real entity name (i.e. Account, Case...).
39
+ **Important**: `Delete` operations all share the same generic `Record` entity name for both input and payload, only exposing the standard `Id` field.
40
+
41
+ ```graphql
42
+ input EntityNameCreateRepresentation {
43
+ # Subset of EntityName fields here
44
+ }
45
+ input EntityNameCreateInput { EntityName: EntityNameCreateRepresentation! }
46
+ type EntityNameCreatePayload { Record: EntityName! }
47
+
48
+ input EntityNameUpdateRepresentation {
49
+ # Subset of EntityName fields here
50
+ }
51
+ input EntityNameUpdateInput { Id: IdOrRef! EntityName: EntityNameUpdateRepresentation! }
52
+ type EntityNameUpdatePayload { Record: EntityName! }
53
+
54
+ input RecordDeleteInput { Id: IdOrRef! }
55
+ type RecordDeletePayload { Id: ID }
56
+
57
+ type UIAPIMutations {
58
+ EntityNameCreate(input: EntityNameCreateInput!): EntityNameCreatePayload
59
+ EntityNameDelete(input: RecordDeleteInput!): RecordDeletePayload
60
+ EntityNameUpdate(input: EntityNameUpdateInput!): EntityNameUpdatePayload
61
+ }
62
+ ```
63
+
64
+ ## Mutation Queries Input Field Constraints
65
+
66
+ 1. **`Create` Mutation Queries**:
67
+ 1. **MUST** include all required fields
68
+ 2. **MUST** only include createable fields
69
+ 3. Child relationships can't be set and **MUST** be excluded
70
+ 4. Fields with type `REFERENCE` can only be assigned IDs through their `ApiName` name
71
+ 2. **`Update` Mutation Queries**:
72
+ 1. **MUST** include the id of the entity to update
73
+ 2. **MUST** only include updateable fields
74
+ 3. Child relationships can't be set and **MUST** be excluded
75
+ 4. Fields with type `REFERENCE` can only be assigned IDs through their `ApiName` name
76
+ 3. **`Delete` Mutation Queries**:
77
+ 1. **MUST** include the id of the entity to delete
78
+
79
+ ## Mutation Queries Output Field Constraints
80
+
81
+ 1. **`Create` and `Update` Mutation Queries**:
82
+ 1. **MUST** exclude all child relationships
83
+ 2. **MUST** exclude all `REFERENCE` fields, unless accessed through their `ApiName` member (no navigation to referenced entity)
84
+ 3. Inaccessible fields will be reported as part of the `errors` attribute in the returned payload
85
+ 4. Child relationships **CAN'T** be queried as part of a mutation
86
+ 5. Fields with type `REFERENCE` can only be queried through their `ApiName` (no referenced entities navigation, no sub fields)
87
+ 2. **`Delete` Mutation Queries**:
88
+ 1. **MUST** only include the `Id` field
89
+
90
+ ## Mutation Query Report Template
91
+
92
+ Input arguments:
93
+ - Required fields: FieldName1 (Type1), FieldName2 (Type2)...
94
+ - Other fields: FieldName3 (Type3)...
95
+ Output fields: FieldNameA (TypeA), FieldNameB (TypeB)...
96
+
97
+ ## Mutation Query Templates
98
+
99
+ ```graphql
100
+ mutation mutateEntityName(
101
+ # arguments
102
+ ) {
103
+ uiapi {
104
+ EntityNameOperation(input: {
105
+ # the following is for `Create` and `Update` operations only
106
+ EntityName: {
107
+ # Input fields
108
+ }
109
+ # the following is for `Update` and `Delete` operations only
110
+ Id: ... # id here
111
+ }) {
112
+ # the following is for `Create` and `Update` operations only
113
+ Record {
114
+ # Output fields
115
+ }
116
+ # the following is for `Delete` operations only
117
+ Id: ... # id here
118
+ }
119
+ }
120
+ }
121
+ ```
122
+
123
+ ## Mutation Standalone (Default) Output Format - CLEAN CODE ONLY
124
+
125
+ ```javascript
126
+ const QUERY_NAME = `
127
+ mutation mutateEntity($input: EntityNameOperationInput!) {
128
+ uiapi {
129
+ EntityNameOperation(input: $input) {
130
+ # select output fields here depending on operation type
131
+ }
132
+ }
133
+ }
134
+ `;
135
+
136
+ const QUERY_VARIABLES = {
137
+ input: {
138
+ // The following is for `Create` and `Update` operations only
139
+ EntityName: {
140
+ // variables here
141
+ },
142
+ // The following is for `Update` and `Delete` operations only
143
+ Id: ... // id here
144
+ }
145
+ };
146
+ ```
147
+
148
+ **❌ DO NOT INCLUDE:**
149
+ - Explanatory comments about the query
150
+ - Field descriptions
151
+ - Additional text about what the query does
152
+ - Workflow step descriptions
153
+
154
+ **✅ ONLY INCLUDE:**
155
+ - Raw query string
156
+ - Variables object
157
+ - Nothing else
158
+
159
+ ## Generated Mutation Query Testing
160
+
161
+ **Triggering conditions** - **ALL CONDITIONS MUST VALIDATE***
162
+ 1. Only if the [Mutation Query Generation Workflow](#mutation-query-generation-workflow) step global status is `SUCCESS` and you have a generated query
163
+ 2. Only if the query to generate is a mutation query
164
+ 3. Only if non manual method was used during `LDS_Guide_GraphQL` rule execution to retrieve introspection data
165
+
166
+ **Workflow**
167
+ 1. **Report Step** - Explain that you are able to test the query using the same method used during introspection
168
+ 1. You **MUST** report the method you will use, based on the one you used during `LDS_Guide_GraphQL` rule execution
169
+ 2. **Interactive Step** - Ask the user whether they want you to test the query using the proposed method
170
+ 1. **WAIT** for the user's answer.
171
+ 3. **Input Arguments** - You **MUST** ask the user for the input arguments to use
172
+ 1. **WAIT** for the user's answer.
173
+ 4. **Test Query** - If the user are OK with you testing the query:
174
+ 1. Use the selected method to test the query
175
+ 2. **IMPORTANT** - If you use the Salesforce CLI `sf api request graphql` command, you will need to inject the variable values directly into the query, as this command doesn't accept variables as a parameter
176
+ 5. **Result Analysis** - Retrieve the `data` and `errors` attributes from the returned payload, and report the result of the test as one of the following options:
177
+ 1. `PARTIAL` if `data` is not an empty object, but `errors` is not an empty list - Explanation: some of the queried fields are not accessible on mutations
178
+ 2. `FAILED` if `data` is an empty object - Explanation: the query is not valid
179
+ 3. `SUCCESS` if `errors` is an empty list
180
+ 6. **Remediation Step** - If status is not `SUCCESS`, use the [`FAILED`](#failed-status-handling-workflow) or [`PARTIAL`](#partial-status-handling-workflow) status handling workflows
181
+
182
+ ### `FAILED` Status Handling Workflow
183
+
184
+ The query is invalid:
185
+ 1. **Error Analysis** - Parse and categorize the specific error messages
186
+ 2. **Root Cause Identification** - Use error message to identify the root cause:
187
+ - **Execution** - Error contains `invalid cross reference id` or `entity is deleted`
188
+ - **Syntax** - Error contains `invalid syntax`
189
+ - **Validation** - Error contains `validation error`
190
+ - **Type** - Error contains `VariableTypeMismatch` or `UnknownType`
191
+ - **Navigation** - Error contains `is not currently available in mutation results`
192
+ - **API Version** - Query deals with updates, you're testing with Connect API and error contains `Cannot invoke JsonElement.isJsonObject()`
193
+ 3. **Targeted Resolution** - Depending on the root cause categorization
194
+ - **Execution** - You're trying to update or delete an unknown/no longer available entity: either create an entity first, if you have generated the related query, or ask for a valid entity id to use
195
+ - **Syntax** - Update the query using the error message information to fix the syntax errors
196
+ - **Validation** - This field's name is most probably invalid, ask user for clarification and **WAIT** for the user's answer
197
+ - **Type** - Use the error details and GraphQL schema to correct argument's type, and adjust variables accordingly
198
+ - **Navigation** - Use the [`PARTIAL` status handling workflow](#partial-status-handling-workflow) below
199
+ - **API Version** - `Record` selection is only available with API version 64 and higher, **report** the issue, and try again with API version 64
200
+ 4. **Test Again** - Resume the [query testing workflow](#generated-mutation-query-testing) with the updated query (increment and track attempt counter)
201
+ 5. **Escalation Path** - If targeted resolution fails after 2 attempts, ask for additional details and restart the entire GraphQL workflow, going again through the introspection phase
202
+
203
+ ### `PARTIAL` Status Handling Workflow
204
+
205
+ The query can be improved:
206
+ 1. Report the fields mentioned in the `errors` list
207
+ 2. Explain that these fields can't be queried as part of a mutation query
208
+ 3. Explain that the query might be considered as failing, as it will report errors
209
+ 4. Offer to remove the offending fields
210
+ 5. **WAIT** for the user's answer
211
+ 6. If they are OK with removing the fields restart the [generation workflow](#mutation-query-generation-workflow) with the new field list
@@ -0,0 +1,185 @@
1
+ # GraphQL Read Query Generation
2
+
3
+ **Triggering conditions**
4
+ 1. Only if the `LDS_Guide_GraphQL` rule completed successfully
5
+ 2. Only if the query to generate is a read query
6
+
7
+ ## Your Role
8
+
9
+ You are a GraphQL expert and your role is to help generate Salesforce compatible GraphQL read queries once the exploration phase has completed.
10
+
11
+ You will leverage the context provided by the requesting user as well as the validation phase provided by the `LDS_Guide_GraphQL` rule.
12
+
13
+ If the `LDS_Guide_GraphQL` rule has not been executed yet, you **MUST** run it first, and then get back to read query generation. This tool will also provide you with a method to dynamically query the target org instance that you will use to test the generated query.
14
+
15
+ ## Read Query Generation Workflow
16
+
17
+ Strictly follow the rules below when generating the GraphQL read query:
18
+ 1. **No Proliferation** - Only generate for the explicitly requested fields, nothing else
19
+ 2. **Unique Query** - Leverage child relationships to query entities in one single query
20
+ 3. **Navigate Entities** - Always use `relationshipName` to access reference fields and child entities
21
+ 1. **Exception** - if the `relationshipName` field is null, you can't navigate the related entity, and will have to return the `Id` itself
22
+ 4. **Leverage Fragments** - Generate one fragment per possible type on polymorphic fields (field with `dataType="REFERENCE"` and more than one entry in `referenceToInfos` introspection attribute)
23
+ 5. **Type Consistency** - Make sure variables used as query arguments and their related fields share the same GraphQL type
24
+ 6. **Type Enforcement** - Make sure to leverage field type information from introspection and GraphQL schema to generate field access
25
+ 7. **Semi and anti joins** - Use the semi-join or anti-join templates to filter an entity with conditions on child entities
26
+ 8. **Query Generation** - Use the [template](#read-query-template) to generate the query
27
+ 9. **Output Format** - Use the [standalone](#read-standalone-default-output-format---clean-code-only)
28
+ 10. **Test the Query** - Use the [Generated Read Query Testing](#generated-read-query-testing) workflow to test the generated query
29
+ 1. **Report First** - Always report first, using the proper output format, before testing
30
+
31
+ ## Read Query Template
32
+
33
+ ```graphql
34
+ query QueryName {
35
+ uiapi {
36
+ query {
37
+ EntityName(
38
+ # conditions here
39
+ ) {
40
+ edges {
41
+ node {
42
+ # Direct fields
43
+ FieldName { value }
44
+
45
+ # Non-polymorphic reference (single type)
46
+ RelationshipName {
47
+ Id
48
+ Name { value }
49
+ }
50
+
51
+ # Polymorphic reference (multiple types)
52
+ PolymorphicRelationshipName {
53
+ ...TypeAInfo
54
+ ...TypeBInfo
55
+ }
56
+
57
+ # Child relationship (subquery)
58
+ RelationshipName(
59
+ # conditions here
60
+ ) {
61
+ edges {
62
+ node {
63
+ # fields
64
+ }
65
+ }
66
+ }
67
+ }
68
+ }
69
+ }
70
+ }
71
+ }
72
+ }
73
+
74
+ fragment TypeAInfo on TypeA {
75
+ Id
76
+ SpecificFieldA { value }
77
+ }
78
+
79
+ fragment TypeBInfo on TypeB {
80
+ Id
81
+ SpecificFieldB { value }
82
+ }
83
+ ```
84
+
85
+ ## Semi-Join and Anti-Join Condition Template
86
+
87
+ Semi-joins (resp. anti-joins) condition leverage parent-child relationships and allow filtering the parent entity using a condition on child entities.
88
+ This is a standard `where` condition, on the parent entity's `Id`, expressed using the `inq` (resp. `ninq`, i.e. not `inq`) operator. This operator accepts two attributes:
89
+ - The child entity camelcase name to apply the condition on, with a value expressing the condition
90
+ - The field name on the child entity containing the parent entity `Id`, which is the `fieldName` from the `childRelationships` information for the child entity
91
+ - If the only condition is related child entity existence, you can use an `Id: { ne: null }` condition
92
+
93
+ ### Semi-Join Example - ParentEntity with at least one Matching ChildEntity
94
+
95
+ ```graphql
96
+ query testSemiJoin {
97
+ uiapi {
98
+ query {
99
+ ParentEntity (
100
+ where: {
101
+ Id: {
102
+ inq: {
103
+ ChildEntity: {
104
+ # standard conditions here
105
+ Name: { like: "test%" }
106
+ Type: { eq: "some value" }
107
+ },
108
+ ApiName: "parentIdFieldInChild"
109
+ }
110
+ }
111
+ }
112
+ ) {
113
+ edges {
114
+ node {
115
+ Id
116
+ Name { value }
117
+ }
118
+ }
119
+ }
120
+ }
121
+ }
122
+ }
123
+ ```
124
+
125
+ ### Anti-Join Example - ParentEntity with no Matching ChildEntity
126
+
127
+ Same example as the [Semi-Join Example](#semi-join-example---parententity-with-at-least-one-matching-childentity), but replacing the `inq` operator by the `ninq` one.
128
+
129
+ ## Read Standalone (Default) Output Format - CLEAN CODE ONLY
130
+
131
+ ```javascript
132
+ const QUERY_NAME = `
133
+ query GetData {
134
+ // query here
135
+ }
136
+ `;
137
+
138
+ const QUERY_VARIABLES = {
139
+ // variables here
140
+ };
141
+ ```
142
+
143
+ **❌ DO NOT INCLUDE:**
144
+ - Explanatory comments about the query
145
+ - Field descriptions
146
+ - Additional text about what the query does
147
+ - Workflow step descriptions
148
+
149
+ **✅ ONLY INCLUDE:**
150
+ - Raw query string
151
+ - Variables object
152
+ - Nothing else
153
+
154
+ ## Generated Read Query Testing
155
+
156
+ **Triggering conditions** - **ALL CONDITIONS MUST VALIDATE***
157
+ 1. Only if the [Read Query Generation Workflow](#read-query-generation-workflow) step global status is `SUCCESS` and you have a generated query
158
+ 2. Only if the query to generate is a read query
159
+ 3. Only if non manual method was used during `LDS_Guide_GraphQL` rule execution to retrieve introspection data
160
+
161
+ **Workflow**
162
+ 1. **Report Step** - Explain that you are able to test the query using the same method used during introspection
163
+ 1. You **MUST** report the method you will use, based on the one you used during `LDS_Guide_GraphQL` rule execution
164
+ 2. **Interactive Step** - Ask the user whether they want you to test the query using the proposed method
165
+ 1. **WAIT** for the user's answer.
166
+ 3. **Test Query** - If the user are OK with you testing the query:
167
+ 1. Use the selected method to test the query
168
+ 2. Report the result of the test as `SUCCESS` if the query executed without error, or `FAILED` if you got errors
169
+ 3. If the query executed without any errors, but you received no data, then the query is valid, and the result of the test is `SUCCESS`
170
+ 4. **Remediation Step** - If status is `FAILED`, use the [`FAILED` status handling workflows](#failed-status-handling-workflow)
171
+
172
+ ### `FAILED` Status Handling Workflow
173
+
174
+ The query is invalid:
175
+ 1. **Error Analysis** - Parse and categorize the specific error messages
176
+ 2. **Root Cause Identification** - Use error message to identify the root cause:
177
+ - **Syntax** - Error contains `invalid syntax`
178
+ - **Validation** - Error contains `validation error`
179
+ - **Type** - Error contains `VariableTypeMismatch` or `UnknownType`
180
+ 3. **Targeted Resolution** - Depending on the root cause categorization
181
+ - **Syntax** - Update the query using the error message information to fix the syntax errors
182
+ - **Validation** - This field's name is most probably invalid, ask user for clarification and **WAIT** for the user's answer
183
+ - **Type** - Use the error details and GraphQL schema to correct argument's type, and adjust variables accordingly
184
+ 4. **Test Again** - Resume the [query testing workflow](#generated-read-query-testing) with the updated query (increment and track attempt counter)
185
+ 5. **Escalation Path** - If targeted resolution fails after 2 attempts, ask for additional details and restart the entire GraphQL workflow, going again through the introspection phase
@@ -0,0 +1,205 @@
1
+ # GraphQL Query Generation Guidelines
2
+
3
+ You are a GraphQL expert, and your role is to help craft GraphQL queries that match Salesforce schema requirements and specificities.
4
+
5
+ This is the main instructions source, and you will leverage the following rules to complete your task:
6
+ - The `LDS_Explore_GraphQLSchema` rule provides Salesforce's static GraphQL schema information
7
+ - The `LDS_Generate_GraphQLReadQuery` rule is specialized in GraphQL read query generation
8
+ - The `LDS_Generate_GraphQLMutationQuery` rule is specialized in GraphQL mutation query generation
9
+
10
+
11
+ **CRITICAL ENFORCEMENT RULES:**
12
+ - **Workflow Enforcement** - You **MUST** follow the workflow steps below, in order
13
+ - **Workflow Steps are Mandatory** - All workflow steps are mandatory, none can be skipped
14
+ - **Workflow Steps Chaining** - Steps need to be chained one after the other
15
+ - **Hard Stop on Failed Step** - Any failed step blocks the workflow until remediation actions are completed
16
+ - **Step Status Reporting** - Each step must report final status in a clear and concise way
17
+ - **Common Knowledge** - You **MUST NOT** rely on common Salesforce knowledge related to entities, always ask for introspection data - if not available, **FAIL** the query generation (hard stop)
18
+ - **Never guess** - You **MUST NOT** guess field type, always rely on introspection data (e.g. Owner doesn't mean User, the field might have a different type or be polymorphic)
19
+
20
+
21
+ ## STEP 1: General Query Information
22
+
23
+ ### Information Workflow
24
+
25
+ 1. Identify namespace: one of `uiapi` or `setup`, defaults to `uiapi`
26
+ 2. Identify query type: one of `read` or `mutation`, defaults to `read`
27
+ 3. Identify desired output
28
+ 4. Use the [information report template](#information-report-template) below to report result
29
+
30
+ ### Information Report Template
31
+
32
+ You want to build a GraphQL {type} query on entities hosted in the {namespace} namespace.
33
+
34
+
35
+ ## STEP 2: Select Introspection Method
36
+
37
+ **IMPORTANT** - This is an **interactive step**, you **MUST** wait for the user to answer your questions, and you **MUST** pause until they do:
38
+ Ask the user how they want to retrieve the introspection information using the following list:
39
+ 1. ***Manually*** - User will execute the queries for you
40
+ 2. ***Connect API*** - You will execute introspection queries using the `graphql`Connect API endpoint
41
+ 3. ***Salesforce CLI*** - You will execute introspection queries using Salesforce CLI
42
+
43
+ **WAIT** for the user's answer.
44
+
45
+ If user picks option 2, Connect API:
46
+ 1. ***Local org details*** - Ask for server url, API version (e.g. 65) and a valid OAuth token, and store these in url, version and token variables
47
+ 2. ***Default API Version*** - If no API version is provided, use 66 as the default value
48
+ 3. ***Escaping*** - Make sure to escape the token to account for shell limitations (e.g. the `!` character might need to be escaped when using bash)
49
+ **WAIT** for the user's answer.
50
+
51
+ **Report** - Mention the method you will use to retrieve introspection data, one of `Salesforce CLI`, `Connect API` or `user manual request`; if `Connect API`, mention server url `{url}/services/data/v{version}.0/graphql` and token
52
+
53
+
54
+ ## STEP 3: Entities Identification
55
+
56
+ **CRITICAL** Your goal is to extract and list **entities** involved in the query to generate:
57
+ - **Entity Names** must obey CamelCase convention
58
+ - **Introspection** - If some entity names are not provided and can't be deduced from context, use the [Map Entity Names](#map-entity-names) workflow
59
+ - **Resolution** - If some entity names are resolved by the previous introspection sub step, ask the user for their names
60
+ - Do **NOT** try to resolve exact field names, as this will be completed as part of [STEP 4](#step-4-iterative-entities-introspection)
61
+ - **Report** - Use the [Identification Report Template](#identification-report-template) to report final step status
62
+
63
+ ### Map Entity Names
64
+
65
+ **List Accessible Entities** - Get a list of accessible entities using one of the following options, depending on the method selected by [STEP 2](#step-2-select-introspection-method):
66
+ 1. If `Salesforce CLI` was selected, use the `sf sobject list --sobject all` command
67
+ 2. If `Connect API` was selected, use `curl` to retrieve introspection data, using the `/services/data/v66.0/ui-api/object-info/` endpoint
68
+ 3. Otherwise, you **MUST** ask the user to retrieve the list of accessible entities for you, and wait for their answer
69
+
70
+ **Report Status** - Use the [report template](#identification-report-template) to report status
71
+ **HARD STOP** - Evaluate [hard stop rules](#identification-hard-stop-rules)
72
+
73
+ ### Identification Hard Stop Rules
74
+
75
+ **Triggering conditions** - ALWAYS
76
+
77
+ If the unknown entity list is not empty:
78
+ - the global step status is `FAILED`
79
+ - stop generation
80
+ - go through [remediation actions](#identification-remediation-actions)
81
+
82
+ ### Identification Report Template
83
+
84
+ **Triggering conditions** - ALWAYS
85
+
86
+ List identified entities:
87
+ - `Entity1` (`Field1.1`, `Field1.2`, ...)
88
+ List unknown entities:
89
+ - entity textual name
90
+
91
+ ### Identification Remediation Actions
92
+
93
+ **Triggering conditions** - Only if the global status for the step is `FAILED`
94
+
95
+ **Interactive** - Ask the user for clarification on any unknown entities, and restart [STEP 3](#step-3-entities-identification)
96
+
97
+
98
+ ## STEP 4: Iterative Entities Introspection
99
+
100
+ **CRITICAL** Your goal is to extract and list entity **fields** involved in the query to generate
101
+
102
+ ### Introspection Workflow
103
+
104
+ **Triggering conditions** - ALWAYS
105
+
106
+ Rules:
107
+ 1. Start with the list of entities from [STEP 3](#step-3-entities-identification)
108
+ 2. **NO ASSUMPTIONS** - You ***MUST*** rely only on introspection data for field name and type
109
+ 3. **NO COMMON KNOWLEDGE** - You ***MUST*** rely only on introspection data for field name and type
110
+ 4. You **MUST** follow the workflow below until all entities involved in the query to generate are properly described
111
+
112
+ **CRITICAL** - **WORKFLOW** - using the list of unknown entities, ***strictly*** follow the following steps, in order:
113
+ 1. **Cleanup** - Remove from the list all entities for which you already retrieved introspection information
114
+ 2. **Introspection Phase** - Request introspection data for all unknown entities
115
+ 1. If you're allowed to use Salesforce CLI, you can use the `sf api request graphql --body "query getData { ... }"` using the [Introspection GraphQL Query](#introspection-graphql-query) query template to replace the $query variable
116
+ 2. If you have valid url, version and token variables, use `curl` to retrieve introspection data, using the [Introspection GraphQL Query](#introspection-graphql-query) query template and proper escaping to avoid shell issues with token characters
117
+ 3. If you don't have valid url, version or token info, you **MUST** ask the user to run the query for you using the [Introspection GraphQL Query](#introspection-graphql-query) query template and **WAIT** for them to provide the required data
118
+ 4. **HARD STOP** - If you didn't get any introspection data back, **STOP** here, and jump to point 8 below
119
+ 3. **Fields Identification** - Using introspection data, retrieve requested field types
120
+ 4. **Reference Fields** - Using introspection data, identify reference requested fields (`dataType="REFERENCE"`)
121
+ 1. **IMPORTANT** - Two fields with the same name from two different entities might have different types
122
+ 2. retrieve possible types using the `referenceToInfos` attribute
123
+ 3. **Polymorphic Fields** - Reference fields with more than entry in the `referenceToInfos` attribute are polymorphic
124
+ 4. add any unknown entity references to the list of entities to introspect
125
+ 5. **Child Relationships** - Using introspection data, identify all requested fields that are child relationships using the `childObjectApiName` attribute
126
+ 1. add any unknown types to the list of types to discover
127
+ 6. **Secondary Introspection Phase** - If list of types to discover is not empty, resume the process from point 1 above
128
+ 7. **Field Type Information** - Retrieve GraphQL detailed type information for all non reference non child relationships requested fields using the `LDS_Explore_GraphQLSchema` rule
129
+ 8. **Report** - Use the [Introspection Report Template](#introspection-report-template) to report on retrieved information
130
+ 9. **Evaluate** - Evaluate the [Introspection Hard Stop Rules](#introspection-hard-stop-rules)
131
+
132
+ ### Introspection Hard Stop Rules
133
+
134
+ **Triggering conditions** - ALWAYS
135
+
136
+ **Critical rule** - If the global status is `FAILED`, **STOP** generation here, and go through [introspection remediation actions](#introspection-remediation-actions)
137
+
138
+ ### Introspection Remediation Actions
139
+
140
+ **Triggering conditions** - Only if the global status for the step is `FAILED`
141
+
142
+ **Action** - Ask for clarification on any unknown fields, and resume the [Introspection Workflow](#introspection-workflow).
143
+
144
+ ### Introspection Report Template
145
+
146
+ **Critical rule** An entity is ✅ only if it has no unknown fields, otherwise it is ❌
147
+ **Critical rule** If any of the entities is not checked in the report, the global status is `FAILED`
148
+
149
+ Introspection phase:
150
+ {✅|❌} `Entity1`
151
+ - Standard fields: `Field1` (`type`), `Field2` (`type`)...
152
+ - Reference fields: `Field3` (`referenceToInfos` information from introspection)...
153
+ - Child relationships: `Field4` (`childObjectApiName` from introspection)
154
+ - Unknown fields: `Field5`...
155
+ {✅|❌} `Entity2`
156
+ - ...
157
+ Introspection workflow status: {SUCCESS|FAILED}
158
+
159
+ ### Introspection GraphQL Query
160
+
161
+ **CRITICAL RULES**
162
+ - When using the request below, proceed with batches of 3 entities max in order to limit the payload size.
163
+ - When introspecting for mutation create queries, add `required` and `createable` to the `fields` field.
164
+ - When introspecting for mutation update queries, add `updateable` to the `fields` field.
165
+ - When introspecting for mutation create or update queries, make sure you query for all fields (no pre-filtering).
166
+ - You don't need introspection for mutation delete queries, as you only need the `Id` field.
167
+
168
+ ```graphql
169
+ query getData {
170
+ uiapi {
171
+ objectInfos(apiNames: ["EntityName1", "EntityName2", ...]) {
172
+ ApiName
173
+ childRelationships { childObjectApiName, fieldName, relationshipName }
174
+ fields { ApiName, dataType, relationshipName, referenceToInfos { ApiName } }
175
+ }
176
+ }
177
+ }
178
+ ```
179
+
180
+
181
+ ## STEP 5: Read Query Generation
182
+
183
+ **Triggering conditions**
184
+ 1. Only if the [iterative entities introspection](#step-4-iterative-entities-introspection) step global status is `SUCCESS`
185
+ 2. Only if the query to generate is a read query
186
+
187
+ Run the `LDS_Generate_GraphQLReadQuery` rule.
188
+
189
+
190
+ ## STEP 6: Mutation Query Generation
191
+
192
+ **Triggering conditions**
193
+ 1. Only if the [iterative entities introspection](#step-4-iterative-entities-introspection) step global status is `SUCCESS`
194
+ 2. Only if the query to generate is a mutation query
195
+
196
+ Run the `LDS_Generate_GraphQLMutationQuery` rule.
197
+
198
+
199
+ ## COMMON WORKFLOW VIOLATIONS TO AVOID
200
+
201
+ - **Bypass Hard Stop Rules** - When a [workflow](#introspection-workflow) step fails to complete, you **MUST** stop here and wait for the remediation action to be completed - **NEVER** attempt to proceed with subsequent rules
202
+ - **Guess Field Name or Type** - You **MUST NOT** try to guess field name or type based on assumptions, only leverage introspection and schema data
203
+ - **Skip Introspection Phase** - **NEVER** bypass introspection phase - only use data from introspection, whether you auto executed the query or asked the user to run it for you
204
+ - **Invalid Type Consistency** - Strong typing must be enforced at all times, and type information must come either from introspection or using the GraphQL schema
205
+ - **Bypass Workflow** - You **MUST** follow strictly steps in the [introspection workflow](#introspection-workflow), **NEVER** try to bypass any step, or continue with subsequent steps if the current one exited with a failed status