@yaacovcr/transform
v0.0.8
Published
A set of tools for transforming GraphQL results.
Maintainers
Readme
@yaacovcr/transform
Installation
Using npm:
npm install @yaacovCR/transform [email protected]Using yarn:
yarn add @yaacovCR/transform [email protected]Using pnpm:
pnpm add @yaacovCR/transform [email protected]Overview
This library, primarily through its transform() export, provides several helpful functionalities for working with GraphQL results:
- Result Composition: Combine GraphQL results, including incremental delivery payloads (
@defer/@stream), from multiple downstream GraphQL services into a single unified result. (Note: Composition is currently under development and primarily functional for root fields.) - Result Transformation: Modify results using configurable transformers based on the leaf type, object field, or specific location within a GraphQL operation.
- Legacy Incremental Format Mapping: Convert results from the modern incremental delivery specification to the legacy format used in earlier
graphql-jsversions.
Notes:
When multiple transformer types are applied to the same field, they execute in the following order: leaf value transformer -> object field transformer -> path-scoped field transformer.
A separate
legacyExecuteIncrementally()export is also available. It leverages the same underlying transformation logic but is specifically designed to provide backwards compatibility for the legacy incremental delivery format when interacting with a single GraphQL service (i.e., without composition).
Usage
Composition of GraphQL Results
To compose results from multiple GraphQL services, provide a subschemas array to transform():
import { transform } from '@yaacovCR/transform';
const transformed = await transform({
schema,
document,
variableValues,
subschemas: [
{
label: 'Subschema1',
subschema: new GraphQLSchema({ ... }),
executor: myExecutor1,
},
{
label: 'Subschema2',
subschema: new GraphQLSchema({ ... }),
executor: myExecutor1,
},
],
});Transformation of GraphQL Results
Configurable Leaf Transformers
To apply transformations to specific leaf types (scalars or enums), pass leafTransformers to transform():
import { transform } from '@yaacovCR/transform';
const transformed = await transform({
schema,
document,
variableValues,
subschemas,
leafTransformers: {
Color: (value) => (value === 'GREEN' ? 'DARK_GREEN' : value),
},
});The signature is as follows:
type LeafTransformers = ObjMap<LeafTransformer>;
type LeafTransformer = (
value: unknown,
type: GraphQLLeafType,
path: Path,
) => unknown;Configurable Object Field Transformers
To apply transformations to specific fields within object types, pass objectFieldTransformers to transform(), namespaced by type name and field name:
import { transform } from '@yaacovCR/transform';
const transformed = await transform({
schema,
document,
variableValues,
subschemas,
objectFieldTransformers: {
SomeType: {
someField: (value) => 'transformed',
},
},
});The signature is as follows:
type ObjectFieldTransformers = ObjMap<ObjMap<FieldTransformer>>;
type FieldTransformer = (
value: unknown,
field: GraphQLField,
path: Path,
) => unknown;Configurable Path-Scoped Field Transformers
To apply transformations based on a field's specific location within the operation, pass pathScopedFieldTransformers to transform(). The keys are period-delimited paths reflecting the field structure in the operation (numeric list indices are omitted).
import { transform } from '@yaacovCR/transform';
const transformed = await transform({
schema,
document,
variableValues,
subschemas,
objectFieldTransformers: {
'someType.someFieldNameOrAlias': (value) => 'transformed',
},
});Legacy Incremental Delivery Format
If you need to interact with systems expecting the older incremental delivery format (from graphql-js pre-v17), you can enable conversion:
import { transform } from '@yaacovCR/transform';
const result = await transform({
schema,
document,
variableValues,
subschemas,
legacyIncremental: true,
});Alternatively, if you are working with a single GraphQL service (no composition) and need the legacy format, the legacyExecuteIncrementally() function provides a dedicated interface:
import { legacyExecuteIncrementally } from '@yaacovCR/transform';
const result = await legacyExecuteIncrementally({
schema,
document,
variableValues,
operationName,
rootValue,
contextValue,
fieldResolver,
typeResolver,
subscribeFieldResolver,
perEventExecutor,
enableEarlyExecution,
hideSuggestions,
abortSignal,
});Changelog
Changes are tracked as GitHub releases.
License
@yaacovcr/transform is MIT-licensed.
