apimo.js 1.0.5 → 1.1.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/dist/core/api.js
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
import Bottleneck from 'bottleneck';
|
|
11
2
|
import { merge } from 'merge-anything';
|
|
12
3
|
import { z } from 'zod';
|
|
@@ -79,113 +70,99 @@ export class Apimo {
|
|
|
79
70
|
const extendedInit = Object.assign(Object.assign({}, init), { headers: Object.assign({ Authorization: `Basic ${btoa(`${this.provider}:${this.token}`)}` }, init === null || init === void 0 ? void 0 : init.headers) });
|
|
80
71
|
return this.limiter.schedule(() => fetch(input, extendedInit));
|
|
81
72
|
}
|
|
82
|
-
get(path, schema, options) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
responseBody = yield response.json();
|
|
94
|
-
}
|
|
95
|
-
catch (_a) {
|
|
96
|
-
// The body wasn't JSON — leave responseBody as undefined
|
|
97
|
-
}
|
|
98
|
-
throwForStatus(response.status, url.toString(), responseBody);
|
|
73
|
+
async get(path, schema, options) {
|
|
74
|
+
const url = makeApiUrl(path, this.config, Object.assign({ culture: this.config.culture }, options));
|
|
75
|
+
const { attempts, initialDelayMs, backoff } = this.config.retry;
|
|
76
|
+
let lastError;
|
|
77
|
+
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
78
|
+
try {
|
|
79
|
+
const response = await this.fetch(url);
|
|
80
|
+
if (!response.ok) {
|
|
81
|
+
let responseBody;
|
|
82
|
+
try {
|
|
83
|
+
responseBody = await response.json();
|
|
99
84
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
if (!result.success) {
|
|
103
|
-
throw new ApiResponseValidationError(url.toString(), result.error);
|
|
85
|
+
catch (_a) {
|
|
86
|
+
// The body wasn't JSON — leave responseBody as undefined
|
|
104
87
|
}
|
|
105
|
-
|
|
88
|
+
throwForStatus(response.status, url.toString(), responseBody);
|
|
106
89
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
// Non-transient errors (4xx, schema failures, etc.) — propagate immediately
|
|
112
|
-
throw error;
|
|
113
|
-
}
|
|
114
|
-
if (!hasMoreAttempts) {
|
|
115
|
-
break;
|
|
116
|
-
}
|
|
117
|
-
yield this.sleep(this.retryDelayMs(attempt, initialDelayMs, backoff));
|
|
90
|
+
const json = await response.json();
|
|
91
|
+
const result = await schema.safeParseAsync(json);
|
|
92
|
+
if (!result.success) {
|
|
93
|
+
throw new ApiResponseValidationError(url.toString(), result.error);
|
|
118
94
|
}
|
|
95
|
+
return result.data;
|
|
119
96
|
}
|
|
120
|
-
|
|
121
|
-
|
|
97
|
+
catch (error) {
|
|
98
|
+
lastError = error;
|
|
99
|
+
const hasMoreAttempts = attempt < attempts;
|
|
100
|
+
if (!isRetryable(error)) {
|
|
101
|
+
// Non-transient errors (4xx, schema failures, etc.) — propagate immediately
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
if (!hasMoreAttempts) {
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
await this.sleep(this.retryDelayMs(attempt, initialDelayMs, backoff));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
throw new ApiRetryExhaustedError(attempts, lastError);
|
|
122
111
|
}
|
|
123
|
-
fetchCatalogs() {
|
|
124
|
-
return
|
|
125
|
-
return this.get(['catalogs'], z.array(CatalogDefinitionSchema));
|
|
126
|
-
});
|
|
112
|
+
async fetchCatalogs() {
|
|
113
|
+
return this.get(['catalogs'], z.array(CatalogDefinitionSchema));
|
|
127
114
|
}
|
|
128
|
-
populateCache(catalogName, culture, id) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
141
|
-
});
|
|
115
|
+
async populateCache(catalogName, culture, id) {
|
|
116
|
+
const catalog = await this.fetchCatalog(catalogName, { culture });
|
|
117
|
+
await this.cache.setEntries(catalogName, culture, catalog);
|
|
118
|
+
if (id !== undefined) {
|
|
119
|
+
const queriedKey = catalog.find(({ id: entryId }) => entryId === id);
|
|
120
|
+
return queriedKey
|
|
121
|
+
? {
|
|
122
|
+
name: queriedKey.name,
|
|
123
|
+
namePlural: queriedKey.name_plurial,
|
|
124
|
+
}
|
|
125
|
+
: null;
|
|
126
|
+
}
|
|
142
127
|
}
|
|
143
|
-
getCatalogEntries(catalogName, options) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
128
|
+
async getCatalogEntries(catalogName, options) {
|
|
129
|
+
var _a, _b, _c;
|
|
130
|
+
try {
|
|
131
|
+
return await this.cache.getEntries(catalogName, (_a = options === null || options === void 0 ? void 0 : options.culture) !== null && _a !== void 0 ? _a : this.config.culture);
|
|
132
|
+
}
|
|
133
|
+
catch (e) {
|
|
134
|
+
if (e instanceof CacheExpiredError) {
|
|
135
|
+
await this.populateCache(catalogName, (_b = options === null || options === void 0 ? void 0 : options.culture) !== null && _b !== void 0 ? _b : this.config.culture);
|
|
136
|
+
return this.cache.getEntries(catalogName, (_c = options === null || options === void 0 ? void 0 : options.culture) !== null && _c !== void 0 ? _c : this.config.culture);
|
|
148
137
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
yield this.populateCache(catalogName, (_b = options === null || options === void 0 ? void 0 : options.culture) !== null && _b !== void 0 ? _b : this.config.culture);
|
|
152
|
-
return this.cache.getEntries(catalogName, (_c = options === null || options === void 0 ? void 0 : options.culture) !== null && _c !== void 0 ? _c : this.config.culture);
|
|
153
|
-
}
|
|
154
|
-
else {
|
|
155
|
-
throw e;
|
|
156
|
-
}
|
|
138
|
+
else {
|
|
139
|
+
throw e;
|
|
157
140
|
}
|
|
158
|
-
}
|
|
141
|
+
}
|
|
159
142
|
}
|
|
160
|
-
fetchCatalog(catalogName, options) {
|
|
161
|
-
return
|
|
162
|
-
return this.get(['catalogs', catalogName], z.array(CatalogEntrySchema), options);
|
|
163
|
-
});
|
|
143
|
+
async fetchCatalog(catalogName, options) {
|
|
144
|
+
return this.get(['catalogs', catalogName], z.array(CatalogEntrySchema), options);
|
|
164
145
|
}
|
|
165
|
-
fetchAgencies(options) {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}));
|
|
173
|
-
});
|
|
146
|
+
async fetchAgencies(options) {
|
|
147
|
+
var _a;
|
|
148
|
+
return this.get(['agencies'], z.object({
|
|
149
|
+
total_items: z.number(),
|
|
150
|
+
agencies: getAgencySchema(this.getLocalizedCatalogTransformer((_a = options === null || options === void 0 ? void 0 : options.culture) !== null && _a !== void 0 ? _a : this.config.culture), this.config).array(),
|
|
151
|
+
timestamp: z.number(),
|
|
152
|
+
}));
|
|
174
153
|
}
|
|
175
|
-
fetchProperties(agencyId, options) {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
}), options);
|
|
183
|
-
});
|
|
154
|
+
async fetchProperties(agencyId, options) {
|
|
155
|
+
var _a;
|
|
156
|
+
return this.get(['agencies', agencyId.toString(), 'properties'], z.object({
|
|
157
|
+
total_items: z.number(),
|
|
158
|
+
timestamp: z.number(),
|
|
159
|
+
properties: getPropertySchema(this.getLocalizedCatalogTransformer((_a = options === null || options === void 0 ? void 0 : options.culture) !== null && _a !== void 0 ? _a : this.config.culture)).array(),
|
|
160
|
+
}), options);
|
|
184
161
|
}
|
|
185
162
|
/** Calculates the delay before the next retry attempt (1-based attempt index). */
|
|
186
163
|
retryDelayMs(attempt, initialDelayMs, backoff) {
|
|
187
164
|
switch (backoff) {
|
|
188
|
-
case 'exponential': return initialDelayMs *
|
|
165
|
+
case 'exponential': return initialDelayMs * 2 ** (attempt - 1);
|
|
189
166
|
case 'linear': return initialDelayMs * attempt;
|
|
190
167
|
case 'fixed': return initialDelayMs;
|
|
191
168
|
}
|
|
@@ -194,7 +171,7 @@ export class Apimo {
|
|
|
194
171
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
195
172
|
}
|
|
196
173
|
getLocalizedCatalogTransformer(culture) {
|
|
197
|
-
return (catalogName, id) =>
|
|
174
|
+
return async (catalogName, id) => {
|
|
198
175
|
if (!this.config.catalogs.transform.active) {
|
|
199
176
|
return `${catalogName}.${id}`;
|
|
200
177
|
}
|
|
@@ -202,21 +179,19 @@ export class Apimo {
|
|
|
202
179
|
return this.config.catalogs.transform.transformFn(catalogName, culture, id);
|
|
203
180
|
}
|
|
204
181
|
return this.catalogTransformer(catalogName, culture, id);
|
|
205
|
-
}
|
|
182
|
+
};
|
|
206
183
|
}
|
|
207
|
-
catalogTransformer(catalogName, culture, id) {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
184
|
+
async catalogTransformer(catalogName, culture, id) {
|
|
185
|
+
try {
|
|
186
|
+
return await this.cache.getEntry(catalogName, culture, id);
|
|
187
|
+
}
|
|
188
|
+
catch (e) {
|
|
189
|
+
if (e instanceof CacheExpiredError) {
|
|
190
|
+
return await this.populateCache(catalogName, culture, id);
|
|
211
191
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
return yield this.populateCache(catalogName, culture, id);
|
|
215
|
-
}
|
|
216
|
-
else {
|
|
217
|
-
throw e;
|
|
218
|
-
}
|
|
192
|
+
else {
|
|
193
|
+
throw e;
|
|
219
194
|
}
|
|
220
|
-
}
|
|
195
|
+
}
|
|
221
196
|
}
|
|
222
197
|
}
|
|
@@ -1,28 +1,13 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
import { CacheExpiredError } from './types';
|
|
11
2
|
export class DummyCache {
|
|
12
3
|
constructor() {
|
|
13
4
|
}
|
|
14
|
-
getEntries(_catalogName, _culture) {
|
|
15
|
-
|
|
16
|
-
throw new CacheExpiredError();
|
|
17
|
-
});
|
|
5
|
+
async getEntries(_catalogName, _culture) {
|
|
6
|
+
throw new CacheExpiredError();
|
|
18
7
|
}
|
|
19
|
-
setEntries(_catalogName, _culture, _entries) {
|
|
20
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
21
|
-
});
|
|
8
|
+
async setEntries(_catalogName, _culture, _entries) {
|
|
22
9
|
}
|
|
23
|
-
getEntry(_catalogName, _culture, _id) {
|
|
24
|
-
|
|
25
|
-
throw new CacheExpiredError();
|
|
26
|
-
});
|
|
10
|
+
async getEntry(_catalogName, _culture, _id) {
|
|
11
|
+
throw new CacheExpiredError();
|
|
27
12
|
}
|
|
28
13
|
}
|
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
import { mkdirSync } from 'node:fs';
|
|
11
2
|
import { readFile, writeFile } from 'node:fs/promises';
|
|
12
3
|
import * as path from 'node:path';
|
|
@@ -20,59 +11,51 @@ export class FilesystemCache {
|
|
|
20
11
|
this.cacheExpirationMs = (_b = settings === null || settings === void 0 ? void 0 : settings.cacheExpirationMs) !== null && _b !== void 0 ? _b : MS_IN_ONE_WEEK;
|
|
21
12
|
mkdirSync(this.path, { recursive: true });
|
|
22
13
|
}
|
|
23
|
-
setEntries(catalogName, culture, entries) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
cache: formattedEntries,
|
|
33
|
-
});
|
|
34
|
-
return writeFile(filePath, dump);
|
|
14
|
+
async setEntries(catalogName, culture, entries) {
|
|
15
|
+
const filePath = this.getCacheFilePath(catalogName, culture);
|
|
16
|
+
const formattedEntries = Object.fromEntries(entries.map(({ id, name, name_plurial }) => [id.toString(), {
|
|
17
|
+
name,
|
|
18
|
+
namePlural: name_plurial,
|
|
19
|
+
}]));
|
|
20
|
+
const dump = JSON.stringify({
|
|
21
|
+
timestamp: Date.now(),
|
|
22
|
+
cache: formattedEntries,
|
|
35
23
|
});
|
|
24
|
+
return writeFile(filePath, dump);
|
|
36
25
|
}
|
|
37
|
-
readFileOrThrow(filePath) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
});
|
|
26
|
+
async readFileOrThrow(filePath) {
|
|
27
|
+
try {
|
|
28
|
+
return await readFile(filePath, 'utf-8');
|
|
29
|
+
}
|
|
30
|
+
catch (_a) {
|
|
31
|
+
throw new CacheExpiredError();
|
|
32
|
+
}
|
|
46
33
|
}
|
|
47
|
-
getEntry(catalogName, culture, id) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
return (_a = parsed.cache[id.toString()]) !== null && _a !== void 0 ? _a : null;
|
|
58
|
-
});
|
|
34
|
+
async getEntry(catalogName, culture, id) {
|
|
35
|
+
var _a;
|
|
36
|
+
const filePath = this.getCacheFilePath(catalogName, culture);
|
|
37
|
+
const data = await this.readFileOrThrow(filePath);
|
|
38
|
+
const parsed = JSON.parse(data);
|
|
39
|
+
const currentTimestamp = Date.now();
|
|
40
|
+
if (parsed.timestamp + this.cacheExpirationMs < currentTimestamp) {
|
|
41
|
+
throw new CacheExpiredError();
|
|
42
|
+
}
|
|
43
|
+
return (_a = parsed.cache[id.toString()]) !== null && _a !== void 0 ? _a : null;
|
|
59
44
|
}
|
|
60
|
-
getEntries(catalogName, culture) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
name_plurial: entry === null || entry === void 0 ? void 0 : entry.namePlural,
|
|
75
|
-
});
|
|
45
|
+
async getEntries(catalogName, culture) {
|
|
46
|
+
const filePath = this.getCacheFilePath(catalogName, culture);
|
|
47
|
+
const data = await this.readFileOrThrow(filePath);
|
|
48
|
+
const parsed = JSON.parse(data);
|
|
49
|
+
const currentTimestamp = Date.now();
|
|
50
|
+
if (parsed.timestamp + this.cacheExpirationMs < currentTimestamp) {
|
|
51
|
+
throw new CacheExpiredError();
|
|
52
|
+
}
|
|
53
|
+
return Object.entries(parsed.cache).map(([id, entry]) => {
|
|
54
|
+
var _a;
|
|
55
|
+
return ({
|
|
56
|
+
id: Number.parseInt(id, 10),
|
|
57
|
+
name: (_a = entry === null || entry === void 0 ? void 0 : entry.name) !== null && _a !== void 0 ? _a : 'missing',
|
|
58
|
+
name_plurial: entry === null || entry === void 0 ? void 0 : entry.namePlural,
|
|
76
59
|
});
|
|
77
60
|
});
|
|
78
61
|
}
|
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
import { CacheExpiredError } from './types';
|
|
11
2
|
const MS_IN_ONE_WEEK = 7 * 24 * 60 * 60 * 1000;
|
|
12
3
|
export class MemoryCache {
|
|
@@ -15,46 +6,40 @@ export class MemoryCache {
|
|
|
15
6
|
this.cacheExpirationMs = (_a = settings === null || settings === void 0 ? void 0 : settings.cacheExpirationMs) !== null && _a !== void 0 ? _a : MS_IN_ONE_WEEK;
|
|
16
7
|
this._MEMORY = new Map();
|
|
17
8
|
}
|
|
18
|
-
setEntries(catalogName, culture, entries) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
cache: memoryEntry,
|
|
27
|
-
});
|
|
9
|
+
async setEntries(catalogName, culture, entries) {
|
|
10
|
+
const memoryEntry = new Map(entries.map(({ id, name, name_plurial }) => [id, {
|
|
11
|
+
name,
|
|
12
|
+
namePlural: name_plurial,
|
|
13
|
+
}]));
|
|
14
|
+
this._MEMORY.set(this.getCacheKey(catalogName, culture), {
|
|
15
|
+
timestamp: Date.now(),
|
|
16
|
+
cache: memoryEntry,
|
|
28
17
|
});
|
|
29
18
|
}
|
|
30
|
-
getEntry(catalogName, culture, id) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return (_a = memoryEntry.cache.get(id)) !== null && _a !== void 0 ? _a : null;
|
|
41
|
-
});
|
|
19
|
+
async getEntry(catalogName, culture, id) {
|
|
20
|
+
var _a;
|
|
21
|
+
const memoryEntry = this._MEMORY.get(this.getCacheKey(catalogName, culture));
|
|
22
|
+
if (!memoryEntry) {
|
|
23
|
+
throw new CacheExpiredError();
|
|
24
|
+
}
|
|
25
|
+
if (memoryEntry.timestamp + this.cacheExpirationMs < Date.now()) {
|
|
26
|
+
throw new CacheExpiredError();
|
|
27
|
+
}
|
|
28
|
+
return (_a = memoryEntry.cache.get(id)) !== null && _a !== void 0 ? _a : null;
|
|
42
29
|
}
|
|
43
|
-
getEntries(catalogName, culture) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}));
|
|
57
|
-
});
|
|
30
|
+
async getEntries(catalogName, culture) {
|
|
31
|
+
const memoryEntry = this._MEMORY.get(this.getCacheKey(catalogName, culture));
|
|
32
|
+
if (!memoryEntry) {
|
|
33
|
+
throw new CacheExpiredError();
|
|
34
|
+
}
|
|
35
|
+
if (memoryEntry.timestamp + this.cacheExpirationMs < Date.now()) {
|
|
36
|
+
throw new CacheExpiredError();
|
|
37
|
+
}
|
|
38
|
+
return Array.from(memoryEntry.cache.entries()).map(([id, { name, namePlural }]) => ({
|
|
39
|
+
id,
|
|
40
|
+
name,
|
|
41
|
+
name_plurial: namePlural,
|
|
42
|
+
}));
|
|
58
43
|
}
|
|
59
44
|
getCacheKey(catalogName, culture) {
|
|
60
45
|
return `${catalogName}.${culture}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "apimo.js",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "A wrapper for the Apimo API with catalog caching for building custom Real Estate website using their technologies.",
|
|
5
5
|
"author": "Vitaly Lysen <vitaly@lysen.dev> (https://lysen.dev)",
|
|
6
6
|
"license": "MIT",
|