Skip to content

Commit 60b01bf

Browse files
committed
Merge branch 'gs-11-api-scaffolding' of github.com:glenstack/.glenstack into gs-11-api-scaffolding
2 parents 8ca19cc + 678a6b8 commit 60b01bf

File tree

5 files changed

+283
-89
lines changed

5 files changed

+283
-89
lines changed

packages/api/src/data/definitions.ts

Lines changed: 143 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,61 @@
11
/* eslint-disable @typescript-eslint/ban-ts-comment */
22
/* eslint-disable @typescript-eslint/no-explicit-any */
33
import { Expr, query as q } from "faunadb";
4-
import { Table, FaunaSchema } from "./types";
4+
import { Table, FaunaSchema, RelationshipField } from "./types";
5+
6+
const generateRelationQueries = (field: RelationshipField) => {
7+
const existingRelation = (id: string) =>
8+
q.Match(q.Index("relationsUnique"), [
9+
field.relationshipRef,
10+
field.relationKey === "A"
11+
? q.Var("docRef")
12+
: q.Ref(q.Collection(field.to.id), id),
13+
field.relationKey === "B"
14+
? q.Var("docRef")
15+
: q.Ref(q.Collection(field.to.id), id),
16+
]);
17+
18+
return {
19+
connect: (ids: Array<string>) => {
20+
if (!ids) return [];
21+
return ids.map((id: string) =>
22+
q.If(
23+
q.IsEmpty(existingRelation(id)),
24+
q.Create(q.Collection("relations"), {
25+
data: {
26+
// @ts-ignore
27+
relationshipRef: field.relationshipRef,
28+
// @ts-ignore
29+
[field.relationKey]: q.Var("docRef"),
30+
// @ts-ignore
31+
[field.relationKey === "A" ? "B" : "A"]: q.Ref(
32+
// @ts-ignore
33+
q.Collection(field.to.id),
34+
// @ts-ignore
35+
id
36+
),
37+
},
38+
}),
39+
q.Abort(`Object with id ${field.to.id} is already connected.`)
40+
)
41+
);
42+
},
43+
disconnect: (ids: Array<string>) => {
44+
if (!ids) return [];
45+
return ids.map((id: string) =>
46+
q.If(
47+
q.IsEmpty(existingRelation(id)),
48+
q.Abort(`Object with id ${field.to.id} does not exist.`),
49+
50+
q.Map(
51+
q.Paginate(existingRelation(id)),
52+
q.Lambda("X", q.Delete(q.Var("X")))
53+
)
54+
)
55+
);
56+
},
57+
};
58+
};
559

