diff --git a/README.md b/README.md index e639a7e..0d221b3 100644 --- a/README.md +++ b/README.md @@ -1,139 +1,213 @@ # artemis-kit -A comprehensive TypeScript/JavaScript utility library focused on precision and efficiency. +TypeScript/JavaScript utility library. Tree-shakeable, split exports per module. -## Features +**Install:** `pnpm install @warkypublic/artemis-kit` -### String Tools +--- -- Advanced string manipulation -- Pattern matching and validation -- Text transformation utilities -- Unicode handling -- i18n support +## Modules -### Blob Tools - -- Blob creation and modification -- Binary data handling -- Stream processing -- MIME type management - -### File Conversion Tools - -- Format conversions -- File type transformations -- Encoding/decoding utilities -- Batch processing capabilities - -### Data Queue Tools - -- Efficient data processing -- Batch operations support - -### DOM - -- DOM shortcuts like opening file links - -### LLM - -- LLM tools for text processing and generation - -## Installation - -```bash -pnpm install @warkypublic/artemis-kit +### `strings` +```ts +import { ... } from "@warkypublic/artemis-kit/strings" ``` -## Usage/Import examples +| Function | Signature | Description | +|---|---|---| +| `trimLeft` | `(str, chars?, times?)` | Trim chars from left, Unicode-safe | +| `trimRight` | `(str, chars?, times?)` | Trim chars from right, Unicode-safe | +| `replaceStr` | `(str, search, replace)` | Replace first occurrence | +| `replaceStrAll` | `(str, search, replace)` | Replace all occurrences | +| `initCaps` | `(sentence)` | Capitalize first letter of each word | +| `titleCase` | `(sentence)` | Title case, skips articles/conjunctions | +| `camelCase` | `(sentence)` | Convert to camelCase | +| `snakeCase` | `(sentence)` | Convert to snake_case | +| `reverseSnakeCase` | `(sentence)` | snake_case → camelCase | +| `splitCamelCase` | `(sentence)` | camelCase → space-separated words | +| `formatNumber` | `(value, locale, options?)` | Locale-aware number formatting via `Intl` | +| `formatCurrency` | `(value, locale, currency)` | Locale-aware currency formatting | +| `formatDate` | `(date, locale, options?)` | Locale-aware date formatting | +| `formatRelativeTime` | `(value, unit, locale)` | Relative time e.g. "2 days ago" | +| `formatPercent` | `(value, locale, decimals?)` | Locale-aware percent formatting | +| `formatUnit` | `(value, unit, locale)` | Locale-aware unit formatting | +| `formatList` | `(items, locale, type?)` | Locale-aware list formatting | +| `getPlural` | `(count, locale, forms)` | Plural form selection via `Intl.PluralRules` | +| `compareStrings` | `(str1, str2, locale)` | Locale-aware string comparison | +| `parseNumberWords` | `(text, locale)` | Word to digit ("two" → 2), supports en-US/af-ZA | +| `handleBiDi` | `(text)` | Wrap text in Unicode BiDi markers | +| `humanFileSize` | `(bytes)` | Bytes to human-readable size | +| `getUUID` | `()` | UUID via `crypto.randomUUID()` with timestamp fallback | +| `newUUID` | `()` | UUID via `uuid` v4 | +| `blankValue` | `(...args)` | First non-blank value (skips null/undefined/0/""/[]/\{\}) | +| `inop` | `(...args)` | Check if value exists in array or matches value | +| `iinop` | `(...args)` | Case-insensitive `inop` | +| `clarionIntToTime` | `(val, detail?)` | Clarion int → time string HH:MM:SS | +| `clarionTimeToInt` | `(timeStr)` | Time string → Clarion int | +| `clarionClock` | `()` | Current time as Clarion centiseconds since midnight | +| `clarionDateToInt` | `(date)` | JS Date → Clarion date int (days since 1800-12-28) | +| `clarionIntToDate` | `(days)` | Clarion date int → JS Date | +| `clarionDateStringToInt` | `(dateStr)` | "YYYY-MM-DD" or "MM/DD/YYYY" → Clarion int | +| `clarionIntToDateString` | `(days, format?)` | Clarion int → date string, format: `'iso'`\|`'us'` | -```typescript -import { getNestedValue } from "@warkypublic/artemis-kit/object"; -import { NestedQueue } from "@warkypublic/artemis-kit/dataqueue"; -import { camelCase, formatPercent } from "@warkypublic/artemis-kit/strings"; -import { - b64DecodeUnicode, - b64EncodeUnicode, -} from "@warkypublic/artemis-kit/base64"; +--- + +### `base64` +```ts +import { ... } from "@warkypublic/artemis-kit/base64" ``` -## Available Methods +| Function | Signature | Description | +|---|---|---| +| `b64EncodeUnicode` | `(str)` | UTF-8 safe base64 encode | +| `b64DecodeUnicode` | `(str)` | UTF-8 safe base64 decode | +| `base64ToBlob` | `(base64, mimeType)` | Base64 string → Blob | +| `blobToBase64` | `(blob)` | Blob → base64 string | +| `FileToBase64` | `(file)` | File → base64 string | +| `FileToBlob` | `(file)` | File → Blob | +| `BlobToString` | `(blob)` | Blob → string | -### Strings +--- -- trimLeft -- trimRight -- replaceStr -- replaceStrAll -- formatNumber -- formatCurrency -- formatDate -- getPlural -- formatPercent -- titleCase -- initCaps -- camelCase -- snakeCase -- reverseSnakeCase -- splitCamelCase -- humanFileSize -- getUUID -- newUUID -- blankValue -- ... +### `object` +```ts +import { ... } from "@warkypublic/artemis-kit/object" +``` -### i18n +| Function | Signature | Description | +|---|---|---| +| `getNestedValue` | `(path, obj)` | Get value by dot-notation path, supports bracket notation | +| `setNestedValue` | `(path, value, obj)` | Set value by dot-notation path, auto-creates intermediates | +| `objectCompare` | `(obj, objToCompare, deep?)` | Shallow or deep object equality | +| `createSelectOptions` | `(obj, options?)` | Object → `[{label, value}]` array for select components | -- createI18nManager -- \_t -- \_tt -- ... +--- -### Base64 +### `dataqueue` +```ts +import { NestedQueue, EnhancedNestedQueue } from "@warkypublic/artemis-kit/dataqueue" +``` -- b64DecodeUnicode -- b64EncodeUnicode -- base64ToBlob -- blobToBase64 -- FileToBase64 -- FileToBlob -- BlobToString +`NestedQueue` — reactive array store with middleware and persistence. -### Object +| Method | Signature | Description | +|---|---|---| +| `add` | `(item, path?)` | Append item, optionally to nested array at path | +| `remove` | `(path)` | Remove item at dot-notation index path | +| `update` | `(path, value)` | Merge partial update at path | +| `get` | `(path)` | Get value at path | +| `getAll` | `()` | Get full data array | +| `search` | `(query, options?)` | Search by string or object pattern | +| `filter` | `(predicate, options?)` | Filter with optional deep traversal | +| `findOne` | `(predicate)` | First matching item | +| `sort` | `(key, options?)` | Sort by key, supports deep/nested sorting | +| `clear` | `()` | Empty the queue | +| `subscribe` | `(callback)` | Subscribe to changes, returns unsubscribe fn | +| `clearPersistence` | `()` | Clear persistence adapter storage | -- getNestedValue -- setNestedValue -- objectCompare -- createSelectOptions +**Constructor options:** +```ts +new NestedQueue(initialData?, { + persistence?: PersistenceAdapter, // { save, load, clear } + middleware?: Middleware[], // { beforeAction?, afterAction? } + autoload?: boolean // auto-load from persistence on init +}) +``` -### Queue +`EnhancedNestedQueue` extends `NestedQueue` with an `ActiveRecordBuffer` — access via `.getBuffer()`. -- NestedQueue +--- -### Dom +### `i18n` +```ts +import { i18n, _t, _tt } from "@warkypublic/artemis-kit/i18n" +``` -- openFileLink +LRU memory cache + IndexedDB persistence, auto-fetches from server on miss/version mismatch. -### Mime +| Export | Type | Description | +|---|---|---| +| `_t` | `(id, default?)` | Sync lookup (returns default if not cached) | +| `_tt` | `(id, default?)` | Async lookup (fetches from server if missing) | +| `i18n.configure` | `(options)` | Set `apiUrl`, `maxCacheSize`, `cacheTTL` | +| `i18n.registerStrings` | `(strings, version)` | Pre-load translations | +| `i18n.clearCache` | `()` | Clear memory + IndexedDB cache | +| `i18n.getCacheStats` | `()` | `{ memorySize, dbSize, hits, misses }` | -- getExtFromMime -- getExtFromFilename -- getMimeFromExt -- isValidExtForMime -- getAllExtensionsForMime +**Configure:** +```ts +i18n.configure({ apiUrl: "/api/translations", maxCacheSize: 1000, cacheTTL: 86400000 }) +``` -### LLM +--- -These are still work in progress. +### `mime` +```ts +import { ... } from "@warkypublic/artemis-kit/mime" +``` -## Requests +| Function | Signature | Description | +|---|---|---| +| `getExtFromMime` | `(mime)` | MIME type → primary extension | +| `getMimeFromExt` | `(ext)` | Extension → MIME type | +| `getExtFromFilename` | `(filename)` | Filename → extension | +| `isValidExtForMime` | `(mime, ext)` | Validate extension against MIME type | +| `getAllExtensionsForMime` | `(mime)` | All valid extensions for MIME type | -Requests are welcome! Please read our contributing guidelines and send me a message on Discord or add a github issue. +--- -## Contributing +### `dom` +```ts +import { openFileLink } from "@warkypublic/artemis-kit/dom" +``` -Contributions are welcome! Please read our contributing guidelines before submitting PRs. +| Function | Signature | Description | +|---|---|---| +| `openFileLink` | `(url)` | Trigger file download via hidden anchor click (browser only) | -## License +--- -MIT +### `promise` +```ts +import { ... } from "@warkypublic/artemis-kit/promise" +``` + +| Function | Signature | Description | +|---|---|---| +| `WaitUntil` | `(condition, options?)` | Poll until condition returns true, throws on timeout | +| `debounce` | `(fn, wait)` | Debounce function by ms | +| `throttle` | `(fn, limit)` | Throttle function by ms | +| `measureTime` | `(fn)` | Measure async fn execution: `{ result, duration }` | + +**`WaitUntil` options:** `{ timeout?: number (default 5000), interval?: number (default 100) }` + +--- + +### `logger` +```ts +import { createLogger } from "@warkypublic/artemis-kit/logger" +``` + +```ts +const logger = createLogger() +logger.error(message, data?) +logger.warn(message, data?) +logger.info(message, data?) +logger.debug(message, data?) +logger.registerPlugin({ name, onLog: async (entry) => void }) +``` + +Plugin `entry`: `{ timestamp: Date, level: 'ERROR'|'WARN'|'INFO'|'DEBUG', message: string, data?: unknown }` + +--- + +### `llm` +```ts +import { OpenAPI } from "@warkypublic/artemis-kit/llm" +``` + +| Function | Signature | Description | +|---|---|---| +| `OpenAPI.getTextCompletion` | `({ prompt, options? })` | OpenAI-compatible text completion | + +**Options:** `{ url?, apiKey?, maxTokens?, temperature?, topP?, n?, stream?, stop? }`