nfkit 1.0.34 → 1.0.36
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 +563 -1
- package/dist/index.cjs +105 -85
- package/dist/index.cjs.map +3 -3
- package/dist/index.mjs +105 -85
- package/dist/index.mjs.map +3 -3
- package/dist/src/app-context/app-context.d.ts +14 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,3 +1,565 @@
|
|
|
1
1
|
# nfkit
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`nfkit` is a TypeScript utility package focused on practical backend/frontend engineering helpers: middleware dispatching, i18n pipeline, lightweight app context (DI-like), task scheduling, abortable proxies, and more.
|
|
4
|
+
|
|
5
|
+
## Feature Count (public exports)
|
|
6
|
+
|
|
7
|
+
Based on `index.ts`, the package currently exposes **14 public entries**:
|
|
8
|
+
|
|
9
|
+
- **13 functional modules**
|
|
10
|
+
- **1 shared types module** (`types`)
|
|
11
|
+
|
|
12
|
+
| # | Entry | Purpose |
|
|
13
|
+
| --- | --- | --- |
|
|
14
|
+
| 1 | `workflow` | Lazy chained calls for property/method/function invocation |
|
|
15
|
+
| 2 | `dual-object` | Dual-state object (`sync object + PromiseLike`) |
|
|
16
|
+
| 3 | `workflow-dispatcher` | Multi-worker task scheduler with retry/backoff and dynamic worker ops |
|
|
17
|
+
| 4 | `round-robin` | Round-robin selector |
|
|
18
|
+
| 5 | `abortable` | AbortSignal-aware proxy wrapper |
|
|
19
|
+
| 6 | `middleware-dispatcher` | Generic middleware dispatching (dynamic/proto variants included) |
|
|
20
|
+
| 7 | `i18n` | i18n pipeline and dictionary lookup middleware |
|
|
21
|
+
| 8 | `patch-string-in-object` | Deep string patching inside object graphs |
|
|
22
|
+
| 9 | `observe-diff` | Object mutation diff observer (`add`/`update`/`delete`) |
|
|
23
|
+
| 10 | `memorize` | Per-instance memoization decorator for methods/getters |
|
|
24
|
+
| 11 | `may-be-array` | `T | T[]` type helper + normalization utility |
|
|
25
|
+
| 12 | `app-context` | Lightweight app context (`provide/use/start/get`) |
|
|
26
|
+
| 13 | `configurer` | Config loading/parsing helpers |
|
|
27
|
+
| 14 | `types` | Shared type exports (`Awaitable`, etc.) |
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm i nfkit
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Quick Start
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import {
|
|
39
|
+
createAppContext,
|
|
40
|
+
MiddlewareDispatcher,
|
|
41
|
+
I18n,
|
|
42
|
+
I18nLookupMiddleware,
|
|
43
|
+
WorkflowDispatcher,
|
|
44
|
+
} from 'nfkit';
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## API and Usage
|
|
48
|
+
|
|
49
|
+
### 1) `workflow`
|
|
50
|
+
|
|
51
|
+
Builds a lazy chain. Execution starts only when you `await` (or call `.then/.catch/.finally`).
|
|
52
|
+
|
|
53
|
+
**API**
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
workflow<T>(source: T | Promise<T>): Chain<T>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Example**
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import { workflow } from 'nfkit';
|
|
63
|
+
|
|
64
|
+
class Client {
|
|
65
|
+
count = 0;
|
|
66
|
+
async connect() {
|
|
67
|
+
return this;
|
|
68
|
+
}
|
|
69
|
+
inc(n: number) {
|
|
70
|
+
this.count += n;
|
|
71
|
+
return this;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const client = new Client();
|
|
76
|
+
const value = await workflow(client).connect().inc(2).count;
|
|
77
|
+
// value === 2
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 2) `dual-object`
|
|
81
|
+
|
|
82
|
+
Creates a dual-state object:
|
|
83
|
+
|
|
84
|
+
- sync access path for properties/methods
|
|
85
|
+
- async object path via `await obj`
|
|
86
|
+
- pending-safe deferred calls for selected async methods (`asyncMethods`)
|
|
87
|
+
|
|
88
|
+
**API**
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
type Dual<T> = T & PromiseLike<T>;
|
|
92
|
+
const DUAL_PENDING: unique symbol;
|
|
93
|
+
throwDualPending(): never;
|
|
94
|
+
|
|
95
|
+
dualizeAny<T>(
|
|
96
|
+
sync: () => T,
|
|
97
|
+
asyncFn: () => Promise<T>,
|
|
98
|
+
options?: { asyncMethods?: readonly (keyof T)[] },
|
|
99
|
+
): Dual<T>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Example**
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
import { dualizeAny } from 'nfkit';
|
|
106
|
+
|
|
107
|
+
type UserClient = {
|
|
108
|
+
id: string;
|
|
109
|
+
ping(): Promise<number>;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const c = dualizeAny<UserClient>(
|
|
113
|
+
() => ({ id: 'cached', ping: async () => 1 }),
|
|
114
|
+
async () => ({ id: 'remote', ping: async () => 42 }),
|
|
115
|
+
{ asyncMethods: ['ping'] as const },
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
const v = await c.ping(); // works even while object is pending
|
|
119
|
+
const obj = await c;
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### 3) `workflow-dispatcher`
|
|
123
|
+
|
|
124
|
+
Asynchronous multi-worker dispatcher with:
|
|
125
|
+
|
|
126
|
+
- global dispatch (auto worker selection)
|
|
127
|
+
- worker-specific dispatch
|
|
128
|
+
- retry + exponential backoff
|
|
129
|
+
- runtime worker replace/add/remove
|
|
130
|
+
|
|
131
|
+
**API**
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
new WorkflowDispatcher<F extends (...args: any[]) => Promise<any>>(
|
|
135
|
+
workersOrPromises: Array<F | Promise<F>>,
|
|
136
|
+
options?: { maxAttempts?: number; backoffBaseMs?: number },
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
dispatch(...args: Parameters<F>): Promise<Awaited<ReturnType<F>>>
|
|
140
|
+
dispatchSpecific(index: number, ...args: Parameters<F>): Promise<Awaited<ReturnType<F>>>
|
|
141
|
+
replaceWorker(index: number, fn: F): void
|
|
142
|
+
addWorker(fn: F): number
|
|
143
|
+
removeWorker(index: number): Promise<void>
|
|
144
|
+
snapshot(): WorkerSnapshot<F>[]
|
|
145
|
+
get pending(): number
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**Example**
|
|
149
|
+
|
|
150
|
+
```ts
|
|
151
|
+
import { WorkflowDispatcher } from 'nfkit';
|
|
152
|
+
|
|
153
|
+
type Worker = (x: number) => Promise<string>;
|
|
154
|
+
|
|
155
|
+
const d = new WorkflowDispatcher<Worker>([
|
|
156
|
+
async (x) => `A:${x}`,
|
|
157
|
+
async (x) => `B:${x}`,
|
|
158
|
+
]);
|
|
159
|
+
|
|
160
|
+
const r1 = await d.dispatch(1);
|
|
161
|
+
const r2 = await d.dispatchSpecific(0, 2);
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### 4) `round-robin`
|
|
165
|
+
|
|
166
|
+
Simple round-robin picker.
|
|
167
|
+
|
|
168
|
+
**API**
|
|
169
|
+
|
|
170
|
+
```ts
|
|
171
|
+
class RoundRobin<T> {
|
|
172
|
+
constructor(items: T[]);
|
|
173
|
+
next(): T;
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**Example**
|
|
178
|
+
|
|
179
|
+
```ts
|
|
180
|
+
import { RoundRobin } from 'nfkit';
|
|
181
|
+
|
|
182
|
+
const rr = new RoundRobin(['a', 'b', 'c']);
|
|
183
|
+
rr.next(); // a
|
|
184
|
+
rr.next(); // b
|
|
185
|
+
rr.next(); // c
|
|
186
|
+
rr.next(); // a
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### 5) `abortable`
|
|
190
|
+
|
|
191
|
+
Wraps an object/function with an AbortSignal-aware proxy. After abort, access/calls throw (or reject for Promise flows).
|
|
192
|
+
|
|
193
|
+
**API**
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
class AbortedError extends Error {}
|
|
197
|
+
|
|
198
|
+
type AbortableOpts = {
|
|
199
|
+
boxPrimitives?: boolean;
|
|
200
|
+
noRecursive?: boolean;
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
abortable<T>(obj: T, signal: AbortSignal, opts?: AbortableOpts): T
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Example**
|
|
207
|
+
|
|
208
|
+
```ts
|
|
209
|
+
import { abortable } from 'nfkit';
|
|
210
|
+
|
|
211
|
+
const ac = new AbortController();
|
|
212
|
+
const obj = abortable({ n: 1 }, ac.signal);
|
|
213
|
+
|
|
214
|
+
obj.n; // 1
|
|
215
|
+
ac.abort('stop');
|
|
216
|
+
// later access throws AbortedError
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### 6) `middleware-dispatcher`
|
|
220
|
+
|
|
221
|
+
Generic middleware execution model: `(args..., next)`.
|
|
222
|
+
|
|
223
|
+
Includes 3 dispatchers:
|
|
224
|
+
|
|
225
|
+
- `DynamicMiddlewareDispatcher<F>`: override `buildMiddlewares`
|
|
226
|
+
- `MiddlewareDispatcher<F>`: direct array registration
|
|
227
|
+
- `ProtoMiddlewareDispatcher<A>`: middleware by instance prototype chain
|
|
228
|
+
|
|
229
|
+
**Core types/options**
|
|
230
|
+
|
|
231
|
+
```ts
|
|
232
|
+
type Middleware<F>
|
|
233
|
+
type MiddlewareNext<F>
|
|
234
|
+
type MiddlewareDispatcherOptions<F> = {
|
|
235
|
+
acceptResult?: (res) => boolean | Promise<boolean>;
|
|
236
|
+
errorHandler?: (e, args, next) => any;
|
|
237
|
+
};
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
**Example**
|
|
241
|
+
|
|
242
|
+
```ts
|
|
243
|
+
import { MiddlewareDispatcher } from 'nfkit';
|
|
244
|
+
|
|
245
|
+
type Handler = (x: number) => number;
|
|
246
|
+
const d = new MiddlewareDispatcher<Handler>();
|
|
247
|
+
|
|
248
|
+
d.middleware(async (x, next) => {
|
|
249
|
+
const r = await next();
|
|
250
|
+
return (r ?? 0) + 1;
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
d.middleware(async (x) => x * 10);
|
|
254
|
+
|
|
255
|
+
const out = await d.dispatch(2); // 21
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### 7) `i18n`
|
|
259
|
+
|
|
260
|
+
Middleware-based translation pipeline with built-in dictionary lookup middleware.
|
|
261
|
+
|
|
262
|
+
**API**
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
class I18n<Ex extends any[] = []> {
|
|
266
|
+
constructor(options: { locales: string[]; defaultLocale?: string });
|
|
267
|
+
middleware(mw: I18nMiddleware<Ex>, prior?: boolean): this;
|
|
268
|
+
removeMiddleware(mw: I18nMiddleware<Ex>): this;
|
|
269
|
+
getExactLocale(locale: string): string;
|
|
270
|
+
translateString(locale: string, text: string, ...ex: Ex): Promise<string>;
|
|
271
|
+
translate<T>(locale: string, obj: T, ...ex: Ex): Promise<T>;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
type I18nDictionary = Record<string, Record<string, string>>;
|
|
275
|
+
I18nLookupMiddleware(
|
|
276
|
+
dictOrFactory,
|
|
277
|
+
options?: { matchType?: 'exact' | 'hierarchy' | 'startsWith' },
|
|
278
|
+
)
|
|
279
|
+
createI18nLookupMiddleware<Ex>()
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
**Example**
|
|
283
|
+
|
|
284
|
+
```ts
|
|
285
|
+
import { I18n, I18nLookupMiddleware } from 'nfkit';
|
|
286
|
+
|
|
287
|
+
const i18n = new I18n({ locales: ['en', 'zh', 'zh-Hans'], defaultLocale: 'en' });
|
|
288
|
+
|
|
289
|
+
i18n.middleware(
|
|
290
|
+
I18nLookupMiddleware(
|
|
291
|
+
{
|
|
292
|
+
en: { hello: 'Hello' },
|
|
293
|
+
'zh-Hans': { hello: '你好' },
|
|
294
|
+
},
|
|
295
|
+
{ matchType: 'hierarchy' },
|
|
296
|
+
),
|
|
297
|
+
);
|
|
298
|
+
|
|
299
|
+
const s = await i18n.translateString('zh-Hans-CN', 'Say #{hello}');
|
|
300
|
+
// Say 你好
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### 8) `patch-string-in-object`
|
|
304
|
+
|
|
305
|
+
Deeply traverses an object graph and transforms all string values (async callback supported).
|
|
306
|
+
|
|
307
|
+
**API**
|
|
308
|
+
|
|
309
|
+
```ts
|
|
310
|
+
patchStringInObject<T>(
|
|
311
|
+
obj: T,
|
|
312
|
+
cb: (s: string) => string | Promise<string>,
|
|
313
|
+
): Promise<T>
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
**Example**
|
|
317
|
+
|
|
318
|
+
```ts
|
|
319
|
+
import { patchStringInObject } from 'nfkit';
|
|
320
|
+
|
|
321
|
+
const out = await patchStringInObject(
|
|
322
|
+
{ a: 'hello', nested: ['x', 'y'] },
|
|
323
|
+
(s) => s.toUpperCase(),
|
|
324
|
+
);
|
|
325
|
+
// { a: 'HELLO', nested: ['X', 'Y'] }
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### 9) `observe-diff`
|
|
329
|
+
|
|
330
|
+
Creates a proxy that reports `add/update/delete` changes on property writes/deletes.
|
|
331
|
+
|
|
332
|
+
**API**
|
|
333
|
+
|
|
334
|
+
```ts
|
|
335
|
+
observeDiff<T>(
|
|
336
|
+
obj: T,
|
|
337
|
+
cb: (change: {
|
|
338
|
+
type: 'add' | 'update' | 'delete';
|
|
339
|
+
key: keyof T;
|
|
340
|
+
oldValue: T[keyof T] | undefined;
|
|
341
|
+
newValue: T[keyof T] | undefined;
|
|
342
|
+
}) => any,
|
|
343
|
+
): T
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
**Example**
|
|
347
|
+
|
|
348
|
+
```ts
|
|
349
|
+
import { observeDiff } from 'nfkit';
|
|
350
|
+
|
|
351
|
+
const state = observeDiff<{ count?: number }>({}, (c) => {
|
|
352
|
+
console.log(c.type, c.key, c.oldValue, c.newValue);
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
state.count = 1; // add
|
|
356
|
+
state.count = 2; // update
|
|
357
|
+
delete state.count; // delete
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### 10) `memorize`
|
|
361
|
+
|
|
362
|
+
Per-instance memoization decorator for methods/getters.
|
|
363
|
+
|
|
364
|
+
**API**
|
|
365
|
+
|
|
366
|
+
```ts
|
|
367
|
+
Memorize(): MethodDecorator & PropertyDecorator
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
**Example**
|
|
371
|
+
|
|
372
|
+
```ts
|
|
373
|
+
import { Memorize } from 'nfkit';
|
|
374
|
+
|
|
375
|
+
class Svc {
|
|
376
|
+
calls = 0;
|
|
377
|
+
|
|
378
|
+
@Memorize()
|
|
379
|
+
expensive() {
|
|
380
|
+
this.calls += 1;
|
|
381
|
+
return Math.random();
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
> Requires TypeScript decorator support (for example `experimentalDecorators`).
|
|
387
|
+
|
|
388
|
+
### 11) `may-be-array`
|
|
389
|
+
|
|
390
|
+
Utility for handling `single value or array` input consistently.
|
|
391
|
+
|
|
392
|
+
**API**
|
|
393
|
+
|
|
394
|
+
```ts
|
|
395
|
+
type MayBeArray<T> = T | T[];
|
|
396
|
+
makeArray<T>(value: MayBeArray<T>): T[];
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
**Example**
|
|
400
|
+
|
|
401
|
+
```ts
|
|
402
|
+
import { makeArray } from 'nfkit';
|
|
403
|
+
|
|
404
|
+
makeArray(1); // [1]
|
|
405
|
+
makeArray([1, 2]); // [1, 2]
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### 12) `app-context`
|
|
409
|
+
|
|
410
|
+
Lightweight app context / DI-like container.
|
|
411
|
+
|
|
412
|
+
Supports:
|
|
413
|
+
|
|
414
|
+
- provider registration via `provide`
|
|
415
|
+
- context composition via `use`
|
|
416
|
+
- lifecycle initialization via `start`
|
|
417
|
+
- service lookup via `get/getAsync`
|
|
418
|
+
|
|
419
|
+
**Core API**
|
|
420
|
+
|
|
421
|
+
```ts
|
|
422
|
+
createAppContext<Req = Empty>(): AppContext<Empty, Req>
|
|
423
|
+
|
|
424
|
+
ctx.provide(ServiceClass, ...args?, options?)
|
|
425
|
+
ctx.use(otherCtx)
|
|
426
|
+
ctx.get(ServiceClass)
|
|
427
|
+
ctx.getAsync(ServiceClass)
|
|
428
|
+
ctx.define()
|
|
429
|
+
ctx.start()
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
**Type-driven IoC contract**
|
|
433
|
+
|
|
434
|
+
`provide()` is type constrained by `AppServiceClass`, whose constructor signature is:
|
|
435
|
+
|
|
436
|
+
```ts
|
|
437
|
+
new (ctx: AppContext<...>, ...args) => Service
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
That means the **first constructor parameter must be `ctx`**.
|
|
441
|
+
|
|
442
|
+
The type system also tracks context shape changes:
|
|
443
|
+
|
|
444
|
+
- `provide: 'name'` adds `ctx.name` as that service instance type.
|
|
445
|
+
- `merge: ['memberA', 'memberB']` maps selected members from service onto `ctx` with correct member types.
|
|
446
|
+
- `use(otherCtx)` merges provided/required context types across contexts.
|
|
447
|
+
- `start()` resolves to `never` at type level if required context (`Req`) is not satisfied.
|
|
448
|
+
|
|
449
|
+
Common `provide` options:
|
|
450
|
+
|
|
451
|
+
```ts
|
|
452
|
+
{
|
|
453
|
+
provide?: string; // expose service instance as ctx[prop]
|
|
454
|
+
merge?: string[]; // map selected service members onto ctx
|
|
455
|
+
useValue?: instance | Promise<instance>;
|
|
456
|
+
useFactory?: (ctx, ...args) => instance | Promise<instance>;
|
|
457
|
+
useClass?: Class;
|
|
458
|
+
}
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
`provide` vs `merge`:
|
|
462
|
+
|
|
463
|
+
- `provide`: exposes the whole service instance on context (for example `ctx.logger`).
|
|
464
|
+
- `merge`: exposes selected service members directly on context (for example `ctx.info` from `ctx.logger.info`).
|
|
465
|
+
|
|
466
|
+
Current runtime semantics:
|
|
467
|
+
|
|
468
|
+
- `ctx.provide/ctx.use` inside a provider constructor: newly added providers are settled after that constructor ends.
|
|
469
|
+
- `ctx.provide/ctx.use` inside `init()`: newly added providers are settled and initialized immediately after the current `init` ends.
|
|
470
|
+
- calling `provide/use` after `start()`: providers are queued; call `define()` to trigger settlement.
|
|
471
|
+
- `use(startedCtx)`: merges existing instances directly; no re-construction and no re-init.
|
|
472
|
+
|
|
473
|
+
**Example**
|
|
474
|
+
|
|
475
|
+
```ts
|
|
476
|
+
import { AppContext, createAppContext } from 'nfkit';
|
|
477
|
+
|
|
478
|
+
class LoggerService {
|
|
479
|
+
constructor(
|
|
480
|
+
public ctx: AppContext,
|
|
481
|
+
private prefix = '[app]',
|
|
482
|
+
) {}
|
|
483
|
+
|
|
484
|
+
logs: string[] = [];
|
|
485
|
+
|
|
486
|
+
info(s: string) {
|
|
487
|
+
this.logs.push(`${this.prefix} ${s}`);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
const app = await createAppContext()
|
|
492
|
+
// first constructor argument of provider class is always ctx
|
|
493
|
+
.provide(LoggerService, '[core]', {
|
|
494
|
+
provide: 'logger', // ctx.logger -> LoggerService
|
|
495
|
+
merge: ['info'], // ctx.info -> bound logger.info
|
|
496
|
+
})
|
|
497
|
+
.define()
|
|
498
|
+
.start();
|
|
499
|
+
|
|
500
|
+
app.logger.info('from instance');
|
|
501
|
+
app.info('from merged method');
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
### 13) `configurer`
|
|
505
|
+
|
|
506
|
+
Config helper for string-based configuration (env-style), with typed getters.
|
|
507
|
+
|
|
508
|
+
**API**
|
|
509
|
+
|
|
510
|
+
```ts
|
|
511
|
+
class Configurer<T extends Record<string, string>> {
|
|
512
|
+
constructor(defaultConfig: T);
|
|
513
|
+
loadConfig(options?: {
|
|
514
|
+
env?: Record<string, string | undefined>;
|
|
515
|
+
obj?: any;
|
|
516
|
+
}): ConfigurerInstance<T>;
|
|
517
|
+
generateExampleObject(): Record<string, unknown>;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
class ConfigurerInstance<T extends Record<string, string>> {
|
|
521
|
+
getString(key): string;
|
|
522
|
+
getInt(key): number;
|
|
523
|
+
getFloat(key): number;
|
|
524
|
+
getBoolean(key): boolean;
|
|
525
|
+
getStringArray(key): string[];
|
|
526
|
+
getIntArray(key): number[];
|
|
527
|
+
getFloatArray(key): number[];
|
|
528
|
+
getBooleanArray(key): boolean[];
|
|
529
|
+
getJSON<R>(key): R;
|
|
530
|
+
}
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
Merge priority:
|
|
534
|
+
|
|
535
|
+
`defaultConfig < obj < env`
|
|
536
|
+
|
|
537
|
+
**Example**
|
|
538
|
+
|
|
539
|
+
```ts
|
|
540
|
+
import { Configurer } from 'nfkit';
|
|
541
|
+
|
|
542
|
+
const cfg = new Configurer({ PORT: '3000', ENABLE_CACHE: '1' }).loadConfig({
|
|
543
|
+
env: { PORT: '8080' },
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
cfg.getInt('PORT'); // 8080
|
|
547
|
+
cfg.getBoolean('ENABLE_CACHE'); // true
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
### 14) `types`
|
|
551
|
+
|
|
552
|
+
Shared type exports:
|
|
553
|
+
|
|
554
|
+
```ts
|
|
555
|
+
type Awaitable<T> = T | Promise<T>;
|
|
556
|
+
type AnyClass = new (...args: any[]) => any;
|
|
557
|
+
type ClassType<T = any> = new (...args: any[]) => T;
|
|
558
|
+
interface Empty {}
|
|
559
|
+
type Prettify<T> = ...
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
## Notes
|
|
563
|
+
|
|
564
|
+
This README reflects the current implementation exported by `index.ts`.
|
|
565
|
+
If exports change in future versions, treat source/types as the final reference.
|