Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,113 @@
# @suaveplan/utils — Specification
**Package:** `@suaveplan/utils`
**Version at graduation:** `0.1.0`
**Layer:** Universal — zero browser/React/Node-specific APIs
**Published:** 2026-04-20
---
## Purpose
Zero-external-dependency utility library covering debugging, object manipulation, platform detection, IEEE 754 float packing, pseudo-random selection, email normalization, audio sprite management, string utilities, hex validation, and byte-size enforcement.
---
## Modules
### `./errors`
- `UtilsError` — typed `SuaveplanError<UtilsCode>` subclass
- `UTILS_CODES` — stable code registry keyed by dot-path
- `UtilsCode` — union type of all code values
### `./debug`
- `assertDefined<T>(val, message?)` — throws if val is null/undefined
- `invariant(condition, message?)` — throws if condition is false
- `unreachable(message?)` — always throws (exhaustiveness check)
- `assert(condition, message?)` — alias for invariant
### `./object`
- `isObject(value)` / `isPlainObject(value)` / `isObjectOrArray(value)` / `isEmpty(obj)`
- `deepMerge(a, b, skipUndefined?)` / `deepMergeAll(...objects)`
- `pick(obj, keys)` / `omit(obj, keys)` / `keepKeys` / `removeKeys`
- `flattenObject(obj, prefix?, separator?)`
- `getNestedValue(obj, path, default?)` / `setNestedValue(obj, path, value)` / `hasPath(obj, path)`
- `deepClone(obj)`
### `./platform`
- `isBrowser()` / `isNode()` / `isBun()` / `isEdge()`
- `isSSR()` / `supportsWebWorkers()` / `supportsServiceWorkers()`
- `getPlatform()` — returns `"browser" | "node" | "bun" | "edge" | "unknown"`
### `./number`
- Constants: `min16`, `max16`, `min32`, `max32`, `min64`, `max64`
- `packFloat16(v)` / `unpackFloat16(buf)` — IEEE 754 half-precision
- `packFloat32(v)` / `unpackFloat32(buf)` — IEEE 754 single-precision
- `packFloat64(v)` / `unpackFloat64(buf)` — IEEE 754 double-precision
- `isInFloat16Range(v)` / `isInFloat32Range(v)` / `isInFloat64Range(v)`
### `./random`
- `pseudoRandom<T>(arr, index, seed?, opts?)` — deterministic element selection
### `./email`
- `normalizeEmail(email)` — provider-aware canonicalization (Gmail/Yahoo/Microsoft/generic)
### `./sound`
- `parseSoundVariations(sprites)` — group `<name>_<n>` keys by base name
- `getSoundKey(name, variations)` — random variation selection; throws `SOUND.NO_VARIATIONS`
- `convertSprites(sprites)` — alias for `parseSoundVariations`
- Types: `SoundSprites`, `SoundVariations`
### `./string`
- `generateId(opts?)` — random hex identifier via `crypto.randomUUID()`
- `parseTextWithLinks(text)` — extract HTTP/HTTPS URLs → `TextLink[]`
- Types: `GenerateIdOptions`, `TextLink`
### `./validate`
- `isHex(i)` — type-guard: non-empty, even-length, hex-only string
### `./validation`
- Constants: `SIZE_LIMITS`, `DEFAULT_MAX_MESSAGE_SIZE`
- `getDataSize(data)` — UTF-8 bytes for string, byteLength for binary, 8 for number
- `validateSize(data, maxSize?)` — throws `VALIDATION.SIZE_EXCEEDED`
- `isWithinSizeLimit(data, maxSize?)` — non-throwing boolean
- `formatSize(bytes, decimals?)` — `"1.50 KB"` format
- `parseSize(str)` — `"1.5MB"` → integer bytes; throws `VALIDATION.PARSE_FAILED`
- `truncateToSize(data, maxSize)` — binary-search string truncation
---
## Error Codes
| Code | Description |
|------|-------------|
| `UTILS/OBJECT.PROTOTYPE_POLLUTION` | `__proto__` / constructor key detected |
| `UTILS/OBJECT.CIRCULAR` | Circular reference in deepClone |
| `UTILS/NUMBER.OUT_OF_RANGE` | Float value outside target precision range |
| `UTILS/RANDOM.EMPTY_ARRAY` | pseudoRandom called with empty array |
| `UTILS/RANDOM.INDEX_OUT_OF_BOUNDS` | index >= array.length |
| `UTILS/VALIDATION.SIZE_EXCEEDED` | Data exceeds maxSize bytes |
| `UTILS/VALIDATION.PARSE_FAILED` | Invalid size string format |
| `UTILS/PLATFORM.UNAVAILABLE` | Requested platform feature unavailable |
| `UTILS/SOUND.NO_VARIATIONS` | getSoundKey called for unknown sound name |
---
## Quality Gates (at ship)
- Istanbul coverage: 100% statements / branches / functions / lines
- Docs coverage: 100% (12/12 files)
- Lint: clean (biome, 0 errors)
- TypeScript: clean (noEmit)
- Tests: 169 passing