From 00777524569abbc834bf65bc722fd86b7c812a49 Mon Sep 17 00:00:00 2001 From: Till JS Date: Mon, 20 Apr 2026 15:53:07 +0200 Subject: [PATCH] =?UTF-8?q?fix(type-check):=20clear=20the=20last=20five=20?= =?UTF-8?q?failures=20=E2=80=94=20monorepo=20type-check=20is=20now=2076/76?= =?UTF-8?q?=20green?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After the mobile-app deletion unblocked \`@context/mobile\`, five more pre-existing failures surfaced across shared packages and two services. All were silent-masked by the postinstall \`|| true\` for months. - **shared-ai**: \`planner/loop.ts\` imported \`ToolSchema\` from \`../tools/function-schema\`, which only imports (not re-exports) the type. Fixed to import from the source (\`../tools/schemas\`). - **shared-logger**: \`typeof window !== 'undefined'\` blows up under tsconfigs that don't include the DOM lib (e.g. uload-server's \`bun-types\`-only config), because shared-logger is consumed via source import. Replaced with a \`globalThis\`-indirected check that compiles under any lib configuration. - **shared-hono**: \`credits.ts\` returned \`res.json()\` directly as \`Promise\`. Modern \`@types/node\` / undici types return \`unknown\` strictly — cast to \`T\` at the boundary so the generic contract is explicit. - **uload-server**: \`routes/analytics.ts\` + \`routes/email.ts\` still imported \`AuthUser\` from a \`middleware/jwt-auth\` module that was deleted during the migration to \`@mana/shared-hono\`. Replaced with \`AuthVariables\` from shared-hono, which matches the actual context shape set by \`authMiddleware()\`. - **manavoxel/web**: \`guestSeed\` collection entries were wrapped in arrow functions, but \`local-store\` expects \`T[]\` directly and iterates \`seed.length\` — which on a function is 0. The "guest seed" was silently dead; eager-evaluating \`generateGuestWorld()\` once and sharing the result fixes both the type and the runtime. Verified: \`pnpm run type-check\` from the repo root now exits 0 — 76/76 tasks successful, no failures. First fully green state since well before the postinstall \`|| true\` was introduced. Co-Authored-By: Claude Opus 4.7 (1M context) --- apps/manavoxel/apps/web/src/lib/data/local-store.ts | 13 ++++++++++--- apps/uload/apps/server/src/routes/analytics.ts | 4 ++-- apps/uload/apps/server/src/routes/email.ts | 4 ++-- packages/shared-ai/src/planner/loop.ts | 3 ++- packages/shared-hono/src/credits.ts | 2 +- packages/shared-logger/src/index.ts | 5 ++++- packages/shared-logger/tsconfig.json | 1 + 7 files changed, 22 insertions(+), 10 deletions(-) diff --git a/apps/manavoxel/apps/web/src/lib/data/local-store.ts b/apps/manavoxel/apps/web/src/lib/data/local-store.ts index 1391666e1..4263774e2 100644 --- a/apps/manavoxel/apps/web/src/lib/data/local-store.ts +++ b/apps/manavoxel/apps/web/src/lib/data/local-store.ts @@ -85,23 +85,30 @@ export function decodeBytes(base64: string): Uint8Array { const SYNC_SERVER_URL = import.meta.env.PUBLIC_SYNC_SERVER_URL || 'http://localhost:3050'; +// @mana/local-store's CollectionDef.guestSeed expects `T[]` (the seed +// array itself), not a lazy producer. The previous three arrow-wrappers +// looked lazy but the framework never awaited them — it iterated them +// as `seed.length`, which against a function silently yielded 0 (dead +// seed). Evaluate once and share. +const guestSeed = generateGuestWorld(); + export const gameStore = createLocalStore({ appId: 'manavoxel', collections: [ { name: 'worlds', indexes: ['creatorId', 'isPublished', 'name', 'template'], - guestSeed: () => generateGuestWorld().worlds, + guestSeed: guestSeed.worlds, }, { name: 'areas', indexes: ['worldId', 'type', '[worldId+name]'], - guestSeed: () => generateGuestWorld().areas, + guestSeed: guestSeed.areas, }, { name: 'items', indexes: ['creatorId', 'rarity', 'isPublished', 'name'], - guestSeed: () => generateGuestWorld().items, + guestSeed: guestSeed.items, }, { name: 'inventories', diff --git a/apps/uload/apps/server/src/routes/analytics.ts b/apps/uload/apps/server/src/routes/analytics.ts index b81e84f47..469b0f332 100644 --- a/apps/uload/apps/server/src/routes/analytics.ts +++ b/apps/uload/apps/server/src/routes/analytics.ts @@ -1,9 +1,9 @@ import { Hono } from 'hono'; +import type { AuthVariables } from '@mana/shared-hono'; import type { AnalyticsService } from '../services/analytics'; -import type { AuthUser } from '../middleware/jwt-auth'; export function createAnalyticsRoutes(analyticsService: AnalyticsService) { - return new Hono<{ Variables: { user: AuthUser } }>() + return new Hono<{ Variables: AuthVariables }>() .get('/:linkId', async (c) => { const linkId = c.req.param('linkId'); const stats = await analyticsService.getClickStats(linkId); diff --git a/apps/uload/apps/server/src/routes/email.ts b/apps/uload/apps/server/src/routes/email.ts index 56d302873..1b04b72c2 100644 --- a/apps/uload/apps/server/src/routes/email.ts +++ b/apps/uload/apps/server/src/routes/email.ts @@ -1,8 +1,8 @@ import { Hono } from 'hono'; -import type { AuthUser } from '../middleware/jwt-auth'; +import type { AuthVariables } from '@mana/shared-hono'; export function createEmailRoutes() { - return new Hono<{ Variables: { user: AuthUser } }>().post('/send-invitation', async (c) => { + return new Hono<{ Variables: AuthVariables }>().post('/send-invitation', async (c) => { // TODO: Implement with Resend return c.json({ error: 'Email not configured yet' }, 501); }); diff --git a/packages/shared-ai/src/planner/loop.ts b/packages/shared-ai/src/planner/loop.ts index 0a12241e2..d3bf8b525 100644 --- a/packages/shared-ai/src/planner/loop.ts +++ b/packages/shared-ai/src/planner/loop.ts @@ -10,7 +10,8 @@ * ``onToolCall`` callback. The loop itself stays pure. */ -import type { ToolSchema, ToolSpec } from '../tools/function-schema'; +import type { ToolSchema } from '../tools/schemas'; +import type { ToolSpec } from '../tools/function-schema'; import { toolsToFunctionSchemas } from '../tools/function-schema'; // ─── Chat-message contract ────────────────────────────────────────── diff --git a/packages/shared-hono/src/credits.ts b/packages/shared-hono/src/credits.ts index 1fec7da5c..c090513f6 100644 --- a/packages/shared-hono/src/credits.ts +++ b/packages/shared-hono/src/credits.ts @@ -42,7 +42,7 @@ async function callCredits(path: string, options: RequestInit = {}): Promise< }, }); if (!res.ok) return null; - return res.json(); + return (await res.json()) as T; } catch (error) { console.error('[credits] Request failed:', error); return null; diff --git a/packages/shared-logger/src/index.ts b/packages/shared-logger/src/index.ts index f789d7d2f..aa13acdc5 100644 --- a/packages/shared-logger/src/index.ts +++ b/packages/shared-logger/src/index.ts @@ -15,7 +15,10 @@ declare const __DEV__: boolean | undefined; const isDevelopment = typeof __DEV__ !== 'undefined' ? __DEV__ : process.env.NODE_ENV === 'development'; -const isBrowser = typeof window !== 'undefined'; +// Use a globalThis indirection instead of `typeof window` so this module +// stays compilable under tsconfigs that don't pull in the DOM lib (e.g. +// Bun-only services consuming shared-logger via workspace source imports). +const isBrowser = typeof (globalThis as { window?: unknown }).window !== 'undefined'; const useJson = process.env.LOGGER_FORMAT === 'json' || diff --git a/packages/shared-logger/tsconfig.json b/packages/shared-logger/tsconfig.json index d92f40466..ded446c46 100644 --- a/packages/shared-logger/tsconfig.json +++ b/packages/shared-logger/tsconfig.json @@ -3,6 +3,7 @@ "target": "ES2022", "module": "ESNext", "moduleResolution": "bundler", + "lib": ["ES2022", "DOM"], "esModuleInterop": true, "strict": true, "skipLibCheck": true,