Skip to content

Commit db21c2d

Browse files
authored
Merge pull request #388 from constructive-io/migration-graphile-many-to-many
Migration graphile many to many
2 parents dfc7e13 + f683df0 commit db21c2d

53 files changed

Lines changed: 11248 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/run-tests.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ jobs:
7070
env: {}
7171
- package: graphile/graphile-simple-inflector
7272
env: {}
73+
- package: graphile/graphile-many-to-many
74+
env: {}
7375
- package: graphile/graphile-i18n
7476
env: {}
7577
- package: graphile/graphile-meta-schema
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
MIT License
2+
3+
Copyright (c) 2019-present, Constructive <developers@constructive.io>
4+
Copyright (c) 2019 Dan Lynch <pyramation@gmail.com>
5+
Copyright (c) 2018 Graphile Contrib
6+
7+
Permission is hereby granted, free of charge, to any person obtaining a copy
8+
of this software and associated documentation files (the "Software"), to deal
9+
in the Software without restriction, including without limitation the rights
10+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
copies of the Software, and to permit persons to whom the Software is
12+
furnished to do so, subject to the following conditions:
13+
14+
The above copyright notice and this permission notice shall be included in all
15+
copies or substantial portions of the Software.
16+
17+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23+
SOFTWARE.
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
# graphile-many-to-many
2+
3+
<p align="center" width="100%">
4+
<img height="250" src="https://raw.githubusercontent.com/constructive-io/constructive/refs/heads/main/assets/outline-logo.svg" />
5+
</p>
6+
7+
<p align="center" width="100%">
8+
<a href="https://github.com/constructive-io/constructive/actions/workflows/run-tests.yaml">
9+
<img height="20" src="https://github.com/constructive-io/constructive/actions/workflows/run-tests.yaml/badge.svg" />
10+
</a>
11+
<a href="https://github.com/constructive-io/constructive/blob/main/LICENSE">
12+
<img height="20" src="https://img.shields.io/badge/license-MIT-blue.svg"/>
13+
</a>
14+
<a href="https://www.npmjs.com/package/graphile-many-to-many">
15+
<img height="20" src="https://img.shields.io/github/package-json/v/launchql/launchql?filename=graphile%2Fgraphile-many-to-many%2Fpackage.json"/>
16+
</a>
17+
</p>
18+
19+
**`graphile-many-to-many`** adds connection fields for many-to-many relations in PostGraphile v4 / Graphile Engine schemas so join tables automatically expose relay-friendly collections. Requires `postgraphile@^4.5.0` or `graphile-build-pg@^4.5.0`.
20+
21+
## 🚀 Installation
22+
23+
```bash
24+
pnpm add graphile-many-to-many
25+
```
26+
27+
## ✨ Features
28+
29+
- Generates many-to-many connection and simple collection fields from junction tables
30+
- Works with PostGraphile CLI and library usage
31+
- Smart comments (`@omit manyToMany`) to suppress specific relations
32+
- Configurable field names via inflectors or smart comments
33+
34+
## 📦 Usage
35+
36+
Append the plugin and the fields will be added to your schema.
37+
38+
### PostGraphile CLI
39+
40+
```bash
41+
pnpm add postgraphile graphile-many-to-many
42+
npx postgraphile --append-plugins graphile-many-to-many
43+
```
44+
45+
### Library
46+
47+
```js
48+
const express = require("express");
49+
const { postgraphile } = require("postgraphile");
50+
const PgManyToManyPlugin = require("graphile-many-to-many");
51+
52+
const app = express();
53+
54+
app.use(
55+
postgraphile(process.env.DATABASE_URL, "app_public", {
56+
appendPlugins: [PgManyToManyPlugin],
57+
graphiql: true,
58+
})
59+
);
60+
61+
app.listen(5000);
62+
```
63+
64+
Example query:
65+
66+
```graphql
67+
{
68+
allPeople {
69+
nodes {
70+
personName
71+
teamsByTeamMemberPersonIdAndTeamId {
72+
nodes {
73+
teamName
74+
}
75+
}
76+
}
77+
}
78+
}
79+
```
80+
81+
## 🙅‍♀️ Excluding Fields
82+
83+
Use `@omit manyToMany` [smart comments](https://www.graphile.org/postgraphile/smart-comments/) on constraints or tables to prevent fields from being generated.
84+
85+
```sql
86+
-- omit a relation by constraint
87+
comment on constraint qux_bar_id_fkey on p.qux is E'@omit manyToMany';
88+
89+
-- or omit the junction table entirely
90+
comment on table p.corge is E'@omit manyToMany';
91+
```
92+
93+
## 📝 Field Naming
94+
95+
Field names are verbose by default (e.g. `teamsByTeamMemberTeamId`) to avoid collisions. You can override them with an inflector plugin or smart comments.
96+
97+
### Custom inflector
98+
99+
> Warning: Short names can collide when a junction table references the same target multiple times—customize accordingly.
100+
101+
```js
102+
const { makeAddInflectorsPlugin } = require("graphile-utils");
103+
104+
module.exports = makeAddInflectorsPlugin(
105+
{
106+
manyToManyRelationByKeys(
107+
_leftKeyAttributes,
108+
_junctionLeftKeyAttributes,
109+
_junctionRightKeyAttributes,
110+
_rightKeyAttributes,
111+
_junctionTable,
112+
rightTable,
113+
_junctionLeftConstraint,
114+
junctionRightConstraint
115+
) {
116+
if (junctionRightConstraint.tags.manyToManyFieldName) {
117+
return junctionRightConstraint.tags.manyToManyFieldName;
118+
}
119+
return this.camelCase(
120+
`${this.pluralize(this._singularizedTableName(rightTable))}`
121+
);
122+
},
123+
manyToManyRelationByKeysSimple(
124+
_leftKeyAttributes,
125+
_junctionLeftKeyAttributes,
126+
_junctionRightKeyAttributes,
127+
_rightKeyAttributes,
128+
_junctionTable,
129+
rightTable,
130+
_junctionLeftConstraint,
131+
junctionRightConstraint
132+
) {
133+
if (junctionRightConstraint.tags.manyToManySimpleFieldName) {
134+
return junctionRightConstraint.tags.manyToManySimpleFieldName;
135+
}
136+
return this.camelCase(
137+
`${this.pluralize(this._singularizedTableName(rightTable))}-list`
138+
);
139+
},
140+
},
141+
true // Passing true here allows the plugin to overwrite existing inflectors.
142+
);
143+
```
144+
145+
### Smart comments
146+
147+
```sql
148+
-- rename the Connection field
149+
comment on constraint membership_team_id_fkey on p.membership is E'@manyToManyFieldName teams';
150+
151+
-- rename both Connection and simple collection fields (when simple collections are enabled)
152+
comment on constraint membership_team_id_fkey on p.membership is E'@manyToManyFieldName teams\n@manyToManySimpleFieldName teamsList';
153+
```
154+
155+
## 🧪 Testing
156+
157+
```sh
158+
# requires a local Postgres available (defaults to postgres/password@localhost:5432)
159+
pnpm --filter graphile-many-to-many test
160+
```

0 commit comments

Comments
 (0)