sindresorhus / alfy

Create Alfred workflows with ease
MIT License
2.63k stars 104 forks source link

Search for multiple object properties in `alfy.matches` and `alfy.inputMatches` #175

Closed kalaschnik closed 11 months ago

kalaschnik commented 11 months ago

Assume I got the follwing workflow from the README.md:

import alfy from 'alfy';

const data = await alfy.fetch('https://jsonplaceholder.typicode.com/posts');

const items = alfy.inputMatches(data, 'title').map((element) => ({
    title: element.title,
    subtitle: element.body,
    arg: element.id,
}));

alfy.output(items);

How would I search for title and the body of the response? For example, I want to be able to search for quia et suscipit and get one result (i.e., the body of first element in the array)

Is this already implemented or do I need to write my own matching function?

kalaschnik commented 11 months ago

I should have read the README.md more carefully. I made my example to work using includes as such:

import alfy from 'alfy';

const data = await alfy.fetch('https://jsonplaceholder.typicode.com/posts');

const items = alfy
  .inputMatches(
    data,
    (item, input) =>
      item.title.toLowerCase().includes(input) ||
      item.body.toLowerCase().includes(input)
  )
  .map((element) => ({
    title: element.title,
    subtitle: element.body,
    arg: element.id,
  }));

alfy.output(items);
kalaschnik commented 11 months ago

In my specific example, I noticed that some properties may contain null on which toLowerCase() would fail. It makes sense to add optional chaining for such properties

import alfy from 'alfy';

const data = await alfy.fetch('https://jsonplaceholder.typicode.com/posts');

const items = alfy
  .inputMatches(
    data,
    (item, input) =>
      item.title?.toLowerCase().includes(input) ||
      item.body?.toLowerCase().includes(input)
  )
  .map((element) => ({
    title: element.title,
    subtitle: element.body,
    arg: element.id,
  }));

alfy.output(items);
kalaschnik commented 11 months ago

Is this little example something worth adding to the README.md? Happy to propose a PR.

sindresorhus commented 11 months ago

The problem with supporting multiple properties like this:

const items = alfy.inputMatches(data, ['title', 'body']).map((element) => ({
    title: element.title,
    subtitle: element.body,
    arg: element.id,
}));

is that it's not immediately clear whether either or both properties have to match.

sindresorhus commented 11 months ago

PR welcome for adding the tip to the readme.

kalaschnik commented 11 months ago

The problem with supporting multiple properties like this:

const items = alfy.inputMatches(data, ['title', 'body']).map((element) => ({
  title: element.title,
  subtitle: element.body,
  arg: element.id,
}));

is that it's not immediately clear whether either or both properties have to match.

Good point. I was about to propose extending your dot.prop’s getProperty function, but that feels too over-engineered in the end.