Giter VIP home page Giter VIP logo

typings's Introduction

OpenRPC Typings

CircleCI branch npm GitHub release GitHub commits since latest release

A tool to produce language-specific typings given an OpenRPC document.

This package will extract the json-schemas from your document, and give you types for them (and language-specific functionality for dealing with data of that json schema type).

Need help or have a question? Join us on our Discord!

Installing

npm install @open-rpc/typings

CLI

$ open-rpc-typings --help
Usage: cli [options]

Options:
  -v, --version                     print the version number
  -d, --document [openrpcDocument]  JSON string, or a filepath or remote URL pointing to an Open-RPC JSON document (default: "./openrpc.json")
  --output-rs [directory]           path to output dir of Rust typings
  --output-ts [directory]           path to output dir of Typescript typings
  --output-go [directory]           path to output dir of Go typings
  --name-rs [file]                  file name to input of Rust typings (default: "./index")
  --name-ts [file]                  file name to input of Typescript typings (default: "./index")
  --name-go [file]                  file name to input of Go typings (default: "./index")
  -h, --help                        print usage information

JS/TS SDK

import OpenRPCTypings from "@open-rpc/typings";


const typings = new OpenRPCTypings(OpenRPCDocument);

await typings.generate()

const rustTypings = typings.toString("rust");

typings's People

Contributors

belfordz avatar dependabot-preview[bot] avatar dependabot-support avatar dependabot[bot] avatar devonwesley avatar meowsbits avatar openrpc-bastion avatar shanejonas avatar zcstarr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

typings's Issues

need uppercase `interface` when creating typings

When declaring a param as object in openRPC.json.

running typings creates interface with lower case I and circleCI is not happy with it.

ERROR: /home/circleci/project/__GENERATED_TYPES__/index.ts:16:18 - interface name must start with a capitalized I

ESLint Github Actions step auto approves

Summary:
Github ESLint Action auto approves the commit even if lint has warnings.

Acceptance criteria:
We should re introduce local linting, either on commit with precommit hook, and use the github actions as a final safety guard.

Independent generation of individual JSON Schema files

Before I start, I just wanted to say I really love this project, especially its full integration with JSON Schema!

I was wondering how easy it would be to generate multiple files instead of one single file. Assuming I have multiple top-level OpenRPC descriptions, as well as multiple JSON Schema files referenced via $ref in e.g. the components section from the OpenRPC schemas, how difficult it would be to generate them in separate files and/or modules depending on target language and add the appropriate imports when external ones are referenced?

