@allratestoday/sdk 1.4.4 → 1.4.6

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/dist/index.d.mts CHANGED
@@ -166,6 +166,15 @@ declare class AllRatesToday {
166
166
  private resolveKey;
167
167
  private request;
168
168
  private formatDate;
169
+ /**
170
+ * The history endpoint serves fixed windows ending today (7d, 30d, 1y) and
171
+ * one target per call, so pick the smallest window that reaches `start`.
172
+ */
173
+ private windowFor;
174
+ private requireSymbols;
175
+ private historyPoints;
176
+ /** Rate on `date`, or the closest earlier point (the 1y window is weekly). */
177
+ private rateOn;
169
178
  /**
170
179
  * Get the latest exchange rates.
171
180
  *
package/dist/index.d.ts CHANGED
@@ -166,6 +166,15 @@ declare class AllRatesToday {
166
166
  private resolveKey;
167
167
  private request;
168
168
  private formatDate;
169
+ /**
170
+ * The history endpoint serves fixed windows ending today (7d, 30d, 1y) and
171
+ * one target per call, so pick the smallest window that reaches `start`.
172
+ */
173
+ private windowFor;
174
+ private requireSymbols;
175
+ private historyPoints;
176
+ /** Rate on `date`, or the closest earlier point (the 1y window is weekly). */
177
+ private rateOn;
169
178
  /**
170
179
  * Get the latest exchange rates.
171
180
  *
package/dist/index.js CHANGED
@@ -92,6 +92,43 @@ var AllRatesToday = class {
92
92
  }
93
93
  return date;
94
94
  }
95
+ /**
96
+ * The history endpoint serves fixed windows ending today (7d, 30d, 1y) and
97
+ * one target per call, so pick the smallest window that reaches `start`.
98
+ */
99
+ windowFor(start) {
100
+ const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
101
+ const days = Math.round((Date.parse(`${today}T00:00:00Z`) - Date.parse(`${start}T00:00:00Z`)) / 864e5);
102
+ if (Number.isNaN(days)) throw new AllRatesTodayError(`Invalid date: ${start}. Use YYYY-MM-DD.`);
103
+ if (days < 0) throw new AllRatesTodayError(`Date ${start} is in the future.`);
104
+ if (days <= 6) return "7d";
105
+ if (days <= 29) return "30d";
106
+ if (days <= 364) return "1y";
107
+ throw new AllRatesTodayError(`Historical market rates cover the last 365 days; ${start} is older.`);
108
+ }
109
+ requireSymbols(symbols, method) {
110
+ if (!symbols?.length) {
111
+ throw new AllRatesTodayError(`${method}() needs symbols, e.g. { symbols: ['EUR'] }.`);
112
+ }
113
+ return symbols;
114
+ }
115
+ async historyPoints(source, target, period, key) {
116
+ const raw = await this.request(
117
+ "/api/historical-rates",
118
+ { source, target, period },
119
+ key
120
+ );
121
+ return (raw.data ?? []).slice().sort((a, b) => a.timestamp - b.timestamp);
122
+ }
123
+ /** Rate on `date`, or the closest earlier point (the 1y window is weekly). */
124
+ async rateOn(source, target, date, key) {
125
+ let rate;
126
+ for (const p of await this.historyPoints(source, target, this.windowFor(date), key)) {
127
+ if (p.date.slice(0, 10) > date) break;
128
+ rate = p.rate;
129
+ }
130
+ return rate;
131
+ }
95
132
  // -------------------------------------------------------------------------
96
133
  // Public API
97
134
  // -------------------------------------------------------------------------
@@ -144,29 +181,13 @@ var AllRatesToday = class {
144
181
  async forDate(date, options = {}) {
145
182
  const key = this.resolveKey(options.apiKey);
146
183
  const dateStr = this.formatDate(date);
147
- const params = {
148
- source: options.base || "USD",
149
- from: dateStr,
150
- to: dateStr
151
- };
152
- if (options.symbols?.length) {
153
- params.target = options.symbols.join(",");
154
- }
155
- const raw = await this.request(
156
- "/api/historical-rates",
157
- params,
158
- key
159
- );
184
+ const source = options.base || "USD";
160
185
  const rates = {};
161
- if (raw.rates?.length) {
162
- for (const r of raw.rates) {
163
- rates[raw.target] = r.rate;
164
- }
165
- }
166
- if (raw.current) {
167
- rates[raw.target] = raw.current.rate;
186
+ for (const target of this.requireSymbols(options.symbols, "forDate")) {
187
+ const rate = await this.rateOn(source, target, dateStr, key);
188
+ if (rate !== void 0) rates[target] = rate;
168
189
  }
169
- return { base: params.source, date: dateStr, rates };
190
+ return { base: source, date: dateStr, rates };
170
191
  }
171
192
  /**
172
193
  * Get exchange rate time series between two dates.
@@ -186,25 +207,14 @@ var AllRatesToday = class {
186
207
  const start = this.formatDate(startDate);
187
208
  const end = this.formatDate(endDate);
188
209
  const source = options.base || "USD";
189
- const params = {
190
- source,
191
- from: start,
192
- to: end
193
- };
194
- if (options.symbols?.length) {
195
- params.target = options.symbols.join(",");
196
- }
197
- const raw = await this.request(
198
- "/api/historical-rates",
199
- params,
200
- key
201
- );
210
+ const period = this.windowFor(start);
202
211
  const rates = {};
203
- if (raw.rates) {
204
- for (const point of raw.rates) {
205
- const dateKey = point.time.split("T")[0];
206
- if (!rates[dateKey]) rates[dateKey] = {};
207
- rates[dateKey][raw.target] = point.rate;
212
+ for (const target of this.requireSymbols(options.symbols, "timeSeries")) {
213
+ for (const point of await this.historyPoints(source, target, period, key)) {
214
+ const day = point.date.slice(0, 10);
215
+ if (day < start || day > end) continue;
216
+ if (!rates[day]) rates[day] = {};
217
+ rates[day][target] = point.rate;
208
218
  }
209
219
  }
210
220
  return { base: source, startDate: start, endDate: end, rates };
@@ -223,7 +233,10 @@ var AllRatesToday = class {
223
233
  */
224
234
  async symbols(options = {}) {
225
235
  const key = this.resolveKey(options.apiKey);
226
- return this.request("/api/v1/symbols", {}, key);
236
+ const raw = await this.request("/api/v1/symbols", {}, key);
237
+ const symbols = {};
238
+ for (const c of raw.currencies ?? []) symbols[c.code] = c.name;
239
+ return { symbols };
227
240
  }
228
241
  /**
229
242
  * Latest table of OFFICIAL rates published by a central bank or tax
@@ -339,18 +352,10 @@ var AllRatesToday = class {
339
352
  const key = this.resolveKey(options.apiKey);
340
353
  if (options.date) {
341
354
  const dateStr = this.formatDate(options.date);
342
- const params = {
343
- source: from,
344
- target: to,
345
- from: dateStr,
346
- to: dateStr
347
- };
348
- const raw = await this.request(
349
- "/api/historical-rates",
350
- params,
351
- key
352
- );
353
- const rate = raw.current?.rate ?? raw.rates?.[0]?.rate ?? 0;
355
+ const rate = await this.rateOn(from, to, dateStr, key);
356
+ if (rate === void 0) {
357
+ throw new AllRatesTodayError(`No ${from}/${to} rate available on or before ${dateStr}`);
358
+ }
354
359
  return { from, to, amount, result: Number((amount * rate).toFixed(6)), rate, date: dateStr };
355
360
  }
356
361
  const data = await this.request(
package/dist/index.mjs CHANGED
@@ -66,6 +66,43 @@ var AllRatesToday = class {
66
66
  }
67
67
  return date;
68
68
  }
69
+ /**
70
+ * The history endpoint serves fixed windows ending today (7d, 30d, 1y) and
71
+ * one target per call, so pick the smallest window that reaches `start`.
72
+ */
73
+ windowFor(start) {
74
+ const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
75
+ const days = Math.round((Date.parse(`${today}T00:00:00Z`) - Date.parse(`${start}T00:00:00Z`)) / 864e5);
76
+ if (Number.isNaN(days)) throw new AllRatesTodayError(`Invalid date: ${start}. Use YYYY-MM-DD.`);
77
+ if (days < 0) throw new AllRatesTodayError(`Date ${start} is in the future.`);
78
+ if (days <= 6) return "7d";
79
+ if (days <= 29) return "30d";
80
+ if (days <= 364) return "1y";
81
+ throw new AllRatesTodayError(`Historical market rates cover the last 365 days; ${start} is older.`);
82
+ }
83
+ requireSymbols(symbols, method) {
84
+ if (!symbols?.length) {
85
+ throw new AllRatesTodayError(`${method}() needs symbols, e.g. { symbols: ['EUR'] }.`);
86
+ }
87
+ return symbols;
88
+ }
89
+ async historyPoints(source, target, period, key) {
90
+ const raw = await this.request(
91
+ "/api/historical-rates",
92
+ { source, target, period },
93
+ key
94
+ );
95
+ return (raw.data ?? []).slice().sort((a, b) => a.timestamp - b.timestamp);
96
+ }
97
+ /** Rate on `date`, or the closest earlier point (the 1y window is weekly). */
98
+ async rateOn(source, target, date, key) {
99
+ let rate;
100
+ for (const p of await this.historyPoints(source, target, this.windowFor(date), key)) {
101
+ if (p.date.slice(0, 10) > date) break;
102
+ rate = p.rate;
103
+ }
104
+ return rate;
105
+ }
69
106
  // -------------------------------------------------------------------------
70
107
  // Public API
71
108
  // -------------------------------------------------------------------------
@@ -118,29 +155,13 @@ var AllRatesToday = class {
118
155
  async forDate(date, options = {}) {
119
156
  const key = this.resolveKey(options.apiKey);
120
157
  const dateStr = this.formatDate(date);
121
- const params = {
122
- source: options.base || "USD",
123
- from: dateStr,
124
- to: dateStr
125
- };
126
- if (options.symbols?.length) {
127
- params.target = options.symbols.join(",");
128
- }
129
- const raw = await this.request(
130
- "/api/historical-rates",
131
- params,
132
- key
133
- );
158
+ const source = options.base || "USD";
134
159
  const rates = {};
135
- if (raw.rates?.length) {
136
- for (const r of raw.rates) {
137
- rates[raw.target] = r.rate;
138
- }
139
- }
140
- if (raw.current) {
141
- rates[raw.target] = raw.current.rate;
160
+ for (const target of this.requireSymbols(options.symbols, "forDate")) {
161
+ const rate = await this.rateOn(source, target, dateStr, key);
162
+ if (rate !== void 0) rates[target] = rate;
142
163
  }
143
- return { base: params.source, date: dateStr, rates };
164
+ return { base: source, date: dateStr, rates };
144
165
  }
145
166
  /**
146
167
  * Get exchange rate time series between two dates.
@@ -160,25 +181,14 @@ var AllRatesToday = class {
160
181
  const start = this.formatDate(startDate);
161
182
  const end = this.formatDate(endDate);
162
183
  const source = options.base || "USD";
163
- const params = {
164
- source,
165
- from: start,
166
- to: end
167
- };
168
- if (options.symbols?.length) {
169
- params.target = options.symbols.join(",");
170
- }
171
- const raw = await this.request(
172
- "/api/historical-rates",
173
- params,
174
- key
175
- );
184
+ const period = this.windowFor(start);
176
185
  const rates = {};
177
- if (raw.rates) {
178
- for (const point of raw.rates) {
179
- const dateKey = point.time.split("T")[0];
180
- if (!rates[dateKey]) rates[dateKey] = {};
181
- rates[dateKey][raw.target] = point.rate;
186
+ for (const target of this.requireSymbols(options.symbols, "timeSeries")) {
187
+ for (const point of await this.historyPoints(source, target, period, key)) {
188
+ const day = point.date.slice(0, 10);
189
+ if (day < start || day > end) continue;
190
+ if (!rates[day]) rates[day] = {};
191
+ rates[day][target] = point.rate;
182
192
  }
183
193
  }
184
194
  return { base: source, startDate: start, endDate: end, rates };
@@ -197,7 +207,10 @@ var AllRatesToday = class {
197
207
  */
198
208
  async symbols(options = {}) {
199
209
  const key = this.resolveKey(options.apiKey);
200
- return this.request("/api/v1/symbols", {}, key);
210
+ const raw = await this.request("/api/v1/symbols", {}, key);
211
+ const symbols = {};
212
+ for (const c of raw.currencies ?? []) symbols[c.code] = c.name;
213
+ return { symbols };
201
214
  }
202
215
  /**
203
216
  * Latest table of OFFICIAL rates published by a central bank or tax
@@ -313,18 +326,10 @@ var AllRatesToday = class {
313
326
  const key = this.resolveKey(options.apiKey);
314
327
  if (options.date) {
315
328
  const dateStr = this.formatDate(options.date);
316
- const params = {
317
- source: from,
318
- target: to,
319
- from: dateStr,
320
- to: dateStr
321
- };
322
- const raw = await this.request(
323
- "/api/historical-rates",
324
- params,
325
- key
326
- );
327
- const rate = raw.current?.rate ?? raw.rates?.[0]?.rate ?? 0;
329
+ const rate = await this.rateOn(from, to, dateStr, key);
330
+ if (rate === void 0) {
331
+ throw new AllRatesTodayError(`No ${from}/${to} rate available on or before ${dateStr}`);
332
+ }
328
333
  return { from, to, amount, result: Number((amount * rate).toFixed(6)), rate, date: dateStr };
329
334
  }
330
335
  const data = await this.request(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allratestoday/sdk",
3
- "version": "1.4.4",
3
+ "version": "1.4.6",
4
4
  "description": "Exchange Rate API — Real-time mid-market currency exchange rates for Node.js and browsers. 160+ currencies, zero dependencies, free tier.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -32,7 +32,13 @@
32
32
  "mid-market-rate",
33
33
  "fx",
34
34
  "exchangerate",
35
- "exchange rate"
35
+ "exchange rate",
36
+ "currency-api",
37
+ "currency-exchange-rates",
38
+ "forex-api",
39
+ "currency-conversion",
40
+ "currency-exchange",
41
+ "currency-rates"
36
42
  ],
37
43
  "author": "AllRatesToday <info@allratestoday.com>",
38
44
  "license": "MIT",