Skip to content

🚀 Add GraphQL default Skeleton API #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions projects/default-graphql/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
trim_trailing_whitespace = false

[*.{yml,yaml,json}]
indent_size = 2

[docker-compose.yml]
indent_size = 4
58 changes: 58 additions & 0 deletions projects/default-graphql/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
APP_NAME="Laravel API Skeleton"
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost

LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=api
DB_USERNAME=root
DB_PASSWORD=

BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DISK=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120

MEMCACHED_HOST=127.0.0.1

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_MAILER=smtp
MAIL_HOST=mailpit
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS="[email protected]"
MAIL_FROM_NAME="${APP_NAME}"

AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false

PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_HOST=
PUSHER_PORT=443
PUSHER_SCHEME=https
PUSHER_APP_CLUSTER=mt1

VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
VITE_PUSHER_HOST="${PUSHER_HOST}"
VITE_PUSHER_PORT="${PUSHER_PORT}"
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
16 changes: 16 additions & 0 deletions projects/default-graphql/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/.phpunit.cache
/public/storage
/storage/*.key
/vendor
/node_modules
.env
.env.backup
.env.production
.phpunit.result.cache
Homestead.json
Homestead.yaml
npm-debug.log
yarn-error.log
/.fleet
/.idea
/.vscode
11 changes: 11 additions & 0 deletions projects/default-graphql/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<img src="/art/graphql.png" alt="Laravel API Skeleton" align="center">

# Laravel API Skeleton - Example
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
to start building your API with GraphQL.

## Installation

```bash
composer require laravelcm/api-skeleton-default-graphql
```
166 changes: 166 additions & 0 deletions projects/default-graphql/_lighthouse_ide_helper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
<?php
# File generated by "php artisan lighthouse:ide-helper".
# Do not edit this file directly.
# This file should be ignored by git as it can be autogenerated.

declare(strict_types=1);

namespace Illuminate\Testing;

use Mockery\MockInterface;
use Nuwave\Lighthouse\Subscriptions\Contracts\Broadcaster;
use PHPUnit\Framework\TestCase;

class TestResponse
{
/**
* Assert the response contains an error with a matching message.
*
* @param \Throwable $error the expected error
*
* @return $this
*/
public function assertGraphQLError(\Throwable $error): self
{
return $this;
}

/**
* Assert the response contains an error with the given message.
*
* @param string $message the expected error message
*
* @return $this
*/
public function assertGraphQLErrorMessage(string $message): self
{
return $this;
}

/**
* Assert the response contains an error with the given debug message.
*
* Requires the config `lighthouse.debug` to include the option \GraphQL\Error\DebugFlag::INCLUDE_DEBUG_MESSAGE.
*
* @param string $message the expected debug message
*
* @return $this
*/
public function assertGraphQLDebugMessage(string $message): self
{
return $this;
}

/**
* Assert the response contains no errors.
*
* @return $this
*/
public function assertGraphQLErrorFree(): self
{
return $this;
}

/**
* Assert the returned result contains exactly the given validation keys.
*
* @param array<string> $keys the validation keys the result should have
*
* @return $this
*/
public function assertGraphQLValidationKeys(array $keys): self
{
return $this;
}

/**
* Assert a given validation error is present in the response.
*
* @param string $key the validation key that should be present
* @param string $message the expected validation message
*
* @return $this
*/
public function assertGraphQLValidationError(string $key, string $message): self
{
return $this;
}

/**
* Assert no validation errors are present in the response.
*
* @return $this
*/
public function assertGraphQLValidationPasses(): self
{
return $this;
}

/**
* Assert current user is authorized to join a subscription.
*
* @param \PHPUnit\Framework\TestCase $testClassInstance usually $this when calling this from a test class
*
* @return $this
*/
public function assertGraphQLSubscriptionAuthorized(TestCase $testClassInstance): self
{
return $this;
}

/**
* Assert current user is NOT authorized to join a subscription.
*
* @param \PHPUnit\Framework\TestCase $testClassInstance usually $this when calling this from a test class
*
* @return $this
*/
public function assertGraphQLSubscriptionNotAuthorized(TestCase $testClassInstance): self
{
return $this;
}

/**
* For cases where you need more control over your broadcast assertions.
*
* @see \Nuwave\Lighthouse\Testing\TestResponseMixin::assertGraphQLBroadcasted
* @see \Nuwave\Lighthouse\Testing\TestResponseMixin::assertGraphQLNotBroadcasted
*
* @return \Mockery\MockInterface&\Nuwave\Lighthouse\Subscriptions\Contracts\Broadcaster
*/
public function graphQLSubscriptionMock() // @phpstan-ignore-line invalid return type?
{
$mock = \Mockery::mock(Broadcaster::class);
assert($mock instanceof Broadcaster && $mock instanceof MockInterface);

return $mock;
}

/** Get the channel name from a subscription query. */
public function graphQLSubscriptionChannelName(): string
{
return '';
}

/**
* Assert the subscription received the given broadcasts.
*
* @param array<int, array<string, mixed>> $data the broadcast pattern that you are expecting
*
* @return $this
*/
public function assertGraphQLBroadcasted(array $data): self
{
return $this;
}

/**
* Assert the subscription received no broadcast.
*
* @return $this
*/
public function assertGraphQLNotBroadcasted(): self
{
return $this;
}
}
Empty file.
13 changes: 13 additions & 0 deletions projects/default-graphql/app/Enum/Error.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace App\Enum;

enum Error: string
{
case AUTH_001 = 'https://docs.api.com/errors/auth_001';
case AUTH_002 = 'https://docs.api.com/errors/auth_002';
case AUTH_003 = 'https://docs.api.com/errors/auth_003';
case AUTH_004 = 'https://docs.api.com/errors/auth_004';
}
Empty file.
20 changes: 20 additions & 0 deletions projects/default-graphql/app/Http/Controllers/HomeController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use JustSteveKing\Launchpad\Http\Responses\MessageResponse;

final class HomeController
{
public function __invoke(Request $request): MessageResponse
{
return new MessageResponse(
data: [
'message' => __('messages.welcome'),
],
);
}
}
Empty file.
48 changes: 48 additions & 0 deletions projects/default-graphql/app/Http/Middleware/CacheHeaders.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

declare(strict_types=1);

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;

final class CacheHeaders
{
public function handle(Request $request, Closure $next): Response
{
/**
* @var \Illuminate\Http\Response $response
*/
$response = $next($request);

if (Auth::check()) {
$response->setCache(
options: [
'private' => true,
'max_age' => 0,
's_maxage' => 0,
'no_store' => true
],
);
} else {
$response->setCache(
options: [
'public' => true,
'max_age' => 60,
's_maxage' => 60,
],
);

foreach ($response->headers->getCookies() as $cookie) {
$response->headers->removeCookie(
name: $cookie->getName(),
);
}
}

return $response;
}
}
12 changes: 12 additions & 0 deletions projects/default-graphql/app/Http/Middleware/EncryptCookies.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace App\Http\Middleware;

use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;

final class EncryptCookies extends Middleware
{
protected $except = [];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace App\Http\Middleware;

use Closure;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

final class EnsureEmailIsVerified
{
public function handle(Request $request, Closure $next, string $redirectToRoute = null): Response
{
if ( ! $request->user() ||
($request->user() instanceof MustVerifyEmail &&
! $request->user()->hasVerifiedEmail())) {
return response()->json(['message' => __('Your email address is not verified.')], 409);
}

return $next($request);
}
}
Loading