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 <justin@jedmund.com>
This commit is contained in:
parent
a208a3c1ea
commit
dfbb1e4e48
12 changed files with 1420 additions and 1221 deletions
147
CLEANUP_PLAN.md
Normal file
147
CLEANUP_PLAN.md
Normal file
|
|
@ -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<any>[]` 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
|
||||||
|
|
@ -96,8 +96,8 @@ export abstract class BaseAdapter {
|
||||||
// Generate a unique ID for this request (used for cancellation and caching)
|
// Generate a unique ID for this request (used for cancellation and caching)
|
||||||
const requestId = this.generateRequestId(path, options.method, options.body as string)
|
const requestId = this.generateRequestId(path, options.method, options.body as string)
|
||||||
|
|
||||||
// Check cache first if caching is enabled (support both cache and cacheTTL)
|
// Check cache first if caching is enabled (support both cacheTime and cacheTTL)
|
||||||
const cacheTime = options.cacheTTL ?? options.cache ?? this.options.cacheTime
|
const cacheTime = options.cacheTTL ?? options.cacheTime ?? this.options.cacheTime
|
||||||
// Allow caching for any method if explicitly set (unless cache is disabled)
|
// Allow caching for any method if explicitly set (unless cache is disabled)
|
||||||
if (!this.disableCache && cacheTime > 0) {
|
if (!this.disableCache && cacheTime > 0) {
|
||||||
const cached = this.getFromCache(requestId)
|
const cached = this.getFromCache(requestId)
|
||||||
|
|
|
||||||
|
|
@ -56,19 +56,27 @@ export interface Character {
|
||||||
}
|
}
|
||||||
rarity: number
|
rarity: number
|
||||||
element: number
|
element: number
|
||||||
|
gender?: number
|
||||||
|
proficiency?: number[]
|
||||||
proficiency1?: number
|
proficiency1?: number
|
||||||
proficiency2?: number
|
proficiency2?: number
|
||||||
series?: number
|
series?: number
|
||||||
minHp?: number
|
race?: number[]
|
||||||
maxHp?: number
|
hp?: {
|
||||||
minAttack?: number
|
minHp?: number
|
||||||
maxAttack?: number
|
maxHp?: number
|
||||||
flbHp?: number
|
maxHpFlb?: number
|
||||||
flbAttack?: number
|
}
|
||||||
ulbHp?: number
|
atk?: {
|
||||||
ulbAttack?: number
|
minAtk?: number
|
||||||
transcendenceHp?: number
|
maxAtk?: number
|
||||||
transcendenceAttack?: number
|
maxAtkFlb?: number
|
||||||
|
}
|
||||||
|
uncap?: {
|
||||||
|
flb?: boolean
|
||||||
|
ulb?: boolean
|
||||||
|
transcendence?: boolean
|
||||||
|
}
|
||||||
special?: boolean
|
special?: boolean
|
||||||
seasonalId?: string
|
seasonalId?: string
|
||||||
awakenings?: Array<{
|
awakenings?: Array<{
|
||||||
|
|
@ -183,4 +191,4 @@ export class EntityAdapter extends BaseAdapter {
|
||||||
/**
|
/**
|
||||||
* Default entity adapter instance
|
* Default entity adapter instance
|
||||||
*/
|
*/
|
||||||
export const entityAdapter = new EntityAdapter(DEFAULT_ADAPTER_CONFIG)
|
export const entityAdapter = new EntityAdapter(DEFAULT_ADAPTER_CONFIG)
|
||||||
|
|
|
||||||
12
src/lib/api/adapters/index.ts
Normal file
12
src/lib/api/adapters/index.ts
Normal file
|
|
@ -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'
|
||||||
|
|
@ -32,7 +32,7 @@ export interface AdapterOptions {
|
||||||
* Options for individual HTTP requests
|
* Options for individual HTTP requests
|
||||||
* Extends the standard RequestInit interface with additional features
|
* Extends the standard RequestInit interface with additional features
|
||||||
*/
|
*/
|
||||||
export interface RequestOptions extends Omit<RequestInit, 'body'> {
|
export interface RequestOptions extends Omit<RequestInit, 'body' | 'cache'> {
|
||||||
/** Query parameters to append to the URL */
|
/** Query parameters to append to the URL */
|
||||||
params?: Record<string, any>
|
params?: Record<string, any>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import type { FetchLike } from '../core'
|
import { userAdapter } from '../adapters/user.adapter'
|
||||||
import { put } from '../core'
|
|
||||||
|
|
||||||
export interface UserUpdateParams {
|
export interface UserUpdateParams {
|
||||||
picture?: string
|
picture?: string
|
||||||
|
|
@ -26,6 +25,16 @@ export const users = {
|
||||||
/**
|
/**
|
||||||
* Update user settings
|
* Update user settings
|
||||||
*/
|
*/
|
||||||
update: (fetch: FetchLike, userId: string, params: UserUpdateParams) =>
|
update: async (userId: string, params: UserUpdateParams): Promise<UserResponse> => {
|
||||||
put<UserResponse>(fetch, `/users/${userId}`, { user: params })
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,13 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Dialog from './ui/Dialog.svelte'
|
import Dialog from './ui/Dialog.svelte'
|
||||||
import Select from './ui/Select.svelte'
|
import Select from './ui/Select.svelte'
|
||||||
import Switch from './ui/switch/switch.svelte'
|
import Switch from './ui/switch/Switch.svelte'
|
||||||
import Button from './ui/Button.svelte'
|
import Button from './ui/Button.svelte'
|
||||||
import { pictureData, type Picture } from '$lib/utils/pictureData'
|
import { pictureData, type Picture } from '$lib/utils/pictureData'
|
||||||
import { users } from '$lib/api/resources/users'
|
import { users } from '$lib/api/resources/users'
|
||||||
import type { UserCookie } from '$lib/types/UserCookie'
|
import type { UserCookie } from '$lib/types/UserCookie'
|
||||||
import { setUserCookie } from '$lib/auth/cookies'
|
import { setUserCookie } from '$lib/auth/cookies'
|
||||||
import { invalidateAll } from '$app/navigation'
|
import { invalidateAll } from '$app/navigation'
|
||||||
import type { Snippet } from 'svelte'
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
open: boolean
|
open: boolean
|
||||||
|
|
@ -83,7 +82,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call API to update user settings
|
// Call API to update user settings
|
||||||
const response = await users.update(fetch, userId, updateData)
|
const response = await users.update(userId, updateData)
|
||||||
|
|
||||||
// Update the user cookie
|
// Update the user cookie
|
||||||
const updatedUser: UserCookie = {
|
const updatedUser: UserCookie = {
|
||||||
|
|
@ -130,10 +129,6 @@
|
||||||
onOpenChange?.(false)
|
onOpenChange?.(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Footer snippet for the dialog
|
|
||||||
const footer: Snippet = {
|
|
||||||
render: () => ({})
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Dialog bind:open {onOpenChange} title="@{username}" description="Account Settings">
|
<Dialog bind:open {onOpenChange} title="@{username}" description="Account Settings">
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -10,7 +10,7 @@
|
||||||
import CharacterGrid from '$lib/components/grids/CharacterGrid.svelte'
|
import CharacterGrid from '$lib/components/grids/CharacterGrid.svelte'
|
||||||
import { openSearchSidebar } from '$lib/features/search/openSearchSidebar.svelte'
|
import { openSearchSidebar } from '$lib/features/search/openSearchSidebar.svelte'
|
||||||
import PartySegmentedControl from '$lib/components/party/PartySegmentedControl.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 { GridType } from '$lib/types/enums'
|
||||||
import Dialog from '$lib/components/ui/Dialog.svelte'
|
import Dialog from '$lib/components/ui/Dialog.svelte'
|
||||||
import Button from '$lib/components/ui/Button.svelte'
|
import Button from '$lib/components/ui/Button.svelte'
|
||||||
|
|
@ -562,8 +562,8 @@
|
||||||
let targetSlot = selectedSlot
|
let targetSlot = selectedSlot
|
||||||
|
|
||||||
// Call appropriate grid service method based on current tab
|
// Call appropriate grid service method based on current tab
|
||||||
// Use granblue_id (snake_case) as that's what the search API returns
|
// Use granblueId (camelCase) as that's what the SearchResult type uses
|
||||||
const itemId = item.granblue_id || item.granblueId
|
const itemId = item.granblueId
|
||||||
if (activeTab === GridType.Weapon) {
|
if (activeTab === GridType.Weapon) {
|
||||||
await gridService.addWeapon(party.id, itemId, targetSlot, editKey || undefined, {
|
await gridService.addWeapon(party.id, itemId, targetSlot, editKey || undefined, {
|
||||||
mainhand: targetSlot === -1,
|
mainhand: targetSlot === -1,
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,22 @@ export interface Character {
|
||||||
}
|
}
|
||||||
special: boolean
|
special: boolean
|
||||||
recruits: string | null
|
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
|
// Summon entity from SummonBlueprint
|
||||||
|
|
@ -178,4 +194,4 @@ export interface User {
|
||||||
role?: string
|
role?: string
|
||||||
createdAt?: string
|
createdAt?: string
|
||||||
updatedAt?: string
|
updatedAt?: string
|
||||||
}
|
}
|
||||||
|
|
|
||||||
50
src/lib/types/declarations.d.ts
vendored
50
src/lib/types/declarations.d.ts
vendored
|
|
@ -5,3 +5,53 @@ declare module '*.svg' {
|
||||||
const SVG: React.FunctionComponent<React.SVGProps<SVGSVGElement>>
|
const SVG: React.FunctionComponent<React.SVGProps<SVGSVGElement>>
|
||||||
export default SVG
|
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<T = any> {
|
||||||
|
constructor(url: string, options?: any)
|
||||||
|
getData(): Promise<T[]>
|
||||||
|
[key: string]: any
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue