From 430ce5af43f2db5ceaf252b73037a7b34ec84549 Mon Sep 17 00:00:00 2001 From: Ryan Tan Date: Fri, 8 Nov 2024 16:37:20 +0000 Subject: [PATCH] feat(ci): add stainless generation to ci --- .github/workflows/generate-node-client.yml | 19 +++ crates/jstz_node/openapi.json | 23 ++-- crates/jstz_node/stainless.yml | 133 +++++++++++++++++++++ crates/jstz_proto/src/operation.rs | 18 ++- crates/jstz_proto/src/receipt.rs | 11 +- 5 files changed, 190 insertions(+), 14 deletions(-) create mode 100644 .github/workflows/generate-node-client.yml create mode 100644 crates/jstz_node/stainless.yml diff --git a/.github/workflows/generate-node-client.yml b/.github/workflows/generate-node-client.yml new file mode 100644 index 000000000..0bfaba7d7 --- /dev/null +++ b/.github/workflows/generate-node-client.yml @@ -0,0 +1,19 @@ +name: Upload OpenAPI spec to Stainless + +on: + pull_request: # testing only + push: + branches: [main] + +jobs: + stainless: + concurrency: upload-openapi-spec-action + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: stainless-api/upload-openapi-spec-action@main + with: + stainless_api_key: ${{ secrets.STAINLESS_API_KEY }} + input_path: "crates/jstz_node/openapi.json" + config_path: "crates/jstz_node/stainless.yml" + project_name: "jstz-client" diff --git a/crates/jstz_node/openapi.json b/crates/jstz_node/openapi.json index 4b359a58b..89f7f1383 100644 --- a/crates/jstz_node/openapi.json +++ b/crates/jstz_node/openapi.json @@ -440,7 +440,8 @@ } } } - ] + ], + "title": "DeployFunction" }, { "allOf": [ @@ -461,7 +462,8 @@ } } } - ] + ], + "title": "RunFunction" } ] }, @@ -679,7 +681,8 @@ } } } - ] + ], + "title": "DeployFunctionReceipt" }, { "allOf": [ @@ -700,10 +703,12 @@ } } } - ] + ], + "title": "RunFunctionReceipt" }, { "type": "object", + "title": "DepositReceipt", "required": [ "#type" ], @@ -735,7 +740,8 @@ } } } - ] + ], + "title": "FaDepositReceipt" }, { "allOf": [ @@ -756,7 +762,8 @@ } } } - ] + ], + "title": "FaWithdrawReceipt" } ] }, @@ -821,7 +828,7 @@ }, "headers": { "type": "object", - "description": "Any valid HTTP headers" + "additionalProperties": true }, "method": { "type": "string", @@ -865,7 +872,7 @@ }, "headers": { "type": "object", - "description": "Any valid HTTP headers" + "additionalProperties": true }, "status_code": { "type": "integer", diff --git a/crates/jstz_node/stainless.yml b/crates/jstz_node/stainless.yml new file mode 100644 index 000000000..db37d7396 --- /dev/null +++ b/crates/jstz_node/stainless.yml @@ -0,0 +1,133 @@ +# yaml-language-server: $schema=https://app.stainlessapi.com/config.schema.json + +organization: + # Name of your organization or company, used to determine the name of the client + # and headings. + name: jstz client # Strangely, the organisation name is used as the name of the root class + docs: https://jstz-dev.github.io/jstz/ + contact: contact@trili.tech + +# `targets` define the output targets and their customization options, such as +# whether to emit the Node SDK and what it's package name should be. +targets: + node: + readme_title: Jstz Client + package_name: "@jstz-dev/client" + production_repo: null + publish: + npm: false + +# `client_settings` define settings for the API client, such as extra constructor +# arguments (used for authentication), retry behavior, idempotency, etc. +client_settings: + opts: {} + +# `environments` are a map of the name of the environment (e.g. "sandbox", +# "production") to the corresponding url to use. +environments: + production: https://localhost:8933 + +# `pagination` defines [pagination schemes] which provides a template to match +# endpoints and generate next-page and auto-pagination helpers in the SDKs. +pagination: [] + +# `resources` define the structure and organziation for your API, such as how +# methods and models are grouped together and accessed. See the [configuration +# guide] for more information. +# +# [configuration guide]: +# https://app.stainlessapi.com/docs/guides/configure#resources +resources: + accounts: + # Subresources define resources that are nested within another for more powerful + # logical groupings, e.g. `cards.payments`. + subresources: + balance: + # Configure the methods defined in this resource. Each key in the object is the + # name of the method and the value is either an endpoint (for example, `get /foo`) + # or an object with more detail. + # + # [reference]: https://app.stainlessapi.com/docs/reference/config#method + methods: + retrieve: get /accounts/{address}/balance + code: + # Configure the models--named types--defined in the resource. Each key in the + # object is the name of the model and the value is either the name of a schema in + # `#/components/schemas` or an object with more detail. + # + # [reference]: https://app.stainlessapi.com/docs/reference/config#model + models: + parsedCode: ParsedCode + methods: + retrieve: get /accounts/{address}/code + kv: + models: + kvValue: KvValue + methods: + retrieve: get /accounts/{address}/kv + subresources: + subkeys: + methods: + list: + type: http + endpoint: get /accounts/{address}/kv/subkeys + paginated: false + nonce: + models: + nonce: Nonce + methods: + retrieve: get /accounts/{address}/nonce + + logs: + models: + logRecord: LogRecord + methods: + stream: get /logs/{address}/stream + subresources: + persistent_requests: + methods: + list: + type: http + endpoint: get /logs/{address}/persistent/requests + paginated: false + retrieve: get /logs/{address}/persistent/requests/{request_id} + + operations: + methods: + inject: post /operations + subresources: + receipt: + models: + receipt: Receipt + methods: + retrieve: get /operations/{operation_hash}/receipt + + crypto: + models: + publicKey: PublicKey + publicKeyHash: PublicKeyHash + signature: Signature + +settings: + license: Apache-2.0 + +# `readme` is used to configure the code snippets that will be rendered in the +# README.md of various SDKs. In particular, you can change the `headline` +# snippet's endpoint and the arguments to call it with. +readme: + example_requests: + default: + type: request + endpoint: get /accounts/{address}/code + params: &ref_0 + address: REPLACE_ME + headline: + type: request + endpoint: get /accounts/{address}/code + params: *ref_0 + pagination: + type: request + endpoint: get /accounts/{address}/kv/subkeys + params: + address: REPLACE_ME + include_stainless_attribution: false diff --git a/crates/jstz_proto/src/operation.rs b/crates/jstz_proto/src/operation.rs index 8fd208ace..97f7b75e9 100644 --- a/crates/jstz_proto/src/operation.rs +++ b/crates/jstz_proto/src/operation.rs @@ -109,10 +109,7 @@ pub struct RunFunction { pub method: Method, /// Any valid HTTP headers #[serde(with = "http_serde::header_map")] - #[schema( - value_type = Object, - additional_properties, - )] + #[schema(schema_with= openapi::http_headers)] pub headers: HeaderMap, #[schema(schema_with = openapi::http_body_schema)] pub body: HttpBody, @@ -123,7 +120,9 @@ pub struct RunFunction { #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, ToSchema)] #[serde(tag = "#type")] pub enum Content { + #[schema(title = "DeployFunction")] DeployFunction(DeployFunction), + #[schema(title = "RunFunction")] RunFunction(RunFunction), } @@ -215,9 +214,18 @@ pub enum ExternalOperation { } pub mod openapi { - use utoipa::{openapi::Array, schema}; + use utoipa::{ + openapi::{schema::AdditionalProperties, Array, Object, ObjectBuilder}, + schema, + }; pub fn http_body_schema() -> Array { schema!(Option>).build() } + + pub fn http_headers() -> Object { + ObjectBuilder::new() + .additional_properties(Some(AdditionalProperties::FreeForm(true))) + .build() + } } diff --git a/crates/jstz_proto/src/receipt.rs b/crates/jstz_proto/src/receipt.rs index 8db5565fd..e9475fb1c 100644 --- a/crates/jstz_proto/src/receipt.rs +++ b/crates/jstz_proto/src/receipt.rs @@ -46,17 +46,26 @@ pub struct RunFunctionReceipt { pub status_code: StatusCode, /// Any valid HTTP headers #[serde(with = "http_serde::header_map")] - #[schema(value_type = Object, additional_properties)] + #[schema(schema_with = crate::operation::openapi::http_headers)] pub headers: HeaderMap, } #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] #[serde(tag = "#type")] pub enum ReceiptContent { + #[schema(title = "DeployFunctionReceipt")] DeployFunction(DeployFunctionReceipt), + + #[schema(title = "RunFunctionReceipt")] RunFunction(RunFunctionReceipt), + + #[schema(title = "DepositReceipt")] Deposit, + + #[schema(title = "FaDepositReceipt")] FaDeposit(FaDepositReceipt), + + #[schema(title = "FaWithdrawReceipt")] FaWithdraw(FaWithdrawReceipt), }