
Security News
PEP 810 Proposes Explicit Lazy Imports for Python 3.15
An opt-in lazy import keyword aims to speed up Python startups, especially CLIs, without the ecosystem-wide risks that sank PEP 690.
urql-serialize-scalars-exchange
Advanced tools
This exchange is inspired by url-custom-scalars-exchange, but does not import the graphql schema which can be really big. Instead, it uses scalar location information which show where structurally the scalar of particular type can appear in arguments and results.
GraphQL is good because it makes data in API type-defined. However, the number of supported scalars (primitive types) is limited and although you can define custom ones on the server side, you can't easily do this on client side.
In our case we allow a field to have Json
type which is serialized and deserialized on the server, but on the client we need to do this by hand, so for example, we will have Post
type with metadata
field of type Json
, which can contain arbitrary metadata. To update such a page, the PostInput variable could look like:
variables.postInput = {
title: "Foo",
slug: "foo-bar",
content: "Hello!",
metadata: '{"category":"manual","promote":true}'
}
With urql-serialize-scalars-exchange
you can nest the object in a more natural way, and the exchange will serialize it using provided serializer:
The scalar locations contain information, that PostInput
type can have metadata field of type Json
, and if you pass an object in that metadata field, it will be serialized with JSON.stringify and sent to the server as string.
On the server side, it will be de-serialized again and resolver will receive a map, not string.
variables.postInput = {
title: "Foo",
slug: "foo-bar",
content: "Hello!",
metadata: {
category: "manual",
promote: true
}
}
You have to define serializer and deserializer function for every custom scalar type. The serializer/deserializer could look like so:
{
Json: {
serialize: (v: any) => typeof v === 'string' ? v : JSON.stringify(v),
deserialize: (v: string) => JSON.parse(v),
},
}
You can define similar ones for Dates, DateTimes, Money, any other scalar type you have defined in GraphQL server.
Add this package to the project.
const serializeScalarsExchange = createSerializeScalarsExchange(
scalarLocations,
{
Json: {
serialize: (v: any) => typeof v === 'string' ? v : JSON.stringify(v),
deserialize: (v: string) => JSON.parse(v),
},
}
);
// then add serializeScalarsExchange before other exchanges when creating urql client
The scalarLocations contain information on where scalars are in types and responses, and you can generate this file using codegen, using codegen-graphql-scalar-locations plugin.
Example for scalarLocations (this is just a part of it, taken from Proca action tool:
export type ObjectFieldTypes = {
[key: string]: { [key: string]: string | string[] }
};
export type OpTypes = {
[key: string]: string | string[]
};
export type ScalarLocations = {
scalars: string[],
inputObjectFieldTypes: ObjectFieldTypes;
outputObjectFieldTypes: ObjectFieldTypes;
operationMap: OpTypes;
};
export const scalarLocations : ScalarLocations = {
"inputObjectFieldTypes": {
...
"CampaignInput": {
"config": "Json",
"actionPages": "ActionPageInput"
},
"ContactInput": {
"address": "AddressInput",
"nationality": "NationalityInput"
}
},
"outputObjectFieldTypes": {
"Contact": {
"publicKey": "KeyIds",
"signKey": "KeyIds"
},
"OrgCount": {
"org": [
"PrivateOrg",
"PublicOrg"
]
},
"PublicCampaign": {
"config": "Json",
"stats": "CampaignStats",
"org": [
"PrivateOrg",
"PublicOrg"
],
"actions": "PublicActionsResult"
}
},
"operationMap": {
"campaigns": [
"PrivateCampaign",
"PublicCampaign"
],
"upsertCampaign": [
"PrivateCampaign",
"PublicCampaign"
],
...
},
"scalars": [
"Json"
]
};
The input scalars has all the types that have custom scalar nested somewhere, and the position of the custom scalar field is indicated by object structure - the string value at the leaf designates the scalar name. For output scalars, we have similar structure but without the types - the top-level keys of outputScalars are query or mutation names which are given back in results.
This library has no fragments support - just because I do not use them and did not plan it for v0.1. Please contribute them, it should not be hard!
Please mind this is best for a situation where you use a fixed set of queries, so you know what their names are; if you use grapqhql-tag and aliases for instance, the scalarLocations will not contain an aliased result. Because graphql results do not contain any typing data, it is impossible to be smarter about this without bundling a schema (which we want to avoid due to its size). However, this is enough good approach to use if you generate all your api calls using graphql codegen - you get not only TypeScript types for all queries and arguments, but you can also do serialization/deserialization based on this.
FAQs
## What is this?
The npm package urql-serialize-scalars-exchange receives a total of 335 weekly downloads. As such, urql-serialize-scalars-exchange popularity was classified as not popular.
We found that urql-serialize-scalars-exchange demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
An opt-in lazy import keyword aims to speed up Python startups, especially CLIs, without the ecosystem-wide risks that sank PEP 690.
Security News
Socket CEO Feross Aboukhadijeh discusses the recent npm supply chain attacks on PodRocket, covering novel attack vectors and how developers can protect themselves.
Security News
Maintainers back GitHub’s npm security overhaul but raise concerns about CI/CD workflows, enterprise support, and token management.