660
export const definitions = (
761
table: Pick<Table, "apiName" | "id">
@@ -16,7 +70,7 @@ export const definitions = (
1670
} => ({
1771
queries: {
1872
findMany: {
19-
name: (): string => table.apiName + "GetMany",
73+
name: (): string => "query" + table.apiName,
2074
// @ts-ignore
2175
query: (args): Expr => {
2276
const options: { size: number; after?: Expr; before?: Expr } = {
@@ -34,6 +88,13 @@ export const definitions = (
3488
);
3589
},
3690
},
91+
findOne: {
92+
name: (): string => "get" + table.apiName,
93+
// @ts-ignore
94+
query: (args: { id: string }): Expr => {
95+
return q.Get(q.Ref(q.Collection(table.id), args.id));
96+
},
97+
},
3798
createOne: {
3899
name: () => table.apiName + "CreateOne",
39100
// @ts-ignore
@@ -42,52 +103,92 @@ export const definitions = (
42103
args,
43104
faunaSchema: FaunaSchema
44105
) => {
45-
{
46-
const data: Record<string, unknown> = {};
47-
let relationQueries;
48-
// const args = getArgumentValues(field, node);
49-
for (const [key, value] of Object.entries(args.input)) {
50-
const faunaField = faunaSchema[table.apiName].fields[key];
51-
if (faunaField.type === "Relation") {
52-
relationQueries = q.Do(
53-
// @ts-ignore
54-
value.connect.map((idToConnect: string) =>
55-
q.Create(q.Collection("relations"), {
56-
data: {
57-
// @ts-ignore
58-
relationshipRef: faunaField.relationshipRef,
59-
// @ts-ignore
60-
[faunaField.relationKey]: q.Var("docRef"),
61-
// @ts-ignore
62-
[faunaField.relationKey === "A" ? "B" : "A"]: q.Ref(
63-
// @ts-ignore
64-
q.Collection(faunaField.to.id),
65-
// @ts-ignore
66-
idToConnect
67-
),
68-
},
69-
})
70-
)
71-
);
72-
} else {
73-
data[faunaField.id] = value;
106+
const data: Record<string, unknown> = {};
107+
let relationQueries: Array<Expr> = [];
108+
// const args = getArgumentValues(field, node);
109+
for (const [key, value] of Object.entries(args.input)) {
110+
const faunaField = faunaSchema[table.apiName].fields[key];
111+
if (faunaField.type === "Relation") {
112+
relationQueries = [
113+
...relationQueries,
114+
// @ts-ignore
115+
...generateRelationQueries(faunaField).connect(value.connect),
116+
];
117+
} else {
118+
data[faunaField.id] = value;
119+
}
120+
}
121+
return q.Select(
122+
["doc"],
123+
q.Let(
124+
{
125+
docRef: q.Select(
126+
["ref"],
127+
q.Create(q.Collection(faunaSchema[table.apiName].id), {
128+
data,
129+
})
130+
),
131+
},
132+
{
133+
doc: q.Get(q.Var("docRef")),
134+
relationQueries: q.Do(relationQueries),
74135
}
136+
)
137+
);
138+
},
139+
},
140+
updateOne: {
141+
name: () => table.apiName + "UpdateOne",
142+
// @ts-ignore
143+
query: (
144+
// @ts-ignore
145+
args: GiraphQLFieldKindToConfig<table.apiName, "args">,
146+
faunaSchema: FaunaSchema
147+
) => {
148+
const data: Record<string, unknown> = {};
149+
let relationQueries: Array<Expr> = [];
150+
// const args = getArgumentValues(field, node);
151+
for (const [key, value] of Object.entries(args.input)) {
152+
const faunaField = faunaSchema[table.apiName].fields[key];
153+
if (faunaField.type === "Relation") {
154+
relationQueries = [
155+
...relationQueries,
156+
// @ts-ignore
157+
...generateRelationQueries(faunaField).connect(value.connect),
158+
...generateRelationQueries(faunaField).disconnect(
159+
// @ts-ignore
160+
value.disconnect
161+
),
162+
];
163+
} else {
164+
data[faunaField.id] = value;
75165
}
76-
return q.Select(
77-
["doc"],
78-
q.Let(
79-
{
80-
docRef: q.Select(
166+
}
167+
return q.Select(
168+
["doc"],
169+
q.Let(
170+
{
171+
toUpdateRef: q.Ref(
172+
q.Collection(faunaSchema[table.apiName].id),
173+
args.id
174+
),
175+
docRef: q.If(
176+
q.Exists(q.Var("toUpdateRef")),
177+
q.Select(
81178
["ref"],
82-
q.Create(q.Collection(faunaSchema[table.apiName].id), {
179+
q.Update(q.Var("toUpdateRef"), {
83180
data,
84181
})
85182
),
86-
},
87-
{ doc: q.Get(q.Var("docRef")), relationQueries }
88-
)
89-
);
90-
}
183+
q.Abort("Object does not exist.")
184+
),
185+
},
186+
{
187+
doc: q.Get(q.Var("docRef")),
188+
relationQueries: q.Do(relationQueries),
189+
}
190+
)
191+
);
91192
},
92193
},
93194
},

packages/api/src/data/fauna/scaffold.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,24 @@ export default async (client: Client): Promise<void> => {
9090
],
9191
})
9292
);
93+
94+
await client.query(
95+
q.CreateIndex({
96+
name: "relationsUnique",
97+
unique: true,
98+
serialized: true,
99+
source: q.Collection("relations"),
100+
terms: [
101+
{
102+
field: ["data", "relationshipRef"],
103+
},
104+
{
105+
field: ["data", "A"],
106+
},
107+
{
108+
field: ["data", "B"],
109+
},
110+
],
111+
})
112+
);
93113
};

packages/api/src/data/generateFaunaQuery.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ const generateSelector = (
9292
name,
9393
q.Select(
9494
["data", faunaSchema[parentType.name].fields[name].id],
95-
CURRENT_DOC_VAR
95+
CURRENT_DOC_VAR,
96+
null
9697
),
9798
];
9899
};

0 commit comments

Comments
 (0)