mirror of
https://github.com/langgenius/dify.git
synced 2026-07-19 16:38:31 +08:00
chore: migrate linting to vp lint with ESLint fallback (#38834)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
12a2628794
commit
eb71e47f3b
3
.github/CODEOWNERS
vendored
3
.github/CODEOWNERS
vendored
@ -6,7 +6,8 @@
|
||||
|
||||
* @crazywoola @laipz8200
|
||||
|
||||
# ESLint suppression file is maintained by autofix.ci pruning.
|
||||
# Lint bulk suppression baselines.
|
||||
/oxlint-suppressions.json
|
||||
/eslint-suppressions.json
|
||||
|
||||
# CODEOWNERS file
|
||||
|
||||
12
.github/workflows/autofix.yml
vendored
12
.github/workflows/autofix.yml
vendored
@ -48,7 +48,10 @@ jobs:
|
||||
pnpm-workspace.yaml
|
||||
.nvmrc
|
||||
vite.config.ts
|
||||
lint.config.ts
|
||||
eslint.config.mjs
|
||||
oxlint-suppressions.json
|
||||
eslint-suppressions.json
|
||||
.vscode/**
|
||||
.github/workflows/autofix.yml
|
||||
.github/workflows/style.yml
|
||||
@ -166,10 +169,15 @@ jobs:
|
||||
if: github.event_name != 'merge_group' && steps.frontend-contract-changes.outputs.any_changed == 'true'
|
||||
run: pnpm --dir packages/contracts gen-api-contract
|
||||
|
||||
- name: ESLint autofix
|
||||
- name: Oxlint autofix
|
||||
if: github.event_name != 'merge_group' && steps.web-changes.outputs.any_changed == 'true'
|
||||
run: |
|
||||
vp exec eslint --fix --concurrency=2 --prune-suppressions --quiet || true
|
||||
pnpm lint:oxlint:fix --prune-suppressions --quiet || true
|
||||
|
||||
- name: ESLint fallback autofix
|
||||
if: github.event_name != 'merge_group' && steps.web-changes.outputs.any_changed == 'true'
|
||||
run: |
|
||||
pnpm lint:eslint:fix --quiet || true
|
||||
|
||||
- name: Format frontend files
|
||||
if: github.event_name != 'merge_group' && (steps.web-changes.outputs.any_changed == 'true' || steps.frontend-contract-changes.outputs.any_changed == 'true')
|
||||
|
||||
2
.github/workflows/cli-tests.yml
vendored
2
.github/workflows/cli-tests.yml
vendored
@ -46,7 +46,7 @@ jobs:
|
||||
if: matrix.os == 'depot-ubuntu-24.04'
|
||||
run: scripts/release-validate-manifest.sh
|
||||
|
||||
- name: CI pipeline (typecheck, lint, coverage, build)
|
||||
- name: CI pipeline (tree, coverage, build)
|
||||
run: pnpm run ci
|
||||
|
||||
- name: Report coverage
|
||||
|
||||
2
.github/workflows/main-ci.yml
vendored
2
.github/workflows/main-ci.yml
vendored
@ -75,7 +75,7 @@ jobs:
|
||||
- 'package.json'
|
||||
- 'pnpm-lock.yaml'
|
||||
- 'pnpm-workspace.yaml'
|
||||
- 'eslint.config.mjs'
|
||||
- 'lint.config.ts'
|
||||
- '.npmrc'
|
||||
- '.nvmrc'
|
||||
- '.github/workflows/cli-tests.yml'
|
||||
|
||||
24
.github/workflows/style.yml
vendored
24
.github/workflows/style.yml
vendored
@ -163,7 +163,10 @@ jobs:
|
||||
pnpm-workspace.yaml
|
||||
.nvmrc
|
||||
vite.config.ts
|
||||
lint.config.ts
|
||||
eslint.config.mjs
|
||||
oxlint-suppressions.json
|
||||
eslint-suppressions.json
|
||||
.vscode/**
|
||||
.github/workflows/autofix.yml
|
||||
.github/workflows/style.yml
|
||||
@ -177,30 +180,13 @@ jobs:
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
run: vp fmt --check
|
||||
|
||||
- name: Restore ESLint cache
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
id: eslint-cache-restore
|
||||
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||
with:
|
||||
path: .eslintcache
|
||||
key: ${{ runner.os }}-eslint-${{ hashFiles('pnpm-lock.yaml', 'eslint.config.mjs', 'packages/dify-ui/eslint.config.mjs', 'web/eslint.config.mjs', 'web/eslint.constants.mjs', 'web/plugins/eslint/**') }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-eslint-${{ hashFiles('pnpm-lock.yaml', 'eslint.config.mjs', 'packages/dify-ui/eslint.config.mjs', 'web/eslint.config.mjs', 'web/eslint.constants.mjs', 'web/plugins/eslint/**') }}-
|
||||
|
||||
- name: Style check
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
run: vp run lint:ci
|
||||
run: pnpm -w lint:ci
|
||||
|
||||
- name: Type check
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
run: vp run type-check
|
||||
|
||||
- name: Save ESLint cache
|
||||
if: steps.changed-files.outputs.any_changed == 'true' && success() && steps.eslint-cache-restore.outputs.cache-hit != 'true'
|
||||
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||
with:
|
||||
path: .eslintcache
|
||||
key: ${{ steps.eslint-cache-restore.outputs.cache-primary-key }}
|
||||
run: pnpm -w type-check
|
||||
|
||||
superlinter:
|
||||
name: SuperLinter
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@ -214,6 +214,7 @@ sdks/python-client/dify_client.egg-info
|
||||
api/.vscode
|
||||
# vscode Code History Extension
|
||||
.history
|
||||
.eslintcache
|
||||
|
||||
.idea/
|
||||
|
||||
@ -258,7 +259,5 @@ scripts/stress-test/reports/
|
||||
# Code Agent Folder
|
||||
.qoder/*
|
||||
.context/
|
||||
.eslintcache
|
||||
|
||||
# Vitest local reports
|
||||
web/.vitest-reports/
|
||||
|
||||
18
.vscode/settings.example.json
vendored
18
.vscode/settings.example.json
vendored
@ -28,20 +28,10 @@
|
||||
"oxc.fmt.configPath": "./vite.config.ts",
|
||||
|
||||
// Lint fix
|
||||
"eslint.useFlatConfig": true,
|
||||
"eslint.validate": ["json", "jsonc", "markdown", "yaml", "toml"],
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.oxc": "explicit",
|
||||
"source.fixAll.eslint": "explicit"
|
||||
},
|
||||
|
||||
// Enable ESLint for linted languages
|
||||
"eslint.validate": [
|
||||
"javascript",
|
||||
"javascriptreact",
|
||||
"typescript",
|
||||
"typescriptreact",
|
||||
"markdown",
|
||||
"json",
|
||||
"jsonc",
|
||||
"yaml",
|
||||
"toml"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,7 +31,7 @@ The codebase is split into:
|
||||
## Language Style
|
||||
|
||||
- **Python**: Keep type hints on functions and attributes, and implement relevant special methods (e.g., `__repr__`, `__str__`). Prefer `TypedDict` over `dict` or `Mapping` for type safety and better code documentation.
|
||||
- **TypeScript**: Use the strict config, format with `vp fmt`, run ESLint for code-quality checks and fixes, run `pnpm type-check`, and avoid `any` types.
|
||||
- **TypeScript**: Use the strict config, format with `vp fmt`, run `pnpm lint` for Oxlint code checks plus ESLint non-code checks, run `pnpm type-check`, and avoid `any` types.
|
||||
|
||||
## General Practices
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# AGENTS.md — difyctl (TypeScript CLI)
|
||||
|
||||
TypeScript port of difyctl. Stack: custom CLI framework (`src/framework/`), Node 22+, ESM, ky for HTTP, Vitest, Vite+ formatting, and ESLint via `@antfu/eslint-config`.
|
||||
TypeScript port of difyctl. Stack: custom CLI framework (`src/framework/`), Node 22+, ESM, ky for HTTP, Vitest, and Vite+ formatting and linting.
|
||||
|
||||
> Architecture patterns, scaffolding recipe, printer chain, strategy pattern, testing conventions, anti-patterns: see **[`ARD.md`]**.
|
||||
|
||||
@ -57,9 +57,9 @@ pnpm install # one-time
|
||||
pnpm dev <command> [args...] # run CLI from source (no -- separator)
|
||||
pnpm test # vitest
|
||||
pnpm test:coverage # with coverage
|
||||
pnpm type-check # tsc, no emit
|
||||
pnpm lint # eslint
|
||||
pnpm lint:fix # eslint semantic fixes
|
||||
pnpm -w type-check # repository-wide type check
|
||||
pnpm -w lint # repository-wide lint
|
||||
pnpm -w lint:fix # repository-wide lint fixes
|
||||
vp fmt # format with Oxfmt
|
||||
pnpm build # production bundle (vp pack)
|
||||
pnpm tree:gen # regenerate src/commands/tree.ts (registry)
|
||||
@ -72,7 +72,7 @@ Release binaries (5 platform targets, Bun-compiled) are produced by `pnpm build:
|
||||
|
||||
- Behavior tests run against real Hono mock at `test/fixtures/dify-mock/`. No `nock`, `msw`, or `fetchMock` — every test exercises real HTTP.
|
||||
- Test files co-located: `foo.test.ts` next to `foo.ts`.
|
||||
- Type-check, lint, full test suite must be green before any commit.
|
||||
- Repository-wide type-check and lint, plus the full test suite, must be green before any commit.
|
||||
|
||||
## Spec docs (`docs/specs/`)
|
||||
|
||||
@ -91,7 +91,7 @@ Behavior contracts. Living tree — amended in place, no version subfolders.
|
||||
Do not modify in passing:
|
||||
|
||||
- `test/fixtures/dify-mock/` public surface (endpoints, JSON shapes, status codes, scenario names) — that's the dify-api contract.
|
||||
- `bin/`, `scripts/`, `Makefile`, `eslint.config.js`, `tsconfig*.json`, `package.json` (unless the change is required by the task).
|
||||
- `bin/`, `scripts/`, `Makefile`, `lint.config.ts`, `tsconfig*.json`, `package.json` (unless the change is required by the task).
|
||||
|
||||
## Commits
|
||||
|
||||
|
||||
30
cli/ARD.md
30
cli/ARD.md
@ -301,19 +301,19 @@ expect(JSON.parse(out).workspaces).toHaveLength(2)
|
||||
|
||||
## Scripts
|
||||
|
||||
| Command | When to run |
|
||||
| ----------------------- | -------------------------------------------------- |
|
||||
| `pnpm dev <cmd> [args]` | Run CLI from source during dev |
|
||||
| `pnpm test` | Full vitest suite — run before every commit |
|
||||
| `pnpm test:coverage` | Coverage report |
|
||||
| `pnpm type-check` | `tsc --noEmit` — catches type errors without build |
|
||||
| `pnpm lint` | ESLint check |
|
||||
| `pnpm lint:fix` | ESLint code-quality fixes |
|
||||
| `vp fmt` | Oxfmt formatting and import sorting |
|
||||
| `pnpm build` | Production bundle (`vp pack`) |
|
||||
| `pnpm tree:gen` | Regenerate `src/commands/tree.ts` (registry) |
|
||||
| `pnpm tree:check` | Verify `tree.ts` matches the filesystem |
|
||||
| `pnpm build:bin` | Cross-compile standalone binaries via Bun (CI) |
|
||||
| Command | When to run |
|
||||
| ----------------------- | ---------------------------------------------- |
|
||||
| `pnpm dev <cmd> [args]` | Run CLI from source during dev |
|
||||
| `pnpm test` | Full vitest suite — run before every commit |
|
||||
| `pnpm test:coverage` | Coverage report |
|
||||
| `pnpm -w type-check` | Repository-wide TypeScript type check |
|
||||
| `pnpm -w lint` | Repository-wide Oxlint and ESLint checks |
|
||||
| `pnpm -w lint:fix` | Repository-wide Oxlint and ESLint fixes |
|
||||
| `vp fmt` | Oxfmt formatting and import sorting |
|
||||
| `pnpm build` | Production bundle (`vp pack`) |
|
||||
| `pnpm tree:gen` | Regenerate `src/commands/tree.ts` (registry) |
|
||||
| `pnpm tree:check` | Verify `tree.ts` matches the filesystem |
|
||||
| `pnpm build:bin` | Cross-compile standalone binaries via Bun (CI) |
|
||||
|
||||
**`pnpm tree:gen` rule:** run after adding, removing, renaming any command. The generated `tree.ts` is the runtime command registry — stale tree causes commands to be invisible at runtime. (Runs implicitly via `prebuild`/`predev`/`pretest`.)
|
||||
|
||||
@ -323,7 +323,7 @@ expect(JSON.parse(out).workspaces).toHaveLength(2)
|
||||
|
||||
## Lint rules that catch contributors
|
||||
|
||||
Repo runs `@antfu/eslint-config` for code-quality rules and Vite+ Oxfmt for formatting.
|
||||
The repository runs Vite+ Oxlint as the primary code-quality linter, an explicit ESLint config for unsupported cases, and Vite+ Oxfmt for formatting. The fallback config does not depend on the Antfu ESLint config.
|
||||
|
||||
| Rule | What it catches |
|
||||
| ---------------------------------- | -------------------------------------------------- |
|
||||
@ -333,7 +333,7 @@ Repo runs `@antfu/eslint-config` for code-quality rules and Vite+ Oxfmt for form
|
||||
| `unicorn/no-new-array` | Use `Array.from({ length: n })` not `new Array(n)` |
|
||||
| `noUncheckedIndexedAccess` (tsc) | `arr[i]` is `T \| undefined`; guard before use |
|
||||
|
||||
Run `pnpm lint:fix` for ESLint fixes, then `vp fmt` so Oxfmt produces the final layout.
|
||||
Run `pnpm -w lint:fix` for Oxlint and ESLint fixes, then `vp fmt` so Oxfmt produces the final layout.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@ -1,100 +0,0 @@
|
||||
// @ts-check
|
||||
|
||||
import antfu, { GLOB_MARKDOWN } from '@antfu/eslint-config'
|
||||
import md from 'eslint-markdown'
|
||||
import markdownPreferences from 'eslint-plugin-markdown-preferences'
|
||||
|
||||
export default antfu(
|
||||
{
|
||||
stylistic: false,
|
||||
perfectionist: {
|
||||
overrides: {
|
||||
'perfectionist/sort-imports': 'off',
|
||||
},
|
||||
},
|
||||
jsonc: {
|
||||
overrides: {
|
||||
'jsonc/space-unary-ops': 'off',
|
||||
},
|
||||
},
|
||||
yaml: {
|
||||
overrides: {
|
||||
'yaml/block-mapping': 'off',
|
||||
'yaml/block-sequence': 'off',
|
||||
'yaml/plain-scalar': 'off',
|
||||
},
|
||||
},
|
||||
toml: {
|
||||
overrides: {
|
||||
'toml/comma-style': 'off',
|
||||
'toml/no-space-dots': 'off',
|
||||
},
|
||||
},
|
||||
ignores: (original) => ['context/**', 'docs/**', 'dist/**', 'coverage/**', ...original],
|
||||
typescript: {
|
||||
overrides: {
|
||||
'ts/consistent-type-definitions': ['error', 'type'],
|
||||
'ts/no-explicit-any': 'error',
|
||||
'ts/no-redeclare': 'off',
|
||||
},
|
||||
erasableOnly: true,
|
||||
},
|
||||
test: {
|
||||
overrides: {
|
||||
'test/prefer-lowercase-title': 'off',
|
||||
},
|
||||
},
|
||||
e18e: false,
|
||||
},
|
||||
{
|
||||
files: [GLOB_MARKDOWN],
|
||||
plugins: {
|
||||
md,
|
||||
'markdown-preferences': markdownPreferences,
|
||||
},
|
||||
rules: {
|
||||
'md/no-url-trailing-slash': 'error',
|
||||
'markdown-preferences/definitions-last': 'error',
|
||||
'markdown-preferences/prefer-link-reference-definitions': [
|
||||
'error',
|
||||
{
|
||||
minLinks: 1,
|
||||
},
|
||||
],
|
||||
'markdown-preferences/sort-definitions': 'error',
|
||||
},
|
||||
},
|
||||
{
|
||||
rules: {
|
||||
'node/prefer-global/process': 'off',
|
||||
'unicorn/number-literal-case': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['bin/**'],
|
||||
rules: {
|
||||
'antfu/no-top-level-await': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['src/**/*.ts'],
|
||||
rules: {
|
||||
'no-restricted-imports': [
|
||||
'error',
|
||||
{
|
||||
patterns: [
|
||||
{
|
||||
group: ['../**', './*/**', '..'],
|
||||
message:
|
||||
'Use the @/ (or @test/) alias for parent-directory or nested relative imports; keep ./ only for same-folder siblings.',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
).override('antfu/sort/package-json', {
|
||||
rules: {
|
||||
'jsonc/sort-keys': 'off',
|
||||
},
|
||||
})
|
||||
@ -23,15 +23,13 @@
|
||||
"test:e2e": "vp test --config vitest.e2e.config.ts",
|
||||
"test:e2e:smoke": "vp test --config vitest.e2e.config.ts --testNamePattern \"\\[P0\\]\"",
|
||||
"test:e2e:local": "DIFY_E2E_MODE=local vp test --config vitest.e2e.config.ts",
|
||||
"lint": "eslint",
|
||||
"lint:fix": "eslint --fix",
|
||||
"type-check": "tsc",
|
||||
"tree:gen": "bun scripts/generate-command-tree.ts",
|
||||
"tree:check": "bun scripts/generate-command-tree.ts --check",
|
||||
"prebuild": "pnpm tree:gen",
|
||||
"predev": "pnpm tree:gen",
|
||||
"pretest": "pnpm tree:gen",
|
||||
"ci": "pnpm tree:check && pnpm type-check && pnpm lint && pnpm test:coverage && pnpm build",
|
||||
"ci": "pnpm tree:check && pnpm test:coverage && pnpm build",
|
||||
"clean": "rm -rf dist node_modules/.cache",
|
||||
"version:info": "bun scripts/print-buildinfo.ts",
|
||||
"build:bin": "scripts/release-build.sh"
|
||||
@ -60,7 +58,6 @@
|
||||
"@types/node": "catalog:",
|
||||
"@typescript/native": "catalog:",
|
||||
"@vitest/coverage-v8": "catalog:",
|
||||
"eslint": "catalog:",
|
||||
"hono": "catalog:",
|
||||
"typescript": "catalog:",
|
||||
"vite": "catalog:",
|
||||
|
||||
@ -26,7 +26,7 @@ function assetVersion(name: string, target: string): string {
|
||||
// offline. Routes by URL; release bodies come from env (TAG_<tag-with-._->_>),
|
||||
// the latest release from LATEST_JSON, the listing from LIST_JSON. A missing
|
||||
// fixture returns 22 to mimic `curl -f` on a 4xx.
|
||||
/* eslint-disable no-template-curly-in-string -- shell parameter expansions, not JS template literals */
|
||||
/* oxlint-disable no-template-curly-in-string -- shell parameter expansions, not JS template literals */
|
||||
const FETCH_STUB = [
|
||||
'fetch_json() {',
|
||||
' case "$1" in',
|
||||
@ -42,7 +42,7 @@ const FETCH_STUB = [
|
||||
' esac',
|
||||
'}',
|
||||
].join('\n')
|
||||
/* eslint-enable no-template-curly-in-string */
|
||||
/* oxlint-enable no-template-curly-in-string */
|
||||
|
||||
function runLib(
|
||||
program: string,
|
||||
|
||||
@ -241,7 +241,7 @@ describe('run() catch routing', () => {
|
||||
it('wraps a non-Error throw via String() coercion into unknown form', async () => {
|
||||
class Throwing extends Command {
|
||||
async run(_argv: string[]) {
|
||||
// eslint-disable-next-line no-throw-literal
|
||||
// oxlint-disable-next-line no-throw-literal
|
||||
throw 'plain string'
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
*/
|
||||
|
||||
import type { AuthFixture } from '../../helpers/cli.js'
|
||||
import { afterEach, beforeEach, describe, expect, it, inject } from 'vitest'
|
||||
import { afterEach, beforeEach, describe, expect, inject, it } from 'vitest'
|
||||
import {
|
||||
assertErrorEnvelope,
|
||||
assertExitCode,
|
||||
@ -39,7 +39,7 @@ import {
|
||||
assertPipeFriendlyJson,
|
||||
} from '../../helpers/assert.js'
|
||||
import { withAuthFixture, withTempConfig } from '../../helpers/cli.js'
|
||||
import { loadE2EEnv, resolveEnv } from '../../setup/env.js'
|
||||
import { resolveEnv } from '../../setup/env.js'
|
||||
|
||||
// @ts-expect-error — see test/e2e/helpers/vitest-context.ts for explanation
|
||||
const caps = inject('e2eCapabilities') as import('../../setup/env.js').E2ECapabilities
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
*/
|
||||
|
||||
import type { AuthFixture } from '../../helpers/cli.js'
|
||||
import { afterEach, beforeEach, describe, expect, it, inject } from 'vitest'
|
||||
import { afterEach, beforeEach, describe, expect, inject, it } from 'vitest'
|
||||
import { assertExitCode, assertNoAnsi } from '../../helpers/assert.js'
|
||||
import { withAuthFixture } from '../../helpers/cli.js'
|
||||
import { resolveEnv } from '../../setup/env.js'
|
||||
@ -147,7 +147,7 @@ describe('E2E / table output — header and column format (spec 5.1–5.19)', ()
|
||||
assertExitCode(result, 0)
|
||||
// No NUL, BEL, BS, VT, FF, SO–US, DEL bytes that would corrupt a pipe
|
||||
// eslint-disable-next-line no-control-regex
|
||||
expect(result.stdout).not.toMatch(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/)
|
||||
expect(result.stdout).not.toMatch(/[\x00-\x08\v\f\x0E-\x1F\x7F]/)
|
||||
})
|
||||
|
||||
it('[P0] 5.16 default table output written to a file contains no control characters', async () => {
|
||||
@ -156,7 +156,7 @@ describe('E2E / table output — header and column format (spec 5.1–5.19)', ()
|
||||
assertExitCode(result, 0)
|
||||
assertNoAnsi(result.stdout, 'stdout')
|
||||
// eslint-disable-next-line no-control-regex
|
||||
expect(result.stdout).not.toMatch(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/)
|
||||
expect(result.stdout).not.toMatch(/[\x00-\x08\v\f\x0E-\x1F\x7F]/)
|
||||
})
|
||||
|
||||
// ── 5.25 — Performance ────────────────────────────────────────────────────
|
||||
|
||||
@ -1,82 +1,410 @@
|
||||
// @ts-check
|
||||
|
||||
import antfu, { GLOB_MARKDOWN } from '@antfu/eslint-config'
|
||||
import markdown from '@eslint/markdown'
|
||||
import md from 'eslint-markdown'
|
||||
import hyoban from 'eslint-plugin-hyoban'
|
||||
import jsonc from 'eslint-plugin-jsonc'
|
||||
import markdownPreferences from 'eslint-plugin-markdown-preferences'
|
||||
import pnpm from 'eslint-plugin-pnpm'
|
||||
import toml from 'eslint-plugin-toml'
|
||||
import yml from 'eslint-plugin-yml'
|
||||
import { defineConfig, globalIgnores } from 'eslint/config'
|
||||
import dify from './web/plugins/eslint/index.js'
|
||||
|
||||
const GENERATED_IGNORES = [
|
||||
'**/storybook-static/',
|
||||
'**/.next/',
|
||||
'**/.vinext/',
|
||||
'web/next/',
|
||||
'web/next-env.d.ts',
|
||||
'**/dist/',
|
||||
'**/coverage/',
|
||||
'e2e/.auth/',
|
||||
'e2e/cucumber-report/',
|
||||
const codeFiles = '**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}'
|
||||
|
||||
/**
|
||||
* Migration tradeoff: ESLint is intentionally restricted to non-code files.
|
||||
*
|
||||
* Disabled code-only checks:
|
||||
* - Core: `no-control-regex`, `no-octal`, `no-octal-escape`, `no-undef-init`,
|
||||
* `no-unreachable-loop`, and `one-var`.
|
||||
* - JavaScript: `dot-notation`.
|
||||
* - Declarations: the former 223-rule snapshot and CLI `no-restricted-imports` override.
|
||||
* - Dify UI: the three `better-tailwindcss` rules and stricter unused-directive severity.
|
||||
*
|
||||
* These checks are documentation only and do not appear in the executable config below.
|
||||
*/
|
||||
|
||||
const tsconfigCompilerOptionsOrder = [
|
||||
'incremental',
|
||||
'composite',
|
||||
'tsBuildInfoFile',
|
||||
'disableSourceOfProjectReferenceRedirect',
|
||||
'disableSolutionSearching',
|
||||
'disableReferencedProjectLoad',
|
||||
'target',
|
||||
'jsx',
|
||||
'jsxFactory',
|
||||
'jsxFragmentFactory',
|
||||
'jsxImportSource',
|
||||
'lib',
|
||||
'moduleDetection',
|
||||
'noLib',
|
||||
'reactNamespace',
|
||||
'useDefineForClassFields',
|
||||
'emitDecoratorMetadata',
|
||||
'experimentalDecorators',
|
||||
'libReplacement',
|
||||
'baseUrl',
|
||||
'rootDir',
|
||||
'rootDirs',
|
||||
'customConditions',
|
||||
'module',
|
||||
'moduleResolution',
|
||||
'moduleSuffixes',
|
||||
'noResolve',
|
||||
'paths',
|
||||
'resolveJsonModule',
|
||||
'resolvePackageJsonExports',
|
||||
'resolvePackageJsonImports',
|
||||
'typeRoots',
|
||||
'types',
|
||||
'allowArbitraryExtensions',
|
||||
'allowImportingTsExtensions',
|
||||
'allowUmdGlobalAccess',
|
||||
'allowJs',
|
||||
'checkJs',
|
||||
'maxNodeModuleJsDepth',
|
||||
'strict',
|
||||
'strictBindCallApply',
|
||||
'strictFunctionTypes',
|
||||
'strictNullChecks',
|
||||
'strictPropertyInitialization',
|
||||
'allowUnreachableCode',
|
||||
'allowUnusedLabels',
|
||||
'alwaysStrict',
|
||||
'exactOptionalPropertyTypes',
|
||||
'noFallthroughCasesInSwitch',
|
||||
'noImplicitAny',
|
||||
'noImplicitOverride',
|
||||
'noImplicitReturns',
|
||||
'noImplicitThis',
|
||||
'noPropertyAccessFromIndexSignature',
|
||||
'noUncheckedIndexedAccess',
|
||||
'noUnusedLocals',
|
||||
'noUnusedParameters',
|
||||
'useUnknownInCatchVariables',
|
||||
'declaration',
|
||||
'declarationDir',
|
||||
'declarationMap',
|
||||
'downlevelIteration',
|
||||
'emitBOM',
|
||||
'emitDeclarationOnly',
|
||||
'importHelpers',
|
||||
'importsNotUsedAsValues',
|
||||
'inlineSourceMap',
|
||||
'inlineSources',
|
||||
'mapRoot',
|
||||
'newLine',
|
||||
'noEmit',
|
||||
'noEmitHelpers',
|
||||
'noEmitOnError',
|
||||
'outDir',
|
||||
'outFile',
|
||||
'preserveConstEnums',
|
||||
'preserveValueImports',
|
||||
'removeComments',
|
||||
'sourceMap',
|
||||
'sourceRoot',
|
||||
'stripInternal',
|
||||
'allowSyntheticDefaultImports',
|
||||
'esModuleInterop',
|
||||
'forceConsistentCasingInFileNames',
|
||||
'isolatedDeclarations',
|
||||
'isolatedModules',
|
||||
'preserveSymlinks',
|
||||
'verbatimModuleSyntax',
|
||||
'erasableSyntaxOnly',
|
||||
'skipDefaultLibCheck',
|
||||
'skipLibCheck',
|
||||
]
|
||||
|
||||
export default antfu(
|
||||
{
|
||||
stylistic: false,
|
||||
perfectionist: {
|
||||
overrides: {
|
||||
'perfectionist/sort-imports': 'off',
|
||||
},
|
||||
},
|
||||
jsonc: {
|
||||
overrides: {
|
||||
'jsonc/space-unary-ops': 'off',
|
||||
},
|
||||
},
|
||||
yaml: {
|
||||
overrides: {
|
||||
'yaml/block-mapping': 'off',
|
||||
'yaml/block-sequence': 'off',
|
||||
'yaml/plain-scalar': 'off',
|
||||
},
|
||||
},
|
||||
toml: {
|
||||
overrides: {
|
||||
'toml/comma-style': 'off',
|
||||
'toml/no-space-dots': 'off',
|
||||
},
|
||||
},
|
||||
ignores: (original) => [
|
||||
'**',
|
||||
'!packages/**',
|
||||
'!web/**',
|
||||
'!e2e/**',
|
||||
const pnpmWorkspaceOrder = [
|
||||
'cacheDir',
|
||||
'catalogMode',
|
||||
'cleanupUnusedCatalogs',
|
||||
'dedupeDirectDeps',
|
||||
'deployAllFiles',
|
||||
'enablePrePostScripts',
|
||||
'engineStrict',
|
||||
'extendNodePath',
|
||||
'hoist',
|
||||
'hoistPattern',
|
||||
'hoistWorkspacePackages',
|
||||
'ignoreCompatibilityDb',
|
||||
'ignoreDepScripts',
|
||||
'ignoreScripts',
|
||||
'ignoreWorkspaceRootCheck',
|
||||
'managePackageManagerVersions',
|
||||
'minimumReleaseAge',
|
||||
'minimumReleaseAgeExclude',
|
||||
'modulesDir',
|
||||
'nodeLinker',
|
||||
'nodeVersion',
|
||||
'optimisticRepeatInstall',
|
||||
'packageManagerStrict',
|
||||
'packageManagerStrictVersion',
|
||||
'preferSymlinkedExecutables',
|
||||
'preferWorkspacePackages',
|
||||
'publicHoistPattern',
|
||||
'registrySupportsTimeField',
|
||||
'requiredScripts',
|
||||
'resolutionMode',
|
||||
'savePrefix',
|
||||
'scriptShell',
|
||||
'shamefullyHoist',
|
||||
'shellEmulator',
|
||||
'stateDir',
|
||||
'supportedArchitectures',
|
||||
'symlink',
|
||||
'tag',
|
||||
'trustPolicy',
|
||||
'trustPolicyExclude',
|
||||
'updateNotifier',
|
||||
'packages',
|
||||
'overrides',
|
||||
'patchedDependencies',
|
||||
'catalog',
|
||||
'catalogs',
|
||||
'allowedDeprecatedVersions',
|
||||
'allowNonAppliedPatches',
|
||||
'configDependencies',
|
||||
'ignoredBuiltDependencies',
|
||||
'ignoredOptionalDependencies',
|
||||
'neverBuiltDependencies',
|
||||
'onlyBuiltDependencies',
|
||||
'onlyBuiltDependenciesFile',
|
||||
'packageExtensions',
|
||||
'peerDependencyRules',
|
||||
]
|
||||
|
||||
export default defineConfig([
|
||||
globalIgnores(
|
||||
[
|
||||
'**/*',
|
||||
'!cli/',
|
||||
'!cli/**/*',
|
||||
'!e2e/',
|
||||
'!e2e/**/*',
|
||||
'!packages/',
|
||||
'!packages/**/*',
|
||||
'!sdks/',
|
||||
'!sdks/nodejs-client/',
|
||||
'!sdks/nodejs-client/src/',
|
||||
'!sdks/nodejs-client/src/**/*',
|
||||
'!sdks/nodejs-client/tests/',
|
||||
'!sdks/nodejs-client/tests/**/*',
|
||||
'!web/',
|
||||
'!web/**/*',
|
||||
'!eslint.config.mjs',
|
||||
'!lint.config.ts',
|
||||
'!package.json',
|
||||
'!pnpm-workspace.yaml',
|
||||
'!vite.config.ts',
|
||||
...GENERATED_IGNORES,
|
||||
...original,
|
||||
],
|
||||
typescript: {
|
||||
overrides: {
|
||||
'ts/consistent-type-definitions': ['error', 'type'],
|
||||
'ts/no-explicit-any': 'error',
|
||||
'ts/no-redeclare': 'off',
|
||||
},
|
||||
erasableOnly: true,
|
||||
'Project lint scope',
|
||||
),
|
||||
globalIgnores([codeFiles], 'Migration tradeoff: code files are handled by Oxlint only'),
|
||||
globalIgnores(
|
||||
[
|
||||
'**/.git/**',
|
||||
'**/node_modules/**',
|
||||
'cli/context/**',
|
||||
'cli/coverage/**',
|
||||
'cli/dist/**',
|
||||
'cli/docs/**',
|
||||
'**/.next/**',
|
||||
'**/.vinext/**',
|
||||
'**/coverage/**',
|
||||
'**/dist/**',
|
||||
'**/storybook-static/**',
|
||||
'e2e/.auth/**',
|
||||
'e2e/cucumber-report/**',
|
||||
'packages/contracts/**',
|
||||
'web/next/**',
|
||||
'web/next-env.d.ts',
|
||||
'web/public/**',
|
||||
'web/types/doc-paths.ts',
|
||||
],
|
||||
'Generated and external files',
|
||||
),
|
||||
{
|
||||
linterOptions: {
|
||||
reportUnusedDisableDirectives: 'warn',
|
||||
},
|
||||
test: {
|
||||
overrides: {
|
||||
'test/prefer-lowercase-title': 'off',
|
||||
},
|
||||
},
|
||||
e18e: false,
|
||||
},
|
||||
{
|
||||
files: [GLOB_MARKDOWN],
|
||||
files: ['**/*.{json,json5,jsonc}'],
|
||||
language: 'jsonc/x',
|
||||
plugins: {
|
||||
md,
|
||||
'markdown-preferences': markdownPreferences,
|
||||
jsonc,
|
||||
},
|
||||
rules: {
|
||||
'md/no-url-trailing-slash': 'error',
|
||||
'no-unused-expressions': 'off',
|
||||
'no-unused-vars': 'off',
|
||||
strict: 'off',
|
||||
'jsonc/no-bigint-literals': 'error',
|
||||
'jsonc/no-binary-expression': 'error',
|
||||
'jsonc/no-binary-numeric-literals': 'error',
|
||||
'jsonc/no-dupe-keys': 'error',
|
||||
'jsonc/no-escape-sequence-in-identifier': 'error',
|
||||
'jsonc/no-floating-decimal': 'error',
|
||||
'jsonc/no-hexadecimal-numeric-literals': 'error',
|
||||
'jsonc/no-infinity': 'error',
|
||||
'jsonc/no-multi-str': 'error',
|
||||
'jsonc/no-nan': 'error',
|
||||
'jsonc/no-number-props': 'error',
|
||||
'jsonc/no-numeric-separators': 'error',
|
||||
'jsonc/no-octal': 'error',
|
||||
'jsonc/no-octal-escape': 'error',
|
||||
'jsonc/no-octal-numeric-literals': 'error',
|
||||
'jsonc/no-parenthesized': 'error',
|
||||
'jsonc/no-plus-sign': 'error',
|
||||
'jsonc/no-regexp-literals': 'error',
|
||||
'jsonc/no-sparse-arrays': 'error',
|
||||
'jsonc/no-template-literals': 'error',
|
||||
'jsonc/no-undefined-value': 'error',
|
||||
'jsonc/no-unicode-codepoint-escapes': 'error',
|
||||
'jsonc/no-useless-escape': 'error',
|
||||
'jsonc/valid-json-number': 'error',
|
||||
'jsonc/vue-custom-block/no-parsing-error': 'error',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/package.json'],
|
||||
rules: {
|
||||
'jsonc/sort-array-values': [
|
||||
'error',
|
||||
{
|
||||
order: { type: 'asc' },
|
||||
pathPattern: '^files$',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/[jt]sconfig.json', '**/[jt]sconfig.*.json'],
|
||||
rules: {
|
||||
'jsonc/sort-keys': [
|
||||
'error',
|
||||
{
|
||||
order: ['extends', 'compilerOptions', 'references', 'files', 'include', 'exclude'],
|
||||
pathPattern: '^$',
|
||||
},
|
||||
{
|
||||
order: tsconfigCompilerOptionsOrder,
|
||||
pathPattern: '^compilerOptions$',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['package.json', '**/package.json'],
|
||||
plugins: {
|
||||
pnpm,
|
||||
},
|
||||
rules: {
|
||||
'pnpm/json-enforce-catalog': [
|
||||
'error',
|
||||
{
|
||||
autofix: true,
|
||||
ignores: ['@types/vscode'],
|
||||
},
|
||||
],
|
||||
'pnpm/json-prefer-workspace-settings': ['error', { autofix: true }],
|
||||
'pnpm/json-valid-catalog': ['error', { autofix: true }],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.{yml,yaml}'],
|
||||
language: 'yml/yaml',
|
||||
plugins: {
|
||||
yml,
|
||||
},
|
||||
rules: {
|
||||
'no-irregular-whitespace': 'off',
|
||||
'no-unused-vars': 'off',
|
||||
'spaced-comment': 'off',
|
||||
'yml/no-empty-key': 'error',
|
||||
'yml/no-empty-sequence-entry': 'error',
|
||||
'yml/no-irregular-whitespace': 'error',
|
||||
'yml/vue-custom-block/no-parsing-error': 'error',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['pnpm-workspace.yaml'],
|
||||
plugins: {
|
||||
pnpm,
|
||||
},
|
||||
rules: {
|
||||
'pnpm/yaml-enforce-settings': [
|
||||
'error',
|
||||
{
|
||||
settings: {
|
||||
shellEmulator: true,
|
||||
trustPolicy: 'no-downgrade',
|
||||
},
|
||||
},
|
||||
],
|
||||
'pnpm/yaml-no-duplicate-catalog-item': 'error',
|
||||
'pnpm/yaml-no-unused-catalog-item': 'error',
|
||||
'yml/sort-keys': [
|
||||
'error',
|
||||
{
|
||||
order: pnpmWorkspaceOrder,
|
||||
pathPattern: '^$',
|
||||
},
|
||||
{
|
||||
order: { type: 'asc' },
|
||||
pathPattern: '.*',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.toml'],
|
||||
language: 'toml/toml',
|
||||
plugins: {
|
||||
toml,
|
||||
},
|
||||
rules: {
|
||||
'no-irregular-whitespace': 'off',
|
||||
'spaced-comment': 'off',
|
||||
'toml/keys-order': 'error',
|
||||
'toml/no-unreadable-number-separator': 'error',
|
||||
'toml/precision-of-fractional-seconds': 'error',
|
||||
'toml/precision-of-integer': 'error',
|
||||
'toml/tables-order': 'error',
|
||||
'toml/vue-custom-block/no-parsing-error': 'error',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.md'],
|
||||
language: 'markdown/gfm',
|
||||
plugins: {
|
||||
markdown,
|
||||
'markdown-preferences': markdownPreferences,
|
||||
md,
|
||||
},
|
||||
rules: {
|
||||
'markdown/fenced-code-language': 'off',
|
||||
'markdown/heading-increment': 'error',
|
||||
'markdown/no-duplicate-definitions': 'error',
|
||||
'markdown/no-empty-definitions': 'error',
|
||||
'markdown/no-empty-images': 'error',
|
||||
'markdown/no-empty-links': 'error',
|
||||
'markdown/no-invalid-label-refs': 'error',
|
||||
'markdown/no-missing-atx-heading-space': 'error',
|
||||
'markdown/no-missing-label-refs': 'off',
|
||||
'markdown/no-missing-link-fragments': 'error',
|
||||
'markdown/no-multiple-h1': 'error',
|
||||
'markdown/no-reference-like-urls': 'error',
|
||||
'markdown/no-reversed-media-syntax': 'error',
|
||||
'markdown/no-space-in-emphasis': 'error',
|
||||
'markdown/no-unused-definitions': 'error',
|
||||
'markdown/require-alt-text': 'error',
|
||||
'markdown/table-column-count': 'error',
|
||||
'markdown-preferences/definitions-last': 'error',
|
||||
'markdown-preferences/prefer-link-reference-definitions': [
|
||||
'error',
|
||||
@ -85,16 +413,20 @@ export default antfu(
|
||||
},
|
||||
],
|
||||
'markdown-preferences/sort-definitions': 'error',
|
||||
'md/no-url-trailing-slash': 'error',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['web/i18n/**/*.json'],
|
||||
plugins: {
|
||||
dify,
|
||||
hyoban,
|
||||
},
|
||||
rules: {
|
||||
'node/prefer-global/process': 'off',
|
||||
'unicorn/number-literal-case': 'off',
|
||||
'dify/consistent-placeholders': 'error',
|
||||
'dify/no-extra-keys': 'error',
|
||||
'hyoban/i18n-flat-key': 'error',
|
||||
'jsonc/sort-keys': 'error',
|
||||
},
|
||||
},
|
||||
).override('antfu/sort/package-json', {
|
||||
rules: {
|
||||
'jsonc/sort-keys': 'off',
|
||||
},
|
||||
})
|
||||
])
|
||||
|
||||
1653
lint.config.ts
Normal file
1653
lint.config.ts
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
36
package.json
36
package.json
@ -8,21 +8,47 @@
|
||||
"fmt:check": "vp fmt --check",
|
||||
"prepare": "vp config",
|
||||
"type-check": "vp run -r type-check",
|
||||
"lint": "eslint --cache --concurrency=auto",
|
||||
"lint:ci": "eslint --cache --cache-strategy content --concurrency 2",
|
||||
"lint:fix": "vp run lint --fix",
|
||||
"lint:quiet": "vp run lint --quiet"
|
||||
"lint": "pnpm lint:oxlint && pnpm lint:eslint",
|
||||
"lint:ci": "pnpm lint:oxlint && pnpm lint:eslint",
|
||||
"lint:fix": "pnpm lint:oxlint:fix && pnpm lint:eslint:fix",
|
||||
"lint:quiet": "pnpm lint:oxlint:quiet && pnpm lint:eslint:quiet",
|
||||
"lint:oxlint": "vp lint",
|
||||
"lint:oxlint:fix": "vp lint --fix",
|
||||
"lint:oxlint:quiet": "vp lint --quiet",
|
||||
"lint:eslint": "eslint --concurrency=auto",
|
||||
"lint:eslint:fix": "eslint --fix --concurrency=auto",
|
||||
"lint:eslint:quiet": "eslint --quiet --concurrency=auto"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "catalog:",
|
||||
"@eslint-community/eslint-plugin-eslint-comments": "catalog:",
|
||||
"@eslint-react/eslint-plugin": "catalog:",
|
||||
"@eslint/markdown": "catalog:",
|
||||
"@iconify-json/heroicons": "catalog:",
|
||||
"@iconify-json/ri": "catalog:",
|
||||
"@tanstack/eslint-plugin-query": "catalog:",
|
||||
"@typescript-eslint/parser": "catalog:",
|
||||
"@typescript/native": "catalog:",
|
||||
"concurrently": "catalog:",
|
||||
"eslint": "catalog:",
|
||||
"eslint-markdown": "catalog:",
|
||||
"eslint-plugin-antfu": "catalog:",
|
||||
"eslint-plugin-better-tailwindcss": "catalog:",
|
||||
"eslint-plugin-command": "catalog:",
|
||||
"eslint-plugin-erasable-syntax-only": "catalog:",
|
||||
"eslint-plugin-hyoban": "catalog:",
|
||||
"eslint-plugin-jsdoc": "catalog:",
|
||||
"eslint-plugin-jsonc": "catalog:",
|
||||
"eslint-plugin-jsx-a11y": "catalog:",
|
||||
"eslint-plugin-markdown-preferences": "catalog:",
|
||||
"eslint-plugin-n": "catalog:",
|
||||
"eslint-plugin-no-barrel-files": "catalog:",
|
||||
"eslint-plugin-perfectionist": "catalog:",
|
||||
"eslint-plugin-pnpm": "catalog:",
|
||||
"eslint-plugin-regexp": "catalog:",
|
||||
"eslint-plugin-storybook": "catalog:",
|
||||
"eslint-plugin-toml": "catalog:",
|
||||
"eslint-plugin-unicorn": "catalog:",
|
||||
"eslint-plugin-yml": "catalog:",
|
||||
"typescript": "catalog:",
|
||||
"vite": "catalog:",
|
||||
"vite-plus": "catalog:"
|
||||
|
||||
@ -1478,7 +1478,7 @@ export const zDailyTokenCostStatisticItem = z.object({
|
||||
token_count: z.int().nullish(),
|
||||
total_price: z
|
||||
.string()
|
||||
.regex(/^(?![-+.]*$)[+-]?\d*(?:\.\d*)?$/)
|
||||
.regex(/^(?![-+.]*$)[+-]?0*\d*\.?\d*$/)
|
||||
.nullish(),
|
||||
})
|
||||
|
||||
|
||||
@ -531,7 +531,7 @@ export const zExploreMessageListItem = z.object({
|
||||
status: z.string(),
|
||||
total_price: z
|
||||
.string()
|
||||
.regex(/^(?![-+.]*$)[+-]?\d*(?:\.\d*)?$/)
|
||||
.regex(/^(?![-+.]*$)[+-]?0*\d*\.?\d*$/)
|
||||
.nullish(),
|
||||
total_tokens: z.int().readonly(),
|
||||
})
|
||||
@ -570,7 +570,7 @@ export const zExploreMessageListItemWritable = z.object({
|
||||
status: z.string(),
|
||||
total_price: z
|
||||
.string()
|
||||
.regex(/^(?![-+.]*$)[+-]?\d*(?:\.\d*)?$/)
|
||||
.regex(/^(?![-+.]*$)[+-]?0*\d*\.?\d*$/)
|
||||
.nullish(),
|
||||
})
|
||||
|
||||
|
||||
@ -2360,12 +2360,12 @@ export const zEventParameterType = z.enum([
|
||||
*/
|
||||
export const zPriceConfigResponse = z.object({
|
||||
currency: z.string(),
|
||||
input: z.string().regex(/^(?![-+.]*$)[+-]?\d*(?:\.\d*)?$/),
|
||||
input: z.string().regex(/^(?![-+.]*$)[+-]?0*\d*\.?\d*$/),
|
||||
output: z
|
||||
.string()
|
||||
.regex(/^(?![-+.]*$)[+-]?\d*(?:\.\d*)?$/)
|
||||
.regex(/^(?![-+.]*$)[+-]?0*\d*\.?\d*$/)
|
||||
.nullish(),
|
||||
unit: z.string().regex(/^(?![-+.]*$)[+-]?\d*(?:\.\d*)?$/),
|
||||
unit: z.string().regex(/^(?![-+.]*$)[+-]?0*\d*\.?\d*$/),
|
||||
})
|
||||
|
||||
/**
|
||||
@ -2870,12 +2870,12 @@ export const zToolProviderEntity = z.object({
|
||||
*/
|
||||
export const zPriceConfig = z.object({
|
||||
currency: z.string(),
|
||||
input: z.string().regex(/^(?![-+.]*$)[+-]?\d*(?:\.\d*)?$/),
|
||||
input: z.string().regex(/^(?![-+.]*$)[+-]?0*\d*\.?\d*$/),
|
||||
output: z
|
||||
.string()
|
||||
.regex(/^(?![-+.]*$)[+-]?\d*(?:\.\d*)?$/)
|
||||
.regex(/^(?![-+.]*$)[+-]?0*\d*\.?\d*$/)
|
||||
.nullish(),
|
||||
unit: z.string().regex(/^(?![-+.]*$)[+-]?\d*(?:\.\d*)?$/),
|
||||
unit: z.string().regex(/^(?![-+.]*$)[+-]?0*\d*\.?\d*$/),
|
||||
})
|
||||
|
||||
/**
|
||||
@ -3244,7 +3244,7 @@ export const zPluginDeclaration = z.object({
|
||||
agent_strategy: zAgentStrategyProviderEntity.nullish(),
|
||||
author: z
|
||||
.string()
|
||||
.regex(/^[\w-]{1,64}$/)
|
||||
.regex(/^[a-zA-Z0-9_-]{1,64}$/)
|
||||
.nullable(),
|
||||
category: zPluginCategory,
|
||||
created_at: z.iso.datetime(),
|
||||
|
||||
@ -1992,7 +1992,7 @@ export const zMessageListItem = z.object({
|
||||
status: z.string(),
|
||||
total_price: z
|
||||
.string()
|
||||
.regex(/^(?![-+.]*$)[+-]?\d*(?:\.\d*)?$/)
|
||||
.regex(/^(?![-+.]*$)[+-]?0*\d*\.?\d*$/)
|
||||
.nullish(),
|
||||
total_tokens: z.int().readonly(),
|
||||
})
|
||||
@ -2343,7 +2343,7 @@ export const zMessageListItemWritable = z.object({
|
||||
status: z.string(),
|
||||
total_price: z
|
||||
.string()
|
||||
.regex(/^(?![-+.]*$)[+-]?\d*(?:\.\d*)?$/)
|
||||
.regex(/^(?![-+.]*$)[+-]?0*\d*\.?\d*$/)
|
||||
.nullish(),
|
||||
})
|
||||
|
||||
|
||||
@ -850,7 +850,7 @@ export const zWebMessageListItem = z.object({
|
||||
status: z.string(),
|
||||
total_price: z
|
||||
.string()
|
||||
.regex(/^(?![-+.]*$)[+-]?\d*(?:\.\d*)?$/)
|
||||
.regex(/^(?![-+.]*$)[+-]?0*\d*\.?\d*$/)
|
||||
.nullish(),
|
||||
total_tokens: z.int().readonly(),
|
||||
})
|
||||
@ -977,7 +977,7 @@ export const zWebMessageListItemWritable = z.object({
|
||||
status: z.string(),
|
||||
total_price: z
|
||||
.string()
|
||||
.regex(/^(?![-+.]*$)[+-]?\d*(?:\.\d*)?$/)
|
||||
.regex(/^(?![-+.]*$)[+-]?0*\d*\.?\d*$/)
|
||||
.nullish(),
|
||||
})
|
||||
|
||||
|
||||
@ -297,10 +297,6 @@ export default defineConfig({
|
||||
suffix: '.gen',
|
||||
},
|
||||
postProcess: [
|
||||
{
|
||||
command: 'eslint',
|
||||
args: ['--fix', '{{path}}/*.ts'],
|
||||
},
|
||||
{
|
||||
command: 'vp',
|
||||
args: ['fmt', '{{path}}'],
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"gen-api-contract": "uv run --project ../../api ../../api/dev/generate_swagger_specs.py --output-dir openapi && uv run --project ../../api ../../api/dev/generate_fastopenapi_specs.py --output-dir openapi && node -e \"fs.rmSync('generated/api', { recursive: true, force: true })\" && openapi-ts -f openapi-ts.api.config.ts && eslint --fix generated/api && vp fmt generated/api",
|
||||
"gen-api-contract": "uv run --project ../../api ../../api/dev/generate_swagger_specs.py --output-dir openapi && uv run --project ../../api ../../api/dev/generate_fastopenapi_specs.py --output-dir openapi && node -e \"fs.rmSync('generated/api', { recursive: true, force: true })\" && openapi-ts -f openapi-ts.api.config.ts && vp fmt generated/api",
|
||||
"gen-enterprise-contract": "openapi-ts -f openapi-ts.enterprise.config.ts",
|
||||
"test": "vp test openapi-yaml.test.ts",
|
||||
"type-check": "tsc"
|
||||
@ -32,7 +32,6 @@
|
||||
"@hey-api/openapi-ts": "catalog:",
|
||||
"@types/node": "catalog:",
|
||||
"@typescript/native": "catalog:",
|
||||
"eslint": "catalog:",
|
||||
"js-yaml": "catalog:",
|
||||
"typescript": "catalog:",
|
||||
"vite-plus": "catalog:",
|
||||
|
||||
@ -188,7 +188,7 @@ See `[web/docs/overlay.md](../../web/docs/overlay.md)` for the web app overlay b
|
||||
|
||||
## Development
|
||||
|
||||
- `vp run @langgenius/dify-ui#lint` (from the repository root) — strict ESLint checks for component source, stories, tests, and package configuration.
|
||||
- `vp run @langgenius/dify-ui#lint` (from the repository root) — strict Oxlint checks for component source, stories, tests, and package configuration.
|
||||
- `pnpm -C packages/dify-ui test` — Vitest unit tests for primitives.
|
||||
- `pnpm -C packages/dify-ui storybook` — Storybook on the default port. Each primitive has `index.stories.tsx`.
|
||||
- `pnpm -C packages/dify-ui test:storybook` — Storybook component tests in Vitest browser mode. Stories without `play` are render and a11y smoke tests; stories with `play` should cover public UI contracts such as opening overlays, keyboard navigation, disabled/loading guards, form submission, and controlled state updates.
|
||||
|
||||
@ -1,130 +0,0 @@
|
||||
// @ts-check
|
||||
|
||||
import path from 'node:path'
|
||||
import antfu, { GLOB_MARKDOWN_CODE, GLOB_TS, GLOB_TSX } from '@antfu/eslint-config'
|
||||
import tailwindcss from 'eslint-plugin-better-tailwindcss'
|
||||
import jsxA11y from 'eslint-plugin-jsx-a11y'
|
||||
import storybook from 'eslint-plugin-storybook'
|
||||
|
||||
const SOURCE_FILES = [GLOB_TS, GLOB_TSX]
|
||||
const TEST_FILES = ['**/__tests__/**/*.{ts,tsx}', '**/*.spec.{ts,tsx}']
|
||||
|
||||
export default antfu(
|
||||
{
|
||||
ignores: ['coverage/', 'dist/', 'storybook-static/'],
|
||||
stylistic: false,
|
||||
perfectionist: {
|
||||
overrides: {
|
||||
'perfectionist/sort-imports': 'off',
|
||||
},
|
||||
},
|
||||
jsonc: {
|
||||
overrides: {
|
||||
'jsonc/space-unary-ops': 'off',
|
||||
},
|
||||
},
|
||||
yaml: {
|
||||
overrides: {
|
||||
'yaml/block-mapping': 'off',
|
||||
'yaml/block-sequence': 'off',
|
||||
'yaml/plain-scalar': 'off',
|
||||
},
|
||||
},
|
||||
toml: {
|
||||
overrides: {
|
||||
'toml/comma-style': 'off',
|
||||
'toml/no-space-dots': 'off',
|
||||
},
|
||||
},
|
||||
react: {
|
||||
overrides: {
|
||||
'react/exhaustive-deps': ['error', { additionalHooks: 'useIsoLayoutEffect' }],
|
||||
'react/no-context-provider': 'off',
|
||||
'react/no-unnecessary-use-prefix': 'error',
|
||||
'react/no-use-context': 'off',
|
||||
'react/rules-of-hooks': 'error',
|
||||
'react/set-state-in-effect': 'error',
|
||||
'react/set-state-in-render': 'error',
|
||||
'react/static-components': 'error',
|
||||
'react-refresh/only-export-components': 'off',
|
||||
},
|
||||
},
|
||||
typescript: {
|
||||
overrides: {
|
||||
'ts/consistent-type-definitions': ['error', 'type'],
|
||||
'ts/no-explicit-any': 'error',
|
||||
'ts/no-redeclare': 'off',
|
||||
},
|
||||
erasableOnly: true,
|
||||
},
|
||||
test: {
|
||||
overrides: {
|
||||
'test/prefer-lowercase-title': 'off',
|
||||
},
|
||||
},
|
||||
e18e: false,
|
||||
pnpm: false,
|
||||
},
|
||||
{
|
||||
files: [GLOB_TSX],
|
||||
...jsxA11y.flatConfigs.recommended,
|
||||
rules: {
|
||||
...jsxA11y.flatConfigs.recommended.rules,
|
||||
'jsx-a11y/anchor-has-content': 'off',
|
||||
'jsx-a11y/label-has-associated-control': 'off',
|
||||
},
|
||||
},
|
||||
...storybook.configs['flat/recommended'],
|
||||
{
|
||||
name: 'dify-ui/storybook',
|
||||
files: ['**/.storybook/main.{js,cjs,mjs,ts}'],
|
||||
rules: {
|
||||
'storybook/no-uninstalled-addons': [
|
||||
'error',
|
||||
{
|
||||
packageJsonLocation: path.resolve(import.meta.dirname, 'package.json'),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'dify-ui/tailwind',
|
||||
files: SOURCE_FILES,
|
||||
ignores: [GLOB_MARKDOWN_CODE, ...TEST_FILES],
|
||||
plugins: {
|
||||
tailwindcss,
|
||||
},
|
||||
rules: {
|
||||
'tailwindcss/no-duplicate-classes': 'error',
|
||||
'tailwindcss/no-deprecated-classes': 'error',
|
||||
'tailwindcss/no-unknown-classes': 'error',
|
||||
},
|
||||
settings: {
|
||||
'better-tailwindcss': {
|
||||
cwd: import.meta.dirname,
|
||||
entryPoint: path.resolve(import.meta.dirname, './.storybook/storybook.css'),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
files: TEST_FILES,
|
||||
rules: {
|
||||
'react/purity': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
rules: {
|
||||
'node/prefer-global/process': 'off',
|
||||
'unicorn/number-literal-case': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
linterOptions: {
|
||||
reportUnusedDisableDirectives: 'error',
|
||||
},
|
||||
},
|
||||
).override('antfu/sort/package-json', {
|
||||
rules: {
|
||||
'jsonc/sort-keys': 'off',
|
||||
},
|
||||
})
|
||||
@ -151,7 +151,6 @@
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint --cache --max-warnings=0 .",
|
||||
"storybook": "storybook dev -p 6006",
|
||||
"storybook:build": "storybook build",
|
||||
"test": "vp test --project unit",
|
||||
@ -164,12 +163,10 @@
|
||||
"tailwind-merge": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "catalog:",
|
||||
"@base-ui/react": "catalog:",
|
||||
"@chromatic-com/storybook": "catalog:",
|
||||
"@dify/tsconfig": "workspace:*",
|
||||
"@egoist/tailwindcss-icons": "catalog:",
|
||||
"@eslint-react/eslint-plugin": "catalog:",
|
||||
"@iconify-json/ri": "catalog:",
|
||||
"@storybook/addon-a11y": "catalog:",
|
||||
"@storybook/addon-docs": "catalog:",
|
||||
@ -188,11 +185,6 @@
|
||||
"@vitest/browser-playwright": "catalog:",
|
||||
"@vitest/coverage-v8": "catalog:",
|
||||
"class-variance-authority": "catalog:",
|
||||
"eslint": "catalog:",
|
||||
"eslint-plugin-better-tailwindcss": "catalog:",
|
||||
"eslint-plugin-jsx-a11y": "catalog:",
|
||||
"eslint-plugin-react-refresh": "catalog:",
|
||||
"eslint-plugin-storybook": "catalog:",
|
||||
"playwright": "catalog:",
|
||||
"react": "catalog:",
|
||||
"react-dom": "catalog:",
|
||||
|
||||
@ -603,7 +603,7 @@ const FuzzyHighlight = ({ text, query }: { text: string; query: string }) => {
|
||||
<React.Fragment>
|
||||
{parts.map((part, index) =>
|
||||
part.toLowerCase() === query.trim().toLowerCase() ? (
|
||||
// eslint-disable-next-line react/no-array-index-key -- Repeated text fragments have no stable identity and never preserve state.
|
||||
// oxlint-disable-next-line react/no-array-index-key -- Repeated text fragments have no stable identity and never preserve state.
|
||||
<mark key={`${part}-${index}`} className="bg-transparent text-text-accent">
|
||||
{part}
|
||||
</mark>
|
||||
|
||||
@ -65,7 +65,7 @@ const HotkeyKbdGroup = ({
|
||||
}) => (
|
||||
<KbdGroup>
|
||||
{displayKeys(hotkey, platform).map((key, index) => (
|
||||
// eslint-disable-next-line react/no-array-index-key -- Repeated display keys are static, ordered tokens with no component state.
|
||||
// oxlint-disable-next-line react/no-array-index-key -- Repeated display keys are static, ordered tokens with no component state.
|
||||
<Kbd key={`${key}-${index}`} color={color}>
|
||||
{key}
|
||||
</Kbd>
|
||||
|
||||
@ -344,7 +344,7 @@ export function PaginationPageJump({
|
||||
<NumberFieldGroup className="h-7 w-full min-w-0 rounded-lg border-[0.5px] border-components-input-border-active bg-components-input-bg-active shadow-xs">
|
||||
<NumberFieldInput
|
||||
aria-label={inputLabel}
|
||||
// eslint-disable-next-line jsx-a11y/no-autofocus -- Editing starts after an explicit user action and focus must move to the replacement input.
|
||||
// oxlint-disable-next-line jsx-a11y/no-autofocus -- Editing starts after an explicit user action and focus must move to the replacement input.
|
||||
autoFocus
|
||||
className="px-2 py-1.5 text-center system-xs-medium tabular-nums"
|
||||
onBlur={() => requestAnimationFrame(() => setEditing(false))}
|
||||
|
||||
1574
pnpm-lock.yaml
generated
1574
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -52,14 +52,14 @@ overrides:
|
||||
catalog:
|
||||
'@amplitude/analytics-browser': 2.44.4
|
||||
'@amplitude/plugin-session-replay-browser': 1.33.0
|
||||
'@antfu/eslint-config': 9.1.0
|
||||
'@base-ui/react': 1.6.0
|
||||
'@chromatic-com/storybook': 5.2.1
|
||||
'@cucumber/cucumber': 13.0.0
|
||||
'@egoist/tailwindcss-icons': 1.9.2
|
||||
'@emoji-mart/data': 1.2.1
|
||||
'@eslint-community/eslint-plugin-eslint-comments': 4.7.2
|
||||
'@eslint-react/eslint-plugin': 5.12.1
|
||||
'@eslint/js': 10.0.1
|
||||
'@eslint/markdown': 8.0.3
|
||||
'@floating-ui/react': 0.27.19
|
||||
'@formatjs/intl-localematcher': 0.8.10
|
||||
'@heroicons/react': 2.2.0
|
||||
@ -80,7 +80,6 @@ catalog:
|
||||
'@mediabunny/mp3-encoder': 1.50.7
|
||||
'@monaco-editor/react': 4.7.0
|
||||
'@napi-rs/keyring': 1.3.0
|
||||
'@next/eslint-plugin-next': 16.2.10
|
||||
'@next/mdx': 16.2.10
|
||||
'@orpc/client': 1.14.7
|
||||
'@orpc/contract': 1.14.7
|
||||
@ -128,7 +127,6 @@ catalog:
|
||||
'@types/react': 19.2.17
|
||||
'@types/react-dom': 19.2.3
|
||||
'@types/sortablejs': 1.15.9
|
||||
'@typescript-eslint/eslint-plugin': 8.63.0
|
||||
'@typescript-eslint/parser': 8.63.0
|
||||
'@typescript/native': npm:typescript@7.0.2
|
||||
'@vitejs/plugin-react': 6.0.3
|
||||
@ -161,14 +159,25 @@ catalog:
|
||||
emoji-mart: 5.6.0
|
||||
es-toolkit: 1.49.0
|
||||
eslint: 10.6.0
|
||||
eslint-markdown: 0.12.0
|
||||
eslint-markdown: 0.12.1
|
||||
eslint-plugin-antfu: 3.2.3
|
||||
eslint-plugin-better-tailwindcss: 4.6.1
|
||||
eslint-plugin-command: 3.5.2
|
||||
eslint-plugin-erasable-syntax-only: 0.4.2
|
||||
eslint-plugin-hyoban: 0.14.1
|
||||
eslint-plugin-jsdoc: 63.0.10
|
||||
eslint-plugin-jsonc: 3.3.0
|
||||
eslint-plugin-jsx-a11y: 6.10.2
|
||||
eslint-plugin-markdown-preferences: 0.41.1
|
||||
eslint-plugin-n: 18.2.1
|
||||
eslint-plugin-no-barrel-files: 1.3.1
|
||||
eslint-plugin-react-refresh: 0.5.3
|
||||
eslint-plugin-perfectionist: 5.9.1
|
||||
eslint-plugin-pnpm: 1.6.1
|
||||
eslint-plugin-regexp: 3.1.1
|
||||
eslint-plugin-storybook: 10.4.6
|
||||
eslint-plugin-toml: 1.4.0
|
||||
eslint-plugin-unicorn: 68.0.0
|
||||
eslint-plugin-yml: 3.6.0
|
||||
eventsource-parser: 3.1.0
|
||||
fast-deep-equal: 3.1.3
|
||||
foxact: 0.3.8
|
||||
|
||||
@ -1,45 +0,0 @@
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import js from '@eslint/js'
|
||||
import tsPlugin from '@typescript-eslint/eslint-plugin'
|
||||
import tsParser from '@typescript-eslint/parser'
|
||||
|
||||
const tsconfigRootDir = path.dirname(fileURLToPath(import.meta.url))
|
||||
const typeCheckedRules =
|
||||
tsPlugin.configs['recommended-type-checked']?.rules ??
|
||||
tsPlugin.configs.recommendedTypeChecked?.rules ??
|
||||
{}
|
||||
|
||||
export default [
|
||||
{
|
||||
ignores: ['dist', 'node_modules', 'scripts'],
|
||||
},
|
||||
js.configs.recommended,
|
||||
{
|
||||
files: ['src/**/*.ts', 'tests/**/*.ts'],
|
||||
languageOptions: {
|
||||
parser: tsParser,
|
||||
ecmaVersion: 'latest',
|
||||
parserOptions: {
|
||||
project: './tsconfig.json',
|
||||
tsconfigRootDir,
|
||||
sourceType: 'module',
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
'@typescript-eslint': tsPlugin,
|
||||
},
|
||||
rules: {
|
||||
...tsPlugin.configs.recommended.rules,
|
||||
...typeCheckedRules,
|
||||
'no-undef': 'off',
|
||||
'no-unused-vars': 'off',
|
||||
'@typescript-eslint/no-unsafe-call': 'error',
|
||||
'@typescript-eslint/no-unsafe-return': 'error',
|
||||
'@typescript-eslint/consistent-type-imports': [
|
||||
'error',
|
||||
{ prefer: 'type-imports', fixStyle: 'separate-type-imports' },
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
@ -27,10 +27,10 @@
|
||||
"directory": "sdks/nodejs-client"
|
||||
},
|
||||
"files": [
|
||||
"dist/index.js",
|
||||
"dist/index.d.ts",
|
||||
"LICENSE",
|
||||
"README.md",
|
||||
"LICENSE"
|
||||
"dist/index.d.ts",
|
||||
"dist/index.js"
|
||||
],
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
@ -43,8 +43,6 @@
|
||||
},
|
||||
"scripts": {
|
||||
"build": "vp pack",
|
||||
"lint": "eslint",
|
||||
"lint:fix": "eslint --fix",
|
||||
"type-check": "tsc",
|
||||
"test": "vp test",
|
||||
"test:coverage": "vp test --coverage",
|
||||
@ -53,13 +51,9 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@dify/tsconfig": "workspace:*",
|
||||
"@eslint/js": "catalog:",
|
||||
"@types/node": "catalog:",
|
||||
"@typescript-eslint/eslint-plugin": "catalog:",
|
||||
"@typescript-eslint/parser": "catalog:",
|
||||
"@typescript/native": "catalog:",
|
||||
"@vitest/coverage-v8": "catalog:",
|
||||
"eslint": "catalog:",
|
||||
"typescript": "catalog:",
|
||||
"vite": "catalog:",
|
||||
"vite-plus": "catalog:",
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
import { defineConfig } from 'vite-plus'
|
||||
import { lintConfig } from './lint.config'
|
||||
|
||||
const lintFiles = '*.{js,cjs,mjs,jsx,ts,cts,mts,tsx,json,jsonc,json5,md,yml,yaml,toml}'
|
||||
const lintFiles = '*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}'
|
||||
const eslintFiles = '*.{json,jsonc,json5,md,yml,yaml,toml}'
|
||||
const formatOnlyFiles = '*.{mdx,css,scss,less,html,vue,svelte,gql,graphql,hbs,handlebars}'
|
||||
const lintFix = 'eslint --fix --pass-on-unpruned-suppressions --no-error-on-unmatched-pattern'
|
||||
const lintFix = 'vp lint --fix --no-error-on-unmatched-pattern'
|
||||
const eslintFix =
|
||||
'eslint --fix --pass-on-unpruned-suppressions --no-error-on-unmatched-pattern --no-warn-ignored'
|
||||
const format = 'vp fmt --no-error-on-unmatched-pattern'
|
||||
|
||||
const nonFrontendIgnores = [
|
||||
@ -30,6 +34,7 @@ const generatedIgnores = [
|
||||
'e2e/.auth/**',
|
||||
'e2e/cucumber-report/**',
|
||||
'eslint-suppressions.json',
|
||||
'oxlint-suppressions.json',
|
||||
'web/next/**',
|
||||
'web/next-env.d.ts',
|
||||
'web/public/embed.min.js',
|
||||
@ -40,8 +45,10 @@ const generatedIgnores = [
|
||||
const formatterUnstableInputs = ['web/app/components/develop/template/*.mdx']
|
||||
|
||||
export default defineConfig({
|
||||
lint: lintConfig,
|
||||
staged: {
|
||||
[lintFiles]: [lintFix, format],
|
||||
[eslintFiles]: [eslintFix, format],
|
||||
[formatOnlyFiles]: format,
|
||||
},
|
||||
fmt: {
|
||||
|
||||
@ -4,7 +4,7 @@ import { act } from '@testing-library/react'
|
||||
export * from 'zustand'
|
||||
|
||||
const { create: actualCreate, createStore: actualCreateStore } =
|
||||
// eslint-disable-next-line antfu/no-top-level-await
|
||||
// oxlint-disable-next-line antfu/no-top-level-await
|
||||
await vi.importActual<typeof ZustandExportedTypes>('zustand')
|
||||
|
||||
export const storeResetFns = new Set<() => void>()
|
||||
|
||||
@ -33,7 +33,7 @@ const WebSSOForm: FC = () => {
|
||||
await webAppLogout(shareCode!)
|
||||
const url = getSigninUrl()
|
||||
router.replace(url)
|
||||
}, [getSigninUrl, router, webAppLogout, shareCode])
|
||||
}, [getSigninUrl, router, shareCode])
|
||||
|
||||
if (!redirectUrl) {
|
||||
return (
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import type { Mock } from 'vitest'
|
||||
import type { AnnotationItem } from '../type'
|
||||
import type { App } from '@/types/app'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import type { Mock } from 'vitest'
|
||||
import type { Locale } from '@/i18n-config'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import type { ComponentProps } from 'react'
|
||||
import type { Mock } from 'vitest'
|
||||
import type { AnnotationItemBasic } from '../../type'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import { fireEvent, render, screen, waitFor, within } from '@testing-library/react'
|
||||
import FeaturesWrappedAppPublisher from '../features-wrapper'
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import { fireEvent, screen, waitFor } from '@testing-library/react'
|
||||
import * as React from 'react'
|
||||
import { renderWithSystemFeatures } from '@/__tests__/utils/mock-system-features'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import type { ReactNode } from 'react'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import { AccessMode } from '@/models/access-control'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import { toast } from '@langgenius/dify-ui/toast'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import VersionInfoModal from '../version-info-modal'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import type { ReactNode } from 'react'
|
||||
import type { PromptRole } from '@/models/debug'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import type { IPromptProps } from '../index'
|
||||
import type { PromptItem, PromptVariable } from '@/models/debug'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import type { ReactNode } from 'react'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import { INSERT_VARIABLE_VALUE_BLOCK_COMMAND } from '@/app/components/base/prompt-editor/plugins/variable-block'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import type { ReactNode } from 'react'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import { InputVarType } from '@/app/components/workflow/types'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import type { InputVar } from '@/app/components/workflow/types'
|
||||
import type { App, AppSSO } from '@/types/app'
|
||||
import { toast } from '@langgenius/dify-ui/toast'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import TypeSelector from '../type-select'
|
||||
|
||||
@ -205,7 +205,7 @@ const ConfigVar: FC<IConfigVarProps> = ({ promptVariables, readonly, onPromptVar
|
||||
[handleOpenExternalDataToolModal, onPromptVariablesChange, promptVariables],
|
||||
)
|
||||
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
eventEmitter?.useSubscription((v: any) => {
|
||||
if (v.type === ADD_EXTERNAL_DATA_TOOL) {
|
||||
const payload = v.payload
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import type { Mock } from 'vitest'
|
||||
import type { FeatureStoreState } from '@/app/components/base/features/store'
|
||||
import type { FileUpload } from '@/app/components/base/features/types'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import type { AgentConfig } from '@/models/debug'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import type { FeatureStoreState } from '@/app/components/base/features/store'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import type { FeatureStoreState } from '@/app/components/base/features/store'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import type { ModelConfig, PromptVariable } from '@/models/debug'
|
||||
import type { ToolItem } from '@/types/app'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import type { PropsWithChildren } from 'react'
|
||||
import type { Mock } from 'vitest'
|
||||
import type SettingBuiltInToolType from '../setting-built-in-tool'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import type { Tool, ToolParameter } from '@/app/components/tools/types'
|
||||
import { render, screen, waitFor } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
|
||||
@ -97,7 +97,7 @@ const SettingBuiltInTool: FC<Props> = ({
|
||||
} catch {}
|
||||
setIsLoading(false)
|
||||
})()
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
// oxlint-disable-next-line react/exhaustive-deps
|
||||
}, [collection?.name, collection?.id, collection?.type])
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import type { DataSet } from '@/models/datasets'
|
||||
import type { DatasetConfigs } from '@/models/debug'
|
||||
import { fireEvent, render, screen, within } from '@testing-library/react'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import type { DataSet } from '@/models/datasets'
|
||||
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import * as React from 'react'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import { act, renderHook } from '@testing-library/react'
|
||||
import { AgentStrategy } from '@/types/app'
|
||||
import {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import type { CSSProperties } from 'react'
|
||||
import type { ModelAndParameter } from '../../types'
|
||||
import type { DebugWithMultipleModelContextType } from '../context'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import type { ReactNode, RefObject } from 'react'
|
||||
import type { DebugWithSingleModelRefType } from '../index'
|
||||
import type { ChatItem } from '@/app/components/base/chat/types'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import { act, renderHook, waitFor } from '@testing-library/react'
|
||||
import {
|
||||
CONTEXT_PLACEHOLDER_TEXT,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import type { VisionSettings } from '@/types/app'
|
||||
import { withSelectorKey } from '@/test/i18n-mock'
|
||||
import {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import { act, renderHook, waitFor } from '@testing-library/react'
|
||||
import { updateAppModelConfig } from '@/service/apps'
|
||||
import { AppModeEnum, ModelModeType } from '@/types/app'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import type { IPromptValuePanelProps } from '../index'
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import * as React from 'react'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import type { App } from '@/models/explore'
|
||||
import type { AppIconType } from '@/types/app'
|
||||
import { screen, within } from '@testing-library/react'
|
||||
@ -73,7 +73,7 @@ describe('AppCard', () => {
|
||||
|
||||
const renderWithProvider = (ui: React.ReactElement) => {
|
||||
return render(
|
||||
// eslint-disable-next-line react/no-context-provider
|
||||
// oxlint-disable-next-line eslint-react/no-context-provider
|
||||
<AppListContext.Provider
|
||||
value={{
|
||||
currentApp: undefined,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import { act, fireEvent, screen, waitFor } from '@testing-library/react'
|
||||
import { renderWithSystemFeatures as render } from '@/__tests__/utils/mock-system-features'
|
||||
import { NEED_REFRESH_APP_LIST_KEY } from '@/app/components/apps/storage'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import { APP_PAGE_LIMIT } from '@/config'
|
||||
import { AppModeEnum } from '@/types/app'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import type { IChatItem } from '@/app/components/base/chat/chat/type'
|
||||
import {
|
||||
applyAnnotationAdded,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import type { ReactNode } from 'react'
|
||||
import { act, fireEvent, screen, waitFor } from '@testing-library/react'
|
||||
import {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import {
|
||||
buildChartOptions,
|
||||
getChartValueField,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable react-refresh/only-export-components */
|
||||
/* oxlint-disable react/only-export-components */
|
||||
import type { SelectorParam, TFunction } from 'i18next'
|
||||
import type { ComponentType, FormEvent, ReactNode } from 'react'
|
||||
import type {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable react-refresh/only-export-components, react/component-hook-factories */
|
||||
/* oxlint-disable react/only-export-components */
|
||||
'use client'
|
||||
import type { Dayjs } from 'dayjs'
|
||||
import type { SelectorParam } from 'i18next'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import { AppSourceType } from '@/service/share'
|
||||
import GenerationItem from '../index'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import ResultTab from '../result-tab'
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import {
|
||||
buildPromptLogItem,
|
||||
getCopyContent,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import WorkflowBody from '../workflow-body'
|
||||
|
||||
|
||||
@ -151,9 +151,9 @@ const GenerationItem: FC<IGenerationItemProps> = ({
|
||||
|
||||
useEffect(() => {
|
||||
if (controlClearMoreLikeThis) {
|
||||
// eslint-disable-next-line react/set-state-in-effect
|
||||
// oxlint-disable-next-line eslint-react/set-state-in-effect
|
||||
setChildMessageId(null)
|
||||
// eslint-disable-next-line react/set-state-in-effect
|
||||
// oxlint-disable-next-line eslint-react/set-state-in-effect
|
||||
setCompletionRes('')
|
||||
}
|
||||
}, [controlClearMoreLikeThis])
|
||||
@ -161,7 +161,7 @@ const GenerationItem: FC<IGenerationItemProps> = ({
|
||||
// regeneration clear child
|
||||
useEffect(() => {
|
||||
if (isLoading)
|
||||
// eslint-disable-next-line react/set-state-in-effect
|
||||
// oxlint-disable-next-line eslint-react/set-state-in-effect
|
||||
setChildMessageId(null)
|
||||
}, [isLoading])
|
||||
|
||||
@ -180,7 +180,7 @@ const GenerationItem: FC<IGenerationItemProps> = ({
|
||||
setCurrentTab(tab)
|
||||
}
|
||||
useEffect(() => {
|
||||
// eslint-disable-next-line react/set-state-in-effect
|
||||
// oxlint-disable-next-line eslint-react/set-state-in-effect
|
||||
setCurrentTab(getDefaultGenerationTab(workflowProcessData))
|
||||
}, [workflowProcessData])
|
||||
const handleSubmitHumanInputForm = useCallback(
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
/**
|
||||
* WorkflowAppLogList Component Tests
|
||||
*
|
||||
|
||||
@ -5,7 +5,7 @@ import { APP_LIST_SEARCH_DEBOUNCE_MS } from '../../constants'
|
||||
import { useAppsQueryState } from '../use-apps-query-state'
|
||||
|
||||
const renderWithAdapter = (searchParams = '') => {
|
||||
// eslint-disable-next-line react/use-state -- renderHook executes a custom hook, not React.useState
|
||||
// oxlint-disable-next-line eslint-react/use-state -- renderHook executes a custom hook, not React.useState
|
||||
return renderHookWithNuqs(() => useAppsQueryState(), { searchParams })
|
||||
}
|
||||
|
||||
|
||||
@ -50,7 +50,7 @@ function List({ controlRefreshList = 0 }: Props) {
|
||||
const workspacePermissionKeys = useAtomValue(workspacePermissionKeysAtom)
|
||||
const { onPlanInfoChanged } = useProviderContext()
|
||||
|
||||
// eslint-disable-next-line react/use-state -- custom URL query hook, not React.useState
|
||||
// oxlint-disable-next-line eslint-react/use-state -- custom URL query hook, not React.useState
|
||||
const {
|
||||
query: { category, keywords, creatorIDs },
|
||||
setCategory,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import AudioPlayer from '@/app/components/base/audio-btn/audio'
|
||||
|
||||
declare global {
|
||||
// eslint-disable-next-line ts/consistent-type-definitions
|
||||
// oxlint-disable-next-line typescript/consistent-type-definitions
|
||||
interface AudioPlayerManager {
|
||||
instance: AudioPlayerManager
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ import { toast } from '@langgenius/dify-ui/toast'
|
||||
import { AppSourceType, textToAudioStream } from '@/service/share'
|
||||
|
||||
declare global {
|
||||
// eslint-disable-next-line ts/consistent-type-definitions
|
||||
// oxlint-disable-next-line typescript/consistent-type-definitions
|
||||
interface Window {
|
||||
ManagedMediaSource: any
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ const AudioPlayer: React.FC<AudioPlayerProps> = ({ src, srcs }) => {
|
||||
const primarySrc = srcs?.[0] || src
|
||||
if (primarySrc) {
|
||||
// Delayed generation of waveform data
|
||||
// eslint-disable-next-line ts/no-use-before-define
|
||||
// oxlint-disable-next-line typescript/no-use-before-define
|
||||
const timer = setTimeout(generateWaveformData, 1000, primarySrc)
|
||||
return () => {
|
||||
audio.removeEventListener('loadedmetadata', setAudioData)
|
||||
|
||||
@ -45,7 +45,7 @@ async function advanceWaveformTimer() {
|
||||
})
|
||||
}
|
||||
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
type ReactEventHandler = ((...args: any[]) => void) | undefined
|
||||
function getReactProps<T extends Element>(el: T): Record<string, ReactEventHandler> {
|
||||
const key = Object.keys(el).find((k) => k.startsWith('__reactProps$'))
|
||||
|
||||
@ -32,7 +32,7 @@ const AutoHeightTextarea = ({
|
||||
}: IProps & {
|
||||
ref?: React.RefObject<HTMLTextAreaElement>
|
||||
}) => {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
// oxlint-disable-next-line react/rules-of-hooks
|
||||
const ref = outerRef || useRef<HTMLTextAreaElement>(null)
|
||||
|
||||
const doFocus = () => {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable react-hooks-extra/no-direct-set-state-in-use-effect */
|
||||
/* oxlint-disable eslint-react/set-state-in-effect */
|
||||
import type { UseEmblaCarouselType } from 'embla-carousel-react'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import Autoplay from 'embla-carousel-autoplay'
|
||||
|
||||
@ -259,7 +259,7 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
|
||||
const [initUserVariables, setInitUserVariables] = useState<Record<string, any>>({})
|
||||
const handleNewConversationInputsChange = useCallback((newInputs: Record<string, any>) => {
|
||||
newConversationInputsRef.current = newInputs
|
||||
// eslint-disable-next-line react/set-state-in-effect -- This handler intentionally syncs derived input defaults when called from the reset effect below.
|
||||
// oxlint-disable-next-line eslint-react/set-state-in-effect -- This handler intentionally syncs derived input defaults when called from the reset effect below.
|
||||
setNewConversationInputs(newInputs)
|
||||
}, [])
|
||||
const inputsForms = useMemo(() => {
|
||||
@ -363,7 +363,7 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
|
||||
const [originConversationList, setOriginConversationList] = useState<ConversationItem[]>([])
|
||||
useEffect(() => {
|
||||
if (appConversationData?.data && !appConversationDataLoading)
|
||||
// eslint-disable-next-line react/set-state-in-effect -- Conversation query results intentionally replace the local editable list.
|
||||
// oxlint-disable-next-line eslint-react/set-state-in-effect -- Conversation query results intentionally replace the local editable list.
|
||||
setOriginConversationList(appConversationData?.data)
|
||||
}, [appConversationData, appConversationDataLoading])
|
||||
const conversationList = useMemo(() => {
|
||||
@ -380,7 +380,7 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
|
||||
}, [originConversationList, showNewConversationItemInList, t])
|
||||
useEffect(() => {
|
||||
if (newConversation) {
|
||||
// eslint-disable-next-line react/set-state-in-effect -- Newly resolved conversation names intentionally patch the local list cache.
|
||||
// oxlint-disable-next-line eslint-react/set-state-in-effect -- Newly resolved conversation names intentionally patch the local list cache.
|
||||
setOriginConversationList(
|
||||
produce((draft) => {
|
||||
const index = draft.findIndex((item) => item.id === newConversation.id)
|
||||
@ -406,7 +406,7 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
|
||||
)
|
||||
useEffect(() => {
|
||||
if (currentConversationItem)
|
||||
// eslint-disable-next-line react/set-state-in-effect -- Selected conversation changes intentionally resync the editable input snapshot.
|
||||
// oxlint-disable-next-line eslint-react/set-state-in-effect -- Selected conversation changes intentionally resync the editable input snapshot.
|
||||
setCurrentConversationInputs(currentConversationLatestInputs || {})
|
||||
}, [currentConversationItem, currentConversationLatestInputs])
|
||||
const checkInputsRequired = useCallback(
|
||||
|
||||
@ -338,7 +338,7 @@ const ChatInputArea = ({
|
||||
)
|
||||
}
|
||||
// Existing chat behavior focuses the composer as soon as it opens.
|
||||
// eslint-disable-next-line jsx-a11y/no-autofocus
|
||||
// oxlint-disable-next-line jsx-a11y/no-autofocus
|
||||
autoFocus={autoFocus}
|
||||
minRows={1}
|
||||
value={query}
|
||||
|
||||
@ -68,7 +68,7 @@ const Citation: FC<CitationProps> = ({
|
||||
}
|
||||
}
|
||||
setLimitNumberInOneLine(limit)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
// oxlint-disable-next-line react/exhaustive-deps
|
||||
}, [])
|
||||
|
||||
const resourcesLength = resources.length
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import type { ChatConfig, ChatItem, Feedback } from '../types'
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import type { InputValueTypes } from '@/app/components/share/text-generation/types'
|
||||
import type { Locale } from '@/i18n-config'
|
||||
import type { AppData, ConversationItem } from '@/models/share'
|
||||
@ -194,7 +194,7 @@ export const useEmbeddedChatbot = (appSourceType: AppSourceType, tryAppId?: stri
|
||||
const [initUserVariables, setInitUserVariables] = useState<Record<string, any>>({})
|
||||
const handleNewConversationInputsChange = useCallback((newInputs: Record<string, any>) => {
|
||||
newConversationInputsRef.current = newInputs
|
||||
// eslint-disable-next-line react-hooks-extra/no-direct-set-state-in-use-effect
|
||||
// oxlint-disable-next-line eslint-react/set-state-in-effect
|
||||
setNewConversationInputs(newInputs)
|
||||
}, [])
|
||||
const inputsForms = useMemo(() => {
|
||||
@ -299,7 +299,7 @@ export const useEmbeddedChatbot = (appSourceType: AppSourceType, tryAppId?: stri
|
||||
const [originConversationList, setOriginConversationList] = useState<ConversationItem[]>([])
|
||||
useEffect(() => {
|
||||
if (appConversationData?.data && !appConversationDataLoading)
|
||||
// eslint-disable-next-line react-hooks-extra/no-direct-set-state-in-use-effect
|
||||
// oxlint-disable-next-line eslint-react/set-state-in-effect
|
||||
setOriginConversationList(appConversationData?.data)
|
||||
}, [appConversationData, appConversationDataLoading])
|
||||
const conversationList = useMemo(() => {
|
||||
@ -341,7 +341,7 @@ export const useEmbeddedChatbot = (appSourceType: AppSourceType, tryAppId?: stri
|
||||
)
|
||||
useEffect(() => {
|
||||
if (currentConversationItem && !isTryApp)
|
||||
// eslint-disable-next-line react-hooks-extra/no-direct-set-state-in-use-effect
|
||||
// oxlint-disable-next-line eslint-react/set-state-in-effect
|
||||
setCurrentConversationInputs(currentConversationLatestInputs || {})
|
||||
}, [currentConversationItem, currentConversationLatestInputs])
|
||||
const checkInputsRequired = useCallback(
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { InputVarType } from '@/app/components/workflow/types'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* eslint-disable ts/no-explicit-any */
|
||||
/* oxlint-disable typescript/no-explicit-any */
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { AppSourceType } from '@/service/share'
|
||||
|
||||
@ -62,18 +62,18 @@ const DatePicker = ({
|
||||
clearMonthMapCache()
|
||||
if (normalizedValue) {
|
||||
const newValue = getDateWithTimezone({ date: normalizedValue, timezone })
|
||||
// eslint-disable-next-line react/set-state-in-effect -- timezone changes intentionally resync the displayed calendar state.
|
||||
// oxlint-disable-next-line eslint-react/set-state-in-effect -- timezone changes intentionally resync the displayed calendar state.
|
||||
setCurrentDate(newValue)
|
||||
// eslint-disable-next-line react/set-state-in-effect -- timezone changes intentionally resync the selected value.
|
||||
// oxlint-disable-next-line eslint-react/set-state-in-effect -- timezone changes intentionally resync the selected value.
|
||||
setSelectedDate(newValue)
|
||||
onChange(newValue)
|
||||
} else {
|
||||
// eslint-disable-next-line react/set-state-in-effect -- timezone changes intentionally resync the displayed calendar state.
|
||||
// oxlint-disable-next-line eslint-react/set-state-in-effect -- timezone changes intentionally resync the displayed calendar state.
|
||||
setCurrentDate((prev) => getDateWithTimezone({ date: prev, timezone }))
|
||||
// eslint-disable-next-line react/set-state-in-effect -- timezone changes intentionally resync the selected value.
|
||||
// oxlint-disable-next-line eslint-react/set-state-in-effect -- timezone changes intentionally resync the selected value.
|
||||
setSelectedDate((prev) => (prev ? getDateWithTimezone({ date: prev, timezone }) : undefined))
|
||||
}
|
||||
// eslint-disable-next-line react/exhaustive-deps -- this effect intentionally runs only when timezone changes.
|
||||
// oxlint-disable-next-line react/exhaustive-deps -- this effect intentionally runs only when timezone changes.
|
||||
}, [timezone])
|
||||
|
||||
const handleOpenChange = useCallback(
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user