@edirect/tokenization 0.0.4 → 0.0.5

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
@@ -10,6 +10,12 @@ To install the necessary dependencies, run:
10
10
  npm install --save @edirect/tokenization
11
11
  ```
12
12
 
13
+ ## Important Note
14
+
15
+ This client **caches** the **configurations** for `5 minutes` and the **tokens** for `1 minute`.
16
+
17
+ This is to avoid making unnecessary requests to the tokenization service. If you want to change any configuration on the tokenization service, you'll need to wait for the cache to expire.
18
+
13
19
  ## Usage
14
20
 
15
21
  The `Tokenization` class provides methods to tokenize and detokenize payloads. Below is an example of how to use the class.
package/dist/index.js CHANGED
@@ -102,7 +102,9 @@ var TokenEvaluator = class {
102
102
  };
103
103
 
104
104
  // src/core/app.ts
105
+ var import_lru_cache = require("lru-cache");
105
106
  var TokenizationApp = class {
107
+ cache;
106
108
  tokenizationService;
107
109
  configurationService;
108
110
  evaluator;
@@ -110,22 +112,38 @@ var TokenizationApp = class {
110
112
  this.tokenizationService = tokenizationService;
111
113
  this.configurationService = configurationService;
112
114
  this.evaluator = new TokenEvaluator(evaluator);
115
+ this.cache = new import_lru_cache.LRUCache({
116
+ max: 5e3,
117
+ ttl: 1e3 * 60 * 1,
118
+ // 1 minute
119
+ allowStale: false,
120
+ updateAgeOnGet: false,
121
+ updateAgeOnHas: false
122
+ });
113
123
  }
114
124
  async tokenize(auth, tenant, configKey, payload) {
115
125
  const config = await this.configurationService.get(auth, tenant, configKey);
116
126
  if (!config) return payload;
117
127
  if ((!config.fields || config.fields.length === 0) && config.defaultClassification === 0)
118
128
  return payload;
119
- const processedPayload = await this.processRequest(config, payload);
120
- const tokenPayload = await this.tokenizationService.tokenize(
121
- auth,
122
- tenant,
123
- configKey,
124
- processedPayload
125
- );
126
129
  const respPayload = payload;
127
- for (const key in tokenPayload) {
128
- set(respPayload, key.split("."), tokenPayload[key]);
130
+ const processedPayload = await this.processRequest(config, payload);
131
+ if (Object.keys(processedPayload.notFound).length > 0) {
132
+ const tokenPayload = await this.tokenizationService.tokenize(
133
+ auth,
134
+ tenant,
135
+ configKey,
136
+ processedPayload.notFound
137
+ );
138
+ for (const key in tokenPayload) {
139
+ set(respPayload, key.split("."), tokenPayload[key]);
140
+ this.cache.set(key, tokenPayload[key]);
141
+ }
142
+ }
143
+ if (Object.keys(processedPayload.found).length > 0) {
144
+ for (const key in processedPayload.found) {
145
+ set(respPayload, key.split("."), processedPayload.found[key]);
146
+ }
129
147
  }
130
148
  return respPayload;
131
149
  }
@@ -134,27 +152,47 @@ var TokenizationApp = class {
134
152
  if (!config) return payload;
135
153
  if ((!config.fields || config.fields.length === 0) && config.defaultClassification === 0)
136
154
  return payload;
137
- const processedPayload = this.processRequest(config, payload);
138
- const tokenPayload = await this.tokenizationService.detokenize(
139
- auth,
140
- tenant,
141
- configKey,
142
- processedPayload
143
- );
144
155
  const respPayload = payload;
145
- for (const key in tokenPayload) {
146
- set(respPayload, key.split("."), tokenPayload[key]);
156
+ const processedPayload = this.processRequest(config, payload);
157
+ if (Object.keys(processedPayload.notFound).length > 0) {
158
+ const tokenPayload = await this.tokenizationService.detokenize(
159
+ auth,
160
+ tenant,
161
+ configKey,
162
+ processedPayload.notFound
163
+ );
164
+ for (const key in tokenPayload) {
165
+ set(respPayload, key.split("."), tokenPayload[key]);
166
+ this.cache.set(key, tokenPayload[key]);
167
+ }
168
+ }
169
+ if (Object.keys(processedPayload.found).length > 0) {
170
+ for (const key in processedPayload.found) {
171
+ set(respPayload, key.split("."), processedPayload.found[key]);
172
+ }
147
173
  }
148
174
  return respPayload;
149
175
  }
150
176
  processRequest(config, payload) {
151
177
  if (config.fields.length === 0) {
152
- return payload;
178
+ return {
179
+ found: payload,
180
+ notFound: {}
181
+ };
153
182
  }
154
- const req = {};
183
+ const req = {
184
+ found: {},
185
+ notFound: {}
186
+ };
155
187
  traverse(payload, (value, path) => {
156
188
  if (this.evaluator.shouldTokenizeField(config, path)) {
157
- req[path.join(".")] = value;
189
+ const pathName = path.join(".");
190
+ const fromCache = this.cache.get(pathName);
191
+ if (fromCache) {
192
+ req.found[pathName] = fromCache;
193
+ } else {
194
+ req.notFound[pathName] = value;
195
+ }
158
196
  }
159
197
  });
160
198
  return req;
@@ -162,14 +200,28 @@ var TokenizationApp = class {
162
200
  };
163
201
 
164
202
  // src/core/services/configuration.ts
203
+ var import_lru_cache2 = require("lru-cache");
165
204
  var ConfigurationService = class {
166
205
  constructor(baseUrl) {
167
206
  this.baseUrl = baseUrl;
168
207
  if (!this.baseUrl) {
169
208
  throw new Error("Configuration Service BaseUrl is required");
170
209
  }
210
+ this.cache = new import_lru_cache2.LRUCache({
211
+ max: 100,
212
+ ttl: 1e3 * 60 * 5,
213
+ // 5 minutes
214
+ allowStale: false,
215
+ updateAgeOnGet: false,
216
+ updateAgeOnHas: false
217
+ });
171
218
  }
219
+ cache;
172
220
  async get(auth, tenant, config) {
221
+ const cached = this.cache.get(`${tenant}/${config}`);
222
+ if (cached) {
223
+ return cached;
224
+ }
173
225
  const resp = await fetch(
174
226
  `${this.baseUrl}/api/v1/${tenant}/${config}/config`,
175
227
  {
@@ -186,6 +238,7 @@ var ConfigurationService = class {
186
238
  throw new Error("Failed to get configuration");
187
239
  }
188
240
  const data = await resp.json();
241
+ this.cache.set(`${tenant}/${config}`, data);
189
242
  return data;
190
243
  }
191
244
  async create(auth, tenant, config) {
package/dist/index.mjs CHANGED
@@ -76,7 +76,9 @@ var TokenEvaluator = class {
76
76
  };
77
77
 
78
78
  // src/core/app.ts
79
+ import { LRUCache } from "lru-cache";
79
80
  var TokenizationApp = class {
81
+ cache;
80
82
  tokenizationService;
81
83
  configurationService;
82
84
  evaluator;
@@ -84,22 +86,38 @@ var TokenizationApp = class {
84
86
  this.tokenizationService = tokenizationService;
85
87
  this.configurationService = configurationService;
86
88
  this.evaluator = new TokenEvaluator(evaluator);
89
+ this.cache = new LRUCache({
90
+ max: 5e3,
91
+ ttl: 1e3 * 60 * 1,
92
+ // 1 minute
93
+ allowStale: false,
94
+ updateAgeOnGet: false,
95
+ updateAgeOnHas: false
96
+ });
87
97
  }
88
98
  async tokenize(auth, tenant, configKey, payload) {
89
99
  const config = await this.configurationService.get(auth, tenant, configKey);
90
100
  if (!config) return payload;
91
101
  if ((!config.fields || config.fields.length === 0) && config.defaultClassification === 0)
92
102
  return payload;
93
- const processedPayload = await this.processRequest(config, payload);
94
- const tokenPayload = await this.tokenizationService.tokenize(
95
- auth,
96
- tenant,
97
- configKey,
98
- processedPayload
99
- );
100
103
  const respPayload = payload;
101
- for (const key in tokenPayload) {
102
- set(respPayload, key.split("."), tokenPayload[key]);
104
+ const processedPayload = await this.processRequest(config, payload);
105
+ if (Object.keys(processedPayload.notFound).length > 0) {
106
+ const tokenPayload = await this.tokenizationService.tokenize(
107
+ auth,
108
+ tenant,
109
+ configKey,
110
+ processedPayload.notFound
111
+ );
112
+ for (const key in tokenPayload) {
113
+ set(respPayload, key.split("."), tokenPayload[key]);
114
+ this.cache.set(key, tokenPayload[key]);
115
+ }
116
+ }
117
+ if (Object.keys(processedPayload.found).length > 0) {
118
+ for (const key in processedPayload.found) {
119
+ set(respPayload, key.split("."), processedPayload.found[key]);
120
+ }
103
121
  }
104
122
  return respPayload;
105
123
  }
@@ -108,27 +126,47 @@ var TokenizationApp = class {
108
126
  if (!config) return payload;
109
127
  if ((!config.fields || config.fields.length === 0) && config.defaultClassification === 0)
110
128
  return payload;
111
- const processedPayload = this.processRequest(config, payload);
112
- const tokenPayload = await this.tokenizationService.detokenize(
113
- auth,
114
- tenant,
115
- configKey,
116
- processedPayload
117
- );
118
129
  const respPayload = payload;
119
- for (const key in tokenPayload) {
120
- set(respPayload, key.split("."), tokenPayload[key]);
130
+ const processedPayload = this.processRequest(config, payload);
131
+ if (Object.keys(processedPayload.notFound).length > 0) {
132
+ const tokenPayload = await this.tokenizationService.detokenize(
133
+ auth,
134
+ tenant,
135
+ configKey,
136
+ processedPayload.notFound
137
+ );
138
+ for (const key in tokenPayload) {
139
+ set(respPayload, key.split("."), tokenPayload[key]);
140
+ this.cache.set(key, tokenPayload[key]);
141
+ }
142
+ }
143
+ if (Object.keys(processedPayload.found).length > 0) {
144
+ for (const key in processedPayload.found) {
145
+ set(respPayload, key.split("."), processedPayload.found[key]);
146
+ }
121
147
  }
122
148
  return respPayload;
123
149
  }
124
150
  processRequest(config, payload) {
125
151
  if (config.fields.length === 0) {
126
- return payload;
152
+ return {
153
+ found: payload,
154
+ notFound: {}
155
+ };
127
156
  }
128
- const req = {};
157
+ const req = {
158
+ found: {},
159
+ notFound: {}
160
+ };
129
161
  traverse(payload, (value, path) => {
130
162
  if (this.evaluator.shouldTokenizeField(config, path)) {
131
- req[path.join(".")] = value;
163
+ const pathName = path.join(".");
164
+ const fromCache = this.cache.get(pathName);
165
+ if (fromCache) {
166
+ req.found[pathName] = fromCache;
167
+ } else {
168
+ req.notFound[pathName] = value;
169
+ }
132
170
  }
133
171
  });
134
172
  return req;
@@ -136,14 +174,28 @@ var TokenizationApp = class {
136
174
  };
137
175
 
138
176
  // src/core/services/configuration.ts
177
+ import { LRUCache as LRUCache2 } from "lru-cache";
139
178
  var ConfigurationService = class {
140
179
  constructor(baseUrl) {
141
180
  this.baseUrl = baseUrl;
142
181
  if (!this.baseUrl) {
143
182
  throw new Error("Configuration Service BaseUrl is required");
144
183
  }
184
+ this.cache = new LRUCache2({
185
+ max: 100,
186
+ ttl: 1e3 * 60 * 5,
187
+ // 5 minutes
188
+ allowStale: false,
189
+ updateAgeOnGet: false,
190
+ updateAgeOnHas: false
191
+ });
145
192
  }
193
+ cache;
146
194
  async get(auth, tenant, config) {
195
+ const cached = this.cache.get(`${tenant}/${config}`);
196
+ if (cached) {
197
+ return cached;
198
+ }
147
199
  const resp = await fetch(
148
200
  `${this.baseUrl}/api/v1/${tenant}/${config}/config`,
149
201
  {
@@ -160,6 +212,7 @@ var ConfigurationService = class {
160
212
  throw new Error("Failed to get configuration");
161
213
  }
162
214
  const data = await resp.json();
215
+ this.cache.set(`${tenant}/${config}`, data);
163
216
  return data;
164
217
  }
165
218
  async create(auth, tenant, config) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edirect/tokenization",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "description": "Javascript library for tokenization service",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -32,5 +32,8 @@
32
32
  "tsup": "^8.3.5",
33
33
  "typescript": "^5.7.2",
34
34
  "vitest": "^2.1.8"
35
+ },
36
+ "dependencies": {
37
+ "lru-cache": "^11.0.2"
35
38
  }
36
39
  }