Skip to content

feat: queryception#15952

Draft
elliott-with-the-longest-name-on-github wants to merge 4 commits into
mainfrom
elliott/queryception-2
Draft

feat: queryception#15952
elliott-with-the-longest-name-on-github wants to merge 4 commits into
mainfrom
elliott/queryception-2

Conversation

@elliott-with-the-longest-name-on-github
Copy link
Copy Markdown
Contributor

@elliott-with-the-longest-name-on-github elliott-with-the-longest-name-on-github commented Jun 3, 2026

Allows returning query, query.live, and prerender instances from queries, commands, and forms. prerender instances can also return other prerender instances*.

This was born of frustration when working with hierarchical data. Imagine you're building out the GitHub PRs view at https://github.com/sveltejs/kit/pulls. You want to be able to fetch 25 pulls per page, which means making a batch query to the server to figure out which pulls to display. However, it would be quite useful to be able to make each row of the response a query itself -- that is, you want a get_pulls query that returns get_pull queries. This way, when you click through to a pull request, the get_pull query cache is already cached. And, crucially, you can single-flight mutate, refresh, or override (via .set) individual get_pull instances to update the individual row.

When implementing the /{repo}/pull/{number} page, you already have warm data from the get_pull cache, so depending on the performance characteristics you want for your application, you could choose whether to preload all of the pull details (like commits, comments, etc.) in get_pulls. Or you could choose to have another get_pull_details remote function to get the additional data, but you'd still be able to instantly navigate to the pull page with the basic pulls data and skeleton-load-in the get_pull_details data. It's very flexible.

Concretely, this looks like:

export const get_pull = query('unchecked', (number) => {
  return get_pull_from_api(number);
});

export const get_pulls = query('unchecked', (page) => {
  const pulls = await get_pulls_from_api(page);
  return pulls.map((pull) => ({
    key: pull.number,
    // get_pull.from is a new API to construct a query from its argument and initial data
    query: get_pull.from(pull.number, pull),
  });
});

And usage in your Svelte component looks like:

<svelte:boundary>
  <PullTable>
    {#each await get_pulls(0) as { key, query } (key)}
      {const pull = await query}
      <PullRow {pull} />
    {/each}
  </PullTable>

  {#snippet pending()}
   <SkeletonBlock />
  {/snippet}
</svelte:boundary>

You could also wrap each row in its own pending snippet if you wanted to have control over things that happen when you .refresh an individual get_pull instance.

You can also return queries from command and form responses, because why wouldn't you be able to do that!

You can also technically have recursive query responses. But... come on. Show some restraint.

TODO explain limitations with prerender
TODO add better tests

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Jun 3, 2026

🦋 Changeset detected

Latest commit: ab6a630

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@sveltejs/kit Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@svelte-docs-bot
Copy link
Copy Markdown

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