fix: as-any cast cleanup + spiral-db prepare + locale typing

Remaining cast cleanups that got lost during the lint-staged stash
cycle and were re-applied:

- citycorners: added createdBy to LocalLocation type, removed 6
  `as any` casts in getCityStats/getPlatformStats
- picture/images: removed toggleField double-cast (now unnecessary
  after the IndexableType widening in shared-stores)
- contacts/[id]: tagIds exists on Contact — removed the
  `as unknown as Record<...>` cast
- calendar/EventForm: same tagIds fix — read directly from event
- +layout.svelte: import SupportedLocale type, use it for locale
  casts instead of `as any`
- spiral-db: added prepare + prepublishOnly scripts so dist/ is
  built on fresh clones

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-04-10 18:43:01 +02:00
parent d7dc5388b9
commit 7d18adadf7
7 changed files with 20 additions and 21 deletions

View file

@ -35,10 +35,8 @@
let calendarId = $state(event?.calendarId || '');
// svelte-ignore state_referenced_locally
let recurrenceRule = $state(event?.recurrenceRule || '');
let selectedTagIds = $state<string[]>(
// svelte-ignore state_referenced_locally
((event as unknown as Record<string, unknown>)?.tagIds as string[]) ?? []
);
let selectedTagIds = $state<string[]>(event?.tagIds ?? []);
const allTags = useAllTags();

View file

@ -123,7 +123,7 @@ export function getCityStats(locations: LocalLocation[]): CityStats {
for (const loc of locations) {
categoryCounts[loc.category] = (categoryCounts[loc.category] || 0) + 1;
if ((loc as any).createdBy) contributors.add((loc as any).createdBy);
if (loc.createdBy) contributors.add(loc.createdBy);
if (loc.latitude && loc.longitude) hasCoordinates++;
}
@ -134,8 +134,8 @@ export function getCityStats(locations: LocalLocation[]): CityStats {
const recentLocations = [...locations]
.sort((a, b) => {
const aTime = (a as any).createdAt ? new Date((a as any).createdAt).getTime() : 0;
const bTime = (b as any).createdAt ? new Date((b as any).createdAt).getTime() : 0;
const aTime = a.createdAt ? new Date(a.createdAt).getTime() : 0;
const bTime = b.createdAt ? new Date(b.createdAt).getTime() : 0;
return bTime - aTime;
})
.slice(0, 3);
@ -161,7 +161,7 @@ export interface PlatformStats {
export function getPlatformStats(cities: LocalCity[], locations: LocalLocation[]): PlatformStats {
const contributors = new Set<string>();
for (const loc of locations) {
if ((loc as any).createdBy) contributors.add((loc as any).createdBy);
if (loc.createdBy) contributors.add(loc.createdBy);
}
for (const city of cities) {
if (city.createdBy) contributors.add(city.createdBy);

View file

@ -37,6 +37,7 @@ export interface LocalLocation extends BaseRecord {
longitude?: number | null;
imageUrl?: string | null;
timeline?: Array<{ year: number; event: string }> | null;
createdBy?: string | null;
}
export interface LocalFavorite extends BaseRecord {

View file

@ -43,14 +43,7 @@ export const imagesStore = {
async toggleFavorite(id: string) {
error = null;
try {
// Cast: toggleField expects a string-keyed Table, but db.table()
// returns the generic IndexableType-keyed shape. The runtime keys
// for `images` are all strings (UUIDs).
await toggleField(
imageTable() as unknown as Parameters<typeof toggleField>[0],
id,
'isFavorite'
);
await toggleField(imageTable(), id, 'isFavorite');
PictureEvents.imageFavorited();
return { success: true };
} catch (e) {

View file

@ -56,7 +56,7 @@
} from '@mana/shared-theme';
import type { ThemeVariant } from '@mana/shared-theme';
import { getLanguageDropdownItems, getCurrentLanguageLabel } from '@mana/shared-i18n';
import { setLocale, supportedLocales } from '$lib/i18n';
import { setLocale, supportedLocales, type SupportedLocale } from '$lib/i18n';
import { ManaEvents, AppEvents } from '@mana/shared-utils/analytics';
import { setUser as setErrorTrackingUser } from '@mana/shared-error-tracking/browser';
import { trackReturnVisit, trackModuleUsed, markAsGuest } from '$lib/stores/funnel-tracking';
@ -145,7 +145,9 @@
// ── i18n ────────────────────────────────────────────────
let currentLocale = $derived($locale || 'de');
function handleLocaleChange(newLocale: string) {
setLocale(newLocale as any);
if (supportedLocales.includes(newLocale as SupportedLocale)) {
setLocale(newLocale as SupportedLocale);
}
userSettings.updateGlobal({ locale: newLocale });
AppEvents.languageChanged(newLocale);
}
@ -154,8 +156,11 @@
$effect(() => {
if (userSettings.loaded && userSettings.locale) {
const settingsLocale = userSettings.locale;
if (supportedLocales.includes(settingsLocale as any) && settingsLocale !== $locale) {
setLocale(settingsLocale as any);
if (
supportedLocales.includes(settingsLocale as SupportedLocale) &&
settingsLocale !== $locale
) {
setLocale(settingsLocale as SupportedLocale);
}
}
});

View file

@ -63,7 +63,7 @@
twitter: contact.twitter,
instagram: contact.instagram,
github: contact.github,
tagIds: ((contact as unknown as Record<string, unknown>).tagIds as string[]) ?? [],
tagIds: contact.tagIds ?? [],
};
isEditing = true;
}

View file

@ -18,6 +18,8 @@
},
"scripts": {
"build": "tsup src/index.ts src/wallpaper.ts --format esm --dts --clean",
"prepublishOnly": "pnpm build",
"prepare": "pnpm build",
"dev": "tsup src/index.ts src/wallpaper.ts --format esm --dts --watch",
"test": "vitest",
"test:run": "vitest run",