Yep, you’re right, that is a problem. Good catch.
Sometimes I think about adding access to state
to functions in libraries but it never convinced me. I think it won’t be a good pattern. I think it’s better to pass it to the library when it’s needed.
One of the reasons is that in the future DevTools if a library mutates the state, the mutation will be attributed to the action that used the library, not to the library itself. Which in my option is correct, because gives the developer the information it needs to start debugging the problem.
A third option would be to add a headers
option to libraries.source.api.get
to make it more imperative:
const response = await libraries.source.api.get({
endpoint: "posts",
params: { slug, _embed: true, ...state.source.params },
headers: { ...myHeaders, ...state.source.headers },
});
This would mean that it’s up to the handler creator to add the headers or not.
On the other hand, I’ve been studying all the standard request headers taking into account the headers forbidden by the browsers and I could not find any other header that makes sense, including:
- The
Accept
header is often used to specify the type of content the browser will accept, but:
- It is optional. If not present, the browser will accept any type of content.
- People have control over their backends. If they create a custom endpoint, they can set
Content-Type
to text/html
for example and they don’t need the Accept
header.
- The
Content-Type
header is not useful for GET
requests because they don’t have a body.
That means that, even though I always try to propose solutions that are as wide as possible in terms of functionality, maybe it doesn’t make much sense for this particular case and it’d be better to add an auth
field instead, to make it more implicit.
So, an alternative would be to use state.source.auth
:
const state = {
source: {
auth: "Basic YWFhOmJiYg",
},
};
We should then let the handler creators decide if they want to use auth for their request or not by like this:
const response = await libraries.source.api.get({
endpoint: "posts",
params: { slug, _embed: true, ...state.source.params },
auth: state.source.auth,
});
And we can implement Michal’s suggestion to delete the state.source.auth
value in the afterSSR
action of wp-source
by default:
const actions = {
source: {
afterSSR: ({ state }) => {
delete state.source.auth;
},
},
};
And that would mean that people wanting to use the Preview in the Decoupled mode wouldn’t even have to create a package, adding the token to their frontity.settings.js
file would be enough.
const settings = {
// ...
packages: [
{
name: "@frontity/wp-source",
state: {
source: {
api: "https://wp.mydomain.com/wp-json"
auth: `Bearer ${process.env.JWT_TOKEN}`,
},
},
},
],
};
@mmczaplinski, thoughts? Should we stick to a general state.source.headers
or should we use state.source.auth
?