ajustacv-resume-schema 0.1.0 → 0.2.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 CHANGED
@@ -51,13 +51,16 @@ import { FULL_RESUME, RESUME_FIXTURES } from "ajustacv-resume-schema/fixtures";
51
51
  ```
52
52
  ResumeDocument
53
53
  ├── header ResumeHeader name, headline, contacts, links, optional photo
54
- ├── sections ResumeSection[] ordered; discriminated union over 8 types
54
+ ├── sections ResumeSection[] ordered; discriminated union over 10 types
55
55
  ├── design DesignSettings templateId, free-hex accent, curated fontId, A4
56
56
  └── meta DocumentMeta schemaVersion, targetRole, nullable ownerId
57
57
  ```
58
58
 
59
- The eight section types are `summary`, `experience`, `education`, `skills`,
60
- `languages`, `certifications`, `projects` and `custom`. `custom` is the
59
+ The ten section types are `summary`, `experience`, `education`, `skills`,
60
+ `languages`, `certifications`, `projects`, `achievements`, `strengths` and
61
+ `custom`. `achievements` and `strengths` share one entry shape — a title and a
62
+ one-line description — and exist as their own types so a template can set them
63
+ apart and an ATS can read them as what they are. `custom` is the
61
64
  catch-all that keeps parsing lossless — content an extractor cannot classify
62
65
  lands there rather than being dropped. Duplicates are allowed: a resume may
63
66
  carry two `custom` sections, or two `experience` ones.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ajustacv-resume-schema",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Canonical ResumeDocument schema, validators and fixtures shared by ajustacv.com and api.ajustacv.com",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {
package/src/fixtures.ts CHANGED
@@ -18,7 +18,7 @@ function fixture(input: ResumeDocumentInput): ResumeDocument {
18
18
  return assertResumeDocument(input);
19
19
  }
20
20
 
21
- // A realistic pt-BR resume exercising all eight section types, inline
21
+ // A realistic pt-BR resume exercising all ten section types, inline
22
22
  // markdown, dates with and without a month, an ongoing role, a hidden field
23
23
  // and a manual page break — the document template work is developed against.
24
24
  export const FULL_RESUME: ResumeDocument = fixture({
@@ -181,6 +181,29 @@ export const FULL_RESUME: ResumeDocument = fixture({
181
181
  },
182
182
  ],
183
183
  },
184
+ {
185
+ id: "s-achv",
186
+ type: "achievements",
187
+ title: "Conquistas",
188
+ visible: true,
189
+ entries: [
190
+ {
191
+ id: "a1",
192
+ title: "Prêmio Inovação 2023",
193
+ description: "Reconhecimento interno pela automação que **cortou 40%** do tempo de deploy.",
194
+ },
195
+ ],
196
+ },
197
+ {
198
+ id: "s-str",
199
+ type: "strengths",
200
+ title: "Pontos fortes",
201
+ visible: true,
202
+ entries: [
203
+ { id: "st1", title: "Liderança técnica", description: "Conduzi 3 squads em migrações sem downtime." },
204
+ { id: "st2", title: "Comunicação", description: "Traduzo decisões técnicas para o negócio." },
205
+ ],
206
+ },
184
207
  {
185
208
  id: "s-custom",
186
209
  type: "custom",
@@ -292,12 +315,26 @@ export const ALL_SECTION_TYPES_RESUME: ResumeDocument = fixture({
292
315
  visible: true,
293
316
  entries: [{ id: "t-proj-1", name: "Painel COVID-RJ", description: "Painel público de indicadores." }],
294
317
  },
318
+ {
319
+ id: "t-achv",
320
+ type: "achievements",
321
+ title: "Conquistas",
322
+ visible: true,
323
+ entries: [{ id: "t-achv-1", title: "Menção honrosa", description: "Hackathon de dados abertos, 2021." }],
324
+ },
325
+ {
326
+ id: "t-str",
327
+ type: "strengths",
328
+ title: "Pontos fortes",
329
+ visible: true,
330
+ entries: [{ id: "t-str-1", title: "Rigor analítico", description: "Valido toda hipótese contra os dados." }],
331
+ },
295
332
  {
296
333
  id: "t-custom",
297
334
  type: "custom",
298
335
  title: "Prêmios",
299
336
  visible: true,
300
- entries: [{ id: "t-custom-1", title: "Menção honrosa", bullets: [] }],
337
+ entries: [{ id: "t-custom-1", title: "Finalista do Prêmio Nacional de Dados", bullets: [] }],
301
338
  },
302
339
  // A renamed, hidden section: the content survives, templates skip it.
303
340
  {
package/src/schema.ts CHANGED
@@ -197,6 +197,21 @@ export const ProjectEntrySchema = z.object({
197
197
  dateRange: DateRangeSchema.nullable().default(null),
198
198
  });
199
199
 
200
+ // Achievements and strengths (#69) share one shape — a short title and one
201
+ // line of prose — but are distinct types: a template may set "Conquistas"
202
+ // apart, and an ATS reads "Prêmios" and "Pontos fortes" as different signals.
203
+ export const AchievementEntrySchema = z.object({
204
+ ...entryBase,
205
+ title: shortText,
206
+ description: RichLineSchema,
207
+ });
208
+
209
+ export const StrengthEntrySchema = z.object({
210
+ ...entryBase,
211
+ title: shortText,
212
+ description: RichLineSchema,
213
+ });
214
+
200
215
  // The catch-all that keeps parsing lossless: anything the extractor cannot
201
216
  // map to a typed section still lands here rather than being dropped.
202
217
  export const CustomEntrySchema = z.object({
@@ -217,6 +232,8 @@ export const SECTION_TYPES = [
217
232
  "languages",
218
233
  "certifications",
219
234
  "projects",
235
+ "achievements",
236
+ "strengths",
220
237
  "custom",
221
238
  ] as const;
222
239
 
@@ -242,6 +259,8 @@ export const ResumeSectionSchema = z.discriminatedUnion("type", [
242
259
  z.object({ ...sectionBase, type: z.literal("languages"), entries: entryList(LanguageEntrySchema) }),
243
260
  z.object({ ...sectionBase, type: z.literal("certifications"), entries: entryList(CertificationEntrySchema) }),
244
261
  z.object({ ...sectionBase, type: z.literal("projects"), entries: entryList(ProjectEntrySchema) }),
262
+ z.object({ ...sectionBase, type: z.literal("achievements"), entries: entryList(AchievementEntrySchema) }),
263
+ z.object({ ...sectionBase, type: z.literal("strengths"), entries: entryList(StrengthEntrySchema) }),
245
264
  z.object({ ...sectionBase, type: z.literal("custom"), entries: entryList(CustomEntrySchema) }),
246
265
  ]);
247
266
 
@@ -306,6 +325,8 @@ export type SkillGroup = z.infer<typeof SkillGroupSchema>;
306
325
  export type LanguageEntry = z.infer<typeof LanguageEntrySchema>;
307
326
  export type CertificationEntry = z.infer<typeof CertificationEntrySchema>;
308
327
  export type ProjectEntry = z.infer<typeof ProjectEntrySchema>;
328
+ export type AchievementEntry = z.infer<typeof AchievementEntrySchema>;
329
+ export type StrengthEntry = z.infer<typeof StrengthEntrySchema>;
309
330
  export type CustomEntry = z.infer<typeof CustomEntrySchema>;
310
331
  export type SectionType = z.infer<typeof SectionTypeSchema>;
311
332
  export type ResumeSection = z.infer<typeof ResumeSectionSchema>;