{"_id":"@adibarra/url-shortener","_rev":"2-c03c95474637653be679253873cce85a","name":"@adibarra/url-shortener","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.0":{"name":"@adibarra/url-shortener","version":"1.0.0","keywords":["url","shortener","utility","typescript"],"author":{"url":"https://adibarra.com","name":"adibarra","email":"github@adibarra.com"},"license":"MIT","_id":"@adibarra/url-shortener@1.0.0","maintainers":[{"name":"adibarra","email":"github@adibarra.com"}],"homepage":"https://github.com/adibarra/url-shortner#readme","bugs":{"url":"https://github.com/adibarra/url-shortner/issues"},"dist":{"shasum":"599670532b001cb9a311bffeff31f5bfb254b495","tarball":"https://registry.npmjs.org/@adibarra/url-shortener/-/url-shortener-1.0.0.tgz","fileCount":33,"integrity":"sha512-A/5SROrBJdEdqGRzhLT+HBbSC5nJzn1JHf24SIXlaTmwB2ObiUh91h0Xkv8pfGeKk10dEfHyK2oFh+/4md302Q==","signatures":[{"sig":"MEUCIQD/16zW377ULRn6T4TAwNqqBjOlIYugMre+riaNs7215QIgXJdDGP8FzWVHVkb+Q38gOUmjR7L+hBPVaKzp6nFoy+4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":73692},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","gitHead":"ee0cce90cf4bd6ddb1a401e998c5a13ca9deea70","scripts":{"lint":"eslint --cache . || exit 0","taze":"taze -I","test":"tsx test/index.test.ts","build":"pnpm clean && tsc","check":"tsc --noEmit","clean":"rm -rf dist/","lint:fix":"eslint --cache . --fix || exit 0","clean:all":"pnpm run clean && rm -rf node_modules .eslintcache"},"_npmUser":{"name":"adibarra","email":"github@adibarra.com"},"repository":{"url":"git+https://github.com/adibarra/url-shortner.git","type":"git"},"_npmVersion":"11.6.1","description":"A simple and lightweight URL shortener utility library","directories":{},"_nodeVersion":"24.11.0","_hasShrinkwrap":false,"packageManager":"pnpm@10.24.0","devDependencies":{"tsx":"^4.21.0","taze":"^19.9.2","eslint":"^9.39.1","manten":"^1.9.0","typescript":"^5.9.3","@types/node":"^24.10.1","@antfu/eslint-config":"^6.2.0"},"_npmOperationalInternal":{"tmp":"tmp/url-shortener_1.0.0_1764570230961_0.1283666505610881","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@adibarra/url-shortener","type":"module","version":"1.0.1","packageManager":"pnpm@10.24.0","description":"A simple and lightweight URL shortener utility library","author":{"name":"adibarra","email":"github@adibarra.com","url":"https://adibarra.com"},"license":"MIT","homepage":"https://github.com/adibarra/url-shortener#readme","repository":{"type":"git","url":"git+https://github.com/adibarra/url-shortener.git"},"bugs":{"url":"https://github.com/adibarra/url-shortener/issues"},"keywords":["url","shortener","utility","typescript"],"main":"dist/index.js","types":"dist/index.d.ts","scripts":{"build":"pnpm clean && tsc","check":"tsc --noEmit","clean":"rm -rf dist/","clean:all":"pnpm run clean && rm -rf node_modules .eslintcache","lint":"eslint --cache . || exit 0","lint:fix":"eslint --cache . --fix || exit 0","test":"tsx test/index.test.ts","taze":"taze -I"},"devDependencies":{"@antfu/eslint-config":"^6.2.0","@types/node":"^24.10.1","eslint":"^9.39.1","manten":"^1.9.0","taze":"^19.9.2","tsx":"^4.21.0","typescript":"^5.9.3"},"gitHead":"fe9dc812ddd6d41a26e82eb3f53b7b4f55fea76a","_id":"@adibarra/url-shortener@1.0.1","_nodeVersion":"24.11.0","_npmVersion":"11.6.1","dist":{"integrity":"sha512-c+4qSClvOVjQeQB5Q/n+NhzrCHTM2KjrmL2doOmpzTMXmKHSpo3vzyfW7P99nQQvVaXmMq3s7DANZi20emIiQg==","shasum":"38ab42208f057829f7c5517621e77dc154022dbd","tarball":"https://registry.npmjs.org/@adibarra/url-shortener/-/url-shortener-1.0.1.tgz","fileCount":33,"unpackedSize":73698,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIATSakqoUmpTfC9vfksBHjG6PWLtnqRZRaVTVZo0g+ewAiB8kBLtgTN7ly0BcJ+F7/hg5M81imFGc0Il9/DJlzbjtA=="}]},"_npmUser":{"name":"adibarra","email":"github@adibarra.com"},"directories":{},"maintainers":[{"name":"adibarra","email":"github@adibarra.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/url-shortener_1.0.1_1764571037467_0.9874524322233149"},"_hasShrinkwrap":false}},"time":{"created":"2025-12-01T06:23:50.846Z","modified":"2025-12-01T06:37:17.850Z","1.0.0":"2025-12-01T06:23:51.143Z","1.0.1":"2025-12-01T06:37:17.660Z"},"bugs":{"url":"https://github.com/adibarra/url-shortener/issues"},"author":{"name":"adibarra","email":"github@adibarra.com","url":"https://adibarra.com"},"license":"MIT","homepage":"https://github.com/adibarra/url-shortener#readme","keywords":["url","shortener","utility","typescript"],"repository":{"type":"git","url":"git+https://github.com/adibarra/url-shortener.git"},"description":"A simple and lightweight URL shortener utility library","maintainers":[{"name":"adibarra","email":"github@adibarra.com"}],"readme":"# @adibarra/url-shortener\n\nA simple and lightweight URL shortener utility library for Node.js.\n\nProvides several modular components for generating short codes, validating and normalizing URLs, and building URL shortening workflows with customizable options.\n\n<p align=\"center\">\n  <a href=\"https://npmjs.com/package/@adibarra/url-shortener\">\n    <img alt=\"npm version\" src=\"https://img.shields.io/npm/v/@adibarra/url-shortener?style=flat&colorA=18181B&colorB=F0DB4F\">\n  </a>\n  <a href=\"https://github.com/adibarra/url-shortener/issues\">\n    <img src=\"https://img.shields.io/github/issues/adibarra/url-shortener\" alt=\"issues\">\n  </a>\n  <a href=\"#\">\n    <img src=\"https://img.shields.io/github/last-commit/adibarra/url-shortener\" alt=\"last commit\">\n  </a>\n  <br />\n  <a href=\"#features\">Features</a> •\n  <a href=\"#installation\">Installation</a> •\n  <a href=\"#usage\">Usage</a> •\n  <a href=\"#error-handling\">Error Handling</a> •\n  <a href=\"#examples\">Examples</a> •\n  <a href=\"#license\">License</a>\n</p>\n\n## Features\n\n- Modular design for flexible URL shortening workflows\n- Highly customizable with options for generation, validation, and normalization\n- Support for random and deterministic short codes\n- Robust URL validation and normalization\n- Batch processing and uniqueness validation\n- Zero dependencies, full TypeScript support\n\n## Installation\n\n```bash\n# npm\nnpm install @adibarra/url-shortener\n\n# pnpm\npnpm add @adibarra/url-shortener\n\n# yarn\nyarn add @adibarra/url-shortener\n```\n\n## Usage\n\n### Code Generation\n\n#### Basic Examples\n\n```typescript\nimport { generateShort, predefinedCharsets } from '@adibarra/url-shortener'\n\n// Show all available charsets\nconsole.log(predefinedCharsets)\n\nconst shortCode = generateShort(6, { charset: 'alphanumeric' }) // e.g., \"aB3kL9\"\n\nconst customCode = generateShort(6, { charset: 'abc123' }) // Custom charset\n\n// With custom random function\nfunction secureRandom(): number {\n  const buffer = randomBytes(4)\n  return buffer.readUInt32LE(0) / 0xFFFFFFFF\n}\n\nconst secureCode = generateShort(8, { customRandomFunction: secureRandom })\n```\n\n```typescript\nimport { generateShortBatch } from '@adibarra/url-shortener'\n\nconst codes = generateShortBatch(5, { length: 6, charset: 'alphanumeric_lower' })\nconsole.log(codes) // [\"a1b2c3\", \"d4e5f6\", ...]\n```\n\n#### Advanced Examples\n\n```typescript\nimport { hashShort } from '@adibarra/url-shortener'\n\n// Always generates the same code for the same URL\nconst code1 = hashShort('https://example.com', { length: 6 })\nconst code2 = hashShort('https://example.com', { length: 6 })\nconsole.log(code1 === code2) // true\n\n// With custom hash function\nfunction customHash(url: string): number {\n  let hash = 0\n  for (let i = 0; i < url.length; i++) {\n    const char = url.charCodeAt(i)\n    hash = ((hash << 5) - hash) + char\n    hash = hash & hash // 32-bit integer\n  }\n  return Math.abs(hash)\n}\n\nconst hashedCode = hashShort('https://example.com', {\n  customHashFunction: customHash,\n  length: 8\n})\n```\n\n### URL Processing\n\n#### Shortening URLs\n\n```typescript\nimport { shortenURL } from '@adibarra/url-shortener'\n\nconst result = shortenURL('https://example.com', { length: 6 })\nconsole.log(result) // { code: \"XyZ123\", original: \"https://example.com\" }\n\nconst invalidResult = shortenURL('invalid-url', { length: 6 })\nconsole.log(invalidResult) // { code: \"XyZ123\", original: \"invalid-url\" }\n```\n\n```typescript\nimport { shortenURL } from '@adibarra/url-shortener'\n\n// Only shorten valid URLs\nconst result = shortenURL('https://example.com', {\n  urlProcessing: 'validate',\n  length: 6\n})\nconsole.log(result) // { code: \"XyZ123\", original: \"https://example.com\" }\n\nconst invalidResult = shortenURL('invalid-url', {\n  urlProcessing: 'validate',\n  length: 6\n})\nconsole.log(invalidResult) // null\n```\n\n```typescript\nimport { shortenURL } from '@adibarra/url-shortener'\n\n// Normalize URL before shortening (also validates)\nconst result = shortenURL('https://EXAMPLE.COM/PATH/?query=value#fragment', {\n  urlProcessing: 'normalize',\n  lowercaseHost: true,\n  lowercasePath: true,\n  removeQuery: true,\n  removeFragment: true,\n  removeTrailingSlash: true,\n  length: 6\n})\nconsole.log(result) // { code: \"XyZ123\", original: \"https://example.com/path\" }\n```\n\n```typescript\nimport { shortenURLs } from '@adibarra/url-shortener'\n\nconst results = shortenURLs(['https://example.com', 'https://google.com'], { length: 6 })\nconsole.log(results) // [{ code: \"XyZ123\", original: \"https://example.com\" }, { code: \"AbC456\", original: \"https://google.com\" }]\n```\n\n#### Validation and Normalization\n\n```typescript\nimport { validateURL } from '@adibarra/url-shortener'\n\nconsole.log(validateURL('https://example.com')) // true\nconsole.log(validateURL('not-a-url')) // false\n\n// Strict validation\nconsole.log(validateURL('https://example.com', {\n  allowedProtocols: ['https:'],\n  allowedHosts: ['example.com']\n})) // true\n```\n\n```typescript\nimport { normalizeURL } from '@adibarra/url-shortener'\n\nconsole.log(normalizeURL('https://EXAMPLE.COM/PATH/?query=value#fragment', {\n  lowercaseHost: true,\n  removeQuery: true,\n  removeFragment: true,\n  removeTrailingSlash: true\n})) // \"https://example.com/PATH\"\n\n// Advanced normalization\nconsole.log(normalizeURL('https://Example.Com:443//path//to//file/?q=1#hash', {\n  lowercaseHost: true,\n  lowercasePath: true,\n  removeDefaultPort: true,\n  removeDuplicateSlashes: true,\n  removeQuery: true,\n  removeFragment: true,\n  removeTrailingSlash: true\n})) // \"https://example.com/path/to/file\"\n```\n\n##### Custom Functions\n\n```typescript\n// Custom validator\nfunction customValidator(url: string): boolean {\n  return url.startsWith('https://') && url.includes('example.com')\n}\n\nconsole.log(validateURL('https://example.com/page', { customValidator })) // true\nconsole.log(validateURL('https://google.com/page', { customValidator })) // false\n\n// Custom normalizer (overrides built-in normalization options)\nfunction customNormalizer(url: string): string | null {\n  try {\n    const parsed = new URL(url)\n    // Custom logic: always use HTTPS and remove www\n    parsed.protocol = 'https:'\n    parsed.hostname = parsed.hostname.replace(/^www\\./, '')\n    return parsed.toString()\n  }\n  catch {\n    return null\n  }\n}\n\nconsole.log(normalizeURL('http://www.example.com/path', { customNormalizer }))\n// \"https://example.com/path\"\n```\n\n### Advanced Usage\n\n```typescript\nimport { generateUniqueShortBatch, shortenURL } from '@adibarra/url-shortener'\n\n// Example: Check uniqueness against a database\nfunction getUniqueCodes(codes: string[]): string[] {\n  const existing = db.query('SELECT code FROM short_urls WHERE code IN (?)', [codes])\n  const existingSet = new Set(existing.map(row => row.code))\n  return codes.filter(code => !existingSet.has(code))\n}\n\n// Generate unique codes in bulk\nconst uniqueCodes = generateUniqueShortBatch(10, getUniqueCodes, { length: 6 })\nconsole.log(uniqueCodes) // [\"unique1\", \"unique2\", ...]\n\n// Or shorten URLs with uniqueness validation\nconst result = shortenURL('https://example.com', {\n  generator: 'validated',\n  getUniqueCodes,\n  length: 6\n})\nconsole.log(result) // { code: \"uniqueCode\", original: \"https://example.com\" }\n```\n\n### Full Example with All Options\n\n```typescript\nimport { shortenURL } from '@adibarra/url-shortener'\n\n// Custom validator and normalizer functions\nfunction customValidator(url: string): boolean {\n  return url.startsWith('https://') && !url.includes('spam')\n}\n\nfunction customNormalizer(url: string): string | null {\n  try {\n    const parsed = new URL(url)\n    parsed.protocol = 'https:'\n    parsed.hostname = parsed.hostname.replace(/^www\\./, '')\n    return parsed.toString()\n  }\n  catch {\n    return null\n  }\n}\n\n// Example database uniqueness check\nfunction getUniqueCodes(codes: string[]): string[] {\n  // Simulate checking against a database\n  const taken = new Set(['taken1', 'taken2'])\n  return codes.filter(code => !taken.has(code))\n}\n\n// Using ALL options together\nconst result = shortenURL('https://WWW.EXAMPLE.COM/PATH/?utm=123#frag', {\n  urlProcessing: 'normalize',\n  allowedProtocols: ['https:'],\n  allowedHosts: ['example.com'],\n  customValidator,\n  lowercaseHost: true,\n  lowercasePath: true,\n  removeDefaultPort: true,\n  removeQuery: true,\n  removeFragment: true,\n  removeTrailingSlash: true,\n  removeDuplicateSlashes: true,\n  customNormalizer,\n  length: 8,\n  charset: 'alphanumeric',\n  generator: 'validated',\n  getUniqueCodes,\n  maxAttempts: 1000\n})\n\nconsole.log(result) // { code: \"uniqueCode\", original: \"https://example.com/path\" }\n```\n\n## Error Handling\n\nThe library throws specific error types for better error handling:\n\n- `UrlShortenerError`: Base error class\n- `InvalidArgumentError`: For invalid arguments like negative lengths\n- `RequiredOptionError`: For missing required options like `getUniqueCodes` for 'validated' generator\n\n```typescript\nimport { RequiredOptionError, shortenURL } from '@adibarra/url-shortener'\n\ntry {\n  shortenURL('https://example.com', { generator: 'validated' })\n}\ncatch (e) {\n  if (e instanceof RequiredOptionError) {\n    console.log('Provide getUniqueCodes!')\n  }\n}\n```\n\n## Examples\n\nSee [EXAMPLES.md](EXAMPLES.md) for detailed examples and comprehensive options.\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md"}