{"id":19273648,"url":"https://github.com/yusufshakeel/couponjs","last_synced_at":"2025-04-21T22:33:05.409Z","repository":{"id":42921531,"uuid":"245202113","full_name":"yusufshakeel/couponjs","owner":"yusufshakeel","description":"Generate coupons.","archived":false,"fork":false,"pushed_at":"2025-02-11T12:44:53.000Z","size":1130,"stargazers_count":7,"open_issues_count":0,"forks_count":4,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-16T04:47:55.583Z","etag":null,"topics":["coupon","es6","javascript","js","nodejs","ts","typescript"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/couponjs","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yusufshakeel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-03-05T15:39:32.000Z","updated_at":"2025-02-11T15:44:29.000Z","dependencies_parsed_at":"2024-06-21T02:36:06.187Z","dependency_job_id":"b6b66cc8-d6f4-4a68-9ad5-fab4d20847a2","html_url":"https://github.com/yusufshakeel/couponjs","commit_stats":{"total_commits":240,"total_committers":2,"mean_commits":120.0,"dds":0.04583333333333328,"last_synced_commit":"3fe48256c90cce33a0eee1b3bf0d6c5ad37ab8f7"},"previous_names":[],"tags_count":38,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yusufshakeel%2Fcouponjs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yusufshakeel%2Fcouponjs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yusufshakeel%2Fcouponjs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yusufshakeel%2Fcouponjs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yusufshakeel","download_url":"https://codeload.github.com/yusufshakeel/couponjs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250145024,"owners_count":21382336,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["coupon","es6","javascript","js","nodejs","ts","typescript"],"created_at":"2024-11-09T20:43:43.417Z","updated_at":"2025-04-21T22:33:00.397Z","avatar_url":"https://github.com/yusufshakeel.png","language":"TypeScript","funding_links":["https://www.paypal.me/yusufshakeel"],"categories":[],"sub_categories":[],"readme":"# couponjs\n\nGenerate coupons.\n\n[![Build Status](https://github.com/yusufshakeel/couponjs/actions/workflows/ci.yml/badge.svg)](https://github.com/yusufshakeel/couponjs/actions/workflows/ci.yml)\n[![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/yusufshakeel/couponjs)\n[![npm version](https://img.shields.io/badge/npm-0.15.0-blue.svg)](https://www.npmjs.com/package/couponjs)\n[![npm Downloads](https://img.shields.io/npm/dm/couponjs.svg)](https://www.npmjs.com/package/couponjs)\n\n![CouponJS](./resource/couponjs-500x150.png)\n\n## Use case\n\nImport. Configure. Generate.\n\nThis is a simple project to generate coupons. Lots of coupons.\n\nImport the package, configure (this is optional), generate (1 or more coupons) and then use the coupons however\nyou like (save in database, etc).\n\n## Table of Contents\n\n* [Getting Started](#getting-started)\n* [Generate coupon](#generate-coupon)\n* [Coupon engine configuration](#coupon-engine-configuration)\n  * [Verbose](#verbose)\n  * [Log Performance](#log-performance)\n  * [Maximum number of coupons to generate](#maximum-number-of-coupons-to-generate)\n* [Configuration to generate coupons](#configuration-to-generate-coupons)\n  * [Coupon of length N](#coupon-of-length-n)\n  * [Coupon with prefix](#coupon-with-prefix)\n  * [Coupon with suffix](#coupon-with-suffix)\n  * [Coupon with prefix and suffix](#coupon-with-prefix-and-suffix)\n  * [Coupon with built in character set](#coupon-with-built-in-character-set)\n  * [Coupon with custom characterSet](#coupon-with-custom-characterset)\n  * [Coupons using built in and custom character set](#coupons-using-built-in-and-custom-character-set)\n  * [Generate multiple unique coupons](#generate-multiple-unique-coupons)\n  * [Omit characters](#omit-characters)\n  * [Format coupons](#format-coupons)\n    * [String format rule](#string-format-rule)\n    * [Object format rule](#object-format-rule)\n  * [Format coupon with prefix and suffix](#format-coupon-with-prefix-and-suffix)\n    * [String format rule and prefix-suffix combo](#string-format-rule-and-prefix-suffix-combo)\n    * [Object format rule and prefix-suffix combo](#object-format-rule-and-prefix-suffix-combo)\n* [Possible number of coupons](#possible-number-of-coupons)\n* [Storage size](#storage-size)\n* [Older version](#older-version)\n* [License](#license)\n* [Donate](#donate)\n\n# Getting Started\n\n#### Install\n\n```\nnpm i couponjs\n```\n\n#### Require\n\n```js\n// ESM\nimport CouponJS from 'couponjs';\n\n// CommonJs\nconst { CouponJS } = require('couponjs');\n```\n\n## Generate coupon\n\nCreate an object.\n\n```javascript\nconst coupon = new CouponJS();\n```\n\nNow, call the `generate` method.\n\n```javascript\nconst myCoupon = coupon.generate();\n```\n\nThe above code will produce coupon like `ASDFGH`.\n\nBy default, `generate` will return coupon code of length 6 using uppercase alphabet.\n\n## Coupon engine configuration\n\nWe can configure the CouponJS engine to get reponse in a different format.\n\nThe syntax looks like the following.\n\n```javascript\nconst coupon = new CouponJS({ key: value });\n```\n\n### Verbose\n\nIf we want verbose response (success/error) then we can set the field `verbose` to true.\n\nDefault value: `false`\n\n```javascript\nconst coupon = new CouponJS({ verbose: true });\n```\n\nIf set to `true` then success response will look like the following.\n\n```\n{\n  status: 'success', \n  numberOfCoupons: 1, \n  coupons: ['QWERTY']\n}\n```\n\nAnd error response will look like the following.\n\n```\n{\n  status: 'error',\n  error: {\n    type: 'COUPONJS_VALIDATION_ERROR',\n    message: 'Invalid characters used in the format rule.',\n    errors: [\n      {\n        field: 'format',\n        type: 'COUPONJS_FORMAT_ERROR',\n        message: 'Invalid characters used in the format rule. Only x and - are allowed. And only one - inbetween like xxx-xxx.'\n      }\n    ]\n  }\n}\n```\n\n### Log Performance\n\nTo log the performance we have to set the option `logPerformance` to `true`.\n\nDefault value: `false`\n\nDepends on: [verbose](#verbose) to be `true`.\n\nSyntax:\n\n```javascript\nconst coupon = new CouponJS({ \n  verbose: true,\n  logPerformance: true\n});\n```\n\nThis will return success response like the following.\n\n```\n{\n  \"status\": \"success\",\n  \"numberOfCoupons\": 1,\n  \"coupons\": [\n    \"QWERTY\"\n  ],\n  \"performance\": {\n    \"duration\": {\n      \"nano\": 730779,\n      \"micro\": 730.779,\n      \"milli\": 0.730779,\n      \"second\": 0.000730779\n    }\n  }\n}\n```\n\nAnd error response like the following.\n\n```\n{\n  \"status\": \"error\",\n  \"error\": {\n    \"message\": \"Invalid characters used in the format rule.\",\n    \"type\": \"COUPONJS_VALIDATION_ERROR\",\n    \"errors\": [\n      {\n        \"type\": \"COUPONJS_FORMAT_ERROR\",\n        \"field\": \"format\",\n        \"message\": \"Invalid characters used in the format rule. Only x and - are allowed. And only one - inbetween like xxx-xxx.\"\n      }\n    ]\n  },\n  \"performance\": {\n    \"duration\": {\n      \"nano\": 1313840,\n      \"micro\": 1313.84,\n      \"milli\": 1.31384,\n      \"second\": 0.00131384\n    }\n  }\n}\n```\n\n### Maximum number of coupons to generate\n\nBy default, we can generate `100000` coupons.\n\nIf we want to increase or decrease the number of coupons that can be generated then we set the `maxNumberOfCouponsToGenerate`\nfield.\n\nIt takes an integer value greater than 0.\n\nDefault value: `100000`\n\nSyntax:\n\n```javascript\nconst coupon = new CouponJS({ \n  maxNumberOfCouponsToGenerate: 100\n});\n```\n\n## Configuration to generate coupons\n\nWe can pass different options to configure the engine to generate coupons as per our settings.\n\nEample:\n\n```javascript\nconst myCoupon = coupon.generate({\n  length: 8\n});\n```\n\nOptions that we can use are listed below.\n\n## Coupon of length N\n\nTo generate coupon of a given length we pass the following option to the `generate` method.\n\n```javascript\nconst myCoupon = coupon.generate({\n  length: 8\n});\n```\n\nWhere, 8 in the above code represent the total number of characters that will be present in the coupon.\n\nRange of `length`\n* Min: 1\n* Max: 128\n\nIf length is not passed then default value of 6 is considered.\n\n## Coupon with prefix\n\nTo generate a coupon with a given prefix we pass the following option to the `generate` method.\n\n```javascript\nconst myCoupon = coupon.generate({\n  prefix: 'SUPER'\n});\n```\n\nThe above code will generate coupon with prefix 'SUPER'. Default lenght of the coupon is 6. So, we will get coupon like the following.\n\n`SUPERAAAAAA`\n\nNote! Prefix characters are not counted.\n\nIf we want to generate coupon of length 3 with prefix 'SUPER' then our option will look like the following.\n\n```javascript\nconst myCoupon = coupon.generate({\n  length: 3,\n  prefix: 'SUPER'\n});\n```\n\nWe will get coupon like the following `SUPERAAA`.\n\n## Coupon with suffix\n\nTo create coupon with suffix pass the following option.\n\n```javascript\nconst myCoupon = coupon.generate({\n  length: 3,\n  suffix: 'AWESOME'\n});\n```\n\nThe above code will generate coupon like the following `ZZZAWESOME`.\n\nNote! Characters of the suffix is not counted. If length is not specified then default value of 6 is considered as the length.\n\n## Coupon with prefix and suffix\n\nTo create coupon with prefix and suffix pass the following option.\n\n```javascript\nconst myCoupon = coupon.generate({\n  length: 6,\n  prefix: 'SUPER',\n  suffix: 'AWESOME'\n});\n```\n\nThe above code will generate coupon like the following `SUPERZZZZZZAWESOME`.\n\nNote! The characters of the prefix and suffix is not considered. If length is not specified then default value of 6 is considered.\n\n## Coupon with built in character set\n\nTo create coupon code with built in character set pass the following option.\n\n```javascript\nconst myCoupon = coupon.generate({\n  characterSet: {\n    builtIn: ['charSetName']\n  }\n});\n```\n\nWhere, `charSetName` is any of the following\n\n- `CHARSET_ALPHA` -- consists of uppercase alphabet characters `A-Z`\n- `CHARSET_ALPHA_LOWER` -- consists of lowercase alphabet characters `a-z`\n- `CHARSET_DIGIT` -- consists of digits `0-9`\n- `CHARSET_ALNUM` -- consists of uppercase alphabet `A-Z`, lowercase alphabet `a-z` and digit `0-9`\n- `CHARSET_BINARY` -- consists of characters `01`\n- `CHARSET_OCTAL` -- consists of characters `01234567`\n- `CHARSET_HEX` -- consists of characters `0-9` and `A-F`\n- `CHARSET_HEX_LOWER` -- consists of characters `0-9` and `a-f`\n\nExample: If we want uppercase and digit we can pass the following.\n\n```javascript\nconst myCoupon = coupon.generate({\n  characterSet: {\n    builtIn: ['CHARSET_ALPHA', 'CHARSET_DIGIT']\n  }\n});\n```\n\nReference:\n\n* [Possible number of coupons](#possible-number-of-coupons)\n\n## Coupon with custom characterSet\n\nTo use custom characters to generate coupons pass the following option.\n\n```javascript\nconst myCoupon = coupon.generate({\n  characterSet: {\n    custom: ['customChar']\n  }\n});\n```\n\nWhere, `customChar` is any custom characters that you wish to use.\n\nExample: To use `ABC`, `xyz` and `01234` in coupon pass the following.\n\n```javascript\nconst myCoupon = coupon.generate({\n  characterSet: {\n    custom: ['ABC', 'xyz', '01234']\n  }\n});\n```\n\n## Coupons using built in and custom character set\n\nExample: Following option will use digit `0-9` and alphabet `ABC`.\n\n```javascript\nconst myCoupon = coupon.generate({\n  characterSet: {\n    builtIn: ['CHARSET_DIGIT'],\n    custom: ['ABC']\n  }\n});\n```\n\n## Generate multiple unique coupons\n\nPass the following to generate multiple unqiue coupons.\n\n```javascript\nconst myCoupons = coupon.generate({\n  numberOfCoupons: number\n});\n```\n\nThe above code will return an array of coupons.\n\nWhere, `number` represents the total number of unique coupons to generate.\n\nRange of `numberOfCoupons`\n\n- Min 1\n- Max 100000\n\nExample:\n\nFollowing code will generate 3 unique coupons of length 8 using builtIn `CHARSET_ALPHA` and `CHARSET_DIGIT` option.\n\n```javascript\nconst myCoupons = coupon.generate({\n  length: 8,\n  numberOfCoupons: 3,\n  characterSet: {\n    builtIn: ['CHARSET_ALPHA', 'CHARSET_DIGIT']\n  }\n});\n```\n\nSample output:\n\n```\n['95TMY9JV', 'RZU6ZL0K', '1Q19N019']\n```\n\nReference: \n\n* [Maximum number of coupons to generate](#maximum-number-of-coupons-to-generate)\n* [Possible number of coupons](#possible-number-of-coupons)\n\n## Omit characters\n\nTo omit characters from the generated coupon code we pass the following option.\n\n```javascript\nconst myCoupons = coupon.generate({\n  omitCharacters: ['charToOmit']\n});\n```\n\nWhere, `omitCharacters` is the field that will help in omitting the characters.\n\n`charToOmit` is a string of characters to omit from the generated coupon codes.\n\nExample:\n\n```javascript\nconst myCoupons = coupon.generate({\n  omitCharacters: ['ABC', 'XYZ']\n});\n```\n\nThe above code will generate coupons that will omit characters `A`, `B`, `C`, `X`, `Y` and `Z`.\n\n## Format coupons\n\nWe can format the coupons that are generated by the engine in two ways.\n\n* [Using string rule](#string-format-rule)\n* [Using object rule](#object-format-rule)\n\n### String format rule\n\nThis is the quick and easy way to format the coupon.\n\nUse `x`'s for coupon characters and `-`'s to separate them into groups.\n\nExample:\n\nIn the following setup we want to generate total `3` coupons.\nEach coupons will be formatted like `xxxx-xxxx-xxxx` where, `x`'s represents the coupon character\nand `-`'s represent the separator. Length of each coupon code is 12.\n\nNote! Total number of characters in the coupon code must be equal to the number of `x`'s in the format.\n\n```javascript\nconst myCoupons = coupon.generate({\n  format: 'xxxx-xxxx-xxxx',\n  length: 12,\n  numberOfCoupons: 3\n});\n```\n\nSample output:\n\n```\n['OHGP-DTMG-HINR', 'DKXN-ALFH-LOQX', 'TAFK-GVXJ-WMPR']\n```\n\n### Object format rule\n\nThis gives us more formatting options and looks like the following.\n\n```\n{\n  separators: ['chars', 'chars', ...],\n  groups: [size, size, ...]\n}\n```\n\nWhere, `separators` are the ones separating the coupon characters into groups.\nAnd `groups` represents the size of each group.\n\n`chars` represents the separator characters. It can be a single character or multiple characters like '-' or '##'. \n\n`size` represents the size of a group. It is an integer value greater than 0.\n\nNote! Total number of elements in the `separators` array must be one less than the total number of elements\nin the `groups` array.\n\nExample:\n\nIn the following example we are generating `3` coupons each having `12` characters.\n\nWe are formatting the coupons into `4 groups` having 2, 4, 4, and 2 characters in that order.\n\nAnd we are separating the\n\n* 1st and 2nd group with `-`\n* 2nd and 3rd group with `~`\n* 3rd and 4th group with `-`\n\n```javascript\nconst myCoupons = coupon.generate({\n  format: {\n    separators: ['-', '~', '-'],\n    groups: [2, 4, 4, 2]\n  },\n  length: 12,\n  numberOfCoupons: 3\n});\n```\n\n```\n['OH-GPDT~MGHI-NR', 'DK-XBCL~FHLO-QX', 'TA-FKGV~XJWM-PR']\n```\n\n## Format coupon with prefix and suffix\n\nIf we have prefix and suffix then we have to consider the total number of characters in them too while setting the format field.\n\n### String format rule and prefix-suffix combo\n\nLets say we want to generate a coupon having 6 characters and also add prefix `QWERT` and suffix `ZXCVB` to it.\n\nSo, our configuration will look something like the following.\n\n```javascript\nconst myCoupon = coupon.generate({\n  length: 6,\n  prefix: 'QWERT',\n  suffix: 'ZXCVB'\n});\n```\n\nOn executing this we will get coupon code like\n\n```\nQWERTOWLZJHZXCVB\n```\n\nNote! Total number of characters in the generated coupon is `5+6+5`.\n\n```\nQWERT = 5 characters (prefix)\nOWLZJH = 6 characters (generated coupon, as length is set to 6)\nZXCVB = 5 characters (suffix)\n------------------------------\nTotal = 16 characters (coupon with prefix and suffix)\n```\n\nTo format the above generated coupon with prefix and suffix we have to consider total 16 `x`'s.\n\nIn the following configuration we are formatting the coupon with prefix and suffix.\n\n```javascript\nconst myCoupon = coupon.generate({\n  length: 6,\n  prefix: 'QWERT',\n  suffix: 'ZXCVB',\n  format: 'xxxx-xxxx-xxxx-xxxx'\n});\n```\n\nOn executing this we will get coupon code like\n\n```\nQWER-TOWL-ZJHZ-XCVB\n```\n\n### Object format rule and prefix-suffix combo\n\nIf we want to generate a coupon having 6 characters and attach prefix `QWERT` and suffix `ZXCVB` then our configuration\nwill look like the following.\n\n```javascript\nconst myCoupon = coupon.generate({\n  length: 6,\n  prefix: 'QWERT',\n  suffix: 'ZXCVB',\n  format: {\n    separators: ['-', '~', '-'],\n    groups: [2, 6, 6, 2]\n  }\n});\n```\n\nWe are formatting the coupon into `4 groups` having 2, 6, 6, and 2 characters in that order.\n\nAnd we are separating the\n\n* 1st and 2nd group with `-`\n* 2nd and 3rd group with `~`\n* 3rd and 4th group with `-`\n\nAnd we can add the following `format` configuration to get formatted coupon.\n\nOn executing this we will get coupon code like\n\n```\nQW-ERTOWL~ZJHZXC-VB\n```\n\n## Possible number of coupons\n\nThis section estimates the possible number of coupons that can be generated using different combinations of characters.\n\n|Character Set       |Characters    |Total Characters    |Coupon Length |Total possibility |Coupon Length |Total possibility |Coupon Length |Total possibility |\n|--------------------|--------------|--------------------|--------------|-----------------:|--------------|-----------------:|--------------|-----------------:|\n|CHARSET_ALPHA       |A-Z           |26                  |6             |308915776         |8             |208827064576      |12            |9.5428957e+16     |\n|CHARSET_ALPHA_LOWER |a-z           |26                  |6             |308915776         |8             |208827064576      |12            |9.5428957e+16     |\n|CHARSET_DIGIT       |0-9           |10                  |6             |1000000           |8             |100000000         |12            |1e+12             |\n|CHARSET_ALNUM       |A-Z, a-z, 0-9 |62                  |6             |56800235584       |8             |2.1834011e+14     |12            |3.2262668e+21     |\n|CHARSET_BINARY      |0-1           |2                   |6             |64                |8             |256               |12            |4096              |\n|CHARSET_OCTAL       |0-7           |8                   |6             |262144            |8             |16777216          |12            |68719476736       |\n|CHARSET_HEX         |0-9, A-F      |16                  |6             |16777216          |8             |4294967296        |12            |2.8147498e+14     |\n|CHARSET_HEX_LOWER   |0-9, a-f      |16                  |6             |16777216          |8             |4294967296        |12            |2.8147498e+14     |\n\n\nPoints to note!\n\n* Repetition of characters considered in the above computation.\n* Prefix and Suffix not considered in the above computaion.\n* Omit characters is not set in the above computation.\n* Different mix of character sets can be used to change the total number of possible coupons that can be generated.\n* Speed and generation of coupons will also depend on the hardware used.\n\n## Storage size\n\nIn this section we estimate the rough storage size based on the coupon size and number of coupons generated.\n\nAssumption:\n* Using UTF8 characters and each character taking up 1 byte storage.\n\n|Total Characters |Number of coupons     |Size (MB)         |Size (GB)         |\n|----------------:|---------------------:|-----------------:|-----------------:|\n|6                |1000                  |0.006             |0.000006          |\n|6                |10000                 |0.060             |0.000060          |\n|6                |100000                |0.600             |0.000600          |\n|6                |1000000               |6.000             |0.006000          |\n|6                |10000000              |60.000            |0.060000          |\n|6                |100000000             |600.000           |0.600000          |\n|6                |1000000000            |6000.000          |6.000000          |\n\n|Total Characters |Number of coupons     |Size (MB)         |Size (GB)         |\n|----------------:|---------------------:|-----------------:|-----------------:|\n|8                |1000                  |0.008             |0.000008          |\n|8                |10000                 |0.080             |0.000080          |\n|8                |100000                |0.800             |0.000800          |\n|8                |1000000               |8.000             |0.008000          |\n|8                |10000000              |80.000            |0.080000          |\n|8                |100000000             |800.000           |0.800000          |\n|8                |1000000000            |8000.000          |8.000000          |\n\n|Total Characters |Number of coupons     |Size (MB)         |Size (GB)         |\n|----------------:|---------------------:|-----------------:|-----------------:|\n|12               |1000                  |0.012             |0.000012          |\n|12               |10000                 |0.120             |0.000120          |\n|12               |100000                |1.200             |0.001200          |\n|12               |1000000               |12.000            |0.012000          |\n|12               |10000000              |120.000           |0.120000          |\n|12               |100000000             |1200.000          |1.200000          |\n|12               |1000000000            |12000.000         |12.000000         |\n\n|Total Characters |Number of coupons     |Size (MB)         |Size (GB)         |\n|----------------:|---------------------:|-----------------:|-----------------:|\n|16               |1000                  |0.016             |0.000016          |\n|16               |10000                 |0.160             |0.000160          |\n|16               |100000                |1.600             |0.001600          |\n|16               |1000000               |16.000            |0.016000          |\n|16               |10000000              |160.000           |0.160000          |\n|16               |100000000             |1600.000          |1.600000          |\n|16               |1000000000            |16000.000         |16.000000         |\n\n### Older version\n\n[CommonJS version - check v0.9.4](https://github.com/yusufshakeel/couponjs/tree/v0.9.4)\n\n## License\n\nIt's free :smiley:\n\n[MIT License](https://github.com/yusufshakeel/couponjs/blob/master/LICENSE) Copyright (c) 2020 Yusuf Shakeel\n\n### Donate\n\nFeeling generous :smiley: [Donate via PayPal](https://www.paypal.me/yusufshakeel)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyusufshakeel%2Fcouponjs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyusufshakeel%2Fcouponjs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyusufshakeel%2Fcouponjs/lists"}