3
Flatten Strapi 4's response JSON · GitHub
source link: https://gist.github.com/hucancode/5b495aabf75fc3b940df3e5f94d5b927
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Flatten Strapi 4's response JSON · GitHub
Graphql Support [Partially tested!!!]
// src/middlewares/flatten-response.js
const fs = require("fs");
const normalize = (data) => {
const isObject = (data) =>
Object.prototype.toString.call(data) === "[object Object]";
const isArray = (data) =>
Object.prototype.toString.call(data) === "[object Array]";
const flatten = (data) => {
if (!data.attributes) return data;
return {
id: data.id,
...data.attributes,
};
};
if (isArray(data)) {
return data.map((item) => normalize(item));
}
if (isObject(data)) {
if (isArray(data.data)) {
data = [...data.data];
} else if (isObject(data.data)) {
data = flatten({ ...data.data });
} else if (data.data === null) {
data = null;
} else {
data = flatten(data);
}
for (const key in data) {
data[key] = normalize(data[key]);
}
return data;
}
return data;
};
const fixTypeDefName = (name) => {
name = name.replace("RelationResponseCollection", "s");
name = name.replace("EntityResponseCollection", "s");
name = name.replace("EntityResponse", "");
name = name.replace("Entity", "");
return name;
};
const fixTypeRefName = (typeDef) => {
if (
typeDef.name != null &&
typeDef.name.endsWith("EntityResponseCollection")
) {
typeDef.ofType = {
kind: "NON_NULL",
name: null,
ofType: {
kind: "OBJECT",
name: typeDef.name.replace("EntityResponseCollection", ""),
ofType: null,
},
};
typeDef.kind = "LIST";
typeDef.name = null;
return typeDef;
}
if (typeDef.ofType != null) {
typeDef.ofType = fixTypeRefName(typeDef.ofType);
}
if (typeDef.name != null) {
typeDef.name = fixTypeDefName(typeDef.name);
}
return typeDef;
};
const fixTypeDef = (typeDef) => {
const fixedType = {
...typeDef,
name: fixTypeDefName(typeDef.name),
};
fixedType.fields = typeDef.fields.map((y) => ({
...y,
type: {
...fixTypeRefName(y.type),
},
}));
return fixedType;
};
const respond = async (ctx, next) => {
await next();
// REST API response
if (ctx.url.startsWith("/api")) {
console.log(
`API request (${ctx.url}) detected, transforming response json...`
);
ctx.response.body = {
...ctx.response.body,
data: normalize(ctx.response.body.data),
};
return;
}
// GraphQL Response for Apollo Codegen script
if (
ctx.url.startsWith("/graphql") &&
ctx.request.headers.apollocodegen === "true"
) {
const parsedBody = JSON.parse(ctx.response.body);
parsedBody.data.__schema.types = parsedBody.data.__schema.types
.filter((x) => !x.name.endsWith("Entity"))
.filter((x) => !x.name.endsWith("EntityResponse"))
.filter((x) => !x.name.endsWith("EntityResponseCollection"))
.map((x) => {
if (x.fields == null) return x;
if (x.name == null) return x;
if (x.name === "Query" || x.name === "Mutation") {
return {
...x,
fields: x.fields.map((y) => ({
...y,
type: {
...fixTypeRefName(y.type),
},
})),
};
}
return fixTypeDef(x);
});
// Uncomment to Debug: Dump parsedBody to a file
// fs.writeFileSync("./schema.json", JSON.stringify(parsedBody, null, 2));
ctx.response.body = parsedBody;
return;
}
// GraphQL Response for Apollo Client
if (
ctx.url.startsWith("/graphql") &&
ctx.request.headers.normalize === "true"
) {
const parsedBody = JSON.parse(ctx.response.body);
if (parsedBody.data.__schema !== undefined) {
return;
}
console.log(
`API request (${ctx.url}) detected, transforming response json...`
);
ctx.response.body = {
...parsedBody.data,
data: normalize(parsedBody.data),
};
return;
}
};
module.exports = () => respond;
Apollo Codegen command
yarn apollo codegen:generate --target=typescript --tagName=gql --includes='operations/**/types.ts' --endpoint=http://localhost:1337/graphql --header='apollocodegen: true'
index.ts should contain the real query
import { gql } from '@apollo/client';
export const GET_ASSETS_QUERY = gql`
query GetAssetsQuery {
asset {
data {
attributes {
banner {
data {
attributes {
url
}
}
}
logo {
data {
attributes {
url
}
}
}
}
}
}
}
`;
export * from './__generated__/GetAssetsQuery';
types.ts the response type
import { gql } from '@apollo/client';
export const GET_ASSETS_QUERY = gql`
query GetAssetsQuery {
asset {
banner {
url
}
logo {
url
}
}
}
`;
And the return types will be generated correctly in your typescript code
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK