@arkyn/shared 3.0.6 → 3.0.8
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/AGENTS.md +191 -0
- package/package.json +2 -1
package/AGENTS.md
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# @arkyn/shared — agent guide
|
|
2
|
+
|
|
3
|
+
Framework-agnostic formatting, validation, generation, and parsing utilities, safe to import in both client and server code (no React/Remix assumptions). Reach for it whenever you need to format/parse dates, currency, Brazilian documents, phone numbers, generate IDs/slugs, or mask sensitive data, instead of writing ad-hoc regex or `Intl` calls. Everything below is exact — signatures, defaults, and throw behavior — read directly from source, no need to open README.md or any other file for correct usage.
|
|
4
|
+
|
|
5
|
+
## Required setup
|
|
6
|
+
|
|
7
|
+
- ESM only: `import`, never `require()`.
|
|
8
|
+
- No required peer deps. `libphonenumber-js` is an optional peer dep, only needed for `formatToPhone` and `findCountryMask`.
|
|
9
|
+
- `formatToCurrency` takes a currency code (e.g. `"BRL"`, `"USD"`) that must exist in `@arkyn/templates`'s `countryCurrencies`, otherwise it throws.
|
|
10
|
+
|
|
11
|
+
## Import convention — always prefer subpath imports
|
|
12
|
+
|
|
13
|
+
Prefer importing each function from its own subpath instead of the root barrel (`@arkyn/shared`):
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { formatToCpf } from "@arkyn/shared/formatToCpf";
|
|
17
|
+
import { generateSlug } from "@arkyn/shared/generateSlug";
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Naming rule**: the subpath is always the export name, unchanged (every export here already starts with a lowercase letter, so this is just `@arkyn/shared/<exportName>`) — no casing transformation needed, unlike `@arkyn/components`. This is exact for every export in this package; each entry below states its own import line. There are no per-export CSS files in this package (no UI).
|
|
21
|
+
|
|
22
|
+
## Formats
|
|
23
|
+
|
|
24
|
+
#### formatDate
|
|
25
|
+
- Import: `import { formatDate } from "@arkyn/shared/formatDate";`
|
|
26
|
+
- Signature: `formatDate([date, time = "00:00:00"]: string[], inputFormat: "brazilianDate" | "isoDate" | "timestamp", outputFormat: string, timezone: number = 0): string`
|
|
27
|
+
- Formats a date (and optional time) string into a custom output format string (e.g. `"YYYY-MM-DD hh:mm"`). Calculations run in UTC+0; `timezone` shifts the result by that many hours. Throws if the input format string is unrecognized or the resulting date is invalid.
|
|
28
|
+
```typescript
|
|
29
|
+
formatDate(["25/12/2023", "15:30:00"], "brazilianDate", "YYYY-MM-DD hh:mm"); // "2023-12-25 15:30"
|
|
30
|
+
formatDate(["2023-12-25", "15:30:00"], "timestamp", "DD/MM/YYYY hh:mm", -3); // "2023-12-25 12:30"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
#### formatToCpf
|
|
34
|
+
- Import: `import { formatToCpf } from "@arkyn/shared/formatToCpf";`
|
|
35
|
+
- Signature: `formatToCpf(value: string): string`
|
|
36
|
+
- Formats to `XXX.XXX.XXX-XX`. Throws if the cleaned input isn't exactly 11 digits. `formatToCpf("12345678909")` → `"123.456.789-09"`.
|
|
37
|
+
|
|
38
|
+
#### formatToCnpj
|
|
39
|
+
- Import: `import { formatToCnpj } from "@arkyn/shared/formatToCnpj";`
|
|
40
|
+
- Signature: `formatToCnpj(value: string): string`
|
|
41
|
+
- Formats to `XX.XXX.XXX/XXXX-XX`. Throws if the cleaned input isn't exactly 14 digits. `formatToCnpj("12345678000195")` → `"12.345.678/0001-95"`.
|
|
42
|
+
|
|
43
|
+
#### formatToCep
|
|
44
|
+
- Import: `import { formatToCep } from "@arkyn/shared/formatToCep";`
|
|
45
|
+
- Signature: `formatToCep(value: string): string`
|
|
46
|
+
- Formats to `XXXXX-XXX`. Throws if the cleaned input isn't exactly 8 digits. `formatToCep("12345678")` → `"12345-678"`.
|
|
47
|
+
|
|
48
|
+
#### formatToCurrency
|
|
49
|
+
- Import: `import { formatToCurrency } from "@arkyn/shared/formatToCurrency";`
|
|
50
|
+
- Signature: `formatToCurrency(value: number, currency: keyof typeof countryCurrencies, config?: { showPrefix?: boolean }): string`
|
|
51
|
+
- Locale-aware currency string via `Intl.NumberFormat`, resolving locale/currency from `@arkyn/templates`'s `countryCurrencies`. `config.showPrefix` defaults to `true`; set `false` to strip the currency symbol. Throws `"Unsupported currency code"` if `currency` isn't a key in `countryCurrencies`.
|
|
52
|
+
```typescript
|
|
53
|
+
formatToCurrency(1234.56, "BRL"); // "R$ 1.234,56"
|
|
54
|
+
formatToCurrency(1234.56, "USD", { showPrefix: false }); // "1,234.56"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
#### formatToPhone
|
|
58
|
+
- Import: `import { formatToPhone } from "@arkyn/shared/formatToPhone";`
|
|
59
|
+
- Signature: `formatToPhone(phoneNumber: string): string`
|
|
60
|
+
- Requires peer dependency: `libphonenumber-js`.
|
|
61
|
+
- Formats an E.164 phone number using the country mask from `@arkyn/templates`. Throws if the number is invalid or no mask is found. `formatToPhone("+5534920524282")` → `"(34) 92052-4282"`.
|
|
62
|
+
|
|
63
|
+
#### formatToCapitalizeFirstWordLetter
|
|
64
|
+
- Import: `import { formatToCapitalizeFirstWordLetter } from "@arkyn/shared/formatToCapitalizeFirstWordLetter";`
|
|
65
|
+
- Signature: `formatToCapitalizeFirstWordLetter(sentence: string): string`
|
|
66
|
+
- Capitalizes the first letter of each space-separated word, lowercases the rest. `"HELLO WORLD"` → `"Hello World"`.
|
|
67
|
+
|
|
68
|
+
#### formatToEllipsis
|
|
69
|
+
- Import: `import { formatToEllipsis } from "@arkyn/shared/formatToEllipsis";`
|
|
70
|
+
- Signature: `formatToEllipsis(text: string, maxLength: number): string`
|
|
71
|
+
- Truncates to `maxLength` without breaking mid-word, appends `"..."` if truncated. `formatToEllipsis("Hello, world!", 5)` → `"Hello..."`.
|
|
72
|
+
|
|
73
|
+
#### formatToHiddenDigits
|
|
74
|
+
- Import: `import { formatToHiddenDigits } from "@arkyn/shared/formatToHiddenDigits";`
|
|
75
|
+
- Signature: `formatToHiddenDigits(value: string, options?: { range?: number | [number, number]; hider?: string }): string`
|
|
76
|
+
- Replaces digit positions with a mask character, non-digits untouched. `options.range`: positive number = first N digits, negative = last N digits, `[start, end]` tuple = 1-indexed inclusive range. Defaults: `range: 3`, `hider: "*"`.
|
|
77
|
+
```typescript
|
|
78
|
+
formatToHiddenDigits("123-456-7890", { range: 3 }); // "***-456-7890"
|
|
79
|
+
formatToHiddenDigits("123-456-7890", { range: [4, 6], hider: "#" }); // "123-###-7890"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
#### formatJsonObject
|
|
83
|
+
- Import: `import { formatJsonObject } from "@arkyn/shared/formatJsonObject";`
|
|
84
|
+
- Signature: `formatJsonObject(value: unknown, indent?: number): string`
|
|
85
|
+
- Pretty-prints a JSON-compatible value (object/array/string/primitive) with indentation; strings that parse as JSON are recursively formatted too.
|
|
86
|
+
|
|
87
|
+
#### formatJsonString
|
|
88
|
+
- Import: `import { formatJsonString } from "@arkyn/shared/formatJsonString";`
|
|
89
|
+
- Signature: `formatJsonString(jsonString: string): string`
|
|
90
|
+
- Parses a JSON string and pretty-prints it. Throws if the input isn't valid JSON.
|
|
91
|
+
|
|
92
|
+
## Generators
|
|
93
|
+
|
|
94
|
+
#### generateId
|
|
95
|
+
- Import: `import { generateId } from "@arkyn/shared/generateId";`
|
|
96
|
+
- Signature: `generateId(type: "text", format: "v4" | "v7"): string` / `generateId(type: "binary", format: "v4" | "v7"): Uint8Array`
|
|
97
|
+
- Generates a UUID. `type` picks the representation (`"text"` string or `"binary"` `Uint8Array`), `format` picks `v4` (random) or `v7` (time-ordered, sortable). Throws `"Invalid type or format"` for any other combination.
|
|
98
|
+
|
|
99
|
+
#### generateSlug
|
|
100
|
+
- Import: `import { generateSlug } from "@arkyn/shared/generateSlug";`
|
|
101
|
+
- Signature: `generateSlug(rawString: string): string`
|
|
102
|
+
- URL-friendly slug: strips accents, removes non-alphanumeric chars (keeps spaces/hyphens), lowercases, spaces → hyphens, collapses/trims hyphens. `"Hello, World!"` → `"hello-world"`.
|
|
103
|
+
|
|
104
|
+
#### generateColorByString
|
|
105
|
+
- Import: `import { generateColorByString } from "@arkyn/shared/generateColorByString";`
|
|
106
|
+
- Signature: `generateColorByString(rawString: string): string`
|
|
107
|
+
- Deterministic hex color derived from a hash of the input; same input always produces the same color. Useful for stable avatar/tag colors keyed by name/id.
|
|
108
|
+
|
|
109
|
+
## Parsers
|
|
110
|
+
|
|
111
|
+
#### parseToDate
|
|
112
|
+
- Import: `import { parseToDate } from "@arkyn/shared/parseToDate";`
|
|
113
|
+
- Signature: `parseToDate([date, time = "00:00:00"]: string[], inputFormat: "brazilianDate" | "isoDate" | "timestamp", timezone: number = 0): Date`
|
|
114
|
+
- Same input contract as `formatDate` but returns a `Date` object instead of a formatted string. Throws under the same conditions.
|
|
115
|
+
|
|
116
|
+
#### parseLargeFields
|
|
117
|
+
- Import: `import { parseLargeFields } from "@arkyn/shared/parseLargeFields";`
|
|
118
|
+
- Signature: `parseLargeFields(jsonString: string, maxLength: number = 1000): string`
|
|
119
|
+
- Parses JSON and replaces any string field longer than `maxLength` with `"To large information: field as {length} characters"`, recursing into nested objects/arrays. Throws if input isn't valid JSON.
|
|
120
|
+
|
|
121
|
+
#### parseSensitiveData
|
|
122
|
+
- Import: `import { parseSensitiveData } from "@arkyn/shared/parseSensitiveData";`
|
|
123
|
+
- Signature: `parseSensitiveData(jsonString: string, sensitiveKeys: string[] = ["password", "confirmPassword", "creditCard"]): string`
|
|
124
|
+
- Parses JSON and replaces the value of every matching key (recursively, including JSON-encoded string values) with `"****"`. Unlike the other parsers, this one does **not** throw on invalid JSON — it returns the original string unchanged. Safe to call on arbitrary log/debug payloads.
|
|
125
|
+
|
|
126
|
+
## Utilities
|
|
127
|
+
|
|
128
|
+
#### calculateCardInstallment
|
|
129
|
+
- Import: `import { calculateCardInstallment } from "@arkyn/shared/calculateCardInstallment";`
|
|
130
|
+
- Signature: `calculateCardInstallment(props: { cashPrice: number; numberInstallments: number; fees?: number }): { totalPrice: number; installmentPrice: number }`
|
|
131
|
+
- Compound-interest installment math. `fees` defaults to `0.0349` (3.49%); no interest applied when `fees === 0` or `numberInstallments === 1`. Throws if `numberInstallments <= 0` or `fees < 0`.
|
|
132
|
+
```typescript
|
|
133
|
+
calculateCardInstallment({ cashPrice: 1000, numberInstallments: 12, fees: 0.02 });
|
|
134
|
+
// { totalPrice: 1124.62, installmentPrice: 93.72 }
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
#### findCountryMask
|
|
138
|
+
- Import: `import { findCountryMask } from "@arkyn/shared/findCountryMask";`
|
|
139
|
+
- Signature: `findCountryMask(phoneNumber: string): [mask: string, country: CountryType]`
|
|
140
|
+
- Requires peer dependency: `libphonenumber-js`.
|
|
141
|
+
- Resolves the phone mask (`"_"` placeholders) and `@arkyn/templates` `CountryType` metadata for an E.164 number. Picks the mask matching the number's digit count for countries with multiple valid lengths (e.g. Brazil with/without the ninth digit). Throws if invalid or no mask found.
|
|
142
|
+
|
|
143
|
+
#### ensureQuotes
|
|
144
|
+
- Import: `import { ensureQuotes } from "@arkyn/shared/ensureQuotes";`
|
|
145
|
+
- Signature: `ensureQuotes(rawValue: string): string`
|
|
146
|
+
- Wraps in double quotes unless already single- or double-quoted.
|
|
147
|
+
|
|
148
|
+
#### isHtml
|
|
149
|
+
- Import: `import { isHtml } from "@arkyn/shared/isHtml";`
|
|
150
|
+
- Signature: `isHtml(rawString: string): boolean`
|
|
151
|
+
- Case-insensitive check for HTML opening/closing tags.
|
|
152
|
+
|
|
153
|
+
#### stripHtmlTags
|
|
154
|
+
- Import: `import { stripHtmlTags } from "@arkyn/shared/stripHtmlTags";`
|
|
155
|
+
- Signature: `stripHtmlTags(rawHtml: string): string`
|
|
156
|
+
- Removes HTML tags, including `<script>`/`<style>` blocks and comments.
|
|
157
|
+
|
|
158
|
+
#### removeCurrencySymbols
|
|
159
|
+
- Import: `import { removeCurrencySymbols } from "@arkyn/shared/removeCurrencySymbols";`
|
|
160
|
+
- Signature: `removeCurrencySymbols(rawString: string): string`
|
|
161
|
+
- Strips `R$`, `$`, `€`, `¥`, `£`, and other Unicode currency symbols, trims whitespace.
|
|
162
|
+
|
|
163
|
+
#### removeNonNumeric
|
|
164
|
+
- Import: `import { removeNonNumeric } from "@arkyn/shared/removeNonNumeric";`
|
|
165
|
+
- Signature: `removeNonNumeric(rawString: string): string`
|
|
166
|
+
- Strips every non-digit character.
|
|
167
|
+
|
|
168
|
+
## Services
|
|
169
|
+
|
|
170
|
+
#### ValidateDateService
|
|
171
|
+
- Import: `import { ValidateDateService } from "@arkyn/shared/validateDateService";`
|
|
172
|
+
- Used internally by `formatDate`/`parseToDate`. Use directly only for standalone date-part validation:
|
|
173
|
+
- `validateDateParts(year: number, month: number, day: number): void` — throws on invalid month/day ranges, month-specific day counts, or non-leap-year Feb 29.
|
|
174
|
+
- `validateInputFormat(format: string): void` — throws unless `format` is `"brazilianDate"`, `"isoDate"`, or `"timestamp"`.
|
|
175
|
+
|
|
176
|
+
## Quick example
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
import { formatToCpf } from "@arkyn/shared/formatToCpf";
|
|
180
|
+
import { formatToCurrency } from "@arkyn/shared/formatToCurrency";
|
|
181
|
+
import { generateSlug } from "@arkyn/shared/generateSlug";
|
|
182
|
+
|
|
183
|
+
formatToCpf("12345678909"); // "123.456.789-09"
|
|
184
|
+
formatToCurrency(1234.56, "BRL"); // "R$ 1.234,56"
|
|
185
|
+
generateSlug("Hello, World!"); // "hello-world"
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Related packages
|
|
189
|
+
|
|
190
|
+
- `@arkyn/templates` — supplies the currency/locale and country-mask data `formatToCurrency`/`formatToPhone`/`findCountryMask` depend on.
|
|
191
|
+
- `@arkyn/components` and `@arkyn/server` — both use this package internally; prefer importing these utilities directly rather than duplicating formatting/validation logic in app code.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arkyn/shared",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.8",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"module": "./dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"files": [
|
|
36
36
|
"dist",
|
|
37
37
|
"README.md",
|
|
38
|
+
"AGENTS.md",
|
|
38
39
|
"LICENSE.txt"
|
|
39
40
|
],
|
|
40
41
|
"sideEffects": false,
|