[Issue #497] Support custom fields in TS SDK client#522
[Issue #497] Support custom fields in TS SDK client#522
Conversation
Allows API client users to pass a custom zod schema to resource methods like `Client.opportunities.get()` this allows users to parse API responses that include custom fields by passing in a schema generated from `withCustomFields()`
- fetchMany() preserves metadata from first response - search() avoids an extra round trip to get response metadata
Previously accepted CustomFieldSpec[] and used `CustomFieldSpec.key` to build the resulting customFields object. Now we expect Record<string,CustomFieldSpec> which more closely matches the final customFields object added to a schema
- Fixes `withCustomFields()` examples in TS SDK README - Adds TS SDK to root-level README
| * const Schema = withCustomFields(OpportunityBaseSchema, { | ||
| * legacyId: { fieldType: "object", valueSchema: ... } | ||
| * } as const); |
There was a problem hiding this comment.
This provides an example of the DX change from the old withCustomFields() to the new pattern which accepts:
Record<string,CustomFieldSpec>instead of:CustomFieldSpec[]
| /** Optional display name; used as the default for CustomField.name when provided, otherwise the record key is used */ | ||
| name?: string; |
There was a problem hiding this comment.
Also adds the CustomFieldSpec.name which was missing from the previous iteration. This is used to populate the default value of customFields.legacyId.name
For example:
{
"id": "1cdb6dcd-18f8-4e21-9e20-f8f77cd11269",
"title": "Example opportunity",
...
"customFields": {
"legacyId": {
"name": "Legacy ID",
"fieldType": "number",
"value": 12345,
"description": "An integer ID for the opportunity, needed for compatibility with legacy systems"
}
}
}
jcrichlake
left a comment
There was a problem hiding this comment.
A couple of questions/comments.
| await expect(client.opportunities.search({ query: "test" })).rejects.toThrow("500"); | ||
| }); | ||
|
|
||
| it("parses items with a custom schema", async () => { |
There was a problem hiding this comment.
This shares the same name as the previous test you added. Can you update this to make it slightly more descriptive so that if it breaks in the future it's less confusing?
There was a problem hiding this comment.
FWIW this was intentional -- I added roughly the same test parses items with custom schema to each of the Client.opportunity methods and the tests are already grouped by method:
And it groups them when they error as well:
But maybe I can restate the response method in that description to make it clearer? ("parses list response item with custom schema")
There was a problem hiding this comment.
Updated the test names here: test(ts-sdk): Make test names more descriptive
Makes the function easier to reason about by moving some logic to a private fetchOnePage() method and moving the first page request out of the while loop
Accidentally dropped an `as const` in the withCustomFields() example
Previously it would error if `Client.opportunity.search()` returned no matching results because pageSize was expected to be > 0
Summary
Enables TypeScript SDK users to leverage the API client to parse API responses that include custom fields.
Changes proposed
Client.opportunitiesto accept an optionalschemaparameter that can be used to parse custom fields included in API responses. Thisschemaparam should be a Zod schema whose inferred type is an extension ofOpportunityBaseClient.opportunities.search()statusCodeandmessagein the response forClient.fetchMany()instead of using the metadata from the first responsewithCustomFields()fromCustomFieldSpec[]toRecord<string, CustomFieldSpec>to more closely match the actualcustomFieldsobject that is being added to a given opportunity.lib/ts-sdk/examples/including a mock server that can be used instead of having to spin up the California grants example or the actual Simpler.Grants.gov APIContext for reviewers
Instructions for review
git checkout issue-497-ts-sdk-client-support-custom-fieldscd lib/ts-sdk/pnpm example:serverto spin up the local mock serverpnpm example:get-custom-fields 573525f2-8e15-4405-83fb-e6523511d893Notes
CustomFieldSpecattributes and thewith_custom_fields()input in the Python SDK, to align with these changes in the TypeScript SDK.Additional information