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.
- package/SECURITY_CHECK.md +121 -0
- package/dist/index.js +159 -29
- package/dist/lib/date.d.ts +8 -0
- package/dist/lib/date.js +52 -0
- package/dist/lib/dateUtils.d.ts +26 -0
- package/dist/lib/dateUtils.js +185 -0
- package/dist/lib/sanity.d.ts +26 -0
- package/dist/lib/sanity.js +146 -0
- package/dist/types/experience.d.ts +12 -0
- package/dist/types/experience.js +2 -0
- package/package.json +6 -4
- package/.cursor/plans/-----------8c733d2f.plan.md +0 -158
- package/.editorconfig +0 -15
- package/.eslintrc.json +0 -33
- package/.github/actions/discord-notify/action.yml +0 -119
- package/.github/actions/setup-runtime/action.yml +0 -41
- package/.github/workflows/ci.yml +0 -79
- package/.github/workflows/deploy.yml +0 -164
- package/.github/workflows/publish.yml +0 -53
- package/.prettierrc +0 -13
- package/bun.lock +0 -212
- package/bunfig.toml +0 -16
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/docs/auto-deployment.md +0 -191
- package/docs/deployment.md +0 -82
- package/docs/development.md +0 -394
- package/docs/direct-deployment.md +0 -116
- package/docs/discord-setup.md +0 -158
- package/docs/github-actions-fixes.md +0 -142
- package/docs/improvements.md +0 -287
- package/docs/pipeline.md +0 -228
- package/docs/testing.md +0 -173
- package/docs/usage.md +0 -112
- package/docs/workflows.md +0 -176
- package/src/index.ts +0 -141
- package/test/index.test.ts +0 -167
- package/tsconfig.eslint.json +0 -9
- package/tsconfig.json +0 -20
- package/vitest.config.ts +0 -22
|
@@ -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
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
-
|
|
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
|
-
โ
|
|
171
|
+
โ ๐ผ Career Experience ๐ผ โ
|
|
76
172
|
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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
|
package/dist/lib/date.js
ADDED
|
@@ -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
|