{"_id":"@wcota/wurl-client","_rev":"28-f918e6b0d1c96006a3c0309e3bb1447d","name":"@wcota/wurl-client","dist-tags":{"latest":"0.2.2"},"versions":{"0.1.5":{"name":"@wcota/wurl-client","version":"0.1.5","author":{"name":"Wesley Cota"},"license":"ISC","_id":"@wcota/wurl-client@0.1.5","maintainers":[{"name":"wcota","email":"npm@wcota.me"}],"homepage":"https://github.com/wcota/wurl-client#readme","bugs":{"url":"https://github.com/wcota/wurl-client/issues"},"dist":{"shasum":"c2b081cf0c827dd62cae83f1c0e227baebc3a4e6","tarball":"https://registry.npmjs.org/@wcota/wurl-client/-/wurl-client-0.1.5.tgz","fileCount":5,"integrity":"sha512-Akl5ZlEw6dLNc8aKlvJ10SGL1SZvaF0B2W9MrJWcRlLuzKTFvKgRQZBlbhdBKZjgBO7ux1qXoWmnLk45oFCt5w==","signatures":[{"sig":"MEYCIQCHH+9W8z8Fq6amOgW/yrtw4ZxIsr1oibegSwGquiK/ngIhAJSHh3tz0qu54Ud9z/KgdJZdtwluCyPWWsJ/RRJQ3pgx","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":8339},"main":"index.js","type":"module","gitHead":"fc34b9ac0a632cdfe0b290e4e02ff5b0c521767e","scripts":{"test":"nodeunit --reporter=minimal test.js"},"_npmUser":{"name":"wcota","email":"npm@wcota.me"},"repository":{"url":"git+https://github.com/wcota/wurl-client.git","type":"git"},"_npmVersion":"8.19.2","description":"NodeJS client of a URL shortener using a database of URLs and Clicks. Provides a function to get the redirected URL and another to save the access.","directories":{},"_nodeVersion":"20.3.1","dependencies":{"request-ip":"^3.3.0","turbo-geoip-country":"^23.7.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.6.1","node-mocks-http":"^1.12.2"},"_npmOperationalInternal":{"tmp":"tmp/wurl-client_0.1.5_1690468956569_0.7458212777637379","host":"s3://npm-registry-packages"}},"0.2.0":{"name":"@wcota/wurl-client","version":"0.2.0","author":{"name":"Wesley Cota"},"license":"ISC","_id":"@wcota/wurl-client@0.2.0","maintainers":[{"name":"wcota","email":"npm@wcota.me"}],"homepage":"https://github.com/wcota/wurl-client#readme","bugs":{"url":"https://github.com/wcota/wurl-client/issues"},"dist":{"shasum":"6fbffc614d2441e409ed7e3559a0d956ccb41cc6","tarball":"https://registry.npmjs.org/@wcota/wurl-client/-/wurl-client-0.2.0.tgz","fileCount":6,"integrity":"sha512-RbDCQUxQ8kdXlzaQ5mXdh3/boIFjnrdunB4/yWDXbp9w2lhwAGooBRXhHphjuG/P4Vb8hUPL50jpptbS9i2DOA==","signatures":[{"sig":"MEQCIBN7XDRfa6aZ3oEZXhrrxOhxCKsJ/j6os0LyricjMQ8fAiBHWuABHW4RiCfJndYSm4IMQJTok7Nd0aB/PEWI6oMDWA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":29570},"main":"index.js","type":"module","gitHead":"7b625638544c263b6a874f19256d4b91e8beac32","scripts":{"test":"nodeunit --reporter=minimal test.js"},"_npmUser":{"name":"wcota","email":"npm@wcota.me"},"repository":{"url":"git+https://github.com/wcota/wurl-client.git","type":"git"},"_npmVersion":"8.19.2","description":"NodeJS client of a URL shortener using a database of URLs and Clicks. Provides a function to get the redirected URL and another to save the access.","directories":{},"_nodeVersion":"20.3.1","dependencies":{"request-ip":"^3.3.0","turbo-geoip-country":"^23.7.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.6.1","node-mocks-http":"^1.12.2"},"_npmOperationalInternal":{"tmp":"tmp/wurl-client_0.2.0_1690469408779_0.7408151074064506","host":"s3://npm-registry-packages"}},"0.2.1":{"name":"@wcota/wurl-client","version":"0.2.1","author":{"name":"Wesley Cota"},"license":"ISC","_id":"@wcota/wurl-client@0.2.1","maintainers":[{"name":"wcota","email":"npm@wcota.me"}],"homepage":"https://github.com/wcota/wurl-client#readme","bugs":{"url":"https://github.com/wcota/wurl-client/issues"},"dist":{"shasum":"9a349dc3361db779a9fbdac724fb611b6e421d51","tarball":"https://registry.npmjs.org/@wcota/wurl-client/-/wurl-client-0.2.1.tgz","fileCount":6,"integrity":"sha512-XeYxbS8y5SXKRz2MwYJy43+WTpG3pzyE4qxVS5E0q8t0lRZmDNE+Sx1o9IbrWFzb7wTcSAUw8Ze+mBmveEI55g==","signatures":[{"sig":"MEYCIQCoTLjAL49dTpiDUGenF7vyR/3JKpgvMk573NMdGTsD6gIhAOeeVAVybVccidBq7IUpXcU6Ll4G7vbuQUseMUHRjtAG","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":29570},"main":"index.js","type":"module","gitHead":"0333214aa30323aa48567dbd838a2ebd9a5a3a76","scripts":{"test":"nodeunit --reporter=minimal test.js"},"_npmUser":{"name":"wcota","email":"npm@wcota.me"},"repository":{"url":"git+https://github.com/wcota/wurl-client.git","type":"git"},"_npmVersion":"11.5.2","description":"NodeJS client of a URL shortener using a database of URLs and Clicks. Provides a function to get the redirected URL and another to save the access.","directories":{},"_nodeVersion":"24.5.0","dependencies":{"request-ip":"^3.3.0","turbo-geoip-country":"^23.7.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.6.1","node-mocks-http":"^1.12.2"},"_npmOperationalInternal":{"tmp":"tmp/wurl-client_0.2.1_1758841882590_0.4329601486928818","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"@wcota/wurl-client","version":"0.2.2","description":"NodeJS client of a URL shortener using a database of URLs and Clicks. Provides a function to get the redirected URL and another to save the access.","main":"index.js","type":"module","scripts":{"test":"nodeunit --reporter=minimal test.js"},"repository":{"type":"git","url":"git+https://github.com/wcota/wurl-client.git"},"author":{"name":"Wesley Cota"},"license":"ISC","bugs":{"url":"https://github.com/wcota/wurl-client/issues"},"homepage":"https://github.com/wcota/wurl-client#readme","devDependencies":{"jest":"^29.6.1","node-mocks-http":"^1.12.2"},"dependencies":{"request-ip":"^3.3.0","turbo-geoip-country":"^25.7.0"},"_id":"@wcota/wurl-client@0.2.2","gitHead":"0333214aa30323aa48567dbd838a2ebd9a5a3a76","_nodeVersion":"24.5.0","_npmVersion":"11.5.2","dist":{"integrity":"sha512-oD4iAVPA+WX3hv/FSjdfHTH7aE5aBxfpq2Pvaubyl54bJrA2ph6XxWtWpnxtNI6cWlrsQ7ryWAWgrrYeyow3oQ==","shasum":"7322d7edd64ec5b4d2fb7b070318576367a78d16","tarball":"https://registry.npmjs.org/@wcota/wurl-client/-/wurl-client-0.2.2.tgz","fileCount":6,"unpackedSize":29570,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIFOKwuoUkujq3cxK2U+NMh94JicAmqp7XveYcawXoi0IAiAvzSSbm5q5mQHU9ul5okJB21Gf+NBZWKngx8y6PaGFxQ=="}]},"_npmUser":{"name":"wcota","email":"npm@wcota.me"},"directories":{},"maintainers":[{"name":"wcota","email":"npm@wcota.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/wurl-client_0.2.2_1758842137094_0.4434019067702122"},"_hasShrinkwrap":false}},"time":{"created":"2023-07-26T14:46:55.213Z","modified":"2025-09-25T23:15:37.509Z","0.0.1":"2023-07-26T14:46:55.478Z","0.0.2":"2023-07-26T14:56:28.021Z","0.0.3":"2023-07-26T15:42:04.463Z","0.0.5":"2023-07-26T17:51:35.798Z","0.0.6":"2023-07-26T18:03:01.540Z","0.0.7":"2023-07-26T18:28:38.707Z","0.0.8":"2023-07-27T02:21:54.195Z","0.0.9":"2023-07-27T03:13:59.209Z","0.1.1":"2023-07-27T03:20:21.664Z","0.1.2":"2023-07-27T03:30:39.967Z","0.1.3":"2023-07-27T14:22:12.859Z","0.1.4":"2023-07-27T14:26:35.726Z","0.1.5":"2023-07-27T14:42:36.729Z","0.2.0":"2023-07-27T14:50:08.973Z","0.2.1":"2025-09-25T23:11:22.766Z","0.2.2":"2025-09-25T23:15:37.286Z"},"bugs":{"url":"https://github.com/wcota/wurl-client/issues"},"author":{"name":"Wesley Cota"},"license":"ISC","homepage":"https://github.com/wcota/wurl-client#readme","repository":{"type":"git","url":"git+https://github.com/wcota/wurl-client.git"},"description":"NodeJS client of a URL shortener using a database of URLs and Clicks. Provides a function to get the redirected URL and another to save the access.","maintainers":[{"name":"wcota","email":"npm@wcota.me"}],"readme":"# w-URL - URL shortener \n\n[![CC BY-NC-SA 4.0][cc-by-nc-sa-shield]][cc-by-nc-sa]\n\nThis is a simple package that provides a function to look for a `id` in a `Url` table and return the redirected URL, and save the click with IP, time, userAgent, referer, and country code of the user.\n\nTo install it, you will need to use [Prisma ORM](https://www.prisma.io/) with the following models in the DB schema:\n\n```prisma\nmodel Url {\n  id        String   @id\n  url       String\n  title     String?\n  createdBy String\n  createdAt DateTime @default(now())\n  updatedAt DateTime @default(now())\n  clicks    Click[]\n}\n\nmodel Click {\n  id            Int      @id @default(autoincrement())\n  time          DateTime @default(now())\n  referer      String\n  userAgent     String\n  clickedBy     String\n  countryCode   String\n  urlId         String?\n  originalUrlId String?\n  requestedUrl  String?\n  Url           Url?     @relation(fields: [urlId], references: [id])\n}\n```\n\n**Note that the write access is needed for `Click` table!**.\n\n## Initializing\n\nImport the client using `import wurl from '@wcota/wurl-client'`. Now, call `wurl.init(prisma)` with a given Prisma client with access to `Url` and `Click` models.  It will link the w-URL client with Prisma. If debug is necessary (please do not use in production!), pass the flag `debug = true` in `wurl.init()`.\n\n## Using `find()`\n\nThis function is `async`, requiring the `id` and an optional `req` object with the HTTP request object. Prisma will try to find the given URL data from for `id`, and if `req` is provided, will add the access to `id` in the Click table with the timestamp, referer, user agent, IP, country code, requested ID, original request URL, and URL to where the user was redirected.\n\nIn case of success (`id` exists), the following object is returned:\n\n```js\n{\n  status: \"ok\", // \"ok\" means that the ID was found\n  data: {\n    id: \"example\", // the requested ID\n    url: \"https://example.com\", // the redirected URL\n    title: \"Example.com web page!\", // title of the page, as it is in the database\n    createdBy: \"127.0.0.1\", // IP of who created the ID\n    createdAt: 2021-03-06T00:43:05.000Z, // timestamp of creation\n    updatedAt: 2022-08-08T04:22:55.723Z // timestamp of last modified\n  },\n  errorCode: undefined, // 500 if there was an error adding the click info\n  errorMessage: undefined // \"error while saving click\" if there was an error adding the click info\n}\n```\n\nNote the `errorCode` if there is an error saving the user's information. \n\nIf the URL does not exist (`id` is not found), the following JSON object is returned, without `data` keyword:\n\n```js\n{\n  status: \"error\", // \"error\" means that the ID was not found or there was another error\n  errorCode: 404, // or 500 if there was an error finding the ID\n  errorMessage: \"not found\" // or \"error while finding link\" if there was an error finding the ID\n}\n```\n\nAll the errors are saved with `console.error()` for debugging.\n\n## Click data\n\nThe user data consists of the following information:\n\n```js\n{\n    referer, // referer address\n    userAgent, // user agent\n    clickedBy, // IP of the user\n    countryCode, // 2 letters country code\n    originalUrlId, // the id accessed when clicked\n    urlId, // the id associated to the click, if the ID was found\n    requestedUrl // the requested URL, preserving query strings and so on\n}\n```\n\nNote that `urlId` and `originalUrlId` can be different. The first only exists if the respective ID was found. It may be different if the ID of the associated click has been changed in the `Url` table.\n\n## Using it in Next.JS\n\nCreate a file at `/lib/wurl.js` with the following content:\n\n```js\nimport { prisma } from '@/lib/db'\nimport wurl from '@wcota/wurl-client'\n\nwurl.init(prisma, false)\n\nexport default wurl\n```\n\nNow, import it where you want to use, such as\n\n```js\nimport wurl from '@/lib/wurl'\n\nexport const getServerSideProps = async ({req, res, params}) => {\n\n    const result = await wurl.find(params.id, req)\n\n    if (result.status != 'ok') {\n        return {\n            redirect: {\n                destination: process.env.DEFAULT_URL_REDIRECT,\n                statusCode: 302\n            }\n        }\n    }\n\n    return {\n        redirect: {\n            destination: result.data.url,\n            statusCode: 301\n        }\n    }\n    \n    return null\n}\n```\n\n## Licence\n\nThis work is licensed under a\n[Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License][cc-by-nc-sa].\n\n[![CC BY-NC-SA 4.0][cc-by-nc-sa-image]][cc-by-nc-sa]\n\n[cc-by-nc-sa]: http://creativecommons.org/licenses/by-nc-sa/4.0/\n[cc-by-nc-sa-image]: https://licensebuttons.net/l/by-nc-sa/4.0/88x31.png\n[cc-by-nc-sa-shield]: https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-lightgrey.svg","readmeFilename":"README.md"}