@smartive/graphql-magic 15.1.0 → 15.2.0
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/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# [15.
|
|
1
|
+
# [15.2.0](https://github.com/smartive/graphql-magic/compare/v15.1.1...v15.2.0) (2024-04-03)
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
### Features
|
|
5
5
|
|
|
6
|
-
*
|
|
6
|
+
* Finish tutorial ([c1b0a21](https://github.com/smartive/graphql-magic/commit/c1b0a215ed23773fd287cd5b5898f07f7c401af1))
|
package/docs/docs/tutorial.md
CHANGED
|
@@ -10,59 +10,85 @@ Let's create a blog with `graphql-magic`!
|
|
|
10
10
|
|
|
11
11
|
### Code base
|
|
12
12
|
|
|
13
|
-
First create a next.js website:
|
|
13
|
+
First create a `next.js` website:
|
|
14
14
|
|
|
15
15
|
```
|
|
16
16
|
npx create-next-app@latest magic-blog --ts --app --tailwind --eslint --src
|
|
17
17
|
cd magic-blog
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
Replace `app/globals.css`:
|
|
21
21
|
|
|
22
22
|
```
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
@tailwind base;
|
|
24
|
+
@tailwind components;
|
|
25
|
+
@tailwind utilities;
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
main {
|
|
28
|
+
@apply w-96 mx-auto
|
|
29
|
+
}
|
|
27
30
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
],
|
|
32
|
-
```
|
|
31
|
+
nav {
|
|
32
|
+
@apply flex items-center
|
|
33
|
+
}
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
h1, h2, h3, h4 {
|
|
36
|
+
@apply font-bold
|
|
37
|
+
}
|
|
35
38
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
+
h1 {
|
|
40
|
+
@apply text-4xl mb-4 flex-grow
|
|
41
|
+
}
|
|
39
42
|
|
|
40
|
-
|
|
43
|
+
h2 {
|
|
44
|
+
@apply text-3xl mb-3
|
|
45
|
+
}
|
|
41
46
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
47
|
+
h3 {
|
|
48
|
+
@apply text-2xl mb-2
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
h4 {
|
|
52
|
+
@apply text-xl mb-1
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
a {
|
|
56
|
+
@apply text-blue-500
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
article, form {
|
|
60
|
+
@apply mb-4 p-3 rounded-lg shadow-md border border-gray-100
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
input, textarea {
|
|
64
|
+
@apply border border-gray-300 w-full rounded-md p-1
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
label span {
|
|
68
|
+
@apply font-bold
|
|
53
69
|
}
|
|
54
70
|
```
|
|
55
71
|
|
|
56
72
|
Replace `app/page.tsx`:
|
|
57
73
|
|
|
58
74
|
```
|
|
59
|
-
export default function
|
|
60
|
-
return <
|
|
75
|
+
export default async function Home() {
|
|
76
|
+
return <main>
|
|
77
|
+
<nav>
|
|
61
78
|
<h1>Magic Blog</h1>
|
|
62
|
-
|
|
79
|
+
</nav>
|
|
80
|
+
</main>
|
|
63
81
|
}
|
|
64
82
|
```
|
|
65
83
|
|
|
84
|
+
Start the website:
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
npm run dev
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Install graphql-magic
|
|
91
|
+
|
|
66
92
|
Add this setting to `next.config.mjs`:
|
|
67
93
|
|
|
68
94
|
```
|
|
@@ -79,28 +105,16 @@ Install `@smartive/graphql-magic`:
|
|
|
79
105
|
npm install @smartive/graphql-magic
|
|
80
106
|
```
|
|
81
107
|
|
|
82
|
-
Temporary:
|
|
83
|
-
|
|
84
|
-
```
|
|
85
|
-
npm i @graphql-codegen/typescript-compatibility
|
|
86
|
-
```
|
|
87
|
-
|
|
88
108
|
Run the gqm cli:
|
|
89
109
|
|
|
90
110
|
```
|
|
91
111
|
npx gqm generate
|
|
92
112
|
```
|
|
93
113
|
|
|
94
|
-
Start the website:
|
|
95
|
-
|
|
96
|
-
```
|
|
97
|
-
npm run dev
|
|
98
|
-
```
|
|
99
|
-
|
|
100
114
|
### Database setup
|
|
101
115
|
|
|
102
|
-
|
|
103
|
-
|
|
116
|
+
Let's boot a local database instance.
|
|
117
|
+
Create the following `docker-compose.yml`:
|
|
104
118
|
|
|
105
119
|
```
|
|
106
120
|
version: '3.4'
|
|
@@ -148,10 +162,12 @@ import { getSession } from '@auth0/nextjs-auth0';
|
|
|
148
162
|
export default async function Page() {
|
|
149
163
|
const session = await getSession();
|
|
150
164
|
|
|
151
|
-
return <
|
|
165
|
+
return <main>
|
|
166
|
+
<nav>
|
|
152
167
|
<h1>Welcome to my Blog</h1>
|
|
153
168
|
{session ? <a href="/api/auth/logout">Logout</a> : <a href="/api/auth/login">Login</a>}
|
|
154
|
-
|
|
169
|
+
</nav>
|
|
170
|
+
</main>
|
|
155
171
|
}
|
|
156
172
|
```
|
|
157
173
|
|
|
@@ -241,17 +257,21 @@ npx gqm generate
|
|
|
241
257
|
Now, let's modify `src/app/page.tsx` so that it fetches the user from the database:
|
|
242
258
|
|
|
243
259
|
```
|
|
244
|
-
import { GetMeQuery } from "
|
|
245
|
-
import { GET_ME } from "
|
|
246
|
-
import { executeGraphql } from "
|
|
260
|
+
import { GetMeQuery } from "@/generated/client";
|
|
261
|
+
import { GET_ME } from "@/graphql/client/queries/get-me";
|
|
262
|
+
import { executeGraphql } from "@/graphql/execute";
|
|
247
263
|
|
|
248
|
-
export default async function
|
|
249
|
-
const { data: { me }} = await executeGraphql<GetMeQuery>({ query: GET_ME });
|
|
264
|
+
export default async function Home() {
|
|
265
|
+
const { data: { me } } = await executeGraphql<GetMeQuery>({ query: GET_ME });
|
|
250
266
|
|
|
251
|
-
return
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
267
|
+
return (
|
|
268
|
+
<main>
|
|
269
|
+
<nav>
|
|
270
|
+
<h1>Blog</h1>
|
|
271
|
+
{me ? <span>Hello, {me.username}! <a href="/api/auth/logout"> Logout</a></span> : <a href="/api/auth/login">Login</a>}
|
|
272
|
+
</nav>
|
|
273
|
+
</main>
|
|
274
|
+
);
|
|
255
275
|
}
|
|
256
276
|
```
|
|
257
277
|
|
|
@@ -316,7 +336,7 @@ npx env-cmd knex migrate:up
|
|
|
316
336
|
npx gqm generate
|
|
317
337
|
```
|
|
318
338
|
|
|
319
|
-
new get-posts
|
|
339
|
+
Create a new query `src/graphql/client/queries/get-posts.ts`:
|
|
320
340
|
|
|
321
341
|
```
|
|
322
342
|
import { gql } from '@smartive/graphql-magic';
|
|
@@ -342,12 +362,53 @@ export const GET_POSTS = gql`
|
|
|
342
362
|
`;
|
|
343
363
|
```
|
|
344
364
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
<Posts/>
|
|
348
|
-
```
|
|
365
|
+
Now add all the logic to create and display posts and comments to `src/app/page.tsx`
|
|
366
|
+
|
|
349
367
|
|
|
350
368
|
```
|
|
369
|
+
import { CreateCommentMutationMutation, CreateCommentMutationMutationVariables, CreatePostMutationMutation, CreatePostMutationMutationVariables, GetMeQuery, GetPostsQuery } from "@/generated/client";
|
|
370
|
+
import { CREATE_COMMENT, CREATE_POST } from "@/generated/client/mutations";
|
|
371
|
+
import { GET_ME } from "@/graphql/client/queries/get-me";
|
|
372
|
+
import { GET_POSTS } from "@/graphql/client/queries/get-posts";
|
|
373
|
+
import { executeGraphql } from "@/graphql/execute";
|
|
374
|
+
import { revalidatePath } from "next/cache";
|
|
375
|
+
|
|
376
|
+
export default async function Home() {
|
|
377
|
+
const { data: { me } } = await executeGraphql<GetMeQuery>({ query: GET_ME });
|
|
378
|
+
|
|
379
|
+
return (
|
|
380
|
+
<main>
|
|
381
|
+
<nav>
|
|
382
|
+
<h1>Blog</h1>
|
|
383
|
+
{me ? <span>Hello, {me.username}! <a href="/api/auth/logout"> Logout</a></span> : <a href="/api/auth/login">Login</a>}
|
|
384
|
+
</nav>
|
|
385
|
+
{me && <CreatePost />}
|
|
386
|
+
<Posts me={me} />
|
|
387
|
+
</main>
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
async function Posts({ me }: { me: GetMeQuery['me'] }) {
|
|
392
|
+
const { data: { posts } } = await executeGraphql<GetPostsQuery>({ query: GET_POSTS })
|
|
393
|
+
|
|
394
|
+
return <div>
|
|
395
|
+
{posts.map(post => <div key={post.id}>
|
|
396
|
+
<article>
|
|
397
|
+
<h2>{post.title}</h2>
|
|
398
|
+
<div>by {post.createdBy.username}</div>
|
|
399
|
+
<p>{post.content}</p>
|
|
400
|
+
<h4>Comments</h4>
|
|
401
|
+
{post.comments.map(comment => (<div key={comment.id}>
|
|
402
|
+
<div>{comment.createdBy.username}</div>
|
|
403
|
+
<p>{comment.content}</p> by {comment.createdBy.username}
|
|
404
|
+
</div>)
|
|
405
|
+
)}
|
|
406
|
+
{me && <CreateComment postId={post.id} />}
|
|
407
|
+
</article>
|
|
408
|
+
</div>)}
|
|
409
|
+
</div>
|
|
410
|
+
}
|
|
411
|
+
|
|
351
412
|
async function CreatePost() {
|
|
352
413
|
async function createPost(formData: FormData) {
|
|
353
414
|
'use server'
|
|
@@ -365,44 +426,20 @@ async function CreatePost() {
|
|
|
365
426
|
|
|
366
427
|
return <form action={createPost}>
|
|
367
428
|
<h2>New Post</h2>
|
|
368
|
-
<
|
|
429
|
+
<label>
|
|
369
430
|
<span>Title</span>
|
|
370
431
|
<input name="title" />
|
|
371
|
-
</
|
|
372
|
-
<
|
|
432
|
+
</label>
|
|
433
|
+
<label>
|
|
373
434
|
<span>Content</span>
|
|
374
435
|
<textarea rows={5} name="content" />
|
|
375
|
-
</
|
|
436
|
+
</label>
|
|
376
437
|
<div>
|
|
377
438
|
<button type="submit">Create</button>
|
|
378
439
|
</div>
|
|
379
440
|
</form>
|
|
380
441
|
}
|
|
381
|
-
```
|
|
382
|
-
|
|
383
|
-
```
|
|
384
|
-
async function Posts() {
|
|
385
|
-
const { data: { posts } } = await executeGraphql<GetPostsQuery>({ query: GET_POSTS })
|
|
386
|
-
|
|
387
|
-
return <div>
|
|
388
|
-
{posts.map(post => <div key={post.id}>
|
|
389
|
-
<article>
|
|
390
|
-
<h3>{post.title}</h3>
|
|
391
|
-
<div>{post.createdBy.username}</div>
|
|
392
|
-
<div>{post.content}</div>
|
|
393
|
-
{post.comments.map(comment => (<div key={comment.id}>
|
|
394
|
-
<div>{comment.createdBy.username}</div>
|
|
395
|
-
<p>{comment.content}</p> by {comment.createdBy.username}
|
|
396
|
-
</div>)
|
|
397
|
-
)}
|
|
398
|
-
<CreateComment postId={post.id} />
|
|
399
|
-
</article>
|
|
400
|
-
</div>)}
|
|
401
|
-
</div>
|
|
402
|
-
}
|
|
403
|
-
```
|
|
404
442
|
|
|
405
|
-
```
|
|
406
443
|
function CreateComment({ postId }: { postId: string }) {
|
|
407
444
|
async function createComment(formData: FormData) {
|
|
408
445
|
'use server'
|
|
@@ -429,3 +466,5 @@ function CreateComment({ postId }: { postId: string }) {
|
|
|
429
466
|
</form>
|
|
430
467
|
}
|
|
431
468
|
```
|
|
469
|
+
|
|
470
|
+
Now you should have a working minimal blog example!
|
|
@@ -7,11 +7,8 @@ const config: Config = {
|
|
|
7
7
|
tagline: 'Model-first GraphQL API generator',
|
|
8
8
|
favicon: 'img/favicon.ico',
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
// Set the /<baseUrl>/ pathname under which your site is served
|
|
13
|
-
// For GitHub pages deployment, it is often '/<projectName>/'
|
|
14
|
-
baseUrl: '/',
|
|
10
|
+
url: 'https://smartive.github.io',
|
|
11
|
+
baseUrl: '/graphql-magic/',
|
|
15
12
|
|
|
16
13
|
// GitHub pages deployment config.
|
|
17
14
|
// If you aren't using GitHub pages, you don't need these.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import clsx from 'clsx';
|
|
2
1
|
import Heading from '@theme/Heading';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
3
|
import styles from './styles.module.css';
|
|
4
4
|
|
|
5
5
|
type FeatureItem = {
|
|
@@ -10,38 +10,35 @@ type FeatureItem = {
|
|
|
10
10
|
|
|
11
11
|
const FeatureList: FeatureItem[] = [
|
|
12
12
|
{
|
|
13
|
-
title: '
|
|
13
|
+
title: 'Model-first',
|
|
14
14
|
Svg: require('@site/static/img/undraw_docusaurus_mountain.svg').default,
|
|
15
15
|
description: (
|
|
16
16
|
<>
|
|
17
|
-
|
|
18
|
-
used to get your website up and running quickly.
|
|
17
|
+
Define your model, generate everything else.
|
|
19
18
|
</>
|
|
20
19
|
),
|
|
21
20
|
},
|
|
22
21
|
{
|
|
23
|
-
title: '
|
|
22
|
+
title: 'CLI',
|
|
24
23
|
Svg: require('@site/static/img/undraw_docusaurus_tree.svg').default,
|
|
25
24
|
description: (
|
|
26
25
|
<>
|
|
27
|
-
|
|
28
|
-
ahead and move your docs into the <code>docs</code> directory.
|
|
26
|
+
Generate things with our cli.
|
|
29
27
|
</>
|
|
30
28
|
),
|
|
31
29
|
},
|
|
32
30
|
{
|
|
33
|
-
title: '
|
|
31
|
+
title: 'Brought to you by smartive',
|
|
34
32
|
Svg: require('@site/static/img/undraw_docusaurus_react.svg').default,
|
|
35
33
|
description: (
|
|
36
34
|
<>
|
|
37
|
-
|
|
38
|
-
be extended while reusing the same header and footer.
|
|
35
|
+
We developed this as an internal tool.
|
|
39
36
|
</>
|
|
40
37
|
),
|
|
41
38
|
},
|
|
42
39
|
];
|
|
43
40
|
|
|
44
|
-
function Feature({title, Svg, description}: FeatureItem) {
|
|
41
|
+
function Feature({ title, Svg, description }: FeatureItem) {
|
|
45
42
|
return (
|
|
46
43
|
<div className={clsx('col col--4')}>
|
|
47
44
|
<div className="text--center">
|