Skip to content

Commit c71a882

Browse files
committed
🎉 hello world
0 parents  commit c71a882

34 files changed

+5365
-0
lines changed

.gitattributes

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/.github/ export-ignore
2+
/app/ export-ignore
3+
/tests/ export-ignore
4+
/.gitattributes export-ignore
5+
/.gitignore export-ignore
6+
/Dockerfile export-ignore
7+
/phpunit.xml export-ignore

.github/workflows/js-test.yaml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: JS Tests
2+
3+
on: [push]
4+
5+
jobs:
6+
tests:
7+
runs-on: ubuntu-latest
8+
9+
steps:
10+
- uses: actions/checkout@v4
11+
12+
- name: Setup Bun
13+
uses: oven-sh/setup-bun@v2
14+
with:
15+
bun-version: latest
16+
17+
- name: Install Bun Dependencies
18+
run: bun install
19+
20+
- name: Build
21+
run: bun run build:package
22+
23+
- name: Prettier
24+
run: bun run fmt
25+
26+
- name: ESLint
27+
run: bun run lint
28+
29+
- name: Typescript
30+
run: bun run ts:check
31+
32+
- name: Unit Tests And Coverage
33+
run: bun run test:coverage

.github/workflows/npm-publish.yaml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: Publish to npmjs registry
2+
on:
3+
workflow_dispatch:
4+
release:
5+
types: [published]
6+
jobs:
7+
build:
8+
runs-on: ubuntu-latest
9+
permissions:
10+
contents: read
11+
id-token: write
12+
steps:
13+
- uses: actions/checkout@v4
14+
# Setup .npmrc file to publish to npm
15+
- uses: actions/setup-node@v4
16+
with:
17+
node-version: '24.x'
18+
registry-url: 'https://registry.npmjs.org'
19+
- run: npm ci
20+
- run: npm run build:package
21+
- run: npm publish --provenance --access public
22+
env:
23+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

.github/workflows/php-test.yaml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: PHP Tests
2+
3+
on: [push]
4+
5+
jobs:
6+
build:
7+
runs-on: ubuntu-latest
8+
strategy:
9+
fail-fast: false
10+
matrix:
11+
laravel: [9, 10, 11, 12]
12+
php: [8.2, 8.3, 8.4]
13+
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- name: test against Laravel ${{ matrix.laravel }} on PHP ${{ matrix.php }}
18+
run: docker build . --build-arg PHP_VERSION=${{ matrix.php }} --build-arg LARAVEL=${{ matrix.laravel }}

.gitignore

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
build
2+
dist
3+
node_modules
4+
vendor
5+
composer.lock
6+
coverage
7+
coverage-html
8+
coverage.xml
9+
.phpunit.cache
10+
.phpunit.result.cache
11+
*.tgz

.prettierrc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"semi": true,
3+
"trailingComma": "all",
4+
"singleQuote": true
5+
}

Dockerfile

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
ARG PHP_VERSION=8.2
2+
FROM php:$PHP_VERSION-cli-alpine
3+
4+
RUN apk add git zip unzip autoconf make g++
5+
6+
# apparently newer xdebug needs these now?
7+
RUN apk add --update linux-headers
8+
9+
RUN pecl install xdebug && docker-php-ext-enable xdebug
10+
11+
RUN curl -sS https://getcomposer.org/installer | php \
12+
&& mv composer.phar /usr/local/bin/composer
13+
14+
WORKDIR /package
15+
16+
RUN adduser -D -g '' dev
17+
18+
RUN chown dev -R /package
19+
20+
USER dev
21+
22+
COPY --chown=dev composer.json ./
23+
24+
ARG LARAVEL=9
25+
RUN composer require laravel/framework ^$LARAVEL.0
26+
27+
COPY --chown=dev . .
28+
29+
RUN composer test

README.md

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
[![JS Tests](https://github.com/SynergiTech/laravel-magic-enums/actions/workflows/js-test.yaml/badge.svg?branch=main)](https://github.com/SynergiTech/laravel-magic-enums/actions/workflows/js-test.yaml)
2+
[![PHP Tests](https://github.com/SynergiTech/laravel-magic-enums/actions/workflows/php-test.yaml/badge.svg)](https://github.com/SynergiTech/laravel-magic-enums/actions/workflows/php-test.yaml)
3+
4+
# Laravel Magic Enums
5+
6+
Have you ever wanted to reference your PHP enums in your frontend code but ended up (or didn't want to end up) duplicating them manually? Well here is your answer.
7+
8+
## Installing
9+
10+
You need both sides to get started.
11+
12+
```sh
13+
$ composer require synergitech/laravel-magic-enums
14+
$ npm install --save laravel-magic-enums
15+
```
16+
17+
## Getting Started
18+
19+
1. Add the trait from this package to your enums
20+
21+
```php
22+
<?php
23+
24+
namespace App\Enums;
25+
26+
use SynergiTech\MagicEnums\Traits\WithToVueArray;
27+
28+
enum YourEnum: string
29+
{
30+
use WithToVueArray;
31+
...
32+
```
33+
34+
2. Include the route somewhere in your routes file of choice, in this example we are going to create `/api/enums`.
35+
36+
```php
37+
<?php
38+
39+
use Illuminate\Support\Facades\Route;
40+
use SynergiTech\MagicEnums\Facades\MagicEnumsRouteFacade;
41+
42+
Route::prefix('/api')->group(function () {
43+
MagicEnumsRouteFacade::enumsController();
44+
});
45+
```
46+
47+
You can obviously include middleware on it if you wish, e.g. for an authenticated session, but this may affect your frontend's ability to initialise, so please be careful.
48+
49+
We recommend you don't include sensitive information in your enums.
50+
51+
3. We work primarily with Inertia and Vue so the integration looks something like this. Note the use of `async`/`await` and reusing the route we created earlier.
52+
53+
```js
54+
import { vueEnumPlugin } from "laravel-magic-enums";
55+
import { createApp, h } from "vue";
56+
import { createInertiaApp } from "@inertiajs/vue3";
57+
58+
createInertiaApp({
59+
resolve: (name) => {
60+
const pages = import.meta.glob("./Pages/**/*.vue");
61+
return pages[`./Pages/${name}.vue`]();
62+
},
63+
64+
async setup({ el, App, props, plugin }) {
65+
createApp({ render: () => h(App, props) })
66+
.use(await vueEnumPlugin("/api/enums"))
67+
.mount(el);
68+
},
69+
...
70+
```
71+
72+
4. During development, you can have Vite reload automatically when your enums change. This is handled by `chokidar`. You might also wish to compile a types definition so your IDE knows the details of the enums. We recommend adding this file to your `.gitignore` file.
73+
74+
While not necessary, you can also provide a cli command to `prettierCommand` to format the generated TypeScript file according to your project's standards.
75+
76+
Update your `vite.config.js` as follows. You'll notice we provide both the directory and the endpoint.
77+
78+
```js
79+
import { defineConfig } from 'vite';
80+
import laravel from 'laravel-vite-plugin';
81+
import vue from '@vitejs/plugin-vue';
82+
import { laravelMagicEnums } from "laravel-magic-enums/vite";
83+
84+
export default defineConfig({
85+
plugins: [
86+
laravel({
87+
...
88+
}),
89+
vue({
90+
...
91+
}),
92+
laravelMagicEnums({
93+
enumDir: "./app/Enums",
94+
enumEndpoint: "http://localhost/api/enums",
95+
interfaceOutput: "./resources/js/globals.d.ts",
96+
prettierCommand: "prettier --write",
97+
}),
98+
],
99+
...
100+
```
101+
102+
5. Now in your frontend, you can reference your enums as if they were key-value objects.
103+
104+
```js
105+
import { useEnums } from 'laravel-magic-enums';
106+
107+
const { YourEnum, YourOtherEnum } = useEnums();
108+
```
109+
110+
## Advanced Usage
111+
112+
### Sub Enums
113+
114+
You may choose to have an array within your enum of a subset of the values for a specific purpose or grouping.
115+
116+
If you use the PHP attribute `SynergiTech\MagicEnums\Attributes\AppendConstToMagic`, then an extra enum representing this will be available in the frontend.
117+
118+
You may also have an array which maps some or all of the values of the enum to a different string.
119+
120+
If you use the PHP attribute `SynergiTech\MagicEnums\Attributes\AppendValueToMagic`, then an extra enum representing this will be available in the frontend.
121+
122+
For example:
123+
124+
```php
125+
<?php
126+
127+
namespace App\Enums;
128+
129+
use SynergiTech\MagicEnums\Attributes\AppendConstToMagic;
130+
use SynergiTech\MagicEnums\Attributes\AppendValueToMagic;
131+
use SynergiTech\MagicEnums\Traits\WithToVueArray;
132+
133+
enum TestingEnum: string
134+
{
135+
use WithToVueArray;
136+
137+
case First = 'first';
138+
case Second = 'second';
139+
case Third = 'third';
140+
141+
#[AppendConstToMagic]
142+
public const JUST_ONE = [
143+
self::First,
144+
];
145+
146+
#[AppendValueToMagic]
147+
public const COLOURS = [
148+
self::First->value => 'red',
149+
];
150+
}
151+
```
152+
153+
Will create the output:
154+
155+
```js
156+
TestingEnum: {
157+
First: "first",
158+
Second: "second",
159+
Third: "third"
160+
},
161+
TestingEnumJustOne: {
162+
First: "first"
163+
},
164+
TestingEnumColours: {
165+
First: "red"
166+
}
167+
```
168+
169+
### Cache and Versioning
170+
171+
To avoid rebuilding the json everytime the endpoint is requested, you can add a file named `VERSION` to your root folder. Magic Enums will determine whether to cache the output based on the time this file was last touched. You can specify a custom cache key in the config.

app/Enums/TestingEnum.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
namespace App\Enums;
4+
5+
use SynergiTech\MagicEnums\Attributes\AppendConstToMagic;
6+
use SynergiTech\MagicEnums\Attributes\AppendValueToMagic;
7+
use SynergiTech\MagicEnums\Traits\WithToVueArray;
8+
9+
enum TestingEnum: string
10+
{
11+
use WithToVueArray;
12+
13+
case First = 'first';
14+
case Second = 'second';
15+
case Third = 'third';
16+
case Fourth = 'fourth';
17+
case Fifth = 'fifth';
18+
case Sixth = 'sixth';
19+
case Seventh = 'seventh';
20+
case Eighth = 'eighth';
21+
22+
/**
23+
* this makes a sub-enum of this enum in
24+
* the output with only the listed values
25+
*
26+
* typed consts have been available since 8.2
27+
*/
28+
#[AppendConstToMagic]
29+
public const THREE_QUARTERS = [
30+
self::First,
31+
self::Second,
32+
self::Third,
33+
self::Fourth,
34+
self::Fifth,
35+
self::Sixth,
36+
];
37+
38+
/**
39+
* this appends extra properties
40+
* to each enum value (or null if missing)
41+
*
42+
* typed consts have been available since 8.2
43+
*/
44+
#[AppendValueToMagic]
45+
public const COLOURS = [
46+
self::First->value => 'red',
47+
self::Second->value => 'yellow',
48+
self::Third->value => 'green',
49+
];
50+
}

0 commit comments

Comments
 (0)