UNPKG

kaabalah

Version:

The de-facto library for any esoteric calculations and tooling

1,591 lines (1,579 loc) 74.8 kB
'use strict'; var chunk4337NVKS_js = require('./chunk-4337NVKS.js'); // wasm/build/swisseph.node.wasm?url var swisseph_node_default = "./swisseph.node-2K5IHMKE.wasm?url"; // wasm/build/swisseph.web.wasm?url var swisseph_web_default = "./swisseph.web-2K5IHMKE.wasm?url"; // wasm/src/swisseph.ts var Planet = /* @__PURE__ */ ((Planet2) => { Planet2[Planet2["SUN"] = 0] = "SUN"; Planet2[Planet2["MOON"] = 1] = "MOON"; Planet2[Planet2["MERCURY"] = 2] = "MERCURY"; Planet2[Planet2["VENUS"] = 3] = "VENUS"; Planet2[Planet2["MARS"] = 4] = "MARS"; Planet2[Planet2["JUPITER"] = 5] = "JUPITER"; Planet2[Planet2["SATURN"] = 6] = "SATURN"; Planet2[Planet2["URANUS"] = 7] = "URANUS"; Planet2[Planet2["NEPTUNE"] = 8] = "NEPTUNE"; Planet2[Planet2["PLUTO"] = 9] = "PLUTO"; Planet2[Planet2["MEAN_NODE"] = 10] = "MEAN_NODE"; Planet2[Planet2["TRUE_NODE"] = 11] = "TRUE_NODE"; Planet2[Planet2["LILITH_MEAN"] = 12] = "LILITH_MEAN"; Planet2[Planet2["LILITH_TRUE"] = 13] = "LILITH_TRUE"; Planet2[Planet2["CHIRON"] = 15] = "CHIRON"; return Planet2; })(Planet || {}); var VirtualNodes = /* @__PURE__ */ ((VirtualNodes2) => { VirtualNodes2["PARS_FORTUNAE"] = "parsFortunae"; return VirtualNodes2; })(VirtualNodes || {}); var PLANET_AND_NODE_NAMES = { [0 /* SUN */]: "Sun", [1 /* MOON */]: "Moon", [2 /* MERCURY */]: "Mercury", [3 /* VENUS */]: "Venus", [4 /* MARS */]: "Mars", [5 /* JUPITER */]: "Jupiter", [6 /* SATURN */]: "Saturn", [7 /* URANUS */]: "Uranus", [8 /* NEPTUNE */]: "Neptune", [9 /* PLUTO */]: "Pluto", [10 /* MEAN_NODE */]: "Mean Node", [11 /* TRUE_NODE */]: "True Node", [12 /* LILITH_MEAN */]: "Lilith Mean", [13 /* LILITH_TRUE */]: "Lilith True", [15 /* CHIRON */]: "Chiron", ["parsFortunae" /* PARS_FORTUNAE */]: "Wheel of Fortune" }; var HouseSystem = /* @__PURE__ */ ((HouseSystem2) => { HouseSystem2["PLACIDUS"] = "P"; HouseSystem2["KOCH"] = "K"; HouseSystem2["PORPHYRIUS"] = "O"; HouseSystem2["REGIOMONTANUS"] = "R"; HouseSystem2["CAMPANUS"] = "C"; HouseSystem2["EQUAL"] = "E"; HouseSystem2["WHOLE_SIGN"] = "W"; HouseSystem2["MERIDIAN"] = "X"; HouseSystem2["MORINUS"] = "M"; HouseSystem2["KRUSINSKI"] = "U"; HouseSystem2["ALCABITIUS"] = "B"; return HouseSystem2; })(HouseSystem || {}); var CalcFlag = /* @__PURE__ */ ((CalcFlag2) => { CalcFlag2[CalcFlag2["JPL_EPH"] = 1] = "JPL_EPH"; CalcFlag2[CalcFlag2["SWISS_EPH"] = 2] = "SWISS_EPH"; CalcFlag2[CalcFlag2["MOSHIER"] = 4] = "MOSHIER"; CalcFlag2[CalcFlag2["HELIOCENTRIC"] = 8] = "HELIOCENTRIC"; CalcFlag2[CalcFlag2["TRUE_POS"] = 16] = "TRUE_POS"; CalcFlag2[CalcFlag2["J2000"] = 32] = "J2000"; CalcFlag2[CalcFlag2["NONUT"] = 64] = "NONUT"; CalcFlag2[CalcFlag2["SPEED3"] = 128] = "SPEED3"; CalcFlag2[CalcFlag2["SPEED"] = 256] = "SPEED"; CalcFlag2[CalcFlag2["EQUATORIAL"] = 2048] = "EQUATORIAL"; CalcFlag2[CalcFlag2["TOPOCTR"] = 32768] = "TOPOCTR"; CalcFlag2[CalcFlag2["SIDEREAL"] = 65536] = "SIDEREAL"; return CalcFlag2; })(CalcFlag || {}); var RiseTransitFlag = /* @__PURE__ */ ((RiseTransitFlag2) => { RiseTransitFlag2[RiseTransitFlag2["RISE"] = 1] = "RISE"; RiseTransitFlag2[RiseTransitFlag2["SET"] = 2] = "SET"; RiseTransitFlag2[RiseTransitFlag2["UPPER_MERIDIAN"] = 4] = "UPPER_MERIDIAN"; RiseTransitFlag2[RiseTransitFlag2["LOWER_MERIDIAN"] = 8] = "LOWER_MERIDIAN"; RiseTransitFlag2[RiseTransitFlag2["DISC_CENTER"] = 256] = "DISC_CENTER"; RiseTransitFlag2[RiseTransitFlag2["NO_REFRACTION"] = 512] = "NO_REFRACTION"; return RiseTransitFlag2; })(RiseTransitFlag || {}); var SE_ECL2HOR = 0; var SE_EQU2HOR = 1; var SE_AST_OFFSET = 1e4; var BODY = { MEAN_APOGEE: 12, // Lilith mean OSC_APOGEE: 13}; var normalizeAngle = (deg) => (deg % 360 + 360) % 360; var SwissEph = class { /** * Constructor that accepts a pre-initialized Swiss Ephemeris module */ constructor(module) { this.swe_julday = null; this.swe_calc_ut = null; this.swe_houses = null; this.swe_house_pos = null; this.swe_set_ephe_path = null; this.swe_close = null; this.swe_set_topo = null; this.swe_set_sid_mode = null; this.swe_azalt_fn = null; this.swe_rise_trans_fn = null; this.module = module; this.swe_julday = this.module.cwrap("swe_julday", "number", [ "number", "number", "number", "number", "number" ]); this.swe_calc_ut = this.module.cwrap("swe_calc_ut", "number", [ "number", "number", "number", "number", "number" ]); this.swe_houses = this.module.cwrap("swe_houses", "number", [ "number", "number", "number", "number", "number", "number" ]); this.swe_house_pos = this.module.cwrap( "swe_house_pos", "number", ["number", "number", "number", "string", "number", "number"] ); this.swe_set_ephe_path = this.module.cwrap( "swe_set_ephe_path", null, ["number"] ); this.swe_close = this.module.cwrap("swe_close", null, []); this.swe_set_topo = this.module.cwrap("swe_set_topo", null, [ "number", "number", "number" ]); this.swe_set_sid_mode = this.module.cwrap( "swe_set_sid_mode", null, ["number", "number", "number"] ); this.swe_azalt_fn = this.module.cwrap( "swe_azalt", null, ["number", "number", "number", "number", "number", "number", "number"] ); this.swe_rise_trans_fn = this.module.cwrap( "swe_rise_trans", "number", ["number", "number", "number", "number", "number", "number", "number", "number", "number", "number"] ); } checkInitialized() { if (!this.module) { throw new Error("Swiss Ephemeris module not available."); } } /** * Sets the path to the ephemeris data files. * @param path - The path to the directory containing ephemeris files. */ setEphemerisPath(path) { this.checkInitialized(); if (path && this.swe_set_ephe_path) { const pathPtr = this.module._malloc(path.length + 1); if (!pathPtr) { throw new Error("Failed to allocate memory for ephemeris path"); } this.module.stringToUTF8(path, pathPtr, path.length + 1); this.swe_set_ephe_path(pathPtr); this.module._free(pathPtr); } } /** * Calculate Julian day number for a given date and time */ getJulianDay(date) { this.checkInitialized(); if (!this.swe_julday) { throw new Error("Julian day calculation function not available"); } const year = date.getUTCFullYear(); const month = date.getUTCMonth() + 1; const day = date.getUTCDate(); const hour = date.getUTCHours() + date.getUTCMinutes() / 60 + date.getUTCSeconds() / 3600; return this.swe_julday(year, month, day, hour, 1); } /** * Calculate planet position at a given Julian day */ calculatePlanetPosition(julday, planet, flags = 2 /* SWISS_EPH */) { this.checkInitialized(); if (!this.swe_calc_ut || !this.module) { throw new Error("Planet calculation function not available"); } const resultPtr = this.module._malloc(6 * 8); if (!resultPtr) { throw new Error("Failed to allocate memory for planet position"); } const ERR_BYTES = 512; const errPtr = this.module._malloc(ERR_BYTES); if (!errPtr) { this.module._free(resultPtr); throw new Error("Failed to allocate memory for error buffer"); } this.module.HEAP8.fill(0, errPtr, errPtr + ERR_BYTES); try { let ret = this.swe_calc_ut(julday, planet, flags, resultPtr, errPtr); if (ret < 0) { const msg = this.module.UTF8ToString(errPtr); throw new Error(msg && msg.length ? msg : `Swiss Ephemeris calculation failed with error code ${ret}`); } const position = { longitude: this.module.getValue(resultPtr, "double"), latitude: this.module.getValue(resultPtr + 8, "double"), distance: this.module.getValue(resultPtr + 16, "double") }; if (flags & 256 /* SPEED */) { position.longitudeSpeed = this.module.getValue(resultPtr + 24, "double"); position.latitudeSpeed = this.module.getValue(resultPtr + 32, "double"); position.distanceSpeed = this.module.getValue(resultPtr + 40, "double"); } return position; } finally { this.module._free(errPtr); this.module._free(resultPtr); } } /** * Calculate houses for a given date, location, and house system */ calculateHouses(julday, latitude, longitude, hsys = "P" /* PLACIDUS */) { this.checkInitialized(); if (!this.swe_houses || !this.module) { throw new Error("Houses calculation function not available"); } if (latitude < -90 || latitude > 90) { throw new Error("Latitude must be between -90 and 90 degrees"); } if (longitude < -180 || longitude > 180) { throw new Error("Longitude must be between -180 and 180 degrees"); } const HOUSES_DOUBLES = 13; const ASCMC_DOUBLES = 10; const BYTES_PER_F64 = 8; const totalBytes = (HOUSES_DOUBLES + ASCMC_DOUBLES) * BYTES_PER_F64; const memoryPtr = this.module._malloc(totalBytes); if (!memoryPtr) throw new Error("Memory allocation failed"); const housesPtr = memoryPtr; const ascmcPtr = memoryPtr + HOUSES_DOUBLES * BYTES_PER_F64; try { const hsysCode = hsys.charCodeAt(0); const ret = this.swe_houses( julday, latitude, longitude, hsysCode, housesPtr, ascmcPtr ); if (ret < 0) { throw new Error(`Houses calculation failed with error code ${ret}`); } const houses = new Array(HOUSES_DOUBLES); for (let i = 0; i < HOUSES_DOUBLES; i++) { houses[i] = this.module.getValue( housesPtr + i * BYTES_PER_F64, "double" ); } const ascendant = this.module.getValue( ascmcPtr + 0 * BYTES_PER_F64, "double" ); const mc = this.module.getValue(ascmcPtr + 1 * BYTES_PER_F64, "double"); const armc = this.module.getValue(ascmcPtr + 2 * BYTES_PER_F64, "double"); const vertex = this.module.getValue( ascmcPtr + 3 * BYTES_PER_F64, "double" ); const equasc = this.module.getValue( ascmcPtr + 4 * BYTES_PER_F64, "double" ); const coasc1 = this.module.getValue( ascmcPtr + 5 * BYTES_PER_F64, "double" ); const coasc2 = this.module.getValue( ascmcPtr + 6 * BYTES_PER_F64, "double" ); const polasc = this.module.getValue( ascmcPtr + 7 * BYTES_PER_F64, "double" ); return { ascendant, mc, houses, ascmc: { armc, vertex, equasc, coasc1, coasc2, polasc } }; } finally { this.module._free(memoryPtr); } } /** * Clean up and close the Swiss Ephemeris */ close() { this.checkInitialized(); if (this.swe_close) { this.swe_close(); } } /** * Set topocentric observer */ setTopocentric(longitude, latitude, altitudeMeters = 0) { this.checkInitialized(); if (!this.swe_set_topo) { throw new Error("Topocentric calculation function not available"); } this.swe_set_topo(longitude, latitude, altitudeMeters); } /** * Set sidereal mode * Ex.: mode=1 (Lahiri). See Swiss Ephemeris mode table. */ setSiderealMode(mode, t0 = 0, ayan_t0 = 0) { this.checkInitialized(); this.swe_set_sid_mode?.(mode, t0, ayan_t0); } /** * Asteroid by MPC number */ calculateAsteroidPosition(julday, mpcNumber, flags = 2 /* SWISS_EPH */) { return this.calculatePlanetPosition( julday, SE_AST_OFFSET + mpcNumber, flags ); } /** * Lilith mean (12) and true (13) */ calculateLilith(julday, kind = "mean", flags = 2 /* SWISS_EPH */) { const id = kind === "mean" ? BODY.MEAN_APOGEE : BODY.OSC_APOGEE; return this.calculatePlanetPosition(julday, id, flags); } /** * Convert ecliptic (or equatorial) coordinates to horizon coordinates. * Returns azimuth (0=south, 90=west, 180=north, 270=east) and altitude. */ azalt(julday, longitude, latitude, altitude, xinLon, xinLat, xinDist, fromEquatorial = false) { this.checkInitialized(); if (!this.swe_azalt_fn) { throw new Error("swe_azalt function not available"); } const BYTES = 8; const geoPtr = this.module._malloc(3 * BYTES); const xinPtr = this.module._malloc(3 * BYTES); const xazPtr = this.module._malloc(3 * BYTES); if (!geoPtr || !xinPtr || !xazPtr) { if (geoPtr) this.module._free(geoPtr); if (xinPtr) this.module._free(xinPtr); if (xazPtr) this.module._free(xazPtr); throw new Error("Memory allocation failed for azalt"); } try { this.module.setValue(geoPtr, longitude, "double"); this.module.setValue(geoPtr + BYTES, latitude, "double"); this.module.setValue(geoPtr + 2 * BYTES, altitude, "double"); this.module.setValue(xinPtr, xinLon, "double"); this.module.setValue(xinPtr + BYTES, xinLat, "double"); this.module.setValue(xinPtr + 2 * BYTES, xinDist, "double"); this.swe_azalt_fn( julday, fromEquatorial ? SE_EQU2HOR : SE_ECL2HOR, geoPtr, 0, // atpress (0 = default 1013.25 mbar) 0, // attemp (0 = default 15°C) xinPtr, xazPtr ); return { azimuth: this.module.getValue(xazPtr, "double"), trueAltitude: this.module.getValue(xazPtr + BYTES, "double"), apparentAltitude: this.module.getValue(xazPtr + 2 * BYTES, "double") }; } finally { this.module._free(geoPtr); this.module._free(xinPtr); this.module._free(xazPtr); } } /** * Find the next rise, set, or meridian transit of a planet. * Returns the Julian day of the event. */ riseTransit(julday, planet, rsmi, longitude, latitude, altitude = 0, flags = 2 /* SWISS_EPH */) { this.checkInitialized(); if (!this.swe_rise_trans_fn) { throw new Error("swe_rise_trans function not available"); } const BYTES = 8; const geoPtr = this.module._malloc(3 * BYTES); const tretPtr = this.module._malloc(BYTES); const ERR_BYTES = 512; const errPtr = this.module._malloc(ERR_BYTES); if (!geoPtr || !tretPtr || !errPtr) { if (geoPtr) this.module._free(geoPtr); if (tretPtr) this.module._free(tretPtr); if (errPtr) this.module._free(errPtr); throw new Error("Memory allocation failed for riseTransit"); } this.module.HEAP8.fill(0, errPtr, errPtr + ERR_BYTES); try { this.module.setValue(geoPtr, longitude, "double"); this.module.setValue(geoPtr + BYTES, latitude, "double"); this.module.setValue(geoPtr + 2 * BYTES, altitude, "double"); const ret = this.swe_rise_trans_fn( julday, planet, 0, // starname pointer (0 = planet, not fixed star) flags, rsmi, geoPtr, 0, // atpress 0, // attemp tretPtr, errPtr ); if (ret < 0) { const msg = this.module.UTF8ToString(errPtr); throw new Error(msg || `swe_rise_trans failed with code ${ret}`); } return this.module.getValue(tretPtr, "double"); } finally { this.module._free(geoPtr); this.module._free(tretPtr); this.module._free(errPtr); } } }; function parsFortunae(asc, sunLon, moonLon, diurnal) { const val = diurnal ? asc + moonLon - sunLon : asc + sunLon - moonLon; return normalizeAngle(val); } // src/astrology/swisseph.ts var swissEph = null; var DEFAULT_FLAGS = 2 /* SWISS_EPH */ | 256 /* SPEED */; var REQUIRED_EPHE_FILES = ["seas_18.se1", "semo_18.se1", "sepl_18.se1"]; var NODE_EPHE_MOUNT_POINT = "/ephefs"; var NODE_EPHE_MEMFS_PATH = "/ephemem"; function emitRuntimeNotice(message) { if (typeof process !== "undefined" && process.stderr && typeof process.stderr.write === "function") { process.stderr.write(`${message} `); return; } console.info(message); } var SWISS_EPH_RUNTIME_WASM_ENV_KEYS = [ "KAABALAH_SWISSEPH_WASM_PATH", "KAABALAH_WASM_PATH" ]; var SWISS_EPH_RUNTIME_EPHE_ENV_KEYS = [ "KAABALAH_SWISSEPH_EPHE_PATH", "KAABALAH_EPHE_PATH" ]; function getRuntimeEnv(env) { if (env) { return env; } if (typeof process !== "undefined" && process.env) { return process.env; } return {}; } function firstDefinedEnvValue(env, keys) { for (const key of keys) { const value = env[key]; if (typeof value === "string" && value.length > 0) { return value; } } return void 0; } function getBundledNodeSwissEphAssets(options) { if (options.bundledNodeWasmPath && options.bundledNodeEphePath) { return { wasmPaths: [options.bundledNodeWasmPath], ephePaths: [options.bundledNodeEphePath] }; } const resolvePath = options.nodePathResolve ?? ((...paths) => chunk4337NVKS_js.__require("path").resolve(...paths)); return { wasmPaths: [ options.bundledNodeWasmPath, resolvePath(__dirname, swisseph_node_default), resolvePath(__dirname, "../../wasm/build/swisseph.node.wasm"), resolvePath(__dirname, "../wasm/build/swisseph.node.wasm") ].filter((value) => typeof value === "string"), ephePaths: [ options.bundledNodeEphePath, resolvePath(__dirname, "../../ephe"), resolvePath(__dirname, "../ephe") ].filter((value) => typeof value === "string") }; } function getBundledBrowserSwissEphAssets(options) { return { wasmPath: options.bundledBrowserWasmPath ?? swisseph_web_default, ephePath: options.bundledBrowserEphePath ?? "../ephe" }; } function formatCandidatePaths(paths) { return paths.length > 0 ? paths.join(", ") : "(none)"; } function resolveBundledRuntimeAssetPath(label, bundledPaths, existsSync) { for (const bundledPath of bundledPaths) { if (existsSync(bundledPath)) { return { path: bundledPath, source: "bundled" }; } } throw new Error( `Unable to resolve Swiss Ephemeris ${label}. Bundled paths checked: ${formatCandidatePaths( bundledPaths )}.` ); } function resolveRuntimeAssetPath(label, explicitPath, envPath, candidatePaths, bundledPaths, existsSync) { if (explicitPath) { if (!existsSync(explicitPath)) { throw new Error( `Swiss Ephemeris ${label} override does not exist: "${explicitPath}".` ); } return { path: explicitPath, source: "explicit" }; } if (envPath) { if (!existsSync(envPath)) { throw new Error( `Swiss Ephemeris ${label} from environment does not exist: "${envPath}".` ); } return { path: envPath, source: "env" }; } for (const candidatePath of candidatePaths) { if (existsSync(candidatePath)) { return { path: candidatePath, source: "candidate" }; } } try { return resolveBundledRuntimeAssetPath(label, bundledPaths, existsSync); } catch (error) { throw new Error( `Unable to resolve Swiss Ephemeris ${label}. Checked candidate paths: ${formatCandidatePaths( candidatePaths )}. ${toError(error).message}` ); } } function resolveSwissEphRuntimeAssetsInternal(options = {}) { const isBrowser = options.isBrowser ?? typeof window !== "undefined"; if (isBrowser) { const bundledAssets2 = getBundledBrowserSwissEphAssets(options); return { wasmPath: options.wasmPath ?? bundledAssets2.wasmPath, ephePath: options.ephePath ?? bundledAssets2.ephePath, wasmPathSource: options.wasmPath ? "explicit" : "bundled", ephePathSource: options.ephePath ? "explicit" : "bundled" }; } const env = getRuntimeEnv(options.env); const existsSync = options.existsSync ?? ((path) => chunk4337NVKS_js.__require("fs").existsSync(path)); const bundledAssets = getBundledNodeSwissEphAssets(options); const envWasmPath = firstDefinedEnvValue(env, SWISS_EPH_RUNTIME_WASM_ENV_KEYS); const envEphePath = firstDefinedEnvValue(env, SWISS_EPH_RUNTIME_EPHE_ENV_KEYS); const resolvedWasm = resolveRuntimeAssetPath( "wasmPath", options.wasmPath, envWasmPath, options.wasmPathCandidates ?? [], bundledAssets.wasmPaths, existsSync ); const resolvedEphe = resolveRuntimeAssetPath( "ephePath", options.ephePath, envEphePath, options.ephePathCandidates ?? [], bundledAssets.ephePaths, existsSync ); return { wasmPath: resolvedWasm.path, ephePath: resolvedEphe.path, wasmPathSource: resolvedWasm.source, ephePathSource: resolvedEphe.source }; } function resolveSwissEphRuntimeAssets(options = {}) { return resolveSwissEphRuntimeAssetsInternal(options); } function normalizeVirtualPath(path) { if (path === "/") { return path; } return path.replace(/\/+$/, "") || "/"; } function joinVirtualPath(rootPath, leaf) { const normalizedRoot = normalizeVirtualPath(rootPath); return normalizedRoot === "/" ? `/${leaf}` : `${normalizedRoot}/${leaf}`; } function ensureVirtualDir(fs, path) { try { fs.mkdir(path); } catch { } } function safeAnalyzePath(fs, path) { if (!fs.analyzePath) { return null; } try { return fs.analyzePath(path).exists === true; } catch { return false; } } function safeReaddir(fs, path) { if (!fs.readdir) { return []; } try { return fs.readdir(path).filter((entry) => entry !== "." && entry !== ".."); } catch { return []; } } function inspectVirtualEphemerisPath(fs, rootPath, requiredFiles = REQUIRED_EPHE_FILES) { if (!fs) { return { rootExists: null, visibleEntries: [], missingFiles: [...requiredFiles] }; } const rootExists = safeAnalyzePath(fs, rootPath); const visibleEntries = safeReaddir(fs, rootPath); const missingFiles = requiredFiles.filter((file) => { const filePath = joinVirtualPath(rootPath, file); return !visibleEntries.includes(file) && safeAnalyzePath(fs, filePath) !== true; }); return { rootExists, visibleEntries, missingFiles }; } function formatVirtualPathCheck(label, path, check) { if (!check) { return `${label} "${path}" could not be inspected.`; } const exists = check.rootExists == null ? "unknown" : check.rootExists ? "yes" : "no"; const visibleEntries = check.visibleEntries.length > 0 ? check.visibleEntries.join(", ") : "(none)"; const missingFiles = check.missingFiles.length > 0 ? check.missingFiles.join(", ") : "(none)"; return `${label} "${path}" exists: ${exists}; visible entries: ${visibleEntries}; missing required files: ${missingFiles}.`; } function normalizeHostFileData(data) { return data instanceof Uint8Array ? data : new Uint8Array(data); } function loadHostEphemerisFiles(ephePath, requiredFiles, nodeFs, pathModule) { const files = /* @__PURE__ */ new Map(); for (const file of requiredFiles) { files.set(file, normalizeHostFileData(nodeFs.readFileSync(pathModule.join(ephePath, file)))); } return files; } function writeEphemerisFilesToMemfs(fs, targetPath, files) { ensureVirtualDir(fs, targetPath); for (const [fileName, fileData] of files.entries()) { fs.writeFile(joinVirtualPath(targetPath, fileName), fileData); } } function toError(err) { return err instanceof Error ? err : new Error(String(err)); } function buildEphemerisResolutionError(finalEphePath, requiredFiles, details) { const parts = [ `Unable to resolve Swiss Ephemeris data files. Expected ${requiredFiles.join(", ")} under "${finalEphePath}".` ]; if (details.mountAttempted) { parts.push( `${formatVirtualPathCheck("Mounted ephemeris path", details.mountPoint, details.mountCheck)} The NODEFS mount may have failed silently.` ); } if (details.mountError) { parts.push(`Mounting the ephemeris directory failed: ${details.mountError.message}.`); } parts.push(formatVirtualPathCheck("Direct host ephemeris path", finalEphePath, details.hostCheck)); if (details.memfsCheck) { parts.push(formatVirtualPathCheck("MEMFS ephemeris copy", details.memfsPath, details.memfsCheck)); } if (details.hostReadError) { parts.push(`Reading host ephemeris files failed: ${details.hostReadError.message}.`); } parts.push( `Pass an explicit ephePath that contains ${requiredFiles.join(", ")} or ensure the packaged ephemeris directory is readable.` ); return parts.join(" "); } function resolveNodeEphemerisPath(module, finalEphePath, options = {}) { const fs = module.FS; const requiredFiles = options.requiredFiles ?? REQUIRED_EPHE_FILES; const mountPoint = options.mountPoint ?? NODE_EPHE_MOUNT_POINT; const memfsPath = options.memfsPath ?? NODE_EPHE_MEMFS_PATH; const nodeFs = options.nodeFs ?? chunk4337NVKS_js.__require("fs"); const pathModule = options.pathModule ?? chunk4337NVKS_js.__require("path"); let mountAttempted = false; let mountCheck = null; let mountError = null; let hostCheck = null; let memfsCheck = null; let hostReadError = null; if (fs?.mount && fs.filesystems?.NODEFS) { mountAttempted = true; ensureVirtualDir(fs, mountPoint); try { fs.mount(fs.filesystems.NODEFS, { root: finalEphePath }, mountPoint); mountCheck = inspectVirtualEphemerisPath(fs, mountPoint, requiredFiles); if (mountCheck.missingFiles.length === 0) { return { path: mountPoint, strategy: "nodefs-mount" }; } } catch (mountErr) { mountError = toError(mountErr); } } hostCheck = inspectVirtualEphemerisPath(fs, finalEphePath, requiredFiles); if (fs && hostCheck.missingFiles.length === 0) { return { path: finalEphePath, strategy: "host-path" }; } let hostFiles = null; try { hostFiles = loadHostEphemerisFiles(finalEphePath, requiredFiles, nodeFs, pathModule); } catch (err) { hostReadError = toError(err); } if (hostFiles && fs?.writeFile) { writeEphemerisFilesToMemfs(fs, memfsPath, hostFiles); memfsCheck = inspectVirtualEphemerisPath(fs, memfsPath, requiredFiles); if (memfsCheck.missingFiles.length === 0) { return { path: memfsPath, strategy: "memfs-copy" }; } } if (hostFiles) { return { path: finalEphePath, strategy: "host-path" }; } throw new Error( buildEphemerisResolutionError(finalEphePath, requiredFiles, { mountAttempted, mountPoint, mountCheck, mountError, hostCheck, memfsPath, memfsCheck, hostReadError }) ); } async function getSwissEph(options = {}) { if (swissEph) { return; } try { const isBrowser = typeof window !== "undefined"; const runtimeAssets = resolveSwissEphRuntimeAssets({ wasmPath: options.wasmPath, ephePath: options.ephePath }); const finalWasmPath = runtimeAssets.wasmPath; const moduleFactory = isBrowser ? (await import('./swisseph.web-GPTWPXKT.js')).default : (await import('./swisseph.node-NWM75JF3.js')).default; const module = await moduleFactory({ locateFile: () => finalWasmPath }); const instance = new SwissEph(module); const finalEphePath = runtimeAssets.ephePath; if (isBrowser) { const epheFsPath = "/ephe"; try { module.FS?.mkdir?.(epheFsPath); } catch { } const files = ["seas_18.se1", "semo_18.se1", "sepl_18.se1"]; await Promise.all( files.map(async (name) => { const url = `${finalEphePath}/${name}`; const res = await fetch(url); if (!res.ok) { throw new Error(`Failed to fetch ephemeris file: ${url}`); } const buf = await res.arrayBuffer(); module.FS?.writeFile?.( `${epheFsPath}/${name}`, new Uint8Array(buf) ); }) ); const browserCheck = inspectVirtualEphemerisPath(module.FS, epheFsPath, REQUIRED_EPHE_FILES); if (browserCheck.missingFiles.length > 0) { throw new Error( `Failed to materialize browser ephemeris files at "${epheFsPath}". Missing: ${browserCheck.missingFiles.join(", ")}.` ); } emitRuntimeNotice(`Setting ephemeris path to: ${epheFsPath}`); instance.setEphemerisPath(epheFsPath); } else { const resolution = resolveNodeEphemerisPath(module, finalEphePath); if (resolution.strategy === "nodefs-mount") { emitRuntimeNotice(`Setting ephemeris path to: ${resolution.path} (mounted from ${finalEphePath})`); } else if (resolution.strategy === "memfs-copy") { emitRuntimeNotice(`Setting ephemeris path to: ${resolution.path} (copied from ${finalEphePath})`); } else { emitRuntimeNotice(`Setting ephemeris path to: ${resolution.path}`); } instance.setEphemerisPath(resolution.path); } swissEph = instance; } catch (error) { console.error("Error initializing Swiss Ephemeris:", error); throw error; } } function calculateSinglePlanetPosition(date, planet) { checkInitialization(); const julday = swissEph.getJulianDay(date); return swissEph.calculatePlanetPosition(julday, planet, DEFAULT_FLAGS); } function calculateEquatorialPosition(date, planet) { checkInitialization(); const julday = swissEph.getJulianDay(date); const pos = swissEph.calculatePlanetPosition( julday, planet, 2 /* SWISS_EPH */ | 2048 /* EQUATORIAL */ ); return { rightAscension: pos.longitude, declination: pos.latitude, distance: pos.distance }; } function getJulianDay(date) { checkInitialization(); return swissEph.getJulianDay(date); } async function calculatePlanetaryPositions(date) { try { checkInitialization(); const julday = swissEph.getJulianDay(date); const flags = DEFAULT_FLAGS; const planets = { sun: 0 /* SUN */, moon: 1 /* MOON */, mercury: 2 /* MERCURY */, venus: 3 /* VENUS */, mars: 4 /* MARS */, jupiter: 5 /* JUPITER */, saturn: 6 /* SATURN */, uranus: 7 /* URANUS */, neptune: 8 /* NEPTUNE */, pluto: 9 /* PLUTO */, meanNode: 10 /* MEAN_NODE */, trueNode: 11 /* TRUE_NODE */, chiron: 15 /* CHIRON */, lilithMean: 12 /* LILITH_MEAN */, lilithTrue: 13 /* LILITH_TRUE */ }; const positions = {}; for (const id of Object.values(planets)) { try { positions[id] = swissEph.calculatePlanetPosition(julday, id, flags); } catch (error) { throw new Error( `Failed to calculate position for ${PLANET_AND_NODE_NAMES[id]}: ${error}` ); } } return positions; } catch (error) { console.error("Error calculating planetary positions:", error); throw error; } } async function calculateHouses(date, latitude, longitude, houseSystem, options = {}) { try { checkInitialization(); const dateForUt = options.treatAsUTC === true ? date instanceof Date ? date : createUtcDateFromParts(buildLocalParts(date)) : await localToUtcDate(date, latitude, longitude, options); const julday = swissEph.getJulianDay(dateForUt); return swissEph.calculateHouses( julday, latitude, longitude, houseSystem ); } catch (error) { console.error("Error calculating houses:", error); throw error; } } function calcParsFortunae(asc, sunLon, moonLon, isDiurnal) { return parsFortunae(asc, sunLon, moonLon, isDiurnal); } function closeSwissEph() { if (swissEph) { try { swissEph.close(); swissEph = null; } catch (error) { console.error("Error closing Swiss Ephemeris:", error); throw error; } } } function checkInitialization() { if (!swissEph) { throw new Error( "Swiss Ephemeris not initialized. Call getSwissEph() first." ); } } function buildLocalParts(date) { if (date instanceof Date) { return { year: date.getFullYear(), month: date.getMonth() + 1, day: date.getDate(), hour: date.getHours(), minute: date.getMinutes(), second: date.getSeconds() }; } return date; } function createUtcDateFromParts(parts) { const { year, month, day, hour = 0, minute = 0, second = 0 } = parts; return new Date(Date.UTC(year, month - 1, day, hour, minute, second)); } function getTimeZoneOffsetMs(instant, timeZone) { const dtf = new Intl.DateTimeFormat("en-US", { timeZone, year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit", hour12: false }); const parts = dtf.formatToParts(instant); const map = {}; for (const p of parts) { map[p.type] = p.value; } const asUTC = Date.UTC( Number(map.year), Number(map.month) - 1, Number(map.day), Number(map.hour), Number(map.minute), Number(map.second) ); return asUTC - instant.getTime(); } async function localToUtcDate(local, latitude, longitude, opts = {}) { if (opts.treatAsUTC === true) { return local instanceof Date ? local : createUtcDateFromParts(buildLocalParts(local)); } const parts = buildLocalParts(local); const auto = opts.autoTimeZone !== false; if (typeof opts.utcOffsetMinutes === "number" && Number.isFinite(opts.utcOffsetMinutes)) { const utcMs = Date.UTC( parts.year, parts.month - 1, parts.day, parts.hour ?? 0, parts.minute ?? 0, parts.second ?? 0 ); return new Date(utcMs - opts.utcOffsetMinutes * 6e4); } if (opts.timeZone) { const naiveUtc = createUtcDateFromParts(parts); const offsetMs = getTimeZoneOffsetMs(naiveUtc, opts.timeZone); return new Date(naiveUtc.getTime() - offsetMs); } if (opts.resolveTimeZone && typeof latitude === "number" && typeof longitude === "number") { const tz = opts.resolveTimeZone(latitude, longitude, parts); if (tz) { const naiveUtc = createUtcDateFromParts(parts); const offsetMs = getTimeZoneOffsetMs(naiveUtc, tz); return new Date(naiveUtc.getTime() - offsetMs); } } if (auto && typeof latitude === "number" && typeof longitude === "number") { const mod = await import('tz-lookup'); const lookup = mod.default ?? mod; const tz = lookup(latitude, longitude); if (tz) { const naiveUtc = createUtcDateFromParts(parts); const offsetMs = getTimeZoneOffsetMs(naiveUtc, tz); return new Date(naiveUtc.getTime() - offsetMs); } } throw new Error( "Time zone information is required. Provide 'utcOffsetMinutes', 'timeZone', 'resolveTimeZone', or enable autoTimeZone with latitude/longitude." ); } async function toUtcDate(local, latitude, longitude, options = {}) { return localToUtcDate(local, latitude, longitude, options); } // src/astrology/astrocartography.ts var ASTROCARTOGRAPHY_DEFAULT_PLANETS = [ 0 /* SUN */, 1 /* MOON */, 2 /* MERCURY */, 3 /* VENUS */, 4 /* MARS */, 5 /* JUPITER */, 6 /* SATURN */, 7 /* URANUS */, 8 /* NEPTUNE */, 9 /* PLUTO */, 15 /* CHIRON */, 11 /* TRUE_NODE */ ]; var DEG = Math.PI / 180; function computeGMST(julianDay) { return normalizeAngle( 280.46061837 + 360.98564736629 * (julianDay - 2451545) ); } function computeMCLongitude(gmst, ra) { return toGeoLon(normalizeAngle(gmst - ra)); } function computeICLongitude(gmst, ra) { return toGeoLon(normalizeAngle(gmst - ra + 180)); } function computeHorizonLongitude(gmst, ra, dec, latitude, angle) { const tanPhi = Math.tan(latitude * DEG); const tanDelta = Math.tan(dec * DEG); const cosH = -(tanPhi * tanDelta); if (Math.abs(cosH) > 1) return null; const H = Math.acos(cosH) / DEG; const lon = angle === "AC" ? normalizeAngle(gmst - ra - H) : normalizeAngle(gmst - ra + H); return toGeoLon(lon); } function geographicAngularDifference(a, b) { const d = normalizeAngle(a - b); return d > 180 ? 360 - d : d; } function toGeoLon(deg360) { const n = normalizeAngle(deg360); return n > 180 ? n - 360 : n; } function computeEquatorialPositions(date, planets = ASTROCARTOGRAPHY_DEFAULT_PLANETS) { const result = {}; for (const p of planets) { const name = PLANET_AND_NODE_NAMES[p]; const eq = calculateEquatorialPosition(date, p); result[name] = { ra: eq.rightAscension, dec: eq.declination, planetId: p }; } return result; } function findParansAtLatitude(equatorialPositions, gmst, latitude, paranOrb = 1) { const ANGLES = ["MC", "IC", "AC", "DC"]; const lines = []; for (const [name, eq] of Object.entries(equatorialPositions)) { for (const angle of ANGLES) { let lon; if (angle === "MC") lon = computeMCLongitude(gmst, eq.ra); else if (angle === "IC") lon = computeICLongitude(gmst, eq.ra); else lon = computeHorizonLongitude(gmst, eq.ra, eq.dec, latitude, angle); if (lon !== null) { lines.push({ planet: name, angle, longitude: lon }); } } } const parans = []; for (let i = 0; i < lines.length; i++) { for (let j = i + 1; j < lines.length; j++) { const a = lines[i]; const b = lines[j]; if (a.planet === b.planet) continue; if (a.angle === b.angle) continue; const dist = geographicAngularDifference(a.longitude, b.longitude); if (dist <= paranOrb) { parans.push({ latitude, planetA: a.planet, angleA: a.angle, longitudeA: a.longitude, planetB: b.planet, angleB: b.angle, longitudeB: b.longitude }); } } } return parans; } function queryAstrocartographyLocation(date, options) { const { latitude, longitude, orb = 2, planets = ASTROCARTOGRAPHY_DEFAULT_PLANETS, paranOrb = 1 } = options; const jd = getJulianDay(date); const gmst = computeGMST(jd); const positions = computeEquatorialPositions(date, planets); const lines = []; const ANGLES = ["MC", "IC", "AC", "DC"]; for (const [name, eq] of Object.entries(positions)) { for (const angle of ANGLES) { let lineLon; if (angle === "MC") lineLon = computeMCLongitude(gmst, eq.ra); else if (angle === "IC") lineLon = computeICLongitude(gmst, eq.ra); else lineLon = computeHorizonLongitude( gmst, eq.ra, eq.dec, latitude, angle ); if (lineLon === null) continue; const dist = geographicAngularDifference(longitude, lineLon); lines.push({ planet: name, angle, distance: Math.round(dist * 1e3) / 1e3, active: dist <= orb, longitude: Math.round(lineLon * 1e3) / 1e3 }); } } lines.sort((a, b) => a.distance - b.distance); const activeLines = lines.filter((l) => l.active); const parans = findParansAtLatitude(positions, gmst, latitude, paranOrb); return { queryLatitude: latitude, queryLongitude: longitude, orb, lines, activeLines, parans }; } function computeAstrocartographyMap(date, options = {}) { const { latitudeStep = 1, latitudeRange = 66.5, planets = ASTROCARTOGRAPHY_DEFAULT_PLANETS } = options; const jd = getJulianDay(date); const gmst = computeGMST(jd); const positions = computeEquatorialPositions(date, planets); const meridianLines = []; const horizonLines = []; for (const [name, eq] of Object.entries(positions)) { meridianLines.push({ planet: name, angle: "MC", longitude: Math.round(computeMCLongitude(gmst, eq.ra) * 1e3) / 1e3 }); meridianLines.push({ planet: name, angle: "IC", longitude: Math.round(computeICLongitude(gmst, eq.ra) * 1e3) / 1e3 }); for (const angle of ["AC", "DC"]) { const points = []; for (let lat = -latitudeRange; lat <= latitudeRange; lat += latitudeStep) { const lon = computeHorizonLongitude(gmst, eq.ra, eq.dec, lat, angle); if (lon !== null) { points.push({ latitude: Math.round(lat * 1e3) / 1e3, longitude: Math.round(lon * 1e3) / 1e3 }); } } horizonLines.push({ planet: name, angle, points }); } } return { meridianLines, horizonLines }; } // src/astrology/aspects.ts var DEFAULT_ASPECT_SPECS = [ { name: "conjunction", angle: 0, orb: 8 }, { name: "duodecile", angle: 30, orb: 2 }, { name: "octile", angle: 45, orb: 3 }, { name: "sextile", angle: 60, orb: 5 }, { name: "square", angle: 90, orb: 6 }, { name: "trine", angle: 120, orb: 7 }, { name: "trioctile", angle: 135, orb: 3 }, { name: "quincunx", angle: 150, orb: 3 }, { name: "opposition", angle: 180, orb: 8 } ]; function getAspectMatch(lonA, lonB, specs = DEFAULT_ASPECT_SPECS) { const a = normalizeAngle(lonA); const b = normalizeAngle(lonB); const delta = Math.min( normalizeAngle(b - a), normalizeAngle(a - b) ); for (const spec of specs) { const orb = Math.abs(delta - spec.angle); if (orb <= spec.orb) { return { spec, orb, delta }; } } return null; } function computeAspects(planets, specs = DEFAULT_ASPECT_SPECS) { const keys = Object.keys(planets); const edges = []; for (let i = 0; i < keys.length; i++) { for (let j = i + 1; j < keys.length; j++) { const a = planets[keys[i]]; const b = planets[keys[j]]; const match = getAspectMatch(a.longitude, b.longitude, specs); if (match) { edges.push({ planetA: keys[i], planetB: keys[j], longitudeA: a.longitude, longitudeB: b.longitude, aspect: match.spec.name, aspectAngle: match.spec.angle, delta: match.delta, orb: match.orb }); } } } return edges; } function computeSynastryAspects(planetsA, planetsB, specs = DEFAULT_ASPECT_SPECS) { const keysA = Object.keys(planetsA); const keysB = Object.keys(planetsB); const edges = []; for (const kA of keysA) { for (const kB of keysB) { const a = planetsA[kA]; const b = planetsB[kB]; const match = getAspectMatch(a.longitude, b.longitude, specs); if (match) { edges.push({ planetA: kA, planetB: kB, longitudeA: a.longitude, longitudeB: b.longitude, aspect: match.spec.name, aspectAngle: match.spec.angle, delta: match.delta, orb: match.orb }); } } } return edges; } function shorterArcMidpoint(a, b) { let diff = b - a; if (diff > 180) diff -= 360; if (diff < -180) diff += 360; return normalizeAngle(a + diff / 2); } function computeMidpoints(planetsA, planetsB) { const result = {}; for (const key of Object.keys(planetsA)) { if (!(key in planetsB)) continue; result[key] = shorterArcMidpoint(planetsA[key].longitude, planetsB[key].longitude); } return result; } var SLOW_PLANETS = /* @__PURE__ */ new Set([ "pluto", "neptune", "uranus", "saturn", "jupiter", "chiron", "mean node", "true node", "lilith true", "lilith mean" ]); function computeTransitAspects(transitPlanets, natalPlanets, specs = DEFAULT_ASPECT_SPECS) { const keysT = Object.keys(transitPlanets); const keysN = Object.keys(natalPlanets); const edges = []; for (const kT of keysT) { const t = transitPlanets[kT]; for (const kN of keysN) { const n = natalPlanets[kN]; const match = getAspectMatch(t.longitude, n.longitude, specs); if (!match) continue; const tSpeed = t.longitudeSpeed ?? 0; const nSpeed = n.longitudeSpeed ?? 0; const dt = 0.01; const tLonFuture = t.longitude + tSpeed * dt; const nLonFuture = n.longitude + nSpeed * dt; const futureMatch = getAspectMatch(tLonFuture, nLonFuture, [match.spec]); const applying = futureMatch != null ? futureMatch.orb < match.orb : false; edges.push({ planetA: kT, planetB: kN, longitudeA: t.longitude, longitudeB: n.longitude, aspect: match.spec.name, aspectAngle: match.spec.angle, delta: match.delta, orb: match.orb, applying, retrograde: tSpeed < 0, category: SLOW_PLANETS.has(kT) ? "slow" : "fast" }); } } return edges; } // src/astrology/dignity.ts var DOMICILE_RULERS = { Aries: "Mars", Taurus: "Venus", Gemini: "Mercury", Cancer: "Moon", Leo: "Sun", Virgo: "Mercury", Libra: "Venus", Scorpio: "Mars", Sagittarius: "Jupiter", Capricorn: "Saturn", Aquarius: "Saturn", Pisces: "Jupiter" }; var EXALTATIONS = { Sun: { sign: "Aries", degree: 19 }, Moon: { sign: "Taurus", degree: 3 }, Mercury: { sign: "Virgo", degree: 15 }, Venus: { sign: "Pisces", degree: 27 }, Mars: { sign: "Capricorn", degree: 28 }, Jupiter: { sign: "Cancer", degree: 15 }, Saturn: { sign: "Libra", degree: 21 } }; function getDomicileRuler(sign) { return DOMICILE_RULERS[sign]; } function getExaltation(planet) { return EXALTATIONS[planet]; } function getOppositeSign(sign) { const idx = SIGNS.indexOf(sign); return SIGNS[(idx + 6) % 12]; } function getDetriment(planet) { const signs = []; for (const [sign, ruler] of Object.entries(DOMICILE_RULERS)) { if (ruler === planet) { signs.push(getOppositeSign(sign)); } } return signs; } function getFall(planet) { return getOppositeSign(EXALTATIONS[planet].sign); } function getEssentialDignity(planet, sign) { const domicile = DOMICILE_RULERS[sign] === planet; const exaltation = EXALTATIONS[planet].sign === sign; const detrimentSigns = getDetriment(planet); const detriment = detrimentSigns.includes(sign); const fallSign = getFall(planet); const fall = fallSign === sign; const domicileRuler = DOMICILE_RULERS[sign]; const peregrine = !domicile && !exaltation && !detriment && !fall; return { domicile, exaltation, detriment, fall, domicileRuler, peregrine }; } // src/astrology/decans.ts var CHALDEAN_RULERS = [ "Mars", "Sun", "Venus", "Mercury", "Moon", "Saturn", "Jupiter" ]; var SIGN_SUITS = { Aries: "Wands", Taurus: "Pentacles", Gemini: "Swords", Cancer: "Cups", Leo: "Wands", Virgo: "Pentacles", Libra: "Swords", Scorpio: "Cups", Sagittarius: "Wands", Capricorn: "Pentacles", Aquarius: "Swords", Pisces: "Cups" }; var RANK_NAMES = ["Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"]; function getDecan(longitude) { const L = normalizeAngle(longitude); const signIndex = Math.floor(L / 30) % 12; const degreeWithinSign = L - signIndex * 30; const decanIndex = Math.min(Math.floor(degreeWithinSign / 10), 2); const globalDecanIndex = signIndex * 3 + decanIndex; const sign = SIGNS[signIndex]; const ruler = CHALDEAN_RULERS[globalDecanIndex % 7]; const suit = SIGN_SUITS[sign]; const rank = RANK_NAMES[globalDecanIndex % 9]; const tarotCard = `${rank} of ${suit}`; return { sign, decanNumber: decanIndex + 1, ruler, tarotCard, startDegree: signIndex * 30 + decanIndex * 10, endDegree: signIndex * 30 + (decanIndex + 1) * 10, degreeWithinSign }; } // src/astrology/dodecatemoria.ts function getDodecatemoria(longitude) { const L = normalizeAngle(longitude); const signIndex = Math.floor(L / 30) % 12; const degreeWithinSign = L - signIndex * 30; const index = Math.min(Math.floor(degreeWithinSign / 2.5), 11); const dodecatemoriaSignIndex = (signIndex + index) % 12; return { originalSign: SIGNS[signIndex], originalDegree: degreeWithinSign, dodecatemoriaSign: SIGNS[dodecatemoriaSignIndex], dodecatemoriaIndex: index }; } // src/astrology/profections.ts function getAnnualProfection(natalChart, birthDate, targetYear) { const year = targetYear ?? (/* @__PURE__ */ new Date()).getFullYear(); const birthYear = birthDate.getFullYear(); const age = year - birthYear; if (age < 0) { throw new Error(`Target year (${year}) is before birth year (${birthYear}).`); } const house = age % 12 + 1; const sign = natalChart.houses.houses[house - 1].sign; const ruler = getDomicileRuler(sign); return { age, house, sign, ruler, targetYear: year }; } function getMonthlyProfections(natalChart, birthDate, targetYear) { const annualProfection = getAnnualProfection(natalChart, birthDate, targetYear); const annualSignIndex = SIGNS.indexOf(annualProfection.sign); const bdMonth = birthDate.getMonth(); const bdDay = birthDate.getDate(); const year = annualProfection.targetYear; const months = []; for (let i = 0; i < 12; i++) { const monthDate = new Date(year, bdMonth + i, bdDay); if (monthDate.getDate() !== bdDay) { monthDate.setDate(0); } const signIndex = (annualSignIndex + i) % 12; const sign = SIGNS[signIndex]; months.push({ month: i + 1, startDate: monthDate, sign, ruler: getDomicileRuler(sign) }); } return { annualProfection, months }; } // src/astrology/firdaria.ts var DAY_SEQUENCE = [ { planet: "Sun", years: 10 }, { planet: "Venus", years: 8 }, { planet: "Mercury", years: 13 }, { planet: "Moon", years: 9 }, { planet: "Saturn", years: 11 }, { planet: "Jupiter", years: 12 }, { planet: "Mars", years: 7 }, { planet: "NorthNode", years: 3 }, { planet: "SouthNode", years: 2 } ]; var NIGHT_SEQUENCE = [ { planet: "Moon", years: 9 }, { planet: "Saturn", years: 11 }, { planet: "Jupiter", years: 12 }, { planet: "Mars", years: 7 }, { planet: "NorthNode", years: 3 }, { planet: "SouthNode", years: 2 }, { planet: "Sun", years: 10 }, { planet: "Venus", years: 8 }, { planet: "Mercury", years: 13 } ]; var CHALDEAN_ORDER = [ "Saturn", "Jupiter", "Mars", "Sun", "Venus", "Mercury", "Moon" ]; function addYears(date, years) { const ms = years * 365.25 * 24 * 60 * 60 * 1e3; return new Date(date.getTime() + ms); } function