Skip to content

Commit ec6e1cb

Browse files
committed
feat: add ESLint configuration and update dependencies
- Introduced a new ESLint configuration file to enforce coding standards. - Updated various package dependencies to their latest versions, including Qwik and TypeScript-related packages. - Enhanced .gitignore to include pnpm store and ensure cleaner builds. - Added documentation for Qwik core development practices and patterns. - Refactored components to utilize new icon imports and improved state management in the Devtools UI.
1 parent 39ed282 commit ec6e1cb

File tree

29 files changed

+5259
-4963
lines changed

29 files changed

+5259
-4963
lines changed

.cursor/skills/qwik/AGENTS.md

Lines changed: 746 additions & 0 deletions
Large diffs are not rendered by default.

.cursor/skills/qwik/SKILL.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
---
2+
name: qwik
3+
description: Workflow and pitfall checklist for Qwik core development (packages/qwik). Use when the user mentions Qwik, packages/qwik, Signal/AsyncSignalImpl, reactive-primitives, serialization/hydration (serialize/inflate), or cursor queue; it enforces running unit tests immediately after any implementation change, following signal/async-signal patterns, and running build/E2E/API validations before finishing.
4+
---
5+
6+
# Qwik Core Development Guide (Skill)
7+
8+
## Scope
9+
- Only for the Qwik core package: `packages/qwik` (especially `src/core/**`, `reactive-primitives/**`).
10+
11+
## Mandatory workflow (must do)
12+
### 0. Run tests immediately after any implementation change
13+
- After changing any implementation file, **immediately** run the relevant unit tests (don’t wait for CI, don’t wait to be asked):
14+
15+
```bash
16+
pnpm vitest run <test-file-path>
17+
```
18+
19+
- Typical example (signals):
20+
21+
```bash
22+
pnpm vitest run packages/qwik/src/core/reactive-primitives/impl/signal.unit.tsx
23+
```
24+
25+
- If tests fail, fix and re-run until they pass. Only then proceed with anything else (docs/refactors/cleanup).
26+
27+
## Implementation essentials (high-signal rules)
28+
- **Constructor parameter plumbing**: when adding params to signal/async-signal constructors, keep parent calls and parameter order stable; extract options in factories (e.g. `signal-api.ts`) before passing into constructors.
29+
- **AsyncSignal promise branches**: `.then()` and `.catch()` must be symmetric (same side-effects / scheduling). Errors should not “stop” polling.
30+
- **invalidate cleanup order**: clear timeouts/resources first, then clear cached data and call `super.invalidate()` to avoid leaks and test interference.
31+
- **SSR vs browser**: guard browser APIs (`setTimeout`, etc.) with `isBrowser`; still persist configuration on the instance for hydration.
32+
- **Subscriber checks**: async signals may have separate subscribers for `.value`, `.loading`, and `.error`; any “has subscribers” logic must consider all three sets.
33+
- **Serialization/hydration alignment**: when adding new serializable fields, array positions in `serialize.ts` and `inflate.ts` must match exactly.
34+
35+
## Testing conventions (high-signal rules)
36+
- Prefer `$()` for QRLs; avoid manually constructing QRLs (e.g. `inlinedQrl()`).
37+
- In `$()` tests that need mutable state, use object refs (e.g. `{ count: 0 }`). Don’t capture and mutate outer-scope primitives (can trigger “Assignment to constant variable”).
38+
- First computation may “throw a promise” to trigger suspense behavior; in tests, use helpers like `retryOnPromise()` / `withContainer()` around first reads/creation.
39+
40+
## Required validations before finishing
41+
When the task is complete / ready to ship (especially core changes), run as appropriate:
42+
43+
```bash
44+
pnpm build --qwik --qwikrouter --dev
45+
pnpm run test.e2e.chromium
46+
pnpm api.update
47+
```
48+
49+
## Detailed reference
50+
- For deeper patterns, examples, pitfall tables, and full checklists, read `[AGENTS.md](AGENTS.md)` in the same folder.
51+

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,5 @@ testem.log
6363
# System Files
6464
.DS_Store
6565
Thumbs.db
66-
.vite-inspect
66+
.vite-inspect
67+
.pnpm-store/*

eslint.config.cjs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
const tsParser = require('@typescript-eslint/parser');
2+
const tsPlugin = require('@typescript-eslint/eslint-plugin');
3+
const qwikPlugin = require('eslint-plugin-qwik');
4+
5+
/** @type {import('eslint').Linter.FlatConfig[]} */
6+
module.exports = [
7+
{
8+
ignores: [
9+
'**/dist/**',
10+
'**/lib/**',
11+
'**/lib-types/**',
12+
'**/.cache/**',
13+
'**/.rollup.cache/**',
14+
'**/node_modules/**',
15+
],
16+
},
17+
{
18+
files: ['**/*.{ts,tsx,js,jsx,mts,cts,cjs,mjs}'],
19+
languageOptions: {
20+
ecmaVersion: 2021,
21+
sourceType: 'module',
22+
parser: tsParser,
23+
parserOptions: {
24+
ecmaFeatures: { jsx: true },
25+
},
26+
},
27+
plugins: {
28+
'@typescript-eslint': tsPlugin,
29+
qwik: qwikPlugin,
30+
},
31+
rules: {
32+
// Keep the intent of the legacy configs with minimal friction.
33+
'no-console': 'off',
34+
'no-case-declarations': 'off',
35+
36+
'no-unused-vars': 'off',
37+
'@typescript-eslint/no-unused-vars': ['error'],
38+
39+
'@typescript-eslint/no-explicit-any': 'off',
40+
'@typescript-eslint/explicit-module-boundary-types': 'off',
41+
'@typescript-eslint/no-non-null-assertion': 'off',
42+
'@typescript-eslint/ban-ts-comment': 'off',
43+
},
44+
},
45+
];
46+

package.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@
1010
"release.pkg-pr-new": "cd packages/devtools && pnpm dlx pkg-pr-new publish"
1111
},
1212
"devDependencies": {
13-
"@changesets/cli": "^2.27.11",
14-
"@changesets/get-github-info": "^0.6.0",
15-
"@changesets/types": "^6.0.0",
16-
"@types/node": "^22.10.5",
17-
"tsdown": "^0.9.6",
18-
"tsx": "^4.19.2",
19-
"vitest": "^3.2.4",
13+
"@changesets/cli": "^2.30.0",
14+
"@changesets/get-github-info": "^0.8.0",
15+
"@changesets/types": "^6.1.0",
16+
"@types/debug": "4.1.12",
17+
"@types/node": "^25.5.0",
2018
"debug": "4.4.3",
21-
"@types/debug": "4.1.12"
19+
"tsdown": "^0.21.4",
20+
"tsx": "^4.21.0",
21+
"vitest": "^4.1.0"
2222
},
2323
"private": true,
2424
"keywords": [

packages/devtools/package.json

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,29 +24,28 @@
2424
"README.md"
2525
],
2626
"peerDependencies": {
27-
"@qwik.dev/core": "2.0.0-beta.15",
28-
"@qwik.dev/router": "2.0.0-beta.15",
29-
"vite": "7.1.3",
30-
"@tailwindcss/postcss": "^4.1.14",
31-
"@tailwindcss/vite": "^4.1.14",
32-
"tailwindcss": "^4.1.14"
27+
"@qwik.dev/core": "^2.0.0-beta.29",
28+
"@qwik.dev/router": "^2.0.0-beta.29",
29+
"@tailwindcss/postcss": "^4.2.1",
30+
"@tailwindcss/vite": "^4.2.1",
31+
"tailwindcss": "^4.2.1",
32+
"vite": "8.0.0"
3333
},
3434
"dependencies": {
35-
"@qwikest/icons": "^0.0.13",
36-
"birpc": "^0.2.19",
35+
"birpc": "^4.0.0",
3736
"dree": "^5.1.5",
38-
"oxc-parser": "^0.82.1",
39-
"superjson": "^2.2.2",
40-
"vite-hot-client": "^0.2.4",
41-
"vite-plugin-inspect": "^11.0.0"
37+
"oxc-parser": "^0.120.0",
38+
"superjson": "^2.2.6",
39+
"vite-hot-client": "^2.1.0",
40+
"vite-plugin-inspect": "^11.3.3"
4241
},
4342
"type": "module",
4443
"devDependencies": {
45-
"tsx": "^4.19.2",
46-
"@types/node": "^22.10.5",
47-
"@changesets/cli": "^2.27.11",
48-
"@changesets/get-github-info": "^0.6.0",
49-
"@changesets/types": "^6.0.0"
44+
"@changesets/cli": "^2.30.0",
45+
"@changesets/get-github-info": "^0.8.0",
46+
"@changesets/types": "^6.1.0",
47+
"@types/node": "^25.5.0",
48+
"tsx": "^4.21.0"
5049
},
5150
"private": false,
5251
"publishConfig": {

packages/kit/package.json

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,24 @@
1717
"build": "tsdown "
1818
},
1919
"dependencies": {
20-
"birpc": "^0.2.19",
20+
"birpc": "^4.0.0",
2121
"dree": "^5.1.5",
22-
"superjson": "^2.2.2"
22+
"superjson": "^2.2.6"
2323
},
2424
"peerDependencies": {
25-
"vite": "^7.1.3"
25+
"vite": "8.0.0"
2626
},
2727
"devDependencies": {
28-
"@types/eslint": "8.56.10",
29-
"@types/node": "20.14.11",
30-
"@typescript-eslint/eslint-plugin": "7.16.1",
31-
"@typescript-eslint/parser": "7.16.1",
32-
"cpy-cli": "^5.0.0",
33-
"eslint": "8.57.0",
34-
"eslint-plugin-qwik": "2.0.0-beta.15",
35-
"np": "^8.0.4",
36-
"prettier": "3.3.3",
37-
"typescript": "5.4.5",
38-
"vite-tsconfig-paths": "^4.2.1"
28+
"@types/eslint": "9.6.1",
29+
"@types/node": "25.5.0",
30+
"@typescript-eslint/eslint-plugin": "8.57.1",
31+
"@typescript-eslint/parser": "8.57.1",
32+
"cpy-cli": "^7.0.0",
33+
"eslint": "10.0.3",
34+
"eslint-plugin-qwik": "2.0.0-beta.29",
35+
"np": "^11.0.2",
36+
"prettier": "3.6.2",
37+
"typescript": "5.9.3",
38+
"vite-tsconfig-paths": "^6.1.1"
3939
}
4040
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"type": "module"
3+
}

