@venizia/ignis-docs 0.2.0 → 0.2.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/README.md +14 -14
- package/content/best-practices/api-usage-examples.md +39 -19
- package/content/best-practices/architectural-patterns.md +22 -11
- package/content/best-practices/architecture-decisions.md +29 -16
- package/content/best-practices/code-style-standards/advanced-patterns.md +43 -31
- package/content/best-practices/code-style-standards/constants-configuration.md +19 -4
- package/content/best-practices/code-style-standards/control-flow.md +33 -1
- package/content/best-practices/code-style-standards/documentation.md +28 -8
- package/content/best-practices/code-style-standards/function-patterns.md +15 -4
- package/content/best-practices/code-style-standards/index.md +7 -2
- package/content/best-practices/code-style-standards/naming-conventions.md +26 -2
- package/content/best-practices/code-style-standards/route-definitions.md +9 -5
- package/content/best-practices/code-style-standards/tooling.md +14 -1
- package/content/best-practices/code-style-standards/type-safety.md +39 -6
- package/content/best-practices/common-pitfalls.md +59 -35
- package/content/best-practices/contribution-workflow.md +6 -2
- package/content/best-practices/data-modeling.md +78 -62
- package/content/best-practices/deployment-strategies.md +56 -19
- package/content/best-practices/error-handling.md +182 -93
- package/content/best-practices/index.md +6 -0
- package/content/best-practices/performance-optimization.md +26 -13
- package/content/best-practices/security-guidelines.md +35 -9
- package/content/best-practices/testing-strategies.md +7 -2
- package/content/best-practices/troubleshooting-tips.md +27 -17
- package/content/extensions/components/api-reference.md +107 -322
- package/content/extensions/components/authentication/api.md +454 -603
- package/content/extensions/components/authentication/errors.md +121 -498
- package/content/extensions/components/authentication/index.md +88 -801
- package/content/extensions/components/authentication/usage.md +207 -956
- package/content/extensions/components/authorization/api.md +736 -656
- package/content/extensions/components/authorization/errors.md +168 -206
- package/content/extensions/components/authorization/index.md +82 -797
- package/content/extensions/components/authorization/usage.md +194 -527
- package/content/extensions/components/health-check.md +71 -243
- package/content/extensions/components/mail/api.md +504 -287
- package/content/extensions/components/mail/errors.md +73 -61
- package/content/extensions/components/mail/index.md +96 -467
- package/content/extensions/components/mail/usage.md +130 -172
- package/content/extensions/components/request-tracker.md +66 -173
- package/content/extensions/components/socket-io/api.md +195 -13
- package/content/extensions/components/socket-io/errors.md +3 -3
- package/content/extensions/components/socket-io/index.md +50 -337
- package/content/extensions/components/socket-io/usage.md +143 -26
- package/content/extensions/components/static-asset/api.md +410 -142
- package/content/extensions/components/static-asset/errors.md +110 -53
- package/content/extensions/components/static-asset/index.md +79 -608
- package/content/extensions/components/static-asset/usage.md +180 -300
- package/content/extensions/components/websocket/api.md +275 -399
- package/content/extensions/components/websocket/errors.md +47 -56
- package/content/extensions/components/websocket/index.md +74 -407
- package/content/extensions/components/websocket/usage.md +110 -341
- package/content/extensions/helpers/cron/index.md +51 -160
- package/content/extensions/helpers/crypto/index.md +62 -483
- package/content/extensions/helpers/crypto/reference.md +456 -0
- package/content/extensions/helpers/env/index.md +60 -178
- package/content/extensions/helpers/error/index.md +221 -207
- package/content/extensions/helpers/inversion/index.md +65 -556
- package/content/extensions/helpers/inversion/reference.md +522 -0
- package/content/extensions/helpers/kafka/admin.md +20 -1
- package/content/extensions/helpers/kafka/compile-binary.md +41 -35
- package/content/extensions/helpers/kafka/consumer.md +54 -20
- package/content/extensions/helpers/kafka/examples.md +21 -16
- package/content/extensions/helpers/kafka/index.md +80 -610
- package/content/extensions/helpers/kafka/producer.md +134 -5
- package/content/extensions/helpers/kafka/schema-registry.md +45 -70
- package/content/extensions/helpers/logger/hf-logger.md +193 -0
- package/content/extensions/helpers/logger/index.md +64 -563
- package/content/extensions/helpers/logger/pino.md +85 -0
- package/content/extensions/helpers/logger/reference.md +746 -0
- package/content/extensions/helpers/network/api.md +241 -195
- package/content/extensions/helpers/network/index.md +72 -530
- package/content/extensions/helpers/queue/index.md +72 -900
- package/content/extensions/helpers/queue/reference.md +467 -0
- package/content/extensions/helpers/redis/index.md +73 -645
- package/content/extensions/helpers/redis/reference.md +727 -0
- package/content/extensions/helpers/secrets/index.md +66 -0
- package/content/extensions/helpers/socket-io/api.md +305 -203
- package/content/extensions/helpers/socket-io/index.md +66 -432
- package/content/extensions/helpers/storage/api.md +564 -462
- package/content/extensions/helpers/storage/index.md +77 -573
- package/content/extensions/helpers/types/index.md +66 -499
- package/content/extensions/helpers/types/reference.md +650 -0
- package/content/extensions/helpers/uid/index.md +58 -227
- package/content/extensions/helpers/websocket/api.md +329 -216
- package/content/extensions/helpers/websocket/index.md +65 -503
- package/content/extensions/helpers/worker-thread/index.md +58 -396
- package/content/extensions/helpers/worker-thread/reference.md +428 -0
- package/content/guides/core-concepts/persistent/models.md +1 -1
- package/content/guides/core-concepts/persistent/search-typesense.md +3 -3
- package/content/guides/core-concepts/persistent/transactions.md +1 -1
- package/content/guides/core-concepts/secrets-vault.md +177 -0
- package/content/guides/core-concepts/services.md +1 -1
- package/content/guides/migrations/redis-helpers-migration.md +1 -1
- package/content/guides/migrations/unified-connectors-migration.md +2 -2
- package/content/guides/tutorials/ecommerce-api.md +3 -8
- package/content/references/base/application.md +1 -1
- package/content/references/base/connectors.md +79 -136
- package/content/references/base/datasources-reference.md +599 -0
- package/content/references/base/datasources.md +84 -444
- package/content/references/base/dependency-injection.md +17 -39
- package/content/references/base/filter-system/application-usage.md +69 -121
- package/content/references/base/filter-system/array-operators.md +12 -0
- package/content/references/base/filter-system/comparison-operators.md +12 -0
- package/content/references/base/filter-system/default-filter.md +136 -348
- package/content/references/base/filter-system/fields-order-pagination.md +38 -16
- package/content/references/base/filter-system/index.md +106 -257
- package/content/references/base/filter-system/json-filtering.md +12 -2
- package/content/references/base/filter-system/list-operators.md +16 -2
- package/content/references/base/filter-system/logical-operators.md +13 -0
- package/content/references/base/filter-system/null-operators.md +13 -0
- package/content/references/base/filter-system/pattern-matching.md +12 -0
- package/content/references/base/filter-system/quick-reference.md +11 -2
- package/content/references/base/filter-system/range-operators.md +12 -0
- package/content/references/base/filter-system/tips.md +70 -133
- package/content/references/base/filter-system/use-cases.md +156 -233
- package/content/references/base/middlewares.md +35 -21
- package/content/references/base/models-reference.md +886 -0
- package/content/references/base/models.md +80 -1452
- package/content/references/base/repositories/advanced.md +156 -192
- package/content/references/base/repositories/index.md +77 -650
- package/content/references/base/repositories/mixins.md +22 -18
- package/content/references/base/repositories/relations.md +123 -171
- package/content/references/base/repositories/soft-deletable.md +58 -56
- package/content/references/base/secrets.md +263 -0
- package/content/references/base/services.md +2 -2
- package/content/references/configuration/environment-variables.md +48 -4
- package/content/references/configuration/index.md +49 -31
- package/content/references/quick-reference.md +3 -16
- package/content/references/utilities/crypto.md +35 -76
- package/content/references/utilities/date.md +33 -73
- package/content/references/utilities/index.md +1 -1
- package/content/references/utilities/jsx-reference.md +298 -0
- package/content/references/utilities/jsx.md +82 -525
- package/content/references/utilities/module.md +29 -62
- package/content/references/utilities/parse.md +34 -64
- package/content/references/utilities/performance.md +33 -58
- package/content/references/utilities/promise.md +28 -62
- package/content/references/utilities/request.md +57 -218
- package/content/references/utilities/schema.md +43 -137
- package/content/references/utilities/statuses-reference.md +361 -0
- package/content/references/utilities/statuses.md +63 -667
- package/package.json +8 -8
|
@@ -1,46 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## `validateModule`
|
|
8
|
-
|
|
9
|
-
Resolves each module name in sequence using `require.resolve`. If any module cannot be found it logs the failure and throws an `ApplicationError` with an install instruction. Returns a `Promise<void>` - it is async to support consistent `await` usage at call sites, though resolution itself is synchronous.
|
|
10
|
-
|
|
11
|
-
### Signature
|
|
12
|
-
|
|
13
|
-
```typescript
|
|
14
|
-
validateModule(opts: {
|
|
15
|
-
scope?: string;
|
|
16
|
-
modules: Array<string>;
|
|
17
|
-
}): Promise<void>
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
**Options**
|
|
21
|
-
|
|
22
|
-
| Option | Type | Default | Description |
|
|
23
|
-
|--------|------|---------|-------------|
|
|
24
|
-
| `modules` | `Array<string>` | `[]` | Module names to check. Evaluated in order - the first missing module stops the loop and throws. |
|
|
25
|
-
| `scope` | `string` | `''` | Human-readable label for the calling feature (e.g. the component or helper class name). Included in the error message to tell the developer which feature needs the package. |
|
|
1
|
+
---
|
|
2
|
+
title: Module Utility
|
|
3
|
+
description: Pre-flight check that fails fast with an install instruction when an optional peer dependency is missing
|
|
4
|
+
difficulty: beginner
|
|
5
|
+
lastUpdated: 2026-07-16
|
|
6
|
+
---
|
|
26
7
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
When a module is missing the thrown error reads:
|
|
30
|
-
|
|
31
|
-
```
|
|
32
|
-
[validateModule] <module> is required for <scope>. Please install '<module>'
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
If `scope` is omitted:
|
|
36
|
-
|
|
37
|
-
```
|
|
38
|
-
[validateModule] <module> is required. Please install '<module>'
|
|
39
|
-
```
|
|
8
|
+
# Module Utility
|
|
40
9
|
|
|
41
|
-
|
|
10
|
+
A pre-flight check for optional peer dependencies. IGNIS helpers and components often depend on packages that are not bundled with the framework (`@connectrpc/connect` for gRPC, `@hono/swagger-ui` for the Swagger component, and so on). Calling `validateModule` before a lazy `import()` throws a clear, actionable error instead of a cryptic "Cannot find module" crash.
|
|
42
11
|
|
|
43
|
-
|
|
12
|
+
## In one example
|
|
44
13
|
|
|
45
14
|
```typescript
|
|
46
15
|
import { validateModule } from '@venizia/ignis-helpers';
|
|
@@ -58,33 +27,31 @@ export class MyGrpcController extends BaseGrpcController {
|
|
|
58
27
|
}
|
|
59
28
|
```
|
|
60
29
|
|
|
61
|
-
|
|
30
|
+
## Functions
|
|
62
31
|
|
|
63
|
-
|
|
32
|
+
| Function | Signature | What it does |
|
|
33
|
+
|----------|-----------|---------------|
|
|
34
|
+
| `validateModule` | `validateModule(opts: { scope?: string; modules: Array<string> }): Promise<void>` | Resolves each module in `modules`, in order, via `require.resolve`. Throws an `ApplicationError` on the first one that cannot be found. |
|
|
64
35
|
|
|
65
|
-
|
|
66
|
-
import { validateModule } from '@venizia/ignis-helpers';
|
|
67
|
-
import { BaseHelper } from '@venizia/ignis-helpers';
|
|
36
|
+
## Error message format
|
|
68
37
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
modules: ['kafkajs', 'kafkajs-snappy'],
|
|
74
|
-
});
|
|
38
|
+
| `scope` | Message |
|
|
39
|
+
|---------|---------|
|
|
40
|
+
| provided | `[validateModule] <module> is required for <scope>. Please install '<module>'` |
|
|
41
|
+
| omitted | `[validateModule] <module> is required. Please install '<module>'` |
|
|
75
42
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
43
|
+
## Notes
|
|
44
|
+
|
|
45
|
+
- **Resolution is rooted at `process.cwd()/node_modules`** via Node's `createRequire`, so peer dependencies installed in the consuming application resolve correctly even though this utility ships inside `packages/helpers/dist/`.
|
|
46
|
+
- **Evaluated in order - first miss wins.** With multiple `modules`, the loop stops at the first unresolved one and throws; later entries are never checked.
|
|
47
|
+
- **`async` for call-site consistency only.** Resolution itself is synchronous (`require.resolve`); the function returns a `Promise<void>` so every call site can `await` it uniformly.
|
|
48
|
+
- **Call it once, at startup - not per request.** Place it in an initialisation hook (`configure`, `binding`, `boot`), before the guarded `import()`.
|
|
49
|
+
- **Recommended pattern:** declare the dependency as `peerDependenciesMeta` with `optional: true` in `package.json`, call `validateModule` at the top of the method that needs it, and pass the feature or class name as `scope` so the thrown message pinpoints the caller.
|
|
81
50
|
|
|
82
|
-
##
|
|
51
|
+
## See also
|
|
83
52
|
|
|
84
|
-
|
|
53
|
+
- [Utilities Overview](/references/utilities/) - all utility functions
|
|
85
54
|
|
|
86
|
-
|
|
87
|
-
2. Call `validateModule` at the top of the method that needs the package - before any `import()`.
|
|
88
|
-
3. Pass the feature or class name as `scope` so the error message pinpoints which feature triggered the check.
|
|
55
|
+
**Files:**
|
|
89
56
|
|
|
90
|
-
|
|
57
|
+
- [`packages/helpers/src/utilities/module.utility.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/utilities/module.utility.ts)
|
|
@@ -1,85 +1,55 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
---
|
|
2
|
+
title: Parse Utility
|
|
3
|
+
description: Type checking, safe numeric and boolean conversion, camelCase transforms, and array-to-map helpers
|
|
4
|
+
difficulty: beginner
|
|
5
|
+
lastUpdated: 2026-07-16
|
|
6
|
+
---
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
- **`isInt(n)`**: Checks if a value is an integer.
|
|
8
|
-
- **`isFloat(n)`**: Checks if a value is a float.
|
|
8
|
+
# Parse Utility
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
A collection of standalone functions for type checking, safe type conversion, and string/object/array transformation - the small helpers repositories and controllers reach for when normalizing loosely typed input.
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
- **`float(input, digit = 2)`**: Parses a value to a float, rounding to a specified number of digits. Handles strings with commas and defaults to `0` if the input is invalid.
|
|
14
|
-
- **`toBoolean(input)`**: Converts a value to a boolean. Returns `false` for empty string, `'false'`, `'0'`, `false`, `0`, `null`, and `undefined`. Returns `true` for everything else.
|
|
12
|
+
## In one example
|
|
15
13
|
|
|
16
14
|
```typescript
|
|
17
|
-
import { int, float, toBoolean } from '@venizia/ignis-helpers';
|
|
15
|
+
import { int, float, toBoolean, toCamel, keysToCamel } from '@venizia/ignis-helpers';
|
|
18
16
|
|
|
19
17
|
const myInt = int('1,000'); // => 1000
|
|
20
18
|
const myFloat = float('1,234.567', 2); // => 1234.57
|
|
21
19
|
const myBool = toBoolean('true'); // => true
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
## String and Object Transformation
|
|
25
|
-
|
|
26
|
-
- **`toCamel(s)`**: Converts a string from snake_case or kebab-case to camelCase.
|
|
27
|
-
- **`keysToCamel(object)`**: Recursively converts all keys in an object (and nested objects) to camelCase.
|
|
28
|
-
|
|
29
|
-
```typescript
|
|
30
|
-
import { toCamel, keysToCamel } from '@venizia/ignis-helpers';
|
|
31
|
-
|
|
32
|
-
const camelString = toCamel('my-snake_case-string');
|
|
33
|
-
// => 'mySnakeCaseString'
|
|
34
20
|
|
|
35
21
|
const camelObject = keysToCamel({ 'first-name': 'John', 'last_name': 'Doe' });
|
|
36
22
|
// => { firstName: 'John', lastName: 'Doe' }
|
|
37
23
|
```
|
|
38
24
|
|
|
39
|
-
##
|
|
25
|
+
## Functions
|
|
40
26
|
|
|
27
|
+
| Function | Signature | What it does |
|
|
28
|
+
|----------|-----------|---------------|
|
|
29
|
+
| `isInt` | `isInt(n: any): boolean` | `true` when `n` is (or coerces to) an integer. |
|
|
30
|
+
| `isFloat` | `isFloat(input: any): boolean` | `true` when `input` is (or coerces to) a non-integer number. |
|
|
31
|
+
| `int` | `int(input: any): number` | Parses `input` to an integer. Strips commas first; returns `0` for empty/invalid input. |
|
|
32
|
+
| `float` | `float(input: any, digit = 2): number` | Parses `input` to a float, rounded to `digit` places (via lodash `round`). Strips commas first; returns `0` for empty/invalid input. |
|
|
33
|
+
| `toBoolean` | `toBoolean(input: any): boolean` | `false` for `''`, `'false'`, `'0'`, `false`, `0`, `null`, `undefined`; `true` for everything else. |
|
|
34
|
+
| `toCamel` | `toCamel(s: string): string` | Converts a `snake_case` or `kebab-case` string to `camelCase`. |
|
|
35
|
+
| `keysToCamel` | `keysToCamel(object: object): any` | Recursively camelizes every key in `object`. Arrays stay arrays (their object elements are still camelized); `Date` values pass through untouched. |
|
|
36
|
+
| `parseArrayToMapWithKey` | `parseArrayToMapWithKey<T, K>(arr: T[], keyMap: K): Map<T[K], T>` | Turns an array of objects into a `Map` keyed by `keyMap`. Positional arguments, not an options object. Throws if `keyMap` is missing from an element; last element wins on duplicate keys. |
|
|
37
|
+
| `toDelimitedArray` | `toDelimitedArray(input: unknown, separator = ','): string[]` | Splits `input` on `separator` into trimmed, non-empty entries. `null`/`undefined` input returns `[]`. |
|
|
38
|
+
| `toTrimmed` | `toTrimmed(input: unknown): string` | Stringifies and trims `input`; `null`/`undefined` returns `''`. |
|
|
39
|
+
| `getUID` | `getUID(): string` | Generates a short, uppercase, `Math.random()`-based ID - not cryptographically unique. |
|
|
41
40
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
// US format (default) - comma is thousands separator
|
|
41
|
+
## Notes
|
|
45
42
|
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
- **`int`/`float` are comma-tolerant.** Both strip `,` before parsing, so `'1,000'` and `1000` behave the same - useful for user-typed numeric input.
|
|
44
|
+
- **`parseArrayToMapWithKey` breaks the options-object convention on purpose** - it takes `(arr, keyMap)` positionally, unlike every other function on this page.
|
|
45
|
+
- **`toDelimitedArray` and `toTrimmed` are the transform functions for list-shaped and string env values** - typical use is `applicationEnvironment.get(KEY, { transform: toDelimitedArray })`.
|
|
46
|
+
- **`getUID` is for short, human-glanceable identifiers**, not for anything that needs global uniqueness guarantees - use the [UID helper](/extensions/helpers/) (Snowflake-based) for that.
|
|
48
47
|
|
|
49
|
-
|
|
50
|
-
|--------|------|---------|-------------|
|
|
51
|
-
| `method` | `'int' \| 'float'` | `'int'` | Parse as integer or float |
|
|
52
|
-
| `locale` | `'us' \| 'eu'` | `'us'` | Number format locale |
|
|
48
|
+
## See also
|
|
53
49
|
|
|
54
|
-
|
|
50
|
+
- [Utilities Overview](/references/utilities/) - all utility functions
|
|
51
|
+
- [Schema Utility](/references/utilities/schema) - `snakeToCamel` for Zod schemas built on `toCamel`/`keysToCamel`
|
|
55
52
|
|
|
56
|
-
|
|
53
|
+
**Files:**
|
|
57
54
|
|
|
58
|
-
|
|
59
|
-
import { parseArrayToMapWithKey } from '@venizia/ignis-helpers';
|
|
60
|
-
|
|
61
|
-
const users = [
|
|
62
|
-
{ id: 1, name: 'Alice' },
|
|
63
|
-
{ id: 2, name: 'Bob' },
|
|
64
|
-
];
|
|
65
|
-
|
|
66
|
-
// Record (options object pattern)
|
|
67
|
-
// => { 1: { id: 1, name: 'Alice' }, 2: { id: 2, name: 'Bob' } }
|
|
68
|
-
|
|
69
|
-
// Map (positional arguments)
|
|
70
|
-
const usersMap = parseArrayToMapWithKey(users, 'id');
|
|
71
|
-
// => Map { 1 => { id: 1, name: 'Alice' }, 2 => { id: 2, name: 'Bob' } }
|
|
72
|
-
|
|
73
|
-
const user = usersMap.get(1);
|
|
74
|
-
// => { id: 1, name: 'Alice' }
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
## Unique ID
|
|
78
|
-
|
|
79
|
-
- **`getUID()`**: Generates a simple, short unique ID string based on `Math.random()`, returned in uppercase.
|
|
80
|
-
|
|
81
|
-
```typescript
|
|
82
|
-
import { getUID } from '@venizia/ignis-helpers';
|
|
83
|
-
|
|
84
|
-
const uniqueId = getUID(); // => e.g., 'A1B2C3D4'
|
|
85
|
-
```
|
|
55
|
+
- [`packages/helpers/src/utilities/parse.utility.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/utilities/parse.utility.ts)
|
|
@@ -1,79 +1,54 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
This is a higher-order function that wraps a task (a function), automatically logging its start time, end time, and total execution duration. Returns a Promise that resolves to the task's return value.
|
|
1
|
+
---
|
|
2
|
+
title: Performance Utility
|
|
3
|
+
description: Checkpoint-based timing and a logging wrapper for measuring execution duration
|
|
4
|
+
difficulty: beginner
|
|
5
|
+
lastUpdated: 2026-07-16
|
|
6
|
+
---
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
- `opts` (object):
|
|
12
|
-
- `logger` (Logger, optional): A logger instance to use for logging. Defaults to `console`.
|
|
13
|
-
- `level` (string, optional): The log level to use (e.g., `'debug'`, `'info'`). Defaults to `'debug'`.
|
|
14
|
-
- `description` (string, optional): A description of the task being measured. Defaults to `'Executing'`.
|
|
15
|
-
- `scope` (string): A scope to identify the context of the measurement.
|
|
16
|
-
- `task` (Function): The function to be executed and measured. Can be sync or async (wrapped with `Promise.resolve()`).
|
|
17
|
-
- `args` (any, optional): Arguments to include in the log output for debugging purposes. When provided, they are logged as JSON (`%j` format).
|
|
8
|
+
# Performance Utility
|
|
18
9
|
|
|
19
|
-
|
|
10
|
+
Functions for measuring and logging how long a code block takes to run, built on `performance.now()` (millisecond resolution). `BaseApplication` uses `executeWithPerformanceMeasure` internally to time component, controller, and datasource registration during startup.
|
|
20
11
|
|
|
21
|
-
|
|
12
|
+
## In one example
|
|
22
13
|
|
|
23
14
|
```typescript
|
|
24
|
-
// Inside BaseApplication class
|
|
25
15
|
import { executeWithPerformanceMeasure } from '@venizia/ignis-helpers';
|
|
26
16
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
// ... logic to register components
|
|
36
|
-
},
|
|
37
|
-
});
|
|
38
|
-
}
|
|
17
|
+
await executeWithPerformanceMeasure({
|
|
18
|
+
logger: this.logger,
|
|
19
|
+
scope: this.registerComponents.name,
|
|
20
|
+
description: 'Register application components',
|
|
21
|
+
task: async () => {
|
|
22
|
+
// ... logic to register components
|
|
23
|
+
},
|
|
24
|
+
});
|
|
39
25
|
```
|
|
40
26
|
|
|
41
|
-
When `registerComponents` is called, it will produce log output similar to this:
|
|
42
|
-
|
|
43
27
|
```
|
|
44
28
|
[RegisterComponents] START | Register application components ...
|
|
45
29
|
[RegisterComponents] DONE | Register application components | Took: 12.3456 (ms)
|
|
46
30
|
```
|
|
47
31
|
|
|
48
|
-
|
|
32
|
+
## Functions
|
|
49
33
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
34
|
+
| Function | Signature | What it does |
|
|
35
|
+
|----------|-----------|---------------|
|
|
36
|
+
| `executeWithPerformanceMeasure` | `executeWithPerformanceMeasure<R>(opts: { logger?: ILogger; level?: string; description?: string; args?: any; scope: string; task: Function }): Promise<R>` | Runs `task` (sync or async), logging a `START` line before and a `DONE` line after with the elapsed time. Resolves to whatever `task` returns. |
|
|
37
|
+
| `getPerformanceCheckpoint` | `getPerformanceCheckpoint(): number` | Returns `performance.now()` - a starting timestamp to pass to `getExecutedPerformance`. |
|
|
38
|
+
| `getExecutedPerformance` | `getExecutedPerformance(opts: { from: number; digit?: number }): number` | Elapsed milliseconds since `from`, rounded to `digit` places (default `6`). |
|
|
54
39
|
|
|
55
|
-
##
|
|
40
|
+
## Notes
|
|
56
41
|
|
|
57
|
-
|
|
42
|
+
- **Defaults:** `logger` falls back to `console`, `level` to `'debug'`, `description` to `'Executing'`.
|
|
43
|
+
- **`args`, when provided, are logged as JSON (`%j`)** on both the `START` and `DONE` lines - handy for correlating a specific call's timing.
|
|
44
|
+
- **`task` is wrapped in `Promise.resolve()`**, so a plain synchronous function works exactly like an `async` one.
|
|
45
|
+
- **Prefer the checkpoint pair for granular, multi-point measurements** inside a single function, where wrapping the whole thing in `executeWithPerformanceMeasure` would not isolate the segment you care about.
|
|
58
46
|
|
|
59
|
-
|
|
60
|
-
- **`getExecutedPerformance(opts)`**: Calculates the elapsed time in milliseconds since a given checkpoint. Rounds to 6 decimal places by default.
|
|
61
|
-
- `opts.from` (number): The starting checkpoint from `getPerformanceCheckpoint()`.
|
|
62
|
-
- `opts.digit` (number, optional): Number of decimal places for rounding. Defaults to `6`.
|
|
47
|
+
## See also
|
|
63
48
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
```typescript
|
|
67
|
-
import { getPerformanceCheckpoint, getExecutedPerformance } from '@venizia/ignis-helpers';
|
|
49
|
+
- [Utilities Overview](/references/utilities/) - all utility functions
|
|
50
|
+
- [Logger](/extensions/helpers/logger/) - the `ILogger` type accepted by `executeWithPerformanceMeasure`
|
|
68
51
|
|
|
69
|
-
|
|
52
|
+
**Files:**
|
|
70
53
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const duration = getExecutedPerformance({ from: start });
|
|
74
|
-
console.log(`The work took ${duration} ms.`);
|
|
75
|
-
|
|
76
|
-
// With custom precision
|
|
77
|
-
const preciseDuration = getExecutedPerformance({ from: start, digit: 2 });
|
|
78
|
-
console.log(`The work took ${preciseDuration} ms.`);
|
|
79
|
-
```
|
|
54
|
+
- [`packages/helpers/src/utilities/performance.utility.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/utilities/performance.utility.ts)
|
|
@@ -1,19 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
---
|
|
2
|
+
title: Promise Utility
|
|
3
|
+
description: Concurrency-limited task execution plus small Promise and object-path helpers
|
|
4
|
+
difficulty: beginner
|
|
5
|
+
lastUpdated: 2026-07-16
|
|
6
|
+
---
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
### `executePromiseWithLimit(opts)`
|
|
8
|
+
# Promise Utility
|
|
10
9
|
|
|
11
|
-
-
|
|
12
|
-
- `tasks` (Array<() => Promise<T>>): An array of functions that each return a Promise.
|
|
13
|
-
- `limit` (number): The maximum number of promises to execute in parallel.
|
|
14
|
-
- `onTaskDone` (<R>(opts: { result: R }) => ValueOrPromise<void>, optional): A callback function that is executed whenever a task is completed (specifically, when the concurrency limit is reached and a task finishes to make room).
|
|
10
|
+
Helper functions for working with Promises - bounding concurrency, normalizing thrown values, type-guarding thenables, reading nested object paths, and firing-and-forgetting async work safely.
|
|
15
11
|
|
|
16
|
-
|
|
12
|
+
## In one example
|
|
17
13
|
|
|
18
14
|
```typescript
|
|
19
15
|
import { executePromiseWithLimit, sleep } from '@venizia/ignis-helpers';
|
|
@@ -22,67 +18,37 @@ const tasks = [
|
|
|
22
18
|
() => sleep(1000).then(() => 'Task 1 done'),
|
|
23
19
|
() => sleep(500).then(() => 'Task 2 done'),
|
|
24
20
|
() => sleep(1200).then(() => 'Task 3 done'),
|
|
25
|
-
() => sleep(800).then(() => 'Task 4 done'),
|
|
26
21
|
];
|
|
27
22
|
|
|
28
|
-
console.log('Starting tasks with a limit of 2...');
|
|
29
|
-
|
|
30
23
|
const results = await executePromiseWithLimit({
|
|
31
24
|
tasks,
|
|
32
25
|
limit: 2,
|
|
33
|
-
onTaskDone: ({ result }) =>
|
|
34
|
-
console.log('A task finished:', result);
|
|
35
|
-
},
|
|
26
|
+
onTaskDone: ({ result }) => console.log('A task finished:', result),
|
|
36
27
|
});
|
|
37
|
-
|
|
38
|
-
console.log('All tasks finished:', results);
|
|
39
28
|
```
|
|
40
29
|
|
|
41
|
-
##
|
|
30
|
+
## Functions
|
|
42
31
|
|
|
43
|
-
|
|
32
|
+
| Function | Signature | What it does |
|
|
33
|
+
|----------|-----------|---------------|
|
|
34
|
+
| `executePromiseWithLimit` | `executePromiseWithLimit<T>(opts: { tasks: Array<() => Promise<T>>; limit: number; onTaskDone?: <R>(opts: { result: R }) => ValueOrPromise<void> }): Promise<T[]>` | Runs `tasks` with at most `limit` running concurrently. Calls `onTaskDone` each time the limit is hit and a slot frees up. Throws if `limit` is not a positive integer. |
|
|
35
|
+
| `toError` | `toError(error: unknown): Error` | Normalizes a `catch`-block value into an `Error` - passes an existing `Error` through, wraps anything else with `new Error(String(error))`. |
|
|
36
|
+
| `isPromiseLike` | `isPromiseLike<T>(value: T \| PromiseLike<T>): value is PromiseLike<T>` | Type guard: `true` when `value` is non-null and has a callable `.then`. |
|
|
37
|
+
| `getDeepProperty` | `getDeepProperty<T, V>(obj: T, path: string): V` | Reads a dot-separated `path` off `obj`. Throws if any intermediate segment is `null`/`undefined`. |
|
|
38
|
+
| `voidExecution` | `voidExecution(opts: { logger?: ILogger; scope: string; execution: ValueOrPromise<unknown> }): void` | Fire-and-forget: if `execution` is a Promise, routes a rejection to `logger.for(scope).error(...)` (or `console.error` without a logger) instead of an unhandled rejection. Synchronous values pass through untouched. |
|
|
44
39
|
|
|
45
|
-
|
|
46
|
-
import { toError } from '@venizia/ignis-helpers';
|
|
40
|
+
## Notes
|
|
47
41
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
console.error(error.message);
|
|
53
|
-
}
|
|
54
|
-
```
|
|
42
|
+
- **`executePromiseWithLimit` validates `limit` eagerly** - a non-integer or a value below `1` throws immediately, before any task runs.
|
|
43
|
+
- **`onTaskDone` only fires under backpressure.** It runs when the number of in-flight tasks reaches `limit` and `Promise.race` resolves one of them - not after every task.
|
|
44
|
+
- **`voidExecution` exists because `BaseHelper` cannot carry `protected` members** on classes the container instantiates anonymously (TS4094) - it is a standalone function, not a helper method, precisely so factory-built controllers can still use it.
|
|
45
|
+
- **`getDeepProperty` throws, it does not return `undefined`**, on a missing intermediate segment - wrap the call if you need optional-path semantics instead.
|
|
55
46
|
|
|
56
|
-
##
|
|
47
|
+
## See also
|
|
57
48
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
```typescript
|
|
61
|
-
import { isPromiseLike } from '@venizia/ignis-helpers';
|
|
49
|
+
- [Utilities Overview](/references/utilities/) - all utility functions
|
|
50
|
+
- [Date Utility](/references/utilities/date) - `sleep()`, used to build the tasks in the example above
|
|
62
51
|
|
|
63
|
-
|
|
64
|
-
const b = 2;
|
|
52
|
+
**Files:**
|
|
65
53
|
|
|
66
|
-
|
|
67
|
-
// This will run
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (isPromiseLike(b)) {
|
|
71
|
-
// This will not run
|
|
72
|
-
}
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
## `getDeepProperty`
|
|
76
|
-
|
|
77
|
-
Traverses a dot-separated property path on an object and returns the value. It throws an error if any intermediate part of the path is null or undefined.
|
|
78
|
-
|
|
79
|
-
```typescript
|
|
80
|
-
import { getDeepProperty } from '@venizia/ignis-helpers';
|
|
81
|
-
|
|
82
|
-
const obj = { a: { b: { c: 'hello' } } };
|
|
83
|
-
|
|
84
|
-
const value = getDeepProperty(obj, 'a.b.c'); // => 'hello'
|
|
85
|
-
|
|
86
|
-
// Throws: Cannot read property 'x' of undefined
|
|
87
|
-
getDeepProperty(obj, 'a.x.y');
|
|
88
|
-
```
|
|
54
|
+
- [`packages/helpers/src/utilities/promise.utility.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/helpers/src/utilities/promise.utility.ts)
|