Skip to content

Commit c18786b

Browse files
committed
feat: refactor context handling in Svelte components and improve data resolution methods in CBNData
1 parent 64a2180 commit c18786b

12 files changed

Lines changed: 173 additions & 159 deletions

_test/all.meta.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"buildNum": "2026-02-17",
3-
"sha": "32d65f15387ee6bedf0cb83216d1b1795fef2c568bb7a0f2c969eeedbbcb6a8a",
4-
"modsSha": "377429dce1c657a236b8f3a16b1173f8b160cb0ef36d1a4aa346e6e3753ae35c"
2+
"buildNum": "2026-03-04",
3+
"sha": "90c827a8a8f5947054cda959af33ca9f1d6461ffac4308c9b9e9c1aa5f53a54e",
4+
"modsSha": "1bd039194b1acfdafe6bd2dc1966df4a1027b20749680d089c5e5d46e16b58b5"
55
}

src/Catalog.svelte

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script lang="ts">
2-
import { setContext } from "svelte";
2+
import { setContext, untrack } from "svelte";
33
import { t } from "@transifex/native";
44
55
import { byName, CBNData, singularName, pluralName, plural } from "./data";
@@ -16,7 +16,6 @@ import MutationCategory from "./types/MutationCategory.svelte";
1616
import ItemLink from "./types/ItemLink.svelte";
1717
import { groupBy } from "./utils/collections";
1818
import OvermapAppearance from "./types/item/OvermapAppearance.svelte";
19-
import { createLiveContextProxy } from "./contextProxy";
2019
2120
interface Props {
2221
// TODO: Transifex extraction only recognizes direct t("...") keys; replace t(plural(type)) heading with literal branches.
@@ -28,7 +27,7 @@ let { type: typeProp, data: dataProp }: Props = $props();
2827
let type = $derived(typeProp);
2928
let data = $derived(dataProp);
3029
let typeWithCorrectType = $derived(type as keyof SupportedTypesWithMapped);
31-
const dataContext = createLiveContextProxy(() => dataProp);
30+
const dataContext: CBNData = untrack(() => dataProp);
3231
setContext("data", dataContext);
3332
3433
let things = $derived.by(() =>

src/SearchResults.svelte

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import { type CBNData, loadProgress, mapType, plural } from "./data";
33
import ItemLink from "./types/ItemLink.svelte";
44
import type { OvermapSpecial } from "./types";
5-
import { setContext } from "svelte";
5+
import { setContext, untrack } from "svelte";
66
import { t } from "@transifex/native";
77
import LimitedList from "./LimitedList.svelte";
88
import {
@@ -11,7 +11,6 @@ import {
1111
} from "./types/item/spawnLocations";
1212
import { type SearchResult, searchResults } from "./search";
1313
import Loading from "./Loading.svelte";
14-
import { createLiveContextProxy } from "./contextProxy";
1514
1615
interface Props {
1716
data: CBNData;
@@ -21,7 +20,7 @@ interface Props {
2120
let { data: dataProp, search: searchProp }: Props = $props();
2221
let data = $derived(dataProp);
2322
let search = $derived(searchProp);
24-
const dataContext = createLiveContextProxy(() => dataProp);
23+
const dataContext: CBNData = untrack(() => dataProp);
2524
setContext("data", dataContext);
2625
2726
//TODO: Transifex extraction only recognizes direct t("...") keys; replace t(plural(...)) section heading below with literal branches.

src/Thing.svelte

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script lang="ts">
22
import { t } from "@transifex/native";
3-
import { onMount, setContext, type Component } from "svelte";
3+
import { onMount, setContext, untrack, type Component } from "svelte";
44
55
import type { CBNData } from "./data";
66
import Monster from "./types/Monster.svelte";
@@ -35,7 +35,6 @@ import Technique from "./types/Technique.svelte";
3535
import { metrics } from "./metrics";
3636
import { nowTimeStamp } from "./utils/perf";
3737
import { isTesting } from "./utils/env";
38-
import { createLiveContextProxy } from "./contextProxy";
3938
4039
interface Props {
4140
item: { id: string; type: string };
@@ -45,7 +44,8 @@ interface Props {
4544
let { item: itemProp, data: dataProp }: Props = $props();
4645
let item = $derived(itemProp);
4746
let data = $derived(dataProp);
48-
const dataContext = createLiveContextProxy(() => dataProp);
47+
// Route-keyed mounts mean `data` is fixed for this component instance.
48+
const dataContext: CBNData = untrack(() => dataProp);
4949
setContext("data", dataContext);
5050
let error: Error | null = $state(null);
5151

src/WithData.svelte

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
<script lang="ts">
2-
import { setContext } from "svelte";
3-
import { createLiveContextProxy } from "./contextProxy";
2+
import { setContext, untrack } from "svelte";
43
54
interface Props {
65
Component: any;
@@ -9,7 +8,7 @@ interface Props {
98
}
109
1110
let { Component, data, ...rest }: Props = $props();
12-
const dataContext = createLiveContextProxy(() => data);
11+
const dataContext = untrack(() => data);
1312
1413
setContext("data", dataContext);
1514
</script>

src/contextProxy.ts

Lines changed: 0 additions & 22 deletions
This file was deleted.

src/data.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,25 @@ export class CBNData {
680680
}
681681
}
682682

683+
hasById<TypeName extends keyof SupportedTypesWithMapped>(
684+
type: TypeName,
685+
id: string,
686+
): boolean {
687+
if (typeof id !== "string") return false;
688+
return this._byTypeById.get(type)?.has(id) ?? false;
689+
}
690+
691+
resolveOneById<TypeName extends keyof SupportedTypesWithMapped>(
692+
type: TypeName,
693+
id: string,
694+
key: string,
695+
): unknown {
696+
if (typeof id !== "string") return undefined;
697+
const obj = this._byTypeById.get(type)?.get(id);
698+
if (!obj) return undefined;
699+
return this.resolveOne(obj, key);
700+
}
701+
683702
/**
684703
* Retrieves an object by type and ID, resolving inheritance.
685704
* Throws an error if the object is not found.

src/testRenderMods.ts

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -154,11 +154,28 @@ export function makeModRenderTests(modId: string): void {
154154
renderCaseTuplesByMod.get(modId)!.push([type, id]);
155155
}
156156

157+
const renderPriority = (rawType: string): number => {
158+
const mappedType = mapType(rawType as any);
159+
if (mappedType === "overmap_special") return 0;
160+
if (mappedType === "item") return 2;
161+
return 1;
162+
};
163+
157164
afterEach(cleanup);
158165

159166
for (const [modId, mod] of modSubset) {
160167
const modData = mod.data ?? [];
161-
const tuples = renderCaseTuplesByMod.get(modId) ?? [];
168+
const tuples = [...(renderCaseTuplesByMod.get(modId) ?? [])].sort(
169+
([typeA, idA], [typeB, idB]) => {
170+
const p = renderPriority(typeA) - renderPriority(typeB);
171+
if (p !== 0) return p;
172+
const typeCmp = mapType(typeA as any).localeCompare(
173+
mapType(typeB as any),
174+
);
175+
if (typeCmp !== 0) return typeCmp;
176+
return idA.localeCompare(idB);
177+
},
178+
);
162179
let Thing: any;
163180
let data: CBNData | undefined;
164181

@@ -224,18 +241,21 @@ export function makeModRenderTests(modId: string): void {
224241
{ timeout: MOD_RENDER_TIMEOUT_MS },
225242
async (type, id) => {
226243
(globalThis as any).__isTesting__ = true;
227-
const { container } = render(Thing, {
244+
const { container, unmount } = render(Thing, {
228245
item: { type: mapType(type as any), id },
229246
data: data!,
230247
});
231248
await act(() => new Promise((resolve) => setTimeout(resolve, 0)));
232249
expect(screen.queryByTestId("loading-indicator")).toBe(null);
233250
if (type !== "technique") {
234-
expect(
235-
container.textContent,
236-
`Rendered output for ${modId}:${type}:${id} contains invalid placeholder text.`,
237-
).not.toMatch(/undefined|NaN|object Object/);
251+
const renderedText = container.textContent ?? "";
252+
if (/undefined|NaN|object Object/.test(renderedText)) {
253+
throw new Error(
254+
`Rendered output for ${modId}:${type}:${id} contains invalid placeholder text.`,
255+
);
256+
}
238257
}
258+
unmount();
239259
},
240260
);
241261
});

0 commit comments

Comments
 (0)