Skip to content

Commit 619b59a

Browse files
fix: resolve all frontend type errors and enforce strict type checking (eneo-ai#291)
* fix: resolve type errors in model admin dialogs and make svelte-check blocking in CI - Fix Input.Text bind:value type mismatch (number|undefined → string) in AddCompletionModelDialog - Remove unnecessary typeof checks on store values in Embedding/Transcription dialogs - Resolve merge conflicts using shared modelProviderCapabilities module - Fix m.provider_no_support_title() to pass both required params - Refactor +page.ts Promise.all to preserve individual types - Make svelte-check and eslint blocking in pr_lint.yml CI workflow * fix: resolve all 448 frontend type errors for strict svelte-check Button variants: - Replace "ghost" with "simple" and "secondary" with "outlined" across 13 files intric-js SDK types: - Fix path parameters ({id} → {provider_id}, {model_id}, {template_id}, etc.) - Fix HTTP method mismatches and response type assertions - Add proper JSDoc types for endpoints not yet in OpenAPI schema Component type fixes: - Add renderComponent() bridge for Svelte 5/4 table component compat - Export components type from @intric/intric-js index.d.ts - Type MCP tool interfaces properly (MCPTool, SelectableMCPServer) - Fix template category Record indexing and implicit any types - Fix RetentionPolicyInput to use non-null local binding - Convert CreateNew.svelte from slot syntax to Snippet pattern - Use spread syntax for props not in component type definitions Misc fixes: - Fix Input.Text bind:value number/string mismatches - Add proper null checks and type narrowing throughout - Fix role comparison, SvelteKit error() calls, import paths - Widen ModelWithProvider type to include optional properties * fix: replace explicit any types with proper types and fix lint warnings - Replace providerData: any with typed object literals - Replace catch (e: any) with catch (e: unknown) + instanceof checks - Change $: to const for static arrays (providerTypes, modelFamilies, etc.) - Type MCP components: intricClient: Intric, model parameters, MCPServer props - Use CapabilityModel type instead of any in model suggestions - Fix quoted attribute warning in MCPServersTable - Add index signature to MCPServer for schema compatibility * fix: clean up lint errors and add frontend pre-commit hook - Remove unused formatTokenLimit function from AddCompletionModelDialog - Remove unused let:close slot bindings from dialog controls - Add (key) to all #each blocks in model admin dialogs - Replace remaining any types with specific types - Fix Prettier formatting in intric-js endpoints and UI table - Add frontend-lint pre-commit hook for Svelte/TS/JS files * fix: resolve svelte-check CI failures for paraglide and DateRange type error - Add i18n:compile step to web check script so paraglide messages are generated before svelte-check runs - Fix DateValue narrowing loss in DateRange.svelte by capturing start in a local variable before reassignment - Keep lint step non-blocking (continue-on-error) due to pre-existing prettier formatting issues across the codebase * fix: resolve all frontend eslint errors and enforce prettier formatting - Fix all 219 ESLint errors across @intric/web and @intric/ui - Replace explicit `any` types with proper types where possible - Remove unused imports and variables - Add keys to {#each} blocks (svelte/require-each-key) - Add descriptions to @ts-expect-error directives - Fix infinite reactive loop warnings with eslint-disable - Convert immutable reactive statements to const declarations - Run prettier --write across entire frontend codebase - Add src/lib/paraglide/ to .prettierignore and eslint ignores (auto-generated files should not be checked) - Make both svelte-check and lint fully blocking in CI * chore: add underscore prefix convention to eslint no-unused-vars config - Add argsIgnorePattern and varsIgnorePattern for ^_ prefix to both @intric/web and @intric/ui eslint configs - Remove 9 now-unnecessary eslint-disable comments that were only needed because the _ prefix wasn't configured * fix: add missing eslint dependencies to all frontend packages - Add @eslint/js to intric-js, ui, and web packages - Add typescript-eslint to ui package - These were imported in eslint configs but relied on hoisting, which fails in CI where node_modules layout differs * fix: add remaining missing eslint dependencies for CI - Add eslint-config-prettier to @intric/web (imported but not declared) - Add eslint-plugin-react-hooks to docs-site (required by eslint-config-next) * fix: scope CI lint to @intric/* packages only docs-site uses eslint-config-next which has transient peer deps that aren't resolved correctly with bun's strict module layout in CI. Since docs-site was never lint-checked in CI before, exclude it from the blocking lint step rather than chasing transient deps. * fix: resolve frontend type errors after openapi-typescript v7 upgrade - Tighten IntricParams helper so endpoints without real path/query/header/cookie properties are typed as `params?: never`, fixing the missing-params errors introduced by the openapi-typescript v6 → v7 upgrade. - Switch api-keys.js JSDoc returns to schema-derived types instead of duplicated literal shapes that drifted from the generated schema. - Replace ad-hoc `error?.getReadableMessage?.()` patterns with the typed getErrorMessage() helper that narrows IntricError properly. - Extend the local Tenant type with id (backend exposes it but the TenantPublic schema omits it) and cast users.tenant() through unknown. - Fix slot misuse in admin api-keys page, replace unsupported "ghost" Button variant with "simple", and split the assistants stream call into two paths so TS can narrow the union endpoint correctly. - Resolve scattered LocalizedString / string-undefined / wizard_config issues in admin and dashboard pages without introducing any casts. - Add SvelteSet/SvelteURLSearchParams + each-block keys + eslint-disable scopes for the dynamic-URL navigation cases the lint rule cannot statically prove. * fix: restore notification policy fields and audit log query param Fix three regressions from the previous type-error sweep: - updateAdminNotificationPolicy() rebuilt the request payload with only three fields, silently dropping allow_auto_follow_published_assistants and allow_auto_follow_published_apps. The proper fix is in api-keys.js: switch the JSDoc to ApiKeyNotificationPolicyUpdate (and the user variant ApiKeyNotificationPreferencesUpdate) so the schema-derived type, which already permits all fields and `null`, drives the contract. The helper now forwards the full updates object unchanged. - The same payload rebuild also coerced max_days_before_expiry: null to undefined. Schema allows `number | null`, where null is the explicit "remove the cap" signal — restoring null pass-through fixes that. - The "open audit config" link lost its ?tab=config query when migrated to resolve(). Pass the full route+query string literal to resolve() (matching the existing pattern in account/integrations) so the link lands on the config tab again. * chore: apply prettier formatting and fix lint issues in api-keys feature Run prettier --write across the workspace to bring it back into compliance with the formatting CI gate. Most touched files come from PR eneo-ai#206 (api-keys-v2) and PR eneo-ai#324 (shadcn-svelte introduction) which were merged without being prettier-formatted. Also fix lint issues in api-keys feature files: - NotificationPreferences.svelte: replace 4× `catch (error: any)` with unknown + getErrorMessage helper, swap Set → SvelteSet for reactivity - ExpirationPicker.svelte: rename Infinity icon import to avoid global shadowing, swap Date → SvelteDate (4×), add each-block key - CreateApiKeyDialog.svelte: swap Map → SvelteMap, add 11 each-block keys, scope eslint-disable for trusted localized {@html} usage, drop a useless literal mustache - OverviewTile.svelte / ExpiringKeysNotification.svelte: scope eslint-disable for href prop / localizeHref navigation cases * fix: resolve all frontend eslint errors Clear the remaining 82 lint errors that were failing CI on both apps/web and packages/ui. Categories: - svelte/prefer-svelte-reactivity: swap Set → SvelteSet, Map → SvelteMap, URLSearchParams → SvelteURLSearchParams, Date → SvelteDate where the instances are held as component state. Drop $state() wrappers around these since they are already reactive. - svelte/no-navigation-without-resolve: wrap static literal routes in resolve() where possible. For dynamic URLs built from template strings, window.location, or props, add eslint-disable scopes with explanatory comments matching the strategy (dynamic URL, localizeHref handles routing, server endpoint, typed href prop, external URL from markdown/metadata/message reference). - svelte/require-each-key: add stable keys to every {#each} block (using a unique id, the literal itself for primitive lists, or the iteration index for fixed skeleton loops). - svelte/no-at-html-tags: add scoped eslint-disable with comments explaining that the content is trusted localized i18n. - @typescript-eslint/no-explicit-any: replace catch (error: any) with unknown + getErrorMessage() helper in NotificationPreferences.svelte. Also: rename Infinity icon import in ExpirationPicker to avoid shadowing the global Infinity, and restructure pushState() call sites in spaces chat page so the eslint-disable directive targets the correct line. * chore: enforce prettier and ruff format in pre-commit hooks Add auto-formatting hooks so code is reformatted (and re-staged) on every commit, preventing the kind of CI formatting-failure churn we've been cleaning up: - ruff-format runs on changed Python files in backend/ (Python equivalent of prettier). Excludes backend/alembic/ since migrations are historical artifacts that shouldn't change after being deployed — whitespace churn breaks git blame / bisect on schema history. - frontend-format runs prettier --write on changed Svelte/TS/JS/CSS/JSON/ MD/YAML files in frontend/apps/* and frontend/packages/*. Covers the full workspace (not just apps/web), excludes .svelte-kit / build / dist generated output. Both hooks auto-stage their changes, so developers don't need to run bun run format / ruff format manually — the hook handles it. bun run format (root-level) is still available for a full workspace reformat. * chore: apply ruff format to backend (excluding alembic migrations) Run ruff format across the backend codebase so it matches the new pre-commit auto-format hook. Result is pure whitespace / line break / trailing comma reformatting — ruff format is a deterministic, semantic-preserving formatter (Python equivalent of black). Alembic migrations (backend/alembic/) are intentionally excluded: they are historical artifacts that should not change after being deployed, and whitespace churn breaks git blame / bisect on schema history. New migrations going forward will still be formatted by the pre-commit hook (which uses the same exclude). No logic changes. 427 files touched, all behavior preserved. Run the test suite after pulling this to verify nothing regresses — ruff format is expected to be safe, but very rare edge cases (docstring whitespace asserted in tests, multi-line string concatenation) could in theory surface. * fix: declare missing @eslint/js dep in @intric/ui and ignore generated inlang files Fixes CI lint failures: @intric/ui's eslint.config.js imports @eslint/js which was only resolvable via the hoisted root node_modules locally, breaking the GitHub Actions runner. Also exclude project.inlang/.meta.json and cache from prettier since they are auto-generated and gitignored.
1 parent b4b719d commit 619b59a

File tree

489 files changed

+16383
-10542
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

489 files changed

+16383
-10542
lines changed

.github/workflows/pr_lint.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ jobs:
5656
- name: Install dependencies
5757
run: bun run setup:github
5858
- name: Run svelte-check
59-
run: bun run check || echo "Svelte check failed but continuing..."
60-
- name: Run eslint (non-blocking)
61-
run: bun run lint || echo "ESLint failed but continuing..."
59+
run: bun run check
60+
- name: Run eslint
61+
run: FORCE_COLOR=1 bun run --filter '@intric/*' lint
6262

6363
backend-checks:
6464
runs-on: ubuntu-latest

.pre-commit-config.yaml

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,15 @@ repos:
88
args: [--fix]
99
stages: [pre-commit]
1010
files: ^backend/
11-
# Format using project configuration (pyproject.toml)
11+
# Auto-format Python with ruff format (Python equivalent of prettier).
12+
# Alembic migrations are excluded — they are historical artifacts that
13+
# should not change after being deployed (whitespace churn breaks
14+
# git blame / bisect on schema history).
1215
- id: ruff-format
1316
name: ruff-format
1417
stages: [pre-commit]
15-
files: ^backend/
18+
files: ^backend/.*\.py$
19+
exclude: ^backend/alembic/
1620

1721
# Pyright type checking via devcontainer
1822
- repo: local
@@ -33,6 +37,27 @@ repos:
3337
- id: uv-lock
3438
args: [--directory, backend]
3539

40+
# Frontend: auto-format changed files with prettier (writes changes back and re-stages)
41+
- repo: local
42+
hooks:
43+
- id: frontend-format
44+
name: frontend-format
45+
entry: bash -c 'cd frontend && bunx prettier --write --ignore-unknown "${@/#frontend\//}"' --
46+
language: system
47+
files: ^frontend/(apps|packages)/[^/]+/.*\.(svelte|ts|tsx|js|jsx|css|scss|json|md|yaml|yml|html)$
48+
exclude: ^frontend/[^/]+/[^/]+/(\.svelte-kit|node_modules|build|dist)/
49+
stages: [pre-commit]
50+
51+
# Frontend: lint changed Svelte/TS/JS files
52+
- repo: local
53+
hooks:
54+
- id: frontend-lint
55+
name: frontend-lint
56+
entry: bash -c 'cd frontend/apps/web && npx eslint --no-warn-ignored "${@/#frontend\/apps\/web\//}"' --
57+
language: system
58+
files: ^frontend/apps/web/src/.*\.(svelte|ts|js)$
59+
stages: [pre-commit]
60+
3661
# Prevent duplicate keys in i18n message files
3762
- repo: local
3863
hooks:

backend/check_icon_columns.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@ async def check_columns():
1515
print(f"Current migration: {current_migration}\n")
1616

1717
# Check columns in both tables
18-
for table in ['assistant_templates', 'app_templates']:
19-
result = await conn.execute(text(f"""
18+
for table in ["assistant_templates", "app_templates"]:
19+
result = await conn.execute(
20+
text(f"""
2021
SELECT column_name, data_type, is_nullable
2122
FROM information_schema.columns
2223
WHERE table_name='{table}' AND column_name='icon_name'
23-
"""))
24+
""")
25+
)
2426
row = result.fetchone()
2527
if row:
2628
print(f"✓ {table}.icon_name: {row[0]} ({row[1]}) - nullable={row[2]}")

backend/init_db.py

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,29 +25,37 @@ class Settings(BaseSettings):
2525
default_user_email: Optional[str] = None
2626
default_user_password: Optional[str] = None
2727

28+
2829
settings = Settings()
2930

31+
3032
# Alembic command
3133
def run_alembic_migrations():
3234
try:
3335
subprocess.run(["alembic", "upgrade", "head"], check=True)
3436
print("Alembic migrations ran successfully.")
3537
except FileNotFoundError:
36-
print("Error: alembic not found on PATH. Ensure it's installed in /app/.venv and PATH includes /app/.venv/bin")
38+
print(
39+
"Error: alembic not found on PATH. Ensure it's installed in /app/.venv and PATH includes /app/.venv/bin"
40+
)
3741
exit(1)
3842
except subprocess.CalledProcessError as e:
3943
print(f"Error running alembic migrations: {e}")
4044
exit(1)
4145

46+
4247
# Password hashing
4348
def create_salt_and_hashed_password(plaintext_password: str):
44-
pwd_bytes = plaintext_password.encode('utf-8')
49+
pwd_bytes = plaintext_password.encode("utf-8")
4550
salt = bcrypt.gensalt()
4651
hashed_password = bcrypt.hashpw(password=pwd_bytes, salt=salt)
47-
return salt.decode(), hashed_password.decode('utf-8')
52+
return salt.decode(), hashed_password.decode("utf-8")
53+
4854

4955
# Add tenant and user
50-
def add_tenant_user(conn, tenant_name, quota_limit, user_name, user_email, user_password):
56+
def add_tenant_user(
57+
conn, tenant_name, quota_limit, user_name, user_email, user_password
58+
):
5159
try:
5260
cur = conn.cursor()
5361

@@ -67,7 +75,9 @@ def add_tenant_user(conn, tenant_name, quota_limit, user_name, user_email, user_
6775
tenant_id = tenant[0]
6876

6977
# Check if user already exists
70-
check_user_query = sql.SQL("SELECT id FROM users WHERE email = %s AND tenant_id = %s")
78+
check_user_query = sql.SQL(
79+
"SELECT id FROM users WHERE email = %s AND tenant_id = %s"
80+
)
7181
cur.execute(check_user_query, (user_email, tenant_id))
7282
user = cur.fetchone()
7383

@@ -140,7 +150,14 @@ def add_tenant_user(conn, tenant_name, quota_limit, user_name, user_email, user_
140150
)
141151
cur.execute(
142152
add_org_space_query,
143-
(org_space_id, "Organization space", "Delad knowledge för hela tenant", tenant_id, now, now),
153+
(
154+
org_space_id,
155+
"Organization space",
156+
"Delad knowledge för hela tenant",
157+
tenant_id,
158+
now,
159+
now,
160+
),
144161
)
145162

146163
conn.commit()
@@ -165,12 +182,16 @@ def add_tenant_user(conn, tenant_name, quota_limit, user_name, user_email, user_
165182
password=settings.postgres_password,
166183
)
167184

168-
if (settings.default_tenant_name is None or
169-
settings.default_tenant_quota_limit is None or
170-
settings.default_user_name is None or
171-
settings.default_user_email is None or
172-
settings.default_user_password is None):
173-
print("Note! One or more environment variables for default tenant and user are not set. Skipping creation of default tenant and user.")
185+
if (
186+
settings.default_tenant_name is None
187+
or settings.default_tenant_quota_limit is None
188+
or settings.default_user_name is None
189+
or settings.default_user_email is None
190+
or settings.default_user_password is None
191+
):
192+
print(
193+
"Note! One or more environment variables for default tenant and user are not set. Skipping creation of default tenant and user."
194+
)
174195
else:
175196
add_tenant_user(
176197
conn,

backend/pyproject.toml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ requires-python = ">=3.11,<4"
77
dependencies = [
88
"fastapi>=0,<1",
99
"uvicorn[standard]>=0.30.0,<1",
10-
1110
"python-dotenv>=1.1.0",
1211
"pydantic[email]>=2,<3",
1312
"tenacity>=8.2.1,<9",
@@ -45,13 +44,11 @@ dependencies = [
4544
"beautifulsoup4>=4.12.3,<5",
4645
"crochet>=2.1.1,<3",
4746
"pgvector>=0.2.5,<0.3",
48-
4947
"sqlalchemy-mixins>=2.0.5,<3",
5048
"python-magic>=0.4.27,<0.5",
5149
"aiocache>=0.12.2,<0.13",
5250
"redis>=5.0.8,<6",
5351
"sentry-sdk[fastapi]==2.8.0",
54-
5552
"tavily-python>=0.5.1,<0.6",
5653
"greenlet>=3.2.2,<4",
5754
"litellm==1.83.0",
@@ -62,7 +59,7 @@ dependencies = [
6259
"orjson>=3.9,<4",
6360
"aiofiles>=23.0,<24",
6461
"python-calamine>=0.3.1,<1", # Fast Excel reader engine for pandas
65-
"rich>=14.2.0"
62+
"rich>=14.2.0",
6663
]
6764

6865
[project.scripts]

backend/scripts/migrate_env_oidc_to_tenant_federation.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ async def main() -> int:
2323
finally:
2424
await sessionmanager.close()
2525

26-
print("Federation migration applied." if migrated else "Federation migration skipped.")
26+
print(
27+
"Federation migration applied." if migrated else "Federation migration skipped."
28+
)
2729
return 0
2830

2931

0 commit comments

Comments
 (0)