Skip to content

Commit 77a0c52

Browse files
committed
build: reset history for open-source
0 parents  commit 77a0c52

File tree

79 files changed

+24712
-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.

79 files changed

+24712
-0
lines changed

.editorconfig

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# http://editorconfig.org
2+
3+
root = true
4+
5+
[*]
6+
charset = utf-8
7+
end_of_line = lf
8+
insert_final_newline = true
9+
indent_style = space
10+
indent_size = 2
11+
max_line_length = 80
12+
trim_trailing_whitespace = true
13+
14+
[*.md]
15+
insert_final_newline = false
16+
trim_trailing_whitespace = false

.github/actions/install/action.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
name: 'Install'
2+
description: 'Install and pre-build'
3+
4+
runs:
5+
using: composite
6+
steps:
7+
- uses: actions/setup-node@v3
8+
with:
9+
node-version: 18
10+
cache: npm
11+
12+
- name: Install dependencies
13+
shell: bash
14+
run: npm ci

.github/dependabot.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: github-actions
4+
directory: /
5+
schedule:
6+
interval: weekly
7+
time: "08:00"
8+
timezone: "America/New_York"

.github/workflows/ci.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: CI
2+
on: push
3+
4+
jobs:
5+
test_build:
6+
name: Test Build
7+
runs-on: ubuntu-latest
8+
steps:
9+
- uses: actions/checkout@v4
10+
11+
- name: Install
12+
uses: ./.github/actions/install
13+
14+
- name: Assert Types
15+
run: npm run check-types
16+
17+
- name: Assert Types
18+
run: npm run lint
19+
20+
- name: Build website
21+
run: npm run build

.github/workflows/deploy.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: Build and Deploy
2+
on:
3+
push:
4+
branches:
5+
- main
6+
workflow_dispatch:
7+
permissions:
8+
contents: read
9+
pages: write
10+
id-token: write
11+
concurrency:
12+
group: "pages"
13+
cancel-in-progress: false
14+
15+
jobs:
16+
build-and-deploy:
17+
environment:
18+
name: github-pages
19+
url: ${{ steps.deployment.outputs.page_url }}
20+
runs-on: ubuntu-latest
21+
steps:
22+
- uses: actions/checkout@v4
23+
24+
- name: Install
25+
uses: ./.github/actions/install
26+
27+
- name: Build website
28+
run: npm run build
29+
30+
- name: Setup Pages
31+
uses: actions/configure-pages@v5
32+
33+
- name: Upload artifact
34+
uses: actions/upload-pages-artifact@v3
35+
with:
36+
path: build
37+
38+
- name: Deploy to GitHub Pages
39+
id: deployment
40+
uses: actions/deploy-pages@v4

