Skip to content

Commit abd3871

Browse files
authored
Merge pull request #1 from laravelcm/default-graphql
🚀 Add GraphQL default Skeleton API
2 parents e117901 + 3965118 commit abd3871

File tree

119 files changed

+16521
-0
lines changed

Some content is hidden

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

119 files changed

+16521
-0
lines changed
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
root = true
2+
3+
[*]
4+
charset = utf-8
5+
end_of_line = lf
6+
indent_size = 4
7+
indent_style = space
8+
insert_final_newline = true
9+
trim_trailing_whitespace = true
10+
11+
[*.md]
12+
trim_trailing_whitespace = false
13+
14+
[*.{yml,yaml,json}]
15+
indent_size = 2
16+
17+
[docker-compose.yml]
18+
indent_size = 4

projects/default-graphql/.env.example

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
APP_NAME="Laravel API Skeleton"
2+
APP_ENV=local
3+
APP_KEY=
4+
APP_DEBUG=true
5+
APP_URL=http://localhost
6+
7+
LOG_CHANNEL=stack
8+
LOG_DEPRECATIONS_CHANNEL=null
9+
LOG_LEVEL=debug
10+
11+
DB_CONNECTION=mysql
12+
DB_HOST=127.0.0.1
13+
DB_PORT=3306
14+
DB_DATABASE=api
15+
DB_USERNAME=root
16+
DB_PASSWORD=
17+
18+
BROADCAST_DRIVER=log
19+
CACHE_DRIVER=file
20+
FILESYSTEM_DISK=local
21+
QUEUE_CONNECTION=sync
22+
SESSION_DRIVER=file
23+
SESSION_LIFETIME=120
24+
25+
MEMCACHED_HOST=127.0.0.1
26+
27+
REDIS_HOST=127.0.0.1
28+
REDIS_PASSWORD=null
29+
REDIS_PORT=6379
30+
31+
MAIL_MAILER=smtp
32+
MAIL_HOST=mailpit
33+
MAIL_PORT=1025
34+
MAIL_USERNAME=null
35+
MAIL_PASSWORD=null
36+
MAIL_ENCRYPTION=null
37+
MAIL_FROM_ADDRESS="[email protected]"
38+
MAIL_FROM_NAME="${APP_NAME}"
39+
40+
AWS_ACCESS_KEY_ID=
41+
AWS_SECRET_ACCESS_KEY=
42+
AWS_DEFAULT_REGION=us-east-1
43+
AWS_BUCKET=
44+
AWS_USE_PATH_STYLE_ENDPOINT=false
45+
46+
PUSHER_APP_ID=
47+
PUSHER_APP_KEY=
48+
PUSHER_APP_SECRET=
49+
PUSHER_HOST=
50+
PUSHER_PORT=443
51+
PUSHER_SCHEME=https
52+
PUSHER_APP_CLUSTER=mt1
53+
54+
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
55+
VITE_PUSHER_HOST="${PUSHER_HOST}"
56+
VITE_PUSHER_PORT="${PUSHER_PORT}"
57+
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
58+
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

