{"_id":"@dytsou/shorten-url","_rev":"19-78c3e0e02cff2cc43f960c7b973a7fec","name":"@dytsou/shorten-url","dist-tags":{"latest":"2.4.4"},"versions":{"2.2.6":{"name":"@dytsou/shorten-url","version":"2.2.6","keywords":["url-shortener","cloudflare-workers","short-url","link-shortener","url-shortening"],"author":{"name":"dytsou"},"license":"MIT","_id":"@dytsou/shorten-url@2.2.6","maintainers":[{"name":"dytsou","email":"dytsou@gmail.com"}],"homepage":"https://github.com/dytsou/shorten-url#readme","bugs":{"url":"https://github.com/dytsou/shorten-url/issues"},"dist":{"shasum":"34c2f9ed08f1622218fa1398defee33f1a773b8f","tarball":"https://registry.npmjs.org/@dytsou/shorten-url/-/shorten-url-2.2.6.tgz","fileCount":9,"integrity":"sha512-VVLCdOfIGY169iiu0bJALE2v3ppm9hdWMftYXT0Lwuu39Qlbi/Xjx/ci82pVY7WKXNm8sSewJknUSetipzWCVA==","signatures":[{"sig":"MEQCIGnCu3LlsLMX9rUWT6lMaFZrL1vRlqiYmn49n4RCHjFhAiBh4JhzJr87ITseWo7pqqf6qjNsRIYoKGdVePtihDV/yw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":54450},"main":"src/worker.js","type":"module","_from":"file:dytsou-shorten-url-2.2.6.tgz","engines":{"node":">=18.0.0"},"scripts":{"dev":"wrangler dev","test":"vitest run","deploy":"wrangler deploy","format":"prettier --write .","preview":"wrangler dev","test:watch":"vitest","format:check":"prettier --check .","publish:npmjs":"bash scripts/publish-npmjs.sh","test:coverage":"vitest run --coverage","publish:github":"pnpm publish --registry https://npm.pkg.github.com"},"_npmUser":{"name":"dytsou","email":"dytsou@gmail.com"},"_resolved":"/private/var/folders/dk/z09d8d2n7jbdng515w1psz3c0000gn/T/365f3b8fd164427703190eb13243170a/dytsou-shorten-url-2.2.6.tgz","_integrity":"sha512-VVLCdOfIGY169iiu0bJALE2v3ppm9hdWMftYXT0Lwuu39Qlbi/Xjx/ci82pVY7WKXNm8sSewJknUSetipzWCVA==","repository":{"url":"git+https://github.com/dytsou/shorten-url.git","type":"git"},"_npmVersion":"11.5.1","description":"A modern, fast URL shortener built with Cloudflare Workers and a responsive web interface","directories":{},"_nodeVersion":"24.6.0","_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.0.16","prettier":"^3.7.4","wrangler":"^4.58.0"},"_npmOperationalInternal":{"tmp":"tmp/shorten-url_2.2.6_1768031065676_0.35062960107490904","host":"s3://npm-registry-packages-npm-production"}},"2.2.7":{"name":"@dytsou/shorten-url","version":"2.2.7","keywords":["url-shortener","cloudflare-workers","short-url","link-shortener","url-shortening"],"author":{"name":"dytsou"},"license":"MIT","_id":"@dytsou/shorten-url@2.2.7","maintainers":[{"name":"dytsou","email":"dytsou@gmail.com"}],"homepage":"https://github.com/dytsou/shorten-url#readme","bugs":{"url":"https://github.com/dytsou/shorten-url/issues"},"dist":{"shasum":"25b83dea23d698e2c8f3f4d0011b551fad3f20d8","tarball":"https://registry.npmjs.org/@dytsou/shorten-url/-/shorten-url-2.2.7.tgz","fileCount":9,"integrity":"sha512-3Sq7kHQU6RoSb/8d6mRSF6hOTHCVCAtKMuE2nxDUVacKtBk78WR4sbeGaVDkCKHGfEFJcnAL1CNXEfBINdZpnA==","signatures":[{"sig":"MEUCIF1o4bPuM7qIn9QhgTFTOYtf+O4Vj6xl2DSaBN+CzeeCAiEA2s7dlUced61NOgPAOnIjXoJXiq9ngijlXtqBgY/rbN4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":54471},"main":"src/worker.js","type":"module","_from":"file:dytsou-shorten-url-2.2.7.tgz","engines":{"node":">=18.0.0"},"scripts":{"dev":"wrangler dev","test":"vitest run","deploy":"wrangler deploy","format":"prettier --write .","preview":"wrangler dev","test:watch":"vitest","format:check":"prettier --check .","publish:npmjs":"pnpm publish --registry https://registry.npmjs.org","test:coverage":"vitest run --coverage","publish:github":"pnpm publish --registry https://npm.pkg.github.com"},"_npmUser":{"name":"dytsou","email":"dytsou@gmail.com"},"_resolved":"/private/var/folders/dk/z09d8d2n7jbdng515w1psz3c0000gn/T/bd4df20625a8b3f47d5da0598d2a3674/dytsou-shorten-url-2.2.7.tgz","_integrity":"sha512-3Sq7kHQU6RoSb/8d6mRSF6hOTHCVCAtKMuE2nxDUVacKtBk78WR4sbeGaVDkCKHGfEFJcnAL1CNXEfBINdZpnA==","repository":{"url":"git+https://github.com/dytsou/shorten-url.git","type":"git"},"_npmVersion":"11.5.1","description":"A modern, fast URL shortener built with Cloudflare Workers and a responsive web interface","directories":{},"_nodeVersion":"24.6.0","_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.0.16","prettier":"^3.7.4","wrangler":"^4.58.0"},"_npmOperationalInternal":{"tmp":"tmp/shorten-url_2.2.7_1768031218766_0.7766656282458344","host":"s3://npm-registry-packages-npm-production"}},"2.2.8":{"name":"@dytsou/shorten-url","version":"2.2.8","keywords":["url-shortener","cloudflare-workers","short-url","link-shortener","url-shortening"],"author":{"name":"dytsou"},"license":"MIT","_id":"@dytsou/shorten-url@2.2.8","maintainers":[{"name":"dytsou","email":"dytsou@gmail.com"}],"homepage":"https://github.com/dytsou/shorten-url#readme","bugs":{"url":"https://github.com/dytsou/shorten-url/issues"},"dist":{"shasum":"3b930655dc281afccea49be43bf1e1720f179001","tarball":"https://registry.npmjs.org/@dytsou/shorten-url/-/shorten-url-2.2.8.tgz","fileCount":9,"integrity":"sha512-M3tptF6d+wksPiso47c4G2ZbLkPn4HdwTuIb7VvcNlTpIqwqcFuFDpZ28lZXkNHZdyw6QkK1BRWAaN3lRMtJZQ==","signatures":[{"sig":"MEUCIQDpwQbjF1+ewS0u4xmNKwCItahixvuVSrAFyoHLrkr+fgIgMY4Em5PZvjJyMGcS1277ICMkRHHVdFe9jzA/7ApoZ6g=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":54471},"main":"src/worker.js","type":"module","_from":"file:dytsou-shorten-url-2.2.8.tgz","engines":{"node":">=18.0.0"},"scripts":{"dev":"wrangler dev","test":"vitest run","deploy":"wrangler deploy","format":"prettier --write .","preview":"wrangler dev","test:watch":"vitest","format:check":"prettier --check .","publish:npmjs":"pnpm publish --registry https://registry.npmjs.org","test:coverage":"vitest run --coverage","publish:github":"pnpm publish --registry https://npm.pkg.github.com"},"_npmUser":{"name":"dytsou","email":"dytsou@gmail.com"},"_resolved":"/private/var/folders/dk/z09d8d2n7jbdng515w1psz3c0000gn/T/dd3b96e50934249ddc77c4740a7179ff/dytsou-shorten-url-2.2.8.tgz","_integrity":"sha512-M3tptF6d+wksPiso47c4G2ZbLkPn4HdwTuIb7VvcNlTpIqwqcFuFDpZ28lZXkNHZdyw6QkK1BRWAaN3lRMtJZQ==","repository":{"url":"git+https://github.com/dytsou/shorten-url.git","type":"git"},"_npmVersion":"11.5.1","description":"A modern, fast URL shortener built with Cloudflare Workers and a responsive web interface","directories":{},"_nodeVersion":"24.6.0","_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.0.16","prettier":"^3.7.4","wrangler":"^4.58.0"},"_npmOperationalInternal":{"tmp":"tmp/shorten-url_2.2.8_1769173103322_0.4451416371357426","host":"s3://npm-registry-packages-npm-production"}},"2.2.9":{"name":"@dytsou/shorten-url","version":"2.2.9","keywords":["url-shortener","cloudflare-workers","short-url","link-shortener","url-shortening"],"author":{"name":"dytsou"},"license":"MIT","_id":"@dytsou/shorten-url@2.2.9","maintainers":[{"name":"dytsou","email":"dytsou@gmail.com"}],"homepage":"https://github.com/dytsou/shorten-url#readme","bugs":{"url":"https://github.com/dytsou/shorten-url/issues"},"dist":{"shasum":"8510f0f810f40f8efb43d67376750aef0556b8ab","tarball":"https://registry.npmjs.org/@dytsou/shorten-url/-/shorten-url-2.2.9.tgz","fileCount":9,"integrity":"sha512-2FlX8YNxYJDCOH5smZYnGWOnzlloiFdzPfGLrCavfQ3wvSFOQCydkDmkmvscfovhhHBkwB0EZLNb0I/NvIszBA==","signatures":[{"sig":"MEYCIQCVCUl6955rIGuZj75e5MnTjkuVE8ZBiZCaUU39/YZSxgIhAOVwburEHCxn9wYBpfY8sh6HNkk52VrHAIw0EEglLXKa","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":54471},"main":"src/worker.js","type":"module","_from":"file:dytsou-shorten-url-2.2.9.tgz","engines":{"node":">=18.0.0"},"scripts":{"dev":"wrangler dev","test":"vitest run","deploy":"wrangler deploy","format":"prettier --write .","preview":"wrangler dev","test:watch":"vitest","format:check":"prettier --check .","publish:npmjs":"pnpm publish --registry https://registry.npmjs.org","test:coverage":"vitest run --coverage","publish:github":"pnpm publish --registry https://npm.pkg.github.com"},"_npmUser":{"name":"dytsou","email":"dytsou@gmail.com"},"_resolved":"/private/var/folders/dk/z09d8d2n7jbdng515w1psz3c0000gn/T/d5c2306a920a982a071a76abdb41670f/dytsou-shorten-url-2.2.9.tgz","_integrity":"sha512-2FlX8YNxYJDCOH5smZYnGWOnzlloiFdzPfGLrCavfQ3wvSFOQCydkDmkmvscfovhhHBkwB0EZLNb0I/NvIszBA==","repository":{"url":"git+https://github.com/dytsou/shorten-url.git","type":"git"},"_npmVersion":"11.5.1","description":"A modern, fast URL shortener built with Cloudflare Workers and a responsive web interface","directories":{},"_nodeVersion":"24.6.0","_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.0.16","prettier":"^3.7.4","wrangler":"^4.58.0"},"_npmOperationalInternal":{"tmp":"tmp/shorten-url_2.2.9_1770385568670_0.6610949422084371","host":"s3://npm-registry-packages-npm-production"}},"2.3.1":{"name":"@dytsou/shorten-url","version":"2.3.1","keywords":["url-shortener","cloudflare-workers","short-url","link-shortener","url-shortening"],"author":{"name":"dytsou"},"license":"MIT","_id":"@dytsou/shorten-url@2.3.1","maintainers":[{"name":"dytsou","email":"dytsou@gmail.com"}],"homepage":"https://github.com/dytsou/shorten-url#readme","bugs":{"url":"https://github.com/dytsou/shorten-url/issues"},"dist":{"shasum":"111f04b9c40f47e184176cba3b2362eeada41883","tarball":"https://registry.npmjs.org/@dytsou/shorten-url/-/shorten-url-2.3.1.tgz","fileCount":9,"integrity":"sha512-ZvyOC7P2qGGSr+4Uc3HKG59g2l2hxrBKdsw3Fw6S2Mpxa7yEZwjlMjSJkLO8irY2QqQoxOllQptC+eeB2Vvsjg==","signatures":[{"sig":"MEUCIH6EppPITA4eXldKIlMkwiJ2AkOwwn51eN3SwvLrEoD0AiEA7cS5WX/b7127hXycEgjc7+4HRqSbDKggWLaA8ji1b3Y=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":54471},"main":"src/worker.js","type":"module","_from":"file:dytsou-shorten-url-2.3.1.tgz","engines":{"node":">=18.0.0"},"scripts":{"dev":"wrangler dev","test":"vitest run","deploy":"wrangler deploy","format":"prettier --write .","preview":"wrangler dev","test:watch":"vitest","format:check":"prettier --check .","publish:npmjs":"pnpm publish --registry https://registry.npmjs.org","test:coverage":"vitest run --coverage","publish:github":"pnpm publish --registry https://npm.pkg.github.com"},"_npmUser":{"name":"dytsou","email":"dytsou@gmail.com"},"_resolved":"/private/var/folders/dk/z09d8d2n7jbdng515w1psz3c0000gn/T/db86afca9a96f0612ad75a2b9c16988b/dytsou-shorten-url-2.3.1.tgz","_integrity":"sha512-ZvyOC7P2qGGSr+4Uc3HKG59g2l2hxrBKdsw3Fw6S2Mpxa7yEZwjlMjSJkLO8irY2QqQoxOllQptC+eeB2Vvsjg==","repository":{"url":"git+https://github.com/dytsou/shorten-url.git","type":"git"},"_npmVersion":"11.10.1","description":"A modern, fast URL shortener built with Cloudflare Workers and a responsive web interface","directories":{},"_nodeVersion":"24.6.0","_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.0.16","prettier":"^3.7.4","wrangler":"^4.58.0"},"_npmOperationalInternal":{"tmp":"tmp/shorten-url_2.3.1_1772985365508_0.562036136323351","host":"s3://npm-registry-packages-npm-production"}},"2.3.2":{"name":"@dytsou/shorten-url","version":"2.3.2","keywords":["url-shortener","cloudflare-workers","short-url","link-shortener","url-shortening"],"author":{"name":"dytsou"},"license":"MIT","_id":"@dytsou/shorten-url@2.3.2","maintainers":[{"name":"dytsou","email":"dytsou@gmail.com"}],"homepage":"https://github.com/dytsou/shorten-url#readme","bugs":{"url":"https://github.com/dytsou/shorten-url/issues"},"dist":{"shasum":"d605b5fa3a5af8cc00a1ea9694d00aa5fb9fb94c","tarball":"https://registry.npmjs.org/@dytsou/shorten-url/-/shorten-url-2.3.2.tgz","fileCount":9,"integrity":"sha512-oM5nzApxO11xD5YvPVq795fGgwnSlQ9Qtcr2YXpXL7rpVU2hn0+NxLn9GuBoz3CLNfsp+b7Bsu09BUrJWTvETQ==","signatures":[{"sig":"MEUCICus1DFD+3usIaTr4ZB5wcAth4oa8pkPsGRgC4Hq/8VJAiEAnVDcFJngryQcHMk83sDmHzelmD2sNV5JOBLZ2W0yPW4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":54471},"main":"src/worker.js","type":"module","_from":"file:dytsou-shorten-url-2.3.2.tgz","engines":{"node":">=18.0.0"},"scripts":{"dev":"wrangler dev","test":"vitest run","deploy":"wrangler deploy","format":"prettier --write .","preview":"wrangler dev","test:watch":"vitest","format:check":"prettier --check .","publish:npmjs":"pnpm publish --registry https://registry.npmjs.org","test:coverage":"vitest run --coverage","publish:github":"pnpm publish --registry https://npm.pkg.github.com"},"_npmUser":{"name":"dytsou","email":"dytsou@gmail.com"},"_resolved":"/private/var/folders/dk/z09d8d2n7jbdng515w1psz3c0000gn/T/4f59db3bfaed14bd77b4324df679d143/dytsou-shorten-url-2.3.2.tgz","_integrity":"sha512-oM5nzApxO11xD5YvPVq795fGgwnSlQ9Qtcr2YXpXL7rpVU2hn0+NxLn9GuBoz3CLNfsp+b7Bsu09BUrJWTvETQ==","repository":{"url":"git+https://github.com/dytsou/shorten-url.git","type":"git"},"_npmVersion":"11.10.1","description":"A modern, fast URL shortener built with Cloudflare Workers and a responsive web interface","directories":{},"_nodeVersion":"24.6.0","_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.0.16","prettier":"^3.7.4","wrangler":"^4.58.0"},"_npmOperationalInternal":{"tmp":"tmp/shorten-url_2.3.2_1775389912940_0.41298422535462276","host":"s3://npm-registry-packages-npm-production"}},"2.4.2":{"name":"@dytsou/shorten-url","version":"2.4.2","keywords":["url-shortener","cloudflare-workers","short-url","link-shortener","url-shortening"],"author":{"name":"dytsou"},"license":"MIT","_id":"@dytsou/shorten-url@2.4.2","maintainers":[{"name":"dytsou","email":"dytsou@gmail.com"}],"homepage":"https://github.com/dytsou/shorten-url#readme","bugs":{"url":"https://github.com/dytsou/shorten-url/issues"},"dist":{"shasum":"7010487b2cfca692e74733eb6f9bfc82ad98b08f","tarball":"https://registry.npmjs.org/@dytsou/shorten-url/-/shorten-url-2.4.2.tgz","fileCount":18,"integrity":"sha512-z6VbrVhVvWsdF6TuqPErxctSH/ajhXAKwJGlhnmpGiglvgUQ7Z1+PO9XkbrFxf426j2v0cn5qifguxP+zVZ3GA==","signatures":[{"sig":"MEYCIQD/mG/BU9nVxch9UUoyMGKM1eT7V4Id6qbN8P+u9GJcoAIhALB4R2qP+kyX06b58g7EiPMH1cRzvQK7Km7JgO3HMPF9","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@dytsou%2fshorten-url@2.4.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":57512},"main":"src/worker.js","type":"module","_from":"file:dytsou-shorten-url-2.4.2.tgz","engines":{"node":">=24.0.0"},"scripts":{"dev":"wrangler dev","logs":"wrangler tail","test":"vitest run","deploy":"wrangler deploy","format":"prettier --write .","preview":"wrangler dev","test:watch":"vitest","format:check":"prettier --check .","publish:npmjs":"pnpm publish --registry https://registry.npmjs.org","test:coverage":"vitest run --coverage","publish:github":"pnpm publish --registry https://npm.pkg.github.com"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:6f37a5ad-74b5-4486-b300-e48e96459508"}},"_resolved":"/tmp/1621a08bf23f3e11e5b8dac20ad7eda1/dytsou-shorten-url-2.4.2.tgz","_integrity":"sha512-z6VbrVhVvWsdF6TuqPErxctSH/ajhXAKwJGlhnmpGiglvgUQ7Z1+PO9XkbrFxf426j2v0cn5qifguxP+zVZ3GA==","repository":{"url":"git+https://github.com/dytsou/shorten-url.git","type":"git"},"_npmVersion":"11.17.0","description":"A modern, fast URL shortener built with Cloudflare Workers and a responsive web interface","directories":{},"_nodeVersion":"24.19.0","_hasShrinkwrap":false,"devDependencies":{"vite":"7.3.6","vitest":"^4.1.10","prettier":"^3.7.4","wrangler":"^4.120.0"},"_npmOperationalInternal":{"tmp":"tmp/shorten-url_2.4.2_1787900332094_0.022964242128072465","host":"s3://npm-registry-packages-npm-production"}},"2.4.3":{"name":"@dytsou/shorten-url","version":"2.4.3","keywords":["url-shortener","cloudflare-workers","short-url","link-shortener","url-shortening"],"author":{"name":"dytsou"},"license":"MIT","_id":"@dytsou/shorten-url@2.4.3","maintainers":[{"name":"dytsou","email":"dytsou@gmail.com"}],"homepage":"https://github.com/dytsou/shorten-url#readme","bugs":{"url":"https://github.com/dytsou/shorten-url/issues"},"dist":{"shasum":"144a8aecc4101072c735fda7ba7fae2f4d03e9c8","tarball":"https://registry.npmjs.org/@dytsou/shorten-url/-/shorten-url-2.4.3.tgz","fileCount":18,"integrity":"sha512-VeoCT9p9gMfvjxyNyO8Sokr/emc/92ISIIyLgCs2eEVnX712Ti+7DUvGRpegKicLSIHUkk7stYztUbhSl2S+zQ==","signatures":[{"sig":"MEUCIH5j8N3qJy28cCHnpRgMYEGwD/x+91rfXJEx390NR6k+AiEAhcfJpjhhcIl6y1lW0g2hMs2V4wpGeM6QX4o4PByLoqg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@dytsou%2fshorten-url@2.4.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":57512},"main":"src/worker.js","type":"module","_from":"file:dytsou-shorten-url-2.4.3.tgz","engines":{"node":">=24.0.0"},"scripts":{"dev":"wrangler dev","logs":"wrangler tail","test":"vitest run","deploy":"wrangler deploy","format":"prettier --write .","preview":"wrangler dev","test:watch":"vitest","format:check":"prettier --check .","publish:npmjs":"pnpm publish --registry https://registry.npmjs.org","test:coverage":"vitest run --coverage","publish:github":"pnpm publish --registry https://npm.pkg.github.com"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:6f37a5ad-74b5-4486-b300-e48e96459508"}},"_resolved":"/tmp/6180c61e564846f7ed5e745d08a9702c/dytsou-shorten-url-2.4.3.tgz","_integrity":"sha512-VeoCT9p9gMfvjxyNyO8Sokr/emc/92ISIIyLgCs2eEVnX712Ti+7DUvGRpegKicLSIHUkk7stYztUbhSl2S+zQ==","repository":{"url":"git+https://github.com/dytsou/shorten-url.git","type":"git"},"_npmVersion":"11.19.0","description":"A modern, fast URL shortener built with Cloudflare Workers and a responsive web interface","directories":{},"_nodeVersion":"24.20.0","_hasShrinkwrap":false,"devDependencies":{"vite":"7.3.6","vitest":"^4.1.10","prettier":"^3.7.4","wrangler":"^4.120.0"},"_npmOperationalInternal":{"tmp":"tmp/shorten-url_2.4.3_1788668621718_0.05689826965740474","host":"s3://npm-registry-packages-npm-production"}},"2.4.4":{"_id":"@dytsou/shorten-url@2.4.4","bugs":{"url":"https://github.com/dytsou/shorten-url/issues"},"dist":{"shasum":"20322822b8d04b4bd0e027c37acefb7cfd936461","tarball":"https://registry.npmjs.org/@dytsou/shorten-url/-/shorten-url-2.4.4.tgz","fileCount":18,"integrity":"sha512-oxIkY9xlt09iL4u9/31Xv/Dh8sX/f610ASFH1DCOrTwmdQNZ3SiA0v8z6v6w4KA/gXlo1lZPu872zPYbzYS/kg==","signatures":[{"sig":"MEUCIQD9lrj2I79Ez/zsxL8fnaWnCF/902KuKUW5MRTKjq8HWQIgeVFPC5gf3iuzoaxnSmN/eYjToHqhHHbTOiU6kxLxE2s=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDibupRI1WIsJ2WvvwX7jD/WRDGM+eHYnZ38UgKqzXdrwIgflH41qMqUZggPp4fE2eUFJN7EISsB+BXnA4dY3i+q/c="}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@dytsou%2fshorten-url@2.4.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":60840},"main":"src/worker.js","name":"@dytsou/shorten-url","type":"module","_from":"file:dytsou-shorten-url-2.4.4.tgz","author":{"name":"dytsou"},"engines":{"node":">=24.0.0"},"license":"MIT","scripts":{"dev":"wrangler dev","logs":"wrangler tail","test":"vitest run","deploy":"wrangler deploy","format":"prettier --write .","preview":"wrangler dev","test:watch":"vitest","format:check":"prettier --check .","publish:npmjs":"pnpm publish --registry https://registry.npmjs.org","test:coverage":"vitest run --coverage","publish:github":"pnpm publish --registry https://npm.pkg.github.com"},"version":"2.4.4","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:6f37a5ad-74b5-4486-b300-e48e96459508"}},"homepage":"https://github.com/dytsou/shorten-url#readme","keywords":["url-shortener","cloudflare-workers","short-url","link-shortener","url-shortening"],"_resolved":"/tmp/a7002a531216d1d39d891a0e7c384c11/dytsou-shorten-url-2.4.4.tgz","_integrity":"sha512-oxIkY9xlt09iL4u9/31Xv/Dh8sX/f610ASFH1DCOrTwmdQNZ3SiA0v8z6v6w4KA/gXlo1lZPu872zPYbzYS/kg==","repository":{"url":"git+https://github.com/dytsou/shorten-url.git","type":"git"},"_npmVersion":"11.19.0","description":"A modern, fast URL shortener built with Cloudflare Workers and a responsive web interface","directories":{},"maintainers":[{"name":"dytsou","email":"dytsou@gmail.com"}],"_nodeVersion":"24.21.0","_hasShrinkwrap":false,"devDependencies":{"vite":"7.3.6","vitest":"^5.0.0","prettier":"^3.7.4","wrangler":"^4.120.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/shorten-url_2.4.4_1790522791154_0.7135520473822303"}}},"time":{"created":"2026-01-10T07:44:25.592Z","modified":"2026-09-27T15:26:31.777Z","2.1.5":"2025-11-23T03:56:23.024Z","2.1.6":"2025-11-23T04:00:13.776Z","2.1.7":"2025-11-23T04:04:38.508Z","2.1.8":"2025-11-23T14:29:27.039Z","2.1.9":"2025-11-28T11:16:32.693Z","2.2.0":"2025-11-28T15:00:38.730Z","2.2.1":"2025-12-04T14:41:09.492Z","2.2.2":"2025-12-04T14:46:37.636Z","2.2.6":"2026-01-10T07:44:25.805Z","2.2.7":"2026-01-10T07:46:58.929Z","2.2.8":"2026-01-23T12:58:23.460Z","2.2.9":"2026-02-06T13:46:08.812Z","2.3.1":"2026-03-08T15:56:05.647Z","2.3.2":"2026-04-05T11:51:53.141Z","2.4.2":"2026-08-28T06:58:52.235Z","2.4.3":"2026-09-06T04:23:41.855Z","2.4.4":"2026-09-27T15:26:31.241Z"},"bugs":{"url":"https://github.com/dytsou/shorten-url/issues"},"author":{"name":"dytsou"},"license":"MIT","homepage":"https://github.com/dytsou/shorten-url#readme","keywords":["url-shortener","cloudflare-workers","short-url","link-shortener","url-shortening"],"repository":{"url":"git+https://github.com/dytsou/shorten-url.git","type":"git"},"description":"A modern, fast URL shortener built with Cloudflare Workers and a responsive web interface","maintainers":[{"name":"dytsou","email":"dytsou@gmail.com"}],"readme":"# URL Shortener\n\nA URL shortener built with Cloudflare Workers, Cloudflare KV, and a responsive static web interface. The Worker creates short links, stores them in KV, and serves redirects; the `docs/` directory contains the website and OpenAPI reference.\n\n[![Built with Cloudflare](https://workers.cloudflare.com/built-with-cloudflare.svg)](https://cloudflare.com)\n[![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/dytsou/shorten-url)\n\n## Features\n\n- **URL Shortening**: Create short links stored in Cloudflare KV and redirect with HTTP 302\n- **Custom Slugs**: Optionally choose a slug using letters, numbers, hyphens, or underscores\n- **Cloudflare Access**: The Worker checks for Cloudflare Access JWT and email headers before creating links\n- **Responsive Design**: Static shortening form supports desktop and mobile screens\n- **Unique Links**: Optionally reuse the same short key when the destination URL already exists\n- **URL Safety**: Validate submitted URLs and optionally check redirect destinations with Google Safe Browsing\n- **Copy Support**: Copy shortened URLs with a manual-selection fallback\n- **Hosted Error Pages**: Configure external 404, error, Safe Browsing warning, and no-referrer pages\n- **API Documentation**: Static Swagger UI with an OpenAPI 3.1 specification\n- **Worker Observability**: Structured logs and traces are supported\n\nThe Worker does not implement click analytics, per-IP rate limiting, or blocked-domain lists. The similarly named settings in `config/config.js` are not used by the current Worker.\n\n## Quick Start\n\n### Prerequisites\n\n- A Cloudflare account with Workers and Pages; the Deploy to Cloudflare button provisions the required KV namespace\n- A GitHub or GitLab account to receive the repository created by the Deploy to Cloudflare button\n- A Cloudflare Pages project to publish `docs/`\n- Node.js 24 or newer and pnpm 10.22.0 for manual deployment\n\n### 1. Deploy with Cloudflare (Recommended)\n\n1. Click the **Deploy to Cloudflare** button near the top of this README.\n2. Connect your Cloudflare and GitHub or GitLab accounts, then choose the destination repository and Worker name.\n3. Confirm the `LINKS` KV binding. Cloudflare provisions the namespace and deploys the Worker from the `main` branch.\n\nThe button deploys the Worker; it does not publish the static homepage in `docs/`. Connect the created repository to Cloudflare Pages, leave the build command blank, and set the output directory to `docs`. Then set `frontend.url` in `config/config.js` to the Pages URL and push the change to redeploy the Worker. The Worker fetches the static homepage and serves it at `/`, so the form submits to `POST /` on the Worker.\n\n### 2. Alternative: Manual Worker Deployment\n\nClone the repository and install the pinned Wrangler version:\n\n```bash\ngit clone https://github.com/dytsou/shorten-url.git\ncd shorten-url\ncorepack enable\npnpm install\n```\n\nSet `frontend.url` in `config/config.js` to the public URL where you host `docs/`. The Worker fetches this page for `GET /`:\n\n```javascript\nconst config = {\n  frontend: {\n    url: \"https://your-project.pages.dev/\",\n  },\n  // Configure worker options here\n};\n```\n\n`src/worker.js` imports `config/config.js` directly. Keep API keys out of this file; configure the optional Google Safe Browsing key with a Wrangler secret.\n\nInstall Wrangler, log in, and deploy:\n\n```bash\npnpm exec wrangler login\npnpm deploy\n```\n\nThe `LINKS` binding in `wrangler.toml` omits an account-specific namespace ID so Wrangler can provision it. To use an existing KV namespace, create it with `pnpm exec wrangler kv namespace create LINKS` and set its ID in `wrangler.toml` before deploying.\n\n### 3. Deploy the Frontend to Cloudflare Pages\n\nThe `main` branch includes a sample page at `docs/index.html`. To create your own Pages site, connect your repository to Cloudflare Pages, set the production branch to the branch containing your homepage, leave the build command blank, and use `docs` as the output directory.\n\nThis repository's Cloudflare Pages project publishes `docs/` from the `production` branch. The `main` branch remains the one-click Worker template. Set `frontend.url` to your Pages URL so the Worker can serve the hosted homepage at `/`.\n\nFor custom error and interstitial pages, set `frontend.pagesBase` to the directory containing those files.\n\nThe Worker returns short URLs using the request's origin, so configure its public domain in Cloudflare separately from `frontend.url`.\n\n## ⚙️ Configuration Options\n\n### Frontend Configuration\n\n| Option                | Description                                                                 | Default  |\n| --------------------- | --------------------------------------------------------------------------- | -------- |\n| `frontend.url`        | Static homepage URL fetched by the Worker for `GET /`                      | Required |\n| `frontend.pagesBase`  | Base URL for hosted error and interstitial pages                            | `url`    |\n\nThe `frontend.displayDomain` and `frontend.theme` values in the configuration are not read by the current static page or Worker.\n\n### Worker Configuration\n\n| Option                          | Description                                                     | Default    |\n| ------------------------------- | --------------------------------------------------------------- | ---------- |\n| `worker.no_ref`                 | Use the hosted no-referrer interstitial before redirecting      | `\"off\"`    |\n| `worker.cors`                   | Add wildcard CORS headers for API responses                     | `\"on\"`     |\n| `worker.unique_link`            | Reuse a key when the same URL has already been shortened        | `true`     |\n| `worker.custom_link`            | Allow custom slugs                                              | `true`     |\n| `SAFE_BROWSING_API_KEY`         | Optional Google Safe Browsing API key stored as a Worker secret  | Unset      |\n| `worker.min_random_key_length`  | Minimum length for generated keys                               | `6`        |\n| `worker.random_chars`           | Characters used for generated keys                              | See config |\n| `worker.max_custom_slug_length` | Maximum length for custom slugs                                 | `50`       |\n| `worker.reserved_slugs`         | Slugs that cannot be used as custom links                       | See config |\n\n### Security Configuration\n\n| Option                                | Description                                                          | Default |\n| ------------------------------------- | -------------------------------------------------------------------- | ------- |\n| `security.rate_limit`                | Not implemented by the Worker                                        | Unused  |\n| `security.validate_urls`             | URLs are always validated; this setting does not toggle validation  | Unused  |\n| `security.blocked_domains`           | Domain blocklists are not implemented by the Worker                 | Unused  |\n| `security.block_suspicious_domains`  | Domain blocklists are not implemented by the Worker                 | Unused  |\n\n### Storage Configuration\n\n| Option                 | Description                                                          | Default   |\n| ---------------------- | -------------------------------------------------------------------- | --------- |\n| `storage.binding_name` | Worker reads KV from `env.LINKS`; this config value is not consulted | `\"LINKS\"` |\n\n## 🔧 Advanced Setup\n\n### Custom Domain\n\n1. Add a custom domain to the Cloudflare Pages project for the static site.\n2. Add a domain to the Cloudflare Worker separately for the shortening API.\n3. Set `frontend.url` to the Cloudflare Pages URL; Pages and Worker domains are configured independently.\n\n### Google Safe Browsing\n\n1. Get an API key from [Google Cloud Console](https://developers.google.com/safe-browsing/v4/get-started)\n2. Store it as a Worker secret:\n\n```bash\npnpm exec wrangler secret put SAFE_BROWSING_API_KEY\n```\n\nThe Worker reads this secret at runtime. The key is not stored in `config/config.js`.\n\n### Analytics Integration\n\nClick analytics is not implemented, and the `analytics` object in `config/config.js` is not used by the Worker. Cloudflare Worker logs and traces are enabled in `wrangler.toml`.\n\n### Custom Error Pages\n\nThe Worker fetches optional error and interstitial pages from `frontend.pagesBase` (or `frontend.url` when `pagesBase` is not set). Add these files to your static host to customize them:\n\n- **404 Page**: `404.html`\n- **Error Page**: `error.html`\n- **Security Warning**: `safe-browsing-warning.html`\n- **No-Referrer Redirect**: `no-ref-page.html`\n\nThese files are not included in this repository. The Worker fetches their current contents from your static host when needed.\n\n## 📖 API Documentation\n\nThe API reference is a static Swagger UI published from `docs/api/`; it is not served by the Worker at `/api`.\n\n### OpenAPI Specification\n\n- **Format**: OpenAPI 3.1.0\n- **Location**: [docs/api/openapi.yaml](docs/api/openapi.yaml)\n- **Interactive UI**: [docs/api/index.html](docs/api/index.html), published at `/api/` under the Pages base URL\n- **Offline Access**: [docs/api/index.html](docs/api/index.html) for local viewing\n\n### Shorten URL\n\n**POST** `/`\n\n```json\n{\n  \"url\": \"https://example.com/very-long-url\",\n  \"custom_slug\": \"my-link\"\n}\n```\n\n`custom_slug` is optional. The default Worker template requires Cloudflare Access headers before creating a link.\n\n**Response (201 Created):**\n\n```json\n{\n  \"short_url\": \"https://your-worker-domain.example/abc123\"\n}\n```\n\n**Error Response:**\n\n```json\n{\n  \"status\": 400,\n  \"message\": \"Invalid URL format\"\n}\n```\n\n### Access Short URL\n\n**GET** `/{key}`\n\nRedirects to the stored destination with HTTP 302. Query parameters from the short URL are appended to the destination.\n\n### Additional Endpoints\n\n- **GET** `/` - Fetches the configured static homepage\n- **OPTIONS** - Returns a CORS preflight response\n\n## 🛠️ Development\n\n### Local Development\n\n```bash\n# Start local development server (see wrangler.toml for port / host)\npnpm dev\n\n# Local-only example. The handler checks for both headers; Cloudflare Access must\n# authenticate production requests before they reach the Worker.\ncurl -X POST http://localhost:8787/ \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Cf-Access-Jwt-Assertion: local-test\" \\\n  -H \"Cf-Access-Authenticated-User-Email: you@example.com\" \\\n  -d '{\"url\": \"https://example.com\"}'\n```\n\nThe Worker imports `config/config.js` directly. Run `pnpm test` to execute the Worker tests.\n\n### File Structure\n\n```\nshorten-url/\n├── src/\n│   ├── lib/                 # Validation, redirects, KV, responses, and observability\n│   └── worker.js            # Worker entrypoint\n├── docs/\n│   ├── index.html          # Sample homepage (POST /)\n│   └── api/\n│       ├── index.html      # Swagger UI for API docs\n│       └── openapi.yaml    # OpenAPI 3.1.0 specification\n├── config/\n│   └── config.js            # Worker configuration\n├── wrangler.toml            # Wrangler configuration\n├── .github/                # GitHub workflows and templates\n├── .gitignore              # Ignores local-only files\n└── README.md               # This file\n```\n\n## Security Considerations\n\n- Keep API keys out of version control; store them with Wrangler secrets\n- Configure a Cloudflare Access policy in front of the Worker; the handler checks for Access headers but does not verify JWT signatures itself\n- The Worker has no built-in per-IP rate limit or blocked-domain list\n- Consider enabling Google Safe Browsing for redirect destinations\n- Regularly monitor your KV storage usage\n\n## Troubleshooting\n\n### Common Issues\n\n**\"Failed to copy\" error:**\n\n- The app uses modern clipboard API with fallbacks\n- Ensure you're using HTTPS (required for clipboard access)\n\n**Worker deployment fails:**\n\n- Confirm `src/worker.js` and `config/config.js` are present\n- Ensure the `LINKS` KV namespace ID in `wrangler.toml` is valid\n- Ensure KV namespace ID is correct\n- Verify you're logged into the correct Cloudflare account\n\n**Custom slugs not working:**\n\n- Check that `custom_link` is enabled in config\n- Verify slug meets validation requirements (alphanumeric, hyphens, underscores only)\n- Ensure slug is not in the reserved slugs list\n\n**Frontend not loading:**\n\n- Set `frontend.url` to the hosted static homepage URL\n- If the form returns an invalid-path response, check that its POST path matches the Worker route (`/` for the template)\n- Enable CORS if the frontend and Worker use different origins\n\n**Rate limiting issues:**\n\n- The Worker does not currently rate-limit requests. Protect shortening with Cloudflare Access or add a rate limiter.\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch (`git checkout -b feature/amazing-feature`)\n3. Commit your changes (`git commit -m 'Add amazing feature'`)\n4. Push to the branch (`git push origin feature/amazing-feature`)\n5. Open a Pull Request\n\n## Support\n\nIf you encounter any issues or have questions:\n\n1. Check the [troubleshooting section](#-troubleshooting)\n2. Search existing issues on GitHub\n3. Create a new issue with detailed information\n\n## Deployment Checklist\n\n- [ ] Set `frontend.url` and the `LINKS` KV namespace in the deployment configuration\n- [ ] Deployed `docs/` to Cloudflare Pages\n- [ ] Created Cloudflare KV namespace\n- [ ] Configured `wrangler.toml` with correct KV namespace ID\n- [ ] Protected the Worker with a Cloudflare Access policy\n- [ ] Deployed the Worker using `pnpm deploy`\n- [ ] Tested URL shortening at `POST /`\n- [ ] Verified copy-to-clipboard feature works\n- [ ] Tested custom error pages (404, security warnings)\n- [ ] (Optional) Configured custom domain\n- [ ] (Optional) Added Google Safe Browsing API key\n","readmeFilename":"README.md"}