Files
Reactive-Resume/packages/import/src/reactive-resume-json.tsx
T
Amruth Pillai afd734dd61 refactor(import): add v4section/v4url aliases, inline clamp wrappers, replace classes with fns
Finding 5: Introduce V4Url + V4Section<T> type aliases in reactive-resume-v4-json.tsx; collapse
310-line V4ResumeData type (13x 5-field section header, 11x {label,href}) into typed aliases.
Inferred shape is structurally identical.

Finding 6: Remove 9 single-caller clamp/pxToPt wrappers; replace compile-time constants
(rotation=0, sidebarWidth=35, shadowWidth=0, gapX=4, gapY=6) with literals; inline dynamic
calls (clamp(x, 32, 512) etc.) at the two body/heading typography call sites.

Finding 7: Convert three stateless single-method importer classes to plain functions.
Extract shared rethrowAsImportError() to error.ts, replacing triplicated ZodError catch blocks.
Update web import dialog + all in-package test files to use function API.

Claude-Session: https://claude.ai/code/session_012Bnvt1MghwHj4qQRxuQUGa
2026-07-04 21:02:17 +02:00

76 lines
2.1 KiB
TypeScript

import type { ResumeData } from "@reactive-resume/schema/resume/data";
import { ZodError } from "zod";
import { resumeDataSchema, sectionTypeSchema } from "@reactive-resume/schema/resume/data";
import { rethrowAsImportError } from "./error";
const BUILT_IN_LAYOUT_SECTION_IDS = sectionTypeSchema.options.filter((section) => section !== "cover-letter");
function normalizeBuiltInSectionsInLayout(data: ResumeData): ResumeData {
const pages = data.metadata.layout.pages;
// Some exported resumes can arrive without any persisted layout pages.
if (pages.length === 0) {
return {
...data,
metadata: {
...data.metadata,
layout: {
...data.metadata.layout,
pages: [
{
fullWidth: false,
main: [...BUILT_IN_LAYOUT_SECTION_IDS],
sidebar: [],
},
],
},
},
};
}
const existingSectionIds = new Set<string>();
// Preserve the imported layout and only compute which built-in IDs are missing entirely.
for (const page of pages) {
for (const sectionId of page.main) existingSectionIds.add(sectionId);
for (const sectionId of page.sidebar) existingSectionIds.add(sectionId);
}
const missingSectionIds = BUILT_IN_LAYOUT_SECTION_IDS.filter((sectionId) => !existingSectionIds.has(sectionId));
if (missingSectionIds.length === 0) return data;
const [firstPage, ...restPages] = pages;
if (!firstPage) return data;
return {
...data,
metadata: {
...data.metadata,
layout: {
...data.metadata.layout,
pages: [
{
fullWidth: firstPage.fullWidth ?? false,
sidebar: firstPage.sidebar ?? [],
// Recover missing built-in sections without reordering the imported layout.
main: [...firstPage.main, ...missingSectionIds],
},
...restPages,
],
},
},
};
}
// ponytail: stateless single-method class → plain function
export function parseReactiveResumeJSON(json: string): ResumeData {
try {
const parsed = resumeDataSchema.parse(JSON.parse(json));
return resumeDataSchema.parse(normalizeBuiltInSectionsInLayout(parsed));
} catch (error) {
if (error instanceof ZodError) rethrowAsImportError(error);
throw error;
}
}