@pranavraut033/ats-checker 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,47 @@
1
+ # ats-checker
2
+
3
+ Deterministic, configurable ATS (Applicant Tracking System) compatibility checker with no external dependencies. Provides a single entry point `analyzeResume()` and extensible configuration for weights, skills, rules, and profiles.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install ats-checker
9
+ ```
10
+
11
+ ## Quick start
12
+
13
+ ```ts
14
+ import { analyzeResume } from "ats-checker";
15
+
16
+ const { score, breakdown, suggestions } = analyzeResume({
17
+ resumeText: "...",
18
+ jobDescription: "..."
19
+ });
20
+ ```
21
+
22
+ ## Configuration
23
+
24
+ - **weights**: adjust scoring weight for skills, experience, keywords, and education.
25
+ - **skillAliases**: normalize synonyms to canonical skills.
26
+ - **profile**: specify mandatory/optional skills and minimum years of experience.
27
+ - **rules**: add custom penalties via functions that inspect parsed resume/job data.
28
+
29
+ See `src/types` for full type definitions.
30
+
31
+ ## Development
32
+
33
+ ```bash
34
+ npm install
35
+ npm run build
36
+ npm test
37
+ ```
38
+
39
+ ## Features
40
+
41
+ - Zero runtime dependencies
42
+ - Deterministic, explainable scoring (0-100)
43
+ - Customizable weights, rules, and industry profiles
44
+ - Parses resumes and job descriptions
45
+ - Detects ATS-unfriendly patterns (tables, keyword stuffing)
46
+ - Generates actionable suggestions
47
+
@@ -0,0 +1,135 @@
1
+ type ResumeSection = "summary" | "experience" | "skills" | "education" | "projects" | "certifications";
2
+ interface ParsedDateRange {
3
+ raw?: string;
4
+ start?: string;
5
+ end?: string;
6
+ durationInMonths?: number;
7
+ }
8
+ interface ParsedExperienceEntry {
9
+ title?: string;
10
+ company?: string;
11
+ location?: string;
12
+ dates?: ParsedDateRange;
13
+ description?: string;
14
+ }
15
+ interface ParsedResume {
16
+ raw: string;
17
+ normalizedText: string;
18
+ detectedSections: ResumeSection[];
19
+ sectionContent: Partial<Record<ResumeSection, string>>;
20
+ skills: string[];
21
+ jobTitles: string[];
22
+ actionVerbs: string[];
23
+ educationEntries: string[];
24
+ experience: ParsedExperienceEntry[];
25
+ totalExperienceYears: number;
26
+ keywords: string[];
27
+ warnings: string[];
28
+ }
29
+ interface ParsedJobDescription {
30
+ raw: string;
31
+ normalizedText: string;
32
+ requiredSkills: string[];
33
+ preferredSkills: string[];
34
+ roleKeywords: string[];
35
+ keywords: string[];
36
+ minExperienceYears?: number;
37
+ educationRequirements: string[];
38
+ }
39
+
40
+ interface ATSWeights {
41
+ skills: number;
42
+ experience: number;
43
+ keywords: number;
44
+ education: number;
45
+ }
46
+ type SkillAliases = Record<string, string[]>;
47
+ interface ATSProfile {
48
+ name: string;
49
+ mandatorySkills: string[];
50
+ optionalSkills: string[];
51
+ minExperience?: number;
52
+ }
53
+ interface KeywordDensityConfig {
54
+ /** Minimum density before a keyword is considered underused (informational only). */
55
+ min: number;
56
+ /** Maximum density before a keyword is considered stuffed. */
57
+ max: number;
58
+ /** Penalty applied when density exceeds max. */
59
+ overusePenalty: number;
60
+ }
61
+ interface SectionPenaltyConfig {
62
+ missingSummary?: number;
63
+ missingExperience?: number;
64
+ missingSkills?: number;
65
+ missingEducation?: number;
66
+ }
67
+ interface ATSRule {
68
+ id: string;
69
+ description?: string;
70
+ penalty: number;
71
+ warning?: string;
72
+ condition: (context: RuleContext) => boolean;
73
+ }
74
+ interface ATSConfig {
75
+ weights?: Partial<ATSWeights>;
76
+ skillAliases?: SkillAliases;
77
+ profile?: ATSProfile;
78
+ rules?: ATSRule[];
79
+ keywordDensity?: KeywordDensityConfig;
80
+ sectionPenalties?: SectionPenaltyConfig;
81
+ allowPartialMatches?: boolean;
82
+ }
83
+ interface NormalizedWeights extends ATSWeights {
84
+ /** Weights normalized so they sum to 1. */
85
+ normalizedTotal: number;
86
+ }
87
+ interface ResolvedATSConfig {
88
+ weights: NormalizedWeights;
89
+ skillAliases: SkillAliases;
90
+ profile?: ATSProfile;
91
+ rules: ATSRule[];
92
+ keywordDensity: KeywordDensityConfig;
93
+ sectionPenalties: Required<SectionPenaltyConfig>;
94
+ allowPartialMatches: boolean;
95
+ }
96
+ interface RuleContext {
97
+ resume: ParsedResume;
98
+ job: ParsedJobDescription;
99
+ weights: NormalizedWeights;
100
+ keywordDensity: KeywordDensityConfig;
101
+ breakdown?: ATSBreakdown;
102
+ matchedKeywords?: string[];
103
+ overusedKeywords?: string[];
104
+ }
105
+
106
+ interface ATSBreakdown {
107
+ skills: number;
108
+ experience: number;
109
+ keywords: number;
110
+ education: number;
111
+ }
112
+ interface AnalyzeResumeInput {
113
+ resumeText: string;
114
+ jobDescription: string;
115
+ config?: ATSConfig;
116
+ }
117
+ interface ATSAnalysisResult {
118
+ score: number;
119
+ breakdown: ATSBreakdown;
120
+ matchedKeywords: string[];
121
+ missingKeywords: string[];
122
+ overusedKeywords: string[];
123
+ suggestions: string[];
124
+ warnings: string[];
125
+ }
126
+
127
+ declare const defaultSkillAliases: SkillAliases;
128
+ declare const defaultProfiles: ATSProfile[];
129
+
130
+ /**
131
+ * Analyze a resume against a job description using deterministic, explainable rules.
132
+ */
133
+ declare function analyzeResume(input: AnalyzeResumeInput): ATSAnalysisResult;
134
+
135
+ export { type ATSAnalysisResult, type ATSBreakdown, type ATSConfig, type ATSProfile, type ATSRule, type ATSWeights, type AnalyzeResumeInput, type KeywordDensityConfig, type NormalizedWeights, type ParsedDateRange, type ParsedExperienceEntry, type ParsedJobDescription, type ParsedResume, type ResolvedATSConfig, type ResumeSection, type RuleContext, type SectionPenaltyConfig, type SkillAliases, analyzeResume, defaultProfiles, defaultSkillAliases };
@@ -0,0 +1,135 @@
1
+ type ResumeSection = "summary" | "experience" | "skills" | "education" | "projects" | "certifications";
2
+ interface ParsedDateRange {
3
+ raw?: string;
4
+ start?: string;
5
+ end?: string;
6
+ durationInMonths?: number;
7
+ }
8
+ interface ParsedExperienceEntry {
9
+ title?: string;
10
+ company?: string;
11
+ location?: string;
12
+ dates?: ParsedDateRange;
13
+ description?: string;
14
+ }
15
+ interface ParsedResume {
16
+ raw: string;
17
+ normalizedText: string;
18
+ detectedSections: ResumeSection[];
19
+ sectionContent: Partial<Record<ResumeSection, string>>;
20
+ skills: string[];
21
+ jobTitles: string[];
22
+ actionVerbs: string[];
23
+ educationEntries: string[];
24
+ experience: ParsedExperienceEntry[];
25
+ totalExperienceYears: number;
26
+ keywords: string[];
27
+ warnings: string[];
28
+ }
29
+ interface ParsedJobDescription {
30
+ raw: string;
31
+ normalizedText: string;
32
+ requiredSkills: string[];
33
+ preferredSkills: string[];
34
+ roleKeywords: string[];
35
+ keywords: string[];
36
+ minExperienceYears?: number;
37
+ educationRequirements: string[];
38
+ }
39
+
40
+ interface ATSWeights {
41
+ skills: number;
42
+ experience: number;
43
+ keywords: number;
44
+ education: number;
45
+ }
46
+ type SkillAliases = Record<string, string[]>;
47
+ interface ATSProfile {
48
+ name: string;
49
+ mandatorySkills: string[];
50
+ optionalSkills: string[];
51
+ minExperience?: number;
52
+ }
53
+ interface KeywordDensityConfig {
54
+ /** Minimum density before a keyword is considered underused (informational only). */
55
+ min: number;
56
+ /** Maximum density before a keyword is considered stuffed. */
57
+ max: number;
58
+ /** Penalty applied when density exceeds max. */
59
+ overusePenalty: number;
60
+ }
61
+ interface SectionPenaltyConfig {
62
+ missingSummary?: number;
63
+ missingExperience?: number;
64
+ missingSkills?: number;
65
+ missingEducation?: number;
66
+ }
67
+ interface ATSRule {
68
+ id: string;
69
+ description?: string;
70
+ penalty: number;
71
+ warning?: string;
72
+ condition: (context: RuleContext) => boolean;
73
+ }
74
+ interface ATSConfig {
75
+ weights?: Partial<ATSWeights>;
76
+ skillAliases?: SkillAliases;
77
+ profile?: ATSProfile;
78
+ rules?: ATSRule[];
79
+ keywordDensity?: KeywordDensityConfig;
80
+ sectionPenalties?: SectionPenaltyConfig;
81
+ allowPartialMatches?: boolean;
82
+ }
83
+ interface NormalizedWeights extends ATSWeights {
84
+ /** Weights normalized so they sum to 1. */
85
+ normalizedTotal: number;
86
+ }
87
+ interface ResolvedATSConfig {
88
+ weights: NormalizedWeights;
89
+ skillAliases: SkillAliases;
90
+ profile?: ATSProfile;
91
+ rules: ATSRule[];
92
+ keywordDensity: KeywordDensityConfig;
93
+ sectionPenalties: Required<SectionPenaltyConfig>;
94
+ allowPartialMatches: boolean;
95
+ }
96
+ interface RuleContext {
97
+ resume: ParsedResume;
98
+ job: ParsedJobDescription;
99
+ weights: NormalizedWeights;
100
+ keywordDensity: KeywordDensityConfig;
101
+ breakdown?: ATSBreakdown;
102
+ matchedKeywords?: string[];
103
+ overusedKeywords?: string[];
104
+ }
105
+
106
+ interface ATSBreakdown {
107
+ skills: number;
108
+ experience: number;
109
+ keywords: number;
110
+ education: number;
111
+ }
112
+ interface AnalyzeResumeInput {
113
+ resumeText: string;
114
+ jobDescription: string;
115
+ config?: ATSConfig;
116
+ }
117
+ interface ATSAnalysisResult {
118
+ score: number;
119
+ breakdown: ATSBreakdown;
120
+ matchedKeywords: string[];
121
+ missingKeywords: string[];
122
+ overusedKeywords: string[];
123
+ suggestions: string[];
124
+ warnings: string[];
125
+ }
126
+
127
+ declare const defaultSkillAliases: SkillAliases;
128
+ declare const defaultProfiles: ATSProfile[];
129
+
130
+ /**
131
+ * Analyze a resume against a job description using deterministic, explainable rules.
132
+ */
133
+ declare function analyzeResume(input: AnalyzeResumeInput): ATSAnalysisResult;
134
+
135
+ export { type ATSAnalysisResult, type ATSBreakdown, type ATSConfig, type ATSProfile, type ATSRule, type ATSWeights, type AnalyzeResumeInput, type KeywordDensityConfig, type NormalizedWeights, type ParsedDateRange, type ParsedExperienceEntry, type ParsedJobDescription, type ParsedResume, type ResolvedATSConfig, type ResumeSection, type RuleContext, type SectionPenaltyConfig, type SkillAliases, analyzeResume, defaultProfiles, defaultSkillAliases };