proresult/php-typescript-rpc-codegen

Generate typescript rpc from php

v0.9.0 2023-05-16 07:34 UTC

README

This library/tool is used to expose type annotated php code written in a certain way as rpc functions, and create typescript client code to use the exposed rpc functions in a typesafe manner from the web.

The goal is to make it easy to do type safe requests from typescript code in the browser to a php function running on a server, and get a typesafe response back.

This is currently beta level quality, but is used in production.

High level overview

  1. Define model classes for request + response in a separate source namespace (directory).
  2. Define rpc classes with methods that accept the request model class as a argument (for post requests), and returns the response model class.
  3. Run the code generator. This will create three things:

    • A typescript interface for each model class.
    • A typescript file per rpc class, exporting one function per rpc method.

      The "rpc function" returns a FetchAdapter instance that has all required info for a general typescript client to do the rpc http request for the given rpc method. This makes it easy to perform a typesafe request and get a typesafe response from typescript code in the browser, using the browser fetch api.

    • A php "adapter" class per rpc class. This handles serverside deserialization/serialization of requests/responses, and mapping incoming requests to correct rpc class + method.(By request URL path).

  4. In a request receiving php file, hook the generated php rpc adapter class(es) into the php server request/response cycle by adding it to a RpcRouter instance (defined in proresult/php-typescript-rpc-server). Pass incoming http requests to the RpcRouter and emit it's response back to requester.
  5. Create typescript code that initializes a Client class from the @proresult/php-typescript-rpc library library. Call Client.do method with a FetchAdapter instance created by the generated typescript rpc function to perform rpc requests.

RPC request methods

The default request method is a POST request where all data from client to server is sent json encoded in the request body. The rpc method must then have exactly one argument declared with the request model type.

By annotating a rpc method with the Get attribute defined in php-typescript-server, the request method will be GET. This is handled differently. For "get methods", all data from client to server is sent as query parameters in the url. This kind of rpc method is defined with zero or more arguments limited to these native php types:

  • string
  • int
  • float
  • bool

The response is always a json encoded rpc model class instance.

Example

Look at the test code in this project, or the standalone php-typescript-rpc-demo project for complete example code.

Recommendations

Request/Response Modelling

When declaring request/response classes, it is recommended, if possible, to have a default initial value for all properties so that a default initialization without values is a valid object instance. This is for forward/backwards compatibility, so that a future or old client don't get BadRequestException because the request is missing a property that is declared in the request class. Naturally, the rpc method being called must also properly handle the default value of the property then.

Development info

When doing development, it can be helpful to include the related dependencies with a symlink, so that one can do required changes in dependencies and see the result immediately. To do this, temporarily add a local repository to the composer.json file.

Example:

"repositories" : {
    "proresult/php-typescript-rpc-server": {
        "type" : "path",
        "url": "../php-typescript-rpc-server",
        "options" : {
            "symlink" : true
        }
    }
}

NB: Remember to remove this again after. Never commit this change.