@vantreeseba/drizzle-graphql 15.1.3 → 15.1.5
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 +50 -11
- package/dist/index.cjs +292 -101
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -2
- package/dist/index.d.ts +16 -2
- package/dist/index.js +292 -101
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -301,7 +301,7 @@ narrow the scope, never widen it. It reaches every path that touches the table:
|
|
|
301
301
|
| `orderBy` through a to-one — `comments(orderBy: { post: { title: … } })` | an out-of-scope post sorts as `NULL` |
|
|
302
302
|
| `updatePosts`, `updatePostsMany`, `deletePosts` | an out-of-scope row is simply not matched |
|
|
303
303
|
| `upsertPosts` (conflict branch) | a conflicting row outside the scope is left alone, not taken over |
|
|
304
|
-
| nested `connect` / `disconnect` / `set` | only in-scope rows can be attached or detached |
|
|
304
|
+
| nested `connect` / `disconnect` / `set` | only in-scope rows can be attached or detached; a many-to-many `set` keeps the links to out-of-scope rows |
|
|
305
305
|
|
|
306
306
|
Two things it deliberately does not do:
|
|
307
307
|
|
|
@@ -347,10 +347,14 @@ const { schema } = buildSchema(db, {
|
|
|
347
347
|
- The column is **removed from `CreatePostsInput` and `UpdatePostsInput`**, so a client cannot
|
|
348
348
|
send it at all — the SDL itself says the column is server-owned. It stays readable on the
|
|
349
349
|
object type.
|
|
350
|
-
- Every insert stamps it, including rows created by a nested `create
|
|
350
|
+
- Every insert stamps it, including rows created by a nested `create` and junction rows a
|
|
351
|
+
many-to-many `connect` / `set` inserts.
|
|
351
352
|
- Updates never write it, so an update cannot hand a row to another owner. Neither does the
|
|
352
353
|
conflict branch of an upsert: it is left out of the default overwrite and of the columns
|
|
353
354
|
`onConflict.update` can name.
|
|
355
|
+
- A relation whose foreign key is such a column gets no
|
|
356
|
+
[nested-write](#nested-writes) field from either side: every nested operation on it would
|
|
357
|
+
write that column. The build notes which relations it left out.
|
|
354
358
|
|
|
355
359
|
Together the two close the loop: `contextValues` decides which tenant a new row belongs to, and
|
|
356
360
|
`scope` decides which rows a request can see and change afterwards.
|
|
@@ -493,8 +497,8 @@ What a declared table gets:
|
|
|
493
497
|
| relation filters — `users(where: { posts: { some: {} } })`, `none`, `every`, `.through()` junctions | a marked post neither matches nor blocks `none`, with the same default as the relation field (see below) |
|
|
494
498
|
| `orderBy` through a to-one | a marked target the relation field hides sorts as `NULL` |
|
|
495
499
|
| `updatePosts`, `updatePostsMany`, a second `deletePosts` | a marked row is simply not matched |
|
|
496
|
-
| nested `connect` / `disconnect` / `set` | a marked row cannot be attached or detached |
|
|
497
|
-
| `CreatePostsInput`, `UpdatePostsInput` | the marker column is **removed** — only the mutations write it |
|
|
500
|
+
| nested `connect` / `disconnect` / `set` | a marked row cannot be attached or detached; a many-to-many `set` keeps the links to marked rows |
|
|
501
|
+
| `CreatePostsInput`, `UpdatePostsInput`, nested `create` payloads | the marker column is **removed** — only the mutations write it |
|
|
498
502
|
|
|
499
503
|
Every read path also gains a `deleted` argument for the cases the default hides:
|
|
500
504
|
|
|
@@ -1361,6 +1365,9 @@ can count or summarise related rows without fetching them:
|
|
|
1361
1365
|
and applies only to the related rows
|
|
1362
1366
|
- A parent with no related rows gets `count: 0` and `null` for every other aggregate
|
|
1363
1367
|
- To-one relations get no aggregate field — there is nothing to aggregate over
|
|
1368
|
+
- A relation joined on several columns (`from: [a, b], to: [x, y]`) is grouped by all of
|
|
1369
|
+
them, so each parent counts only the rows that match it on every column. A many-to-many
|
|
1370
|
+
(`.through()`) relation whose junction has a composite key gets no aggregate field
|
|
1364
1371
|
- The field is skipped if its name would collide with a column or another relation
|
|
1365
1372
|
- Set `features: { relationAggregates: false }` (globally or per table) to leave these
|
|
1366
1373
|
fields out
|
|
@@ -1689,9 +1696,10 @@ mutation {
|
|
|
1689
1696
|
|
|
1690
1697
|
- `connect`, `disconnect` and `set` take the target's own `Filters` input — a list of them
|
|
1691
1698
|
on a to-many relation, a single one that must match exactly one row on a to-one — so they
|
|
1692
|
-
select rows the same way a query does. A to-one `
|
|
1693
|
-
|
|
1694
|
-
|
|
1699
|
+
select rows the same way a query does. A to-one `connect` that matches no row, or several,
|
|
1700
|
+
fails with `DRIZZLE_NESTED_WRITE_INVALID` before anything is detached. A to-one
|
|
1701
|
+
`disconnect` is just `disconnect: true`, since there is only one row to detach. A filter
|
|
1702
|
+
that matches everything is rejected rather than attaching the whole table
|
|
1695
1703
|
- `set` replaces the relation wholesale — everything attached is detached first, then the
|
|
1696
1704
|
filters attach. It runs before `create`, so a row created in the same write survives it
|
|
1697
1705
|
- A to-one relation takes one operation at a time (`connect` **or** `disconnect` **or**
|
|
@@ -1713,14 +1721,42 @@ mutation {
|
|
|
1713
1721
|
— so a failure anywhere leaves nothing behind
|
|
1714
1722
|
- A `set` that carries only relation fields is a valid update: it changes what the row is
|
|
1715
1723
|
attached to without rewriting the row
|
|
1724
|
+
- When the parent write produces no row — an update whose `where` matched nothing, an
|
|
1725
|
+
insert or upsert a conflict turned into a no-op — whatever a parent-side `create` inserted
|
|
1726
|
+
for it is rolled back too, so no orphan is left. In a batch only that entry is undone
|
|
1727
|
+
- The returned rows reflect the nested write: on a self-referencing relation
|
|
1728
|
+
(`reports: { connect: … }` on the row itself), where a child-side statement rewrites the
|
|
1729
|
+
parent row, the parent rows are read back after it
|
|
1730
|
+
- A relation joining on more than one column per side gets no nested-write field: setting
|
|
1731
|
+
one key would leave the rest of the join (a tenant column, say) unmatched and unwritten
|
|
1732
|
+
|
|
1733
|
+
### A relation's own `where`
|
|
1734
|
+
|
|
1735
|
+
A relation declared with a `where` (`publishedPosts: r.many.posts({ …, where: { published: true } })`)
|
|
1736
|
+
is written through the same way it is read: only the rows it shows.
|
|
1737
|
+
|
|
1738
|
+
- `disconnect`, `set`, and the detaching a to-one attach does, reach only rows that satisfy
|
|
1739
|
+
the `where` — `publishedPosts: { set: [] }` leaves the drafts attached
|
|
1740
|
+
- `connect` and `set` attach only rows that satisfy it, so the relation shows what was
|
|
1741
|
+
attached. A to-one `connect` must match exactly one such row
|
|
1742
|
+
- There is no `create`: the inserted row is attached whether or not it satisfies the
|
|
1743
|
+
`where`, and the relation could come back without it. Create it with its own mutation, or
|
|
1744
|
+
through a relation with no `where`
|
|
1745
|
+
- A many-to-many `set` unlinks only the links to rows the `where` shows
|
|
1746
|
+
- A relation that inherits its `where` from the other side (declared without `from` / `to`)
|
|
1747
|
+
filters the parent rather than the target. Writing through it on a parent row it is
|
|
1748
|
+
hidden for fails with `DRIZZLE_NESTED_WRITE_INVALID`
|
|
1716
1749
|
|
|
1717
1750
|
### The target table's own rules
|
|
1718
1751
|
|
|
1719
1752
|
A nested write is a write to another table, so it follows that table's rules, not just the
|
|
1720
1753
|
root field's:
|
|
1721
1754
|
|
|
1722
|
-
- **`scope`**
|
|
1723
|
-
|
|
1755
|
+
- **`scope`** and **`softDelete`** narrow the rows `connect` / `disconnect` / `set` can
|
|
1756
|
+
reach — a many-to-many `set` keeps the links to rows it cannot reach — and
|
|
1757
|
+
**`contextValues`** stamp the rows a nested `create` inserts. A relation keyed on a
|
|
1758
|
+
`contextValues` column is not offered at all, and the payload of a nested `create` leaves
|
|
1759
|
+
out the context columns and the soft-delete marker, as the target's own create input does
|
|
1724
1760
|
- **`features`**: each nested input is generated only when the table it writes has that
|
|
1725
1761
|
write turned on. Whatever is left out is noted on the console at build time, and a
|
|
1726
1762
|
relation with nothing left loses its field altogether
|
|
@@ -1764,7 +1800,8 @@ mutation {
|
|
|
1764
1800
|
re-connecting is a no-op rather than a unique-constraint error
|
|
1765
1801
|
- `disconnect` deletes only the links, never the rows they pointed at
|
|
1766
1802
|
- `set: []` unlinks everything and links nothing back, which is how a many-to-many relation
|
|
1767
|
-
is cleared
|
|
1803
|
+
is cleared. "Everything" is everything the request could have unlinked: links to rows
|
|
1804
|
+
outside the target's `scope`, soft-deleted, or hidden by the relation's own `where` stay
|
|
1768
1805
|
- There is no `create`: inserting a row *and* linking it is a write to two tables, and the
|
|
1769
1806
|
link is what the relation field is for. Create the row with its own mutation, then
|
|
1770
1807
|
`connect` it
|
|
@@ -2447,7 +2484,9 @@ Generated schemas resolve nested relations without N+1 query explosions:
|
|
|
2447
2484
|
(request-scoped, keyed on the GraphQL `context`), preventing N+1. Per-parent
|
|
2448
2485
|
`limit` / `offset` on a to-many relation is applied across the whole batch using a
|
|
2449
2486
|
`ROW_NUMBER() OVER (PARTITION BY …)` window function — still one query, not one per
|
|
2450
|
-
parent.
|
|
2487
|
+
parent. A relation joined on several columns (`from: [a, b], to: [x, y]`) is batched,
|
|
2488
|
+
grouped and partitioned by all of them, matching the parents with
|
|
2489
|
+
`(a = … AND b = …) OR …` instead of `IN (…)`.
|
|
2451
2490
|
|
|
2452
2491
|
```Typescript
|
|
2453
2492
|
// entities.fieldResolvers is keyed by table name, then relation name
|