@typescriptify/sweph 1.0.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.
Files changed (211) hide show
  1. package/README.md +422 -0
  2. package/ephe/semo_18.se1 +0 -0
  3. package/ephe/sepl_18.se1 +0 -0
  4. package/originalCode/.eslintrc.json +124 -0
  5. package/originalCode/.gitattributes +2 -0
  6. package/originalCode/.github/FUNDING.yml +5 -0
  7. package/originalCode/.github/workflows/test.yml +35 -0
  8. package/originalCode/LICENSE +840 -0
  9. package/originalCode/README.md +91 -0
  10. package/originalCode/binding.gyp +41 -0
  11. package/originalCode/constants.js +366 -0
  12. package/originalCode/docs.gif +0 -0
  13. package/originalCode/index.d.ts +5115 -0
  14. package/originalCode/index.js +7 -0
  15. package/originalCode/index.mjs +109 -0
  16. package/originalCode/package.json +55 -0
  17. package/originalCode/src/functions/azalt.cpp +39 -0
  18. package/originalCode/src/functions/azalt_rev.cpp +35 -0
  19. package/originalCode/src/functions/calc.cpp +29 -0
  20. package/originalCode/src/functions/calc_pctr.cpp +31 -0
  21. package/originalCode/src/functions/calc_ut.cpp +29 -0
  22. package/originalCode/src/functions/close.cpp +6 -0
  23. package/originalCode/src/functions/cotrans.cpp +26 -0
  24. package/originalCode/src/functions/cotrans_sp.cpp +26 -0
  25. package/originalCode/src/functions/cs2degstr.cpp +19 -0
  26. package/originalCode/src/functions/cs2lonlatstr.cpp +23 -0
  27. package/originalCode/src/functions/cs2timestr.cpp +23 -0
  28. package/originalCode/src/functions/csnorm.cpp +15 -0
  29. package/originalCode/src/functions/csroundsec.cpp +15 -0
  30. package/originalCode/src/functions/d2l.cpp +15 -0
  31. package/originalCode/src/functions/date_conversion.cpp +30 -0
  32. package/originalCode/src/functions/day_of_week.cpp +15 -0
  33. package/originalCode/src/functions/degnorm.cpp +15 -0
  34. package/originalCode/src/functions/deltat.cpp +15 -0
  35. package/originalCode/src/functions/deltat_ex.cpp +24 -0
  36. package/originalCode/src/functions/difcs2n.cpp +19 -0
  37. package/originalCode/src/functions/difcsn.cpp +19 -0
  38. package/originalCode/src/functions/difdeg2n.cpp +19 -0
  39. package/originalCode/src/functions/difdegn.cpp +19 -0
  40. package/originalCode/src/functions/fixstar.cpp +32 -0
  41. package/originalCode/src/functions/fixstar2.cpp +32 -0
  42. package/originalCode/src/functions/fixstar2_mag.cpp +28 -0
  43. package/originalCode/src/functions/fixstar2_ut.cpp +32 -0
  44. package/originalCode/src/functions/fixstar_mag.cpp +28 -0
  45. package/originalCode/src/functions/fixstar_ut.cpp +32 -0
  46. package/originalCode/src/functions/gauquelin_sector.cpp +44 -0
  47. package/originalCode/src/functions/get_ayanamsa.cpp +15 -0
  48. package/originalCode/src/functions/get_ayanamsa_ex.cpp +27 -0
  49. package/originalCode/src/functions/get_ayanamsa_ex_ut.cpp +27 -0
  50. package/originalCode/src/functions/get_ayanamsa_name.cpp +19 -0
  51. package/originalCode/src/functions/get_ayanamsa_ut.cpp +15 -0
  52. package/originalCode/src/functions/get_current_file_data.cpp +28 -0
  53. package/originalCode/src/functions/get_library_path.cpp +8 -0
  54. package/originalCode/src/functions/get_orbital_elements.cpp +29 -0
  55. package/originalCode/src/functions/get_planet_name.cpp +19 -0
  56. package/originalCode/src/functions/get_tid_acc.cpp +7 -0
  57. package/originalCode/src/functions/heliacal_pheno_ut.cpp +52 -0
  58. package/originalCode/src/functions/heliacal_ut.cpp +52 -0
  59. package/originalCode/src/functions/helio_cross.cpp +33 -0
  60. package/originalCode/src/functions/helio_cross_ut.cpp +33 -0
  61. package/originalCode/src/functions/house_name.cpp +20 -0
  62. package/originalCode/src/functions/house_pos.cpp +36 -0
  63. package/originalCode/src/functions/houses.cpp +35 -0
  64. package/originalCode/src/functions/houses_armc.cpp +38 -0
  65. package/originalCode/src/functions/houses_armc_ex2.cpp +47 -0
  66. package/originalCode/src/functions/houses_ex.cpp +37 -0
  67. package/originalCode/src/functions/houses_ex2.cpp +46 -0
  68. package/originalCode/src/functions/jdet_to_utc.cpp +38 -0
  69. package/originalCode/src/functions/jdut1_to_utc.cpp +38 -0
  70. package/originalCode/src/functions/julday.cpp +25 -0
  71. package/originalCode/src/functions/lat_to_lmt.cpp +27 -0
  72. package/originalCode/src/functions/lmt_to_lat.cpp +27 -0
  73. package/originalCode/src/functions/lun_eclipse_how.cpp +34 -0
  74. package/originalCode/src/functions/lun_eclipse_when.cpp +31 -0
  75. package/originalCode/src/functions/lun_eclipse_when_loc.cpp +39 -0
  76. package/originalCode/src/functions/lun_occult_when_glob.cpp +35 -0
  77. package/originalCode/src/functions/lun_occult_when_loc.cpp +43 -0
  78. package/originalCode/src/functions/lun_occult_where.cpp +34 -0
  79. package/originalCode/src/functions/mooncross.cpp +26 -0
  80. package/originalCode/src/functions/mooncross_node.cpp +30 -0
  81. package/originalCode/src/functions/mooncross_node_ut.cpp +30 -0
  82. package/originalCode/src/functions/mooncross_ut.cpp +26 -0
  83. package/originalCode/src/functions/nod_aps.cpp +42 -0
  84. package/originalCode/src/functions/nod_aps_ut.cpp +42 -0
  85. package/originalCode/src/functions/orbit_max_min_true_distance.cpp +37 -0
  86. package/originalCode/src/functions/pheno.cpp +29 -0
  87. package/originalCode/src/functions/pheno_ut.cpp +29 -0
  88. package/originalCode/src/functions/radnorm.cpp +15 -0
  89. package/originalCode/src/functions/refrac.cpp +23 -0
  90. package/originalCode/src/functions/refrac_extended.cpp +32 -0
  91. package/originalCode/src/functions/revjul.cpp +33 -0
  92. package/originalCode/src/functions/rise_trans.cpp +44 -0
  93. package/originalCode/src/functions/rise_trans_true_hor.cpp +46 -0
  94. package/originalCode/src/functions/set_delta_t_userdef.cpp +14 -0
  95. package/originalCode/src/functions/set_ephe_path.cpp +14 -0
  96. package/originalCode/src/functions/set_jpl_file.cpp +14 -0
  97. package/originalCode/src/functions/set_sid_mode.cpp +20 -0
  98. package/originalCode/src/functions/set_tid_acc.cpp +14 -0
  99. package/originalCode/src/functions/set_topo.cpp +20 -0
  100. package/originalCode/src/functions/sidtime.cpp +15 -0
  101. package/originalCode/src/functions/sidtime0.cpp +21 -0
  102. package/originalCode/src/functions/sol_eclipse_how.cpp +34 -0
  103. package/originalCode/src/functions/sol_eclipse_when_glob.cpp +31 -0
  104. package/originalCode/src/functions/sol_eclipse_when_loc.cpp +39 -0
  105. package/originalCode/src/functions/sol_eclipse_where.cpp +30 -0
  106. package/originalCode/src/functions/solcross.cpp +26 -0
  107. package/originalCode/src/functions/solcross_ut.cpp +26 -0
  108. package/originalCode/src/functions/split_deg.cpp +35 -0
  109. package/originalCode/src/functions/time_equ.cpp +25 -0
  110. package/originalCode/src/functions/utc_time_zone.cpp +48 -0
  111. package/originalCode/src/functions/utc_to_jd.cpp +37 -0
  112. package/originalCode/src/functions/version.cpp +8 -0
  113. package/originalCode/src/functions/vis_limit_mag.cpp +50 -0
  114. package/originalCode/src/sweph.cpp +150 -0
  115. package/originalCode/src/sweph.h +119 -0
  116. package/originalCode/swisseph/swecl.c +6428 -0
  117. package/originalCode/swisseph/swedate.c +588 -0
  118. package/originalCode/swisseph/swedate.h +81 -0
  119. package/originalCode/swisseph/swehel.c +3511 -0
  120. package/originalCode/swisseph/swehouse.c +3143 -0
  121. package/originalCode/swisseph/swehouse.h +98 -0
  122. package/originalCode/swisseph/swejpl.c +958 -0
  123. package/originalCode/swisseph/swejpl.h +103 -0
  124. package/originalCode/swisseph/swemmoon.c +1930 -0
  125. package/originalCode/swisseph/swemplan.c +967 -0
  126. package/originalCode/swisseph/swemptab.h +10640 -0
  127. package/originalCode/swisseph/swenut2000a.h +2819 -0
  128. package/originalCode/swisseph/sweodef.h +326 -0
  129. package/originalCode/swisseph/sweph.c +8614 -0
  130. package/originalCode/swisseph/sweph.h +849 -0
  131. package/originalCode/swisseph/swephexp.h +1020 -0
  132. package/originalCode/swisseph/swephlib.c +4634 -0
  133. package/originalCode/swisseph/swephlib.h +189 -0
  134. package/package.json +28 -0
  135. package/scripts/gen-swemptab.js +177 -0
  136. package/scripts/gen-swenut2000a.js +106 -0
  137. package/src/SwissEph/README.md +268 -0
  138. package/src/SwissEph/UseCases/Ayanamsa.md +363 -0
  139. package/src/SwissEph/UseCases/AzimuthAltitude.md +408 -0
  140. package/src/SwissEph/UseCases/CoordinateSystems.md +337 -0
  141. package/src/SwissEph/UseCases/DateAndTime.md +368 -0
  142. package/src/SwissEph/UseCases/DeltaT.md +258 -0
  143. package/src/SwissEph/UseCases/EphemerisFiles.md +338 -0
  144. package/src/SwissEph/UseCases/FixedStars.md +300 -0
  145. package/src/SwissEph/UseCases/GauquelinSectors.md +304 -0
  146. package/src/SwissEph/UseCases/HeliacalEvents.md +396 -0
  147. package/src/SwissEph/UseCases/HelioCrossings.md +325 -0
  148. package/src/SwissEph/UseCases/HousePosition.md +254 -0
  149. package/src/SwissEph/UseCases/HouseSystems.md +279 -0
  150. package/src/SwissEph/UseCases/LunarEclipse.md +326 -0
  151. package/src/SwissEph/UseCases/MeridianTransit.md +279 -0
  152. package/src/SwissEph/UseCases/MoonCrossings.md +373 -0
  153. package/src/SwissEph/UseCases/NodesAndApsides.md +307 -0
  154. package/src/SwissEph/UseCases/Occultation.md +352 -0
  155. package/src/SwissEph/UseCases/OrbitalElements.md +469 -0
  156. package/src/SwissEph/UseCases/Phenomena.md +328 -0
  157. package/src/SwissEph/UseCases/PlanetPositions.md +366 -0
  158. package/src/SwissEph/UseCases/Planetocentric.md +278 -0
  159. package/src/SwissEph/UseCases/Refraction.md +314 -0
  160. package/src/SwissEph/UseCases/RiseAndSet.md +433 -0
  161. package/src/SwissEph/UseCases/SiderealTime.md +302 -0
  162. package/src/SwissEph/UseCases/SolarEclipse.md +379 -0
  163. package/src/SwissEph/UseCases/SunCrossings.md +275 -0
  164. package/src/SwissEph/UseCases/TopocentricCorrection.md +335 -0
  165. package/src/SwissEph/errors.ts +10 -0
  166. package/src/SwissEph/index.ts +823 -0
  167. package/src/SwissEph/types.ts +291 -0
  168. package/src/constants.ts +762 -0
  169. package/src/file-reader.ts +147 -0
  170. package/src/index.ts +10 -0
  171. package/src/swecl.ts +4526 -0
  172. package/src/swedate.ts +376 -0
  173. package/src/swehel.ts +1939 -0
  174. package/src/swehouse.ts +2167 -0
  175. package/src/swejpl.ts +470 -0
  176. package/src/swemmoon.ts +1318 -0
  177. package/src/swemplan.ts +585 -0
  178. package/src/swemptab.ts +4448 -0
  179. package/src/swenut2000a.ts +2763 -0
  180. package/src/sweph.ts +3993 -0
  181. package/src/swephlib.ts +2720 -0
  182. package/src/types.ts +490 -0
  183. package/tests/c-style/ayanamsa.test.ts +63 -0
  184. package/tests/c-style/config.test.ts +96 -0
  185. package/tests/c-style/crossings.test.ts +81 -0
  186. package/tests/c-style/date-time.test.ts +114 -0
  187. package/tests/c-style/eclipses.test.ts +84 -0
  188. package/tests/c-style/fixed-stars.test.ts +66 -0
  189. package/tests/c-style/heliacal.test.ts +34 -0
  190. package/tests/c-style/houses.test.ts +135 -0
  191. package/tests/c-style/math-utils.test.ts +160 -0
  192. package/tests/c-style/orbital.test.ts +78 -0
  193. package/tests/c-style/phenomena.test.ts +42 -0
  194. package/tests/c-style/planetocentric.test.ts +26 -0
  195. package/tests/c-style/planets.test.ts +117 -0
  196. package/tests/c-style/rise-set.test.ts +71 -0
  197. package/tests/helpers.ts +21 -0
  198. package/tests/modern/ayanamsa.test.ts +47 -0
  199. package/tests/modern/calc.test.ts +113 -0
  200. package/tests/modern/config.test.ts +46 -0
  201. package/tests/modern/crossings.test.ts +45 -0
  202. package/tests/modern/eclipses.test.ts +81 -0
  203. package/tests/modern/errors.test.ts +71 -0
  204. package/tests/modern/heliacal.test.ts +30 -0
  205. package/tests/modern/houses.test.ts +87 -0
  206. package/tests/modern/orbital.test.ts +79 -0
  207. package/tests/modern/phenomena.test.ts +41 -0
  208. package/tests/modern/rise-set.test.ts +60 -0
  209. package/tests/modern/statics.test.ts +99 -0
  210. package/tests/modern/utilities.test.ts +70 -0
  211. package/tsconfig.json +20 -0
