@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.
Files changed (2) hide show
  1. package/AGENTS.md +191 -0
  2. 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.6",
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,