@ttoss/graphql-api 0.8.10 → 0.8.11
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.
- package/README.md +66 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -185,6 +185,72 @@ composeWithRelay(UserTC);
|
|
|
185
185
|
|
|
186
186
|
_We inspired ourselves on [graphql-compose-relay](https://graphql-compose.github.io/docs/plugins/plugin-relay.html) to create `composeWithRelay`._
|
|
187
187
|
|
|
188
|
+
### What Is a Node in Relay
|
|
189
|
+
|
|
190
|
+
In the [Relay Server Specification](https://relay.dev/docs/guides/graphql-server-specification/), a **Node** is any object that:
|
|
191
|
+
|
|
192
|
+
Has a **globally unique identity** across your entire GraphQL API.
|
|
193
|
+
Can be **fetched independently** using the `node(id: ID!)`: Node query.
|
|
194
|
+
Implements the `Node` interface.
|
|
195
|
+
|
|
196
|
+
Only types that are nodes should use `composeWithRelay`.
|
|
197
|
+
|
|
198
|
+
### When to Use `composeWithRelay` (i.e., When Is a Type a Node?)
|
|
199
|
+
|
|
200
|
+
| Condition | Must Be True |
|
|
201
|
+
| ---------------------------------------------------------- | ------------ |
|
|
202
|
+
| Has a unique record ID in your database or external system | Yes |
|
|
203
|
+
| Can be refetched by ID from anywhere in the app | Yes |
|
|
204
|
+
| Clients may cache and reuse it via global ID | Yes |
|
|
205
|
+
| Appears nested inside other objects and also stands alone | Yes |
|
|
206
|
+
|
|
207
|
+
#### Not Nodes (Don't Use `composeWithRelay`):
|
|
208
|
+
|
|
209
|
+
Examples of types should **never** use `composeWithRelay`
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
// Wrong - embedded objects
|
|
213
|
+
SubscriptionUpcomingInvoiceTC; // Only exists inside Subscription
|
|
214
|
+
PriceDetailsTC; // Embedded value object
|
|
215
|
+
MarketingFeatures; // Configuration data
|
|
216
|
+
|
|
217
|
+
// Wrong - computed values
|
|
218
|
+
UserFullNameTC; // Derived from firstName + lastName
|
|
219
|
+
OrderTotalTC; // Calculated from line items
|
|
220
|
+
|
|
221
|
+
// Wrong - transient data
|
|
222
|
+
ValidationErrorTC; // Temporary error state
|
|
223
|
+
SearchResultTC; // Query response wrapper
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
#### Why Embedded Objects Are Not Nodes
|
|
227
|
+
|
|
228
|
+
Consider this embedded object:
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
type Subscription {
|
|
232
|
+
upcomingInvoice: SubscriptionUpcomingInvoice
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
`SubscriptionUpcomingInvoice` should **not** use `composeWithRelay` because it fails the Node criteria:
|
|
237
|
+
|
|
238
|
+
**Missing Node Requirements:**
|
|
239
|
+
|
|
240
|
+
- No independent identity - exists only within its parent Subscription
|
|
241
|
+
- Cannot be refetched independently - no direct database record
|
|
242
|
+
- Not cached separately - lifecycle tied 1:1 to parent object
|
|
243
|
+
- Never queried directly - accessed only through parent
|
|
244
|
+
|
|
245
|
+
**Problems Created by `composeWithRelay`:**
|
|
246
|
+
|
|
247
|
+
- Generates meaningless global IDs for non-independent objects
|
|
248
|
+
- Pollutes the `node` interface with unfetchable objects
|
|
249
|
+
- Breaks Relay's cache normalization expectations
|
|
250
|
+
- Adds unnecessary complexity without any benefit
|
|
251
|
+
|
|
252
|
+
**Simple Test:** If you cannot write `node(id: "...")` to fetch this object independently, it should not be a Node.
|
|
253
|
+
|
|
188
254
|
### Connections
|
|
189
255
|
|
|
190
256
|
This package provides the method `composeWithConnection` to create a connection type and queries for a given type, based on [graphql-compose-connection](https://graphql-compose.github.io/docs/plugins/plugin-connection.html) plugin and following the [Relay Connection Specification](https://facebook.github.io/relay/graphql/connections.htm).
|
|
@@ -313,7 +379,6 @@ It's an object that defines the sort options. Each key is the sort name and the
|
|
|
313
379
|
- `value`: and object that the `args` resolver will receive as the `sort` argument. It'll also be the values of the sort enum composer created (check the implementation details [here](https://github.com/graphql-compose/graphql-compose-connection/blob/master/src/types/sortInputType.ts).)
|
|
314
380
|
- `cursorFields`: an array of fields that will be used to create the cursor.
|
|
315
381
|
- `beforeCursorQuery` and `afterCursorQuery`: methods that will be used to create the `rawQuery` object for the `findManyResolver`. They receive the following arguments:
|
|
316
|
-
|
|
317
382
|
- `rawQuery`: the `rawQuery` object that will be used to find the nodes.
|
|
318
383
|
- `cursorData`: the data from the cursor define on `cursorFields`. For example, if you define `cursorFields` as `['id', 'name']`, the `cursorData` will an object with the `id` and `name` properties.
|
|
319
384
|
- `resolveParams`: the `resolveParams` object from the resolver. You can access `args`, `context` and `info` and other GraphQL properties from this object.
|