Skip to content

Commit 3cb8c6b

Browse files
committed
fix(quoteforge[typecheck]): split tsconfig for src/studio and fix remaining type errors
1 parent b2f137c commit 3cb8c6b

13 files changed

Lines changed: 62 additions & 17 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"qf": "./src/cli/index.ts"
99
},
1010
"scripts": {
11-
"typecheck": "tsc --noEmit",
11+
"typecheck": "tsc --noEmit && tsc --noEmit -p studio",
1212
"quoteforge": "bun run src/cli/index.ts",
1313
"qf": "bun run src/cli/index.ts",
1414
"build:binary": "bun run scripts/build-binaries.ts",

src/__tests__/image-resolver.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,9 @@ describe("resolveImageBlocks", () => {
7171
],
7272
};
7373
const out = resolveImageBlocks(deck, dir);
74-
expect(out.slides[0].blocks[0]).toEqual({ type: "text", content: "unchanged" });
75-
expect((out.slides[0].blocks[1] as { src: string }).src.startsWith("data:image/png;base64,")).toBe(true);
74+
const slide = out.slides[0]!;
75+
expect(slide.blocks[0]).toEqual({ type: "text", content: "unchanged" });
76+
expect((slide.blocks[1] as { src: string }).src.startsWith("data:image/png;base64,")).toBe(true);
7677
});
7778
});
7879

src/__tests__/slide-renderer.test.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { buildSlideCardContent } from "../renderer/slide-renderer.js";
33
import { resolveDimensions } from "../renderer/dimensions.js";
44
import type { DeckContent } from "../cli/utils/validator.js";
55

6+
type DeckSlide = DeckContent["slides"][number];
7+
68
function makeDeck(overrides: Partial<DeckContent["defaults"]>): DeckContent {
79
return {
810
type: "deck",
@@ -36,9 +38,9 @@ describe("buildSlideCardContent", () => {
3638

3739
test("uses per-slide custom width/height when defaults are a preset", () => {
3840
const deck = makeDeck({ size: "instagram-sq" });
39-
const slide = {
41+
const slide: DeckSlide = {
4042
id: "slide-1",
41-
size: "custom" as const,
43+
size: "custom",
4244
width: 500,
4345
height: 700,
4446
blocks: [{ type: "text", content: "hello" }],
@@ -54,9 +56,9 @@ describe("buildSlideCardContent", () => {
5456

5557
test("slide preset override with custom defaults uses preset dimensions", () => {
5658
const deck = makeDeck({ size: "custom", width: 1200, height: 900 });
57-
const slide = {
59+
const slide: DeckSlide = {
5860
id: "slide-1",
59-
size: "instagram-sq" as const,
61+
size: "instagram-sq",
6062
blocks: [{ type: "text", content: "hello" }],
6163
};
6264

src/cli/commands/new.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export const newCommand = new Command("new")
8585
message: "Filename (without .json):",
8686
placeholder: type === "deck" ? "my-deck" : "my-card",
8787
validate: (val) => {
88-
if (!val.trim()) return "Name is required";
88+
if (!val || !val.trim()) return "Name is required";
8989
if (!/^[a-z0-9-]+$/.test(val)) return "Use kebab-case (lowercase, hyphens only)";
9090
return undefined;
9191
},

src/cli/utils/validator.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export const SIZES = {
2525
"custom": { w: 0, h: 0, ratio: "free", label: "Custom dimensions" },
2626
} as const;
2727

28-
const sizeNames = Object.keys(SIZES) as [string, ...string[]];
28+
const sizeNames = Object.keys(SIZES) as [keyof typeof SIZES, ...(keyof typeof SIZES)[]];
2929
export const SizeNameSchema = z.enum(sizeNames);
3030
export type SizeName = z.infer<typeof SizeNameSchema>;
3131

src/renderer/template-engine.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ export function initials(name: string): string {
112112
const parts = name.trim().split(/\s+/).filter(Boolean);
113113
if (parts.length === 0) return "";
114114
if (parts.length === 1) return parts[0]!.slice(0, 2).toUpperCase();
115-
return (parts[0]![0] + parts[parts.length - 1]![0]).toUpperCase();
115+
return (parts[0]![0]! + parts[parts.length - 1]![0]!).toUpperCase();
116116
}
117117

118118
env.addGlobal("initials", initials);

src/server/routes/export.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export async function exportRoute(req: Request): Promise<Response> {
3131

3232
const buf = await renderCard(body.card, theme, body.size, body.scale ?? 2, undefined, undefined, body.fitContent ?? false);
3333

34-
return new Response(buf, {
34+
return new Response(new Uint8Array(buf), {
3535
headers: {
3636
"Content-Type": "image/png",
3737
"Content-Disposition": "attachment; filename=quoteforge-export.png",

src/server/routes/exportDeck.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export async function exportDeckRoute(req: Request): Promise<Response> {
2020

2121
const zipBuf = await buildZip(buffers, names);
2222

23-
return new Response(zipBuf, {
23+
return new Response(new Uint8Array(zipBuf), {
2424
headers: {
2525
"Content-Type": "application/zip",
2626
"Content-Disposition": "attachment; filename=quoteforge-deck.zip",

src/server/routes/themes.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ export async function themesRoute(req: Request, url: URL): Promise<Response> {
2222
const nameMatch = url.pathname.match(/^\/api\/themes\/([^/]+)$/);
2323
if (req.method === "PUT" && nameMatch) {
2424
const name = nameMatch[1];
25+
if (!name) {
26+
return new Response("Not found", { status: 404 });
27+
}
2528
const body = await req.json();
2629
const theme = ThemeSchema.parse(body);
2730
const filePath = resolveThemeWrite(name);

studio/src/components/ui/ErrorBoundary.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,19 @@ interface State {
1212
}
1313

1414
export class ErrorBoundary extends Component<Props, State> {
15-
state: State = { hasError: false, error: null };
15+
override state: State = { hasError: false, error: null };
1616

1717
static getDerivedStateFromError(error: Error): State {
1818
return { hasError: true, error: error.message };
1919
}
2020

21-
componentDidCatch(error: Error, info: ErrorInfo) {
21+
override componentDidCatch(error: Error, info: ErrorInfo) {
2222
if (import.meta.env.DEV) {
2323
console.error(`[ErrorBoundary] ${this.props.fallback}:`, error, info);
2424
}
2525
}
2626

27-
render() {
27+
override render() {
2828
if (this.state.hasError) {
2929
return (
3030
<div className="flex items-center justify-center h-full p-6">

0 commit comments

Comments
 (0)