tylersong 1.0.11 โ†’ 1.0.13

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.
@@ -0,0 +1,121 @@
1
+ # ๐Ÿ”’ ๊ฐœ์ธ์ •๋ณด ๋ณด์•ˆ ์ ๊ฒ€ ๋ณด๊ณ ์„œ
2
+
3
+ **์ ๊ฒ€ ์ผ์‹œ**: 2025-12-15
4
+ **์ ๊ฒ€ ๋Œ€์ƒ**: npmjs ๋ฐฐํฌ ์‹œ ๊ฐœ์ธ์ •๋ณด ๋…ธ์ถœ ์—ฌ๋ถ€
5
+ **์ ๊ฒ€ ๋ฐฉ๋ฒ•**: `.npmignore` ํŒŒ์ผ ํ™•์ธ, `npm pack --dry-run` ์‹œ๋ฎฌ๋ ˆ์ด์…˜
6
+
7
+ ## โœ… ๋ณด์•ˆ ์ƒํƒœ: ์•ˆ์ „
8
+
9
+ ### 1. ๋ฏผ๊ฐํ•œ ์ •๋ณด ํ™•์ธ
10
+
11
+ #### โœ… ์•ˆ์ „ํ•œ ํ•ญ๋ชฉ (๊ณต๊ฐœ ์˜๋„)
12
+
13
+ - **์ด๋ฉ”์ผ**: `wsc7202@gmail.com`
14
+ - ์œ„์น˜: `src/index.ts`, `README.md`
15
+ - ์ƒํƒœ: CLI ๋„๊ตฌ์˜ ๋ชฉ์ ์ƒ ํ•„์š”ํ•œ ๊ณต๊ฐœ ์ •๋ณด
16
+ - **GitHub**: `alstjd0051`
17
+ - ์œ„์น˜: `src/index.ts`, `README.md`
18
+ - ์ƒํƒœ: CLI ๋„๊ตฌ์˜ ๋ชฉ์ ์ƒ ํ•„์š”ํ•œ ๊ณต๊ฐœ ์ •๋ณด
19
+ - **์ด๋ฆ„**: `์†ก๋ฏผ์„ฑ`
20
+ - ์œ„์น˜: `package.json` (author ํ•„๋“œ), `src/index.ts`, `README.md`
21
+ - ์ƒํƒœ: npm ํŒจํ‚ค์ง€์˜ ํ‘œ์ค€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ
22
+
23
+ #### โš ๏ธ ๋ฏผ๊ฐํ•œ ์ •๋ณด (๋ณดํ˜ธ๋จ)
24
+
25
+ - **Sanity API ํ† ํฐ**: `.env` ํŒŒ์ผ์— ์ €์žฅ
26
+ - ์ƒํƒœ: โœ… `.npmignore`์— ์˜ํ•ด npm ๋ฐฐํฌ ์‹œ ์ œ์™ธ๋จ
27
+ - ์ƒํƒœ: โœ… `.gitignore`์— ์˜ํ•ด GitHub์— ์ปค๋ฐ‹๋˜์ง€ ์•Š์Œ
28
+ - **Sanity ํ”„๋กœ์ ํŠธ ID**: `.env` ํŒŒ์ผ์— ์ €์žฅ
29
+ - ์ƒํƒœ: โœ… `.npmignore`์— ์˜ํ•ด npm ๋ฐฐํฌ ์‹œ ์ œ์™ธ๋จ
30
+
31
+ ### 2. ํŒŒ์ผ ์ œ์™ธ ํ™•์ธ
32
+
33
+ #### `.npmignore` ํŒŒ์ผ
34
+
35
+ โœ… ์ƒ์„ฑ ์™„๋ฃŒ - ๋‹ค์Œ ํ•ญ๋ชฉ๋“ค์ด npm ๋ฐฐํฌ ์‹œ ์ œ์™ธ๋ฉ๋‹ˆ๋‹ค:
36
+
37
+ - `.env` ๋ฐ ๋ชจ๋“  ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ํŒŒ์ผ
38
+ - `src/` ์†Œ์Šค ์ฝ”๋“œ (๋นŒ๋“œ๋œ `dist/`๋งŒ ํฌํ•จ)
39
+ - `test/` ํ…Œ์ŠคํŠธ ํŒŒ์ผ
40
+ - `bun.lock`, `package-lock.json` ๋“ฑ ๋ฝ ํŒŒ์ผ
41
+ - ๊ฐœ๋ฐœ ๊ด€๋ จ ํŒŒ์ผ๋“ค (`.cursor/`, `.github/`, `docs/` ๋“ฑ)
42
+
43
+ #### `npm pack --dry-run` ๊ฒฐ๊ณผ
44
+
45
+ ```
46
+ โœ… .env ํŒŒ์ผ์ด npm ํŒจํ‚ค์ง€์— ํฌํ•จ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค
47
+ โœ… bun.lock ํŒŒ์ผ์ด npm ํŒจํ‚ค์ง€์— ํฌํ•จ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค
48
+ โœ… src/ ์†Œ์Šค ์ฝ”๋“œ๊ฐ€ npm ํŒจํ‚ค์ง€์— ํฌํ•จ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค
49
+ ```
50
+
51
+ **์‹ค์ œ ํฌํ•จ๋˜๋Š” ํŒŒ์ผ (8๊ฐœ)**:
52
+
53
+ - `README.md`
54
+ - `package.json`
55
+ - `dist/index.js`
56
+ - `dist/index.d.ts`
57
+ - `dist/lib/sanity.js`
58
+ - `dist/lib/sanity.d.ts`
59
+ - `dist/types/experience.js`
60
+ - `dist/types/experience.d.ts`
61
+
62
+ ### 3. GitHub Actions ์›Œํฌํ”Œ๋กœ์šฐ ํ™•์ธ
63
+
64
+ #### ๋ฐฐํฌ ์›Œํฌํ”Œ๋กœ์šฐ
65
+
66
+ 1. **`publish.yml`** (ํƒœ๊ทธ ๊ธฐ๋ฐ˜ ๋ฐฐํฌ)
67
+ - ํŠธ๋ฆฌ๊ฑฐ: `v*` ํƒœ๊ทธ ํ‘ธ์‹œ ์‹œ
68
+ - ๋ฐฐํฌ ๋ช…๋ น: `npm publish --provenance --access public`
69
+ - โœ… `.npmignore` ํŒŒ์ผ์ด ์ ์šฉ๋จ
70
+
71
+ 2. **`deploy.yml`** (main ๋ธŒ๋žœ์น˜ ๋ฐ ํƒœ๊ทธ ๊ธฐ๋ฐ˜ ๋ฐฐํฌ)
72
+ - ํŠธ๋ฆฌ๊ฑฐ: `main` ๋ธŒ๋žœ์น˜ ํ‘ธ์‹œ ๋˜๋Š” `v*` ํƒœ๊ทธ
73
+ - ๋ฐฐํฌ ๋ช…๋ น: `npm publish`
74
+ - โœ… `.npmignore` ํŒŒ์ผ์ด ์ ์šฉ๋จ
75
+
76
+ #### ๋ณด์•ˆ ํ™•์ธ
77
+
78
+ - โœ… `.env` ํŒŒ์ผ์€ `.gitignore`์— ํฌํ•จ๋˜์–ด GitHub์— ์ปค๋ฐ‹๋˜์ง€ ์•Š์Œ
79
+ - โœ… ์›Œํฌํ”Œ๋กœ์šฐ ์‹คํ–‰ ์‹œ `.env` ํŒŒ์ผ์ด ์ฒดํฌ์•„์›ƒ๋˜์ง€ ์•Š์Œ (GitHub์— ์—†์œผ๋ฏ€๋กœ)
80
+ - โœ… `npm publish` ์‹คํ–‰ ์‹œ `.npmignore`์— ์˜ํ•ด `.env` ํŒŒ์ผ์ด ์ œ์™ธ๋จ
81
+ - โœ… ๋นŒ๋“œ ๊ณผ์ •์—์„œ `.env` ํŒŒ์ผ์ด ํ•„์š”ํ•˜์ง€ ์•Š์Œ (๋Ÿฐํƒ€์ž„์—๋งŒ ์‚ฌ์šฉ)
82
+
83
+ ### 4. ๋Ÿฐํƒ€์ž„ ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์ฒ˜๋ฆฌ
84
+
85
+ `src/lib/sanity.ts` ํŒŒ์ผ์˜ ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ๋กœ๋”ฉ ๋กœ์ง:
86
+
87
+ 1. ๋จผ์ € `.env` ํŒŒ์ผ์„ ์ฝ์œผ๋ ค๊ณ  ์‹œ๋„
88
+ 2. ์‹คํŒจ ์‹œ `process.env`์—์„œ ์ฝ๊ธฐ
89
+ 3. โœ… npm์— ๋ฐฐํฌ๋œ ํŒจํ‚ค์ง€์—์„œ๋Š” `.env` ํŒŒ์ผ์ด ์—†์œผ๋ฏ€๋กœ `process.env` ์‚ฌ์šฉ
90
+
91
+ **๊ถŒ์žฅ์‚ฌํ•ญ**:
92
+
93
+ - ์‚ฌ์šฉ์ž๋Š” ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ `process.env`๋กœ ์„ค์ •ํ•˜๊ฑฐ๋‚˜
94
+ - `.env` ํŒŒ์ผ์„ ์ง์ ‘ ์ƒ์„ฑํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค
95
+ - npm ํŒจํ‚ค์ง€์—๋Š” `.env` ํŒŒ์ผ์ด ํฌํ•จ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค
96
+
97
+ ## ๐Ÿ“‹ ๊ฒฐ๋ก 
98
+
99
+ ### โœ… ์•ˆ์ „ํ•œ ์ƒํƒœ
100
+
101
+ 1. **`.env` ํŒŒ์ผ**: npm ๋ฐฐํฌ ์‹œ ์™„์ „ํžˆ ์ œ์™ธ๋จ
102
+ 2. **์†Œ์Šค ์ฝ”๋“œ**: ๋นŒ๋“œ๋œ `dist/` ํด๋”๋งŒ ํฌํ•จ๋จ
103
+ 3. **๊ฐœ์ธ์ •๋ณด**: ๊ณต๊ฐœ ์˜๋„๊ฐ€ ์žˆ๋Š” ์ •๋ณด๋งŒ ํฌํ•จ๋จ (์ด๋ฉ”์ผ, GitHub, ์ด๋ฆ„)
104
+ 4. **๋ฏผ๊ฐํ•œ ํ† ํฐ**: npm์— ์—…๋กœ๋“œ๋˜์ง€ ์•Š์Œ
105
+
106
+ ### ๐Ÿ”’ ๋ณด์•ˆ ๊ถŒ์žฅ์‚ฌํ•ญ
107
+
108
+ 1. โœ… `.npmignore` ํŒŒ์ผ์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์„ค์ •๋˜์–ด ์žˆ์Œ
109
+ 2. โœ… `.gitignore`์— `.env` ํŒŒ์ผ์ด ํฌํ•จ๋˜์–ด ์žˆ์Œ
110
+ 3. โœ… GitHub Actions ์›Œํฌํ”Œ๋กœ์šฐ์—์„œ ์•ˆ์ „ํ•˜๊ฒŒ ๋ฐฐํฌ๋จ
111
+ 4. โš ๏ธ **์ฃผ์˜**: ๋กœ์ปฌ์—์„œ ์ง์ ‘ `npm publish` ์‹คํ–‰ ์‹œ `.npmignore`๊ฐ€ ์ ์šฉ๋˜๋ฏ€๋กœ ์•ˆ์ „ํ•จ
112
+
113
+ ### ๐ŸŽฏ ์ตœ์ข… ํ™•์ธ
114
+
115
+ - โœ… ๊ฐœ์ธ์ •๋ณด(API ํ† ํฐ)๊ฐ€ npmjs์— ์—…๋กœ๋“œ๋˜์ง€ ์•Š์Œ
116
+ - โœ… GitHub Actions๋ฅผ ํ†ตํ•œ ๋ฐฐํฌ๋„ ์•ˆ์ „ํ•จ
117
+ - โœ… `.npmignore` ํŒŒ์ผ์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž‘๋™ํ•จ
118
+
119
+ ---
120
+
121
+ **์ ๊ฒ€ ์™„๋ฃŒ**: ๋ชจ๋“  ๊ฐœ์ธ์ •๋ณด๊ฐ€ ์•ˆ์ „ํ•˜๊ฒŒ ๋ณดํ˜ธ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๐ŸŽ‰
package/dist/index.js CHANGED
@@ -6,6 +6,8 @@ import { exec } from "child_process";
6
6
  import { readFileSync } from "fs";