My goal is to get some autogenerated stub classes that contain decorators describing params and return types including the validation rules. Other types would ideally also be represented as "classterfaces" (microsoft/TypeScript#27519 (comment)) which would allow attaching extra validation metadata to them.

Not saying it would necessarily belong to this project, was just wondering what tools would you recommend that I use in order to achieve something like the above. From a quick glance, openrpc-schema-js looks like the right package to get started, but I'm not sure if the model preserves the original location of all the resolved schema references.

Generated types for PHP

After some discussion in discord, I think the best approach would be to generate PHP interfaces that have the appropriate docblocks for each service method.

Example:

<?php

namespace Rpc/Types;

interface MathService
{
    /**
     * My awesome method description
     *
     * @param int|float $a is a really cool number
     * @param int|float $a another cool number
     * @return int|float the result of $a + $b
    */
    public function addition($a, $b);
}

Namespace & output path should be configurable ideally (didn't dig much into this repo yet to see the CLI params).

Some users may want their interfaces strongly typed with param/return types, but the easiest thing for the time being is to skip that part and just do docblocks at first. Could have some config to allow for enabling strong types, for example, using PHP 8.0 union types:

<?php

namespace Rpc/Types;

interface MathService
{
    /**
     * My awesome method description
     *
     * @param int|float $a is a really cool number
     * @param int|float $a another cool number
     * @return int|float the result of $a + $b
    */
    public function addition(int|float $a, int|float $b) : int|float;
}

P.S. My preferred JSON-RPC server lib in PHP is https://github.com/datto/php-json-rpc, also includes a client which is useful for testing etc.

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
...
zsh: abort      open-rpc-typings -d openrpc-specs.json --output-go pkg/openrpc/ --name-go sui

When trying to generate a client in Go, the script crashes because of OOM. Tried to increase it, but it seems it is stuck in a loop or something.

Samething seems to happen with open-rpc/generator open-rpc/generator#689

<--- Last few GCs --->

[51614:0x158008000]    55860 ms: Mark-Compact 4045.5 (4132.3) -> 4031.4 (4133.6) MB, 5534.75 / 0.00 ms  (average mu = 0.118, current mu = 0.006) allocation failure; scavenge might not succeed
[51614:0x158008000]    59939 ms: Mark-Compact 4047.5 (4133.8) -> 4033.2 (4135.6) MB, 4057.96 / 0.00 ms  (average mu = 0.070, current mu = 0.005) allocation failure; scavenge might not succeed


<--- JS stacktrace --->

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
 1: 0x100a6bc2c node::Abort() [/opt/homebrew/Cellar/node/20.2.0/bin/node]
 2: 0x100a6d088 node::ModifyCodeGenerationFromStrings(v8::Local<v8::Context>, v8::Local<v8::Value>, bool) [/opt/homebrew/Cellar/node/20.2.0/bin/node]
 3: 0x100bd10d8 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, v8::OOMDetails const&) [/opt/homebrew/Cellar/node/20.2.0/bin/node]
 4: 0x100bd1084 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, v8::OOMDetails const&) [/opt/homebrew/Cellar/node/20.2.0/bin/node]
 5: 0x100d5b7ac v8::internal::Heap::CallGCPrologueCallbacks(v8::GCType, v8::GCCallbackFlags, v8::internal::GCTracer::Scope::ScopeId) [/opt/homebrew/Cellar/node/20.2.0/bin/node]
 6: 0x100d5e410 v8::internal::Heap::ComputeMutatorUtilization(char const*, double, double) [/opt/homebrew/Cellar/node/20.2.0/bin/node]
 7: 0x100d5c450 v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::internal::GarbageCollectionReason, char const*) [/opt/homebrew/Cellar/node/20.2.0/bin/node]
 8: 0x100d5a2c8 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [/opt/homebrew/Cellar/node/20.2.0/bin/node]
 9: 0x100d52294 v8::internal::HeapAllocator::AllocateRawWithLightRetrySlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [/opt/homebrew/Cellar/node/20.2.0/bin/node]
10: 0x100d52a10 v8::internal::HeapAllocator::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [/opt/homebrew/Cellar/node/20.2.0/bin/node]
11: 0x100d3b8b0 v8::internal::Factory::NewFillerObject(int, v8::internal::AllocationAlignment, v8::internal::AllocationType, v8::internal::AllocationOrigin) [/opt/homebrew/Cellar/node/20.2.0/bin/node]
12: 0x10104aaa4 v8::internal::Runtime_AllocateInYoungGeneration(int, unsigned long*, v8::internal::Isolate*) [/opt/homebrew/Cellar/node/20.2.0/bin/node]
13: 0x1008acc44 Builtins_CEntry_Return1_ArgvOnStack_NoBuiltinExit [/opt/homebrew/Cellar/node/20.2.0/bin/node]
14: 0x108198e2c 
15: 0x1081b4320 
16: 0x108197374 
17: 0x1081952f0 
18: 0x1081ace74 
19: 0x107f3b2e4 
20: 0x100908fb8 Builtins_PromiseFulfillReactionJob [/opt/homebrew/Cellar/node/20.2.0/bin/node]
21: 0x10084ab94 Builtins_RunMicrotasks [/opt/homebrew/Cellar/node/20.2.0/bin/node]
22: 0x1008223f4 Builtins_JSRunMicrotasksEntry [/opt/homebrew/Cellar/node/20.2.0/bin/node]
23: 0x100ce7908 v8::internal::(anonymous namespace)::Invoke(v8::internal::Isolate*, v8::internal::(anonymous namespace)::InvokeParams const&) [/opt/homebrew/Cellar/node/20.2.0/bin/node]
24: 0x100ce7d9c v8::internal::(anonymous namespace)::InvokeWithTryCatch(v8::internal::Isolate*, v8::internal::(anonymous namespace)::InvokeParams const&) [/opt/homebrew/Cellar/node/20.2.0/bin/node]
25: 0x100d091d4 v8::internal::MicrotaskQueue::RunMicrotasks(v8::internal::Isolate*) [/opt/homebrew/Cellar/node/20.2.0/bin/node]
26: 0x100d09008 v8::internal::MicrotaskQueue::PerformCheckpointInternal(v8::Isolate*) [/opt/homebrew/Cellar/node/20.2.0/bin/node]
27: 0x10099cb40 node::InternalCallbackScope::Close() [/opt/homebrew/Cellar/node/20.2.0/bin/node]
28: 0x10099d094 node::InternalMakeCallback(node::Environment*, v8::Local<v8::Object>, v8::Local<v8::Object>, v8::Local<v8::Function>, int, v8::Local<v8::Value>*, node::async_context) [/opt/homebrew/Cellar/node/20.2.0/bin/node]
29: 0x1009b25e0 node::AsyncWrap::MakeCallback(v8::Local<v8::Function>, int, v8::Local<v8::Value>*) [/opt/homebrew/Cellar/node/20.2.0/bin/node]
30: 0x100a72fd0 node::fs::FSReqCallback::Resolve(v8::Local<v8::Value>) [/opt/homebrew/Cellar/node/20.2.0/bin/node]
31: 0x100a748f0 node::fs::AfterNoArgs(uv_fs_s*) [/opt/homebrew/Cellar/node/20.2.0/bin/node]
32: 0x100a66090 node::MakeLibuvRequestCallback<uv_fs_s, void (*)(uv_fs_s*)>::Wrapper(uv_fs_s*) [/opt/homebrew/Cellar/node/20.2.0/bin/node]
33: 0x1036132d4 uv__work_done [/opt/homebrew/Cellar/libuv/1.45.0/lib/libuv.1.dylib]
34: 0x103616928 uv__async_io [/opt/homebrew/Cellar/libuv/1.45.0/lib/libuv.1.dylib]
35: 0x1036262e4 uv__io_poll [/opt/homebrew/Cellar/libuv/1.45.0/lib/libuv.1.dylib]
36: 0x103616dc4 uv_run [/opt/homebrew/Cellar/libuv/1.45.0/lib/libuv.1.dylib]
37: 0x10099d994 node::SpinEventLoopInternal(node::Environment*) [/opt/homebrew/Cellar/node/20.2.0/bin/node]
38: 0x100aaebe4 node::NodeMainInstance::Run(node::ExitCode*, node::Environment*) [/opt/homebrew/Cellar/node/20.2.0/bin/node]
39: 0x100aae940 node::NodeMainInstance::Run() [/opt/homebrew/Cellar/node/20.2.0/bin/node]
40: 0x100a359fc node::LoadSnapshotDataAndRun(node::SnapshotData const**, node::InitializationResultImpl const*) [/opt/homebrew/Cellar/node/20.2.0/bin/node]
41: 0x100a35bfc node::Start(int, char**) [/opt/homebrew/Cellar/node/20.2.0/bin/node]
42: 0x1a2d53f28 start [/usr/lib/dyld]
zsh: abort      open-rpc-typings -d openrpc-specs.json --output-go pkg/openrpc/ --name-go sui

Here's the specification: https://gist.github.com/RdeWilde/b6ec9c3c9e0b921d496e4553b5935300

Invalid Rust bindings are generated

I tried generating Rust bindings for this openrpc.json: https://raw.githubusercontent.com/ethereum/execution-apis/v1.0.0-beta.1/refs-openrpc.json; but it resulted in invalid Rust code.

The problems I'm seeing:

  • duplicate Rust types (#42 mentions this having been resolved for Rust)
  • cyclic type definitions
     {
     	"name": "rewardPercentiles",
     	"description": "A monotonically increasing list of percentile values. For each block in the requested range, the transactions will be sorted in ascending order by effective tip per gas and the coresponding effective tip for the percentile will be determined, accounting for gas consumed.",
     	"required": true,
     	"schema": {
     		"title": "rewardPercentiles",
     		"type": "array",
     		"items": {
     			"title": "rewardPercentile",
     			"description": "Floating point value between 0 and 100.",
     			"type": "number"
     		}
     	}
     }
    
    results in this Rust code:
    pub type RewardPercentiles = Vec<RewardPercentile>;
    
    where I would have expected something like:
    pub type RewardPercentiles = Vec<u32>;
    
  • functions are generated without a body. E.g.
    pub fn EthGetBlockByHash(&mut self, Block hash: 2ByteHexValue, Hydrated transactions: Hydrated) -> RpcRequest<BlockObject>;
    

Proper Types not being generated

I have the following schema it, fails to generate nested object types properly.

{
  "openrpc": "1.0.0",
  "info": {
    "title": "SuuperClient",
    "version": "0.1.0"
  },
  "methods": [
    {
      "name": "startTest",
      "params": [
        {
          "required": true,
          "name": "testParams",
          "schema": {
            "$ref": "#/components/schemas/TestParams"
          }
        },
        {
          "required": true,
          "name": "testParams1",
          "schema": {
            "$ref": "#/components/schemas/TestParams1"
          }
        }
      ],
      "result": {
        "name": "testResult",
        "schema": {
          "type": "string"
        }
      }
    }
  ],
  "components": {
    "contentDescriptors": {},
    "schemas": {
      "Accounts": {
        "type": "string",
        "title": "accounts"
      },
      "TestParams1": {
        "title": "TestParams1",
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "file": {
              "schema": {
                "type": "string"
              }
            }
          }
        }
      },
      "TestParams": {
        "title": "TestParams",
        "type": "object",
        "properties": {
          "accounts": {
            "title": "accounts",
            "schema": {
              "$ref": "#/components/schemas/Accounts"
            }
          }
        },
        "required": [
          "accounts"
        ]
      }
    }
  }
}

Outputs

export type Accounts = any;
export interface TestParams {
  accounts: Accounts;
  [k: string]: any;
}
export type Any7KQxXMBG = any;
export interface ObjectOfAny7KQxXMBGU1MDqLz7 {
  file?: Any7KQxXMBG;
  [k: string]: any;
}
export type TestParams1 = ObjectOfAny7KQxXMBGU1MDqLz7[];
export type StringDoaGddGA = string;
/**
 *
 * Generated! Represents an alias to any of the provided schemas
 *
 */
export type AnyOfTestParamsTestParams1StringDoaGddGA = TestParams | TestParams1 | StringDoaGddGA;
export type StartTest = (testParams: TestParams, testParams1: TestParams1) => Promise<StringDoaGddGA>;

Expected Output is that the any types are object types

Make the struct fields public in OpenRPC schema data repr types

Currently generator-client generates structs with all fields private, which makes it impossible to use those types when we use the generated client as a library in Rust (fields are hidden).

How it is now:

pub struct NewAccount {
    /// account description
    #[serde(rename = "description")]
    description: Option<String>,

    /// account name
    #[serde(rename = "name")]
    name: Option<String>,

    /// passphrase used to encode keyfile (recommend to use 8+ words with good entropy)
    #[serde(rename = "passphrase")]
    passphrase: Option<String>,
}

How it should be:

pub struct NewAccount {
    /// account description
    #[serde(rename = "description")]
    pub description: Option<String>,

    /// account name
    #[serde(rename = "name")]
    pub name: Option<String>,

    /// passphrase used to encode keyfile (recommend to use 8+ words with good entropy)
    #[serde(rename = "passphrase")]
    pub passphrase: Option<String>,
}

feat: add comment 'Generated: DO NOT EDIT' disclaimer to generated (Go,...?) typed files

The following command produces a type Go file with head as below

> open-rpc-typings --output-go goout -d https://raw.githubusercontent.com/open-rpc/examples/master/service-descriptions/petstore-expanded-openrpc.json
> head goout/index.go 
type StringDoaGddGA string
type UnorderedSetOfStringDoaGddGADvj0XlFa []StringDoaGddGA
type Integer2AHOqbcQ int64
type ObjectOfStringDoaGddGAStringDoaGddGAUbqj18UU struct {
        Name *StringDoaGddGA `json:"name"`
        Tag  *StringDoaGddGA `json:"tag,omitempty"`
}
type AnyBrndsk4F interface{}
type AllOfAnyBrndsk4FObjectOfStringDoaGddGAStringDoaGddGAUbqj18UUKZp9HQVl map[string]interface{}
type UnorderedSetOfAllOfAnyBrndsk4FObjectOfStringDoaGddGAStringDoaGddGAUbqj18UUKZp9HQVlL0I1EEvd []AllOfAnyBrndsk4FObjectOfStringDoaGddGAStringDoaGddGAUbqj18UUKZp9HQVl

In Go, it is conventional to prepend a "Generated - DO NOT EDIT" disclaimer comment at or near the top of generated files. This is useful for both robots and humans futher down the line. I don't know of any "canonical" phrase or sentence; usually includes the bespoke four words, though caps and ordering and punctuation may vary.

I don't know if this applies to other languages like Rust and Typescript too... ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.