av6-utils 1.0.0 → 1.0.1
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 +132 -203
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,234 +1,163 @@
|
|
|
1
|
-
#
|
|
1
|
+
# av6-utils
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Utilities shared across AV6 Node.js services, covering billing calculations, audit diffing, data-shaping helpers, and reusable regex patterns. Distributed as both CommonJS and ES modules with full TypeScript definitions.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
- **Typed billing engine** for line-level and master-level price breakdowns with rounding, discount, tax, and co-pay rules.
|
|
6
|
+
- **Audit helpers** that flatten nested payloads and report field-level changes.
|
|
7
|
+
- **General-purpose helpers** for safe object access, numeric casting, regex lookups, templating, and more.
|
|
8
|
+
- **Tree-shakable build** powered by `tsup`, shipping `dist/` bundles plus `.d.ts`.
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
- **Caching Support**: Built-in Redis caching for improved performance
|
|
9
|
-
- **Excel Import/Export**: Seamless Excel file handling for data import and export
|
|
10
|
-
- **Pagination**: Built-in pagination for search results
|
|
11
|
-
- **DTO Mapping**: Support for Data Transfer Object mapping
|
|
12
|
-
- **Type Safety**: Written in TypeScript with comprehensive type definitions
|
|
13
|
-
- **UIN Config Management**: Unique Identification Number generation with configurable segments and automatic reset policies
|
|
10
|
+
---
|
|
14
11
|
|
|
15
12
|
## Installation
|
|
16
13
|
|
|
17
14
|
```bash
|
|
18
|
-
npm install av6-
|
|
15
|
+
npm install av6-utils
|
|
16
|
+
# or
|
|
17
|
+
pnpm add av6-utils
|
|
19
18
|
```
|
|
20
19
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
To use the library, you need to provide the necessary dependencies:
|
|
26
|
-
|
|
27
|
-
```typescript
|
|
28
|
-
import { commonService, Deps } from 'av6-core';
|
|
29
|
-
import { PrismaClient } from '@prisma/client';
|
|
30
|
-
import winston from 'winston';
|
|
31
|
-
import { AsyncLocalStorage } from 'async_hooks';
|
|
32
|
-
|
|
33
|
-
// Initialize dependencies
|
|
34
|
-
const deps: Deps = {
|
|
35
|
-
config: {
|
|
36
|
-
REDIS_PREFIX: 'your-prefix:',
|
|
37
|
-
CACHE_KEY_NAME: 'your-cache-key'
|
|
38
|
-
},
|
|
39
|
-
mapper: {
|
|
40
|
-
dtoMapping: {}, // Your DTO mapping functions
|
|
41
|
-
mappingExport: {}, // Your export mapping functions
|
|
42
|
-
mappingImport: {}, // Your import mapping functions
|
|
43
|
-
},
|
|
44
|
-
helpers: {
|
|
45
|
-
generateErrorMessage: (type, ...variables) => {
|
|
46
|
-
// Your error message generation logic
|
|
47
|
-
},
|
|
48
|
-
ErrorHandler: class ErrorHandler extends Error {
|
|
49
|
-
// Your error handler implementation
|
|
50
|
-
}
|
|
51
|
-
},
|
|
52
|
-
logger: winston.createLogger({
|
|
53
|
-
// Your logger configuration
|
|
54
|
-
}),
|
|
55
|
-
cacheAdapter: {
|
|
56
|
-
// Your cache adapter implementation
|
|
57
|
-
},
|
|
58
|
-
requestStorage: new AsyncLocalStorage(),
|
|
59
|
-
db: new PrismaClient()
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
// Initialize the service
|
|
63
|
-
const service = commonService(deps);
|
|
20
|
+
### Importing
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { calculateBillingFromChildren, findDifferences, customOmit, getPattern, RoundFormat } from "av6-utils";
|
|
64
24
|
```
|
|
65
25
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
});
|
|
26
|
+
The package exposes named exports only; pick the pieces you need for optimal bundling.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Helper Utilities (`src/utils/helper.utils.ts`)
|
|
31
|
+
|
|
32
|
+
| Function | Purpose |
|
|
33
|
+
| -------------------------------------- | --------------------------------------------------------------------------------- |
|
|
34
|
+
| `customOmit(obj, keys)` | Returns `{ rest, omitted }`, splitting an object by keys. |
|
|
35
|
+
| `getDynamicValue(obj, "path.to.leaf")` | Safely walks dot-notation paths, returning `null` when a segment is missing. |
|
|
36
|
+
| `objectTo2DArray(obj, maxCols)` | Converts key/value pairs into rows with a configurable maximum number of columns. |
|
|
37
|
+
| `toNumberOrNull(value)` | Attempts to coerce to `number`, returning `null` if it fails. |
|
|
38
|
+
| `getPattern[name]` | Registry of common regex patterns (emails, SKU, UUID, file extensions, etc.). |
|
|
39
|
+
| `interpolate(template, vars)` | Basic `{{ placeholder }}` string interpolation. |
|
|
40
|
+
|
|
41
|
+
Example:
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
const { rest, omitted } = customOmit({ id: 1, secret: "x" }, ["secret"]);
|
|
45
|
+
const licenseValid = getPattern.licenseTitle.test("AV6 License - 23");
|
|
46
|
+
const greeting = interpolate("Hi {{ user }}!", { user: "Ani" });
|
|
85
47
|
```
|
|
86
48
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Billing Calculation Utilities (`src/utils/calculation.utils.ts`)
|
|
52
|
+
|
|
53
|
+
Two main exports power healthcare/commerce billing logic:
|
|
54
|
+
|
|
55
|
+
- `calculateSingleChild(input, coPayMode, options)` – processes one line item.
|
|
56
|
+
- `calculateBillingFromChildren(inputs, masterExtra, options)` – aggregates children, applies master-level discounts, and rounds headers.
|
|
57
|
+
|
|
58
|
+
Key capabilities:
|
|
59
|
+
|
|
60
|
+
- Supports **percentage or absolute discounts**, **inclusive/exclusive/none** tax methods, and **step-wise vs final** rounding.
|
|
61
|
+
- Handles **co-pay** via `PERCENTAGE-AMOUNT` or `EXCLUSIVE-INCLUSIVE` strategies.
|
|
62
|
+
- Provides fine-grained control over rounding via `RoundFormat` and `precision`.
|
|
63
|
+
|
|
64
|
+
Example:
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
import { calculateBillingFromChildren, RoundFormat } from "av6-utils";
|
|
68
|
+
|
|
69
|
+
const result = calculateBillingFromChildren(
|
|
70
|
+
[
|
|
71
|
+
{ qty: 2, rate: 500, discountMode: "PERCENTAGE", discountValue: 10, taxMethod: "EXCLUSIVE", taxValue: 5 },
|
|
72
|
+
{ qty: 1, rate: 1200, coPaymentType: "PERCENTAGE", coPayValue: 50 },
|
|
73
|
+
],
|
|
74
|
+
{ mode: "AMOUNT", value: 150, coPayMode: "PERCENTAGE-AMOUNT" },
|
|
75
|
+
{ calculationMethod: "STEP_WISE", lineRound: RoundFormat.TO_FIXED, precision: 2 }
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
console.log(result.master.netAmount);
|
|
101
79
|
```
|
|
102
80
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
tableName: 'user'
|
|
123
|
-
}
|
|
124
|
-
});
|
|
81
|
+
All related TypeScript types (`ChildCalcInput`, `MasterAdditionalDiscount`, `ChildCalculated`, `BillingCalcResult`, etc.) are exported from `src/types/calculation.ts` for end-to-end typing.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Audit Utilities (`src/utils/audit.utils.ts`)
|
|
86
|
+
|
|
87
|
+
`findDifferences(obj1, obj2)` flattens nested objects, normalizes dates to `YYYY-MM-DD`, and returns an array of `CreateTransaction` entries detailing changes:
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
import { findDifferences } from "av6-utils";
|
|
91
|
+
|
|
92
|
+
const changes = findDifferences(
|
|
93
|
+
{ patient: { name: "Ava", dob: "1990-01-01" }, active: true },
|
|
94
|
+
{ patient: { name: "Ava Smith", dob: "1990-01-01" }, active: false }
|
|
95
|
+
);
|
|
96
|
+
// [
|
|
97
|
+
// { field: "patient name", changedFrom: "Ava", changedTo: "Ava Smith" },
|
|
98
|
+
// { field: "active", changedFrom: "true", changedTo: "false" }
|
|
99
|
+
// ]
|
|
125
100
|
```
|
|
126
101
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
generateErrorMessage: (type, ...variables) => {
|
|
140
|
-
// Your error message generation logic
|
|
141
|
-
},
|
|
142
|
-
ErrorHandler: class ErrorHandler extends Error {
|
|
143
|
-
// Your error handler implementation
|
|
144
|
-
}
|
|
145
|
-
},
|
|
146
|
-
logger: winston.createLogger({
|
|
147
|
-
// Your logger configuration
|
|
148
|
-
}),
|
|
149
|
-
cacheAdapter: {
|
|
150
|
-
// Your cache adapter implementation
|
|
151
|
-
},
|
|
152
|
-
requestStorage: new AsyncLocalStorage(),
|
|
153
|
-
db: new PrismaClient(),
|
|
154
|
-
prisma: PrismaNamespace,
|
|
155
|
-
shortCode: 'UIN_CONFIG',
|
|
156
|
-
cacheKey: 'uin-config'
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
// Initialize the UIN Config service
|
|
160
|
-
const uinService = uinConfigService(uinDeps);
|
|
161
|
-
|
|
162
|
-
// Create a new UIN Config
|
|
163
|
-
const newUinConfig = await uinService.createUINConfig({
|
|
164
|
-
shortCode: UinShortCode.INVOICE,
|
|
165
|
-
seqResetPolicy: UIN_RESET_POLICY.monthly,
|
|
166
|
-
description: 'Invoice number generator',
|
|
167
|
-
uinSegments: [
|
|
168
|
-
{ order: 1, type: 'text', value: 'INV-' },
|
|
169
|
-
{ order: 2, type: 'dateFormat', value: 'YYYYMM' },
|
|
170
|
-
{ order: 3, type: 'separator', value: '-' },
|
|
171
|
-
{ order: 4, type: 'sequenceNo', minSeqLength: 5 }
|
|
172
|
-
]
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
// Generate a UIN preview
|
|
176
|
-
const uinPreview = await uinService.previewUIN({
|
|
177
|
-
uinSegments: [
|
|
178
|
-
{ order: 1, type: 'text', value: 'INV-' },
|
|
179
|
-
{ order: 2, type: 'dateFormat', value: 'YYYYMM' },
|
|
180
|
-
{ order: 3, type: 'separator', value: '-' },
|
|
181
|
-
{ order: 4, type: 'sequenceNo', minSeqLength: 5 }
|
|
182
|
-
]
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
// Get a UIN Config by ID
|
|
186
|
-
const uinConfig = await uinService.getUINConfigById(1);
|
|
187
|
-
|
|
188
|
-
// Generate a new UIN
|
|
189
|
-
const generatedUin = await uinService.generateUIN(UinShortCode.INVOICE);
|
|
102
|
+
Supporting types live in `src/types/helper.ts`.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Messages (`src/enums/message.enums.ts`)
|
|
107
|
+
|
|
108
|
+
`SuccessMessageType` and `ErrorMessageType` centralize template strings for UI or API responses. Example:
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
import { SuccessMessageType } from "av6-utils/dist/enums/message.enums.js";
|
|
112
|
+
|
|
113
|
+
const message = SuccessMessageType.CREATED.replace("%1", "Patient");
|
|
190
114
|
```
|
|
191
115
|
|
|
192
|
-
|
|
116
|
+
> Note: enums are emitted into `dist/enums` by TypeScript. Adjust your import path or add an explicit re-export if using them frequently.
|
|
117
|
+
|
|
118
|
+
---
|
|
193
119
|
|
|
194
|
-
|
|
120
|
+
## Project Structure
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
src/
|
|
124
|
+
├─ utils/
|
|
125
|
+
│ ├─ helper.utils.ts
|
|
126
|
+
│ ├─ calculation.utils.ts
|
|
127
|
+
│ └─ audit.utils.ts
|
|
128
|
+
├─ enums/
|
|
129
|
+
│ └─ message.enums.ts
|
|
130
|
+
└─ types/
|
|
131
|
+
├─ calculation.ts
|
|
132
|
+
└─ helper.ts
|
|
133
|
+
dist/
|
|
134
|
+
└─ index.(js|mjs|d.ts|d.mts) # Generated by tsup
|
|
135
|
+
```
|
|
195
136
|
|
|
196
|
-
|
|
137
|
+
---
|
|
197
138
|
|
|
198
|
-
|
|
199
|
-
- `dropdownSearch`: Search records for dropdown components
|
|
200
|
-
- `fixedSearch`: Search with fixed criteria
|
|
201
|
-
- `fixedSearchWoPaginationService`: Search with fixed criteria without pagination
|
|
202
|
-
- `commonExcelService`: Generate Excel workbooks
|
|
203
|
-
- `fetch`: Fetch a specific record by ID
|
|
204
|
-
- `commonExcelImport`: Import data from Excel files
|
|
205
|
-
- `commonExcelExport`: Export data to Excel files
|
|
206
|
-
- `delete`: Delete a record
|
|
207
|
-
- `updateStatus`: Update the status of a record
|
|
208
|
-
- `fetchImageStream`: Fetch an image as a stream
|
|
139
|
+
## Development
|
|
209
140
|
|
|
210
|
-
|
|
141
|
+
```bash
|
|
142
|
+
npm install # install deps
|
|
143
|
+
npm run build # format *.ts files, then bundle via tsup (CJS+ESM+d.ts)
|
|
144
|
+
```
|
|
211
145
|
|
|
212
|
-
|
|
146
|
+
- TypeScript config targets ES2022 with path alias `@/* → src/*`.
|
|
147
|
+
- `tsup.config.ts` emits both module formats and cleans `dist/` on each build.
|
|
148
|
+
- Prettier (installed as a dependency) keeps source formatting consistent.
|
|
213
149
|
|
|
214
|
-
|
|
215
|
-
- `updateUINConfig`: Update an existing UIN configuration
|
|
216
|
-
- `getUINConfigById`: Retrieve a UIN configuration by ID
|
|
217
|
-
- `getAllUINConfig`: Retrieve all UIN configurations
|
|
218
|
-
- `deleteUINConfig`: Delete a UIN configuration
|
|
219
|
-
- `generateUIN`: Generate a new UIN based on a shortcode
|
|
220
|
-
- `previewUIN`: Preview a UIN based on segment configuration
|
|
150
|
+
---
|
|
221
151
|
|
|
222
|
-
|
|
152
|
+
## Versioning & Publishing Checklist
|
|
223
153
|
|
|
224
|
-
|
|
154
|
+
1. Update `package.json` version and changelog notes (if any).
|
|
155
|
+
2. `npm run build` to refresh `dist/`.
|
|
156
|
+
3. Optionally run a smoke test by importing the built `dist/index.js`.
|
|
157
|
+
4. `npm publish` from the package root (`packages/node-utils`).
|
|
225
158
|
|
|
226
|
-
|
|
227
|
-
- `objectTo2DArray`: Convert an object to a 2D array
|
|
228
|
-
- `toRelativeImageUrl`: Convert an absolute path to a relative image URL
|
|
159
|
+
---
|
|
229
160
|
|
|
230
161
|
## License
|
|
231
162
|
|
|
232
|
-
ISC
|
|
233
|
-
|
|
234
|
-
|
|
163
|
+
Licensed under the ISC License. © Aniket Sarkar.
|