key-rotation-manager 1.0.6 → 1.0.9

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
@@ -7,6 +7,21 @@ This library is designed for backend systems that need safe, extensible, and tra
7
7
 
8
8
  ---
9
9
 
10
+ ## Issues & Bug Reports
11
+
12
+ Found a bug or have a feature request?
13
+
14
+ **[🐛 Report an Issue](https://github.com/DucAnh2611/key-rotation-manager/issues/new)**
15
+
16
+ Please include:
17
+ - A clear description of the issue
18
+ - Steps to reproduce
19
+ - Expected vs actual behavior
20
+ - Your environment (Node.js version, OS, package version)
21
+ - Code samples if applicable
22
+
23
+ ---
24
+
10
25
  ## Features
11
26
 
12
27
  - 🔐 Secure key generation (AES-256-GCM by default)
@@ -43,7 +58,7 @@ const { key, path } = await keyManager.newKey({
43
58
  ```
44
59
 
45
60
  This will:
46
- - Create a `keys/` directory base on {{path}}/{{filename}}.{{fileExt}}
61
+ - Create a `keys/` directory base on `{{path}}/{{filename}}.{{fileExt}}`
47
62
  - Generate a new key
48
63
  - Save it using default storage rules
49
64
 
@@ -56,9 +71,9 @@ This will:
56
71
  ```typescript
57
72
  import { create, km } from 'key-rotation-manager';
58
73
 
59
- const keyManager = create({});
74
+ const keyManager = create();
60
75
  // or
61
- const keyManager = km({});
76
+ const keyManager = km();
62
77
  ```
63
78
 
64
79
  On initialization:
@@ -70,15 +85,15 @@ On initialization:
70
85
 
71
86
  ```typescript
72
87
  {
73
- path: ['keys'],
74
- file: ['{{type}}', 'v', '{{version}}'],
88
+ path: ['keys', '{{type}}'], // FROM 1.0.8 allow using variable: {{...}}
89
+ file: ['v', '{{version}}'],
75
90
  fileSplitor: '_',
76
91
  fileExt: 'json',
77
92
  gitIgnore: true, // add resolved path to .gitignore
78
93
 
79
94
  crypto: {
80
95
  algorithm: 'aes-256-gcm',
81
- kdf: 'scrypt',
96
+ kdf: 'pbkdf2',
82
97
  hashAlgorithm: 'sha256',
83
98
  keyLength: 32,
84
99
  ivLength: 16,
@@ -98,7 +113,8 @@ With default settings, keys are stored as:
98
113
 
99
114
  ```
100
115
  keys/
101
- └── api_v_1700000000000.json
116
+ └── {{type}}/
117
+ └── v_{{version}}.json
102
118
  ```
103
119
 
104
120
  ---
@@ -133,10 +149,8 @@ Merge mode stores multiple key versions in a single file.
133
149
  ```typescript
134
150
  const { key } = await keyManager.newKey({
135
151
  type: 'service',
136
- duration: 30,
137
- unit: 'seconds',
138
- rotate: true,
139
152
  merge: true, // Merge into 1 file {{path}}/{filename}
153
+ ...options,
140
154
  });
141
155
  ```
142
156
 
@@ -148,8 +162,8 @@ const { key } = await keyManager.newKey({
148
162
  import { create } from 'key-rotation-manager';
149
163
 
150
164
  const keyManager = create({
151
- path: ['keys', 'custom'],
152
- file: '{{type}}',
165
+ path: ['keys', '{{type}}'],
166
+ file: ['{{version}}', '{{custom_variables}}'],
153
167
  fileExt: 'txt',
154
168
  ...options,
155
169
  });
@@ -158,10 +172,16 @@ const keyManager = create({
158
172
  Resulting structure:
159
173
 
160
174
  ```
161
- keys/custom/service.txt
175
+ path: ['keys', '{{type}}']
176
+ file: ['{{version}}', '{{custom_variables}}']
177
+ fileExt: "txt"
178
+ type: "service"
179
+ variables: { custom_variables: "example" }
180
+
181
+ getKey({ type }, variables) -> keys/service/17000000000_example.txt
162
182
 
163
183
  >> .gitignore
164
- keys/custom/*
184
+ keys/*/*_*.txt
165
185
  ```
166
186
 
167
187
  ---
@@ -186,7 +206,7 @@ The returned value becomes `key.path`.
186
206
 
187
207
  ```typescript
188
208
  const result = await keyManager.getKey({
189
- path: 'keys/service_merge.json',
209
+ path: 'path (full path return from km.newKey)',
190
210
  version: 'rotate',
191
211
  onRotate: {
192
212
  duration: 30,
@@ -194,7 +214,42 @@ const result = await keyManager.getKey({
194
214
  rotate: true,
195
215
  merge: true,
196
216
  },
197
- });
217
+ }, eventHandlers);
218
+ ```
219
+
220
+ ```typescript
221
+ // from 1.0.8 getKey allow user use events
222
+
223
+ type TGetKeyEvents = {
224
+ /**
225
+ * This will fire when key is rotatable but expired and missing options to rotate
226
+ */
227
+ onMissingRotateOption: (key: TKeyGenerated, options: TGetKeyOptions) => void | Promise<void>;
228
+ /**
229
+ * This will fire when key is invalid includes validate types, from date, to date, etc...
230
+ */
231
+ onKeyInvalid: (
232
+ key: TKeyGenerated,
233
+ message: string,
234
+ errorOn?: keyof TKeyGenerated
235
+ ) => void | Promise<void>;
236
+ /**
237
+ * This will fire when key is renewed
238
+ */
239
+ onKeyRenewed: (getKey: TGetKey, options: TGetKeyOptions['onRotate']) => void | Promise<void>;
240
+ /**
241
+ * This will fire when key file is not found or version is not found in file
242
+ * @description
243
+ * IMPORTANT: every file invalid should return `{}` as key data and this will caused this event to be fired
244
+ * - Invalid file (file not found or not valid json)
245
+ * - Version not found in file
246
+ * - From date in future
247
+ * - Properties in key data is not valid types
248
+ * - hashedBytes is less than 0
249
+ */
250
+ onKeyNotFound: (path: string, version: string | number) => void | Promise<void>;
251
+ onExpired: (path: string, key: TKeyGenerated) => void | Promise<void>;
252
+ };
198
253
  ```
199
254
 
200
255
  Returned structure:
@@ -207,21 +262,21 @@ Returned structure:
207
262
  ```
208
263
 
209
264
  - `ready` → usable key
210
- - `expired` → expired key (if rotation occurred)
265
+ - `expired` → expired key
211
266
 
212
267
  ### Rotate Key (Invalid – Missing Options)
213
268
 
214
269
  ```typescript
215
270
  await keyManager.getKey({
216
- path: 'keys/service_merge.json',
271
+ path: 'path (full path return from km.newKey)',
217
272
  version: 'rotate-invalid',
218
273
  });
219
274
  ```
220
275
 
221
- Throws:
276
+ Return:
222
277
 
223
278
  ```
224
- Expired rotate options not provided
279
+ { expired: null, ready: null }
225
280
  ```
226
281
 
227
282
  ### Non-Rotating Key
@@ -246,6 +301,7 @@ keyManager.useGetKey(async () => {
246
301
  to: '2099-12-29T01:23:57.882Z',
247
302
  key: '...',
248
303
  hashed: '...',
304
+ hashedBytes: 16,
249
305
  type: 'service',
250
306
  version: 'version',
251
307
  rotate: true,
@@ -255,6 +311,28 @@ keyManager.useGetKey(async () => {
255
311
 
256
312
  Return `null` to indicate an invalid or missing key.
257
313
 
314
+ ## Custom logger
315
+
316
+ Override how logger work
317
+
318
+ ```typescript
319
+ km.setLogger((...args: unknown[]) => console.log(...args))
320
+ // or Async
321
+ km.setLogger(async (...args: unknown[]) => console.log(...args))
322
+
323
+ km.sysLog(...args);
324
+ km.customLog(async (...args: unknown[]) => console.log(...args))
325
+ ```
326
+
327
+ ## Clone instance
328
+
329
+ Clone instance to new instance include custom saveKey, getKey and storePath
330
+
331
+ ```typescript
332
+ const k = km();
333
+ const k2 = k.clone(options);
334
+ ```
335
+
258
336
  ---
259
337
 
260
338
  ## Events
@@ -286,6 +364,12 @@ keyManager.once(EEvent.STORE_INIT_FOLDER, ({ storePath }) => {
286
364
 
287
365
  ---
288
366
 
367
+ ## Contributing
368
+
369
+ Contributions are welcome! Please feel free to submit a Pull Request.
370
+
371
+ ---
372
+
289
373
  ## License
290
374
 
291
375
  MIT