Creating TypeScript interfaces from Laravel backend

I'm currently exploring ways to automatically generate TypeScript code from the API of my Laravel application. I have been using scribe for generating API documentation and then utilizing it to create TypeScript definitions. However, I am facing an issue related to handling server messages. My approach involves creating OpenAPI docs based on the Resources returned by the APIs. If I proceed in this direction, each endpoint would require its own designated resource which should include the 'server message' to ensure proper generation of API docs.

To illustrate, consider the following example:

/**
 * @apiResource App\Http\Admin\Resources\PermissionCreateResource
 * @apiResourceModel App\Models\Permission
 * @param PermissionCreateRequest $request
 */
public function create(PermissionCreateRequest $request): JsonResponse
{
    $input = $request->validated();
    $permission = $this->permissionFactory->createPermission($input);
    return new JsonResponse(new PermissionCreateResource($permission), Response::HTTP_CREATED);
}

Here is how the PermissionCreateResource class might look:

public function toArray(Request $request): array
{
    return [
        'message' => 'Permission created',
        'data' => [
            'id' => $this->id,
            'name' => $this->name,
        ]
    ];
}

In order to adhere to best practices and maintain clarity, it is essential to carefully design the structure of resources and endpoints. Any suggestions on what would be the most appropriate course of action?

Thank you in advance! Cheers!

Answer №1

From a personal perspective, I believe that simply responding with the HTTP status code 201 is sufficient to indicate success without the need for an additional success message in the responses.

For error messages or specific notifications, it may be more appropriate to return an error code (such as "invalid-param") rather than a user-friendly message, allowing the frontend to handle language localization.

When working with the Permission model, it is recommended to utilize a PermissionResource for any operations related to it:

public function toArray(Request $request): array
{
    return [
        'data' => [
            'id' => $this->id,
            'name' => $this->name,
        ]
    ];
}

This resource can then be utilized in all endpoints associated with the Permission model:

/**
 * @apiResource App\Http\Admin\Resources\PermissionResource
 * @apiResourceModel App\Models\Permission
 * @param PermissionCreateRequest $request
 */
public function create(PermissionCreateRequest $request): JsonResponse
{
    $input = $request->validated();
    $permission = $this->permissionFactory->createPermission($input);
    return new JsonResponse(new PermissionResource($permission), Response::HTTP_CREATED);
}

If there is a necessity to include endpoint-specific data in the resource, it is recommended to pass this data from the controller to ensure uniformity across endpoints related to the Permission model.

Laravel documentation suggests utilizing the additional() method and annotating with @apiResourceAdditional to inform Scribe of any additional data being added to the resource directly from the controller.

/**
 * @apiResource App\Http\Admin\Resources\PermissionResource
 * @apiResourceModel App\Models\Permission
 * @param PermissionCreateRequest $request
 * @apiResourceAdditional message="Permission created"
 */
public function create(PermissionCreateRequest $request): JsonResponse
{
    $input = $request->validated();
    $permission = $this->permissionFactory->createPermission($input);
    return (new JsonResponse(new PermissionResource($permission), Response::HTTP_CREATED))
        ->additional([
            'message' => 'Permission created',
        ]);
}

