feat(utils): Provide an utils that allows to convert an array of fields to a complete remote query object (#5161)

**What**
For simplicity and compatibility with the front, the fields are stored as an array of strings containing the list of fields that should be selected by a query. In order to reduce the delta between this object shape and what is expected by the remoteQuery when passing an object, we built util to make the translation from fields to config.

This will allow us to update the endpoint fields to specify what exactly needs to be selected and based on that we will be able to build the remote query object. Furthermore, it will allow us to drop back the functionality of custom fields and relations. we will still have to take into account the limit constraint of an url size including the parameters if a user want to select everything from a relation. In that case, we might maybe think about handling this case once the modules will export all available relations and fields so that the remote joiner would be able to pass them all automatically if the relation is present but a `*` is passed or no values in the fields during the translation with the util. But this is something we can come up in a separate iteration
This commit is contained in:
Adrien de Peretti
2023-09-21 12:50:28 +02:00
committed by GitHub
parent f5274c5b4f
commit cc4169a94c
3 changed files with 210 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
---
"@medusajs/utils": patch
---
feat(utils): Provide an utils that allows to convert an array of fields to a complete remote query object

View File

@@ -0,0 +1,81 @@
import { stringToRemoteQueryObject } from "../string-to-remote-query-object"
const fields = [
"id",
"created_at",
"updated_at",
"deleted_at",
"url",
"metadata",
"tags.id",
"tags.created_at",
"tags.updated_at",
"tags.deleted_at",
"tags.value",
"options.id",
"options.created_at",
"options.updated_at",
"options.deleted_at",
"options.title",
"options.product_id",
"options.metadata",
"options.values.id",
"options.values.created_at",
"options.values.updated_at",
"options.values.deleted_at",
"options.values.value",
"options.values.option_id",
"options.values.variant_id",
"options.values.metadata",
]
describe("stringToRemoteQueryObject", function () {
it("should return a remote query object", function () {
const output = stringToRemoteQueryObject({
entryPoint: "product",
variables: {},
fields,
})
expect(output).toEqual({
product: {
__args: {},
fields: [
"id",
"created_at",
"updated_at",
"deleted_at",
"url",
"metadata",
],
tags: {
fields: ["id", "created_at", "updated_at", "deleted_at", "value"],
},
options: {
fields: [
"id",
"created_at",
"updated_at",
"deleted_at",
"title",
"product_id",
"metadata",
],
values: {
fields: [
"id",
"created_at",
"updated_at",
"deleted_at",
"value",
"option_id",
"variant_id",
"metadata",
],
},
},
},
})
})
})

View File

@@ -0,0 +1,124 @@
/**
* Convert a string fields array to a remote query object
* @param entryPoint
* @param variables
* @param fields
*
* @example
* const fields = [
* "id",
* "created_at",
* "updated_at",
* "deleted_at",
* "url",
* "metadata",
* "tags.id",
* "tags.created_at",
* "tags.updated_at",
* "tags.deleted_at",
* "tags.value",
* "options.id",
* "options.created_at",
* "options.updated_at",
* "options.deleted_at",
* "options.title",
* "options.product_id",
* "options.metadata",
* "options.values.id",
* "options.values.created_at",
* "options.values.updated_at",
* "options.values.deleted_at",
* "options.values.value",
* "options.values.option_id",
* "options.values.variant_id",
* "options.values.metadata",
* ]
*
* const remoteQueryObject = stringToRemoteQueryObject({
* entryPoint: "product",
* variables: {},
* fields,
* })
*
* console.log(remoteQueryObject)
* // {
* // product: {
* // __args: {},
* // fields: [
* // "id",
* // "created_at",
* // "updated_at",
* // "deleted_at",
* // "url",
* // "metadata",
* // ],
* //
* // tags: {
* // fields: ["id", "created_at", "updated_at", "deleted_at", "value"],
* // },
* //
* // options: {
* // fields: [
* // "id",
* // "created_at",
* // "updated_at",
* // "deleted_at",
* // "title",
* // "product_id",
* // "metadata",
* // ],
* // values: {
* // fields: [
* // "id",
* // "created_at",
* // "updated_at",
* // "deleted_at",
* // "value",
* // "option_id",
* // "variant_id",
* // "metadata",
* // ],
* // },
* // },
* // },
* // }
*/
export function stringToRemoteQueryObject({
entryPoint,
variables,
fields,
}: {
entryPoint: string
variables?: any
fields: string[]
}): object {
const remoteJoinerConfig: object = {
[entryPoint]: {
fields: [],
},
}
if (variables) {
remoteJoinerConfig[entryPoint]["__args"] = variables
}
for (const field of fields) {
if (!field.includes(".")) {
remoteJoinerConfig[entryPoint]["fields"].push(field)
continue
}
const fieldSegments = field.split(".")
const fieldProperty = fieldSegments.pop()
const deepConfigRef = fieldSegments.reduce((acc, curr) => {
acc[curr] ??= {}
return acc[curr]
}, remoteJoinerConfig[entryPoint])
deepConfigRef["fields"] ??= []
deepConfigRef["fields"].push(fieldProperty)
}
return remoteJoinerConfig
}