kaabalah
Version:
The de-facto library for any esoteric calculations and tooling
1,591 lines (1,579 loc) • 74.8 kB
JavaScript
'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