Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Js Dto Bundle Laravel Package

dayploy/js-dto-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation

    composer require dayploy/js-dto-bundle
    

    Add the bundle to your config/bundles.php:

    Dayploy\JsDtoBundle\DayployJsDtoBundle::class => ['all' => true],
    
  2. Basic Setup Run migrations (if any) and clear cache:

    php bin/console doctrine:migrations:diff
    php bin/console doctrine:migrations:migrate
    php bin/console cache:clear
    
  3. First Use Case Define a DTO (Data Transfer Object) in PHP:

    namespace App\Dto;
    
    use Dayploy\JsDtoBundle\Annotation\JsDto;
    
    #[JsDto]
    class UserDto
    {
        public string $name;
        public int $age;
    }
    

    Generate the JavaScript counterpart:

    php bin/console js-dto:generate
    

    The bundle will create a UserDto.js file in public/js/dtos/ with TypeScript types and serialization logic.


Implementation Patterns

Workflows

  1. DTO Definition

    • Use annotations (#[JsDto]) or attributes to mark classes as DTOs.
    • Define properties with PHP types (e.g., string, int, array, DateTime).
    • Example with nested DTOs:
      #[JsDto]
      class AddressDto {
          public string $street;
          public string $city;
      }
      
      #[JsDto]
      class UserDto {
          public string $name;
          public AddressDto $address;
      }
      
  2. Serialization/Deserialization

    • Automatically generate JavaScript functions to convert between PHP objects and JSON:
      // Auto-generated in UserDto.js
      export function serialize(userDto: UserDto): string {
          return JSON.stringify(userDto);
      }
      
      export function deserialize(json: string): UserDto {
          return JSON.parse(json) as UserDto;
      }
      
  3. Integration with Controllers

    • Use the generated JS in your frontend (e.g., Vue/React) to handle API responses:
      import { UserDto, deserialize } from './js/dtos/UserDto';
      
      fetch('/api/users/1')
          .then(response => response.json())
          .then(json => {
              const user: UserDto = deserialize(json);
              console.log(user.name); // Type-safe access
          });
      
  4. API Response Handling

    • In Laravel controllers, return DTOs directly:
      use App\Dto\UserDto;
      
      public function show(User $user)
      {
          $dto = new UserDto();
          $dto->name = $user->name;
          $dto->age = $user->age;
      
          return response()->json($dto);
      }
      
  5. Frontend State Management

    • Use generated DTOs in state management (e.g., Pinia/Vuex) for type safety:
      const userState = reactive({
          user: null as UserDto | null,
      });
      

Integration Tips

  1. Custom Serialization Override default behavior by implementing JsonSerializable in your DTO:

    #[JsDto]
    class CustomUserDto implements JsonSerializable
    {
        public function jsonSerialize(): array
        {
            return [
                'full_name' => $this->name . ' ' . $this->surname,
                'age' => $this->age,
            ];
        }
    }
    
  2. Excluding Properties Use #[JsDto\Exclude] to skip properties during serialization:

    #[JsDto]
    class UserDto {
        public string $name;
        #[JsDto\Exclude]
        public string $password;
    }
    
  3. Dynamic DTOs For dynamic properties (e.g., from databases), use array or stdClass:

    #[JsDto]
    class DynamicDto {
        public array $metadata;
    }
    
  4. Frontend API Client Combine with API clients (e.g., Axios) for consistent type safety:

    import axios from 'axios';
    import { UserDto, deserialize } from './js/dtos/UserDto';
    
    const api = axios.create({ baseURL: '/api' });
    
    async function fetchUser(id: number): Promise<UserDto> {
        const response = await api.get(`/users/${id}`);
        return deserialize(response.data);
    }
    
  5. Testing Mock DTOs in PHPUnit:

    $dto = new UserDto();
    $dto->name = 'John';
    $dto->age = 30;
    
    $serialized = json_encode($dto);
    $this->assertEquals('{"name":"John","age":30}', $serialized);
    

Gotchas and Tips

Pitfalls

  1. Caching Issues

    • Generated JS files are cached. Clear the cache after changes:
      php bin/console js-dto:clear-cache
      
    • Or force regeneration:
      php bin/console js-dto:generate --force
      
  2. Type Mismatches

    • Ensure PHP and JavaScript types align (e.g., DateTime in PHP becomes string in JS by default).
    • Customize with #[JsDto\Type]:
      #[JsDto]
      class EventDto {
          #[JsDto\Type('Date')]
          public DateTime $date;
      }
      
  3. Circular References

    • Avoid circular references in DTOs (e.g., UserDto referencing OrderDto which references UserDto).
    • Use #[JsDto\Exclude] or break cycles manually.
  4. Namespace Conflicts

    • Ensure DTO class names are unique to avoid JS namespace collisions.
    • Prefix namespaces if needed:
      namespace App\Dto\Users;
      
  5. Database Migrations

    • If using DTOs for database interactions, ensure migrations align with DTO properties.
    • Example:
      #[JsDto]
      class ProductDto {
          public string $sku;
          public string $name;
          // Add new fields here before migrating
      }
      

Debugging

  1. Generated JS Inspection

    • Check public/js/dtos/ for generated files to verify output.
    • Look for errors in the JS console (e.g., deserialize failures).
  2. PHP Annotations

    • Validate annotations with:
      php bin/console js-dto:validate
      
  3. Logging

    • Enable debug mode in config/packages/dayploy_js_dto.yaml:
      debug: true
      
    • Check logs for generation errors:
      tail -f var/log/dev.log
      

Extension Points

  1. Custom Generators

    • Extend the generator by implementing Dayploy\JsDtoBundle\Generator\DtoGeneratorInterface:
      namespace App\Generator;
      
      use Dayploy\JsDtoBundle\Generator\DtoGeneratorInterface;
      
      class CustomDtoGenerator implements DtoGeneratorInterface
      {
          public function generate(string $className, array $properties): string
          {
              // Custom logic
              return '// Custom generated code';
          }
      }
      
    • Register in config/packages/dayploy_js_dto.yaml:
      generators:
          custom: App\Generator\CustomDtoGenerator
      
  2. Post-Generation Hooks

    • Use Symfony events to modify generated files:
      // src/EventListener/DtoGenerationListener.php
      use Dayploy\JsDtoBundle\Event\DtoGeneratedEvent;
      use Symfony\Component\EventDispatcher\EventSubscriberInterface;
      
      class DtoGenerationListener implements EventSubscriberInterface
      {
          public static function getSubscribedEvents()
          {
              return [
                  DtoGeneratedEvent::class => 'onDtoGenerated',
              ];
          }
      
          public function onDtoGenerated(DtoGeneratedEvent $event)
          {
              $content = $event->getContent();
              $content .= '\n// Custom post-processing';
              $event->setContent($content);
          }
      }
      
  3. Custom Templates

    • Override Twig templates in templates/bundles/dayployjsdto/:
      {# Custom template for DTO generation #}
      export interface {{ className }} {
          {% for property in properties %}
          {{ property.type }} {{ property.name }}{% if not loop.last %},{% endif %}
          {% endfor %}
      }
      
  4. Conditional Generation

    • Skip generation for specific DTOs via config:
      ignore_classes:
          - 'App\Dto\InternalDto'
          - 'App\Dto\TempDto'
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
babenkoivan/elastic-client
innmind/static-analysis
innmind/coding-standard
datacore/hub-sdk
alengo/sulu-http-cache-bundle
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
imbo/imbo-coding-standard
visualbuilder/filament-lottie
servicioslineaonce/starter-kit
atomcoder/laravel-reorderable
irajul/filament-shadcn-theme
agtp/agtp-php
agtp/mod-php
centraldesktop/protobuf-php