mirror of
https://github.com/usetrmnl/byos_laravel.git
synced 2026-01-14 15:37:53 +00:00
Compare commits
3 commits
e812f56c11
...
91e222f7a6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
91e222f7a6 | ||
|
|
203584107f | ||
|
|
56548a96cb |
13 changed files with 240 additions and 291 deletions
|
|
@ -11,7 +11,7 @@ The Laravel Boost guidelines are specifically curated by Laravel maintainers for
|
||||||
## Foundational Context
|
## Foundational Context
|
||||||
This application is a Laravel application and its main Laravel ecosystems package & versions are below. You are an expert with them all. Ensure you abide by these specific packages & versions.
|
This application is a Laravel application and its main Laravel ecosystems package & versions are below. You are an expert with them all. Ensure you abide by these specific packages & versions.
|
||||||
|
|
||||||
- php - 8.4.12
|
- php - 8.4.13
|
||||||
- laravel/framework (LARAVEL) - v12
|
- laravel/framework (LARAVEL) - v12
|
||||||
- laravel/prompts (PROMPTS) - v0
|
- laravel/prompts (PROMPTS) - v0
|
||||||
- laravel/sanctum (SANCTUM) - v4
|
- laravel/sanctum (SANCTUM) - v4
|
||||||
|
|
@ -25,6 +25,7 @@ This application is a Laravel application and its main Laravel ecosystems packag
|
||||||
- laravel/sail (SAIL) - v1
|
- laravel/sail (SAIL) - v1
|
||||||
- pestphp/pest (PEST) - v4
|
- pestphp/pest (PEST) - v4
|
||||||
- phpunit/phpunit (PHPUNIT) - v12
|
- phpunit/phpunit (PHPUNIT) - v12
|
||||||
|
- rector/rector (RECTOR) - v2
|
||||||
- tailwindcss (TAILWINDCSS) - v4
|
- tailwindcss (TAILWINDCSS) - v4
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
3
.github/copilot-instructions.md
vendored
3
.github/copilot-instructions.md
vendored
|
|
@ -8,7 +8,7 @@ The Laravel Boost guidelines are specifically curated by Laravel maintainers for
|
||||||
## Foundational Context
|
## Foundational Context
|
||||||
This application is a Laravel application and its main Laravel ecosystems package & versions are below. You are an expert with them all. Ensure you abide by these specific packages & versions.
|
This application is a Laravel application and its main Laravel ecosystems package & versions are below. You are an expert with them all. Ensure you abide by these specific packages & versions.
|
||||||
|
|
||||||
- php - 8.4.12
|
- php - 8.4.13
|
||||||
- laravel/framework (LARAVEL) - v12
|
- laravel/framework (LARAVEL) - v12
|
||||||
- laravel/prompts (PROMPTS) - v0
|
- laravel/prompts (PROMPTS) - v0
|
||||||
- laravel/sanctum (SANCTUM) - v4
|
- laravel/sanctum (SANCTUM) - v4
|
||||||
|
|
@ -22,6 +22,7 @@ This application is a Laravel application and its main Laravel ecosystems packag
|
||||||
- laravel/sail (SAIL) - v1
|
- laravel/sail (SAIL) - v1
|
||||||
- pestphp/pest (PEST) - v4
|
- pestphp/pest (PEST) - v4
|
||||||
- phpunit/phpunit (PHPUNIT) - v12
|
- phpunit/phpunit (PHPUNIT) - v12
|
||||||
|
- rector/rector (RECTOR) - v2
|
||||||
- tailwindcss (TAILWINDCSS) - v4
|
- tailwindcss (TAILWINDCSS) - v4
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ The Laravel Boost guidelines are specifically curated by Laravel maintainers for
|
||||||
## Foundational Context
|
## Foundational Context
|
||||||
This application is a Laravel application and its main Laravel ecosystems package & versions are below. You are an expert with them all. Ensure you abide by these specific packages & versions.
|
This application is a Laravel application and its main Laravel ecosystems package & versions are below. You are an expert with them all. Ensure you abide by these specific packages & versions.
|
||||||
|
|
||||||
- php - 8.4.12
|
- php - 8.4.13
|
||||||
- laravel/framework (LARAVEL) - v12
|
- laravel/framework (LARAVEL) - v12
|
||||||
- laravel/prompts (PROMPTS) - v0
|
- laravel/prompts (PROMPTS) - v0
|
||||||
- laravel/sanctum (SANCTUM) - v4
|
- laravel/sanctum (SANCTUM) - v4
|
||||||
|
|
@ -22,6 +22,7 @@ This application is a Laravel application and its main Laravel ecosystems packag
|
||||||
- laravel/sail (SAIL) - v1
|
- laravel/sail (SAIL) - v1
|
||||||
- pestphp/pest (PEST) - v4
|
- pestphp/pest (PEST) - v4
|
||||||
- phpunit/phpunit (PHPUNIT) - v12
|
- phpunit/phpunit (PHPUNIT) - v12
|
||||||
|
- rector/rector (RECTOR) - v2
|
||||||
- tailwindcss (TAILWINDCSS) - v4
|
- tailwindcss (TAILWINDCSS) - v4
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ The Laravel Boost guidelines are specifically curated by Laravel maintainers for
|
||||||
## Foundational Context
|
## Foundational Context
|
||||||
This application is a Laravel application and its main Laravel ecosystems package & versions are below. You are an expert with them all. Ensure you abide by these specific packages & versions.
|
This application is a Laravel application and its main Laravel ecosystems package & versions are below. You are an expert with them all. Ensure you abide by these specific packages & versions.
|
||||||
|
|
||||||
- php - 8.4.12
|
- php - 8.4.13
|
||||||
- laravel/framework (LARAVEL) - v12
|
- laravel/framework (LARAVEL) - v12
|
||||||
- laravel/prompts (PROMPTS) - v0
|
- laravel/prompts (PROMPTS) - v0
|
||||||
- laravel/sanctum (SANCTUM) - v4
|
- laravel/sanctum (SANCTUM) - v4
|
||||||
|
|
@ -22,6 +22,7 @@ This application is a Laravel application and its main Laravel ecosystems packag
|
||||||
- laravel/sail (SAIL) - v1
|
- laravel/sail (SAIL) - v1
|
||||||
- pestphp/pest (PEST) - v4
|
- pestphp/pest (PEST) - v4
|
||||||
- phpunit/phpunit (PHPUNIT) - v12
|
- phpunit/phpunit (PHPUNIT) - v12
|
||||||
|
- rector/rector (RECTOR) - v2
|
||||||
- tailwindcss (TAILWINDCSS) - v4
|
- tailwindcss (TAILWINDCSS) - v4
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ It allows you to manage TRMNL devices, generate screens using native plugins, re
|
||||||
* 📡 Device Information – Display battery status, WiFi strength, firmware version, and more.
|
* 📡 Device Information – Display battery status, WiFi strength, firmware version, and more.
|
||||||
* 🔍 Auto-Join – Automatically detects and adds devices from your local network.
|
* 🔍 Auto-Join – Automatically detects and adds devices from your local network.
|
||||||
* 🖥️ Screen Generation – Supports Plugins (including Mashups), Recipes, API, Markup, or updates via Code.
|
* 🖥️ Screen Generation – Supports Plugins (including Mashups), Recipes, API, Markup, or updates via Code.
|
||||||
|
* Support for TRMNL [Design Framework](https://usetrmnl.com/framework)
|
||||||
* Over 45 compatible open-source recipes are available in the [community catalog](https://bnussbau.github.io/trmnl-recipe-catalog/)
|
* Over 45 compatible open-source recipes are available in the [community catalog](https://bnussbau.github.io/trmnl-recipe-catalog/)
|
||||||
* Supported Devices
|
* Supported Devices
|
||||||
* TRMNL OG (1-bit & 2-bit)
|
* TRMNL OG (1-bit & 2-bit)
|
||||||
|
|
@ -22,8 +23,12 @@ It allows you to manage TRMNL devices, generate screens using native plugins, re
|
||||||
* Seeed Studio (XIAO 7.5" ePaper Panel)
|
* Seeed Studio (XIAO 7.5" ePaper Panel)
|
||||||
* reTerminal E1001 Monochrome ePaper Display
|
* reTerminal E1001 Monochrome ePaper Display
|
||||||
* Custom ESP32 with TRMNL firmware
|
* Custom ESP32 with TRMNL firmware
|
||||||
* Kindle Devices with [trmnl-kindle](https://github.com/usetrmnl/byos_laravel/pull/27)
|
* E-Reader Devices
|
||||||
|
* Kindle ([trmnl-kindle](https://github.com/usetrmnl/byos_laravel/pull/27))
|
||||||
|
* Nook ([trmnl-nook](https://github.com/usetrmnl/trmnl-nook))
|
||||||
|
* Kobo ([trmnl-kobo](https://github.com/usetrmnl/trmnl-kobo))
|
||||||
* Android Devices with [trmnl-android](https://github.com/usetrmnl/trmnl-android)
|
* Android Devices with [trmnl-android](https://github.com/usetrmnl/trmnl-android)
|
||||||
|
* Raspberry Pi (HDMI output) [trmnl-display](https://github.com/usetrmnl/trmnl-display)
|
||||||
* 🔄 TRMNL API Proxy – Can act as a proxy for the native cloud service (requires TRMNL Developer Edition).
|
* 🔄 TRMNL API Proxy – Can act as a proxy for the native cloud service (requires TRMNL Developer Edition).
|
||||||
* This enables a hybrid setup – for example, you can update your custom Train Monitor every 5 minutes in the morning, while displaying native TRMNL plugins throughout the day.
|
* This enables a hybrid setup – for example, you can update your custom Train Monitor every 5 minutes in the morning, while displaying native TRMNL plugins throughout the day.
|
||||||
* 🌙 Dark Mode – Switch between light and dark mode.
|
* 🌙 Dark Mode – Switch between light and dark mode.
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ class ExpressionUtils
|
||||||
*/
|
*/
|
||||||
public static function isAssociativeArray(array $array): bool
|
public static function isAssociativeArray(array $array): bool
|
||||||
{
|
{
|
||||||
if (empty($array)) {
|
if ($array === []) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -81,8 +81,10 @@ class ExpressionUtils
|
||||||
self::evaluateCondition($condition['right'], $variable, $object);
|
self::evaluateCondition($condition['right'], $variable, $object);
|
||||||
|
|
||||||
case 'or':
|
case 'or':
|
||||||
return self::evaluateCondition($condition['left'], $variable, $object) ||
|
if (self::evaluateCondition($condition['left'], $variable, $object)) {
|
||||||
self::evaluateCondition($condition['right'], $variable, $object);
|
return true;
|
||||||
|
}
|
||||||
|
return self::evaluateCondition($condition['right'], $variable, $object);
|
||||||
|
|
||||||
case 'comparison':
|
case 'comparison':
|
||||||
$leftValue = self::resolveValue($condition['left'], $variable, $object);
|
$leftValue = self::resolveValue($condition['left'], $variable, $object);
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ class BatteryLow extends Notification
|
||||||
return (new MailMessage)->markdown('mail.battery-low', ['device' => $this->device]);
|
return (new MailMessage)->markdown('mail.battery-low', ['device' => $this->device]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function toWebhook(object $notifiable)
|
public function toWebhook(object $notifiable): \App\Notifications\Messages\WebhookMessage
|
||||||
{
|
{
|
||||||
return WebhookMessage::create()
|
return WebhookMessage::create()
|
||||||
->data([
|
->data([
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ class PluginExportService
|
||||||
// Generate shared.liquid if needed (for liquid templates)
|
// Generate shared.liquid if needed (for liquid templates)
|
||||||
if ($plugin->markup_language === 'liquid') {
|
if ($plugin->markup_language === 'liquid') {
|
||||||
$sharedTemplate = $this->generateSharedTemplate();
|
$sharedTemplate = $this->generateSharedTemplate();
|
||||||
|
/** @phpstan-ignore-next-line */
|
||||||
if ($sharedTemplate) {
|
if ($sharedTemplate) {
|
||||||
File::put($tempDir.'/shared.liquid', $sharedTemplate);
|
File::put($tempDir.'/shared.liquid', $sharedTemplate);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
15
boost.json
Normal file
15
boost.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"agents": [
|
||||||
|
"claude_code",
|
||||||
|
"copilot",
|
||||||
|
"cursor",
|
||||||
|
"phpstorm"
|
||||||
|
],
|
||||||
|
"editors": [
|
||||||
|
"claude_code",
|
||||||
|
"cursor",
|
||||||
|
"phpstorm",
|
||||||
|
"vscode"
|
||||||
|
],
|
||||||
|
"guidelines": []
|
||||||
|
}
|
||||||
450
composer.lock
generated
450
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -18,7 +18,7 @@ beforeEach(function (): void {
|
||||||
Storage::disk('public')->put('/images/sleep.bmp', 'fake-bmp-content');
|
Storage::disk('public')->put('/images/sleep.bmp', 'fake-bmp-content');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('command transforms default images for all device models', function () {
|
test('command transforms default images for all device models', function (): void {
|
||||||
// Ensure we have device models
|
// Ensure we have device models
|
||||||
$deviceModels = DeviceModel::all();
|
$deviceModels = DeviceModel::all();
|
||||||
expect($deviceModels)->not->toBeEmpty();
|
expect($deviceModels)->not->toBeEmpty();
|
||||||
|
|
@ -43,7 +43,7 @@ test('command transforms default images for all device models', function () {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('getDeviceSpecificDefaultImage returns correct path for device with model', function () {
|
test('getDeviceSpecificDefaultImage returns correct path for device with model', function (): void {
|
||||||
$deviceModel = DeviceModel::first();
|
$deviceModel = DeviceModel::first();
|
||||||
expect($deviceModel)->not->toBeNull();
|
expect($deviceModel)->not->toBeNull();
|
||||||
|
|
||||||
|
|
@ -66,7 +66,7 @@ test('getDeviceSpecificDefaultImage returns correct path for device with model',
|
||||||
expect($sleepImage)->toBe($sleepPath);
|
expect($sleepImage)->toBe($sleepPath);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('getDeviceSpecificDefaultImage falls back to original images for device without model', function () {
|
test('getDeviceSpecificDefaultImage falls back to original images for device without model', function (): void {
|
||||||
$device = new Device();
|
$device = new Device();
|
||||||
$device->deviceModel = null;
|
$device->deviceModel = null;
|
||||||
|
|
||||||
|
|
@ -77,7 +77,7 @@ test('getDeviceSpecificDefaultImage falls back to original images for device wit
|
||||||
expect($sleepImage)->toBe('images/sleep.bmp');
|
expect($sleepImage)->toBe('images/sleep.bmp');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('generateDefaultScreenImage creates images from Blade templates', function () {
|
test('generateDefaultScreenImage creates images from Blade templates', function (): void {
|
||||||
$device = Device::factory()->create();
|
$device = Device::factory()->create();
|
||||||
|
|
||||||
$setupUuid = ImageGenerationService::generateDefaultScreenImage($device, 'setup-logo');
|
$setupUuid = ImageGenerationService::generateDefaultScreenImage($device, 'setup-logo');
|
||||||
|
|
@ -97,14 +97,14 @@ test('generateDefaultScreenImage creates images from Blade templates', function
|
||||||
expect(Storage::disk('public')->exists($sleepPath))->toBeTrue();
|
expect(Storage::disk('public')->exists($sleepPath))->toBeTrue();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('generateDefaultScreenImage throws exception for invalid image type', function () {
|
test('generateDefaultScreenImage throws exception for invalid image type', function (): void {
|
||||||
$device = Device::factory()->create();
|
$device = Device::factory()->create();
|
||||||
|
|
||||||
expect(fn () => ImageGenerationService::generateDefaultScreenImage($device, 'invalid-type'))
|
expect(fn (): string => ImageGenerationService::generateDefaultScreenImage($device, 'invalid-type'))
|
||||||
->toThrow(InvalidArgumentException::class);
|
->toThrow(InvalidArgumentException::class);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('getDeviceSpecificDefaultImage returns null for invalid image type', function () {
|
test('getDeviceSpecificDefaultImage returns null for invalid image type', function (): void {
|
||||||
$device = new Device();
|
$device = new Device();
|
||||||
$device->deviceModel = DeviceModel::first();
|
$device->deviceModel = DeviceModel::first();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -146,7 +146,7 @@ LIQUID
|
||||||
|
|
||||||
// Instead of checking for absence of 1 and 2, let's verify the count
|
// Instead of checking for absence of 1 and 2, let's verify the count
|
||||||
// The filtered result should only contain 3, 4, 5
|
// The filtered result should only contain 3, 4, 5
|
||||||
$filteredContent = strip_tags($result);
|
$filteredContent = strip_tags((string) $result);
|
||||||
$this->assertStringNotContainsString('1', $filteredContent);
|
$this->assertStringNotContainsString('1', $filteredContent);
|
||||||
$this->assertStringNotContainsString('2', $filteredContent);
|
$this->assertStringNotContainsString('2', $filteredContent);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ beforeEach(function (): void {
|
||||||
Storage::disk('public')->put('/images/sleep.bmp', 'fake-bmp-content');
|
Storage::disk('public')->put('/images/sleep.bmp', 'fake-bmp-content');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('command transforms default images for all device models', function () {
|
test('command transforms default images for all device models', function (): void {
|
||||||
// Ensure we have device models
|
// Ensure we have device models
|
||||||
$deviceModels = DeviceModel::all();
|
$deviceModels = DeviceModel::all();
|
||||||
expect($deviceModels)->not->toBeEmpty();
|
expect($deviceModels)->not->toBeEmpty();
|
||||||
|
|
@ -42,7 +42,7 @@ test('command transforms default images for all device models', function () {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('getDeviceSpecificDefaultImage falls back to original images for device without model', function () {
|
test('getDeviceSpecificDefaultImage falls back to original images for device without model', function (): void {
|
||||||
$device = new Device();
|
$device = new Device();
|
||||||
$device->deviceModel = null;
|
$device->deviceModel = null;
|
||||||
|
|
||||||
|
|
@ -53,7 +53,7 @@ test('getDeviceSpecificDefaultImage falls back to original images for device wit
|
||||||
expect($sleepImage)->toBe('images/sleep.bmp');
|
expect($sleepImage)->toBe('images/sleep.bmp');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('generateDefaultScreenImage creates images from Blade templates', function () {
|
test('generateDefaultScreenImage creates images from Blade templates', function (): void {
|
||||||
$device = Device::factory()->create();
|
$device = Device::factory()->create();
|
||||||
|
|
||||||
$setupUuid = ImageGenerationService::generateDefaultScreenImage($device, 'setup-logo');
|
$setupUuid = ImageGenerationService::generateDefaultScreenImage($device, 'setup-logo');
|
||||||
|
|
@ -71,14 +71,14 @@ test('generateDefaultScreenImage creates images from Blade templates', function
|
||||||
expect(Storage::disk('public')->exists($sleepPath))->toBeTrue();
|
expect(Storage::disk('public')->exists($sleepPath))->toBeTrue();
|
||||||
})->skipOnCI();
|
})->skipOnCI();
|
||||||
|
|
||||||
test('generateDefaultScreenImage throws exception for invalid image type', function () {
|
test('generateDefaultScreenImage throws exception for invalid image type', function (): void {
|
||||||
$device = Device::factory()->create();
|
$device = Device::factory()->create();
|
||||||
|
|
||||||
expect(fn () => ImageGenerationService::generateDefaultScreenImage($device, 'invalid-type'))
|
expect(fn (): string => ImageGenerationService::generateDefaultScreenImage($device, 'invalid-type'))
|
||||||
->toThrow(InvalidArgumentException::class);
|
->toThrow(InvalidArgumentException::class);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('getDeviceSpecificDefaultImage returns null for invalid image type', function () {
|
test('getDeviceSpecificDefaultImage returns null for invalid image type', function (): void {
|
||||||
$device = new Device();
|
$device = new Device();
|
||||||
$device->deviceModel = DeviceModel::first();
|
$device->deviceModel = DeviceModel::first();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue