@astro-api/n8n-nodes-astrology 0.2.0 → 0.3.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.
package/README.md CHANGED
@@ -25,8 +25,14 @@ Official n8n community node for [Astrology API](https://astrology-api.io) — pr
25
25
 
26
26
  ### Charts & Visualization
27
27
  - **Natal Charts** — Birth chart generation with SVG output
28
- - **Transit Charts** — Current planetary transits overlay
29
- - **Synastry** — Relationship compatibility analysis
28
+ - **Transit Charts** — Current planetary transits overlay on natal chart
29
+ - **Synastry Charts** — Relationship compatibility analysis (cross-aspects)
30
+ - **Composite Charts** — Merged midpoint chart for couples
31
+ - **Solar Return Charts** — Birthday year forecast
32
+ - **Lunar Return Charts** — Monthly forecast based on Moon return
33
+ - **Progressions Charts** — Secondary progressions for life phases
34
+ - **Natal Transits** — Transit analysis over date range
35
+ - **Directions Charts** — Primary directions for timing predictions
30
36
  - **Multiple House Systems** — Placidus, Koch, Equal, Whole Sign, and 20+ more
31
37
 
32
38
  ## Installation
@@ -89,6 +95,14 @@ For Docker deployments, mount the package or use `N8N_CUSTOM_EXTENSIONS`.
89
95
  | Personal forecast | Horoscope | Personal Daily/Weekly/Monthly/Yearly | Birth chart-based personalized predictions |
90
96
  | Chinese astrology | Horoscope | Chinese Bazi | Four Pillars of Destiny analysis |
91
97
  | Birth chart | Charts | Natal | SVG natal chart with configurable house system |
98
+ | Relationship chart | Charts | Synastry | Two-person compatibility analysis (cross-aspects) |
99
+ | Combined chart | Charts | Composite | Merged midpoint chart for couples |
100
+ | Current transits | Charts | Transit | Planetary transits overlay on natal chart |
101
+ | Birthday forecast | Charts | Solar Return | Year-ahead predictions based on Sun return |
102
+ | Monthly forecast | Charts | Lunar Return | Month-ahead predictions based on Moon return |
103
+ | Life phases | Charts | Progressions | Secondary progressions for internal development |
104
+ | Period analysis | Charts | Natal Transits | Transit events over a date range |
105
+ | Timing predictions | Charts | Directions | Primary directions for life event timing |
92
106
 
93
107
  ### Common Use Cases
94
108
 
@@ -30,7 +30,7 @@ class Astrology {
30
30
  version: 1,
31
31
  usableAsTool: true,
32
32
  subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
33
- description: "Professional astrological calculations: planetary positions, house cusps, aspects, lunar metrics, horoscopes, and natal charts using Astrology API",
33
+ description: "Perform astrological calculations via Astrology API",
34
34
  defaults: {
35
35
  name: "Astrology",
36
36
  },
@@ -2,6 +2,20 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.handleChartsResource = handleChartsResource;
4
4
  const shared_1 = require("../shared");
5
+ /**
6
+ * Endpoint mapping for chart operations
7
+ */
8
+ const CHARTS_ENDPOINTS = {
9
+ natal: "/api/v3/charts/natal",
10
+ synastry: "/api/v3/charts/synastry",
11
+ transit: "/api/v3/charts/transit",
12
+ composite: "/api/v3/charts/composite",
13
+ solarReturn: "/api/v3/charts/solar-return",
14
+ lunarReturn: "/api/v3/charts/lunar-return",
15
+ progressions: "/api/v3/charts/progressions",
16
+ natalTransits: "/api/v3/charts/natal-transits",
17
+ directions: "/api/v3/charts/directions",
18
+ };
5
19
  /**
6
20
  * Active points presets mapping
7
21
  */
@@ -119,10 +133,28 @@ const ACTIVE_POINTS_PRESETS = {
119
133
  */
120
134
  async function handleChartsResource(context, operation) {
121
135
  const op = operation;
122
- if (op === "natal") {
123
- return await handleNatalChart(context);
136
+ switch (op) {
137
+ case "natal":
138
+ return handleNatalChart(context);
139
+ case "synastry":
140
+ return handleSynastryChart(context);
141
+ case "transit":
142
+ return handleTransitChart(context);
143
+ case "composite":
144
+ return handleCompositeChart(context);
145
+ case "solarReturn":
146
+ return handleSolarReturnChart(context);
147
+ case "lunarReturn":
148
+ return handleLunarReturnChart(context);
149
+ case "progressions":
150
+ return handleProgressionsChart(context);
151
+ case "natalTransits":
152
+ return handleNatalTransits(context);
153
+ case "directions":
154
+ return handleDirectionsChart(context);
155
+ default:
156
+ throw new Error(`The operation '${operation}' is not supported for the charts resource`);
124
157
  }
125
- throw new Error(`The operation '${operation}' is not supported for the charts resource`);
126
158
  }
127
159
  /**
128
160
  * Handles natal chart generation
@@ -199,3 +231,298 @@ async function handleNatalChart(context) {
199
231
  const simplify = executeFunctions.getNodeParameter("simplify", itemIndex, true);
200
232
  return simplify ? (0, shared_1.simplifyResponse)(responseData) : responseData;
201
233
  }
234
+ /**
235
+ * Builds second subject birth data from subject2* prefixed fields
236
+ */
237
+ function buildSecondSubjectBirthData(executeFunctions, itemIndex) {
238
+ const locationType = executeFunctions.getNodeParameter("subject2LocationType", itemIndex);
239
+ const birthData = {
240
+ year: executeFunctions.getNodeParameter("subject2Year", itemIndex),
241
+ month: executeFunctions.getNodeParameter("subject2Month", itemIndex),
242
+ day: executeFunctions.getNodeParameter("subject2Day", itemIndex),
243
+ hour: executeFunctions.getNodeParameter("subject2Hour", itemIndex),
244
+ minute: executeFunctions.getNodeParameter("subject2Minute", itemIndex),
245
+ };
246
+ if (locationType === "city") {
247
+ birthData.city = executeFunctions.getNodeParameter("subject2City", itemIndex);
248
+ birthData.country_code = executeFunctions.getNodeParameter("subject2CountryCode", itemIndex);
249
+ }
250
+ else {
251
+ birthData.latitude = executeFunctions.getNodeParameter("subject2Latitude", itemIndex);
252
+ birthData.longitude = executeFunctions.getNodeParameter("subject2Longitude", itemIndex);
253
+ }
254
+ return birthData;
255
+ }
256
+ /**
257
+ * Builds transit time object from transit* prefixed fields
258
+ */
259
+ function buildTransitTime(executeFunctions, itemIndex) {
260
+ const locationType = executeFunctions.getNodeParameter("transitLocationType", itemIndex);
261
+ const transitTime = {
262
+ year: executeFunctions.getNodeParameter("transitYear", itemIndex),
263
+ month: executeFunctions.getNodeParameter("transitMonth", itemIndex),
264
+ day: executeFunctions.getNodeParameter("transitDay", itemIndex),
265
+ hour: executeFunctions.getNodeParameter("transitHour", itemIndex),
266
+ minute: executeFunctions.getNodeParameter("transitMinute", itemIndex),
267
+ };
268
+ if (locationType === "city") {
269
+ transitTime.city = executeFunctions.getNodeParameter("transitCity", itemIndex);
270
+ transitTime.country_code = executeFunctions.getNodeParameter("transitCountryCode", itemIndex);
271
+ }
272
+ else {
273
+ transitTime.latitude = executeFunctions.getNodeParameter("transitLatitude", itemIndex);
274
+ transitTime.longitude = executeFunctions.getNodeParameter("transitLongitude", itemIndex);
275
+ }
276
+ return transitTime;
277
+ }
278
+ /**
279
+ * Gets common chart options
280
+ */
281
+ function getChartOptions(executeFunctions, itemIndex) {
282
+ const houseSystem = executeFunctions.getNodeParameter("houseSystem", itemIndex);
283
+ const zodiacType = executeFunctions.getNodeParameter("zodiacType", itemIndex);
284
+ const perspective = executeFunctions.getNodeParameter("perspective", itemIndex);
285
+ const precision = executeFunctions.getNodeParameter("precision", itemIndex);
286
+ const activePointsPreset = executeFunctions.getNodeParameter("activePointsPreset", itemIndex);
287
+ let activePoints;
288
+ if (activePointsPreset === "custom") {
289
+ activePoints = executeFunctions.getNodeParameter("customActivePoints", itemIndex);
290
+ }
291
+ else {
292
+ activePoints =
293
+ ACTIVE_POINTS_PRESETS[activePointsPreset] || ACTIVE_POINTS_PRESETS.modern;
294
+ }
295
+ return {
296
+ house_system: houseSystem,
297
+ zodiac_type: zodiacType,
298
+ active_points: activePoints,
299
+ precision,
300
+ perspective,
301
+ };
302
+ }
303
+ /**
304
+ * Handles synastry chart generation (two-person relationship chart)
305
+ */
306
+ async function handleSynastryChart(context) {
307
+ const { executeFunctions, itemIndex, baseUrl, apiKey } = context;
308
+ // Build subject 1
309
+ const birthData1 = (0, shared_1.buildBirthData)(executeFunctions, itemIndex);
310
+ const subjectName1 = executeFunctions.getNodeParameter("subjectName", itemIndex, "");
311
+ // Build subject 2
312
+ const birthData2 = buildSecondSubjectBirthData(executeFunctions, itemIndex);
313
+ const subjectName2 = executeFunctions.getNodeParameter("subject2Name", itemIndex, "");
314
+ // Get options
315
+ const options = getChartOptions(executeFunctions, itemIndex);
316
+ // Build request body
317
+ const body = {
318
+ subject1: {
319
+ birth_data: birthData1,
320
+ ...(subjectName1 && { name: subjectName1 }),
321
+ },
322
+ subject2: {
323
+ birth_data: birthData2,
324
+ ...(subjectName2 && { name: subjectName2 }),
325
+ },
326
+ options,
327
+ };
328
+ const responseData = await (0, shared_1.makeApiRequest)(executeFunctions, "POST", baseUrl, CHARTS_ENDPOINTS.synastry, apiKey, body);
329
+ const simplify = executeFunctions.getNodeParameter("simplify", itemIndex, true);
330
+ return simplify ? (0, shared_1.simplifyResponse)(responseData) : responseData;
331
+ }
332
+ /**
333
+ * Handles transit chart generation (transits overlay on natal)
334
+ */
335
+ async function handleTransitChart(context) {
336
+ const { executeFunctions, itemIndex, baseUrl, apiKey } = context;
337
+ // Build natal subject
338
+ const birthData = (0, shared_1.buildBirthData)(executeFunctions, itemIndex);
339
+ const subjectName = executeFunctions.getNodeParameter("subjectName", itemIndex, "");
340
+ // Build transit time
341
+ const transitTime = buildTransitTime(executeFunctions, itemIndex);
342
+ // Get options
343
+ const options = getChartOptions(executeFunctions, itemIndex);
344
+ // Build request body
345
+ const body = {
346
+ subject: {
347
+ birth_data: birthData,
348
+ ...(subjectName && { name: subjectName }),
349
+ },
350
+ transit_time: {
351
+ datetime: transitTime,
352
+ },
353
+ options,
354
+ };
355
+ const responseData = await (0, shared_1.makeApiRequest)(executeFunctions, "POST", baseUrl, CHARTS_ENDPOINTS.transit, apiKey, body);
356
+ const simplify = executeFunctions.getNodeParameter("simplify", itemIndex, true);
357
+ return simplify ? (0, shared_1.simplifyResponse)(responseData) : responseData;
358
+ }
359
+ /**
360
+ * Handles composite chart generation (merged relationship chart)
361
+ */
362
+ async function handleCompositeChart(context) {
363
+ const { executeFunctions, itemIndex, baseUrl, apiKey } = context;
364
+ // Build subject 1
365
+ const birthData1 = (0, shared_1.buildBirthData)(executeFunctions, itemIndex);
366
+ const subjectName1 = executeFunctions.getNodeParameter("subjectName", itemIndex, "");
367
+ // Build subject 2
368
+ const birthData2 = buildSecondSubjectBirthData(executeFunctions, itemIndex);
369
+ const subjectName2 = executeFunctions.getNodeParameter("subject2Name", itemIndex, "");
370
+ // Get options
371
+ const options = getChartOptions(executeFunctions, itemIndex);
372
+ // Build request body
373
+ const body = {
374
+ subject1: {
375
+ birth_data: birthData1,
376
+ ...(subjectName1 && { name: subjectName1 }),
377
+ },
378
+ subject2: {
379
+ birth_data: birthData2,
380
+ ...(subjectName2 && { name: subjectName2 }),
381
+ },
382
+ options,
383
+ };
384
+ const responseData = await (0, shared_1.makeApiRequest)(executeFunctions, "POST", baseUrl, CHARTS_ENDPOINTS.composite, apiKey, body);
385
+ const simplify = executeFunctions.getNodeParameter("simplify", itemIndex, true);
386
+ return simplify ? (0, shared_1.simplifyResponse)(responseData) : responseData;
387
+ }
388
+ /**
389
+ * Handles solar return chart generation (birthday year forecast)
390
+ */
391
+ async function handleSolarReturnChart(context) {
392
+ const { executeFunctions, itemIndex, baseUrl, apiKey } = context;
393
+ // Build natal subject
394
+ const birthData = (0, shared_1.buildBirthData)(executeFunctions, itemIndex);
395
+ const subjectName = executeFunctions.getNodeParameter("subjectName", itemIndex, "");
396
+ // Get return year
397
+ const returnYear = executeFunctions.getNodeParameter("returnYear", itemIndex);
398
+ // Get options
399
+ const options = getChartOptions(executeFunctions, itemIndex);
400
+ // Build request body
401
+ const body = {
402
+ subject: {
403
+ birth_data: birthData,
404
+ ...(subjectName && { name: subjectName }),
405
+ },
406
+ return_year: returnYear,
407
+ options,
408
+ };
409
+ // Handle relocated return location
410
+ const useRelocatedReturn = executeFunctions.getNodeParameter("useRelocatedReturn", itemIndex, false);
411
+ if (useRelocatedReturn) {
412
+ const returnLocationType = executeFunctions.getNodeParameter("returnLocationType", itemIndex);
413
+ const returnLocation = {};
414
+ if (returnLocationType === "city") {
415
+ returnLocation.city = executeFunctions.getNodeParameter("returnCity", itemIndex);
416
+ returnLocation.country_code = executeFunctions.getNodeParameter("returnCountryCode", itemIndex);
417
+ }
418
+ else {
419
+ returnLocation.latitude = executeFunctions.getNodeParameter("returnLatitude", itemIndex);
420
+ returnLocation.longitude = executeFunctions.getNodeParameter("returnLongitude", itemIndex);
421
+ }
422
+ body.return_location = returnLocation;
423
+ }
424
+ const responseData = await (0, shared_1.makeApiRequest)(executeFunctions, "POST", baseUrl, CHARTS_ENDPOINTS.solarReturn, apiKey, body);
425
+ const simplify = executeFunctions.getNodeParameter("simplify", itemIndex, true);
426
+ return simplify ? (0, shared_1.simplifyResponse)(responseData) : responseData;
427
+ }
428
+ /**
429
+ * Handles lunar return chart generation (monthly forecast)
430
+ */
431
+ async function handleLunarReturnChart(context) {
432
+ const { executeFunctions, itemIndex, baseUrl, apiKey } = context;
433
+ // Build natal subject
434
+ const birthData = (0, shared_1.buildBirthData)(executeFunctions, itemIndex);
435
+ const subjectName = executeFunctions.getNodeParameter("subjectName", itemIndex, "");
436
+ // Get return date (optional)
437
+ const lunarReturnDate = executeFunctions.getNodeParameter("lunarReturnDate", itemIndex, "");
438
+ // Get options
439
+ const options = getChartOptions(executeFunctions, itemIndex);
440
+ // Build request body
441
+ const body = {
442
+ subject: {
443
+ birth_data: birthData,
444
+ ...(subjectName && { name: subjectName }),
445
+ },
446
+ options,
447
+ };
448
+ if (lunarReturnDate) {
449
+ body.return_date = lunarReturnDate;
450
+ }
451
+ const responseData = await (0, shared_1.makeApiRequest)(executeFunctions, "POST", baseUrl, CHARTS_ENDPOINTS.lunarReturn, apiKey, body);
452
+ const simplify = executeFunctions.getNodeParameter("simplify", itemIndex, true);
453
+ return simplify ? (0, shared_1.simplifyResponse)(responseData) : responseData;
454
+ }
455
+ /**
456
+ * Handles progressions chart generation (secondary progressions)
457
+ */
458
+ async function handleProgressionsChart(context) {
459
+ const { executeFunctions, itemIndex, baseUrl, apiKey } = context;
460
+ // Build natal subject
461
+ const birthData = (0, shared_1.buildBirthData)(executeFunctions, itemIndex);
462
+ const subjectName = executeFunctions.getNodeParameter("subjectName", itemIndex, "");
463
+ // Get target date
464
+ const targetDate = executeFunctions.getNodeParameter("targetDate", itemIndex);
465
+ // Get options
466
+ const options = getChartOptions(executeFunctions, itemIndex);
467
+ // Build request body
468
+ const body = {
469
+ subject: {
470
+ birth_data: birthData,
471
+ ...(subjectName && { name: subjectName }),
472
+ },
473
+ progression_date: targetDate,
474
+ options,
475
+ };
476
+ const responseData = await (0, shared_1.makeApiRequest)(executeFunctions, "POST", baseUrl, CHARTS_ENDPOINTS.progressions, apiKey, body);
477
+ const simplify = executeFunctions.getNodeParameter("simplify", itemIndex, true);
478
+ return simplify ? (0, shared_1.simplifyResponse)(responseData) : responseData;
479
+ }
480
+ /**
481
+ * Handles natal transits analysis (transit period over date range)
482
+ */
483
+ async function handleNatalTransits(context) {
484
+ const { executeFunctions, itemIndex, baseUrl, apiKey } = context;
485
+ // Build natal subject
486
+ const birthData = (0, shared_1.buildBirthData)(executeFunctions, itemIndex);
487
+ const subjectName = executeFunctions.getNodeParameter("subjectName", itemIndex, "");
488
+ // Get date range
489
+ const startDate = executeFunctions.getNodeParameter("startDate", itemIndex);
490
+ const endDate = executeFunctions.getNodeParameter("endDate", itemIndex);
491
+ // Build request body
492
+ const body = {
493
+ subject: {
494
+ birth_data: birthData,
495
+ ...(subjectName && { name: subjectName }),
496
+ },
497
+ start_date: startDate,
498
+ end_date: endDate,
499
+ };
500
+ const responseData = await (0, shared_1.makeApiRequest)(executeFunctions, "POST", baseUrl, CHARTS_ENDPOINTS.natalTransits, apiKey, body);
501
+ const simplify = executeFunctions.getNodeParameter("simplify", itemIndex, true);
502
+ return simplify ? (0, shared_1.simplifyResponse)(responseData) : responseData;
503
+ }
504
+ /**
505
+ * Handles directions chart generation (primary directions)
506
+ */
507
+ async function handleDirectionsChart(context) {
508
+ const { executeFunctions, itemIndex, baseUrl, apiKey } = context;
509
+ // Build natal subject
510
+ const birthData = (0, shared_1.buildBirthData)(executeFunctions, itemIndex);
511
+ const subjectName = executeFunctions.getNodeParameter("subjectName", itemIndex, "");
512
+ // Get target date
513
+ const targetDate = executeFunctions.getNodeParameter("targetDate", itemIndex);
514
+ // Get options
515
+ const options = getChartOptions(executeFunctions, itemIndex);
516
+ // Build request body
517
+ const body = {
518
+ subject: {
519
+ birth_data: birthData,
520
+ ...(subjectName && { name: subjectName }),
521
+ },
522
+ direction_date: targetDate,
523
+ options,
524
+ };
525
+ const responseData = await (0, shared_1.makeApiRequest)(executeFunctions, "POST", baseUrl, CHARTS_ENDPOINTS.directions, apiKey, body);
526
+ const simplify = executeFunctions.getNodeParameter("simplify", itemIndex, true);
527
+ return simplify ? (0, shared_1.simplifyResponse)(responseData) : responseData;
528
+ }
@@ -37,7 +37,90 @@ export type HoroscopeOperation = "signDaily" | "signDailyText" | "signWeekly" |
37
37
  /**
38
38
  * Charts resource operations
39
39
  */
40
- export type ChartsOperation = "natal";
40
+ export type ChartsOperation = "natal" | "synastry" | "transit" | "composite" | "solarReturn" | "lunarReturn" | "progressions" | "natalTransits" | "directions";
41
+ /**
42
+ * Transit time structure for transit chart requests
43
+ */
44
+ export interface ITransitTime {
45
+ year: number;
46
+ month: number;
47
+ day: number;
48
+ hour: number;
49
+ minute: number;
50
+ city?: string;
51
+ country_code?: string;
52
+ latitude?: number;
53
+ longitude?: number;
54
+ }
55
+ /**
56
+ * Two-subject request for synastry/composite charts
57
+ */
58
+ export interface ITwoSubjectRequest {
59
+ subject1: {
60
+ name?: string;
61
+ birth_data: IBirthData;
62
+ };
63
+ subject2: {
64
+ name?: string;
65
+ birth_data: IBirthData;
66
+ };
67
+ options?: IDataObject;
68
+ }
69
+ /**
70
+ * Transit chart request structure
71
+ */
72
+ export interface ITransitChartRequest {
73
+ subject: {
74
+ name?: string;
75
+ birth_data: IBirthData;
76
+ };
77
+ transit_time: {
78
+ datetime: ITransitTime;
79
+ };
80
+ options?: IDataObject;
81
+ }
82
+ /**
83
+ * Solar/Lunar return request structure
84
+ */
85
+ export interface IReturnChartRequest {
86
+ subject: {
87
+ name?: string;
88
+ birth_data: IBirthData;
89
+ };
90
+ return_year?: number;
91
+ return_date?: string;
92
+ return_location?: {
93
+ city?: string;
94
+ country_code?: string;
95
+ latitude?: number;
96
+ longitude?: number;
97
+ };
98
+ options?: IDataObject;
99
+ }
100
+ /**
101
+ * Progressions/Directions request structure
102
+ */
103
+ export interface IProgressionChartRequest {
104
+ subject: {
105
+ name?: string;
106
+ birth_data: IBirthData;
107
+ };
108
+ progression_date?: string;
109
+ direction_date?: string;
110
+ options?: IDataObject;
111
+ }
112
+ /**
113
+ * Natal transits (date range) request structure
114
+ */
115
+ export interface INatalTransitsRequest {
116
+ subject: {
117
+ name?: string;
118
+ birth_data: IBirthData;
119
+ };
120
+ start_date: string;
121
+ end_date: string;
122
+ options?: IDataObject;
123
+ }
41
124
  /**
42
125
  * Handler context passed to resource handlers
43
126
  */
@@ -2,6 +2,33 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.chartsOperations = void 0;
4
4
  const shared_1 = require("../shared");
5
+ /**
6
+ * Operation groups for displayOptions
7
+ */
8
+ // Operations that use birth data (almost all except maybe specific ones)
9
+ const birthDataOperations = [
10
+ "natal",
11
+ "synastry",
12
+ "transit",
13
+ "composite",
14
+ "solarReturn",
15
+ "lunarReturn",
16
+ "progressions",
17
+ "natalTransits",
18
+ "directions",
19
+ ];
20
+ // Operations requiring two subjects
21
+ const twoPersonOperations = ["synastry", "composite"];
22
+ // Operations requiring transit time
23
+ const transitOperations = ["transit"];
24
+ // Solar return operations
25
+ const solarReturnOperations = ["solarReturn"];
26
+ // Lunar return operations
27
+ const lunarReturnOperations = ["lunarReturn"];
28
+ // Date-based operations (single target date)
29
+ const dateBasedOperations = ["progressions", "directions"];
30
+ // Date range operations
31
+ const dateRangeOperations = ["natalTransits"];
5
32
  /**
6
33
  * All available active points for natal chart
7
34
  */
@@ -103,12 +130,60 @@ const chartsOperationField = {
103
130
  },
104
131
  },
105
132
  options: [
133
+ {
134
+ name: "Composite Chart",
135
+ value: "composite",
136
+ description: "Generate a merged midpoint chart representing the combined energy of two people as a relationship entity",
137
+ action: "Generate composite chart",
138
+ },
139
+ {
140
+ name: "Directions Chart",
141
+ value: "directions",
142
+ description: "Generate a primary directions chart for predictive timing of life events",
143
+ action: "Generate directions chart",
144
+ },
145
+ {
146
+ name: "Lunar Return Chart",
147
+ value: "lunarReturn",
148
+ description: "Generate a monthly forecast chart based on Moon returning to natal position",
149
+ action: "Generate lunar return chart",
150
+ },
106
151
  {
107
152
  name: "Natal Chart",
108
153
  value: "natal",
109
154
  description: "Generate a complete natal (birth) chart with planetary positions, house cusps, and aspects",
110
155
  action: "Generate natal chart",
111
156
  },
157
+ {
158
+ name: "Natal Transits",
159
+ value: "natalTransits",
160
+ description: "Analyze planetary transits over a date range against the natal chart for period forecasting",
161
+ action: "Get natal transits",
162
+ },
163
+ {
164
+ name: "Progressions Chart",
165
+ value: "progressions",
166
+ description: "Generate a secondary progressions chart showing internal development and life phase themes",
167
+ action: "Generate progressions chart",
168
+ },
169
+ {
170
+ name: "Solar Return Chart",
171
+ value: "solarReturn",
172
+ description: "Generate a birthday chart showing themes and predictions for the coming year based on Sun return",
173
+ action: "Generate solar return chart",
174
+ },
175
+ {
176
+ name: "Synastry Chart",
177
+ value: "synastry",
178
+ description: "Generate a relationship compatibility chart comparing two birth charts to analyze partnership dynamics",
179
+ action: "Generate synastry chart",
180
+ },
181
+ {
182
+ name: "Transit Chart",
183
+ value: "transit",
184
+ description: "Generate a transit overlay showing planetary positions at a specific time against the natal chart",
185
+ action: "Generate transit chart",
186
+ },
112
187
  ],
113
188
  default: "natal",
114
189
  };
@@ -435,6 +510,188 @@ const useCacheField = {
435
510
  default: true,
436
511
  description: "Whether to use cached calculations when available",
437
512
  };
513
+ /**
514
+ * Solar Return year field
515
+ */
516
+ const returnYearField = {
517
+ displayName: "Return Year",
518
+ name: "returnYear",
519
+ type: "number",
520
+ displayOptions: {
521
+ show: {
522
+ resource: ["charts"],
523
+ operation: solarReturnOperations,
524
+ },
525
+ },
526
+ default: 2024,
527
+ placeholder: "e.g. 2024",
528
+ description: "Year for the solar return chart (year of birthday to analyze)",
529
+ required: true,
530
+ };
531
+ /**
532
+ * Use relocated return toggle
533
+ */
534
+ const useRelocatedReturnField = {
535
+ displayName: "Use Relocated Location",
536
+ name: "useRelocatedReturn",
537
+ type: "boolean",
538
+ displayOptions: {
539
+ show: {
540
+ resource: ["charts"],
541
+ operation: solarReturnOperations,
542
+ },
543
+ },
544
+ default: false,
545
+ description: "Whether to calculate for a different location than birth place (relocation astrology)",
546
+ };
547
+ /**
548
+ * Relocated return location type
549
+ */
550
+ const returnLocationTypeField = {
551
+ displayName: "Return Location Type",
552
+ name: "returnLocationType",
553
+ type: "options",
554
+ displayOptions: {
555
+ show: {
556
+ resource: ["charts"],
557
+ operation: solarReturnOperations,
558
+ useRelocatedReturn: [true],
559
+ },
560
+ },
561
+ options: [
562
+ {
563
+ name: "City Name",
564
+ value: "city",
565
+ description: "Enter city and country",
566
+ },
567
+ {
568
+ name: "Coordinates",
569
+ value: "coordinates",
570
+ description: "Enter exact latitude and longitude",
571
+ },
572
+ ],
573
+ default: "city",
574
+ description: "How to specify the relocated return location",
575
+ };
576
+ /**
577
+ * Relocated return city
578
+ */
579
+ const returnCityField = {
580
+ displayName: "Return City",
581
+ name: "returnCity",
582
+ type: "string",
583
+ displayOptions: {
584
+ show: {
585
+ resource: ["charts"],
586
+ operation: solarReturnOperations,
587
+ useRelocatedReturn: [true],
588
+ returnLocationType: ["city"],
589
+ },
590
+ },
591
+ default: "",
592
+ placeholder: "e.g. New York",
593
+ description: "City where you will be on your birthday",
594
+ };
595
+ /**
596
+ * Relocated return country code
597
+ */
598
+ const returnCountryCodeField = {
599
+ displayName: "Return Country Code",
600
+ name: "returnCountryCode",
601
+ type: "string",
602
+ displayOptions: {
603
+ show: {
604
+ resource: ["charts"],
605
+ operation: solarReturnOperations,
606
+ useRelocatedReturn: [true],
607
+ returnLocationType: ["city"],
608
+ },
609
+ },
610
+ default: "",
611
+ placeholder: "e.g. US",
612
+ description: "2-letter ISO country code for return location",
613
+ };
614
+ /**
615
+ * Relocated return latitude
616
+ */
617
+ const returnLatitudeField = {
618
+ displayName: "Return Latitude",
619
+ name: "returnLatitude",
620
+ type: "number",
621
+ displayOptions: {
622
+ show: {
623
+ resource: ["charts"],
624
+ operation: solarReturnOperations,
625
+ useRelocatedReturn: [true],
626
+ returnLocationType: ["coordinates"],
627
+ },
628
+ },
629
+ default: 0,
630
+ placeholder: "e.g. 40.71",
631
+ typeOptions: {
632
+ minValue: -90,
633
+ maxValue: 90,
634
+ },
635
+ description: "Latitude of return location (-90 to 90)",
636
+ };
637
+ /**
638
+ * Relocated return longitude
639
+ */
640
+ const returnLongitudeField = {
641
+ displayName: "Return Longitude",
642
+ name: "returnLongitude",
643
+ type: "number",
644
+ displayOptions: {
645
+ show: {
646
+ resource: ["charts"],
647
+ operation: solarReturnOperations,
648
+ useRelocatedReturn: [true],
649
+ returnLocationType: ["coordinates"],
650
+ },
651
+ },
652
+ default: 0,
653
+ placeholder: "e.g. -74.01",
654
+ typeOptions: {
655
+ minValue: -180,
656
+ maxValue: 180,
657
+ },
658
+ description: "Longitude of return location (-180 to 180)",
659
+ };
660
+ /**
661
+ * Lunar Return date field
662
+ */
663
+ const lunarReturnDateField = {
664
+ displayName: "Return Date",
665
+ name: "lunarReturnDate",
666
+ type: "string",
667
+ displayOptions: {
668
+ show: {
669
+ resource: ["charts"],
670
+ operation: lunarReturnOperations,
671
+ },
672
+ },
673
+ default: "",
674
+ placeholder: "2024-06-15",
675
+ description: "Target date for lunar return (YYYY-MM-DD). Leave empty for current/next lunar return.",
676
+ };
677
+ /**
678
+ * Progression/Direction date field
679
+ */
680
+ const targetDateField = {
681
+ displayName: "Target Date",
682
+ name: "targetDate",
683
+ type: "string",
684
+ displayOptions: {
685
+ show: {
686
+ resource: ["charts"],
687
+ operation: dateBasedOperations,
688
+ },
689
+ },
690
+ default: "",
691
+ placeholder: "2024-06-15",
692
+ description: "Target date for progression/direction calculation (YYYY-MM-DD format)",
693
+ required: true,
694
+ };
438
695
  /**
439
696
  * Simplify output toggle for charts resource
440
697
  */
@@ -455,10 +712,30 @@ const simplifyField = {
455
712
  */
456
713
  exports.chartsOperations = [
457
714
  chartsOperationField,
715
+ // Subject 1 fields (for all operations)
458
716
  subjectNameField,
459
- ...(0, shared_1.createBirthDataFields)("charts"),
717
+ ...(0, shared_1.createBirthDataFields)("charts", birthDataOperations),
460
718
  secondField,
461
- ...(0, shared_1.createLocationFields)("charts"),
719
+ ...(0, shared_1.createLocationFields)("charts", birthDataOperations),
720
+ // Subject 2 fields (for synastry, composite)
721
+ ...(0, shared_1.createSecondSubjectFields)("charts", twoPersonOperations),
722
+ // Transit time fields (for transit operation)
723
+ ...(0, shared_1.createTransitTimeFields)("charts", transitOperations),
724
+ // Solar Return fields
725
+ returnYearField,
726
+ useRelocatedReturnField,
727
+ returnLocationTypeField,
728
+ returnCityField,
729
+ returnCountryCodeField,
730
+ returnLatitudeField,
731
+ returnLongitudeField,
732
+ // Lunar Return fields
733
+ lunarReturnDateField,
734
+ // Progression/Direction date field
735
+ targetDateField,
736
+ // Date range fields (for natalTransits)
737
+ ...(0, shared_1.createDateRangeFields)("charts", dateRangeOperations),
738
+ // Chart options (for most operations)
462
739
  houseSystemField,
463
740
  zodiacTypeField,
464
741
  activePointsPresetField,
@@ -466,6 +743,7 @@ exports.chartsOperations = [
466
743
  perspectiveField,
467
744
  precisionField,
468
745
  simplifyField,
746
+ // Advanced options
469
747
  showAdvancedOptionsField,
470
748
  enableFixedStarsField,
471
749
  fixedStarPresetsField,
@@ -0,0 +1,8 @@
1
+ import type { INodeProperties } from "n8n-workflow";
2
+ /**
3
+ * Creates date range fields for natal transits analysis
4
+ *
5
+ * @param resourceName - The resource value to show these fields for
6
+ * @param showForOperations - Operations that should show these fields
7
+ */
8
+ export declare function createDateRangeFields(resourceName: string, showForOperations: string[]): INodeProperties[];
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createDateRangeFields = createDateRangeFields;
4
+ /**
5
+ * Creates date range fields for natal transits analysis
6
+ *
7
+ * @param resourceName - The resource value to show these fields for
8
+ * @param showForOperations - Operations that should show these fields
9
+ */
10
+ function createDateRangeFields(resourceName, showForOperations) {
11
+ const baseDisplayOptions = {
12
+ show: {
13
+ resource: [resourceName],
14
+ operation: showForOperations,
15
+ },
16
+ };
17
+ return [
18
+ // Section header
19
+ {
20
+ displayName: "Date Range for Transit Analysis",
21
+ name: "dateRangeNotice",
22
+ type: "notice",
23
+ displayOptions: { ...baseDisplayOptions },
24
+ default: "",
25
+ },
26
+ {
27
+ displayName: "Start Date",
28
+ name: "startDate",
29
+ type: "string",
30
+ displayOptions: { ...baseDisplayOptions },
31
+ default: "",
32
+ placeholder: "2024-01-01",
33
+ description: "Start date for transit analysis period (YYYY-MM-DD format)",
34
+ required: true,
35
+ },
36
+ {
37
+ displayName: "End Date",
38
+ name: "endDate",
39
+ type: "string",
40
+ displayOptions: { ...baseDisplayOptions },
41
+ default: "",
42
+ placeholder: "2024-12-31",
43
+ description: "End date for transit analysis period (YYYY-MM-DD format)",
44
+ required: true,
45
+ },
46
+ ];
47
+ }
@@ -1,4 +1,7 @@
1
1
  export { createBirthDataFields } from "./birthData.fields";
2
2
  export { createLocationFields } from "./location.fields";
3
3
  export { zodiacSignOptions, createZodiacSignField, traditionOptions, createTraditionField, } from "./zodiac.fields";
4
+ export { createSecondSubjectFields } from "./secondSubject.fields";
5
+ export { createTransitTimeFields } from "./transitTime.fields";
6
+ export { createDateRangeFields } from "./dateRange.fields";
4
7
  export { buildBirthData, makeApiRequest, createSubjectRequest, simplifyResponse, } from "./helpers";
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.simplifyResponse = exports.createSubjectRequest = exports.makeApiRequest = exports.buildBirthData = exports.createTraditionField = exports.traditionOptions = exports.createZodiacSignField = exports.zodiacSignOptions = exports.createLocationFields = exports.createBirthDataFields = void 0;
3
+ exports.simplifyResponse = exports.createSubjectRequest = exports.makeApiRequest = exports.buildBirthData = exports.createDateRangeFields = exports.createTransitTimeFields = exports.createSecondSubjectFields = exports.createTraditionField = exports.traditionOptions = exports.createZodiacSignField = exports.zodiacSignOptions = exports.createLocationFields = exports.createBirthDataFields = void 0;
4
4
  // Shared field creators
5
5
  var birthData_fields_1 = require("./birthData.fields");
6
6
  Object.defineProperty(exports, "createBirthDataFields", { enumerable: true, get: function () { return birthData_fields_1.createBirthDataFields; } });
@@ -11,6 +11,12 @@ Object.defineProperty(exports, "zodiacSignOptions", { enumerable: true, get: fun
11
11
  Object.defineProperty(exports, "createZodiacSignField", { enumerable: true, get: function () { return zodiac_fields_1.createZodiacSignField; } });
12
12
  Object.defineProperty(exports, "traditionOptions", { enumerable: true, get: function () { return zodiac_fields_1.traditionOptions; } });
13
13
  Object.defineProperty(exports, "createTraditionField", { enumerable: true, get: function () { return zodiac_fields_1.createTraditionField; } });
14
+ var secondSubject_fields_1 = require("./secondSubject.fields");
15
+ Object.defineProperty(exports, "createSecondSubjectFields", { enumerable: true, get: function () { return secondSubject_fields_1.createSecondSubjectFields; } });
16
+ var transitTime_fields_1 = require("./transitTime.fields");
17
+ Object.defineProperty(exports, "createTransitTimeFields", { enumerable: true, get: function () { return transitTime_fields_1.createTransitTimeFields; } });
18
+ var dateRange_fields_1 = require("./dateRange.fields");
19
+ Object.defineProperty(exports, "createDateRangeFields", { enumerable: true, get: function () { return dateRange_fields_1.createDateRangeFields; } });
14
20
  // Helper functions
15
21
  var helpers_1 = require("./helpers");
16
22
  Object.defineProperty(exports, "buildBirthData", { enumerable: true, get: function () { return helpers_1.buildBirthData; } });
@@ -0,0 +1,9 @@
1
+ import type { INodeProperties } from "n8n-workflow";
2
+ /**
3
+ * Creates second subject fields (subject2*) for synastry/composite charts
4
+ * Includes birth data and location with subject2 prefix
5
+ *
6
+ * @param resourceName - The resource value to show these fields for
7
+ * @param showForOperations - Operations that should show these fields
8
+ */
9
+ export declare function createSecondSubjectFields(resourceName: string, showForOperations: string[]): INodeProperties[];
@@ -0,0 +1,190 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createSecondSubjectFields = createSecondSubjectFields;
4
+ /**
5
+ * Creates second subject fields (subject2*) for synastry/composite charts
6
+ * Includes birth data and location with subject2 prefix
7
+ *
8
+ * @param resourceName - The resource value to show these fields for
9
+ * @param showForOperations - Operations that should show these fields
10
+ */
11
+ function createSecondSubjectFields(resourceName, showForOperations) {
12
+ const baseDisplayOptions = {
13
+ show: {
14
+ resource: [resourceName],
15
+ operation: showForOperations,
16
+ },
17
+ };
18
+ // City-based location displayOptions for subject2
19
+ const cityDisplayOptions = {
20
+ show: {
21
+ ...baseDisplayOptions.show,
22
+ subject2LocationType: ["city"],
23
+ },
24
+ };
25
+ // Coordinate-based location displayOptions for subject2
26
+ const coordDisplayOptions = {
27
+ show: {
28
+ ...baseDisplayOptions.show,
29
+ subject2LocationType: ["coordinates"],
30
+ },
31
+ };
32
+ return [
33
+ // Section header
34
+ {
35
+ displayName: "Second Person Birth Data",
36
+ name: "subject2Notice",
37
+ type: "notice",
38
+ displayOptions: { ...baseDisplayOptions },
39
+ default: "",
40
+ },
41
+ // Optional name
42
+ {
43
+ displayName: "Name (Subject 2)",
44
+ name: "subject2Name",
45
+ type: "string",
46
+ displayOptions: { ...baseDisplayOptions },
47
+ default: "",
48
+ placeholder: "e.g. Partner",
49
+ description: "Optional name for the second person (used in report titles)",
50
+ },
51
+ // Birth data fields
52
+ {
53
+ displayName: "Year (Subject 2)",
54
+ name: "subject2Year",
55
+ type: "number",
56
+ displayOptions: { ...baseDisplayOptions },
57
+ default: 1990,
58
+ placeholder: "e.g. 1990",
59
+ description: "Birth year of the second person (e.g., 1990)",
60
+ required: true,
61
+ },
62
+ {
63
+ displayName: "Month (Subject 2)",
64
+ name: "subject2Month",
65
+ type: "number",
66
+ displayOptions: { ...baseDisplayOptions },
67
+ default: 1,
68
+ placeholder: "e.g. 6",
69
+ typeOptions: {
70
+ minValue: 1,
71
+ maxValue: 12,
72
+ },
73
+ description: "Birth month of the second person (1-12)",
74
+ required: true,
75
+ },
76
+ {
77
+ displayName: "Day (Subject 2)",
78
+ name: "subject2Day",
79
+ type: "number",
80
+ displayOptions: { ...baseDisplayOptions },
81
+ default: 1,
82
+ placeholder: "e.g. 15",
83
+ typeOptions: {
84
+ minValue: 1,
85
+ maxValue: 31,
86
+ },
87
+ description: "Birth day of the second person (1-31)",
88
+ required: true,
89
+ },
90
+ {
91
+ displayName: "Hour (Subject 2)",
92
+ name: "subject2Hour",
93
+ type: "number",
94
+ displayOptions: { ...baseDisplayOptions },
95
+ default: 12,
96
+ placeholder: "e.g. 14",
97
+ typeOptions: {
98
+ minValue: 0,
99
+ maxValue: 23,
100
+ },
101
+ description: "Birth hour of the second person in 24-hour format (0-23)",
102
+ required: true,
103
+ },
104
+ {
105
+ displayName: "Minute (Subject 2)",
106
+ name: "subject2Minute",
107
+ type: "number",
108
+ displayOptions: { ...baseDisplayOptions },
109
+ default: 0,
110
+ placeholder: "e.g. 30",
111
+ typeOptions: {
112
+ minValue: 0,
113
+ maxValue: 59,
114
+ },
115
+ description: "Birth minute of the second person (0-59)",
116
+ required: true,
117
+ },
118
+ // Location type selector
119
+ {
120
+ displayName: "Location Type (Subject 2)",
121
+ name: "subject2LocationType",
122
+ type: "options",
123
+ displayOptions: { ...baseDisplayOptions },
124
+ options: [
125
+ {
126
+ name: "City Name",
127
+ value: "city",
128
+ description: "Enter city and country - coordinates detected automatically",
129
+ },
130
+ {
131
+ name: "Coordinates",
132
+ value: "coordinates",
133
+ description: "Enter exact latitude and longitude",
134
+ },
135
+ ],
136
+ default: "city",
137
+ description: "How to specify the second person's birth location",
138
+ },
139
+ // City-based location fields
140
+ {
141
+ displayName: "City (Subject 2)",
142
+ name: "subject2City",
143
+ type: "string",
144
+ displayOptions: cityDisplayOptions,
145
+ default: "",
146
+ placeholder: "London",
147
+ description: "Birth city of the second person",
148
+ required: true,
149
+ },
150
+ {
151
+ displayName: "Country Code (Subject 2)",
152
+ name: "subject2CountryCode",
153
+ type: "string",
154
+ displayOptions: cityDisplayOptions,
155
+ default: "",
156
+ placeholder: "GB",
157
+ description: "2-letter ISO country code for the second person's birth city",
158
+ required: true,
159
+ },
160
+ // Coordinate-based location fields
161
+ {
162
+ displayName: "Latitude (Subject 2)",
163
+ name: "subject2Latitude",
164
+ type: "number",
165
+ displayOptions: coordDisplayOptions,
166
+ default: 0,
167
+ placeholder: "e.g. 50.45",
168
+ typeOptions: {
169
+ minValue: -90,
170
+ maxValue: 90,
171
+ },
172
+ description: "Latitude of the second person's birth location (-90 to 90)",
173
+ required: true,
174
+ },
175
+ {
176
+ displayName: "Longitude (Subject 2)",
177
+ name: "subject2Longitude",
178
+ type: "number",
179
+ displayOptions: coordDisplayOptions,
180
+ default: 0,
181
+ placeholder: "e.g. 30.52",
182
+ typeOptions: {
183
+ minValue: -180,
184
+ maxValue: 180,
185
+ },
186
+ description: "Longitude of the second person's birth location (-180 to 180)",
187
+ required: true,
188
+ },
189
+ ];
190
+ }
@@ -0,0 +1,9 @@
1
+ import type { INodeProperties } from "n8n-workflow";
2
+ /**
3
+ * Creates transit time fields for transit chart overlay
4
+ * Includes datetime and optional location fields with transit prefix
5
+ *
6
+ * @param resourceName - The resource value to show these fields for
7
+ * @param showForOperations - Operations that should show these fields
8
+ */
9
+ export declare function createTransitTimeFields(resourceName: string, showForOperations: string[]): INodeProperties[];
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createTransitTimeFields = createTransitTimeFields;
4
+ /**
5
+ * Creates transit time fields for transit chart overlay
6
+ * Includes datetime and optional location fields with transit prefix
7
+ *
8
+ * @param resourceName - The resource value to show these fields for
9
+ * @param showForOperations - Operations that should show these fields
10
+ */
11
+ function createTransitTimeFields(resourceName, showForOperations) {
12
+ const baseDisplayOptions = {
13
+ show: {
14
+ resource: [resourceName],
15
+ operation: showForOperations,
16
+ },
17
+ };
18
+ // City-based location displayOptions for transit
19
+ const cityDisplayOptions = {
20
+ show: {
21
+ ...baseDisplayOptions.show,
22
+ transitLocationType: ["city"],
23
+ },
24
+ };
25
+ // Coordinate-based location displayOptions for transit
26
+ const coordDisplayOptions = {
27
+ show: {
28
+ ...baseDisplayOptions.show,
29
+ transitLocationType: ["coordinates"],
30
+ },
31
+ };
32
+ return [
33
+ // Section header
34
+ {
35
+ displayName: "Transit Time",
36
+ name: "transitNotice",
37
+ type: "notice",
38
+ displayOptions: { ...baseDisplayOptions },
39
+ default: "",
40
+ },
41
+ // Transit datetime fields
42
+ {
43
+ displayName: "Transit Year",
44
+ name: "transitYear",
45
+ type: "number",
46
+ displayOptions: { ...baseDisplayOptions },
47
+ default: 2024,
48
+ placeholder: "e.g. 2024",
49
+ description: "Year for the transit calculation",
50
+ required: true,
51
+ },
52
+ {
53
+ displayName: "Transit Month",
54
+ name: "transitMonth",
55
+ type: "number",
56
+ displayOptions: { ...baseDisplayOptions },
57
+ default: 1,
58
+ placeholder: "e.g. 6",
59
+ typeOptions: {
60
+ minValue: 1,
61
+ maxValue: 12,
62
+ },
63
+ description: "Month for the transit calculation (1-12)",
64
+ required: true,
65
+ },
66
+ {
67
+ displayName: "Transit Day",
68
+ name: "transitDay",
69
+ type: "number",
70
+ displayOptions: { ...baseDisplayOptions },
71
+ default: 1,
72
+ placeholder: "e.g. 15",
73
+ typeOptions: {
74
+ minValue: 1,
75
+ maxValue: 31,
76
+ },
77
+ description: "Day for the transit calculation (1-31)",
78
+ required: true,
79
+ },
80
+ {
81
+ displayName: "Transit Hour",
82
+ name: "transitHour",
83
+ type: "number",
84
+ displayOptions: { ...baseDisplayOptions },
85
+ default: 12,
86
+ placeholder: "e.g. 14",
87
+ typeOptions: {
88
+ minValue: 0,
89
+ maxValue: 23,
90
+ },
91
+ description: "Hour for the transit calculation in 24-hour format (0-23)",
92
+ required: true,
93
+ },
94
+ {
95
+ displayName: "Transit Minute",
96
+ name: "transitMinute",
97
+ type: "number",
98
+ displayOptions: { ...baseDisplayOptions },
99
+ default: 0,
100
+ placeholder: "e.g. 30",
101
+ typeOptions: {
102
+ minValue: 0,
103
+ maxValue: 59,
104
+ },
105
+ description: "Minute for the transit calculation (0-59)",
106
+ required: true,
107
+ },
108
+ // Location type selector for transit
109
+ {
110
+ displayName: "Transit Location Type",
111
+ name: "transitLocationType",
112
+ type: "options",
113
+ displayOptions: { ...baseDisplayOptions },
114
+ options: [
115
+ {
116
+ name: "City Name",
117
+ value: "city",
118
+ description: "Enter city and country - coordinates detected automatically",
119
+ },
120
+ {
121
+ name: "Coordinates",
122
+ value: "coordinates",
123
+ description: "Enter exact latitude and longitude",
124
+ },
125
+ ],
126
+ default: "city",
127
+ description: "How to specify the location for transit calculation",
128
+ },
129
+ // City-based location fields
130
+ {
131
+ displayName: "Transit City",
132
+ name: "transitCity",
133
+ type: "string",
134
+ displayOptions: cityDisplayOptions,
135
+ default: "",
136
+ placeholder: "London",
137
+ description: "City for the transit calculation",
138
+ required: true,
139
+ },
140
+ {
141
+ displayName: "Transit Country Code",
142
+ name: "transitCountryCode",
143
+ type: "string",
144
+ displayOptions: cityDisplayOptions,
145
+ default: "",
146
+ placeholder: "GB",
147
+ description: "2-letter ISO country code for the transit location",
148
+ required: true,
149
+ },
150
+ // Coordinate-based location fields
151
+ {
152
+ displayName: "Transit Latitude",
153
+ name: "transitLatitude",
154
+ type: "number",
155
+ displayOptions: coordDisplayOptions,
156
+ default: 0,
157
+ placeholder: "e.g. 50.45",
158
+ typeOptions: {
159
+ minValue: -90,
160
+ maxValue: 90,
161
+ },
162
+ description: "Latitude for the transit location (-90 to 90)",
163
+ required: true,
164
+ },
165
+ {
166
+ displayName: "Transit Longitude",
167
+ name: "transitLongitude",
168
+ type: "number",
169
+ displayOptions: coordDisplayOptions,
170
+ default: 0,
171
+ placeholder: "e.g. 30.52",
172
+ typeOptions: {
173
+ minValue: -180,
174
+ maxValue: 180,
175
+ },
176
+ description: "Longitude for the transit location (-180 to 180)",
177
+ required: true,
178
+ },
179
+ ];
180
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astro-api/n8n-nodes-astrology",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "n8n community node for Astrology API - professional astrological calculations, charts, horoscopes, and interpretations",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {