thoth-cli 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,576 +0,0 @@
1
- // src/lib/core.ts
2
- import { execa } from "execa";
3
-
4
- // src/lib/binary.ts
5
- import { platform, arch } from "os";
6
- import { join, dirname } from "path";
7
- import { existsSync } from "fs";
8
- import { fileURLToPath } from "url";
9
- var __dirname = dirname(fileURLToPath(import.meta.url));
10
- function getPlatformKey() {
11
- const p = platform();
12
- const a = arch();
13
- const platformMap = {
14
- "darwin": "darwin",
15
- "linux": "linux",
16
- "win32": "win32"
17
- };
18
- const archMap = {
19
- "x64": "x64",
20
- "arm64": "arm64"
21
- };
22
- const mappedPlatform = platformMap[p];
23
- const mappedArch = archMap[a];
24
- if (!mappedPlatform || !mappedArch) {
25
- throw new Error(`Unsupported platform: ${p}-${a}`);
26
- }
27
- return `${mappedPlatform}-${mappedArch}`;
28
- }
29
- function getBinaryName() {
30
- const p = platform();
31
- return p === "win32" ? "thoth-core.exe" : "thoth-core";
32
- }
33
- function getBinaryPath() {
34
- const platformKey = getPlatformKey();
35
- const binaryName = getBinaryName();
36
- const possiblePaths = [
37
- // Installed via npm (production)
38
- join(__dirname, "..", "..", "bin", platformKey, binaryName),
39
- // Development (monorepo)
40
- join(__dirname, "..", "..", "..", "..", "bin", platformKey, binaryName),
41
- // Local development
42
- join(__dirname, "..", "..", "bin", binaryName)
43
- ];
44
- for (const p of possiblePaths) {
45
- if (existsSync(p)) {
46
- return p;
47
- }
48
- }
49
- return "python";
50
- }
51
- function getCommand() {
52
- const binaryPath = getBinaryPath();
53
- if (binaryPath === "python") {
54
- return {
55
- command: "python3",
56
- args: ["-m", "thoth_core.cli"]
57
- };
58
- }
59
- return {
60
- command: binaryPath,
61
- args: []
62
- };
63
- }
64
-
65
- // src/lib/core.ts
66
- async function execute(subcommand, args) {
67
- const { command, args: baseArgs } = getCommand();
68
- try {
69
- const result = await execa(command, [...baseArgs, subcommand, ...args], {
70
- encoding: "utf8",
71
- reject: false
72
- });
73
- if (result.exitCode !== 0) {
74
- const error = result.stderr || result.stdout;
75
- try {
76
- return JSON.parse(error);
77
- } catch {
78
- return { error: error || "Unknown error" };
79
- }
80
- }
81
- return JSON.parse(result.stdout);
82
- } catch (err) {
83
- return { error: err instanceof Error ? err.message : "Unknown error" };
84
- }
85
- }
86
- async function chart(options) {
87
- const args = [
88
- "--year",
89
- String(options.year),
90
- "--month",
91
- String(options.month),
92
- "--day",
93
- String(options.day),
94
- "--hour",
95
- String(options.hour ?? 12),
96
- "--minute",
97
- String(options.minute ?? 0),
98
- "--name",
99
- options.name ?? "Subject"
100
- ];
101
- if (options.city) {
102
- args.push("--city", options.city);
103
- args.push("--nation", options.nation ?? "US");
104
- } else if (options.lat !== void 0 && options.lng !== void 0) {
105
- args.push("--lat", String(options.lat));
106
- args.push("--lng", String(options.lng));
107
- }
108
- return execute("chart", args);
109
- }
110
- async function transit(options) {
111
- const args = [
112
- "--natal-year",
113
- String(options.natalYear),
114
- "--natal-month",
115
- String(options.natalMonth),
116
- "--natal-day",
117
- String(options.natalDay),
118
- "--natal-hour",
119
- String(options.natalHour ?? 12),
120
- "--natal-minute",
121
- String(options.natalMinute ?? 0),
122
- "--orb",
123
- String(options.orb ?? 3)
124
- ];
125
- if (options.natalCity) {
126
- args.push("--natal-city", options.natalCity);
127
- args.push("--nation", options.nation ?? "US");
128
- } else if (options.natalLat !== void 0 && options.natalLng !== void 0) {
129
- args.push("--natal-lat", String(options.natalLat));
130
- args.push("--natal-lng", String(options.natalLng));
131
- }
132
- if (options.transitYear) args.push("--transit-year", String(options.transitYear));
133
- if (options.transitMonth) args.push("--transit-month", String(options.transitMonth));
134
- if (options.transitDay) args.push("--transit-day", String(options.transitDay));
135
- return execute("transit", args);
136
- }
137
- async function moon(options = {}) {
138
- const args = [];
139
- if (options.year) args.push("--year", String(options.year));
140
- if (options.month) args.push("--month", String(options.month));
141
- if (options.day) args.push("--day", String(options.day));
142
- if (options.lat) args.push("--lat", String(options.lat));
143
- if (options.lng) args.push("--lng", String(options.lng));
144
- return execute("moon", args);
145
- }
146
- async function ephemeris(options) {
147
- const args = ["--body", options.body];
148
- if (options.year) args.push("--year", String(options.year));
149
- if (options.month) args.push("--month", String(options.month));
150
- if (options.day) args.push("--day", String(options.day));
151
- return execute("ephemeris", args);
152
- }
153
- async function version() {
154
- return execute("version", []);
155
- }
156
-
157
- // src/lib/format.ts
158
- import chalk from "chalk";
159
- var COLORS = {
160
- // Planets (Sephirotic correspondences)
161
- sun: chalk.hex("#FFD700"),
162
- // Gold - Tiphareth
163
- moon: chalk.hex("#C0C0C0"),
164
- // Silver - Yesod
165
- mercury: chalk.hex("#FF8C00"),
166
- // Orange - Hod
167
- venus: chalk.hex("#00FF7F"),
168
- // Green - Netzach
169
- mars: chalk.hex("#FF0000"),
170
- // Red - Geburah
171
- jupiter: chalk.hex("#4169E1"),
172
- // Royal Blue - Chesed
173
- saturn: chalk.hex("#4B0082"),
174
- // Indigo - Binah
175
- uranus: chalk.hex("#00FFFF"),
176
- // Electric Cyan - Chokmah
177
- neptune: chalk.hex("#20B2AA"),
178
- // Sea Green
179
- pluto: chalk.hex("#8B0000"),
180
- // Dark Red
181
- chiron: chalk.hex("#9932CC"),
182
- // Purple - wounded healer
183
- lilith: chalk.hex("#800020"),
184
- // Burgundy - primal
185
- northNode: chalk.hex("#FFD700"),
186
- // Gold
187
- southNode: chalk.hex("#C0C0C0")
188
- // Silver
189
- };
190
- function getPlanetColor(name) {
191
- const colorMap = {
192
- "sun": COLORS.sun,
193
- "moon": COLORS.moon,
194
- "mercury": COLORS.mercury,
195
- "venus": COLORS.venus,
196
- "mars": COLORS.mars,
197
- "jupiter": COLORS.jupiter,
198
- "saturn": COLORS.saturn,
199
- "uranus": COLORS.uranus,
200
- "neptune": COLORS.neptune,
201
- "pluto": COLORS.pluto,
202
- "chiron": COLORS.chiron,
203
- "mean_lilith": COLORS.lilith,
204
- "lilith": COLORS.lilith,
205
- "true_north_lunar_node": COLORS.northNode,
206
- "true_south_lunar_node": COLORS.southNode,
207
- "nn": COLORS.northNode,
208
- "sn": COLORS.southNode
209
- };
210
- return colorMap[name.toLowerCase()] || chalk.white;
211
- }
212
- function getZodiacColor(sign) {
213
- const colorMap = {
214
- "Ari": COLORS.mars,
215
- "Tau": COLORS.venus,
216
- "Gem": COLORS.mercury,
217
- "Can": COLORS.moon,
218
- "Leo": COLORS.sun,
219
- "Vir": COLORS.mercury,
220
- "Lib": COLORS.venus,
221
- "Sco": COLORS.pluto,
222
- "Sag": COLORS.jupiter,
223
- "Cap": COLORS.saturn,
224
- "Aqu": COLORS.uranus,
225
- "Pis": COLORS.neptune
226
- };
227
- return colorMap[sign] || chalk.white;
228
- }
229
- function getAspectColor(aspect) {
230
- const colorMap = {
231
- "conjunction": COLORS.sun,
232
- // Tiphareth
233
- "opposition": COLORS.moon,
234
- // Yesod
235
- "trine": COLORS.jupiter,
236
- // Chesed
237
- "square": COLORS.mars,
238
- // Geburah
239
- "sextile": COLORS.venus,
240
- // Netzach
241
- "quintile": COLORS.mercury,
242
- // Hod
243
- "quincunx": COLORS.uranus
244
- };
245
- return colorMap[aspect] || chalk.white;
246
- }
247
- var ZODIAC_SYMBOLS = {
248
- "Ari": "\u2648",
249
- "Tau": "\u2649",
250
- "Gem": "\u264A",
251
- "Can": "\u264B",
252
- "Leo": "\u264C",
253
- "Vir": "\u264D",
254
- "Lib": "\u264E",
255
- "Sco": "\u264F",
256
- "Sag": "\u2650",
257
- "Cap": "\u2651",
258
- "Aqu": "\u2652",
259
- "Pis": "\u2653"
260
- };
261
- var PLANET_SYMBOLS = {
262
- "sun": "\u2609",
263
- "moon": "\u263D",
264
- "mercury": "\u263F",
265
- "venus": "\u2640",
266
- "mars": "\u2642",
267
- "jupiter": "\u2643",
268
- "saturn": "\u2644",
269
- "uranus": "\u2645",
270
- "neptune": "\u2646",
271
- "pluto": "\u2647",
272
- "chiron": "\u26B7",
273
- "north_node": "\u260A",
274
- "south_node": "\u260B",
275
- "true_north_lunar_node": "\u260A",
276
- "true_south_lunar_node": "\u260B",
277
- "mean_lilith": "\u26B8",
278
- "medium_coeli": "MC",
279
- "imum_coeli": "IC",
280
- "ascendant": "ASC",
281
- "descendant": "DSC",
282
- // Short names from transit aspects
283
- "nn": "\u260A",
284
- "sn": "\u260B",
285
- "lilith": "\u26B8",
286
- "mc": "MC",
287
- "ic": "IC",
288
- "asc": "ASC",
289
- "dsc": "DSC"
290
- };
291
- var ASPECT_SYMBOLS = {
292
- "conjunction": "\u260C",
293
- "opposition": "\u260D",
294
- "trine": "\u25B3",
295
- "square": "\u25A1",
296
- "sextile": "\u26B9",
297
- "quintile": "\u235F",
298
- "quincunx": "\u26BB",
299
- "semi-sextile": "\u26BA",
300
- "semi-square": "\u2220",
301
- "sesquiquadrate": "\u26BC"
302
- };
303
- function getZodiacSymbol(sign) {
304
- const key = sign.slice(0, 3);
305
- return ZODIAC_SYMBOLS[key] || sign;
306
- }
307
- function getPlanetSymbol(planet) {
308
- return PLANET_SYMBOLS[planet.toLowerCase()] || planet;
309
- }
310
- function getAspectSymbol(aspect) {
311
- return ASPECT_SYMBOLS[aspect.toLowerCase()] || aspect;
312
- }
313
- function formatDegrees(degrees) {
314
- const d = Math.floor(degrees);
315
- const m = Math.floor((degrees - d) * 60);
316
- return `${d}\xB0${m.toString().padStart(2, "0")}'`;
317
- }
318
- function formatChart(result) {
319
- const lines = [];
320
- lines.push(chalk.bold.white(`
321
- \u{1315D} Natal Chart: ${result.name}`));
322
- const dateStr = `${result.datetime.year}-${String(result.datetime.month).padStart(2, "0")}-${String(result.datetime.day).padStart(2, "0")} ${String(result.datetime.hour).padStart(2, "0")}:${String(result.datetime.minute).padStart(2, "0")}`;
323
- lines.push(chalk.dim(` ${dateStr}`));
324
- if (result.location.city) {
325
- lines.push(chalk.dim(` ${result.location.city}`));
326
- } else {
327
- lines.push(chalk.dim(` Lat: ${result.location.lat}, Lng: ${result.location.lng}`));
328
- }
329
- if (result.lunar_phase) {
330
- lines.push(chalk.dim(` Born during: ${result.lunar_phase.emoji} ${result.lunar_phase.name}`));
331
- }
332
- lines.push("");
333
- lines.push(chalk.bold.cyan("\u2500\u2500 ANGLES \u2500\u2500"));
334
- if (result.ascendant.sign) {
335
- const zColor = getZodiacColor(result.ascendant.sign);
336
- lines.push(` ${COLORS.mars("ASC")} ${zColor(getZodiacSymbol(result.ascendant.sign) + " " + result.ascendant.sign)} ${chalk.white(formatDegrees(result.ascendant.position || 0))}`);
337
- }
338
- if (result.midheaven.sign) {
339
- const zColor = getZodiacColor(result.midheaven.sign);
340
- lines.push(` ${COLORS.sun("MC")} ${zColor(getZodiacSymbol(result.midheaven.sign) + " " + result.midheaven.sign)} ${chalk.white(formatDegrees(result.midheaven.position || 0))}`);
341
- }
342
- lines.push("");
343
- lines.push(chalk.bold.cyan("\u2500\u2500 PLANETS \u2500\u2500"));
344
- const planetOrder = ["sun", "moon", "mercury", "venus", "mars", "jupiter", "saturn", "uranus", "neptune", "pluto"];
345
- for (const name of planetOrder) {
346
- const planet = result.planets[name];
347
- if (planet) {
348
- const pColor = getPlanetColor(name);
349
- const zColor = getZodiacColor(planet.sign);
350
- const symbol = getPlanetSymbol(name);
351
- const zodiac = getZodiacSymbol(planet.sign);
352
- const deg = formatDegrees(planet.position);
353
- const rx = planet.retrograde ? COLORS.mars(" \u211E") : "";
354
- const house = planet.house ? chalk.dim(` (${planet.house})`) : "";
355
- lines.push(` ${pColor(symbol)} ${name.padEnd(10)} ${zColor(zodiac + " " + planet.sign)} ${chalk.white(deg)}${rx}${house}`);
356
- }
357
- }
358
- lines.push("");
359
- lines.push(chalk.bold.cyan("\u2500\u2500 POINTS \u2500\u2500"));
360
- const pointOrder = ["chiron", "mean_lilith", "true_north_lunar_node", "true_south_lunar_node"];
361
- const pointNames = {
362
- "chiron": "Chiron",
363
- "mean_lilith": "Lilith",
364
- "true_north_lunar_node": "North Node",
365
- "true_south_lunar_node": "South Node"
366
- };
367
- for (const name of pointOrder) {
368
- const planet = result.planets[name];
369
- if (planet) {
370
- const pColor = getPlanetColor(name);
371
- const zColor = getZodiacColor(planet.sign);
372
- const symbol = getPlanetSymbol(name);
373
- const displayName = pointNames[name] || name;
374
- const zodiac = getZodiacSymbol(planet.sign);
375
- const deg = formatDegrees(planet.position);
376
- const house = planet.house ? chalk.dim(` (${planet.house})`) : "";
377
- lines.push(` ${pColor(symbol)} ${displayName.padEnd(10)} ${zColor(zodiac + " " + planet.sign)} ${chalk.white(deg)}${house}`);
378
- }
379
- }
380
- lines.push("");
381
- if (result.houses && Object.keys(result.houses).length > 0) {
382
- lines.push(chalk.bold.cyan("\u2500\u2500 HOUSES \u2500\u2500"));
383
- for (let i = 1; i <= 12; i++) {
384
- const house = result.houses[String(i)];
385
- if (house && house.sign) {
386
- const zodiac = getZodiacSymbol(house.sign);
387
- const deg = formatDegrees(house.position || 0);
388
- const label = i === 1 ? "(ASC)" : i === 4 ? "(IC)" : i === 7 ? "(DSC)" : i === 10 ? "(MC)" : "";
389
- lines.push(` ${String(i).padStart(2)} ${chalk.cyan(zodiac)} ${house.sign} ${chalk.dim(deg)} ${chalk.yellow(label)}`);
390
- }
391
- }
392
- lines.push("");
393
- }
394
- if (result.elements && result.modes) {
395
- lines.push(chalk.bold.cyan("\u2500\u2500 BALANCE \u2500\u2500"));
396
- const elem = result.elements;
397
- const mode = result.modes;
398
- lines.push(` ${COLORS.mars("\u{1F702} Fire:")} ${elem.Fire} ${COLORS.venus("\u{1F703} Earth:")} ${elem.Earth} ${COLORS.mercury("\u{1F701} Air:")} ${elem.Air} ${COLORS.moon("\u{1F704} Water:")} ${elem.Water}`);
399
- lines.push(` ${COLORS.mars("Cardinal:")} ${mode.Cardinal} ${COLORS.sun("Fixed:")} ${mode.Fixed} ${COLORS.mercury("Mutable:")} ${mode.Mutable}`);
400
- lines.push("");
401
- }
402
- if (result.aspects && result.aspects.length > 0) {
403
- lines.push(chalk.bold.cyan("\u2500\u2500 ASPECTS \u2500\u2500"));
404
- const aspects = result.aspects.slice(0, 15);
405
- for (const asp of aspects) {
406
- const p1Name = asp.planet1.toLowerCase().replace(/ /g, "_");
407
- const p2Name = asp.planet2.toLowerCase().replace(/ /g, "_");
408
- const p1Color = getPlanetColor(p1Name);
409
- const p2Color = getPlanetColor(p2Name);
410
- const p1 = getPlanetSymbol(p1Name);
411
- const p2 = getPlanetSymbol(p2Name);
412
- const aspectSym = getAspectSymbol(asp.aspect);
413
- const aspectName = asp.aspect.charAt(0).toUpperCase() + asp.aspect.slice(1);
414
- const aColor = getAspectColor(asp.aspect);
415
- lines.push(` ${p1Color(p1)} ${asp.planet1.padEnd(10)} ${aColor(aspectSym + " " + aspectName.padEnd(11))} ${p2Color(p2)} ${asp.planet2.padEnd(10)} ${chalk.dim(`${asp.orb}\xB0`)}`);
416
- }
417
- lines.push("");
418
- }
419
- return lines.join("\n");
420
- }
421
- function formatTransits(result) {
422
- const lines = [];
423
- lines.push(chalk.bold.white(`
424
- \u{1315D} Transits`));
425
- if (result.natal.name) {
426
- lines.push(chalk.dim(` For: ${result.natal.name}`));
427
- }
428
- if (result.natal.city) {
429
- lines.push(chalk.dim(` Natal: ${result.natal.datetime} \xB7 ${result.natal.city}`));
430
- } else {
431
- lines.push(chalk.dim(` Natal: ${result.natal.datetime}`));
432
- }
433
- lines.push(chalk.dim(` Transit: ${result.transit.datetime}`));
434
- if (result.transit.lunar_phase) {
435
- lines.push(chalk.dim(` Moon: ${result.transit.lunar_phase.emoji} ${result.transit.lunar_phase.name}`));
436
- }
437
- lines.push("");
438
- if (result.transit.planets) {
439
- lines.push(chalk.bold.cyan("\u2500\u2500 CURRENT SKY \u2500\u2500"));
440
- const planets = result.transit.planets;
441
- for (const name of ["sun", "moon", "mercury", "venus", "mars", "jupiter", "saturn", "uranus", "neptune", "pluto"]) {
442
- const planet = planets[name];
443
- if (planet) {
444
- const pColor = getPlanetColor(name);
445
- const zColor = getZodiacColor(planet.sign);
446
- const symbol = getPlanetSymbol(name);
447
- const zodiac = getZodiacSymbol(planet.sign);
448
- const deg = formatDegrees(planet.position);
449
- const rx = planet.retrograde ? COLORS.mars("\u211E") : " ";
450
- const cH = planet.house ? planet.house.replace(/ house/i, "").replace(/first/i, "1").replace(/second/i, "2").replace(/third/i, "3").replace(/fourth/i, "4").replace(/fifth/i, "5").replace(/sixth/i, "6").replace(/seventh/i, "7").replace(/eighth/i, "8").replace(/ninth/i, "9").replace(/tenth/i, "10").replace(/eleventh/i, "11").replace(/twelfth/i, "12") : "?";
451
- lines.push(` ${pColor(symbol)} ${zColor(zodiac + " " + planet.sign)} ${chalk.white(deg)} ${rx} ${chalk.dim(`${cH}H`)}`);
452
- }
453
- }
454
- lines.push("");
455
- }
456
- const transitHouses = result.transit.houses;
457
- const natalHouses = result.natal_houses;
458
- if (transitHouses && natalHouses && Object.keys(transitHouses).length > 0) {
459
- lines.push(chalk.bold.cyan("\u2500\u2500 HOUSES \u2500\u2500"));
460
- lines.push(chalk.dim(" TRANSIT NATAL"));
461
- for (let i = 1; i <= 12; i++) {
462
- const tH = transitHouses[String(i)];
463
- const nH = natalHouses[String(i)];
464
- if (tH && nH) {
465
- const label = i === 1 ? "ASC" : i === 4 ? "IC" : i === 7 ? "DSC" : i === 10 ? "MC" : `${i}`.padStart(2) + "H";
466
- const tZColor = getZodiacColor(tH.sign);
467
- const nZColor = getZodiacColor(nH.sign);
468
- const tZodiac = getZodiacSymbol(tH.sign);
469
- const nZodiac = getZodiacSymbol(nH.sign);
470
- const tDeg = formatDegrees(tH.position);
471
- const nDeg = formatDegrees(nH.position);
472
- lines.push(` ${chalk.white(label.padStart(3))} ${tZColor(tZodiac + " " + tH.sign)} ${chalk.dim(tDeg)} ${nZColor(nZodiac + " " + nH.sign)} ${chalk.dim(nDeg)}`);
473
- }
474
- }
475
- lines.push("");
476
- }
477
- lines.push(chalk.bold.cyan("\u2500\u2500 TRANSITS TO NATAL \u2500\u2500"));
478
- if (result.aspects.length === 0) {
479
- lines.push(chalk.dim(" No aspects within orb"));
480
- } else {
481
- const shortName = (name) => {
482
- const map = {
483
- "sun": "SUN",
484
- "moon": "MOO",
485
- "mercury": "MER",
486
- "venus": "VEN",
487
- "mars": "MAR",
488
- "jupiter": "JUP",
489
- "saturn": "SAT",
490
- "uranus": "URA",
491
- "neptune": "NEP",
492
- "pluto": "PLU",
493
- "chiron": "CHI",
494
- "nn": "NN",
495
- "sn": "SN",
496
- "lilith": "LIL",
497
- "mc": "MC",
498
- "ic": "IC",
499
- "asc": "ASC",
500
- "dsc": "DSC"
501
- };
502
- return map[name.toLowerCase()] || name.slice(0, 3).toUpperCase();
503
- };
504
- for (const aspect of result.aspects) {
505
- const tPlanet = aspect.transit_planet.toLowerCase().replace(/ /g, "_");
506
- const nPlanet = aspect.natal_planet.toLowerCase().replace(/ /g, "_");
507
- const tColor = getPlanetColor(tPlanet);
508
- const nColor = getPlanetColor(nPlanet);
509
- const tSym = getPlanetSymbol(tPlanet);
510
- const nSym = getPlanetSymbol(nPlanet);
511
- const tName = shortName(aspect.transit_planet);
512
- const nName = shortName(aspect.natal_planet);
513
- const aSym = getAspectSymbol(aspect.aspect);
514
- const aColor = getAspectColor(aspect.aspect);
515
- const aspectShort = aspect.aspect === "conjunction" ? "CNJ" : aspect.aspect === "opposition" ? "OPP" : aspect.aspect === "trine" ? "TRI" : aspect.aspect === "square" ? "SQR" : aspect.aspect === "sextile" ? "SXT" : aspect.aspect === "quintile" ? "QNT" : aspect.aspect === "quincunx" ? "QCX" : String(aspect.aspect).slice(0, 3).toUpperCase();
516
- const tH = aspect.transit_house;
517
- const nH = aspect.natal_house;
518
- const houses = `${tH || "?"}H\u2192${nH || "?"}H`;
519
- const orb = aspect.orb.toFixed(2).padStart(5);
520
- lines.push(` ${tColor(tSym)} ${tName.padEnd(3)} ${aColor(aSym + " " + aspectShort)} ${nColor(nSym)} ${nName.padEnd(3)} ${chalk.dim(orb + "\xB0")} ${chalk.dim(houses)}`);
521
- }
522
- }
523
- lines.push("");
524
- return lines.join("\n");
525
- }
526
- function formatMoon(result) {
527
- const lines = [];
528
- const moonEmoji = result.phase.illumination > 50 ? "\u{1F315}" : "\u{1F311}";
529
- const zColor = getZodiacColor(result.moon.sign);
530
- lines.push(chalk.bold.white(`
531
- ${moonEmoji} Moon Phase`));
532
- lines.push(chalk.dim(` ${result.datetime}`));
533
- lines.push("");
534
- lines.push(` ${COLORS.moon("\u263D")} ${chalk.white("Moon in")} ${zColor(result.moon.sign)} ${chalk.white(formatDegrees(result.moon.position))}`);
535
- lines.push(` ${chalk.white("Phase:")} ${COLORS.moon(result.phase.name)}`);
536
- lines.push(` ${chalk.white("Illumination:")} ${COLORS.moon(result.phase.illumination.toFixed(1) + "%")}`);
537
- lines.push("");
538
- return lines.join("\n");
539
- }
540
- function formatEphemeris(result) {
541
- const lines = [];
542
- const pColor = getPlanetColor(result.body);
543
- const zColor = getZodiacColor(result.sign);
544
- const symbol = getPlanetSymbol(result.body);
545
- const rx = result.retrograde ? COLORS.mars(" \u211E") : "";
546
- lines.push(chalk.bold.white(`
547
- \u{1315D} Ephemeris: ${result.body}`));
548
- lines.push(chalk.dim(` ${result.datetime}`));
549
- lines.push("");
550
- lines.push(` ${pColor(symbol)} ${chalk.white(result.body)} in ${zColor(result.sign)} ${chalk.white(formatDegrees(result.position))}${rx}`);
551
- lines.push(` ${chalk.dim(`Absolute: ${result.abs_position.toFixed(4)}\xB0`)}`);
552
- lines.push("");
553
- return lines.join("\n");
554
- }
555
-
556
- // src/types.ts
557
- function isError(result) {
558
- return "error" in result;
559
- }
560
-
561
- export {
562
- chart,
563
- transit,
564
- moon,
565
- ephemeris,
566
- version,
567
- getZodiacSymbol,
568
- getPlanetSymbol,
569
- getAspectSymbol,
570
- formatDegrees,
571
- formatChart,
572
- formatTransits,
573
- formatMoon,
574
- formatEphemeris,
575
- isError
576
- };