projects/default-graphql/.gitignore

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/.phpunit.cache
2+
/public/storage
3+
/storage/*.key
4+
/vendor
5+
/node_modules
6+
.env
7+
.env.backup
8+
.env.production
9+
.phpunit.result.cache
10+
Homestead.json
11+
Homestead.yaml
12+
npm-debug.log
13+
yarn-error.log
14+
/.fleet
15+
/.idea
16+
/.vscode

projects/default-graphql/README.md

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<img src="/art/graphql.png" alt="Laravel API Skeleton" align="center">
2+
3+
# Laravel API Skeleton - Example
4+
This project is a skeleton for building an API with Laravel and GraphQL. It is the simplest skeleton and contains only the basic files and dependencies
5+
to start building your API with GraphQL.
6+
7+
## Installation
8+
9+
```bash
10+
composer require laravelcm/api-skeleton-default-graphql
11+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
<?php
2+
# File generated by "php artisan lighthouse:ide-helper".
3+
# Do not edit this file directly.
4+
# This file should be ignored by git as it can be autogenerated.
5+
6+
declare(strict_types=1);
7+
8+
namespace Illuminate\Testing;
9+
10+
use Mockery\MockInterface;
11+
use Nuwave\Lighthouse\Subscriptions\Contracts\Broadcaster;
12+
use PHPUnit\Framework\TestCase;
13+
14+
class TestResponse
15+
{
16+
/**
17+
* Assert the response contains an error with a matching message.
18+
*
19+
* @param \Throwable $error the expected error
20+
*
21+
* @return $this
22+
*/
23+
public function assertGraphQLError(\Throwable $error): self
24+
{
25+
return $this;
26+
}
27+
28+
/**
29+
* Assert the response contains an error with the given message.
30+
*
31+
* @param string $message the expected error message
32+
*
33+
* @return $this
34+
*/
35+
public function assertGraphQLErrorMessage(string $message): self
36+
{
37+
return $this;
38+
}
39+
40+
/**
41+
* Assert the response contains an error with the given debug message.
42+
*
43+
* Requires the config `lighthouse.debug` to include the option \GraphQL\Error\DebugFlag::INCLUDE_DEBUG_MESSAGE.
44+
*
45+
* @param string $message the expected debug message
46+
*
47+
* @return $this
48+
*/
49+
public function assertGraphQLDebugMessage(string $message): self
50+
{
51+
return $this;
52+
}
53+
54+
/**
55+
* Assert the response contains no errors.
56+
*
57+
* @return $this
58+
*/
59+
public function assertGraphQLErrorFree(): self
60+
{
61+
return $this;
62+
}
63+
64+
/**
65+
* Assert the returned result contains exactly the given validation keys.
66+
*
67+
* @param array<string> $keys the validation keys the result should have
68+
*
69+
* @return $this
70+
*/
71+
public function assertGraphQLValidationKeys(array $keys): self
72+
{
73+
return $this;
74+
}
75+
76+
/**
77+
* Assert a given validation error is present in the response.
78+
*
79+
* @param string $key the validation key that should be present
80+
* @param string $message the expected validation message
81+
*
82+
* @return $this
83+
*/
84+
public function assertGraphQLValidationError(string $key, string $message): self
85+
{
86+
return $this;
87+
}
88+
89+
/**
90+
* Assert no validation errors are present in the response.
91+
*
92+
* @return $this
93+
*/
94+
public function assertGraphQLValidationPasses(): self
95+
{
96+
return $this;
97+
}
98+
99+
/**
100+
* Assert current user is authorized to join a subscription.
101+
*
102+
* @param \PHPUnit\Framework\TestCase $testClassInstance usually $this when calling this from a test class
103+
*
104+
* @return $this
105+
*/
106+
public function assertGraphQLSubscriptionAuthorized(TestCase $testClassInstance): self
107+
{
108+
return $this;
109+
}
110+
111+
/**
112+
* Assert current user is NOT authorized to join a subscription.
113+
*
114+
* @param \PHPUnit\Framework\TestCase $testClassInstance usually $this when calling this from a test class
115+
*
116+
* @return $this
117+
*/
118+
public function assertGraphQLSubscriptionNotAuthorized(TestCase $testClassInstance): self
119+
{
120+
return $this;
121+
}
122+
123+
/**
124+
* For cases where you need more control over your broadcast assertions.
125+
*
126+
* @see \Nuwave\Lighthouse\Testing\TestResponseMixin::assertGraphQLBroadcasted
127+
* @see \Nuwave\Lighthouse\Testing\TestResponseMixin::assertGraphQLNotBroadcasted
128+
*
129+
* @return \Mockery\MockInterface&\Nuwave\Lighthouse\Subscriptions\Contracts\Broadcaster
130+
*/
131+
public function graphQLSubscriptionMock() // @phpstan-ignore-line invalid return type?
132+
{
133+
$mock = \Mockery::mock(Broadcaster::class);
134+
assert($mock instanceof Broadcaster && $mock instanceof MockInterface);
135+
136+
return $mock;
137+
}
138+
139+
/** Get the channel name from a subscription query. */
140+
public function graphQLSubscriptionChannelName(): string
141+
{
142+
return '';
143+
}
144+
145+
/**
146+
* Assert the subscription received the given broadcasts.
147+
*
148+
* @param array<int, array<string, mixed>> $data the broadcast pattern that you are expecting
149+
*
150+
* @return $this
151+
*/
152+
public function assertGraphQLBroadcasted(array $data): self
153+
{
154+
return $this;
155+
}
156+
157+
/**
158+
* Assert the subscription received no broadcast.
159+
*
160+
* @return $this
161+
*/
162+
public function assertGraphQLNotBroadcasted(): self
163+
{
164+
return $this;
165+
}
166+
}