@@ -0,0 +1,81 @@
1
+ import { describe, it, before, after } from 'node:test';
2
+ import { strict as assert } from 'node:assert';
3
+ import { near, LONDON } from '../helpers';
4
+ import { SwissEph } from '../../src/SwissEph';
5
+ import { SE_MARS } from '../../src/constants';
6
+
7
+ describe('Eclipses (modern)', () => {
8
+ let swe: SwissEph;
9
+
10
+ before(() => { swe = new SwissEph(); });
11
+ after(() => { swe.close(); });
12
+
13
+ describe('Solar eclipse — 2024 Apr 8', () => {
14
+ const eclJd = SwissEph.julianDay(2024, 4, 1, 0);
15
+
16
+ it('should find the eclipse', () => {
17
+ const ecl = swe.solarEclipseGlobal(eclJd);
18
+ assert.ok(ecl.maximum > eclJd);
19
+ });
20
+
21
+ it('should occur on Apr 8', () => {
22
+ const ecl = swe.solarEclipseGlobal(eclJd);
23
+ const d = SwissEph.fromJulianDay(ecl.maximum);
24
+ assert.strictEqual(d.month, 4);
25
+ assert.strictEqual(d.day, 8);
26
+ });
27
+
28
+ it('central path should be near lon -104', () => {
29
+ const ecl = swe.solarEclipseGlobal(eclJd);
30
+ const where = swe.solarEclipseWhere(ecl.maximum);
31
+ near(where.geopos.longitude, -104, 20);
32
+ });
33
+
34
+ it('solarEclipseHow should return attributes', () => {
35
+ const ecl = swe.solarEclipseGlobal(eclJd);
36
+ const how = swe.solarEclipseHow(ecl.maximum, { longitude: -104, latitude: 25 });
37
+ assert.ok(typeof how.type === 'number');
38
+ assert.ok(typeof how.attributes.magnitude === 'number');
39
+ });
40
+
41
+ it('solarEclipseLocal should find eclipse', () => {
42
+ const ecl = swe.solarEclipseLocal(eclJd, { longitude: -104, latitude: 25 });
43
+ assert.ok(ecl.maximum > eclJd);
44
+ });
45
+ });
46
+
47
+ describe('Lunar eclipse — 2025 Mar 14', () => {
48
+ const lunJd = SwissEph.julianDay(2025, 3, 1, 0);
49
+
50
+ it('should find the eclipse', () => {
51
+ const lun = swe.lunarEclipseGlobal(lunJd);
52
+ assert.ok(lun.maximum > lunJd);
53
+ });
54
+
55
+ it('should occur on Mar 14', () => {
56
+ const lun = swe.lunarEclipseGlobal(lunJd);
57
+ const d = SwissEph.fromJulianDay(lun.maximum);
58
+ assert.strictEqual(d.month, 3);
59
+ assert.strictEqual(d.day, 14);
60
+ });
61
+
62
+ it('umbral magnitude should be ~1.176', () => {
63
+ const lun = swe.lunarEclipseGlobal(lunJd);
64
+ const how = swe.lunarEclipseHow(lun.maximum);
65
+ near(how.umbraMagnitude, 1.176, 0.05);
66
+ });
67
+
68
+ it('lunarEclipseLocal should return', () => {
69
+ const lun = swe.lunarEclipseLocal(lunJd, LONDON);
70
+ assert.ok(typeof lun.maximum === 'number');
71
+ });
72
+ });
73
+
74
+ describe('Occultation', () => {
75
+ it('should search for Mars occultation', () => {
76
+ const start = SwissEph.julianDay(2024, 1, 1, 0);
77
+ const r = swe.occultationGlobal(start, SE_MARS);
78
+ assert.ok(typeof r.type === 'number');
79
+ });
80
+ });
81
+ });
@@ -0,0 +1,71 @@
1
+ import { describe, it, before, after } from 'node:test';
2
+ import { strict as assert } from 'node:assert';
3
+ import { J2000 } from '../helpers';
4
+ import { SwissEph, SwissEphError } from '../../src/SwissEph';
5
+
6
+ describe('Error Handling (modern)', () => {
7
+ let swe: SwissEph;
8
+
9
+ before(() => { swe = new SwissEph(); });
10
+ after(() => { swe.close(); });
11
+
12
+ describe('SwissEphError', () => {
13
+ it('should be thrown for bad planet ID', () => {
14
+ assert.throws(
15
+ () => swe.calc(J2000, 999),
16
+ (err: any) => err.name === 'SwissEphError',
17
+ );
18
+ });
19
+
20
+ it('should be an instance of Error', () => {
21
+ try {
22
+ swe.calc(J2000, 999);
23
+ assert.fail('Should have thrown');
24
+ } catch (e: any) {
25
+ assert.ok(e instanceof SwissEphError);
26
+ assert.ok(e instanceof Error);
27
+ assert.strictEqual(e.name, 'SwissEphError');
28
+ }
29
+ });
30
+
31
+ it('should have a message', () => {
32
+ try {
33
+ swe.calc(J2000, 999);
34
+ assert.fail('Should have thrown');
35
+ } catch (e: any) {
36
+ assert.ok(e.message.length > 0);
37
+ }
38
+ });
39
+ });
40
+
41
+ describe('Invalid star name', () => {
42
+ it('should throw for nonexistent star', () => {
43
+ assert.throws(
44
+ () => swe.fixedStarMagnitude('ZZZNOTASTAR'),
45
+ (err: any) => err.name === 'SwissEphError',
46
+ );
47
+ });
48
+ });
49
+
50
+ describe('Constructor options', () => {
51
+ it('should create with default options', () => {
52
+ const s = new SwissEph();
53
+ assert.ok(s);
54
+ s.close();
55
+ });
56
+
57
+ it('should accept timeMode et', () => {
58
+ const s = new SwissEph({ timeMode: 'et' });
59
+ // ET calc should still work
60
+ const sun = s.calc(J2000, 0);
61
+ assert.ok(sun.longitude > 0);
62
+ s.close();
63
+ });
64
+
65
+ it('should accept topo option', () => {
66
+ const s = new SwissEph({ topo: { longitude: -0.1278, latitude: 51.5074 } });
67
+ assert.ok(s);
68
+ s.close();
69
+ });
70
+ });
71
+ });
@@ -0,0 +1,30 @@
1
+ import { describe, it, before, after } from 'node:test';
2
+ import { strict as assert } from 'node:assert';
3
+ import { J2000, LONDON } from '../helpers';
4
+ import { SwissEph } from '../../src/SwissEph';
5
+ import { SE_HELIACAL_RISING } from '../../src/constants';
6
+
7
+ describe('Heliacal (modern)', () => {
8
+ let swe: SwissEph;
9
+
10
+ before(() => {
11
+ swe = new SwissEph({ topo: LONDON });
12
+ });
13
+ after(() => { swe.close(); });
14
+
15
+ describe('heliacalEvent', () => {
16
+ it('Venus heliacal rising should return result', () => {
17
+ const r = swe.heliacalEvent(J2000, LONDON, 'Venus', SE_HELIACAL_RISING);
18
+ assert.ok(typeof r.startVisible === 'number');
19
+ assert.ok(typeof r.bestVisible === 'number');
20
+ assert.ok(typeof r.endVisible === 'number');
21
+ });
22
+ });
23
+
24
+ describe('visualLimitMagnitude', () => {
25
+ it('should return limiting magnitude for Venus', () => {
26
+ const r = swe.visualLimitMagnitude(J2000, LONDON, 'Venus');
27
+ assert.ok(typeof r.limitingMagnitude === 'number');
28
+ });
29
+ });
30
+ });
@@ -0,0 +1,87 @@
1
+ import { describe, it, before, after } from 'node:test';
2
+ import { strict as assert } from 'node:assert';
3
+ import { near, J2000, LONDON } from '../helpers';
4
+ import { SwissEph } from '../../src/SwissEph';
5
+ import { SE_SUN } from '../../src/constants';
6
+
7
+ describe('Houses (modern)', () => {
8
+ let swe: SwissEph;
9
+
10
+ before(() => { swe = new SwissEph(); });
11
+ after(() => { swe.close(); });
12
+
13
+ describe('houses (Placidus, London, J2000)', () => {
14
+ it('ascendant should be ~24.03', () => {
15
+ const h = swe.houses(J2000, LONDON, 'P');
16
+ near(h.ascendant, 24.03, 0.5);
17
+ });
18
+
19
+ it('MC should be ~279.50', () => {
20
+ const h = swe.houses(J2000, LONDON, 'P');
21
+ near(h.mc, 279.50, 0.5);
22
+ });
23
+
24
+ it('cusps should have 37 elements', () => {
25
+ const h = swe.houses(J2000, LONDON, 'P');
26
+ assert.strictEqual(h.cusps.length, 37);
27
+ });
28
+
29
+ it('cusp[1] should equal ascendant', () => {
30
+ const h = swe.houses(J2000, LONDON, 'P');
31
+ near(h.cusps[1], h.ascendant, 0.001);
32
+ });
33
+
34
+ it('should have vertex', () => {
35
+ const h = swe.houses(J2000, LONDON, 'P');
36
+ assert.ok(h.vertex >= 0 && h.vertex < 360);
37
+ });
38
+ });
39
+
40
+ describe('housesFromArmc', () => {
41
+ it('should match houses result', () => {
42
+ const h = swe.houses(J2000, LONDON, 'P');
43
+ const h2 = swe.housesFromArmc(h.armc, LONDON.latitude, 23.44, 'P');
44
+ near(h2.ascendant, h.ascendant, 0.5);
45
+ });
46
+ });
47
+
48
+ describe('housePosition', () => {
49
+ it('Sun should be in house ~10.05', () => {
50
+ const h = swe.houses(J2000, LONDON, 'P');
51
+ const sun = swe.calc(J2000, SE_SUN);
52
+ const pos = swe.housePosition(h.armc, LONDON.latitude, 23.44, 'P',
53
+ sun.longitude, sun.latitude);
54
+ near(pos, 10.05, 0.2);
55
+ });
56
+
57
+ it('should return value between 1 and 12', () => {
58
+ const h = swe.houses(J2000, LONDON, 'P');
59
+ const sun = swe.calc(J2000, SE_SUN);
60
+ const pos = swe.housePosition(h.armc, LONDON.latitude, 23.44, 'P',
61
+ sun.longitude, sun.latitude);
62
+ assert.ok(pos >= 1 && pos <= 13);
63
+ });
64
+ });
65
+
66
+ describe('houseName', () => {
67
+ it('should return name containing Placidus for P', () => {
68
+ assert.ok(swe.houseName('P').toLowerCase().includes('placidus'));
69
+ });
70
+
71
+ it('should return Koch for K', () => {
72
+ assert.ok(swe.houseName('K').toLowerCase().includes('koch'));
73
+ });
74
+ });
75
+
76
+ describe('All house systems', () => {
77
+ const systems = ['P', 'K', 'E', 'W', 'C', 'R', 'T', 'B', 'M', 'O'];
78
+
79
+ for (const sys of systems) {
80
+ it(`System ${sys} should produce valid result`, () => {
81
+ const h = swe.houses(J2000, LONDON, sys);
82
+ assert.ok(h.ascendant >= 0 && h.ascendant < 360);
83
+ assert.ok(h.mc >= 0 && h.mc < 360);
84
+ });
85
+ }
86
+ });
87
+ });
@@ -0,0 +1,79 @@
1
+ import { describe, it, before, after } from 'node:test';
2
+ import { strict as assert } from 'node:assert';
3
+ import { near, J2000 } from '../helpers';
4
+ import { SwissEph } from '../../src/SwissEph';
5
+ import { SE_MARS, SE_EARTH } from '../../src/constants';
6
+
7
+ describe('Orbital Elements (modern)', () => {
8
+ let swe: SwissEph;
9
+
10
+ before(() => { swe = new SwissEph(); });
11
+ after(() => { swe.close(); });
12
+
13
+ describe('nodesApsides', () => {
14
+ it('Mars ascending node should be valid', () => {
15
+ const r = swe.nodesApsides(J2000, SE_MARS);
16
+ assert.ok(r.ascendingNode.longitude > 0);
17
+ });
18
+
19
+ it('Mars perihelion should be valid', () => {
20
+ const r = swe.nodesApsides(J2000, SE_MARS);
21
+ assert.ok(r.perihelion.longitude > 0);
22
+ });
23
+
24
+ it('Mars descending node should differ from ascending', () => {
25
+ const r = swe.nodesApsides(J2000, SE_MARS);
26
+ assert.ok(Math.abs(r.ascendingNode.longitude - r.descendingNode.longitude) > 90);
27
+ });
28
+ });
29
+
30
+ describe('orbitalElements', () => {
31
+ it('Mars semi-axis should be ~1.5237 AU', () => {
32
+ const r = swe.orbitalElements(J2000, SE_MARS);
33
+ near(r.semiAxis, 1.5237, 0.01);
34
+ });
35
+
36
+ it('Mars eccentricity should be ~0.0933', () => {
37
+ const r = swe.orbitalElements(J2000, SE_MARS);
38
+ near(r.eccentricity, 0.0933, 0.01);
39
+ });
40
+
41
+ it('Mars inclination should be ~1.85 deg', () => {
42
+ const r = swe.orbitalElements(J2000, SE_MARS);
43
+ near(r.inclination, 1.85, 0.2);
44
+ });
45
+
46
+ it('Mars tropical period should be positive', () => {
47
+ const r = swe.orbitalElements(J2000, SE_MARS);
48
+ assert.ok(r.tropicalPeriod > 0, `period=${r.tropicalPeriod}`);
49
+ });
50
+
51
+ it('Earth semi-axis should be ~1.0 AU', () => {
52
+ const r = swe.orbitalElements(J2000, SE_EARTH);
53
+ near(r.semiAxis, 1.0, 0.01);
54
+ });
55
+
56
+ it('Earth eccentricity should be ~0.0167', () => {
57
+ const r = swe.orbitalElements(J2000, SE_EARTH);
58
+ near(r.eccentricity, 0.0167, 0.01);
59
+ });
60
+ });
61
+
62
+ describe('orbitDistances', () => {
63
+ it('Mars dmin should be ~0.37 AU', () => {
64
+ const r = swe.orbitDistances(J2000, SE_MARS);
65
+ near(r.min, 0.37, 0.1);
66
+ });
67
+
68
+ it('Mars dmax should be ~2.68 AU', () => {
69
+ const r = swe.orbitDistances(J2000, SE_MARS);
70
+ near(r.max, 2.68, 0.1);
71
+ });
72
+
73
+ it('dmin < dtrue < dmax', () => {
74
+ const r = swe.orbitDistances(J2000, SE_MARS);
75
+ assert.ok(r.min < r.true);
76
+ assert.ok(r.true < r.max);
77
+ });
78
+ });
79
+ });
@@ -0,0 +1,41 @@
1
+ import { describe, it, before, after } from 'node:test';
2
+ import { strict as assert } from 'node:assert';
3
+ import { J2000, LONDON } from '../helpers';
4
+ import { SwissEph } from '../../src/SwissEph';
5
+ import { SE_SUN, SE_MARS } from '../../src/constants';
6
+
7
+ describe('Phenomena (modern)', () => {
8
+ let swe: SwissEph;
9
+
10
+ before(() => { swe = new SwissEph(); });
11
+ after(() => { swe.close(); });
12
+
13
+ describe('phenomena', () => {
14
+ it('Mars should have phase angle', () => {
15
+ const r = swe.phenomena(J2000, SE_MARS);
16
+ assert.ok(r.phaseAngle >= 0 && r.phaseAngle < 180);
17
+ });
18
+
19
+ it('Mars should have elongation', () => {
20
+ const r = swe.phenomena(J2000, SE_MARS);
21
+ assert.ok(typeof r.elongation === 'number');
22
+ });
23
+
24
+ it('Mars should have apparent magnitude', () => {
25
+ const r = swe.phenomena(J2000, SE_MARS);
26
+ assert.ok(typeof r.apparentMagnitude === 'number');
27
+ });
28
+
29
+ it('Mars should have apparent diameter', () => {
30
+ const r = swe.phenomena(J2000, SE_MARS);
31
+ assert.ok(r.apparentDiameter > 0);
32
+ });
33
+ });
34
+
35
+ describe('gauquelinSector', () => {
36
+ it('Sun sector should be 1-36', () => {
37
+ const r = swe.gauquelinSector(J2000, SE_SUN, LONDON);
38
+ assert.ok(r.sector > 0 && r.sector <= 36, `sector=${r.sector}`);
39
+ });
40
+ });
41
+ });
@@ -0,0 +1,60 @@
1
+ import { describe, it, before, after } from 'node:test';
2
+ import { strict as assert } from 'node:assert';
3
+ import { J2000, LONDON } from '../helpers';
4
+ import { SwissEph } from '../../src/SwissEph';
5
+ import { SE_SUN } from '../../src/constants';
6
+
7
+ describe('Rise/Set/Transit (modern)', () => {
8
+ let swe: SwissEph;
9
+
10
+ before(() => { swe = new SwissEph(); });
11
+ after(() => { swe.close(); });
12
+
13
+ describe('rise', () => {
14
+ it('Sun rise should be after J2000', () => {
15
+ const r = swe.rise(J2000, SE_SUN, LONDON);
16
+ assert.ok(r.jd > J2000);
17
+ });
18
+ });
19
+
20
+ describe('set', () => {
21
+ it('Sun set should be after J2000', () => {
22
+ const r = swe.set(J2000, SE_SUN, LONDON);
23
+ assert.ok(r.jd > J2000);
24
+ });
25
+ });
26
+
27
+ describe('transit', () => {
28
+ it('Sun transit should return JD', () => {
29
+ const r = swe.transit(J2000, SE_SUN, LONDON);
30
+ assert.ok(r.jd > 0);
31
+ });
32
+ });
33
+
34
+ describe('antiTransit', () => {
35
+ it('Sun anti-transit should return JD', () => {
36
+ const r = swe.antiTransit(J2000, SE_SUN, LONDON);
37
+ assert.ok(r.jd > 0);
38
+ });
39
+ });
40
+
41
+ describe('azalt', () => {
42
+ it('should compute Sun azimuth and altitude', () => {
43
+ const sun = swe.calc(J2000, SE_SUN);
44
+ const az = swe.azalt(J2000, LONDON, sun.longitude, sun.latitude);
45
+ assert.ok(typeof az.azimuth === 'number');
46
+ assert.ok(typeof az.trueAltitude === 'number');
47
+ assert.ok(typeof az.apparentAltitude === 'number');
48
+ });
49
+ });
50
+
51
+ describe('azaltReverse', () => {
52
+ it('should reverse azalt', () => {
53
+ const sun = swe.calc(J2000, SE_SUN);
54
+ const az = swe.azalt(J2000, LONDON, sun.longitude, sun.latitude);
55
+ const rev = swe.azaltReverse(J2000, LONDON, az.azimuth, az.apparentAltitude);
56
+ assert.ok(typeof rev.azimuth === 'number');
57
+ assert.ok(typeof rev.altitude === 'number');
58
+ });
59
+ });
60
+ });
@@ -0,0 +1,99 @@
1
+ import { describe, it } from 'node:test';
2
+ import { strict as assert } from 'node:assert';
3
+ import { near, J2000 } from '../helpers';
4
+ import { SwissEph } from '../../src/SwissEph';
5
+ import { SE_GREG_CAL } from '../../src/constants';
6
+
7
+ describe('Static Methods (modern)', () => {
8
+ describe('julianDay', () => {
9
+ it('J2000 = 2451545.0', () => {
10
+ assert.strictEqual(SwissEph.julianDay(2000, 1, 1, 12), J2000);
11
+ });
12
+
13
+ it('should handle default hour = 0', () => {
14
+ const jd = SwissEph.julianDay(2000, 1, 1);
15
+ assert.strictEqual(jd, J2000 - 0.5);
16
+ });
17
+ });
18
+
19
+ describe('fromJulianDay', () => {
20
+ it('should round-trip J2000', () => {
21
+ const d = SwissEph.fromJulianDay(J2000);
22
+ assert.strictEqual(d.year, 2000);
23
+ assert.strictEqual(d.month, 1);
24
+ assert.strictEqual(d.day, 1);
25
+ assert.strictEqual(d.hour, 12);
26
+ });
27
+ });
28
+
29
+ describe('utcToJd', () => {
30
+ it('should produce JD near J2000', () => {
31
+ const r = SwissEph.utcToJd(2000, 1, 1, 12, 0, 0);
32
+ near(r.tjdUt, J2000, 0.001);
33
+ });
34
+
35
+ it('ET should be ahead of UT', () => {
36
+ const r = SwissEph.utcToJd(2000, 1, 1, 12, 0, 0);
37
+ assert.ok(r.tjdEt > r.tjdUt);
38
+ });
39
+ });
40
+
41
+ describe('jdToUtc', () => {
42
+ it('should convert ET JD to UTC components', () => {
43
+ const r = SwissEph.utcToJd(2000, 1, 1, 12, 0, 0);
44
+ const utc = SwissEph.jdToUtc(r.tjdEt);
45
+ assert.strictEqual(utc.year, 2000);
46
+ assert.strictEqual(utc.month, 1);
47
+ assert.strictEqual(utc.day, 1);
48
+ });
49
+ });
50
+
51
+ describe('jdUtToUtc', () => {
52
+ it('should convert UT JD to UTC components', () => {
53
+ const utc = SwissEph.jdUtToUtc(J2000);
54
+ assert.strictEqual(utc.year, 2000);
55
+ });
56
+ });
57
+
58
+ describe('dayOfWeek', () => {
59
+ it('J2000 should be Saturday (5)', () => {
60
+ assert.strictEqual(SwissEph.dayOfWeek(J2000), 5);
61
+ });
62
+ });
63
+
64
+ describe('normalizeDegrees', () => {
65
+ it('370 -> 10', () => {
66
+ assert.strictEqual(SwissEph.normalizeDegrees(370), 10);
67
+ });
68
+
69
+ it('-10 -> 350', () => {
70
+ assert.strictEqual(SwissEph.normalizeDegrees(-10), 350);
71
+ });
72
+ });
73
+
74
+ describe('normalizeRadians', () => {
75
+ it('should normalize 7 to 0-2pi', () => {
76
+ const r = SwissEph.normalizeRadians(7);
77
+ assert.ok(r >= 0 && r < 2 * Math.PI);
78
+ });
79
+ });
80
+
81
+ describe('degreeMidpoint', () => {
82
+ it('midpoint of 350,10 -> 0', () => {
83
+ near(SwissEph.degreeMidpoint(350, 10), 0, 0.01);
84
+ });
85
+ });
86
+
87
+ describe('coordinateTransform', () => {
88
+ it('should transform coordinates', () => {
89
+ const out = SwissEph.coordinateTransform([280.0, -0.5, 1.0], 23.44);
90
+ assert.ok(out[0] !== 0 || out[1] !== 0);
91
+ });
92
+ });
93
+
94
+ describe('version', () => {
95
+ it('should return non-empty string', () => {
96
+ assert.ok(SwissEph.version().length > 0);
97
+ });
98
+ });
99
+ });
@@ -0,0 +1,70 @@
1
+ import { describe, it, before, after } from 'node:test';
2
+ import { strict as assert } from 'node:assert';
3
+ import { near, J2000 } from '../helpers';
4
+ import { SwissEph } from '../../src/SwissEph';
5
+ import { SE_SUN, SE_MARS, SE_TRUE_TO_APP } from '../../src/constants';
6
+
7
+ describe('Utilities (modern)', () => {
8
+ let swe: SwissEph;
9
+
10
+ before(() => { swe = new SwissEph(); });
11
+ after(() => { swe.close(); });
12
+
13
+ describe('deltaT', () => {
14
+ it('should be positive at J2000', () => {
15
+ const dt = swe.deltaT(J2000);
16
+ assert.ok(dt > 0);
17
+ assert.ok(dt < 0.01);
18
+ });
19
+ });
20
+
21
+ describe('siderealTime', () => {
22
+ it('should return 0-24 hours at J2000', () => {
23
+ const st = swe.siderealTime(J2000);
24
+ assert.ok(st > 0 && st < 24, `st=${st}`);
25
+ });
26
+ });
27
+
28
+ describe('timeEquation', () => {
29
+ it('should return a number', () => {
30
+ const teq = swe.timeEquation(J2000);
31
+ assert.ok(typeof teq === 'number');
32
+ });
33
+ });
34
+
35
+ describe('refraction', () => {
36
+ it('true-to-apparent should return different value', () => {
37
+ const ref = swe.refraction(10, 1013.25, 15, SE_TRUE_TO_APP);
38
+ assert.ok(typeof ref === 'number');
39
+ assert.ok(ref !== 0);
40
+ });
41
+ });
42
+
43
+ describe('splitDegrees', () => {
44
+ it('should split 123.456 correctly', () => {
45
+ const r = swe.splitDegrees(123.456, 0);
46
+ assert.strictEqual(r.deg, 123);
47
+ assert.strictEqual(r.min, 27);
48
+ });
49
+ });
50
+
51
+ describe('difDeg2n', () => {
52
+ it('10,350 -> 20', () => {
53
+ near(swe.difDeg2n(10, 350), 20, 0.001);
54
+ });
55
+
56
+ it('350,10 -> -20', () => {
57
+ near(swe.difDeg2n(350, 10), -20, 0.001);
58
+ });
59
+ });
60
+
61
+ describe('getPlanetName', () => {
62
+ it('should return Sun for SE_SUN', () => {
63
+ assert.strictEqual(swe.getPlanetName(SE_SUN), 'Sun');
64
+ });
65
+
66
+ it('should return Mars for SE_MARS', () => {
67
+ assert.strictEqual(swe.getPlanetName(SE_MARS), 'Mars');
68
+ });
69
+ });
70
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "ES2020",
5
+ "moduleResolution": "node",
6
+ "strict": true,
7
+ "noEmit": true,
8
+ "esModuleInterop": true,
9
+ "skipLibCheck": true,
10
+ "forceConsistentCasingInFileNames": true,
11
+ "declaration": true,
12
+ "declarationMap": true,
13
+ "sourceMap": true,
14
+ "outDir": "./dist",
15
+ "rootDir": "./src",
16
+ "lib": ["ES2020", "DOM"]
17
+ },
18
+ "include": ["src/**/*.ts"],
19
+ "exclude": ["node_modules", "dist"]
20
+ }