Skip to content
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
fbd1ddb
feat lit-query: add initial lit-query package
Apr 14, 2026
bf31fc5
remove internal docs from initial PR
Apr 14, 2026
a322b9c
fix review issues
Apr 14, 2026
d545bf7
align scripts with monorepo Nx targets and use workspace:* for query…
Apr 14, 2026
a87a875
feat(lit-query): fix type inference and monorepo integration
Apr 14, 2026
35e3ec0
fix(lit-query): polish package validation and examples
Apr 16, 2026
3c33376
Merge branch 'main' into feature/lit-query-adapter
TkDodo Apr 18, 2026
1e98c04
ci: apply automated fixes
autofix-ci[bot] Apr 18, 2026
e93e740
lit-query: preserve provider handshake ordering in BaseController
Apr 22, 2026
2dc7432
Update .changeset/lemon-memes-divide.md
chughgaurav Apr 23, 2026
aee2808
removing prettier config from adapter, so that global config from the…
Apr 23, 2026
e976ddc
removed the package local format scripts so formatting stays centrali…
Apr 23, 2026
915ba27
removing like other adapters keep build and test:build as separate ta…
Apr 23, 2026
45acd10
Compared against the other adapters and removed the lit-query-only al…
Apr 23, 2026
d912e37
package:check has been removed. The CJS smoke check is still needed b…
Apr 23, 2026
54add68
fix(lit-query): align lit examples and integration with monorepo conv…
Apr 26, 2026
099c508
chore(lit-query): clean up stale package checks
Apr 28, 2026
a1a9868
fix(lit-query): address review feedback for lit examples and lifecycl…
Apr 29, 2026
a35543f
Merge branch 'main' into feature/lit-query-adapter
TkDodo May 3, 2026
82d5ebb
chore: fix lockfile
TkDodo May 3, 2026
8a5092f
fix: add customCondition
TkDodo May 3, 2026
6aedfba
Merge branch 'main' into feature/lit-query-adapter
TkDodo May 3, 2026
6a45489
Merge branch 'main' into feature/lit-query-adapter
TkDodo May 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/lemon-memes-divide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tanstack/lit-query': patch
Comment thread
chughgaurav marked this conversation as resolved.
Outdated
---

Add initial @tanstack/lit-query package
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ yarn.lock
build
coverage
dist
dist-cjs
dist-ts
packages/lit-query/examples/**/output/playwright/

# misc
.DS_Store
Expand Down
3 changes: 3 additions & 0 deletions knip.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
"entry": ["src/v4/**/*.cjs", "src/v5/**/*.cjs"],
"ignore": ["**/__testfixtures__/**"]
},
"packages/lit-query": {
"ignore": ["examples/**", "src/tests/**"]
},
"packages/vue-query": {
"ignoreDependencies": ["vue2", "vue2.7"]
}
Expand Down
9 changes: 9 additions & 0 deletions packages/lit-query/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
2 changes: 2 additions & 0 deletions packages/lit-query/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
docs/
src/tests/
10 changes: 10 additions & 0 deletions packages/lit-query/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
dist
dist-cjs
node_modules
coverage
.claude
.references
*.tgz
package-lock.json
examples/**/output
examples/**/dist
237 changes: 237 additions & 0 deletions packages/lit-query/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
# @tanstack/lit-query

Lit adapter for `@tanstack/query-core` using Lit reactive controllers.

## Install

```bash
npm install @tanstack/lit-query @tanstack/query-core lit @lit/context
```

For local development in this repository:

```bash
npm install
npm run build
```

## Quick Start

```ts
import { LitElement, html } from 'lit'
import { QueryClient } from '@tanstack/query-core'
import { QueryClientProvider, createQueryController } from '@tanstack/lit-query'

const client = new QueryClient({
defaultOptions: { queries: { retry: false } },
})

class AppProvider extends QueryClientProvider {
constructor() {
super()
this.client = client
}

protected override createRenderRoot(): HTMLElement | DocumentFragment {
return this
}
}
customElements.define('app-provider', AppProvider)

class UsersView extends LitElement {
private readonly users = createQueryController(this, {
queryKey: ['users'],
queryFn: async () => {
const response = await fetch('/api/users')
return response.json() as Promise<Array<{ id: string; name: string }>>
},
})

protected override createRenderRoot(): HTMLElement | DocumentFragment {
return this
}

render() {
const query = this.users()
if (query.isPending) return html`Loading...`
if (query.isError) return html`Error`
return html`<ul>
${query.data?.map((u) => html`<li>${u.name}</li>`)}
</ul>`
}
}
customElements.define('users-view', UsersView)
```

## API Surface (v1)

- `QueryClientProvider`, `useQueryClient`, `resolveQueryClient`
- `createQueryController`
- `createMutationController`
- `createInfiniteQueryController`
- `createQueriesController`
- `useIsFetching`, `useIsMutating`, `useMutationState`
- `queryOptions`, `infiniteQueryOptions`, `mutationOptions`

## Runnable Examples

This repo includes a Vite Lit example app at `examples/lit-query-e2e-app`.
The demo uses a local in-memory mock API (`src/todoApi.ts`) for deterministic behavior.

Run:

```bash
npm run example:install
npm run example:dev
```

Open:

- `http://127.0.0.1:4173/` (full integration demo)
- `http://127.0.0.1:4173/basic-query.html` (query-only runnable example)
- `http://127.0.0.1:4173/mutation.html` (mutation runnable example)

Smoke test:

```bash
npm run example:e2e
```

Focused scenarios:

```bash
npm run example:e2e:query-error
npm run example:e2e:mutation-error
npm run example:e2e:refetch-button
npm run example:e2e:lifecycle-reconnect
npm run example:e2e:lifecycle-contract
```

Run all scenarios:

```bash
npm run example:e2e:all
```

This repo also includes a pagination example app at `examples/lit-query-pagination-app`.
It demonstrates paginated queries, optimistic updates, prefetching, and error recovery against a local API.

Run:

```bash
npm run example:pagination:install
npm run example:pagination:dev
```

Smoke test:

```bash
npm run example:pagination:e2e
```

Focused scenarios:

```bash
npm run example:pagination:e2e:prefetch
npm run example:pagination:e2e:error
npm run example:pagination:e2e:mutations
npm run example:pagination:e2e:boundary
```

Run all scenarios:

```bash
npm run example:pagination:e2e:all
```

Use a different port (optional):

```bash
DEMO_PORT=4180 npm run example:dev
DEMO_PORT=4180 npm run example:e2e:all
```

E2E harness options (optional):

```bash
PW_HTTP_PROBE_TIMEOUT_MS=1000
PW_SERVER_READY_TIMEOUT_MS=30000
PW_WAIT_FOR_TEXT_TIMEOUT_MS=10000
PW_CAPTURE_FAILURE_ARTIFACTS=false
PW_ARTIFACT_DIR=output/playwright
```

This repo also includes an SSR example app at `examples/lit-query-ssr-app`.
It demonstrates explicit `QueryClient` prefetch, SSR render, dehydrate, and hydrate flow for Lit.

Run:

```bash
npm run example:ssr:install
npm run example:ssr:dev
```

Open:

- `http://127.0.0.1:4174/` (SSR example app)

Smoke test:

```bash
npm run example:ssr:e2e
```

That root smoke test runs both the default same-origin SSR flow and the documented `SSR_PUBLIC_ORIGIN=http://localhost:4174` variant.

Focused scenarios:

```bash
npm run example:ssr:e2e:error
npm run example:ssr:e2e:refreshing
```

Run the full default-origin SSR suite plus the documented public-origin smoke:

```bash
npm run example:ssr:e2e:all
```

Run either path directly (optional):

```bash
npm run example:ssr:e2e:default
npm run example:ssr:e2e:public-origin
npm run example:ssr:e2e:all:default
```

Use a different host or port (optional):

```bash
SSR_PORT=4180 npm run example:ssr:dev
SSR_PORT=4180 npm run example:ssr:e2e
SSR_HOST=0.0.0.0 npm run example:ssr:dev
npm run example:ssr:dev:public-origin
```

## Quality Gates

- Core matrix: `docs/TEST_MATRIX.md`
- Integration matrix: `docs/TEST_MATRIX_INTEGRATION.md`
- Perf matrix: `docs/TEST_MATRIX_PERF.md`
- RFC and phase log: `docs/RFC-v4.1.md`

Current local quality gate:

```bash
npm run typecheck && npm test && npm run build
```

Full local demo gate:

```bash
npm run demo:gate
```
Comment thread
coderabbitai[bot] marked this conversation as resolved.

## License

MIT
52 changes: 52 additions & 0 deletions packages/lit-query/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// @ts-check

import js from '@eslint/js'
import vitest from '@vitest/eslint-plugin'
import globals from 'globals'
import tseslint from 'typescript-eslint'

export default tseslint.config(
{
ignores: [
'dist/**',
'coverage/**',
'node_modules/**',
'.claude/**',
'.references/**',
'**/dist/**',
'**/dist-cjs/**',
'examples/**/output/**',
'**/*.d.ts',
],
},
js.configs.recommended,
...tseslint.configs.recommended,
{
files: ['**/*.{ts,js,mjs,cjs}'],
languageOptions: {
globals: {
...globals.browser,
...globals.node,
},
},
rules: {
'@typescript-eslint/no-explicit-any': 'off',
'no-console': 'off',
},
},
{
files: ['src/tests/**/*.{ts,js,mjs}', 'examples/**/e2e/**/*.{js,mjs}'],
plugins: {
vitest,
},
languageOptions: {
globals: {
...vitest.environments.env.globals,
},
},
rules: {
...vitest.configs.recommended.rules,
'vitest/expect-expect': 'off',
},
},
)
12 changes: 12 additions & 0 deletions packages/lit-query/examples/lit-query-e2e-app/basic-query.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Lit Query Basic Example</title>
</head>
<body>
<basic-query-root></basic-query-root>
<script type="module" src="/src/basic-query.ts"></script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const DEMO_PORT: number
22 changes: 22 additions & 0 deletions packages/lit-query/examples/lit-query-e2e-app/config/port.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const DEFAULT_DEMO_PORT = 4173
const envPort = process.env.DEMO_PORT

function resolvePort() {
if (!envPort) {
return DEFAULT_DEMO_PORT
}

const parsedPort = Number.parseInt(envPort, 10)
const isValidPort =
Number.isInteger(parsedPort) && parsedPort > 0 && parsedPort <= 65535

if (!isValidPort) {
throw new Error(
`Invalid DEMO_PORT "${envPort}". Expected an integer between 1 and 65535.`,
)
}

return parsedPort
}

export const DEMO_PORT = resolvePort()
Loading