packages/playgrounds/package.json

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,17 @@
2929
"devDependencies": {
3030
"@devtools/plugin": "workspace:*",
3131
"@devtools/ui": "workspace:*",
32-
"@qwik.dev/core": "2.0.0-beta.15",
33-
"@qwik.dev/router": "2.0.0-beta.15",
34-
"@types/eslint": "8.56.10",
35-
"@types/node": "20.14.11",
36-
"@typescript-eslint/eslint-plugin": "7.16.1",
37-
"@typescript-eslint/parser": "7.16.1",
38-
"eslint": "8.57.0",
39-
"eslint-plugin-qwik": "2.0.0-beta.15",
40-
"prettier": "3.3.3",
41-
"typescript": "5.4.5",
42-
"vite": "7.1.3",
43-
"vite-tsconfig-paths": "^4.2.1"
32+
"@qwik.dev/core": "2.0.0-beta.29",
33+
"@qwik.dev/router": "2.0.0-beta.29",
34+
"@types/eslint": "9.6.1",
35+
"@types/node": "25.5.0",
36+
"@typescript-eslint/eslint-plugin": "8.57.1",
37+
"@typescript-eslint/parser": "8.57.1",
38+
"eslint": "10.0.3",
39+
"eslint-plugin-qwik": "2.0.0-beta.29",
40+
"prettier": "3.8.1",
41+
"typescript": "5.9.3",
42+
"vite": "8.0.0",
43+
"vite-tsconfig-paths": "^6.1.1"
4444
}
4545
}

packages/playgrounds/src/components/Button/Button.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
useStylesScoped$,
1616
createContextId,
1717
Resource,
18-
useAsyncComputed$,
18+
useAsync$,
1919
useSerializer$,
2020
useConstant,
2121
useOn,
@@ -70,7 +70,6 @@ export default component$<ButtonProps>((props) => {
7070
signal.value = '33333';
7171
});
7272

73-
// eslint-disable-next-line qwik/no-use-visible-task
7473
useVisibleTask$(({ track }) => {
7574
track(() => store.count);
7675
signal.value = '2227';
@@ -89,8 +88,9 @@ export default component$<ButtonProps>((props) => {
8988
}
9089
});
9190

92-
const asyncComputedValue = useAsyncComputed$(({ track }) =>
93-
Promise.resolve(track(signal) + 3),
91+
const asyncComputedValue = useAsync$(
92+
async ({ track }) => Promise.resolve(track(signal) + 3),
93+
{ initial: '' },
9494
);
9595

9696
useContextProvider(ButtonContext, {

0 commit comments

Comments
 (0)