.gitignore

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Dependencies
2+
/node_modules
3+
4+
# Production
5+
/build
6+
7+
# Generated files
8+
.docusaurus
9+
.cache-loader
10+
11+
# Misc
12+
.DS_Store
13+
.env.local
14+
.env.development.local
15+
.env.test.local
16+
.env.production.local
17+
18+
npm-debug.log*
19+
yarn-debug.log*
20+
yarn-error.log*
21+
22+
# IDEs
23+
.idea

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Open Source at Sourcetoad
2+
_Built using [Docusaurus 3](https://docusaurus.io/), a modern static website generator._
3+
4+
## Branch Management
5+
* `main` - Branch off for features. Merges will deploy to `main` environment.
6+
7+
## Environments
8+
* `main` - `https://opensource.sourcetoad.com`
9+
10+
### Local Setup
11+
12+
```
13+
git clone [email protected]:sourcetoad/open-source.git
14+
npm ci
15+
npm run start
16+
```
64.9 KB
Loading
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
---
2+
slug: 2023/rule-helper-for-laravel
3+
title: Rule Helper for Laravel
4+
authors: [connort, erikp]
5+
tags: [php, fluent, laravel, validation, rules]
6+
---
7+
8+
As our applications moved from Laravel 4 into the future versions we noticed an issue that occasionally came up. Laravel validation rules in the early days of Laravel were primarily leveraged using string concatenation with pipe (`|`) characters.
9+
10+
```php
11+
$this->validate($request, [
12+
'title' => 'required|unique:posts|max:255',
13+
'body' => 'required',
14+
]);
15+
```
16+
17+
This added a bit of a mental overhead to know all the variations these rules offered and would require a fair amount of trips to the documentation to remember all the possible validation options. Additionally, if you made a typo on some of the rule names Laravel would just silently skip that rule during validation. If you didn't have great test coverage it was pretty easy to make a mistake with this style of validation writing.
18+
19+
We were in search of a more fluent approach to validation rules and as the release of Laravel 8 arrived we decided to create a package to solve our issue.
20+
21+
{/* truncate */}
22+
23+
We knew that validation re-use and IDE support was key so we set off to reproduce the above example in the most fluent way possible.
24+
25+
```php
26+
$this->validate($request, [
27+
'title' => RuleSet::create()
28+
->required()
29+
->unique('posts')
30+
->max(255),
31+
'body' => RuleSet::create()
32+
->required(),
33+
]);
34+
```
35+
36+
With the fluent class based structure our tooling could enumerate all possibilities enhancing the developer experience and reducing mistakes.
37+
38+
<div class="text--center">
39+
![](./ide-support.png)
40+
</div>
41+
42+
As Laravel 9 and 10 arrived we saw the introduction of more and more fluent validation rules added. This meant it was increasingly possible to write validation rules without any magic strings, but Laravel itself was not 100% covered with fluent rules.
43+
44+
So our package continued to be updated for each major Laravel version (or even minor when a validation rule was changed).
45+
46+
This package is an instant addition on any new project we do to elevate the developer experience and reduce potential for errors.
47+
48+
* [GitHub Repo](https://github.com/sourcetoad/rule-helper-for-laravel)
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
---
2+
slug: 2023/enhanced-resources-for-laravel
3+
title: Enhanced Resources for Laravel
4+
authors: [connort, jasonj]
5+
tags: [php, resources, fractal, responses, laravel]
6+
---
7+
8+
Developing an API was a common task for engineers working with Laravel in the early days of the framework. Prior to version 5.5 Laravel did not offer an elegant way to format/prepare API responses. Historically, it worked by calling `toArray()` on your model instance.
9+
10+
This pattern of calling `toArray()` risked the possibility of exposing attributes that should not be exposed over an API. As a result, it was common to use the `$hidden` property to exclude the specified attributes during serialization which was helpful in building an API response as both a mechanism to avoid exposing sensitive data and more generally controlling which data would be included. The example shown below was a common pattern prior to Laravel 5.5.
11+
12+
```php
13+
<?php
14+
15+
class User extends Eloquent {
16+
protected $hidden = ['password', 'remember_token'];
17+
}
18+
19+
// Usage
20+
$user = User::find(1);
21+
$user->toArray();
22+
// Returns: ['name' => 'John', 'email' => '[email protected]']
23+
```
24+
25+
This approach was flexible, but any change to your database schema resulted in those changes appearing in your API. We needed something more concrete and landed on [Fractal](https://fractal.thephpleague.com) which served us well until Laravel added [official support](https://laravel.com/docs/5.5/releases) for API Resources, and thus we worked on an enhancement for that feature.
26+
27+
{/* truncate */}
28+
29+
A stock installation of Laravel leveraging API resources may have a class similar to the one shown below.
30+
31+
```php
32+
<?php
33+
34+
class UserResource extends JsonResource
35+
{
36+
public function toArray(Request $request): array
37+
{
38+
return [
39+
'id' => $this->id,
40+
'name' => $this->name,
41+
'email' => $this->email,
42+
'created_at' => $this->created_at,
43+
'updated_at' => $this->updated_at,
44+
];
45+
}
46+
}
47+
```
48+
49+
A common complaint we had was that an entity (in this case a User) may have a different responses depending on the permissions of the user making the request. An admin may see more information about a user than a support user, or staff member. Laravel offered conditional attributes we could leverage, but those exploded in complexity pretty quickly when balancing many roles and many conditional attributes.
50+
51+
So we built [Enhanced Resources](https://github.com/sourcetoad/enhanced-resources) to make this is a bit easier.
52+
53+
```php
54+
<?php
55+
56+
use Sourcetoad\EnhancedResources\Formatting\Attributes\Format;
57+
use Sourcetoad\EnhancedResources\Formatting\Attributes\IsDefault;
58+
use Sourcetoad\EnhancedResources\Resource;
59+
60+
class QuestionResource extends Resource
61+
{
62+
#[IsDefault, Format]
63+
public function base(): array
64+
{
65+
return [
66+
'type' => $this->type,
67+
'text' => $this->text,
68+
'answers' => $this->answers,
69+
];
70+
}
71+
72+
#[Format]
73+
public function teacher(): array
74+
{
75+
$data = $this->base();
76+
$data['correct_answer'] = $this->correct_answer;
77+
78+
return $data;
79+
}
80+
}
81+
```
82+
83+
In this example we had a format that was the default (or `base`) for usage of the Question model. This example reflected a question schema which may have a question type, the question itself and any possible answers. We know students shouldn't have the answers, but the teacher should. We can easily assume the properties of the base resource and add on multiple conditional properties.
84+
85+
Over time, we found this package to excel when formatting data differently depending on the permissions/roles of the requesting user. In addition to the structured approach that the Resource file had we also supported a variety of mutations directly on the resource.
86+
87+
* `modify` - Change a key/value.
88+
* `except` - Exclude specific keys.
89+
* `only` - Include specific keys only.
90+
91+
This meant we could quickly apply a change if needed without adapting the resource file. We could also apply an attribute directly to the model to bind it to the corresponding Resource that represented it.
92+
93+
```php
94+
use Illuminate\Database\Eloquent\Model;
95+
use Sourcetoad\EnhancedResources\Resourceable\AsResource;
96+
use Sourcetoad\EnhancedResources\Resourceable\ConvertsToResource;
97+
98+
/**
99+
* @method ExampleResource toResource()
100+
*/
101+
#[AsResource(ExampleResource::class)]
102+
class Example extends Model
103+
{
104+
use ConvertsToResource;
105+
}
106+
107+
(new Example)->toResource();
108+
```
109+
110+
Enhanced Resources has been around since 2019 and is still in use to this day.
111+
112+
* [GitHub Repo](https://github.com/sourcetoad/enhanced-resources)
113+
* [Packagist](https://packagist.org/packages/sourcetoad/enhanced-resources)

0 commit comments

Comments
 (0)