@ttoss/graphql-api 0.8.10 → 0.8.12

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 (2) hide show
  1. package/README.md +66 -1
  2. package/package.json +4 -4
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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttoss/graphql-api",
3
- "version": "0.8.10",
3
+ "version": "0.8.12",
4
4
  "description": "A library for building GraphQL APIs using ttoss ecosystem.",
5
5
  "license": "MIT",
6
6
  "author": "ttoss",
@@ -35,16 +35,16 @@
35
35
  "graphql-middleware": "^6.1.35",
36
36
  "graphql-shield": "^7.6.5",
37
37
  "npmlog": "^7.0.1",
38
- "@ttoss/ids": "^0.3.8"
38
+ "@ttoss/ids": "^0.3.9"
39
39
  },
40
40
  "peerDependencies": {
41
41
  "graphql": "^16.6.0"
42
42
  },
43
43
  "devDependencies": {
44
44
  "graphql": "^16.11.0",
45
- "jest": "^30.0.4",
45
+ "jest": "^30.2.0",
46
46
  "tsup": "^8.5.0",
47
- "@ttoss/config": "^1.35.8"
47
+ "@ttoss/config": "^1.35.9"
48
48
  },
49
49
  "keywords": [
50
50
  "api",