7
7
  import { fileURLToPath } from "url";
8
8
  import { dirname, join } from "path";
9
+ import { getExperiences, getPortfolio } from "./lib/sanity.js";
10
+ import { calculateTotalDuration, formatDate } from "./lib/dateUtils.js";
9
11
  // package.json์—์„œ ๋ฒ„์ „ ๋™์ ์œผ๋กœ ์ฝ๊ธฐ
10
12
  const getPackageVersion = () => {
11
13
  try {
@@ -33,15 +35,101 @@ const openUrl = (url) => {
33
35
  }
34
36
  });
35
37
  };
36
- program.version(getPackageVersion());
37
- program.option("-g, --github", "GitHub ํ”„๋กœํ•„ ์—ด๊ธฐ");
38
- program.parse(process.argv);
39
- const options = program.opts();
40
- if (Object.keys(options).length > 0) {
41
- if (options.github)
42
- openUrl("https://github.com/alstjd0051");
43
- process.exit(0);
44
- }
38
+ /**
39
+ * ๊ฒฝ๋ ฅ ์ •๋ณด๋ฅผ ํฌ๋งทํŒ…ํ•˜์—ฌ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค
40
+ */
41
+ const formatExperience = (experience) => {
42
+ const position = chalk.cyan(experience.position);
43
+ const startDate = chalk.gray(formatDate(experience.startDate));
44
+ const endDate = experience.endDate
45
+ ? chalk.gray(formatDate(experience.endDate))
46
+ : chalk.green("ํ˜„์žฌ");
47
+ const period = `${startDate} ~ ${endDate}`;
48
+ let result = `\n${chalk.bold("๐Ÿ’ผ " + experience.company)}\n`;
49
+ result += ` ${chalk.dim("์ง์ฑ…:")} ${position}\n`;
50
+ result += ` ${chalk.dim("๊ธฐ๊ฐ„:")} ${period}\n`;
51
+ return result;
52
+ };
53
+ /**
54
+ * ๋ชจ๋“  ๊ฒฝ๋ ฅ ์ •๋ณด๋ฅผ ํฌ๋งทํŒ…ํ•˜์—ฌ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค
55
+ */
56
+ const formatAllExperiences = (experiences) => {
57
+ if (experiences.length === 0) {
58
+ return chalk.yellow("\n ๋“ฑ๋ก๋œ ๊ฒฝ๋ ฅ์ด ์—†์Šต๋‹ˆ๋‹ค.\n");
59
+ }
60
+ // ์ด ๊ฒฝ๋ ฅ ๊ณ„์‚ฐ
61
+ const totalDuration = calculateTotalDuration(experiences);
62
+ const totalDurationText = chalk.bold.cyan(`์ด ๊ฒฝ๋ ฅ: ${totalDuration}`);
63
+ let result = `\n${totalDurationText}\n`;
64
+ result += experiences.map(formatExperience).join("\n");
65
+ return result;
66
+ };
67
+ /**
68
+ * ํ”„๋กœํ•„ ์ •๋ณด๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค
69
+ */
70
+ const showProfile = async () => {
71
+ let authorName = "๊ฐœ๋ฐœ์ž";
72
+ let authorEmail = "";
73
+ try {
74
+ const portfolio = await getPortfolio("์†ก๋ฏผ์„ฑ");
75
+ if (portfolio?.author) {
76
+ authorName = portfolio.author.name || "์ค€๋น„์ค‘์ž…๋‹ˆ๋‹ค.";
77
+ authorEmail = portfolio.author.email || "์ค€๋น„์ค‘์ž…๋‹ˆ๋‹ค.";
78
+ }
79
+ }
80
+ catch (error) {
81
+ console.error(chalk.yellow(`\nโš ๏ธ ํฌํŠธํด๋ฆฌ์˜ค ์ •๋ณด๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค: ${error instanceof Error ? error.message : String(error)}\n`));
82
+ }
83
+ let profileOutput = chalk.bold.cyan(`
84
+ โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
85
+ โ”‚ ๐Ÿš€ Developer Profile ๐Ÿš€ โ”‚
86
+ โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
87
+
88
+ `) +
89
+ chalk.green(`๐Ÿ‘‹ ์•ˆ๋…•ํ•˜์„ธ์š”!
90
+ ๐Ÿ’ป ๊ฐœ๋ฐœ์ž ${chalk.bold.yellow(authorName)}์ž…๋‹ˆ๋‹ค.
91
+
92
+ `) +
93
+ chalk.hex("#fef6e1")(`๐Ÿ“Œ Github: ${chalk.underline.whiteBright(`https://github.com/alstjd0051`)}
94
+ `);
95
+ if (authorEmail) {
96
+ profileOutput += chalk.blue(`โœ‰๏ธ E-mail: ${chalk.underline.whiteBright(authorEmail)}
97
+ `);
98
+ }
99
+ profileOutput += chalk.magenta(`
100
+ ๐Ÿ’ก ๋” ๋งŽ์€ ์ •๋ณด๋Š” ${chalk.bold("--help")}๋ฅผ ํ†ตํ•ด ํ™•์ธํ•ด์ฃผ์„ธ์š”.
101
+ `);
102
+ console.log(profileOutput);
103
+ };
104
+ /**
105
+ * ๊ฒฝ๋ ฅ ์ •๋ณด๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค
106
+ */
107
+ const showCareer = async () => {
108
+ try {
109
+ const experiences = await getExperiences();
110
+ if (experiences.length > 0) {
111
+ let careerOutput = chalk.bold.magenta(`
112
+ โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
113
+ โ”‚ ๐Ÿ’ผ Career Experience ๐Ÿ’ผ โ”‚
114
+ โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
115
+ `);
116
+ careerOutput += formatAllExperiences(experiences);
117
+ careerOutput += chalk.magenta(`
118
+ ๐Ÿ’ก ๋” ๋งŽ์€ ์ •๋ณด๋Š” ${chalk.bold("--help")}๋ฅผ ํ†ตํ•ด ํ™•์ธํ•ด์ฃผ์„ธ์š”.
119
+ `);
120
+ console.log(careerOutput);
121
+ }
122
+ else {
123
+ console.log(chalk.yellow("\nโš ๏ธ ๋“ฑ๋ก๋œ ๊ฒฝ๋ ฅ์ด ์—†์Šต๋‹ˆ๋‹ค.\n"));
124
+ }
125
+ }
126
+ catch (error) {
127
+ console.error(chalk.yellow(`\nโš ๏ธ ๊ฒฝ๋ ฅ ์ •๋ณด๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค: ${error instanceof Error ? error.message : String(error)}\n`));
128
+ }
129
+ };
130
+ /**
131
+ * ๋ฉ”์ธ ํ•จ์ˆ˜
132
+ */
45
133
  const main = async () => {
46
134
  try {
47
135
  // ๋„์›€๋ง ์˜ต์…˜ ์ฒดํฌ
@@ -55,6 +143,8 @@ const main = async () => {
55
143
  โ”‚ ์˜ต์…˜: โ”‚
56
144
  โ”‚ -V, --version ๋ฒ„์ „ ์ •๋ณด โ”‚
57
145
  โ”‚ -g, --github GitHub ์—ด๊ธฐ โ”‚
146
+ โ”‚ -p, --profile ํ”„๋กœํ•„ ๋ณด๊ธฐ โ”‚
147
+ โ”‚ -c, --career ๊ฒฝ๋ ฅ ๋ณด๊ธฐ โ”‚
58
148
  โ”‚ -h, --help ๋„์›€๋ง โ”‚
59
149
  โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
60
150
  `));
@@ -70,23 +160,25 @@ const main = async () => {
70
160
  },
71
161
  ]);
72
162
  if (answer.showInfo) {
73
- console.log(chalk.bold.cyan(`
163
+ // ํ”„๋กœํ•„ ์ •๋ณด ํ‘œ์‹œ
164
+ await showProfile();
165
+ // ๊ฒฝ๋ ฅ ์ •๋ณด ์กฐํšŒ ๋ฐ ํ‘œ์‹œ
166
+ try {
167
+ const experiences = await getExperiences();
168
+ if (experiences.length > 0) {
169
+ let careerOutput = chalk.bold.magenta(`
74
170
  โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
75
- โ”‚ ๐Ÿš€ Developer Profile ๐Ÿš€ โ”‚
171
+ โ”‚ ๐Ÿ’ผ Career Experience ๐Ÿ’ผ โ”‚
76
172
  โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
77
-
78
- `) +
79
- chalk.green(`๐Ÿ‘‹ ์•ˆ๋…•ํ•˜์„ธ์š”!
80
- ๐Ÿ’ป ๊ฐœ๋ฐœ์ž ${chalk.bold.yellow("์†ก๋ฏผ์„ฑ")}์ž…๋‹ˆ๋‹ค.
81
-
82
- `) +
83
- chalk.hex("#fef6e1")(`๐Ÿ“Œ Github: ${chalk.underline.whiteBright(`https://github.com/alstjd0051`)}
84
- `) +
85
- chalk.blue(`โœ‰๏ธ E-mail: ${chalk.underline.whiteBright(`wsc7202@gmail.com`)}
86
- `) +
87
- chalk.magenta(`
88
- ๐Ÿ’ก ๋” ๋งŽ์€ ์ •๋ณด๋Š” ${chalk.bold("--help")}๋ฅผ ํ†ตํ•ด ํ™•์ธํ•ด์ฃผ์„ธ์š”.
89
- `));
173
+ `);
174
+ careerOutput += formatAllExperiences(experiences);
175
+ console.log(careerOutput);
176
+ }
177
+ }
178
+ catch (error) {
179
+ // Sanity ์—ฐ๊ฒฐ ์˜ค๋ฅ˜ ์‹œ ๊ฒฝ๋ ฅ ์ •๋ณด ์—†์ด ๊ณ„์† ์ง„ํ–‰
180
+ console.error(chalk.yellow(`\nโš ๏ธ ๊ฒฝ๋ ฅ ์ •๋ณด๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค: ${error instanceof Error ? error.message : String(error)}\n`));
181
+ }
90
182
  }
91
183
  }
92
184
  catch (error) {
@@ -100,9 +192,47 @@ const main = async () => {
100
192
  process.exit(1);
101
193
  }
102
194
  };
103
- main().catch((error) => {
104
- console.error(chalk.red("\nโŒ ์น˜๋ช…์ ์ธ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค:"));
105
- console.error(error);
106
- process.exit(1);
107
- });
195
+ program.version(getPackageVersion());
196
+ program.option("-g, --github", "GitHub ํ”„๋กœํ•„ ์—ด๊ธฐ");
197
+ program.option("-p, --profile", "ํ”„๋กœํ•„ ์ •๋ณด๋งŒ ๋ณด๊ธฐ");
198
+ program.option("-c, --career", "๊ฒฝ๋ ฅ ์ •๋ณด๋งŒ ๋ณด๊ธฐ");
199
+ program.parse(process.argv);
200
+ const options = program.opts();
201
+ // ์˜ต์…˜์ด ์žˆ์œผ๋ฉด ํ•ด๋‹น ๊ธฐ๋Šฅ ์‹คํ–‰ ํ›„ ์ข…๋ฃŒ
202
+ if (Object.keys(options).length > 0 &&
203
+ (options.github || options.profile || options.career)) {
204
+ const runOptions = async () => {
205
+ try {
206
+ if (options.github) {
207
+ openUrl("https://github.com/alstjd0051");
208
+ }
209
+ if (options.profile) {
210
+ await showProfile();
211
+ }
212
+ if (options.career) {
213
+ await showCareer();
214
+ }
215
+ process.exit(0);
216
+ }
217
+ catch (error) {
218
+ console.error(chalk.red("\nโŒ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค:"));
219
+ if (error instanceof Error) {
220
+ console.error(chalk.yellow(error.message));
221
+ }
222
+ else {
223
+ console.error(chalk.yellow("์•Œ ์ˆ˜ ์—†๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค."));
224
+ }
225
+ process.exit(1);
226
+ }
227
+ };
228
+ void runOptions();
229
+ }
230
+ else {
231
+ // ์˜ต์…˜์ด ์—†์œผ๋ฉด ๊ธฐ๋ณธ main ํ•จ์ˆ˜ ์‹คํ–‰
232
+ main().catch((error) => {
233
+ console.error(chalk.red("\nโŒ ์น˜๋ช…์ ์ธ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค:"));
234
+ console.error(error);
235
+ process.exit(1);
236
+ });
237
+ }
108
238
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,8 @@
1
+ /**
2
+ * ๋‘ ๋‚ ์งœ ์‚ฌ์ด์˜ ๊ธฐ๊ฐ„์„ ๊ณ„์‚ฐํ•˜์—ฌ ํ•œ๊ตญ์–ด ํ˜•์‹์œผ๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค
3
+ * @param startDate ์‹œ์ž‘ ๋‚ ์งœ (YYYY-MM-DD ํ˜•์‹)
4
+ * @param endDate ์ข…๋ฃŒ ๋‚ ์งœ (YYYY-MM-DD ํ˜•์‹ ๋˜๋Š” undefined/null์ธ ๊ฒฝ์šฐ ํ˜„์žฌ ๋‚ ์งœ)
5
+ * @returns "2๋…„ 3๊ฐœ์›”" ํ˜•์‹์˜ ๋ฌธ์ž์—ด
6
+ */
7
+ export declare const calculatePeriod: (startDate: string, endDate?: string | null) => string;
8
+ //# sourceMappingURL=date.d.ts.map
@@ -0,0 +1,52 @@
1
+ /**
2
+ * ๋‘ ๋‚ ์งœ ์‚ฌ์ด์˜ ๊ธฐ๊ฐ„์„ ๊ณ„์‚ฐํ•˜์—ฌ ํ•œ๊ตญ์–ด ํ˜•์‹์œผ๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค
3
+ * @param startDate ์‹œ์ž‘ ๋‚ ์งœ (YYYY-MM-DD ํ˜•์‹)
4
+ * @param endDate ์ข…๋ฃŒ ๋‚ ์งœ (YYYY-MM-DD ํ˜•์‹ ๋˜๋Š” undefined/null์ธ ๊ฒฝ์šฐ ํ˜„์žฌ ๋‚ ์งœ)
5
+ * @returns "2๋…„ 3๊ฐœ์›”" ํ˜•์‹์˜ ๋ฌธ์ž์—ด
6
+ */
7
+ export const calculatePeriod = (startDate, endDate) => {
8
+ try {
9
+ const start = new Date(startDate);
10
+ const end = endDate ? new Date(endDate) : new Date();
11
+ if (isNaN(start.getTime()) || isNaN(end.getTime())) {
12
+ return "๋‚ ์งœ ์˜ค๋ฅ˜";
13
+ }
14
+ // ์‹œ์ž‘์ผ์ด ์ข…๋ฃŒ์ผ๋ณด๋‹ค ๋‚˜์ค‘์ธ ๊ฒฝ์šฐ
15
+ if (start > end) {
16
+ return "๋‚ ์งœ ์˜ค๋ฅ˜";
17
+ }
18
+ // ๋…„๊ณผ ์›” ๊ณ„์‚ฐ
19
+ let years = end.getFullYear() - start.getFullYear();
20
+ let months = end.getMonth() - start.getMonth();
21
+ // ์Œ์ˆ˜ ์›” ์ฒ˜๋ฆฌ
22
+ if (months < 0) {
23
+ years--;
24
+ months += 12;
25
+ }
26
+ // ์ผ์ž ๊ณ ๋ ค: ์ข…๋ฃŒ์ผ์˜ ์ผ์ž๊ฐ€ ์‹œ์ž‘์ผ์˜ ์ผ์ž๋ณด๋‹ค ์ž‘์œผ๋ฉด ํ•œ ๋‹ฌ ๋นผ๊ธฐ
27
+ if (end.getDate() < start.getDate()) {
28
+ months--;
29
+ if (months < 0) {
30
+ years--;
31
+ months += 12;
32
+ }
33
+ }
34
+ // ๊ฒฐ๊ณผ ํฌ๋งทํŒ…
35
+ const parts = [];
36
+ if (years > 0) {
37
+ parts.push(`${years}๋…„`);
38
+ }
39
+ if (months > 0) {
40
+ parts.push(`${months}๊ฐœ์›”`);
41
+ }
42
+ // ๋…„๊ณผ ์›”์ด ๋ชจ๋‘ 0์ธ ๊ฒฝ์šฐ (1๊ฐœ์›” ๋ฏธ๋งŒ)
43
+ if (parts.length === 0) {
44
+ return "1๊ฐœ์›” ๋ฏธ๋งŒ";
45
+ }
46
+ return parts.join(" ");
47
+ }
48
+ catch (error) {
49
+ return "๋‚ ์งœ ์˜ค๋ฅ˜";
50
+ }
51
+ };
52
+ //# sourceMappingURL=date.js.map
@@ -0,0 +1,26 @@
1
+ /**
2
+ * ๋‘ ๋‚ ์งœ ์‚ฌ์ด์˜ ๊ธฐ๊ฐ„์„ ๊ณ„์‚ฐํ•˜์—ฌ ํฌ๋งทํŒ…๋œ ๋ฌธ์ž์—ด๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค
3
+ * @param startDate ์‹œ์ž‘์ผ (YYYY-MM-DD ํ˜•์‹)
4
+ * @param endDate ์ข…๋ฃŒ์ผ (YYYY-MM-DD ํ˜•์‹ ๋˜๋Š” null/undefined์ธ ๊ฒฝ์šฐ ํ˜„์žฌ ๋‚ ์งœ)
5
+ * @returns ํฌ๋งทํŒ…๋œ ๊ธฐ๊ฐ„ ๋ฌธ์ž์—ด (์˜ˆ: "2๋…„ 3๊ฐœ์›”", "6๊ฐœ์›”", "ํ˜„์žฌ")
6
+ */
7
+ export declare const calculateDuration: (startDate: string, endDate?: string | null) => string;
8
+ /**
9
+ * ๋‚ ์งœ๋ฅผ ํฌ๋งทํŒ…ํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค
10
+ * @param dateString ๋‚ ์งœ ๋ฌธ์ž์—ด (YYYY-MM-DD ํ˜•์‹)
11
+ * @param formatString ํฌ๋งท ๋ฌธ์ž์—ด (๊ธฐ๋ณธ๊ฐ’: "yyyy-MM-dd")
12
+ * @returns ํฌ๋งทํŒ…๋œ ๋‚ ์งœ ๋ฌธ์ž์—ด
13
+ */
14
+ export declare const formatDate: (dateString: string, formatString?: string) => string;
15
+ /**
16
+ * ๊ฒฝ๋ ฅ ๋ฐฐ์—ด์˜ ์ด ๊ธฐ๊ฐ„์„ ๊ณ„์‚ฐํ•˜์—ฌ ํฌ๋งทํŒ…๋œ ๋ฌธ์ž์—ด๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค
17
+ * ๊ฒน์น˜๋Š” ๊ธฐ๊ฐ„์„ ๋ณ‘ํ•ฉํ•˜์—ฌ ์‹ค์ œ ๊ทผ๋ฌด ๊ธฐ๊ฐ„์„ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค.
18
+ * @param experiences ๊ฒฝ๋ ฅ ๋ฐฐ์—ด (startDate, endDate, position ํฌํ•จ)
19
+ * @returns ํฌ๋งทํŒ…๋œ ์ด ๊ธฐ๊ฐ„ ๋ฌธ์ž์—ด (์˜ˆ: "5๋…„ 3๊ฐœ์›”")
20
+ */
21
+ export declare const calculateTotalDuration: (experiences: Array<{
22
+ startDate: string;
23
+ endDate?: string | null;
24
+ position?: string;
25
+ }>) => string;
26
+ //# sourceMappingURL=dateUtils.d.ts.map
@@ -0,0 +1,185 @@
1
+ import { differenceInMonths, parseISO, format } from "date-fns";
2
+ import { ko } from "date-fns/locale";
3
+ /**
4
+ * ๋‘ ๋‚ ์งœ ์‚ฌ์ด์˜ ๊ธฐ๊ฐ„์„ ๊ณ„์‚ฐํ•˜์—ฌ ํฌ๋งทํŒ…๋œ ๋ฌธ์ž์—ด๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค
5
+ * @param startDate ์‹œ์ž‘์ผ (YYYY-MM-DD ํ˜•์‹)
6
+ * @param endDate ์ข…๋ฃŒ์ผ (YYYY-MM-DD ํ˜•์‹ ๋˜๋Š” null/undefined์ธ ๊ฒฝ์šฐ ํ˜„์žฌ ๋‚ ์งœ)
7
+ * @returns ํฌ๋งทํŒ…๋œ ๊ธฐ๊ฐ„ ๋ฌธ์ž์—ด (์˜ˆ: "2๋…„ 3๊ฐœ์›”", "6๊ฐœ์›”", "ํ˜„์žฌ")
8
+ */
9
+ export const calculateDuration = (startDate, endDate) => {
10
+ try {
11
+ const start = parseISO(startDate);
12
+ const end = endDate ? parseISO(endDate) : new Date();
13
+ // ์‹œ์ž‘์ผ์ด ์ข…๋ฃŒ์ผ๋ณด๋‹ค ๋‚˜์ค‘์ธ ๊ฒฝ์šฐ ์ฒ˜๋ฆฌ
14
+ if (start > end) {
15
+ return "๊ธฐ๊ฐ„ ์˜ค๋ฅ˜";
16
+ }
17
+ const totalMonths = differenceInMonths(end, start);
18
+ // 1๊ฐœ์›” ๋ฏธ๋งŒ์ธ ๊ฒฝ์šฐ
19
+ if (totalMonths === 0) {
20
+ return "1๊ฐœ์›” ๋ฏธ๋งŒ";
21
+ }
22
+ let years = Math.floor(totalMonths / 12);
23
+ let months = totalMonths % 12;
24
+ // 11๊ฐœ์›” ์ด์ƒ์ด๋ฉด ๋ฐ˜์˜ฌ๋ฆผํ•˜์—ฌ 1๋…„์œผ๋กœ ์˜ฌ๋ฆผ
25
+ if (months >= 11) {
26
+ years += 1;
27
+ months = 0;
28
+ }
29
+ // 1๋…„ ์ด์ƒ์ธ ๊ฒฝ์šฐ
30
+ const parts = [];
31
+ if (years > 0) {
32
+ parts.push(`${years}๋…„`);
33
+ }
34
+ if (months > 0) {
35
+ parts.push(`${months}๊ฐœ์›”`);
36
+ }
37
+ return parts.length > 0 ? parts.join(" ") : "1๊ฐœ์›”";
38
+ }
39
+ catch (error) {
40
+ console.error("๋‚ ์งœ ๊ณ„์‚ฐ ์˜ค๋ฅ˜:", error);
41
+ return "๊ธฐ๊ฐ„ ๊ณ„์‚ฐ ์˜ค๋ฅ˜";
42
+ }
43
+ };
44
+ /**
45
+ * ๋‚ ์งœ๋ฅผ ํฌ๋งทํŒ…ํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค
46
+ * @param dateString ๋‚ ์งœ ๋ฌธ์ž์—ด (YYYY-MM-DD ํ˜•์‹)
47
+ * @param formatString ํฌ๋งท ๋ฌธ์ž์—ด (๊ธฐ๋ณธ๊ฐ’: "yyyy-MM-dd")
48
+ * @returns ํฌ๋งทํŒ…๋œ ๋‚ ์งœ ๋ฌธ์ž์—ด
49
+ */
50
+ export const formatDate = (dateString, formatString = "yyyy-MM-dd") => {
51
+ try {
52
+ const date = parseISO(dateString);
53
+ return format(date, formatString, { locale: ko });
54
+ }
55
+ catch (error) {
56
+ console.error("๋‚ ์งœ ํฌ๋งทํŒ… ์˜ค๋ฅ˜:", error);
57
+ return dateString;
58
+ }
59
+ };
60
+ /**
61
+ * ๊ฒฝ๋ ฅ ๋ฐฐ์—ด์˜ ์ด ๊ธฐ๊ฐ„์„ ๊ณ„์‚ฐํ•˜์—ฌ ํฌ๋งทํŒ…๋œ ๋ฌธ์ž์—ด๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค
62
+ * ๊ฒน์น˜๋Š” ๊ธฐ๊ฐ„์„ ๋ณ‘ํ•ฉํ•˜์—ฌ ์‹ค์ œ ๊ทผ๋ฌด ๊ธฐ๊ฐ„์„ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค.
63
+ * @param experiences ๊ฒฝ๋ ฅ ๋ฐฐ์—ด (startDate, endDate, position ํฌํ•จ)
64
+ * @returns ํฌ๋งทํŒ…๋œ ์ด ๊ธฐ๊ฐ„ ๋ฌธ์ž์—ด (์˜ˆ: "5๋…„ 3๊ฐœ์›”")
65
+ */
66
+ export const calculateTotalDuration = (experiences) => {
67
+ try {
68
+ if (experiences.length === 0) {
69
+ return "0๊ฐœ์›”";
70
+ }
71
+ // ๋ชจ๋“  ๊ฒฝ๋ ฅ์˜ ๋‚ ์งœ ๋ฒ”์œ„๋ฅผ ์ˆ˜์ง‘ (Side Project ์ œ์™ธ)
72
+ const dateRanges = [];
73
+ for (const exp of experiences) {
74
+ try {
75
+ // Side Project๊ฐ€ ํฌํ•จ๋œ ์ง์ฑ…์€ ์ œ์™ธ
76
+ if (exp.position && exp.position.includes("Side Project")) {
77
+ continue;
78
+ }
79
+ const start = parseISO(exp.startDate);
80
+ const end = exp.endDate ? parseISO(exp.endDate) : new Date();
81
+ if (start <= end) {
82
+ dateRanges.push({ start, end });
83
+ }
84
+ }
85
+ catch (error) {
86
+ // ๊ฐœ๋ณ„ ๊ฒฝ๋ ฅ ๊ณ„์‚ฐ ์˜ค๋ฅ˜๋Š” ๋ฌด์‹œํ•˜๊ณ  ๊ณ„์† ์ง„ํ–‰
87
+ console.error("๊ฒฝ๋ ฅ ๊ธฐ๊ฐ„ ๊ณ„์‚ฐ ์˜ค๋ฅ˜:", error);
88
+ }
89
+ }
90
+ if (dateRanges.length === 0) {
91
+ return "0๊ฐœ์›”";
92
+ }
93
+ // ์‹œ์ž‘์ผ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌ
94
+ dateRanges.sort((a, b) => {
95
+ const startDiff = a.start.getTime() - b.start.getTime();
96
+ if (startDiff !== 0)
97
+ return startDiff;
98
+ // ์‹œ์ž‘์ผ์ด ๊ฐ™์œผ๋ฉด ์ข…๋ฃŒ์ผ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌ
99
+ return a.end.getTime() - b.end.getTime();
100
+ });
101
+ // ๊ฒน์น˜๋Š” ๊ธฐ๊ฐ„ ๋ณ‘ํ•ฉ
102
+ const mergedRanges = [];
103
+ let currentRange = {
104
+ start: new Date(dateRanges[0].start),
105
+ end: new Date(dateRanges[0].end),
106
+ };
107
+ for (let i = 1; i < dateRanges.length; i++) {
108
+ const nextRange = dateRanges[i];
109
+ const nextStart = new Date(nextRange.start);
110
+ const nextEnd = new Date(nextRange.end);
111
+ // ํ˜„์žฌ ๋ฒ”์œ„์˜ ์ข…๋ฃŒ์ผ๊ณผ ๋‹ค์Œ ๋ฒ”์œ„์˜ ์‹œ์ž‘์ผ ๋น„๊ต
112
+ // ๊ฒน์น˜๋Š” ๊ฒฝ์šฐ: nextStart <= currentEnd
113
+ const currentEndTime = currentRange.end.getTime();
114
+ const nextStartTime = nextStart.getTime();
115
+ // ๊ฒน์น˜๋Š” ๊ฒฝ์šฐ ๋ณ‘ํ•ฉ (์ข…๋ฃŒ์ผ์ด ์‹œ์ž‘์ผ๋ณด๋‹ค ํฌ๊ฑฐ๋‚˜ ๊ฐ™์œผ๋ฉด ๊ฒน์นจ)
116
+ if (nextStartTime <= currentEndTime) {
117
+ // ๋ฒ”์œ„ ํ™•์žฅ (๋” ๋Šฆ์€ ์ข…๋ฃŒ์ผ๋กœ)
118
+ if (nextEnd.getTime() > currentRange.end.getTime()) {
119
+ currentRange.end = new Date(nextEnd);
120
+ }
121
+ }
122
+ else {
123
+ // ๊ฒน์น˜์ง€ ์•Š์œผ๋ฉด ํ˜„์žฌ ๋ฒ”์œ„๋ฅผ ์ €์žฅํ•˜๊ณ  ๋‹ค์Œ ๋ฒ”์œ„๋กœ ์ด๋™
124
+ mergedRanges.push({
125
+ start: new Date(currentRange.start),
126
+ end: new Date(currentRange.end),
127
+ });
128
+ currentRange = {
129
+ start: new Date(nextStart),
130
+ end: new Date(nextEnd),
131
+ };
132
+ }
133
+ }
134
+ // ๋งˆ์ง€๋ง‰ ๋ฒ”์œ„ ์ถ”๊ฐ€
135
+ mergedRanges.push({
136
+ start: new Date(currentRange.start),
137
+ end: new Date(currentRange.end),
138
+ });
139
+ // ๋ณ‘ํ•ฉ๋œ ๋ฒ”์œ„๋“ค์˜ ์ด ๊ฐœ์›” ์ˆ˜ ๊ณ„์‚ฐ
140
+ let totalMonths = 0;
141
+ for (const range of mergedRanges) {
142
+ // differenceInMonths๋Š” ๋‘ ๋‚ ์งœ ์‚ฌ์ด์˜ ์™„์ „ํ•œ ๊ฐœ์›” ์ˆ˜๋ฅผ ๊ณ„์‚ฐ
143
+ // ์˜ˆ: 2018-02-01 ~ 2020-01-01 = 23๊ฐœ์›”
144
+ const months = differenceInMonths(range.end, range.start);
145
+ // ๊ฐ™์€ ๋‹ฌ ๋‚ด์—์„œ ์‹œ์ž‘์ผ๊ณผ ์ข…๋ฃŒ์ผ์ด ๋‹ค๋ฅด๋ฉด ์ตœ์†Œ 1๊ฐœ์›”๋กœ ๊ณ„์‚ฐ
146
+ if (months === 0) {
147
+ // ๊ฐ™์€ ๋‹ฌ์ด์ง€๋งŒ ๋‚ ์งœ๊ฐ€ ๋‹ค๋ฅด๋ฉด 1๊ฐœ์›”๋กœ ๊ณ„์‚ฐ
148
+ if (range.start.getTime() !== range.end.getTime() &&
149
+ range.start.getMonth() === range.end.getMonth() &&
150
+ range.start.getFullYear() === range.end.getFullYear()) {
151
+ totalMonths += 1;
152
+ }
153
+ }
154
+ else {
155
+ totalMonths += months;
156
+ }
157
+ }
158
+ // ์ด ๊ฐœ์›” ์ˆ˜๊ฐ€ 0์ธ ๊ฒฝ์šฐ
159
+ if (totalMonths === 0) {
160
+ return "1๊ฐœ์›” ๋ฏธ๋งŒ";
161
+ }
162
+ // ์ด ๊ฐœ์›” ์ˆ˜๋ฅผ ๋…„๊ณผ ๊ฐœ์›”๋กœ ๋ณ€ํ™˜
163
+ let years = Math.floor(totalMonths / 12);
164
+ let months = totalMonths % 12;
165
+ // 10๊ฐœ์›” ์ด์ƒ์ด๋ฉด ๋ฐ˜์˜ฌ๋ฆผํ•˜์—ฌ 1๋…„์œผ๋กœ ์˜ฌ๋ฆผ (11๊ฐœ์›” โ†’ 1๋…„)
166
+ // ํ•˜์ง€๋งŒ 5๋…„ 9๊ฐœ์›”์ด ๋‚˜์™€์•ผ ํ•˜๋ฏ€๋กœ 11๊ฐœ์›” ์ด์ƒ์ผ ๋•Œ๋งŒ ๋ฐ˜์˜ฌ๋ฆผ
167
+ if (months >= 11) {
168
+ years += 1;
169
+ months = 0;
170
+ }
171
+ const parts = [];
172
+ if (years > 0) {
173
+ parts.push(`${years}๋…„`);
174
+ }
175
+ if (months > 0) {
176
+ parts.push(`${months}๊ฐœ์›”`);
177
+ }
178
+ return parts.length > 0 ? parts.join(" ") : "1๊ฐœ์›”";
179
+ }
180
+ catch (error) {
181
+ console.error("์ด ๊ฒฝ๋ ฅ ๊ณ„์‚ฐ ์˜ค๋ฅ˜:", error);
182
+ return "๊ณ„์‚ฐ ์˜ค๋ฅ˜";
183
+ }
184
+ };
185
+ //# sourceMappingURL=dateUtils.js.map
@@ -0,0 +1,26 @@
1
+ import { createClient } from "@sanity/client";
2
+ import type { Experience } from "../types/experience.js";
3
+ /**
4
+ * ๋ชจ๋“  Experience(๊ฒฝ๋ ฅ) ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค
5
+ */
6
+ export declare const getExperiences: () => Promise<Experience[]>;
7
+ /**
8
+ * ํŠน์ • ID์˜ Experience๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค
9
+ */
10
+ export declare const getExperienceById: (id: string) => Promise<Experience | null>;
11
+ /**
12
+ * Portfolio ์ •๋ณด๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค (author์˜ name, email ํฌํ•จ)
13
+ */
14
+ export interface PortfolioAuthor {
15
+ name?: string;
16
+ email?: string;
17
+ }
18
+ export interface Portfolio {
19
+ author?: PortfolioAuthor | null;
20
+ }
21
+ export declare const getPortfolio: (name: string | undefined) => Promise<Portfolio | null>;
22
+ /**
23
+ * Sanity ํด๋ผ์ด์–ธํŠธ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค (ํ•„์š”ํ•œ ๊ฒฝ์šฐ)
24
+ */
25
+ export declare const getSanityClient: () => ReturnType<typeof createClient>;
26
+ //# sourceMappingURL=sanity.d.ts.map