{"_id":"@codenhub/validation","name":"@codenhub/validation","dist-tags":{"latest":"0.0.1"},"versions":{"0.0.1":{"name":"@codenhub/validation","version":"0.0.1","private":false,"description":"Zero-dependency validation and primitive coercion helpers for TypeScript apps.","homepage":"https://github.com/codenhub/codenhub/tree/main/packages/validation","license":"Apache-2.0","repository":{"type":"git","url":"git+https://github.com/codenhub/codenhub.git","directory":"packages/validation"},"type":"module","main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"publishConfig":{"access":"public"},"devDependencies":{"@vitest/coverage-v8":"4.1.8","tsdown":"^0.22.2","typescript":"^6.0.3","vitest":"^4.0.17"},"scripts":{"build":"tsdown src/index.ts --format esm --dts --clean --no-fixed-extension","status:npm":"npm view @codenhub/validation version dist-tags time --json && npm dist-tag ls @codenhub/validation && npm access get status @codenhub/validation","status:pack":"npm pack --dry-run","test":"vitest run","test:coverage":"vitest run --coverage","test:watch":"vitest","typecheck":"tsc --noEmit"},"_id":"@codenhub/validation@0.0.1","bugs":{"url":"https://github.com/codenhub/codenhub/issues"},"_integrity":"sha512-ypuwc+Kc4/HKHFRBEuZU1pm8EPcvsF0Wn2ImgRv5P0SSRZcOr2uB+xJWWXVOWMcBDSF1aI5LXozRr1J5oGHgtg==","_resolved":"C:\\Users\\GUSTAV~1.MOT\\AppData\\Local\\Temp\\f46fc8dab30f8d7933d2623d71cc2562\\codenhub-validation-0.0.1.tgz","_from":"file:codenhub-validation-0.0.1.tgz","_nodeVersion":"24.12.0","_npmVersion":"11.12.0","dist":{"integrity":"sha512-ypuwc+Kc4/HKHFRBEuZU1pm8EPcvsF0Wn2ImgRv5P0SSRZcOr2uB+xJWWXVOWMcBDSF1aI5LXozRr1J5oGHgtg==","shasum":"4b5ceee3721d6721f37aa4a82472b1cc97d920e5","tarball":"https://registry.npmjs.org/@codenhub/validation/-/validation-0.0.1.tgz","fileCount":5,"unpackedSize":58753,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQC5DWzUMGFwcHta6qOVrfetroopzs0ZdWmpJjgmsdbFNQIgNgiNNIFb9dd0DZvuYczMW/FXbwyP+ieVnmS2ofACDGk="}]},"_npmUser":{"name":"coden.agency","email":"contact@coden.agency"},"directories":{},"maintainers":[{"name":"coden.agency","email":"contact@coden.agency"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/validation_0.0.1_1781118634094_0.3478028404351299"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-10T19:10:33.917Z","0.0.1":"2026-06-10T19:10:34.280Z","modified":"2026-06-10T19:10:34.533Z"},"maintainers":[{"name":"coden.agency","email":"contact@coden.agency"}],"description":"Zero-dependency validation and primitive coercion helpers for TypeScript apps.","homepage":"https://github.com/codenhub/codenhub/tree/main/packages/validation","repository":{"type":"git","url":"git+https://github.com/codenhub/codenhub.git","directory":"packages/validation"},"bugs":{"url":"https://github.com/codenhub/codenhub/issues"},"license":"Apache-2.0","readme":"# @codenhub/validation\n\nValidation and primitive coercion helpers for TypeScript apps. Validators return a validation-owned result shape, so callers can handle invalid input without exceptions.\n\n## Installation\n\n```sh\npnpm add @codenhub/validation\n```\n\n## Usage\n\nValidate unknown boundary input with `val` and convert primitive values with `coerce` when input arrives as strings, environment values, form values, or query params.\n\n```ts\nimport { coerce, val, type ValidationResult } from \"@codenhub/validation\";\n\nconst parsePort = (raw: unknown): ValidationResult<number> => {\n  const port = coerce.int(raw, { path: [\"port\"] });\n\n  if (!port.ok) return port;\n\n  return val.number(port.value, { path: [\"port\"] }).port();\n};\n\nconst result = parsePort(\"3000\");\n\nif (result.ok) {\n  console.log(result.value);\n} else {\n  console.error(result.error.message);\n}\n```\n\n## Reference\n\n### `@codenhub/validation`\n\nPrimary entrypoint for validation, coercion, custom validators, and result helpers.\n\n```ts\nimport {\n  coerce,\n  custom,\n  err,\n  ok,\n  parseResult,\n  type ArrayValidators,\n  type NumberValidators,\n  type ObjectValidators,\n  type PlainObject,\n  type StringValidators,\n  val,\n  type ValidationErr,\n  type ValidationError,\n  type ValidationErrorCode,\n  type ValidationErrorInput,\n  type ValidationErrorOptions,\n  type ValidationIssue,\n  type ValidationOk,\n  type ValidationOptions,\n  type ValidationPathSegment,\n  type ValidationResult,\n} from \"@codenhub/validation\";\n```\n\nSupported import paths:\n\n| Path                   | Description                                 |\n| ---------------------- | ------------------------------------------- |\n| `@codenhub/validation` | Validation, coercion, and result utilities. |\n\n#### `ValidationResult<T>`\n\nRepresents success or validation failure without throwing.\n\n```ts\ntype ValidationResult<T> = ValidationOk<T> | ValidationErr;\n\ninterface ValidationOk<T> {\n  ok: true;\n  value: T;\n}\n\ninterface ValidationErr {\n  ok: false;\n  error: ValidationError;\n}\n```\n\n#### `ValidationError`\n\nPlain object describing why validation failed.\n\n```ts\ninterface ValidationError {\n  code: ValidationErrorCode;\n  message: string;\n  path: readonly ValidationPathSegment[];\n  input?: unknown;\n  expected?: string;\n  received?: string;\n  issues?: readonly ValidationIssue[];\n}\n\ntype ValidationErrorCode =\n  | \"invalid_type\"\n  | \"invalid_value\"\n  | \"invalid_format\"\n  | \"too_small\"\n  | \"too_big\"\n  | \"missing_key\"\n  | \"custom\";\n\ntype ValidationPathSegment = string | number;\n\ninterface ValidationIssue {\n  code: ValidationErrorCode;\n  message: string;\n  path: readonly ValidationPathSegment[];\n  input?: unknown;\n  expected?: string;\n  received?: string;\n}\n```\n\n`path` points to the invalid value. `input` is included only when requested through validation options.\n\n#### `ValidationOptions`\n\nCommon options accepted by validators and coercers.\n\n```ts\ninterface ValidationOptions {\n  path?: readonly ValidationPathSegment[];\n  includeInput?: boolean;\n}\n```\n\n#### `ok()`\n\nCreates a successful validation result.\n\n```ts\nfunction ok<T>(value: T): ValidationOk<T>;\n```\n\n#### `err()`\n\nCreates a failed validation result.\n\n```ts\nfunction err(error: ValidationErrorInput): ValidationErr;\n\ntype ValidationErrorInput = string | ValidationIssue | ValidationErrorOptions;\n\ninterface ValidationErrorOptions {\n  code?: ValidationErrorCode;\n  message: string;\n  path?: readonly ValidationPathSegment[];\n  input?: unknown;\n  expected?: string;\n  received?: string;\n  issues?: readonly ValidationIssue[];\n}\n```\n\nString input uses `code: \"custom\"` and an empty path.\n\n#### `parseResult()`\n\nNormalizes unknown validator output into `ValidationResult<T>`.\n\n```ts\nfunction parseResult<T>(value: unknown): ValidationResult<T>;\n```\n\nAccepted input:\n\n| Input shape              | Output                                             |\n| ------------------------ | -------------------------------------------------- |\n| `{ ok: true, value }`    | Success result.                                    |\n| `{ ok: false, error }`   | Failure with normalized `ValidationError`.         |\n| `ValidationErrorOptions` | Failure result.                                    |\n| `Error`                  | Failure with `code: \"custom\"` and `message`.       |\n| `string`                 | Failure with `code: \"custom\"` and `message`.       |\n| Anything else            | Failure with `code: \"custom\"` and generic message. |\n\n#### `val`\n\nValidation factory for common string, number, object, and array checks.\n\n```ts\nconst val: {\n  string(value: unknown, options?: ValidationOptions): StringValidators;\n  number(value: unknown, options?: ValidationOptions): NumberValidators;\n  object(value: unknown, options?: ValidationOptions): ObjectValidators;\n  array<T = unknown>(value: unknown, options?: ValidationOptions): ArrayValidators<T>;\n};\n```\n\nValidators return `ValidationResult<T>` and do not throw for invalid input.\n\nAll validator factories accept `unknown` input. If the input has the wrong base type, every method on the returned validator object returns the same `ValidationErr` with `code: \"invalid_type\"`, the provided `path`, and the original `input` only when `includeInput` is enabled.\n\n#### Validator Types\n\nValidator interfaces describe the method sets returned by `val` factories. They are exported for callers that need to type reusable validators or function boundaries.\n\n```ts\ntype PlainObject = Record<string, unknown>;\n\ninterface StringValidators { ... }\ninterface NumberValidators { ... }\ninterface ObjectValidators { ... }\ninterface ArrayValidators<T> { ... }\n```\n\n| Type                 | Import path            | Purpose                                           |\n| -------------------- | ---------------------- | ------------------------------------------------- |\n| `StringValidators`   | `@codenhub/validation` | Return type for `val.string()`.                   |\n| `NumberValidators`   | `@codenhub/validation` | Return type for `val.number()`.                   |\n| `ObjectValidators`   | `@codenhub/validation` | Return type for `val.object()`.                   |\n| `ArrayValidators<T>` | `@codenhub/validation` | Return type for `val.array<T>()`.                 |\n| `PlainObject`        | `@codenhub/validation` | Plain object shape returned by object validators. |\n\n##### `val.string()`\n\n```ts\nval.string(value: unknown, options?: ValidationOptions): StringValidators;\n```\n\nCreates validators for input that must be a string. Non-string input fails with `code: \"invalid_type\"`.\n\n| Method                                                    | Success value                                                                  | Failure behavior                                                                                                                                                  |\n| --------------------------------------------------------- | ------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `email(options?: { allowPlus?: boolean })`                | Trimmed email with the host lowercased. `allowPlus` defaults to `true`.        | Returns `code: \"invalid_format\"` for invalid local parts, public hosts, length limits, or disallowed plus addressing.                                             |\n| `url(options?: { forceHttps?: boolean })`                 | Normalized public HTTP(S) URL string. Missing protocol defaults to `https://`. | Returns `code: \"invalid_format\"` for invalid URLs, private/non-public host shapes, credentials, or HTTP when `forceHttps` is `true`.                              |\n| `fileType(allowed: string[])`                             | Lowercase file extension without a leading dot.                                | Returns `code: \"invalid_value\"` when the allow list is empty after normalization, or `code: \"invalid_format\"` when the input extension is missing or not allowed. |\n| `minLength(length: number, options?: { trim?: boolean })` | Original string, or trimmed string when `trim` is `true`.                      | Returns `code: \"invalid_value\"` for invalid limits, or `code: \"too_small\"` when shorter than `length`.                                                            |\n| `maxLength(length: number, options?: { trim?: boolean })` | Original string, or trimmed string when `trim` is `true`.                      | Returns `code: \"invalid_value\"` for invalid limits, or `code: \"too_big\"` when longer than `length`.                                                               |\n| `notEmpty(options?: { trim?: boolean })`                  | Original string, or trimmed string. `trim` defaults to `true`.                 | Returns `code: \"too_small\"` when the checked string is empty.                                                                                                     |\n| `matches(pattern: RegExp, message?: string)`              | Original string.                                                               | Returns `code: \"invalid_format\"` with the provided message when the pattern does not match.                                                                       |\n\n##### `val.number()`\n\n```ts\nval.number(value: unknown, options?: ValidationOptions): NumberValidators;\n```\n\nCreates validators for finite number input. Non-number and `NaN` input fails with `code: \"invalid_type\"`; non-finite numbers fail with `code: \"invalid_value\"` before method-specific checks run.\n\n| Method                                           | Success value    | Failure behavior                                                                                                                    |\n| ------------------------------------------------ | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------- |\n| `positive()`                                     | Original number. | Returns `code: \"invalid_value\"` when the number is not greater than zero.                                                           |\n| `negative()`                                     | Original number. | Returns `code: \"invalid_value\"` when the number is not less than zero.                                                              |\n| `nonNegative()`                                  | Original number. | Returns `code: \"invalid_value\"` when the number is less than zero.                                                                  |\n| `nonPositive()`                                  | Original number. | Returns `code: \"invalid_value\"` when the number is greater than zero.                                                               |\n| `nonZero()`                                      | Original number. | Returns `code: \"invalid_value\"` when the number is zero.                                                                            |\n| `int()`                                          | Original number. | Returns `code: \"invalid_value\"` when the number is not an integer.                                                                  |\n| `safeInt()`                                      | Original number. | Returns `code: \"invalid_value\"` when the number is not a safe JavaScript integer.                                                   |\n| `range(options: { min?: number; max?: number })` | Original number. | Returns `code: \"invalid_value\"` for invalid range configuration, `code: \"too_small\"` below `min`, or `code: \"too_big\"` above `max`. |\n| `finite()`                                       | Original number. | Returns success because non-finite values fail before this method runs.                                                             |\n| `port()`                                         | Original number. | Returns `code: \"invalid_value\"` unless the number is an integer from `1` through `65535`.                                           |\n\n##### `val.object()`\n\n```ts\nval.object(value: unknown, options?: ValidationOptions): ObjectValidators;\n```\n\nCreates validators for plain objects, including null-prototype objects. Arrays, `null`, functions, and class instances fail with `code: \"invalid_type\"`.\n\n| Method                             | Success value          | Failure behavior                                                                                                |\n| ---------------------------------- | ---------------------- | --------------------------------------------------------------------------------------------------------------- |\n| `plain()`                          | Original plain object. | Returns the base type failure for non-plain objects.                                                            |\n| `hasKeys(keys: readonly string[])` | Original plain object. | Returns `code: \"missing_key\"` with the missing key appended to `path` when any required own property is absent. |\n\n##### `val.array()`\n\n```ts\nval.array<T = unknown>(value: unknown, options?: ValidationOptions): ArrayValidators<T>;\n```\n\nCreates validators for array input. Non-array input fails with `code: \"invalid_type\"`.\n\n| Method                      | Success value   | Failure behavior                                                                                           |\n| --------------------------- | --------------- | ---------------------------------------------------------------------------------------------------------- |\n| `minLength(length: number)` | Original array. | Returns `code: \"invalid_value\"` for invalid limits, or `code: \"too_small\"` when the array has fewer items. |\n| `maxLength(length: number)` | Original array. | Returns `code: \"invalid_value\"` for invalid limits, or `code: \"too_big\"` when the array has more items.    |\n| `notEmpty()`                | Original array. | Returns `code: \"too_small\"` when the array is empty.                                                       |\n\n#### `coerce`\n\nConverts primitive input before validation.\n\n```ts\nconst coerce: {\n  int(value: unknown, options?: ValidationOptions): ValidationResult<number>;\n  number(value: unknown, options?: ValidationOptions): ValidationResult<number>;\n  bool(value: unknown, options?: ValidationOptions): ValidationResult<boolean>;\n  string(value: unknown, options?: ValidationOptions): ValidationResult<string>;\n};\n```\n\nObjects and functions are rejected. `null` and `undefined` are rejected by `coerce.string()`.\n\n| Method                           | Success value          | Failure behavior                                                                                                                                                                               |\n| -------------------------------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `coerce.int(value, options?)`    | Safe integer.          | Returns `code: \"invalid_type\"` for objects/functions, or `code: \"invalid_format\"` for non-decimal or unsafe integer input.                                                                     |\n| `coerce.number(value, options?)` | Finite number.         | Returns `code: \"invalid_type\"` for objects/functions, or `code: \"invalid_format\"` for unsupported number strings such as exponent notation.                                                    |\n| `coerce.bool(value, options?)`   | Boolean.               | Accepts booleans and `true`, `false`, `1`, `0`, `yes`, `no`, `on`, and `off` strings. Other primitive values return `code: \"invalid_format\"`; objects/functions return `code: \"invalid_type\"`. |\n| `coerce.string(value, options?)` | Stringified primitive. | Returns `code: \"invalid_type\"` for `null`, `undefined`, objects, functions, or values that cannot be converted to strings.                                                                     |\n\n#### `custom()`\n\nRuns a custom validator and normalizes returned or thrown failures.\n\n```ts\nfunction custom<T>(\n  value: unknown,\n  validator: (value: unknown) => unknown,\n  options?: ValidationOptions,\n): ValidationResult<T>;\n```\n\nThrown strings, `Error` objects, result-like objects, and validation error options become `ValidationErr`.\n\n## Examples\n\n### Validate Object Fields\n\n```ts\nimport { err, val } from \"@codenhub/validation\";\n\nconst input = { email: \"user@example.com\", port: 3000 };\nconst email = val.string(input.email, { path: [\"email\"] }).email();\nconst port = val.number(input.port, { path: [\"port\"] }).port();\n\nconst issues = [];\n\nfor (const result of [email, port]) {\n  if (!result.ok) issues.push(result.error);\n}\n\nconst result = issues.length > 0 ? err({ message: \"Invalid config\", issues }) : port;\n```\n\n### Custom Validator\n\n```ts\nimport { custom, err, ok } from \"@codenhub/validation\";\n\nconst userId = custom(\"usr_123\", (value) => {\n  if (typeof value !== \"string\") return err({ code: \"invalid_type\", message: \"Expected user id\" });\n  if (!value.startsWith(\"usr_\")) return err({ code: \"invalid_format\", message: \"Invalid user id\" });\n\n  return ok(value);\n});\n```\n\n## Requirements\n\n- TypeScript strict mode.\n- ESM package.\n- No runtime dependencies.\n- Browser, Node, and SSR safe.\n\n## Notes\n\n- Validators return results instead of throwing for invalid input.\n- Validation errors are plain serializable objects.\n- `includeInput` should be used only when retaining the original input is safe for the caller.\n","readmeFilename":"README.md","_rev":"1-5333d27f6fba9bf9e2910661e4c4ca85"}