Skip to content

Feat/add support boost skill#14

Closed
iqbalhasandev wants to merge 2 commits intomainfrom
feat/add-support-boost-skill
Closed

Feat/add support boost skill#14
iqbalhasandev wants to merge 2 commits intomainfrom
feat/add-support-boost-skill

Conversation

@iqbalhasandev
Copy link
Copy Markdown
Member

This pull request introduces comprehensive documentation and utility code for the Enumify skill, which streamlines syncing PHP enums with TypeScript, enforces strict enum usage patterns, and provides helper methods for both backend and frontend development. The most important changes are grouped below:

Enumify skill documentation and workflow:

  • Added a detailed SKILL.md file for the Enumify skill, outlining strict rules for PHP enum creation, model casting, frontend usage, and anti-patterns to avoid. The documentation also describes the complete workflow for syncing enums and using them across backend and frontend, including artisan commands and configuration options.

Backend utility trait for enums:

  • Introduced the EnumHelpers trait in src/Concerns/EnumHelpers.php, providing static methods for listing enum options, values, names, and checking value existence. These helpers simplify common enum operations and ensure consistency between backend and frontend representations.

@iqbalhasandev iqbalhasandev self-assigned this Mar 10, 2026
Copilot AI review requested due to automatic review settings March 10, 2026 06:00
@iqbalhasandev iqbalhasandev added the enhancement New feature or request label Mar 10, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds two new artifacts to the laravel-enumify package: a SKILL.md documentation file for AI-powered "boost" workflows, and a new EnumHelpers PHP trait providing utility methods for backed enums. Together, these help developers use enums consistently across the PHP backend and TypeScript frontend.

Changes:

  • Introduced src/Concerns/EnumHelpers.php — a new trait with static utility methods (options, selectOptions, values, names, hasValue) for backed enums.
  • Added resources/boost/skills/enumify/SKILL.md — comprehensive AI-skill documentation describing strict rules, workflow steps, configuration, and anti-patterns for Enumify usage.
  • Updated .gitignore to exclude .DS_Store files.

Reviewed changes

Copilot reviewed 2 out of 3 changed files in this pull request and generated 5 comments.

File Description
src/Concerns/EnumHelpers.php New trait providing reusable static helper methods for backed enums
resources/boost/skills/enumify/SKILL.md New AI boost skill documentation covering all aspects of Enumify usage
.gitignore Added .DS_Store to ignored files

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +25 to +46
public static function options(string $label = 'label'): array
{
return collect(self::cases())
->mapWithKeys(fn (self $case): array => [$case->value => $case->{$label}()])
->all();
}

/**
* Get all enum cases as an array of {value, label} objects for frontend selects.
*
* @return array<int, array{value: string|int, label: string}>
*/
public static function selectOptions(string $label = 'label'): array
{
return collect(self::cases())
->map(fn (self $case): array => [
'value' => $case->value,
'label' => $case->{$label}(),
])
->values()
->all();
}
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The options() and selectOptions() methods call a dynamically-named method on each enum case ($case->{$label}()) with no check that the method actually exists on the enum. If an enum uses this trait but does not implement the method named by $label (defaulting to 'label'), or if a caller passes a method name that doesn't exist, PHP will throw a fatal Error ("Call to undefined method"). Consider adding a method_exists($case, $label) guard and throwing a descriptive \BadMethodCallException (or \InvalidArgumentException) with the enum class and missing method name, so callers get an actionable error message instead of a generic PHP fatal.

Copilot uses AI. Check for mistakes.
Comment on lines +178 to +185
16. **When localization is enabled** (`react` or `vue` mode), ALWAYS use the hook function instead of the static Utils:
```typescript
// With localization.mode = 'react'
const { label, color, options } = useOrderStatusUtils();

// With localization.mode = 'vue'
const { label, color, options } = useOrderStatusUtils();
```
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rule 16 in the documentation shows identical code snippets for both react and vue localization modes. The React and Vue hook usage patterns are identical, which is either intentional (and should be noted in the doc) or a copy-paste error where the Vue example should demonstrate a Vue-specific usage pattern (e.g. using ref / computed if the hook returns reactive values, or showing the Composition API style). This makes the section misleading to developers who need to understand the difference between the two modes.

Copilot uses AI. Check for mistakes.
Comment on lines +15 to +75
trait EnumHelpers
{
/**
* Get all enum cases as an array of value => label pairs.
*
* Calls the given method name on each case (defaults to "label").
* Requires the enum to implement a public instance method with that name.
*
* @return array<string|int, string>
*/
public static function options(string $label = 'label'): array
{
return collect(self::cases())
->mapWithKeys(fn (self $case): array => [$case->value => $case->{$label}()])
->all();
}

/**
* Get all enum cases as an array of {value, label} objects for frontend selects.
*
* @return array<int, array{value: string|int, label: string}>
*/
public static function selectOptions(string $label = 'label'): array
{
return collect(self::cases())
->map(fn (self $case): array => [
'value' => $case->value,
'label' => $case->{$label}(),
])
->values()
->all();
}

/**
* Get all enum values as an array.
*
* @return array<int, string|int>
*/
public static function values(): array
{
return array_column(self::cases(), 'value');
}

/**
* Get all enum names as an array.
*
* @return array<int, string>
*/
public static function names(): array
{
return array_column(self::cases(), 'name');
}

/**
* Check if a value exists in this enum.
*/
public static function hasValue(string|int $value): bool
{
return in_array($value, self::values(), true);
}
}
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are no tests for the newly introduced EnumHelpers trait. The project has comprehensive unit test coverage (with a 100% coverage requirement per composer.json's test-coverage script: --min=100). Tests should be added to cover all five methods: options(), selectOptions(), values(), names(), and hasValue(), including edge cases such as calling options() with a non-existent method name.

Copilot uses AI. Check for mistakes.
Comment on lines +33 to +37
* Get all enum cases as an array of {value, label} objects for frontend selects.
*
* @return array<int, array{value: string|int, label: string}>
*/
public static function selectOptions(string $label = 'label'): array
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The @return docblock for selectOptions() declares label: string in the returned array shape, but the $label parameter accepts any method name, and that method may return a non-string type (e.g., int, bool). The docblock should use a more accurate return type like array{value: string|int, label: mixed}, or document that the $label method must return a string for this contract to hold.

Copilot uses AI. Check for mistakes.
Comment on lines +248 to +250
public function isEscalated(): bool
{
return in_array($this, [self::HIGH, self::URGENT]);
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The isEscalated() example in the documentation calls in_array($this, [self::HIGH, self::URGENT]) without the strict (true) third argument. This is inconsistent with the codebase's own hasValue() in the trait (line 73), which correctly uses true for strict comparison, and could mislead developers into using loose comparisons when implementing similar methods.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants