Repository navigation
TypeScript target: request types require readOnly properties #43
Description
With --target ts, a request body whose schema has required readOnly properties keeps them required in the request type. Callers have to supply server-assigned values such as id and created_on, or cast, and whatever they pass is sent.
src/lib.rs says "The body keeps its read-only fields, since a model is the same object in requests and responses: a generator leaves out of what a client sends the fields that [Field::is_read_only] reports" (likewise src/types.rs), but nothing under src/bin/forge checks is_read_only. OpenAPI 3.0 also says a required readOnly property is required in responses only.
Repro
On main at 697d90e:
{
"openapi": "3.0.3",
"info": { "title": "Repro", "version": "1" },
"servers": [{ "url": "https://api.example.com" }],
"paths": {
"/things": {
"post": {
"x-fern-sdk-group-name": "things", "x-fern-sdk-method-name": "create",
"requestBody": { "required": true, "content": { "application/json": {
"schema": { "$ref": "#/components/schemas/Thing" } } } },
"responses": { "200": { "description": "ok", "content": { "application/json": {
"schema": { "$ref": "#/components/schemas/Thing" } } } } }
}
}
},
"components": { "schemas": { "Thing": {
"type": "object", "required": ["id", "createdOn", "name"],
"properties": {
"id": { "type": "string", "readOnly": true },
"createdOn": { "type": "string", "format": "date-time", "readOnly": true },
"name": { "type": "string" }
} } } }
}forge spec.json --target ts --out sdksdk/things/client.ts has export type CreateRequest = Thing;, and sdk/things/models.ts has:
export interface Thing {
createdOn: Temporal.Instant;
id: string;
name: string;
}So create({ name: "x" }) doesn't type-check.
Impact
In openapi.forge.json from this repo's openapi@416bb87 release, 40 JSON request bodies require a readOnly property at the top level (counting allOf), and at least 9 more do so only in a nested object, such as policies[].id in POST /accounts/{account_id}/tokens. For example, POST /accounts/{account_id}/workers/scripts/{script_name}/deployments uses workers_deployment, which requires the read-only id, source and created_on.
A few look like mistakes in the document instead. For example, POST /accounts/{account_id}/teamnet/routes requires tunnel_id, which is marked read-only through the shared tunnel_tunnel_id schema but has to be sent. Leaving read-only fields out of what's sent would break that call until the document is fixed.
Expected
Read-only properties are left out of request types, or at least not required, as src/lib.rs describes. Since models are shared, this probably needs request-side types for models with read-only fields, nested ones included.
Found while experimenting with an alternative TypeScript generator on top of forge.
Activity