Skip to content

Conversation

torjusb
Copy link

@torjusb torjusb commented Sep 8, 2025

Description

This change allows putting query fragments into queries, and have them be resolved before the query is executed.

Given this code:

const author = defineQuery(`{
  name,
}`);

const query = defineQuery(`
  *[_type == "article"]{
    "title": coalesce(select($lang == "es" => title.es, title.en), ""),
    author->${author},
  }`);

previously, the executed query would then be:

*[_type == "article"]{
    "title": coalesce(select($lang == "es" => title.es, title.en), ""),
    author->${author},
  }

which is invalid GROQ. The changes in this PR will ensure the interpolated string is resolved before executed, so the full GROQ query which is executed is:

*[_type == "article"]{
    "title": coalesce(select($lang == "es" => title.es, title.en), ""),
    author->{
     name,
    },
  }

The query will also resolve if the author is imported from a different file.

What to review

This PR changes to using ts-morph to extract, parse and resolve the queries. Most of the logic is the resolve-queries.ts file.

Testing

There didn't seem to be much of a testing facility set up for this project. But happy to try to set something up if desirable.

This introduces using ts-morph to parse and resolve extracted queries
from defineQuery() calls and groq`` template literals.
This allows for resolving queries which uses string interpolation
to embed fragments in the query.

Example:

  const subQuery = defineQuery(`{ name }`)

  const query = defineQuery(`{
    _id,
    author->${subQuery}
  }`)

will resolve to:

  {
    _id,
    author->{ name }
  }

Since we leverage ts-morph to parse the extracted code, this will also
work if `subQuery` is defined in a separate file.

To use ts-morph we need to create a Project - this is stored in a cache
based on the ts-config file to ensure that we don't need to do all the
parsing on each iteration. The extractAllDefineQuery() will get the
source and path of the current file, and ensure that it is always up to
date in the Project.

We implement some logic to resolve the nearest ts config file from the
current file. This should hopefully ensure everything resolves correctly
in a mono repo.

I had to update Prettier to get it working on my machine.
Copy link

Copy link

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
[email protected] has Obfuscated code.

Confidence: 0.94

Location: Package overview

From: package-lock.jsonnpm/[email protected]npm/[email protected]

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at [email protected].

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/[email protected]. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

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.

1 participant