Skip to content

feat: add getSearchResults endpoint#233

Open
arnestaphorsius wants to merge 7 commits into
achievements-app:mainfrom
arnestaphorsius:feat/add-get-search-results
Open

feat: add getSearchResults endpoint#233
arnestaphorsius wants to merge 7 commits into
achievements-app:mainfrom
arnestaphorsius:feat/add-get-search-results

Conversation

@arnestaphorsius
Copy link
Copy Markdown

This PR adds the graphql endpoint getSearchResults to the library.

The endpoint:

  • does a broad search on the Playstation Store and returns games, add-ons, etc.
  • takes country and language code to return localized prices
  • does not require authorization

You can see the endpoint in action here: https://store.playstation.com/en-us/search/batman/1. You have to use pagination to see it (first page load is server side).

@wescopeland Sending along an Authorization header breaks the price information of this endpoint (it will be null in the response), which is why I made it optional downstream. Obviously that's the fastest way, but perhaps you prefer a separate call method to make a distinction between calls with or without authorization.

@vercel
Copy link
Copy Markdown

vercel Bot commented Feb 23, 2026

@arnestaphorsius is attempting to deploy a commit to the achievements-app Team on Vercel.

A member of the Team first needs to authorize it.

@wescopeland
Copy link
Copy Markdown
Member

Hi @arnestaphorsius! Sorry for the delay. I'll get a review in for this within 24 hours.

Copy link
Copy Markdown
Member

@wescopeland wescopeland left a comment

Choose a reason for hiding this comment

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

Thanks, there's some good stuff here. I have some feedback that's mostly minor.

nextCursor
};

url.searchParams.set("variables", JSON.stringify(variables));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

DX: variables includes undefined values. We're destructuring pageSize, pageOffset, and nextCursor from options, but when they're not provided, we're stuffing undefined into variables and shipping it as JSON.

JSON.stringify() strips undefined values automagically, so this does technically work, but it means we're relying on a serialization side effect to clean up the variables data.

I think we should be more explicit about what we send. Maybe something like:

const variables: Record<string, unknown> = {
  countryCode,
  languageCode,
  searchTerm,
  ...(pageSize !== undefined && { pageSize }),
  ...(pageOffset !== undefined && { pageOffset }),
  ...(nextCursor !== undefined && { nextCursor })
};

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Sure, let's strip them then. I don't really see a "nicer" way to handle it than what you suggested, so I'll go with that.

Comment on lines +18 to +19
* NOTE: This endpoint should be called WITHOUT authorization to receive price information.
* When called with authorization, price data may be filtered or unavailable.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

DX: This makes sense. What gives me pause is the function signature here is inconsistent with every other function in psn-api.

Every other endpoint takes authorization as the 1st param. It makes sense this one is intentionally different, but it may confuse a consumer unless they read this JSDoc. They may see:

getPurchasedGames(authorization, ...)
getRecentlyPlayedGames(authorization, ...)
getSearchResults(searchTerm, ...) // wait, what?

Since call() already handles authorization as optional, we could accept it as an optional 1st param for signature consistency. Consumers who want prices omit it, consumers who don't care pass it in. The JSDoc warning stays, but the API shape is now uniform.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Yea, consistency would be nice here.

But making the first parameter optional would force the other parameters to be optional too, and that would make the usage very confusing in my opinion. On top of that the endpoint also returns an error if you do not send a searchTerm.

I could have it as a required parameter, and simply not pass it to call(), of course explaining that in the JSDoc. WDYT?

Comment on lines +7 to +8
countryCode: string;
languageCode: string;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

DX: We should document the expected format of these values.

The Accept-Language spec uses subtags like en_US, nl-NL, etc.

What if someone passes countryCode: "US" and languageCode: "en-us"? Given there's no validation on these inputs, some sort of JSDoc here with expected format, probably via @example, would help.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good suggestion. I've added a full description of the variables in the options object with example values.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Testing: Recommend adding a test case which exercises nextCursor and pageOffset.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Done 👍

@arnestaphorsius arnestaphorsius force-pushed the feat/add-get-search-results branch from 83b0e8d to 6dbf831 Compare March 6, 2026 19:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants