saju8z 1.0.0 → 1.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 +262 -108
- package/bin/saju8z.js +91 -0
- package/dist/core.cjs +135 -33
- package/dist/core.js +135 -33
- package/dist/format.cjs +222 -55
- package/dist/format.js +222 -55
- package/dist/index.cjs +524 -329
- package/dist/index.js +524 -329
- package/dist/lunar.cjs +4 -4
- package/dist/lunar.js +4 -4
- package/dist/types/application/normalizeDateTime.d.ts +3 -0
- package/dist/types/calendar/dateMath.d.ts +1 -1
- package/dist/types/config/saju8z.d.ts +1 -1
- package/dist/types/contracts/sajuChart.d.ts +1 -2
- package/dist/types/input/parseSajuChartInput.d.ts +10 -0
- package/dist/types/output/chartPresentation.d.ts +14 -0
- package/dist/types/output/createSajuPrompt.d.ts +1 -0
- package/dist/types/output/formatSajuChart.d.ts +1 -1
- package/dist/types/output/formatSajuText.d.ts +2 -0
- package/dist/types-cjs/application/normalizeDateTime.d.ts +3 -0
- package/dist/types-cjs/calendar/dateMath.d.ts +1 -1
- package/dist/types-cjs/config/saju8z.d.ts +1 -1
- package/dist/types-cjs/contracts/sajuChart.d.ts +1 -2
- package/dist/types-cjs/input/parseSajuChartInput.d.ts +10 -0
- package/dist/types-cjs/output/chartPresentation.d.ts +14 -0
- package/dist/types-cjs/output/createSajuPrompt.d.ts +1 -0
- package/dist/types-cjs/output/formatSajuChart.d.ts +1 -1
- package/dist/types-cjs/output/formatSajuText.d.ts +2 -0
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -1,27 +1,233 @@
|
|
|
1
1
|
# saju8z
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
생년월일시로 사주팔자와 십성을 계산하는 만세력 CLI 라이브러리입니다.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
- 네트워크·API 키·데이터베이스 없이 실행
|
|
7
|
-
- 현재 시각과 실행 환경의 시간대에 의존하지 않는 계산
|
|
8
|
-
- 음력 변환 의존성을 번들에 포함하여 별도 런타임 의존성 설치 불필요
|
|
5
|
+
양력/음력/윤달을 지원하고, 결과를 텍스트/JSON/AI 전달용 프롬프트로 출력합니다.
|
|
9
6
|
|
|
10
|
-
Node.js
|
|
7
|
+
**Node.js 22 이상과 npm**이 필요합니다. 터미널에서 바로 사용하려면 `--date`, `--time`을 본인의 생년월일시로 바꾸세요.
|
|
11
8
|
|
|
12
|
-
## 설치
|
|
13
9
|
|
|
14
|
-
|
|
10
|
+
|
|
11
|
+
## CLI 빠른 시작
|
|
12
|
+
|
|
13
|
+
### 바로 실행하고 결과 보기
|
|
14
|
+
|
|
15
|
+
전역 설치 없이 한 줄로 실행합니다. 아래 예시는 양력 2000년 2월 23일 00시 10분, 현재 GMT 기준입니다.
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
npx --yes saju8z --date 2000-02-25 --time 04:10
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### 전역 설치 후 실행
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
npm install -g saju8z
|
|
25
|
+
saju8z --date 2000-02-25 --time 04:10
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
### 출력 형식 선택
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
| 옵션 | 결과 |
|
|
34
|
+
| ----------------- | ------------------------ |
|
|
35
|
+
| `--format text` | 만세력 텍스트 (기본값) |
|
|
36
|
+
| `--format json` | 환산·계산 시각, 사주팔자, 십성의 JSON |
|
|
37
|
+
| `--format prompt` | AI 전달용 프롬프트 텍스트 |
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
### 만세력 텍스트 출력:
|
|
43
|
+
|
|
44
|
+
```text
|
|
45
|
+
2000-02-25 04:10
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
```text
|
|
53
|
+
[만세력]
|
|
54
|
+
양력 환산 시각: 2000-02-25 04:10 (GMT+09:00)
|
|
55
|
+
-30분 보정 후 계산 시각: 2000-02-25 03:40
|
|
56
|
+
일간: 계수(癸水)
|
|
57
|
+
|
|
58
|
+
년주: 경진(庚辰)
|
|
59
|
+
- 천간: 경(庚), 금(金), 정인
|
|
60
|
+
- 지지: 진(辰), 토(土), 정관
|
|
61
|
+
|
|
62
|
+
월주: 무인(戊寅)
|
|
63
|
+
- 천간: 무(戊), 토(土), 정관
|
|
64
|
+
- 지지: 인(寅), 목(木), 상관
|
|
65
|
+
|
|
66
|
+
일주: 계축(癸丑)
|
|
67
|
+
- 천간: 계(癸), 수(水), 본원
|
|
68
|
+
- 지지: 축(丑), 토(土), 편관
|
|
69
|
+
|
|
70
|
+
시주: 갑인(甲寅)
|
|
71
|
+
- 천간: 갑(甲), 목(木), 상관
|
|
72
|
+
- 지지: 인(寅), 목(木), 상관
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
**JSON 출력:**
|
|
78
|
+
|
|
79
|
+
```sh
|
|
80
|
+
npx --yes saju8z --date 2000-02-29 --time 00:10 --gmt +09:00 --format json
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
<details class="orca-details">
|
|
84
|
+
<summary>실제 JSON 결과 펼치기</summary>
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"normalizedDateTime": {
|
|
89
|
+
"year": 2000,
|
|
90
|
+
"month": 2,
|
|
91
|
+
"day": 29,
|
|
92
|
+
"hour": 0,
|
|
93
|
+
"minute": 10
|
|
94
|
+
},
|
|
95
|
+
"calculationDateTime": {
|
|
96
|
+
"year": 2000,
|
|
97
|
+
"month": 2,
|
|
98
|
+
"day": 28,
|
|
99
|
+
"hour": 23,
|
|
100
|
+
"minute": 40
|
|
101
|
+
},
|
|
102
|
+
"fourPillars": {
|
|
103
|
+
"year": {
|
|
104
|
+
"stem": "경",
|
|
105
|
+
"branch": "진"
|
|
106
|
+
},
|
|
107
|
+
"month": {
|
|
108
|
+
"stem": "무",
|
|
109
|
+
"branch": "인"
|
|
110
|
+
},
|
|
111
|
+
"day": {
|
|
112
|
+
"stem": "병",
|
|
113
|
+
"branch": "진"
|
|
114
|
+
},
|
|
115
|
+
"hour": {
|
|
116
|
+
"stem": "무",
|
|
117
|
+
"branch": "자"
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
"tenGods": {
|
|
121
|
+
"yearStem": "편재",
|
|
122
|
+
"yearBranch": "식신",
|
|
123
|
+
"monthStem": "식신",
|
|
124
|
+
"monthBranch": "편인",
|
|
125
|
+
"dayBranch": "식신",
|
|
126
|
+
"hourStem": "식신",
|
|
127
|
+
"hourBranch": "정관"
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
</details>
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
**AI 전달용 프롬프트 출력:**
|
|
137
|
+
|
|
138
|
+
```sh
|
|
139
|
+
npx --yes saju8z --date 2000-02-29 --time 00:10 --gmt +09:00 --format prompt
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
해석 지침 사이에 만세력 계산 결과가 들어갑니다. 생성한 출력 전체를 AI 대화창에 붙여 넣어 사용합니다.
|
|
143
|
+
|
|
144
|
+
CLI 자체는 AI를 호출하거나 해석을 생성하지 않습니다.
|
|
145
|
+
|
|
146
|
+
<details class="orca-details">
|
|
147
|
+
<summary>실제 프롬프트 결과 펼치기</summary>
|
|
148
|
+
|
|
149
|
+
```text
|
|
150
|
+
너는 전통 명리학의 관점으로 사주 계산 결과를 설명하는 해설자다.
|
|
151
|
+
|
|
152
|
+
아래 만세력 계산 결과를 바탕으로 사주를 설명해 줘.
|
|
153
|
+
사주팔자를 다시 계산하지 말고 제공된 정보를 사용해 줘.
|
|
154
|
+
|
|
155
|
+
[만세력]
|
|
156
|
+
양력 환산 시각: 2000-02-29 00:10 (GMT+09:00)
|
|
157
|
+
-30분 보정 후 계산 시각: 2000-02-28 23:40
|
|
158
|
+
일간: 병화(丙火)
|
|
159
|
+
|
|
160
|
+
년주: 경진(庚辰)
|
|
161
|
+
- 천간: 경(庚), 금(金), 편재
|
|
162
|
+
- 지지: 진(辰), 토(土), 식신
|
|
163
|
+
|
|
164
|
+
월주: 무인(戊寅)
|
|
165
|
+
- 천간: 무(戊), 토(土), 식신
|
|
166
|
+
- 지지: 인(寅), 목(木), 편인
|
|
167
|
+
|
|
168
|
+
일주: 병진(丙辰)
|
|
169
|
+
- 천간: 병(丙), 화(火), 본원
|
|
170
|
+
- 지지: 진(辰), 토(土), 식신
|
|
171
|
+
|
|
172
|
+
시주: 무자(戊子)
|
|
173
|
+
- 천간: 무(戊), 토(土), 식신
|
|
174
|
+
- 지지: 자(子), 수(水), 정관
|
|
175
|
+
|
|
176
|
+
다음 내용을 설명해라.
|
|
177
|
+
1. 성격적으로 나타날 수 있는 경향과 강점
|
|
178
|
+
2. 스트레스를 받을 때 나타날 수 있는 반응
|
|
179
|
+
3. 대인관계와 의사소통에서 참고할 점
|
|
180
|
+
4. 업무 방식과 협업에서 참고할 점
|
|
181
|
+
5. 스스로 확인해 볼 질문 3가지
|
|
182
|
+
|
|
183
|
+
답변 기준:
|
|
184
|
+
- 전통적 상징 해석과 실제로 확인된 사실을 구분해라.
|
|
185
|
+
- 사주 용어를 사용하지 마라.
|
|
186
|
+
- 성격이나 미래를 단정하지 말고 가능한 경향으로 표현해라.
|
|
187
|
+
- 10살짜리도 이해할 수 있도록 쉽게 풀어서 설명해라.
|
|
188
|
+
- 제공되지 않은 대운·세운·지장간 등의 계산 결과를 만들어내지 마라.
|
|
189
|
+
- 정보가 부족한 질문에는 무엇이 더 필요한지 설명해라
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
</details>
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
### 음력과 윤달 입력
|
|
197
|
+
|
|
198
|
+
양력은 기본값입니다. 한국 음력 날짜는 `--calendar lunar`를 추가하고, **음력 윤달이면 `--leap`도 함께** 지정합니다. 날짜와 출생 시각은 선택한 달력과 GMT 기준으로 입력합니다.
|
|
15
199
|
|
|
16
200
|
```sh
|
|
17
|
-
|
|
201
|
+
# 음력 평달 2017년 5월 1일 12:00
|
|
202
|
+
npx --yes saju8z --date 2017-05-01 --time 12:00 --gmt +09:00 --calendar lunar
|
|
203
|
+
|
|
204
|
+
# 음력 윤5월 1일 12:00 → 양력 2017-06-24 12:00과 같은 계산 결과
|
|
205
|
+
npx --yes saju8z --date 2017-05-01 --time 12:00 --gmt +09:00 --calendar lunar --leap
|
|
18
206
|
```
|
|
19
207
|
|
|
20
|
-
설치 후 `saju8z`에서 함수를 가져와 바로 사용할 수 있습니다. 패키지 사용을 위해 이 저장소를 내려받거나 직접 빌드할 필요는 없습니다.
|
|
21
208
|
|
|
22
|
-
## 빠른 시작
|
|
23
209
|
|
|
24
|
-
|
|
210
|
+
### CLI 옵션과 시차
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
| 옵션 | 필수 | 기본값·설명 |
|
|
214
|
+
| -------------- | --- | ----------------------------------------------------- |
|
|
215
|
+
| `--date` | 예 | 생년월일 `YYYY-MM-DD`. 월·일은 두 자리 |
|
|
216
|
+
| `--time` | 예 | 출생 시각 `HH:mm`, `00:00`\~`23:59`. 초는 지원하지 않음 |
|
|
217
|
+
| `--gmt` | 아니요 | 고정 시차 `±HH:mm`, `-12:00`\~`+14:00` 기본값은 실행 환경의 현재 GMT |
|
|
218
|
+
| `--calendar` | 아니요 | `solar`(기본, 양력) 또는 `lunar`(한국 음력) |
|
|
219
|
+
| `--leap` | 아니요 | 음력 윤달일 때 지정. `--calendar lunar`와 함께 사용 |
|
|
220
|
+
| `--format` | 아니요 | `text`(기본), `json`, `prompt` |
|
|
221
|
+
| `--help`, `-h` | 아니요 | 도움말 출력 |
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
시차는 `--gmt -05:00` 또는 `--gmt=-05:00`처럼 전달합니다.
|
|
225
|
+
|
|
226
|
+
`--gmt`를 생략하면 출생일 당시가 아닌 **실행 시점의 GMT 시차**를 사용합니다. 한국 표준시 환경에서는 `+09:00`이며, 서머타임을 사용하는 환경에서는 현재 서머타임도 반영됩니다. 출생 당시 위치의 시차로 계산하려면 해당 시차를 직접 지정하세요.
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
## 라이브러리 적용
|
|
25
231
|
|
|
26
232
|
```js
|
|
27
233
|
import { calculateSajuChart, formatSajuChart } from "saju8z";
|
|
@@ -34,36 +240,28 @@ const result = calculateSajuChart({
|
|
|
34
240
|
|
|
35
241
|
console.log(result.fourPillars); // 사주팔자 객체
|
|
36
242
|
console.log(result.tenGods); // 십성 객체
|
|
37
|
-
console.log(formatSajuChart(result, "text")); //
|
|
243
|
+
console.log(formatSajuChart(result, "text")); // 만세력 텍스트 문자열
|
|
38
244
|
console.log(formatSajuChart(result, "json")); // JSON 문자열
|
|
245
|
+
console.log(formatSajuChart(result, "prompt")); // AI 전달용 프롬프트 문자열
|
|
39
246
|
```
|
|
40
247
|
|
|
41
|
-
CommonJS에서는 `require`로 가져옵니다.
|
|
42
248
|
|
|
43
|
-
```js
|
|
44
|
-
const { calculateSajuChart, formatSajuChart } = require("saju8z");
|
|
45
|
-
|
|
46
|
-
const result = calculateSajuChart({
|
|
47
|
-
date: "2000-02-29",
|
|
48
|
-
time: "00:10",
|
|
49
|
-
gmt: "+09:00"
|
|
50
|
-
});
|
|
51
|
-
console.log(formatSajuChart(result));
|
|
52
|
-
```
|
|
53
249
|
|
|
54
250
|
## 입력
|
|
55
251
|
|
|
56
252
|
`calculateSajuChart(input)`은 다음 객체를 받습니다.
|
|
57
253
|
|
|
58
|
-
| 필드 | 타입 | 필수 | 설명 |
|
|
59
|
-
| ----------- | --------- | -------- | ------------------------------------------------------ | ------------------------------------- |
|
|
60
|
-
| `date` | `string` | 예 | `YYYY-MM-DD`. 선택한 달력 기준의 날짜 |
|
|
61
|
-
| `time` | `string` | 예 | `HH:mm`, `00:00`\~`23:59`. 초는 지원하지 않음 |
|
|
62
|
-
| `gmt` | `string` | 예 | 부호를 포함한 고정 시차 `±HH:mm`, `-12:00`\~`+14:00` |
|
|
63
|
-
| `calendar` | `"solar" | "lunar"` | 아니요 | 양력 또는 한국 음력. 기본값 `"solar"` |
|
|
64
|
-
| `leapMonth` | `boolean` | 아니요 | 음력 윤달 여부. 기본값 `false`, 음력에서만 `true` 허용 |
|
|
65
254
|
|
|
66
|
-
|
|
255
|
+
| 필드 | 타입 | 필수 | 설명 |
|
|
256
|
+
| ----------- | -------------------- | --- | ------------------------------------------ |
|
|
257
|
+
| `date` | `string` | 예 | `YYYY-MM-DD`. 선택한 달력 기준의 날짜 |
|
|
258
|
+
| `time` | `string` | 예 | `HH:mm`, `00:00`\~`23:59`. 초는 지원하지 않음 |
|
|
259
|
+
| `gmt` | `string` | 예 | 부호를 포함한 고정 시차 `±HH:mm`, `-12:00`\~`+14:00` |
|
|
260
|
+
| `calendar` | `"solar"`, `"lunar"` | 아니요 | 양력 또는 한국 음력. 기본값 `"solar"` |
|
|
261
|
+
| `leapMonth` | `boolean` | 아니요 | 음력 윤달 여부. 기본값 `false`, 음력에서만 `true` 허용 |
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
라이브러리 API의 `gmt`는 출생 당시 날짜·시간의 시차를 직접 지정합니다. 예를 들어 한국 표준시는 `+09:00`, UTC는 `+00:00`입니다. 실행 환경의 시간대나 지역 이름으로 자동 추정하지 않습니다.
|
|
67
265
|
|
|
68
266
|
음력 윤달은 다음과 같이 입력합니다.
|
|
69
267
|
|
|
@@ -78,84 +276,39 @@ const result = calculateSajuChart({
|
|
|
78
276
|
// 양력 2017-06-24 12:00, GMT+09:00 입력과 같은 결과
|
|
79
277
|
```
|
|
80
278
|
|
|
81
|
-
## 결과와 출력 형식
|
|
82
|
-
|
|
83
|
-
`calculateSajuChart`는 JSON으로 직렬화 가능한 `SajuChartResult` 객체를 반환합니다.
|
|
84
279
|
|
|
85
|
-
| 필드 | 내용 |
|
|
86
|
-
| --------------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
87
|
-
| `normalizedDateTime` | 양력으로 변환하고 GMT+09:00으로 환산한 `{ year, month, day, hour, minute }` |
|
|
88
|
-
| `calculationDateTime` | 환산 시각에 -30분 보정을 적용한 계산 시각 |
|
|
89
|
-
| `fourPillars` | `year`, `month`, `day`, `hour`의 사주팔자. 각 값은 `{ stem, branch }` |
|
|
90
|
-
| `tenGods` | 일간 기준 십성. `yearStem`, `yearBranch`, `monthStem`, `monthBranch`, `dayBranch`, `hourStem`, `hourBranch` |
|
|
91
|
-
| `calculationProfile` | 계산 규칙 식별자. 현재 `saju8z-fixed-gmt-kst-minus30-v1` |
|
|
92
280
|
|
|
93
|
-
|
|
281
|
+
## 결과와 출력 형식
|
|
94
282
|
|
|
95
|
-
|
|
283
|
+
`calculateSajuChart`는 JSON으로 직렬화 가능한 `SajuChartResult` 객체를 반환합니다.
|
|
96
284
|
|
|
97
|
-
`formatSajuChart(result)` 또는 `formatSajuChart(result, "text")`는 시주·일주·월주·년주 순서의 Markdown 표를 반환합니다. 천간·지지의 한자, 오행, 십성을 포함합니다. 빠른 시작 예제의 출력은 다음과 같습니다.
|
|
98
285
|
|
|
99
|
-
|
|
100
|
-
|
|
|
101
|
-
|
|
|
102
|
-
|
|
|
103
|
-
|
|
|
104
|
-
|
|
|
105
|
-
| 지지 | 자(子) | 진(辰) | 인(寅) | 진(辰) |
|
|
106
|
-
| 지지 오행 | 水 | 土 | 木 | 土 |
|
|
107
|
-
| 지지 십성 | 정관 | 식신 | 편인 | 식신 |
|
|
108
|
-
```
|
|
286
|
+
| 필드 | 내용 |
|
|
287
|
+
| --------------------- | ----------------------------------------------------------------------------------------------------- |
|
|
288
|
+
| `normalizedDateTime` | 양력으로 변환하고 GMT+09:00으로 환산한 `{ year, month, day, hour, minute }` |
|
|
289
|
+
| `calculationDateTime` | 환산 시각에 -30분 보정을 적용한 계산 시각 |
|
|
290
|
+
| `fourPillars` | `year`, `month`, `day`, `hour`의 사주팔자. 각 값은 `{ stem, branch }` |
|
|
291
|
+
| `tenGods` | 일간 기준 십성. `yearStem`, `yearBranch`, `monthStem`, `monthBranch`, `dayBranch`, `hourStem`, `hourBranch` |
|
|
109
292
|
|
|
110
|
-
### JSON
|
|
111
293
|
|
|
112
|
-
`
|
|
294
|
+
천간·지지·십성은 `"병"`, `"진"`, `"식신"`과 같은 한국어 문자열입니다. 일간 자체의 십성 필드는 없으며, 만세력 텍스트에서는 `본원`으로 표시합니다.
|
|
113
295
|
|
|
114
|
-
```js
|
|
115
|
-
const json = formatSajuChart(result, "json");
|
|
116
|
-
const restored = JSON.parse(json);
|
|
117
|
-
console.log(restored.fourPillars.day); // { stem: "병", branch: "진" }
|
|
118
|
-
```
|
|
119
296
|
|
|
120
|
-
## TypeScript와 오류 처리
|
|
121
297
|
|
|
122
|
-
|
|
298
|
+
## 추가 진입점
|
|
123
299
|
|
|
124
|
-
```ts
|
|
125
|
-
import { calculateSajuChart, formatSajuChart, UserInputError } from "saju8z";
|
|
126
|
-
import type { SajuChartInput, SajuChartResult, SajuChartFormat } from "saju8z";
|
|
127
300
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
try {
|
|
136
|
-
const result: SajuChartResult = calculateSajuChart(input);
|
|
137
|
-
console.log(formatSajuChart(result, format));
|
|
138
|
-
} catch (error) {
|
|
139
|
-
if (error instanceof UserInputError) {
|
|
140
|
-
console.error(error.message);
|
|
141
|
-
} else {
|
|
142
|
-
throw error;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
```
|
|
301
|
+
| 가져오기 경로 | 용도 |
|
|
302
|
+
| --------------- | ------------------------------------------------------------------ |
|
|
303
|
+
| `saju8z` | `calculateSajuChart`, `formatSajuChart`, `UserInputError` 및 입출력 타입 |
|
|
304
|
+
| `saju8z/core` | 저수준 계산 함수, 상수, 간지·오행 데이터와 도메인 타입 |
|
|
305
|
+
| `saju8z/lunar` | `lunarToSolar`, `lunarMonthDays`, `hasLunarLeapMonth` |
|
|
306
|
+
| `saju8z/format` | `formatSajuChart`, `SajuChartFormat`, `SajuChartResult` 타입 |
|
|
146
307
|
|
|
147
|
-
잘못된 날짜·시각·GMT, 지원 범위 밖 날짜, 존재하지 않는 윤달은 `UserInputError`를 발생시킵니다. 출력 형식은 `"text"`와 `"json"`만 허용합니다.
|
|
148
308
|
|
|
149
|
-
|
|
309
|
+
일반적인 만세력 계산에는 `saju8z`를 사용합니다. 저수준 함수는 입력 검증과 보정 적용 방식을 호출자가 확인해야 합니다.
|
|
150
310
|
|
|
151
|
-
| 가져오기 경로 | 용도 |
|
|
152
|
-
| --------------- | ------------------------------------------------------------------------ |
|
|
153
|
-
| `saju8z` | `calculateSajuChart`, `formatSajuChart`, `UserInputError` 및 입출력 타입 |
|
|
154
|
-
| `saju8z/core` | 저수준 계산 함수, 상수, 간지·오행 데이터와 도메인 타입 |
|
|
155
|
-
| `saju8z/lunar` | `lunarToSolar`, `lunarMonthDays`, `hasLunarLeapMonth` |
|
|
156
|
-
| `saju8z/format` | `formatSajuChart`, `SajuChartFormat`, `SajuChartResult` 타입 |
|
|
157
311
|
|
|
158
|
-
일반적인 만세력 계산에는 `saju8z`를 사용합니다. 저수준 함수는 입력 검증과 보정 적용 방식을 호출자가 확인해야 합니다.
|
|
159
312
|
|
|
160
313
|
## 계산 기준과 지원 범위
|
|
161
314
|
|
|
@@ -169,22 +322,23 @@ try {
|
|
|
169
322
|
|
|
170
323
|
성별 입력은 필요하지 않습니다. 대운·세운·운세·성격 해석 기능은 제공하지 않습니다.
|
|
171
324
|
|
|
172
|
-
## 소스 개발과 패키지 검증
|
|
173
325
|
|
|
174
|
-
라이브러리 자체를 수정하는 경우 저장소를 내려받은 뒤 아래 명령을 사용합니다.
|
|
175
326
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
327
|
+
## 폴더 역할
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
| 위치 | 역할 |
|
|
331
|
+
| -------------------------- | ----------------------------- |
|
|
332
|
+
| `src/input/` | 입력 문자열 해석, 형식 검증, 사용자 입력 오류 |
|
|
333
|
+
| `src/application/` | 음력·시차 환산과 사주 계산 순서 조합 |
|
|
334
|
+
| `src/calendar/` | 날짜 산술, 음력 변환, 절기·태양시 보정 |
|
|
335
|
+
| `src/saju/`, `src/domain/` | 사주·십성 계산 규칙, 타입과 기준 데이터 |
|
|
336
|
+
| `src/output/` | 만세력 텍스트 생성, 프롬프트 조립과 출력 형식 선택 |
|
|
337
|
+
| `bin/` | CLI 옵션 해석과 표준 입출력 |
|
|
338
|
+
| `test/`, `scripts/` | 회귀 테스트, 빌드와 설치 패키지 검증 |
|
|
339
|
+
|
|
340
|
+
|
|
186
341
|
|
|
187
|
-
계산 원본은 `src/`, 테스트는 `test/`, 빌드·패키지 검증 스크립트는 `scripts/`에 있습니다. JavaScript 스크립트는 `package.json`의 `"type": "module"` 설정에 따라 ES 모듈로 실행합니다. `dist/`는 빌드 산출물이며 npm 패키지에는 실행 번들·타입 선언·README·LICENSE·제3자 고지를 포함합니다.
|
|
188
342
|
|
|
189
343
|
## 라이선스
|
|
190
344
|
|
|
@@ -192,4 +346,4 @@ npm pack # saju8z-1.0.0.tgz 생성
|
|
|
192
346
|
|
|
193
347
|
상업적 사용·수정·재배포를 허용하며, 소프트웨어의 복사본이나 주요 부분에 저작권 및 라이선스 고지를 유지해야 합니다. 소프트웨어는 보증 없이 제공됩니다. 정확한 조건은 LICENSE 전문을 참고하세요.
|
|
194
348
|
|
|
195
|
-
번들에 포함된 `korean-lunar-calendar`의 원 저작권 및 MIT 라이선스 고지는 [THIRD-PARTY-LICENSES.txt](THIRD-PARTY-LICENSES.txt)에 별도로 보존합니다.
|
|
349
|
+
번들에 포함된 `korean-lunar-calendar`의 원 저작권 및 MIT 라이선스 고지는 [THIRD-PARTY-LICENSES.txt](THIRD-PARTY-LICENSES.txt)에 별도로 보존합니다.
|
package/bin/saju8z.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import process from "node:process";
|
|
3
|
+
import { calculateSajuChart, formatSajuChart, UserInputError } from "../dist/index.js";
|
|
4
|
+
|
|
5
|
+
const HELP_TEXT = `사용법: saju8z --date YYYY-MM-DD --time HH:mm [--gmt ±HH:mm] [옵션]
|
|
6
|
+
|
|
7
|
+
필수 입력:
|
|
8
|
+
--date 생년월일 (YYYY-MM-DD)
|
|
9
|
+
--time 출생 시각 (HH:mm, 00:00~23:59)
|
|
10
|
+
|
|
11
|
+
옵션:
|
|
12
|
+
--gmt 고정 GMT 시차 (기본: 실행 환경의 현재 시차, -12:00~+14:00)
|
|
13
|
+
--calendar solar (기본) 또는 lunar (한국 음력)
|
|
14
|
+
--leap 음력 윤달 지정 (--calendar lunar와 함께 사용)
|
|
15
|
+
--format text (기본 만세력 텍스트), json 또는 prompt (AI 전달용)
|
|
16
|
+
--help, -h 도움말
|
|
17
|
+
|
|
18
|
+
예제:
|
|
19
|
+
saju8z --date 2000-02-29 --time 00:10
|
|
20
|
+
saju8z --date 2000-02-29 --time 00:10 --gmt +09:00
|
|
21
|
+
saju8z --date 2000-02-29 --time 00:10 --gmt=-05:00 --format json
|
|
22
|
+
saju8z --date 2000-02-29 --time 00:10 --format prompt
|
|
23
|
+
saju8z --date 2017-05-01 --time 12:00 --gmt +09:00 --calendar lunar --leap
|
|
24
|
+
`;
|
|
25
|
+
|
|
26
|
+
function getCurrentGmtOffset() {
|
|
27
|
+
const minutes = -new Date().getTimezoneOffset();
|
|
28
|
+
const sign = minutes < 0 ? "-" : "+";
|
|
29
|
+
const absolute = Math.abs(minutes);
|
|
30
|
+
const hours = String(Math.floor(absolute / 60)).padStart(2, "0");
|
|
31
|
+
const remainder = String(absolute % 60).padStart(2, "0");
|
|
32
|
+
return `${sign}${hours}:${remainder}`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const VALUE_OPTIONS = new Set(["--date", "--time", "--gmt", "--calendar", "--format"]);
|
|
36
|
+
|
|
37
|
+
/** @param {string[]} args */
|
|
38
|
+
function parseOptions(args) {
|
|
39
|
+
/** @type {Map<string, string>} */
|
|
40
|
+
const values = new Map();
|
|
41
|
+
let leapMonth = false;
|
|
42
|
+
for (let index = 0; index < args.length; index++) {
|
|
43
|
+
const argument = args[index];
|
|
44
|
+
const separator = argument.indexOf("=");
|
|
45
|
+
const option = separator < 0 ? argument : argument.slice(0, separator);
|
|
46
|
+
if (option === "--leap" && separator < 0) {
|
|
47
|
+
if (leapMonth) throw new UserInputError("중복된 옵션입니다: --leap");
|
|
48
|
+
leapMonth = true;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (!VALUE_OPTIONS.has(option)) throw new UserInputError(`지원하지 않는 옵션입니다: ${option}`);
|
|
52
|
+
if (values.has(option)) throw new UserInputError(`중복된 옵션입니다: ${option}`);
|
|
53
|
+
const value = separator < 0 ? args[++index] : argument.slice(separator + 1);
|
|
54
|
+
if (!value || value.startsWith("--")) throw new UserInputError(`${option} 값을 입력하세요.`);
|
|
55
|
+
values.set(option, value);
|
|
56
|
+
}
|
|
57
|
+
return { values, leapMonth };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** @param {string[]} args */
|
|
61
|
+
function parseArguments(args) {
|
|
62
|
+
const { values, leapMonth } = parseOptions(args);
|
|
63
|
+
const date = values.get("--date");
|
|
64
|
+
const time = values.get("--time");
|
|
65
|
+
if (!date || !time) throw new UserInputError("--date, --time은 필수입니다.");
|
|
66
|
+
const gmt = values.get("--gmt") ?? getCurrentGmtOffset();
|
|
67
|
+
const calendar = values.get("--calendar") ?? "solar";
|
|
68
|
+
if (calendar !== "solar" && calendar !== "lunar")
|
|
69
|
+
throw new UserInputError("달력은 solar 또는 lunar여야 합니다.");
|
|
70
|
+
const format = values.get("--format") ?? "text";
|
|
71
|
+
if (format !== "text" && format !== "json" && format !== "prompt")
|
|
72
|
+
throw new UserInputError("출력 형식은 text, json 또는 prompt이어야 합니다.");
|
|
73
|
+
return { input: { date, time, gmt, calendar, leapMonth }, format };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
const args = process.argv.slice(2);
|
|
78
|
+
const showHelp = args.length === 1 && (args[0] === "--help" || args[0] === "-h");
|
|
79
|
+
if (showHelp) {
|
|
80
|
+
process.stdout.write(HELP_TEXT);
|
|
81
|
+
} else {
|
|
82
|
+
const { input, format } = parseArguments(args);
|
|
83
|
+
const result = calculateSajuChart(input);
|
|
84
|
+
process.stdout.write(`${formatSajuChart(result, format)}\n`);
|
|
85
|
+
}
|
|
86
|
+
} catch (error) {
|
|
87
|
+
process.stderr.write(
|
|
88
|
+
`saju8z: ${error instanceof Error ? error.message : "계산에 실패했습니다."}\n도움말: saju8z --help\n`
|
|
89
|
+
);
|
|
90
|
+
process.exitCode = 1;
|
|
91
|
+
}
|