(Reference: https://laravel.com/docs/10.x/eloquent-resources#adding-meta-data-when-constructing-resources)

(Reference: )

Hope this provides some clarity!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Access-Control-Allow-Methods does not allow the use of Method PUT in the preflight response, as stated by Firebase Cloud Functions

I am facing an issue with my Firebase cloud function endpoint. I have a setup where it forwards PUT requests to another API endpoint. I have configured the following Access-Control-Allow- headers: // src/middlewares/enableCORS.ts export default function en ...

typescript, generate a new type by merging option values

In typescript I am faced with a challenge. I have a type called A: interface A { a1: string; a2: int; } As well as another type called B: interface B { b1: number } Now, my goal is to create a new type: interface AB { a1?: string; a2? ...

Adjust the size of the plane in Three.js to match the entire view

English is not my strong suit, as I am Japanese. I apologize for any confusion. Currently, my focus is on studying Three.js. I aim to position a Plane directly in front of the camera as the background. My goal is to have the Plane background fill the en ...

Encountering a 500 error code while attempting to send a post request using Angular

Whenever I attempt to send a post request to Django server, I encounter a 500 (Internal Server Error) response. Interestingly, the get and put requests work flawlessly on the same server where Django is connected to PostgreSQL database. Here is a snippet ...

Overriding TypeScript types generated from the GraphQL schema

Currently, I am utilizing the graphql-code-generator to automatically generate TypeScript types from my GraphQL schema. Within GraphQL, it is possible to define custom scalar types that result in specific type mappings, as seen below in the following code ...

Error encountered while transforming object due to index type mismatch

I am attempting to change the values of an object, which consist of arrays with numbers as keys, to their respective array lengths. However, I received a type error that says 'Element implicity has any type because a string element cannot be used to ...

Updating the value in React context does not result in the value being updated

I am in the process of developing a simple routing system where users can either be authenticated or not. I have been using hooks to implement this functionality, but so far, it has not been as successful as I hoped for. authProvider.tsx import React, {Di ...

Retrieve data that resets to undefined upon reloading from an array

Encountering an unusual error while working with TypeScript for the first time. Initially, when I use console.log(data), it displays an array with objects. However, upon reloading the webpage without making any changes, the console log shows undefined. con ...

Transforming named functions in const or class constructors with Eslint and Typescript: a guide

Lately, I've been relying heavily on the code snippet from an answer that I requested: function sameValuesAsKeys<K extends string>(...values: K[]): {readonly [P in K]: P} { const ret = {} as {[P in K]: P} values.forEach(k => ret[k] = k); ...

Transmit information from an IONIC 3 application to a PHP server using the POST method

Having trouble sending data from Ionic 3 to php via the http library using post? When php tries to retrieve it, it's unable to locate. Below is the Typescript file that generates the token to be sent to php and calls the php file on localhost (xampp) ...

Exploring the functionality of two-way data binding in Angular - a beginner's guide

Transitioning from a different framework and switching from JavaScript to Angular & TypeScript has left me feeling confused about how to efficiently share data/values between components. ...

Concise way to add or insert an element into an array, at a specific property of an object

I am working with an object of the ObjectOfArrays type: type ObjectOfArrays = { [id: string]: Array<string> }; Throughout my code, I need to add strings to the correct array based on the id. Currently, I am using the following approach: if (id i ...

I'm currently working on building a fresh window with Tauri 1.2, combining the powers of Rust, React, and Typescript. However, I've encountered a few

Utilizing Tauri's WindowBuilder in Rust, I attempted to create a new window. Despite successfully generating a blank window, I encountered challenges: The inability to display any content on the window The failure to close the window Being relativel ...

Guide to accessing a newly opened window from a different domain originating from the current window

Currently working on an Angular project, I am facing a scenario where I have a link on page A that directs users to a different origin page B. The HTML code for the link is shown below: ... <a href="https://another.origin"> PAGE B </a> ... On ...

How can I extract a value from an object that is readonly, using a formatted string as the key?

I encountered a situation where I have code resembling the following snippet. It involves an object called errorMessages and multiple fields. Each field corresponds to various error messages in the errorMessages object, but using a formatted string to retr ...

The component is failing to store its value within the database

I'm encountering an problem when attempting to save an option in the database. To address this issue, I created a component in Svelte called StatePicker that is responsible for saving US States. However, when I try to save it in the database using a ...

Tips for troubleshooting the error message: "The relative import path "$fresh/dev.ts" is not prefaced with / or ./ or ../"

My editor is showing a TypeScript error for a Deno module I am working on. The import path "$fresh/dev.ts" should be prefixed with / or ./ or ../ I have an import_map.json file set up with the following content. { "imports": { "$fre ...

ES6: The attribute 'selected' is not found on the data type 'Object'

While attempting to convert the JS code from 'AMcharts4 codepen pre selecting areas' into ES6, I encountered an error. Error TS2339: Property 'selected' does not exist on type 'Object'. Here is the code snippet that I am l ...

What is the most efficient way to find the sum of duplicates in an array based on two different properties and then return the

var data = [ { "amount": 270, "xlabel": "25-31/10", "datestatus": "past", "color": "#E74C3C", "y": 270, "date": "2020-10-31T00:00:00Z", "entityId": 1, "entityName": "Lenovo HK", "bankName": "BNP Paribas Bank", "b ...

The specified file is not located within the 'rootDir' directory in the Cypress tsconfig.json file

I've encountered an issue while configuring Cypress in my Project, specifically with the typescript setup for Cypress. Here is the structure of my project: fronend/ - cypress/ -tsconfig.json - src/ - tsconfig.json - package.jso ...