Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filters implementation #33

Merged
merged 2 commits into from Oct 6, 2018
Merged

Filters implementation #33

merged 2 commits into from Oct 6, 2018

Conversation

jfthuillier
Copy link
Contributor

@jfthuillier jfthuillier commented Jun 8, 2018

In parseHydraDocumentation > addFilters
I made the choice to ignore filters with null property (PropertyFilter provides null).
Are you ok with this ?

@jfthuillier jfthuillier changed the title WIP : filters implementation Filters implementation Jun 12, 2018
let promise = fetchResource(resource.url).then(response => {
const resourceFilters = [];

if (response.filters) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (!response.filters) {
    return [];
}

// loop on filters


const resourceFilter = new Filter(property, filter.variable);

resourceFilters.push(resourceFilter);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be resourceFilters.push(new Filter(property, filter.variable))

for (const filter of response.filters) {
let property = filter.property;

// TODO : To prevent PropertyFilter, maybe should be handle specifically ?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what do you mean?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PropertyFilter provides null as property, but it can be applied to all properties. I thought i could iterate on each properties to create all filters, but this behavior could be different on another type of filter providing null as property, so i guess just skipping the filter might be what we want.

{
property: "id",
variable: "id"
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

possible to add a filter without property to test the line you commented above?

@@ -1365,7 +1365,7 @@ test("Invalid docs JSON", async () => {
});

test("Invalid entrypoint JSON", async () => {
let entrypoint = `{foo,}`;
const entrypoint = `{foo,}`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you don't need brackets, use a simple quote (') instead :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change came from #34. It has been removed.

src/Filter.js Outdated
variable: string;

/**
* @param {string} property
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Too many spaces?

import get from "lodash.get";

export default async entrypointUrl => {
return await fetchJsonLd(entrypointUrl, { items_per_page: 0 }).then(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By default, the name of this attribute in API Platform core is itemsPerPage, we should use it here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@mauchede
Copy link
Contributor

mauchede commented Jun 15, 2018

@jfthuillier: To improve readability of this PR, could you rebase your code? It should remove changes from your first PR.

@jfthuillier jfthuillier force-pushed the filters branch 3 times, most recently from 5751076 to 99d112b Compare June 15, 2018 11:26
@jfthuillier
Copy link
Contributor Author

I can't manage to squash the last merge commit with the Filters implementation 😡

@vdumontier
Copy link

Just tested and work fine for me (including api-platform/admin#100)
Needed to add authentification support for api-doc-parser (using fetch option) cause my resources endpoints are protected.
Needed to change fetchResources error to return response, to handle 401 status -> /login redirection.


const resourceFilters = [];

for (const filter of response.filters) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We usually use the functional style: response.filters.forEach()

const resourceFilters = [];

for (const filter of response.filters) {
let property = filter.property;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be const, the variable can even be removed

import fetchJsonLd from "./fetchJsonLd";
import get from "lodash.get";

export default async entrypointUrl => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resourceUrl?

src/hydra/parseHydraDocumentation.test.js Show resolved Hide resolved
src/Filter.js Outdated
/**
* @property {string} variable - The variable of this field
*/
export default class Filter {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not very confident in this structure.
Here is the OpenAPI structure for filters (they did a great job): https://swagger.io/docs/specification/describing-parameters/
And the Hydra one: http://www.hydra-cg.com/spec/latest/core/#x5-2-templated-links

To support both I suggest to rename this class Parameter with the following structure:

class Parameter {
  variable: string;
  type: string; // (an IRI)
  required: bool;
  description: string;
}

@jfthuillier jfthuillier force-pushed the filters branch 6 times, most recently from 3101b8a to 4757139 Compare June 26, 2018 13:55
}

resourceParameters.push(
new Parameter(parameter.variable, "", parameter.required, "")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dunglas : what is the type value you are expecting ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something like an XSD type?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will be the same that the range attribute of the Field

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests fixed & and attribute name changed to range

@jfthuillier jfthuillier force-pushed the filters branch 2 times, most recently from 286a937 to d77fd6a Compare June 26, 2018 16:04
const promises = [];

for (const resource of api.resources) {
let promise = fetchResource(resource.url).then(response => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let -> const


for (const resource of api.resources) {
let promise = fetchResource(resource.url).then(response => {
if (!response.parameters) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use a default value:

const resourceParameters = [];
const { parameters = {} } = response;

parameters.forEach(....);

return resourceParameters;

const resourceParameters = [];
const { parameters = {} } = response;

parameters.forEach(parameter => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You only used parameter.variable, parameter.property and parameter.required. Maybe could you use destructuring?

parameters.forEach(({ property = null, required, variable }) => {
    if (null === property) {
        return;
    }

    // ...

    resourceParameter.push(
        new Parameter(variable, range, required, "")
    );
});

let range = null;

const resourceProperty = resource.fields.find(
field => property === field.name
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

({ name }) => property === name

const resourceProperty = resource.fields.find(
field => property === field.name
);
if (resourceProperty) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const { range = null } = resource.fields.find(...) || {};

const promises = [];

for (const resource of api.resources) {
const promise = fetchResource(resource.url).then(response => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that only response.parameters is needed.

In that case:

const promise = fetchResource(resource.url).then(({ parameters = {} }) => {
    const resourceParameters = [];
    parameters.forEach(({ property = null, required, variable }) => {
        // ...
    });

    return resourceParameters;
});

return;
}

const { range = null } = resource.fields.find(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it sure to always match a field here? In my previous comment, I suggested to add a default value (|| {}) to avoid runtime errors.

status: get(response, "status")
})
)
.then(({ api, response, status }) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.then(({ api, response, status }) => (
    addParameters(api).then(api => ({ api, response, status }));
));

) {
throw new Error(
'The entrypoint definition has no "http://www.w3.org/ns/hydra/core#supportedProperty" key or it is not an array.'
return fetchEntrypointAndDocs(entrypointUrl, options)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of modifications in this file are only CS changes. Could you remove them from this PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, is it just to have visibility for your review ?
I will have to reuse yarn fix before merging, right ?

@jfthuillier
Copy link
Contributor Author

@mauchede @dunglas : not sure if you are to busy or the checks failing make you think there is still work to do. But checks are deliberatly failing because of eslint to make your review of parseHydraDocumentation.js easier, when you'll approve these changes i'll apply eslint.

@dunglas dunglas merged commit da3131b into api-platform:master Oct 6, 2018
@dunglas
Copy link
Member

dunglas commented Oct 6, 2018

Thanks @jfthuillier! Great PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants