npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

saju-core

v0.2.0

Published

Core computational engine for Saju fortune analysis.

Readme

Saju Core

Saju Core는 사주(四柱) 명리학을 분석하기 위한 순수 TypeScript 라이브러리입니다. 천간/지지 데이터를 기반으로 명식을 계산하고, 대운 흐름과 일/주간 운세를 추적하며, 두 사람 간의 궁합을 정량적으로 산출할 수 있습니다. 또한 i18n 언어팩과 표현(포맷팅) 플러그인 시스템을 내장하여 다양한 언어·도메인에 맞게 커스터마이징할 수 있습니다.

목차

특징

  • 정확한 명식 계산: 천간/지지 60갑자 순환과 시주 계산, 숨은 천간, 십신 관계를 자동 계산합니다.
  • 다양한 분석 기능: 대운 주기, 일일/주간 운세, 두 명의 명식을 기반으로 한 궁합 점수 및 분석 메모를 제공합니다.
  • 포맷팅 추상화: 언어 혹은 도메인에 맞게 결과를 문자열로 표현할 수 있는 플러그인 아키텍처를 제공합니다.
  • 국제화 지원: 언어팩 레지스트리를 통해 메시지를 다국어로 교체할 수 있습니다.
  • 데이터 제공: 오행, 십천간, 십이지, 절기, 합·충·형 등 명리 핵심 자료를 JSON 형태로 내장하여 손쉽게 활용할 수 있습니다.
  • TypeScript 친화적: 정교한 타입 정의를 통해 정적 타입 검증과 IDE 자동완성을 지원합니다.

설치

워크스페이스 루트에서 다음 명령을 실행합니다.

pnpm install
pnpm --filter @saju/core build

다른 프로젝트에서 사용할 때는 워크스페이스 루트에서 다음 명령으로 의존성을 추가하세요.

pnpm --filter @saju/core add <프로젝트 경로>

빠른 시작

import {
  computeNatal,
  computeLuck,
  computeDailyFortune,
  computeMatchFromNatal,
  evaluateMovingDate,
  evaluateMarriageDate,
  evaluateOpeningDate,
  formatNatal,
  formatWeeklyFortune
} from '@saju/core';

const natal = computeNatal({ birth: new Date('1991-07-15T09:30:00Z') });
const luck = computeLuck(natal);
const daily = computeDailyFortune(natal);
const weeklyText = formatWeeklyFortune(computeWeeklyFortune(natal));

const match = computeMatchFromNatal(
  { birth: new Date('1991-07-15T09:30:00Z') },
  { birth: new Date('1993-02-01T21:00:00Z') }
);

const moving = evaluateMovingDate(
  { birth: new Date('1990-05-15T00:00:00Z') },
  new Date('2024-03-18T00:00:00Z'),
  { direction: 'north', distanceKm: 0.3 }
);

const marriage = evaluateMarriageDate(
  { birth: new Date('1986-02-10T00:00:00Z'), gender: 'male' },
  { birth: new Date('1988-08-21T00:00:00Z'), gender: 'female' },
  new Date('2024-06-22T00:00:00Z')
);

const opening = evaluateOpeningDate(
  { birth: new Date('1984-11-02T00:00:00Z') },
  new Date('2024-09-05T00:00:00Z')
);

console.log(formatNatal(natal));
console.log(luck.dominantElement, match.score.compatibility);
console.log(daily.summaryKey, weeklyText);
console.log(moving.totalScore, moving.vetoReasons);
console.log(marriage.isViable, marriage.applications);
console.log(opening.totalScore);

API 요약

핵심 계산

  • computeNatal(input: NatalInput): NatalChart
    • 출생 정보를 기반으로 년/월/일/시 기둥, 일간(주인), 숨은 천간, 십신, 오행 분포, 정규화된 오행 비율을 계산합니다.
    • 시간 표준화: 입력값은 “한국 민간 시계 기준(Local Korea Civil Time)”으로 간주되며, 내부적으로 역사적 표준시/서머타임 규칙을 적용해 UTC로 정규화한 뒤 경도 127.5°E 기준 LMT(UTC+8:30)로 변환하여 명식을 산출합니다. 결과 객체의 input.localKoreaCivil/utc/lmt에서 세 시각을 모두 확인할 수 있습니다.
    • 예시 반환:
      {
        "year": { "index": 4, "stem": { "id": 4, "name": "무", "element": "earth", "polarity": "yang" }, "branch": { "id": 4, "name": "진", "element": "earth", "animal": "dragon" } },
        "month": { "index": 49, "stem": { "id": 9, "name": "계", "element": "water", "polarity": "yin" }, "branch": { "id": 1, "name": "축", "element": "earth", "animal": "ox" } },
        "day": { "index": 0, "stem": { "id": 0, "name": "갑", "element": "wood", "polarity": "yang" }, "branch": { "id": 0, "name": "자", "element": "water", "animal": "rat" } },
        "hour": { "index": 1, "stem": { "id": 1, "name": "을", "element": "wood", "polarity": "yin" }, "branch": { "id": 1, "name": "축", "element": "earth", "animal": "ox" } },
        "dayMaster": { "id": 0, "name": "갑", "element": "wood", "polarity": "yang" },
        "normalizedElementTally": { "wood": 0.25, "fire": 0, "earth": 0.5, "metal": 0, "water": 0.25 }
      }
  • computeLuck(natal: NatalChart): LuckProfile
    • 명식 기준 10년 단위 대운 주기와 각 주기의 점수, 우세 오행을 제공합니다.
    • 주의: 대운의 순/역행과 시작나이는 연간 음양과 성별에 의해 결정됩니다. 성별을 반영하려면 computeLuck(natal, 'male' | 'female') 인자를 사용하세요.
    • 예시 반환:
      {
        "dominantElement": "earth",
        "firstCycle": {
          "startYear": 4,
          "endYear": 13,
          "pillar": { "index": 5, "stem": { "id": 5, "name": "기", "element": "earth", "polarity": "yin" }, "branch": { "id": 5, "name": "사", "element": "fire", "animal": "snake" } },
          "score": 0.3
        }
      }
  • setRuleWeights(partial: Partial<RuleWeights>): void
    • 매칭/운세 평가에 사용되는 가중치를 부분적으로 덮어씁니다.
    • 예시 반환: undefined (예: setRuleWeights({ match: { elementHarmony: 0.5 } }) 호출 후 RULE_WEIGHTS.match{ elementHarmony: 0.5, tenGodSynergy: 0.3, branchInteractions: 0.3 }).

궁합 및 운세

  • computeMatch(a: NatalChart, b: NatalChart): MatchResult
    • 오행 조화, 십신 시너지, 지지 상호작용을 바탕으로 궁합 점수와 상세 메모를 산출합니다.
    • 예시 반환:
      {
        "score": { "compatibility": 0.601, "elementHarmony": 0.8, "tenGodSynergy": 0.5, "branchInteractions": 0.438 },
        "notes": ["오행 조화: 80.0%", "십신 시너지: 50.0%"]
      }
  • computeMatchFromNatal(a: NatalInput, b: NatalInput): MatchResult
    • 입력된 출생 정보로 명식을 생성한 뒤 computeMatch를 호출합니다.
    • 예시 반환:
      {
        "score": { "compatibility": 0.601, "elementHarmony": 0.8, "tenGodSynergy": 0.5, "branchInteractions": 0.438 },
        "notes": ["오행 조화: 80.0%", "십신 시너지: 50.0%"]
      }
  • computeDailyFortune(natal: NatalChart, options?: DailyFortuneOptions): DailyFortuneResult
    • 특정 일자의 운세 점수, 요약 메시지 키, 조언 메시지를 제공합니다.
    • 예시 반환:
      {
        "date": "2024-01-01T00:00:00.000Z",
        "dayPillar": { "index": 58, "stem": { "id": 8, "name": "임", "element": "water", "polarity": "yang" }, "branch": { "id": 10, "name": "술", "element": "earth", "animal": "dog" } },
        "score": { "compatibility": 0.677, "elementHarmony": 0.85, "tenGodSynergy": 0.75, "branchInteractions": 0.375 },
        "level": "good",
        "summaryKey": "fortune.daily.summary.good",
        "adviceKeys": ["fortune.advice.progress"]
      }
  • computeWeeklyFortune(natal: NatalChart, options?: WeeklyFortuneOptions): WeeklyFortuneResult
    • 7일 간의 일일 운세, 평균 점수, 추세, 가장 좋은/도전적인 날을 계산합니다.
    • 예시 반환:
      {
        "averageScore": { "compatibility": 0.648, "elementHarmony": 0.864, "tenGodSynergy": 0.607, "branchInteractions": 0.402 },
        "dominantTrend": "steady",
        "bestDayIndex": 3,
        "daily": [
          { "date": "2024-01-01T00:00:00.000Z", "score": { "compatibility": 0.677, "elementHarmony": 0.85, "tenGodSynergy": 0.75, "branchInteractions": 0.375 }, "level": "good", "summaryKey": "fortune.daily.summary.good", "adviceKeys": ["fortune.advice.progress"] }
        ]
      }

신년 운세 2026

  • getNewYearFortune2026(input: NatalInput, options?: NewYearFortune2026Options): NewYearFortune2026Result
    • 2026년 병오년을 기준으로 명식의 신년 운세를 분석하고, 명식 강약·대운·합충·생활 영역별 메시지를 제공합니다.
    • 로케일: options.locale'ko' | 'en' 등을 전달해 다국어 출력을 제어할 수 있습니다. 전달하지 않으면 현재 활성화된 언어팩 또는 기본 로케일을 따릅니다.
    • 예시 반환:

정통 사주 분석

  • computeTraditionalSajuAnalysis(input: NatalInput): TraditionalSajuAnalysis
    • 정통 명리 규칙을 반영해 원국의 강약, 격/변격(프레임워크), 주요 기운, 오행 합·충, 재물/직업/관계 테마, 대운 흐름, 신살(천을귀인·월덕귀인·도화·역마·화개·탕화·고신·과숙·괴강·원진 등)을 종합 리포트 형태로 제공합니다.

    • 시간 표준화는 computeNatal과 동일하게 적용됩니다. 입력에 gender가 포함되면 대운 방향 및 시작나이에 반영됩니다.

    • 반환 구조는 다음과 같이 3개 대영역으로 구성됩니다.

      • foundationalAnalysis: 원국 기반 분석(강약, 격/변격, 주요 기운, 합·충)
      • thematicFortuneAnalysis: 재물/직업, 관계운 요약
      • lifeFlowAndSpecialInfluences: 대운(10년 주기)과 신살 요약
    • 추가 제공 항목(요구사항 반영):

      • 격: 아래 10개 중 하나의 표준 명칭으로 반환 + 변격 여부(boolean)
        • 건록격(建祿格), 양인격(陽刃格), 식신격(食神格), 상관격(傷官格), 정재격(正財格), 편재격(偏財格), 정관격(正官格), 편관격(七殺格), 정인격(正印格), 편인격(偏印格)
      • 오행 상태 평가: status(아래 중 하나)와 오행 상대 비율(%)
        • 균형형 (조화형) | 편중형 (偏旺) | 결핍형 (欠行) | 극단형 (過旺·過弱) | 화평형 (調和)
      • 대운: 전체 등급(약함|보통|강함)과 주제별 강세 구간 문장 배열
        • 예) 대운(大運)에 재물운이 강하게 들어오는 시기는 [ 11세에서 20세 ] 사이입니다.
      • 신살: 대표 신살 이름 배열(한자 병기)과 감지된 신호(positive/neutral/cautionary) 목록
        • 예) ['월덕귀인(月德貴人)', '천덕귀인(天德貴人)', '도화살(桃花殺)', '현침(懸針)']
    • 간단 사용 예:

      import { computeTraditionalSajuAnalysis } from '@saju/core';
      const report = computeTraditionalSajuAnalysis({ birth: new Date('1991-07-15T09:30:00Z'), gender: 'female' });
      console.log(report.lifeFlowAndSpecialInfluences.symbolicStars.insight);
      {
        "strength": {
          "level": "strong",
          "score": 310,
          "supportiveFactors": ["연지의 숨은 기운이 일간을 보강합니다.", "월지의 숨은 기운이 일간을 보강합니다.", "일지의 숨은 기운이 일간을 보강합니다."]
        },
        "year": {
          "pillar": { "index": 42, "stem": { "id": 2, "name": "병", "element": "fire", "polarity": "yang" }, "branch": { "id": 6, "name": "오", "element": "fire", "animal": "horse" } },
          "stemRelation": "식신",
          "branchRelations": ["상관", "편재"]
        },
        "keyThemes": ["병오년의 식신 기운이 한 해의 핵심 의제가 됩니다."],
        "categories": {
          "career": "표현력과 기획력이 살아나 창의적인 프로젝트에 강점을 보입니다. 콘텐츠 기획, 강연, 브랜딩 등 외부와 소통하는 일을 적극 추진하면 성과가 따릅니다. 주도권을 잡을 수 있을 만큼 에너지가 충분하니, 공식적인 자리에서 리더십을 발휘해 보세요. 중요한 회의나 발표에서 주도권을 확보하면 영향력도 함께 커집니다. 직장 환경은 비교적 안정적으로 유지될 가능성이 큽니다. 성과 리뷰와 역량 개발 계획을 차분히 진행하면 내실을 다질 수 있습니다."
        }
      }
  • generate2026NewYearFortune (alias)
    • getNewYearFortune2026의 별칭으로 동일한 결과를 반환합니다.
    • 예시 반환: 위 getNewYearFortune2026과 동일.

택일 지원

  • evaluateMovingDate(person: DateSelectionPerson, date: Date, options?: MovingSelectionOptions): DateSelectionResult
    • 생기복덕, 월가흉신, 대장군방/삼살방을 종합하여 이사 적합도를 점수화합니다.
    • 예시 반환:
      {
        "totalScore": -30,
        "isViable": true,
        "vetoReasons": [],
        "applications": [
          { "id": "personal:가장:절체", "label": "가장 - 절체", "category": "personal", "type": "penalty", "score": -30 },
          { "id": "universal:hwangdo", "label": "황도일", "category": "universal", "type": "bonus", "score": 100 }
        ]
      }
  • evaluateMarriageDate(groom: DateSelectionPerson, bride: DateSelectionPerson, date: Date): DateSelectionResult
    • 신랑·신부 모두의 생기복덕과 고진/과숙살, 음양부장길일, 홍사 흉살을 동시에 평가합니다.
    • 예시 반환:
      {
        "totalScore": 70,
        "isViable": false,
        "vetoReasons": ["신랑에게 절명일", "수사일"],
        "applications": [
          { "id": "personal:신랑:절명", "label": "신랑 - 절명", "category": "personal", "type": "veto", "score": 0 },
          { "id": "personal:신부:귀혼", "label": "신부 - 귀혼", "category": "personal", "type": "penalty", "score": -30 },
          { "id": "universal:susa", "label": "수사", "category": "universal", "type": "veto", "score": 0 }
        ]
      }
  • evaluateOpeningDate(owner: DateSelectionPerson, date: Date): DateSelectionResult
    • 갑불개창·유불회객·공망일 금기를 확인하고 황도일·십전대길일 등의 가점을 계산합니다.
    • 예시 반환:
      {
        "totalScore": 170,
        "isViable": true,
        "vetoReasons": [],
        "applications": [
          { "id": "personal:대표:귀혼", "label": "대표 - 귀혼", "category": "personal", "type": "penalty", "score": -30 },
          { "id": "universal:hwangdo", "label": "황도일", "category": "universal", "type": "bonus", "score": 100 },
          { "id": "universal:tengreat", "label": "십전대길일", "category": "universal", "type": "bonus", "score": 100 }
        ]
      }

DateSelectionResult는 날짜의 총점(totalScore)과 적용된 규칙(applications), 치명적 금기 발생 여부(isViable, vetoReasons)를 제공합니다.

포맷팅 플러그인

  • formatNatal(chart: NatalChart): string
    • 예시 반환: 일간: 갑 (wood)\n지장간: 진[무, 을, 계], 축[기, 계, 신], 자[임, 계]\n십신: 무-정재, 계-편인, 갑-비견, 을-겁재
  • formatLuck(luck: LuckProfile): string
    • 예시 반환: 대운 4~13: 기사 (30.0%)\n대운 14~23: 경오 (0.0%)\n대운 24~33: 신미 (0.0%)\n대운 34~43: 임신 (15.0%)
  • formatMatch(match: MatchResult): string
    • 예시 반환: 궁합: 60.1%\n오행: 80.0%\n십신: 50.0%\n지지: 43.8%
  • formatDailyFortune(fortune: DailyFortuneResult): string
    • 예시 반환: 오늘의 종합운세: 2024-01-01\n종합 점수: 67.7%\n오행 조화: 85.0%\n십신 시너지: 75.0%\n지지 교감: 37.5%\n움직임이 잘 맞아떨어지는 날입니다.\n- 기회가 보이면 과감히 추진해도 좋습니다.
  • formatWeeklyFortune(fortune: WeeklyFortuneResult): string
    • 활성화된 표현 플러그인을 통해 분석 결과를 사람이 읽기 쉬운 문자열로 변환합니다.
    • 예시 반환: 주간 통합운세: 2024-01-01 ~ 2024-01-07\n종합 점수: 64.8%\n오행 조화: 86.4%\n십신 시너지: 60.7%\n지지 교감: 40.2%
  • registerExpressionPlugin(plugin: ExpressionPlugin): void
    • 새로운 포맷터를 등록합니다.
    • 예시 반환:
      registerExpressionPlugin({
        locale: 'en-demo',
        formatNatal: () => 'custom natal',
        formatLuck: () => 'custom luck',
        formatMatch: () => 'custom match',
        formatDailyFortune: () => 'custom daily',
        formatWeeklyFortune: () => 'custom weekly'
      });
      setActiveExpressionPlugin('en-demo');
      // register/set 호출 자체는 undefined를 반환하며, 이후
      getActiveExpressionPlugin().locale; // 'en-demo'
  • setActiveExpressionPlugin(locale: string): void
    • 사용할 포맷터를 선택합니다.
    • 예시 반환: undefined (예: 'en-demo' 지정 시 직후 getActiveExpressionPlugin().locale'en-demo').
  • getActiveExpressionPlugin(): ExpressionPlugin
    • 현재 활성화된 포맷터를 반환합니다.
    • 예시 반환: { "locale": "ko" }
  • 기본 제공 플러그인: defaultKoreanPlugin (ko-KR), defaultEnglishPlugin (en).

다국어(i18n)

  • getPhrase(key: string, localeOrVars?: string | Record<string, unknown>, vars?: Record<string, unknown>): string
    • 등록된 언어팩과 활성화된 프레이즈 프로바이더를 사용해 메시지 키를 문자열로 변환합니다.
    • 예시 반환: getPhrase('natal.dayMaster')'일간'
  • setPhraseProvider(provider?: (key: string, vars?: Record<string, unknown>, locale?: string) => string): void
    • 커스텀 메시지 조회 로직을 주입하거나 기본 프로바이더로 되돌립니다.
    • 예시 반환: undefined (예: 커스텀 제공자 설정 후 getPhrase('natal.dayMaster')'custom-natal.dayMaster', 해제 후 '일간').
  • registerLanguagePack(pack: LanguagePack): void
    • 메시지 번들을 레지스트리에 추가합니다.
    • 예시 반환: undefined (예: registerLanguagePack({ locale: 'en-demo', messages: { 'natal.dayMaster': 'Day Master' } })setActiveLocale('en-demo')getPhrase('natal.dayMaster')'Day Master').
  • setActiveLocale(locale: string): void
    • 사용할 언어팩을 선택합니다.
    • 예시 반환: undefined (예: 'en-demo' 활성화 시 이후 getPhrase('natal.dayMaster')'Day Master').
  • getActiveLocale(): LanguagePack
    • 활성화된 언어팩 정보를 가져옵니다.
    • 예시 반환:
      {
        "locale": "ko",
        "messages": {
          "natal.dayMaster": "일간",
          "fortune.daily.title": "오늘의 종합운세",
          "fortune.weekly.title": "주간 통합운세"
        }
      }
  • getAvailableLocales(): string[]
    • 등록된 언어팩 및 별칭 목록을 반환합니다.
    • 예시 반환: ["ko", "en", "cn"]
  • resolveLocale(locale?: string): string
    • 입력된 로케일 혹은 현재 활성화된 로케일을 정규화된 코드로 돌려줍니다.
    • 예시 반환: resolveLocale('en-US')'en'
  • 기본 언어팩: ko-KR (packages/core/src/i18n/ko-KR.json).

로케일 사용 팁

  • 핵심 API에서 options.locale 또는 활성 언어팩을 통해 메시지 로케일을 제어합니다. 예: getNewYearFortune2026(input, { locale: 'ko' }).
  • 문구 플러그인을 교체해야 하는 경우에도 우선 options.locale 전달을 권장합니다. 자세한 운영 지침은 리포지터리 루트의 AGENTS.md 문서 “Locale Handling in Agents” 섹션을 참고하세요.

데이터 & 규칙

아래 상수들은 명리 계산에 필요한 기본 데이터를 제공합니다.

  • HEAVENLY_STEMS, EARTHLY_BRANCHES: 십천간, 십이지 목록과 속성
    • 예시: HEAVENLY_STEMS.slice(0, 3)[{ "id": 0, "name": "갑", "element": "wood", "polarity": "yang" }, { "id": 1, "name": "을", "element": "wood", "polarity": "yin" }, { "id": 2, "name": "병", "element": "fire", "polarity": "yang" }], EARTHLY_BRANCHES.slice(0, 3)[{ "id": 0, "name": "자", "element": "water", "animal": "rat" }, { "id": 1, "name": "축", "element": "earth", "animal": "ox" }, { "id": 2, "name": "인", "element": "wood", "animal": "tiger" }]
  • ELEMENTS: 오행 정의 및 상생/상극 관계
    • 예시: ELEMENTS.slice(0, 2)[{ "id": "wood", "name": "목", "generates": "fire", "controls": "earth" }, { "id": "fire", "name": "화", "generates": "earth", "controls": "metal" }]
  • SOLAR_TERMS: 24절기 정보
    • 예시: SOLAR_TERMS[0]{ "id": 0, "name": "입춘", "degree": 315 }
  • HIDDEN_STEMS: 지지별 장간(장간 목록)
    • 예시: HIDDEN_STEMS.slice(0, 2)[{ "branch": "자", "stems": ["임", "계"] }, { "branch": "축", "stems": ["기", "계", "신"] }]
  • TEN_GODS: 십신 관계표
    • 예시: TEN_GODS.wood{ "wood": { "yang": "비견", "yin": "겁재" }, "fire": { "yang": "식신", "yin": "상관" }, "earth": { "yang": "정재", "yin": "편재" }, "metal": { "yang": "편관", "yin": "정관" }, "water": { "yang": "정인", "yin": "편인" } }
  • INTERACTIONS: 합(合)·충(沖)·형(刑)·파(破)·해(害) 규칙
    • 예시: INTERACTIONS.combine.slice(0, 2)[["자", "축"], ["인", "해"]]
  • RULE_WEIGHTS: 기본 가중치 설정 (오행 조화 등)
    • 예시: RULE_WEIGHTS.match{ "elementHarmony": 0.4, "tenGodSynergy": 0.3, "branchInteractions": 0.3 }

데이터는 packages/core/data/*.json 파일로도 제공되므로 필요 시 직접 참조할 수 있습니다.

유틸리티 함수

  • clamp(value: number, min: number, max: number): number
    • 점수를 지정한 범위로 제한합니다.
    • 예시 반환: clamp(120, 0, 100)100
  • indexToPillar(index: number): Pillar
    • 60갑자 인덱스를 천간/지지 기둥 객체로 변환합니다.
    • 예시 반환: indexToPillar(37){ "index": 37, "stem": { "id": 7, "name": "신", "element": "metal", "polarity": "yin" }, "branch": { "id": 1, "name": "축", "element": "earth", "animal": "ox" } }
  • getSexagenaryIndex(date: Date, unit?: 'year' | 'month' | 'day' | 'hour'): number
    • 지정한 단위에 대한 60갑자 순환 인덱스를 계산합니다.
    • 예시 반환: getSexagenaryIndex(new Date('2024-01-01T00:00:00Z'), 'year')40
  • normalizeElementTally(tally: ElementTally): ElementTally
    • 오행 개수를 합이 1이 되도록 정규화합니다.
    • 예시 반환: normalizeElementTally({ wood: 3, fire: 1, earth: 0, metal: 2, water: 4 }){ "wood": 0.3, "fire": 0.1, "earth": 0, "metal": 0.2, "water": 0.4 }

주요 타입

@saju/core는 모든 공개 API에 대해 타입 정의를 제공합니다. 대표 타입은 다음과 같습니다.

  • NatalInput, NatalChart
  • LuckCycle, LuckProfile
  • MatchResult, MatchScore
  • DailyFortuneResult, WeeklyFortuneResult
  • LanguagePack, ExpressionPlugin
  • NewYearFortune2026Result, NewYearFortune2026Options, ActiveLuckCycleInsight, YearInteractionInsight
  • ElementId, Pillar, HeavenlyStem, EarthlyBranch

사용 예시

궁합 및 운세 계산

import {
  computeNatal,
  computeMatch,
  computeWeeklyFortune,
  formatMatch
} from '@saju/core';

const alice = computeNatal({ birth: new Date('1988-03-12T02:00:00Z') });
const bob = computeNatal({ birth: new Date('1990-11-25T18:30:00Z') });

const match = computeMatch(alice, bob);
console.log(formatMatch(match));

const weekly = computeWeeklyFortune(alice, { startDate: new Date('2024-01-01T00:00:00Z') });
console.log(weekly.dominantTrend, weekly.bestDayIndex);

// 대운 방향/시작나이 성별 반영 및 시간 표준화 확인
const natalWithGender = computeNatal({ birth: new Date('1991-07-15T09:30:00Z'), gender: 'male' });
const luckMale = computeLuck(natalWithGender, 'male');
console.log(natalWithGender.input.localKoreaCivil.toISOString(), natalWithGender.input.utc.toISOString(), natalWithGender.input.lmt.toISOString());
console.log(luckMale.cycles[0].startAge, luckMale.cycles[0].startYear);

택일 분석 활용

import {
  evaluateMovingDate,
  evaluateMarriageDate,
  evaluateOpeningDate
} from '@saju/core';

const moving = evaluateMovingDate(
  { birth: new Date('1990-05-15T00:00:00Z') },
  new Date('2024-03-18T00:00:00Z'),
  { direction: 'north', distanceKm: 0.5 }
);

const marriage = evaluateMarriageDate(
  { birth: new Date('1986-02-10T00:00:00Z'), gender: 'male' },
  { birth: new Date('1988-08-21T00:00:00Z'), gender: 'female' },
  new Date('2024-06-22T00:00:00Z')
);

const opening = evaluateOpeningDate(
  { birth: new Date('1984-11-02T00:00:00Z') },
  new Date('2024-09-05T00:00:00Z')
);

console.log(moving.totalScore, moving.vetoReasons);
console.log(marriage.isViable, marriage.applications.map((app) => app.label));
console.log(opening.totalScore, opening.vetoReasons);

규칙 가중치 커스터마이징

import { setRuleWeights } from '@saju/core';

setRuleWeights({
  match: {
    elementHarmony: 0.5,
    tenGodSynergy: 0.3,
    branchInteractions: 0.2
  }
});

언어팩 확장

import { registerLanguagePack, setActiveLocale } from '@saju/core';

registerLanguagePack({
  locale: 'en-US',
  messages: {
    'natal.dayMaster': 'Day Master',
    'fortune.daily.title': 'Daily Fortune',
    'fortune.trend.rising': 'Rising'
    // ...필요한 메시지를 모두 추가하세요.
  }
});

setActiveLocale('en-US');

표현 플러그인 확장

import {
  registerExpressionPlugin,
  setActiveExpressionPlugin,
  formatLuck
} from '@saju/core';

registerExpressionPlugin({
  locale: 'en-US',
  formatNatal: (chart) => `Day master: ${chart.dayMaster.name}`,
  formatLuck: (luck) => `Dominant element: ${luck.dominantElement}`,
  formatMatch: (match) => `Compatibility: ${(match.score.compatibility * 100).toFixed(1)}%`,
  formatDailyFortune: (fortune) => `Score: ${(fortune.score.compatibility * 100).toFixed(1)}%`,
  formatWeeklyFortune: (fortune) => `Trend: ${fortune.dominantTrend}`
});

setActiveExpressionPlugin('en-US');

// 이후 formatLuck 등은 새 플러그인을 사용합니다.

개발 및 테스트

pnpm install
pnpm --filter @saju/core lint
pnpm --filter @saju/core test
pnpm --filter @saju/core build

테스트 러너는 Vitest와 fast-check 기반으로 구성되어 있습니다.

라이선스

MIT