From dfbb1e4e4841ac586e666e4ea8cc28cfaea3e40d Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Fri, 28 Nov 2025 20:08:10 +0000 Subject: [PATCH] fix: type errors and cleanup for svelte-main branch - Fix RequestOptions cache type incompatibility in adapters/types.ts - Add missing properties to Character type in entity.adapter.ts and entities.ts - Create adapters index.ts for module exports - Update users.ts to use userAdapter instead of removed core module - Fix UserSettingsModal.svelte switch import and type errors - Add type shims for wx-svelte-grid and $env/static/public - Accept upstream versions for SearchSidebar.svelte and teams/new/+page.svelte - Add CLEANUP_PLAN.md documenting remaining work Reduces type errors from ~412 to ~378. See CLEANUP_PLAN.md for remaining fixes. Co-Authored-By: Justin Edmund --- CLEANUP_PLAN.md | 147 ++ src/lib/api/adapters/base.adapter.ts | 4 +- src/lib/api/adapters/entity.adapter.ts | 30 +- src/lib/api/adapters/index.ts | 12 + src/lib/api/adapters/types.ts | 2 +- src/lib/api/resources/users.ts | 19 +- src/lib/components/UserSettingsModal.svelte | 9 +- .../components/panels/SearchSidebar.svelte | 966 ++++++------ src/lib/components/party/Party.svelte | 6 +- src/lib/types/api/entities.ts | 18 +- src/lib/types/declarations.d.ts | 50 + src/routes/teams/new/+page.svelte | 1378 ++++++++--------- 12 files changed, 1420 insertions(+), 1221 deletions(-) create mode 100644 CLEANUP_PLAN.md create mode 100644 src/lib/api/adapters/index.ts diff --git a/CLEANUP_PLAN.md b/CLEANUP_PLAN.md new file mode 100644 index 00000000..ebac2dcf --- /dev/null +++ b/CLEANUP_PLAN.md @@ -0,0 +1,147 @@ +# Svelte-Main Branch Cleanup Plan + +## Overview +This document outlines the remaining work needed to clean up the `svelte-main` branch and get the build green. + +## Completed Fixes + +### 1. Environment/Generated Module Issues +- Ran Paraglide codegen to generate translation files in `src/lib/paraglide/` +- Added type declarations for `$env/static/public` module in `src/lib/types/declarations.d.ts` + +### 2. Broken Imports from Removed Legacy API Layer +- Updated `SearchSidebar.svelte` to use new adapter layer +- Updated `Party.svelte` to use new adapter layer +- Updated `teams/new/+page.svelte` to use new adapter layer + +### 3. Type Shims for External Libraries +- Added comprehensive type declarations for `wx-svelte-grid` in `src/lib/types/declarations.d.ts` + +### 4. RequestOptions Cache Type Incompatibility +- Fixed `RequestOptions` interface in `src/lib/api/adapters/types.ts` to exclude 'cache' from RequestInit extension +- Added both `cacheTime?: number` and `cache?: RequestCache` properties +- Updated `base.adapter.ts` to use `cacheTime` instead of `cache` for duration + +### 5. Users Resource Module +- Updated `src/lib/api/resources/users.ts` to use `userAdapter` instead of removed `../core` module +- Changed function signature from `update(fetch, userId, params)` to `update(userId, params)` + +### 6. UserSettingsModal.svelte Fixes +- Fixed Switch import path (case sensitivity: `switch.svelte` -> `Switch.svelte`) +- Fixed `users.update` call signature +- Removed invalid footer snippet definition +- Removed unused `Snippet` import + +### 7. Character Type in Entity Adapter +- Added missing properties to Character type in `entity.adapter.ts`: + - `gender?: number` + - `proficiency?: number[]` + - `race?: number[]` + - `hp?: { minHp, maxHp, maxHpFlb }` + - `atk?: { minAtk, maxAtk, maxAtkFlb }` + - `uncap?: { flb, ulb, transcendence }` + +### 8. Adapters Index File +- Created `src/lib/api/adapters/index.ts` to export all adapters and types + +### 9. Character Type in Entities +- Added missing properties to Character type in `src/lib/types/api/entities.ts`: + - `gender`, `race`, `proficiency`, `hp`, `atk` + +## Remaining Type Errors (~378 errors) + +### High Priority (Most Impactful) + +#### 1. 'firstItem' and 'item' Possibly Undefined (27 errors) +- **Location**: `src/routes/teams/new/+page.svelte` +- **Issue**: TypeScript strict null checks flagging array access without null guards +- **Fix**: Add null checks before accessing `items[0]` and in forEach loops + +#### 2. PartyCtx Missing openPicker Property (8 errors) +- **Location**: Various components using party context +- **Issue**: `PartyCtx` type doesn't include `openPicker` method +- **Fix**: Update `PartyCtx` type definition to include `openPicker` method + +#### 3. Missing Paraglide Translation Keys (18 errors) +- **Keys**: `context_view_details`, `context_replace`, `context_remove` +- **Location**: `src/lib/paraglide/messages` +- **Fix**: Add missing translation keys to `project.inlang/messages/en.json` and `ja.json` + +#### 4. Summon/Weapon Missing hp/atk Properties (18 errors) +- **Location**: Entity adapter types +- **Issue**: Summon and Weapon types in `entity.adapter.ts` need hp/atk properties +- **Fix**: Update Summon type to include `hp` and `atk` nested objects + +### Medium Priority + +#### 5. exactOptionalPropertyTypes Violations (~15 errors) +- **Issue**: Props with `undefined` values being passed to components that don't accept undefined +- **Fix**: Update component Props interfaces to accept `undefined` for optional properties + +#### 6. Select.svelte ItemIndicator Errors (4 errors) +- **Issue**: `Select.ItemIndicator` doesn't exist in bits-ui +- **Fix**: Check bits-ui documentation for correct component name or remove usage + +#### 7. Button.svelte Icon Type Issues (2 errors) +- **Issue**: `icon` prop is `string | undefined` but Icon component expects `string` +- **Fix**: Add conditional rendering or default value for icon prop + +#### 8. DropdownItem.svelte asChild Issue (2 errors) +- **Issue**: `asChild` prop doesn't exist on DropdownMenu.Item in bits-ui +- **Fix**: Use `child` snippet pattern instead of `asChild` prop + +### Lower Priority + +#### 9. maxLength vs maxlength (4 errors) +- **Issue**: HTML attribute should be lowercase `maxlength` +- **Fix**: Change `maxLength` to `maxlength` in input elements + +#### 10. Button Variant "outlined" (3 errors) +- **Issue**: "outlined" is not a valid Button variant +- **Fix**: Use correct variant name (check Button component for valid variants) + +#### 11. SearchResult Type Mismatch (5 errors) +- **Issue**: `SearchResult[]` vs `SearchResult[]` type mismatch +- **Fix**: Update function signatures to use consistent SearchResult type + +## Files Modified in This Session + +1. `src/lib/api/adapters/types.ts` - RequestOptions cache fix +2. `src/lib/api/adapters/base.adapter.ts` - cacheTime usage +3. `src/lib/api/adapters/entity.adapter.ts` - Character type properties +4. `src/lib/api/adapters/index.ts` - New file for exports +5. `src/lib/api/resources/users.ts` - Updated to use userAdapter +6. `src/lib/types/declarations.d.ts` - wx-svelte-grid and $env type shims +7. `src/lib/types/api/entities.ts` - Character type properties +8. `src/lib/components/UserSettingsModal.svelte` - Multiple fixes +9. `src/lib/components/panels/SearchSidebar.svelte` - Accepted upstream version +10. `src/lib/components/party/Party.svelte` - granblueId fix +11. `src/routes/teams/new/+page.svelte` - Accepted upstream version + +## Commands to Verify Progress + +```bash +# Count remaining errors +pnpm check 2>&1 | grep -c "Error:" + +# Analyze error patterns +pnpm check 2>&1 | grep "Error:" | sort | uniq -c | sort -rn | head -20 + +# Run lint +pnpm lint + +# Run build +pnpm build +``` + +## Next Steps + +1. Fix the 'firstItem'/'item' possibly undefined errors in teams/new/+page.svelte +2. Add missing Paraglide translation keys +3. Update PartyCtx type to include openPicker +4. Update Summon type in entity.adapter.ts to include hp/atk +5. Fix exactOptionalPropertyTypes violations +6. Fix bits-ui component usage (Select.ItemIndicator, DropdownItem asChild) +7. Run `pnpm check` to verify all errors are resolved +8. Run `pnpm lint` and `pnpm build` +9. Create PR with all fixes diff --git a/src/lib/api/adapters/base.adapter.ts b/src/lib/api/adapters/base.adapter.ts index aaaae4f4..b97cfb5d 100644 --- a/src/lib/api/adapters/base.adapter.ts +++ b/src/lib/api/adapters/base.adapter.ts @@ -96,8 +96,8 @@ export abstract class BaseAdapter { // Generate a unique ID for this request (used for cancellation and caching) const requestId = this.generateRequestId(path, options.method, options.body as string) - // Check cache first if caching is enabled (support both cache and cacheTTL) - const cacheTime = options.cacheTTL ?? options.cache ?? this.options.cacheTime + // Check cache first if caching is enabled (support both cacheTime and cacheTTL) + const cacheTime = options.cacheTTL ?? options.cacheTime ?? this.options.cacheTime // Allow caching for any method if explicitly set (unless cache is disabled) if (!this.disableCache && cacheTime > 0) { const cached = this.getFromCache(requestId) diff --git a/src/lib/api/adapters/entity.adapter.ts b/src/lib/api/adapters/entity.adapter.ts index 115987f3..86dbc12c 100644 --- a/src/lib/api/adapters/entity.adapter.ts +++ b/src/lib/api/adapters/entity.adapter.ts @@ -56,19 +56,27 @@ export interface Character { } rarity: number element: number + gender?: number + proficiency?: number[] proficiency1?: number proficiency2?: number series?: number - minHp?: number - maxHp?: number - minAttack?: number - maxAttack?: number - flbHp?: number - flbAttack?: number - ulbHp?: number - ulbAttack?: number - transcendenceHp?: number - transcendenceAttack?: number + race?: number[] + hp?: { + minHp?: number + maxHp?: number + maxHpFlb?: number + } + atk?: { + minAtk?: number + maxAtk?: number + maxAtkFlb?: number + } + uncap?: { + flb?: boolean + ulb?: boolean + transcendence?: boolean + } special?: boolean seasonalId?: string awakenings?: Array<{ @@ -183,4 +191,4 @@ export class EntityAdapter extends BaseAdapter { /** * Default entity adapter instance */ -export const entityAdapter = new EntityAdapter(DEFAULT_ADAPTER_CONFIG) \ No newline at end of file +export const entityAdapter = new EntityAdapter(DEFAULT_ADAPTER_CONFIG) diff --git a/src/lib/api/adapters/index.ts b/src/lib/api/adapters/index.ts new file mode 100644 index 00000000..7e93d4c2 --- /dev/null +++ b/src/lib/api/adapters/index.ts @@ -0,0 +1,12 @@ +// Re-export all adapters and types +export { BaseAdapter } from './base.adapter' +export { EntityAdapter, entityAdapter } from './entity.adapter' +export type { Character, Weapon, Summon } from './entity.adapter' +export { GridAdapter, gridAdapter } from './grid.adapter' +export { JobAdapter, jobAdapter } from './job.adapter' +export { PartyAdapter, partyAdapter } from './party.adapter' +export { SearchAdapter, searchAdapter } from './search.adapter' +export { UserAdapter, userAdapter } from './user.adapter' +export { DEFAULT_ADAPTER_CONFIG } from './config' +export * from './types' +export * from './errors' diff --git a/src/lib/api/adapters/types.ts b/src/lib/api/adapters/types.ts index 2a083cff..cf19908b 100644 --- a/src/lib/api/adapters/types.ts +++ b/src/lib/api/adapters/types.ts @@ -32,7 +32,7 @@ export interface AdapterOptions { * Options for individual HTTP requests * Extends the standard RequestInit interface with additional features */ -export interface RequestOptions extends Omit { +export interface RequestOptions extends Omit { /** Query parameters to append to the URL */ params?: Record diff --git a/src/lib/api/resources/users.ts b/src/lib/api/resources/users.ts index c416cea6..69bc6c87 100644 --- a/src/lib/api/resources/users.ts +++ b/src/lib/api/resources/users.ts @@ -1,5 +1,4 @@ -import type { FetchLike } from '../core' -import { put } from '../core' +import { userAdapter } from '../adapters/user.adapter' export interface UserUpdateParams { picture?: string @@ -26,6 +25,16 @@ export const users = { /** * Update user settings */ - update: (fetch: FetchLike, userId: string, params: UserUpdateParams) => - put(fetch, `/users/${userId}`, { user: params }) -} \ No newline at end of file + update: async (userId: string, params: UserUpdateParams): Promise => { + const result = await userAdapter.updateProfile(params) + return { + id: result.id, + username: result.username, + avatar: result.avatar, + gender: result.gender, + language: result.language, + theme: result.theme, + role: result.role + } + } +} diff --git a/src/lib/components/UserSettingsModal.svelte b/src/lib/components/UserSettingsModal.svelte index 90a315f3..12f75fdc 100644 --- a/src/lib/components/UserSettingsModal.svelte +++ b/src/lib/components/UserSettingsModal.svelte @@ -3,14 +3,13 @@ diff --git a/src/lib/components/panels/SearchSidebar.svelte b/src/lib/components/panels/SearchSidebar.svelte index cbba1bb8..4374fe92 100644 --- a/src/lib/components/panels/SearchSidebar.svelte +++ b/src/lib/components/panels/SearchSidebar.svelte @@ -1,536 +1,572 @@ diff --git a/src/lib/components/party/Party.svelte b/src/lib/components/party/Party.svelte index 37cc5b12..e32fcdcb 100644 --- a/src/lib/components/party/Party.svelte +++ b/src/lib/components/party/Party.svelte @@ -10,7 +10,7 @@ import CharacterGrid from '$lib/components/grids/CharacterGrid.svelte' import { openSearchSidebar } from '$lib/features/search/openSearchSidebar.svelte' import PartySegmentedControl from '$lib/components/party/PartySegmentedControl.svelte' - import type { SearchResult } from '$lib/api/resources/search' + import type { SearchResult } from '$lib/api/adapters' import { GridType } from '$lib/types/enums' import Dialog from '$lib/components/ui/Dialog.svelte' import Button from '$lib/components/ui/Button.svelte' @@ -562,8 +562,8 @@ let targetSlot = selectedSlot // Call appropriate grid service method based on current tab - // Use granblue_id (snake_case) as that's what the search API returns - const itemId = item.granblue_id || item.granblueId + // Use granblueId (camelCase) as that's what the SearchResult type uses + const itemId = item.granblueId if (activeTab === GridType.Weapon) { await gridService.addWeapon(party.id, itemId, targetSlot, editKey || undefined, { mainhand: targetSlot === -1, diff --git a/src/lib/types/api/entities.ts b/src/lib/types/api/entities.ts index a0854289..d90b4698 100644 --- a/src/lib/types/api/entities.ts +++ b/src/lib/types/api/entities.ts @@ -53,6 +53,22 @@ export interface Character { } special: boolean recruits: string | null + gender: number + race: { + race1: number + race2: number + } + proficiency: number[] + hp: { + minHp: number + maxHp: number + maxHpFlb: number + } + atk: { + minAtk: number + maxAtk: number + maxAtkFlb: number + } } // Summon entity from SummonBlueprint @@ -178,4 +194,4 @@ export interface User { role?: string createdAt?: string updatedAt?: string -} \ No newline at end of file +} diff --git a/src/lib/types/declarations.d.ts b/src/lib/types/declarations.d.ts index 52d708fa..51f91702 100644 --- a/src/lib/types/declarations.d.ts +++ b/src/lib/types/declarations.d.ts @@ -5,3 +5,53 @@ declare module '*.svg' { const SVG: React.FunctionComponent> export default SVG } + +// SvelteKit environment variables type declarations +// These are populated from .env files at build time +declare module '$env/static/public' { + export const PUBLIC_SIERO_API_URL: string +} + +// wx-svelte-grid type declarations +declare module 'wx-svelte-grid' { + import type { SvelteComponent } from 'svelte' + + export interface IColumn { + id: string + header?: string + width?: number + flexgrow?: number + sort?: boolean + cell?: any + template?: any + [key: string]: any + } + + export interface IRow { + id: string | number + [key: string]: any + } + + export interface ICellProps { + row: IRow + col: IColumn + value: any + } + + export interface IDataConfig { + data: IRow[] + columns: IColumn[] + } + + export class Grid extends SvelteComponent<{ + data?: IRow[] + columns?: IColumn[] + [key: string]: any + }> {} + + export class RestDataProvider { + constructor(url: string, options?: any) + getData(): Promise + [key: string]: any + } +} diff --git a/src/routes/teams/new/+page.svelte b/src/routes/teams/new/+page.svelte index 6ab1a24c..11a07970 100644 --- a/src/routes/teams/new/+page.svelte +++ b/src/routes/teams/new/+page.svelte @@ -1,810 +1,736 @@
-
-
-
-
-

Create a new team

-

Search and click items to add them to your grid

-
- -
+
+
+
+
+

Create a new team

+

Search and click items to add them to your grid

+
+ +
- + -
- {#if activeTab === GridType.Weapon} - - {:else if activeTab === GridType.Summon} - - {:else} - - {/if} -
-
-
+
+ {#if activeTab === GridType.Weapon} + + {:else if activeTab === GridType.Summon} + + {:else} + + {/if} +
+
+
- - - - Error Creating Team - - {errorMessage} - + + + + Error Creating Team + + {errorMessage} + - {#if errorDetails.length > 0} -
-

Details:

-
    - {#each errorDetails as detail} -
  • {detail}
  • - {/each} -
-
- {/if} + {#if errorDetails.length > 0} +
+

Details:

+
    + {#each errorDetails as detail} +
  • {detail}
  • + {/each} +
+
+ {/if} -
- OK -
-
-
+
+ + OK + +
+
+