mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-07-24 00:43:29 +10:00
refactor(v4.0.0-alpha): beginning of a new era
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
import { createId } from "@paralleldrive/cuid2";
|
||||
import {
|
||||
defaultCertification,
|
||||
defaultEducation,
|
||||
defaultExperience,
|
||||
defaultLanguage,
|
||||
defaultProfile,
|
||||
defaultProject,
|
||||
defaultResumeData,
|
||||
defaultSkill,
|
||||
ResumeData,
|
||||
resumeDataSchema,
|
||||
} from "@reactive-resume/schema";
|
||||
import { extractUrl, Json, parseCSV } from "@reactive-resume/utils";
|
||||
import * as JSZip from "jszip";
|
||||
import { Schema } from "zod";
|
||||
|
||||
import { Parser } from "../interfaces/parser";
|
||||
import { LinkedIn, linkedInSchema } from "./schema";
|
||||
|
||||
export * from "./schema";
|
||||
|
||||
export class LinkedInParser implements Parser<JSZip, LinkedIn> {
|
||||
schema: Schema;
|
||||
|
||||
constructor() {
|
||||
this.schema = linkedInSchema;
|
||||
}
|
||||
|
||||
async readFile(file: File): Promise<JSZip> {
|
||||
const data = await JSZip.loadAsync(file);
|
||||
|
||||
if (Object.keys(data.files).length === 0) {
|
||||
throw new Error("ParserError: There were no files found inside the zip archive.");
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
async validate(data: JSZip) {
|
||||
const result: Json = {};
|
||||
|
||||
for (const [name, file] of Object.entries(data.files)) {
|
||||
for (const key of Object.keys(linkedInSchema.shape)) {
|
||||
if (name.includes(key)) {
|
||||
const content = await file.async("text");
|
||||
const jsonArray = await parseCSV(content);
|
||||
result[key] = jsonArray;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return linkedInSchema.parse(result);
|
||||
}
|
||||
|
||||
convert(data: LinkedIn) {
|
||||
const result = JSON.parse(JSON.stringify(defaultResumeData)) as ResumeData;
|
||||
|
||||
// Profile
|
||||
if (data.Profile && data.Profile.length > 0) {
|
||||
const profile = data.Profile[0];
|
||||
const twitterHandle = profile["Twitter Handles"];
|
||||
|
||||
result.basics.name = `${profile["First Name"]} ${profile["Last Name"]}`;
|
||||
result.basics.location = profile["Geo Location"];
|
||||
result.basics.headline = profile.Headline;
|
||||
result.basics.url.href = extractUrl(profile.Websites) ?? "";
|
||||
result.sections.summary.content = profile.Summary;
|
||||
result.sections.profiles.items.push({
|
||||
...defaultProfile,
|
||||
id: createId(),
|
||||
icon: "twitter",
|
||||
network: "Twitter",
|
||||
username: twitterHandle,
|
||||
url: { ...defaultProfile.url, href: `https://twitter.com/${twitterHandle}` },
|
||||
});
|
||||
}
|
||||
|
||||
// Email Addresses
|
||||
if (data["Email Addresses"] && data["Email Addresses"].length > 0) {
|
||||
const email = data["Email Addresses"][0];
|
||||
|
||||
result.basics.email = email["Email Address"];
|
||||
}
|
||||
|
||||
// Positions
|
||||
if (data["Positions"] && data["Positions"].length > 0) {
|
||||
for (const position of data["Positions"]) {
|
||||
result.sections.experience.items.push({
|
||||
...defaultExperience,
|
||||
id: createId(),
|
||||
company: position["Company Name"],
|
||||
position: position.Title,
|
||||
location: position.Location,
|
||||
summary: position.Description ?? "",
|
||||
date: `${position["Started On"]} - ${position["Finished On"] ?? "Present"}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Education
|
||||
if (data["Education"] && data["Education"].length > 0) {
|
||||
for (const education of data["Education"]) {
|
||||
result.sections.education.items.push({
|
||||
...defaultEducation,
|
||||
id: createId(),
|
||||
institution: education["School Name"],
|
||||
studyType: education["Degree Name"],
|
||||
summary: education.Notes ?? "",
|
||||
date: `${education["Start Date"]} - ${education["End Date"] ?? "Present"}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Skills
|
||||
if (data["Skills"] && data["Skills"].length > 0) {
|
||||
for (const skill of data["Skills"]) {
|
||||
result.sections.skills.items.push({
|
||||
...defaultSkill,
|
||||
id: createId(),
|
||||
name: skill.Name,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Languages
|
||||
if (data["Languages"] && data["Languages"].length > 0) {
|
||||
for (const language of data["Languages"]) {
|
||||
result.sections.languages.items.push({
|
||||
...defaultLanguage,
|
||||
id: createId(),
|
||||
name: language.Name,
|
||||
fluency: language.Proficiency ?? "",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Certifications
|
||||
if (data["Certifications"] && data["Certifications"].length > 0) {
|
||||
for (const certification of data["Certifications"]) {
|
||||
result.sections.certifications.items.push({
|
||||
...defaultCertification,
|
||||
id: createId(),
|
||||
name: certification.Name,
|
||||
issuer: certification.Authority,
|
||||
url: { ...defaultCertification.url, href: certification.Url },
|
||||
date: `${certification["Started On"]} - ${certification["Finished On"] ?? "Present"}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Projects
|
||||
if (data["Projects"] && data["Projects"].length > 0) {
|
||||
for (const project of data["Projects"]) {
|
||||
result.sections.projects.items.push({
|
||||
...defaultProject,
|
||||
id: createId(),
|
||||
name: project.Title,
|
||||
description: project.Description,
|
||||
url: { ...defaultProject.url, href: project.Url },
|
||||
date: `${project["Started On"]} - ${project["Finished On"] ?? "Present"}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return resumeDataSchema.parse(result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const certificationSchema = z.object({
|
||||
Name: z.string(),
|
||||
Url: z.string().url(),
|
||||
Authority: z.string(),
|
||||
"Started On": z.string(),
|
||||
"Finished On": z.string().optional(),
|
||||
"License Number": z.string(),
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const educationSchema = z.object({
|
||||
"School Name": z.string(),
|
||||
"Start Date": z.string(),
|
||||
"End Date": z.string(),
|
||||
Notes: z.string().optional(),
|
||||
"Degree Name": z.string(),
|
||||
Activities: z.string(),
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const emailSchema = z.object({
|
||||
"Email Address": z.string().email(),
|
||||
Confirmed: z.enum(["Yes", "No"]),
|
||||
Primary: z.enum(["Yes", "No"]),
|
||||
"Updated On": z.string(),
|
||||
});
|
||||
@@ -0,0 +1,23 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { certificationSchema } from "./certification";
|
||||
import { educationSchema } from "./education";
|
||||
import { emailSchema } from "./email";
|
||||
import { languageSchema } from "./language";
|
||||
import { positionSchema } from "./position";
|
||||
import { profileSchema } from "./profile";
|
||||
import { projectSchema } from "./project";
|
||||
import { skillSchema } from "./skill";
|
||||
|
||||
export const linkedInSchema = z.object({
|
||||
Profile: z.array(profileSchema).optional(),
|
||||
"Email Addresses": z.array(emailSchema).optional(),
|
||||
Certifications: z.array(certificationSchema).optional(),
|
||||
Education: z.array(educationSchema).optional(),
|
||||
Languages: z.array(languageSchema).optional(),
|
||||
Positions: z.array(positionSchema).optional(),
|
||||
Projects: z.array(projectSchema).optional(),
|
||||
Skills: z.array(skillSchema).optional(),
|
||||
});
|
||||
|
||||
export type LinkedIn = z.infer<typeof linkedInSchema>;
|
||||
@@ -0,0 +1,6 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const languageSchema = z.object({
|
||||
Name: z.string(),
|
||||
Proficiency: z.string().optional(),
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const positionSchema = z.object({
|
||||
"Company Name": z.string(),
|
||||
Title: z.string(),
|
||||
Description: z.string().optional(),
|
||||
Location: z.string(),
|
||||
"Started On": z.string(),
|
||||
"Finished On": z.string().optional(),
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const profileSchema = z.object({
|
||||
"First Name": z.string(),
|
||||
"Last Name": z.string(),
|
||||
"Maiden Name": z.string().optional(),
|
||||
Address: z.string(),
|
||||
"Birth Date": z.string(),
|
||||
Headline: z.string(),
|
||||
Summary: z.string(),
|
||||
Industry: z.string(),
|
||||
"Zip Code": z.string().optional(),
|
||||
"Geo Location": z.string(),
|
||||
"Twitter Handles": z.string(),
|
||||
Websites: z.string(),
|
||||
"Instant Messengers": z.string().optional(),
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const projectSchema = z.object({
|
||||
Title: z.string(),
|
||||
Description: z.string(),
|
||||
Url: z.string().url(),
|
||||
"Started On": z.string(),
|
||||
"Finished On": z.string().optional(),
|
||||
});
|
||||
@@ -0,0 +1,5 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const skillSchema = z.object({
|
||||
Name: z.string(),
|
||||
});
|
||||
Reference in New Issue
Block a user