projects/default-graphql/app/Console/Commands/.gitkeep

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Enum;
6+
7+
enum Error: string
8+
{
9+
case AUTH_001 = 'https://docs.api.com/errors/auth_001';
10+
case AUTH_002 = 'https://docs.api.com/errors/auth_002';
11+
case AUTH_003 = 'https://docs.api.com/errors/auth_003';
12+
case AUTH_004 = 'https://docs.api.com/errors/auth_004';
13+
}

projects/default-graphql/app/Exceptions/.gitkeep

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Http\Controllers;
6+
7+
use Illuminate\Http\Request;
8+
use JustSteveKing\Launchpad\Http\Responses\MessageResponse;
9+
10+
final class HomeController
11+
{
12+
public function __invoke(Request $request): MessageResponse
13+
{
14+
return new MessageResponse(
15+
data: [
16+
'message' => __('messages.welcome'),
17+
],
18+
);
19+
}
20+
}

projects/default-graphql/app/Http/Controllers/V1/.gitkeep

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Http\Middleware;
6+
7+
use Closure;
8+
use Illuminate\Http\Request;
9+
use Illuminate\Support\Facades\Auth;
10+
use Symfony\Component\HttpFoundation\Response;
11+
12+
final class CacheHeaders
13+
{
14+
public function handle(Request $request, Closure $next): Response
15+
{
16+
/**
17+
* @var \Illuminate\Http\Response $response
18+
*/
19+
$response = $next($request);
20+
21+
if (Auth::check()) {
22+
$response->setCache(
23+
options: [
24+
'private' => true,
25+
'max_age' => 0,
26+
's_maxage' => 0,
27+
'no_store' => true
28+
],
29+
);
30+
} else {
31+
$response->setCache(
32+
options: [
33+
'public' => true,
34+
'max_age' => 60,
35+
's_maxage' => 60,
36+
],
37+
);
38+
39+
foreach ($response->headers->getCookies() as $cookie) {
40+
$response->headers->removeCookie(
41+
name: $cookie->getName(),
42+
);
43+
}
44+
}
45+
46+
return $response;
47+
}
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Http\Middleware;
6+
7+
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
8+
9+
final class EncryptCookies extends Middleware
10+
{
11+
protected $except = [];
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Http\Middleware;
6+
7+
use Closure;
8+
use Illuminate\Contracts\Auth\MustVerifyEmail;
9+
use Illuminate\Http\Request;
10+
use Symfony\Component\HttpFoundation\Response;
11+
12+
final class EnsureEmailIsVerified
13+
{
14+
public function handle(Request $request, Closure $next, string $redirectToRoute = null): Response
15+
{
16+
if ( ! $request->user() ||
17+
($request->user() instanceof MustVerifyEmail &&
18+
! $request->user()->hasVerifiedEmail())) {
19+
return response()->json(['message' => __('Your email address is not verified.')], 409);
20+
}
21+
22+
return $next($request);
23+
}
24+
}

0 commit comments

Comments
 (0)