domain-quotes 0.0.11 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +19 -18
  2. package/dist/index.js +1 -1
  3. package/package.json +11 -8
package/README.md CHANGED
@@ -1,12 +1,12 @@
1
- # DomainPrices
1
+ # Domain Quotes
2
2
 
3
- [![Build](https://github.com/namewiz/domainprices/actions/workflows/build.yml/badge.svg)](https://github.com/namewiz/domainprices/actions/workflows/build.yml)
4
- [![Test](https://github.com/namewiz/domainprices/actions/workflows/test.yml/badge.svg)](https://github.com/namewiz/domainprices/actions/workflows/test.yml)
5
- [![NPM](http://img.shields.io/npm/v/domainprices.svg)](https://www.npmjs.com/package/domainprices)
6
- [![License](https://img.shields.io/npm/l/domainprices.svg)](https://github.com/namewiz/domainprices/blob/main/LICENSE)
3
+ [![Build](https://github.com/namewiz/domain-quotes/actions/workflows/build.yml/badge.svg)](https://github.com/namewiz/domain-quotes/actions/workflows/build.yml)
4
+ [![Test](https://github.com/namewiz/domain-quotes/actions/workflows/test.yml/badge.svg)](https://github.com/namewiz/domain-quotes/actions/workflows/test.yml)
5
+ [![NPM](http://img.shields.io/npm/v/domain-quotes.svg)](https://www.npmjs.com/package/domain-quotes)
6
+ [![License](https://img.shields.io/npm/l/domain-quotes.svg)](https://github.com/namewiz/domain-quotes/blob/main/LICENSE)
7
7
 
8
8
 
9
- DomainPrices is a lightweight TypeScript/JavaScript library to compute domain registration prices across currencies with discounts and VAT, using curated datasets.
9
+ Domain Quote is a lightweight TypeScript/JavaScript library to compute domain registration quotes across currencies with discounts and VAT, using curated datasets.
10
10
 
11
11
  Includes:
12
12
  - Extension support based on unified registrar price list (OpenProvider/NIRA)
@@ -19,25 +19,25 @@ Includes:
19
19
  Install
20
20
 
21
21
  ```bash
22
- npm i domainprices
22
+ npm i domain-quotes
23
23
  ```
24
24
 
25
25
  Usage
26
26
 
27
27
  ```ts
28
- import { getDefaultPrice, DomainPrices, DEFAULTS_Sept2025 } from 'domainprices';
28
+ import { getDefaultQuote, DomainPrices, DEFAULT_RATES } from 'domain-quotes';
29
29
 
30
- // Quick price (uses bundled defaults)
31
- const quote = await getDefaultPrice('com', 'USD', { discountCodes: ['SAVE10'] });
30
+ // Quick quote (uses bundled defaults)
31
+ const quote = await getDefaultQuote('com', 'USD', { discountCodes: ['SAVE10'] });
32
32
  // → { extension, currency, basePrice, discount, tax, totalPrice, symbol }
33
33
 
34
34
  // Advanced: custom or explicit config via the class
35
- const dp = new DomainPrices(DEFAULTS_Sept2025); // or provide your own DomainPricesConfig
35
+ const dp = new DomainPrices(DEFAULT_RATES); // or provide your own DomainPricesConfig
36
36
  const eur = await dp.getPrice('example.com', 'EUR', { discountPolicy: 'stack' });
37
37
 
38
38
  // Add a 15% markup before discounts/taxes
39
39
  const withMarkup = new DomainPrices({
40
- ...DEFAULTS_Sept2025,
40
+ ...DEFAULT_RATES,
41
41
  markup: { type: 'percentage', value: 0.15 },
42
42
  });
43
43
  const quoteWithMarkup = await withMarkup.getPrice('example.com', 'USD', { discountCodes: ['SAVE10'] });
@@ -45,16 +45,17 @@ const quoteWithMarkup = await withMarkup.getPrice('example.com', 'USD', { discou
45
45
 
46
46
  API
47
47
 
48
- - `getDefaultPrice(extension: string, currency: string, options?: GetPriceOptions): Promise<PriceQuote>`
49
- - Computes price for a TLD/SLD extension (e.g. `com`, `com.ng`, `.org`) using the bundled defaults.
48
+ - `getDefaultQuote(extension: string, currency: string, options?: GetPriceOptions): Promise<PriceQuote>`
49
+ - Computes a quote for a TLD/SLD extension (e.g. `com`, `com.ng`, `.org`) using the bundled defaults.
50
+ - Alias: `getDefaultPrice(...)` for backward-compatibility.
50
51
  - `options`
51
52
  - `discountCodes?: string[]` – one or more codes; case-insensitive.
52
53
  - `now?: number | Date` – inject time for deterministic tests.
53
54
  - `discountPolicy?: 'stack' | 'max'` – default `'max'` (highest single discount only).
54
55
 
55
56
  - `class DomainPrices(config: DomainPricesConfig)`
56
- - `getPrice(extension: string, currency: string, options?: GetPriceOptions): Promise<PriceQuote>` – same behavior as above, but uses the provided config.
57
- - `DEFAULTS_Sept2025: DomainPricesConfig` – exported snapshot config used by `getDefaultPrice`.
57
+ - `getPrice(extension: string, currency: string, options?: GetPriceOptions): Promise<PriceQuote>` – same behavior as above, but uses the provided config. Alias: `getQuote(...)`.
58
+ - `DEFAULT_RATES: DomainPricesConfig` – exported snapshot config used by `getDefaultQuote`.
58
59
 
59
60
  - `listSupportedExtensions(): string[]`
60
61
  - All extensions with a non-zero price in the dataset.
@@ -120,7 +121,7 @@ interface DomainPricesConfig {
120
121
  restorePrices?: Record<string, number>;
121
122
  transferPrices?: Record<string, number>;
122
123
  exchangeRates: ExchangeRateData[]; // currency conversion data
123
- vatRates: Record<string, number>; // ISO country code VAT rate
124
+ vatRate: number; // single VAT rate applied to subtotal
124
125
  discounts: Record<string, DiscountConfig>; // discount code → config
125
126
  markup?: PriceMarkup; // optional markup applied before conversion
126
127
  }
@@ -134,7 +135,7 @@ Errors
134
135
  Notes
135
136
 
136
137
  - Rounding is to 2 decimal places at each step to keep totals predictable (`base`, `discount`, `tax`, `total`).
137
- - VAT mapping is intentionally narrow and explicit by currency country: `USD US (0)`, `GBP → GB (0.2)`, `EUR DE (0.19)`, `NGN NG (0.075)`.
138
+ - A single VAT rate is applied to the subtotal by default (7.5% in the default config). Override `vatRate` in the config to change it.
138
139
  - Price and exchange-rate data are fetched from maintained remote sources at import time:
139
140
  - Prices: `https://raw.githubusercontent.com/namewiz/registrar-pricelist/refs/heads/main/data/unified-create-prices.csv`
140
141
  - Exchange rates: `https://raw.githubusercontent.com/namewiz/registrar-pricelist/refs/heads/main/data/exchange-rates.json`
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- var k={SAVE1:{rate:.01,extensions:["com","net"],startAt:"2023-01-01T00:00:00Z",endAt:"2025-12-31T23:59:59Z"},NEWUSER15:{rate:.15,extensions:["com","net","org"],startAt:"2023-01-01T00:00:00Z",endAt:"2024-12-31T23:59:59Z"},FALL20:{rate:.2,extensions:["org","info"],startAt:"2024-09-01T00:00:00Z",endAt:"2024-12-01T00:00:00Z"}};var v={US:0,GB:.2,DE:.19,NG:.075};var b={USD:"US",GBP:"GB",EUR:"DE",NGN:"NG"};function se(){return Object.keys(b)}function oe(t){return t!=null&&b.hasOwnProperty(t.toUpperCase())}function ie(){let t=E();return Object.keys(t).sort()}function ce(t){let e=E(),r=O(e,t),n=e[r];return typeof n=="number"&&n>0}function O(t,e){if(!e)return e;let n=e.trim().toLowerCase().replace(/^\.+/,"");if(!n)return"";if(t.hasOwnProperty(n))return n;if(n.includes(".")){let s=n.split(".");for(let i=0;i<s.length;i++){let c=s.slice(i).join(".");if(t.hasOwnProperty(c))return c}return s[s.length-1]}return n}function j(t){return t instanceof Date?t.getTime():typeof t=="number"?t:Date.now()}var F="https://raw.githubusercontent.com/namewiz/registrar-pricelist/refs/heads/main/data/unified-create-prices.csv",L="https://raw.githubusercontent.com/namewiz/registrar-pricelist/refs/heads/main/data/exchange-rates.json";async function Z(t){let e=await fetch(t);if(!e.ok)throw new Error(`Failed to fetch ${t}: ${e.status} ${e.statusText}`);return e.text()}async function B(t){let e=await fetch(t);if(!e.ok)throw new Error(`Failed to fetch ${t}: ${e.status} ${e.statusText}`);return e.json()}function J(t){let e=t.split(/\r?\n/).map(s=>s.trim()).filter(Boolean);if(e.length===0)return{};let r=e.shift(),n={};for(let s of e){let i=s.split(",");if(i.length<3)continue;let c=i[0]?.trim().toLowerCase(),o=i[2]?.trim(),a=Number(o);!c||!Number.isFinite(a)||a<=0||(!(c in n)||a<n[c])&&(n[c]=a)}return n}var[z,Q]=await Promise.all([Z(F).then(J),B(L)]);function E(){return z}function X(){return Q}function H(){return v}function q(){return k}var x=class extends Error{constructor(e,r){super(r),this.name="DomainPricesError",this.code=e}},y=class extends x{constructor(e){super("ERR_UNSUPPORTED_EXTENSION",`Unsupported extension: ${e}`),this.name="UnsupportedExtensionError"}},l=class extends x{constructor(e){super("ERR_UNSUPPORTED_CURRENCY",`Unsupported currency: ${e}`),this.name="UnsupportedCurrencyError"}};function W(){return{countryCode:"US",currencyName:"United States Dollar",currencySymbol:"$",currencyCode:"USD",exchangeRate:1,inverseRate:1}}function p(t){return Math.round(t*100)/100}function Y(t,e){if(!e)return t;let r=typeof e.value=="number"?e.value:0;if(!Number.isFinite(r)||r<=0)return t;switch(e.type){case"percentage":return t+t*r;case"fixedUsd":return t+r;default:return t}}var P=class{constructor(e){this.config=e}findRateInfo(e){if(e==="USD")return W();let r=this.config.exchangeRates.find(n=>n.currencyCode===e);if(!r)throw new l(e);return r}async getPrice(e,r,n={}){let s=this.config.createPrices,i=this.config.vatRates,c=this.config.discounts,o=O(s,e),a=n.transaction||"create",u;switch(a){case"renew":u=this.config.renewPrices?.[o]??s[o];break;case"restore":u=this.config.restorePrices?.[o]??s[o];break;case"transfer":u=this.config.transferPrices?.[o]??s[o];break;case"create":default:u=s[o];break}if(u===void 0||u===0)throw new y(o);let R=(r||"").toUpperCase(),w=b[R];if(!w)throw new l(r);let D=i[w];if(typeof D!="number")throw new l(r);let C=this.findRateInfo(R),_=C.currencySymbol,G=Y(u,this.config.markup),d=p(G*C.exchangeRate),I=Array.from(new Set((n.discountCodes||[]).map(m=>m.toUpperCase()))),T=j(n.now),h=[];for(let m of I){let f=c[m];if(!f)continue;let U=Date.parse(f.startAt),A=Date.parse(f.endAt);Number.isNaN(U)||Number.isNaN(A)||T<U||T>A||f.extensions.includes(o)&&h.push(p(d*f.rate))}let g=0;h.length>0&&(n.discountPolicy==="stack"?g=p(h.reduce((m,f)=>m+f,0)):g=Math.max(...h)),g>d&&(g=d);let S=p(d-g),N=p(S*D),M=p(S+N);return{extension:o,currency:R,basePrice:d,discount:g,tax:N,totalPrice:M,symbol:_,transaction:a}}},K={createPrices:E(),exchangeRates:X(),vatRates:H(),discounts:q()};async function ae(t,e,r={}){return new P(K).getPrice(t,e,r)}export{K as DEFAULTS_Sept2025,P as DomainPrices,l as UnsupportedCurrencyError,y as UnsupportedExtensionError,ae as getDefaultPrice,oe as isSupportedCurrency,ce as isSupportedExtension,se as listSupportedCurrencies,ie as listSupportedExtensions};
1
+ var S={SAVE1:{rate:.01,extensions:["com","net"],startAt:"2023-01-01T00:00:00Z",endAt:"2025-12-31T23:59:59Z"},NEWUSER15:{rate:.15,extensions:["com","net","org"],startAt:"2023-01-01T00:00:00Z",endAt:"2024-12-31T23:59:59Z"},FALL20:{rate:.2,extensions:["org","info"],startAt:"2024-09-01T00:00:00Z",endAt:"2024-12-01T00:00:00Z"}};var U=.075;function I(){return(_.supportedCurrencies??["USD","NGN"]).slice()}function et(e){if(!e)return!1;let t=e.toUpperCase();return I().includes(t)}function nt(){let e=y();return Object.keys(e).sort()}function rt(e){let t=y(),n=A(e),r=t[n];return typeof r=="number"&&r>0}function A(e){return e&&e.trim().toLowerCase().replace(/^\.+/,"")}function $(e){return e instanceof Date?e.getTime():typeof e=="number"?e:Date.now()}var L="https://raw.githubusercontent.com/namewiz/registrar-pricelist/refs/heads/main/data/unified-create-prices.csv",M="https://raw.githubusercontent.com/namewiz/registrar-pricelist/refs/heads/main/data/exchange-rates.json";async function Z(e){let t=await fetch(e);if(!t.ok)throw new Error(`Failed to fetch ${e}: ${t.status} ${t.statusText}`);return t.text()}async function j(e){let t=await fetch(e);if(!t.ok)throw new Error(`Failed to fetch ${e}: ${t.status} ${t.statusText}`);return t.json()}function V(e){let t=e.split(/\r?\n/).map(i=>i.trim()).filter(Boolean);if(t.length===0)return{};let n=t.shift(),r={};for(let i of t){let g=i.split(",");if(g.length<3)continue;let u=g[0]?.trim().toLowerCase(),s=g[2]?.trim(),o=Number(s);!u||!Number.isFinite(o)||o<=0||(!(u in r)||o<r[u])&&(r[u]=o)}return r}var[z,J]=await Promise.all([Z(L).then(V),j(M)]);function y(){return z}function X(){return J}function H(){return S}var h=class extends Error{constructor(t,n){super(n),this.name="DomainPricesError",this.code=t}},R=class extends h{constructor(t){super("ERR_UNSUPPORTED_EXTENSION",`Unsupported extension: ${t}`),this.name="UnsupportedExtensionError"}},P=class extends h{constructor(t){super("ERR_UNSUPPORTED_CURRENCY",`Unsupported currency: ${t}`),this.name="UnsupportedCurrencyError"}};function q(){return{countryCode:"US",currencyName:"United States Dollar",currencySymbol:"$",currencyCode:"USD",exchangeRate:1,inverseRate:1}}function p(e){return Number(e.toFixed(2))}function B(e,t){if(!t)return e;let n=typeof t.value=="number"?t.value:0;if(!Number.isFinite(n)||n<=0)return e;switch(t.type){case"percentage":return e+e*n;case"fixedUsd":return e+n;default:return e}}var E=class{constructor(t){this.config=t}findRateInfo(t){if(t==="USD")return q();let n=this.config.exchangeRates.find(r=>r.currencyCode===t);if(!n)throw new P(t);return n}async getPrice(t,n,r={}){let i=this.config.createPrices,g=typeof this.config.vatRate=="number"?this.config.vatRate:U,u=this.config.discounts,s=A(t),o=r.transaction||"create",c;switch(o){case"renew":c=this.config.renewPrices?.[s]??i[s];break;case"restore":c=this.config.restorePrices?.[s]??i[s];break;case"transfer":c=this.config.transferPrices?.[s]??i[s];break;case"create":default:c=i[s];break}if(c===void 0||c===0)throw new R(s);let x=(n||"").toUpperCase();if(!(this.config.supportedCurrencies??["USD","NGN"]).includes(x))throw new P(n);let D=this.findRateInfo(x),k=D.currencySymbol,v=B(c,this.config.markup),d=p(v*D.exchangeRate),G=g,O=Array.from(new Set((r.discountCodes||[]).map(m=>m.toUpperCase()))),C=$(r.now),l=[];for(let m of O){let a=u[m];if(!a)continue;let w=Date.parse(a.startAt),N=Date.parse(a.endAt);Number.isNaN(w)||Number.isNaN(N)||C<w||C>N||a.extensions.includes(s)&&l.push(p(d*a.rate))}let f=0;l.length>0&&(r.discountPolicy==="stack"?f=p(l.reduce((m,a)=>m+a,0)):f=Math.max(...l)),f>d&&(f=d);let b=p(d-f),T=p(b*G),Q=p(b+T);return{extension:s,currency:x,basePrice:d,discount:f,tax:T,totalPrice:Q,symbol:k,transaction:o}}async getQuote(t,n,r={}){return this.getPrice(t,n,r)}},_={createPrices:y(),exchangeRates:X(),vatRate:U,discounts:H(),supportedCurrencies:["USD","NGN"]};async function W(e,t,n={}){return new E(_).getPrice(e,t,n)}async function st(e,t,n={}){return W(e,t,n)}export{_ as DEFAULT_CONFIG,U as DEFAULT_VAT_RATE,E as DomainPrices,E as DomainQuote,P as UnsupportedCurrencyError,R as UnsupportedExtensionError,W as getDefaultPrice,st as getDefaultQuote,et as isSupportedCurrency,rt as isSupportedExtension,I as listSupportedCurrencies,nt as listSupportedExtensions};
package/package.json CHANGED
@@ -1,29 +1,32 @@
1
1
  {
2
2
  "name": "domain-quotes",
3
- "version": "0.0.11",
4
- "description": "Fast multi-currency domain price checker library across registrars.",
3
+ "version": "0.1.0",
4
+ "description": "Fast multi-currency domain quote checker library across registrars.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "scripts": {
8
8
  "build": "npx -y esbuild src/index.ts --bundle --minify --format=esm --target=esnext --outdir=dist/ --platform=neutral",
9
- "postbuild": "cp dist/index.js docs/domainprices.js",
9
+ "postbuild": "cp dist/index.js docs/domain-quotes.js",
10
10
  "test": "npm run build && node --test",
11
- "start": "npm run build && cp dist/index.js docs/domainprices.js && npx serve docs"
11
+ "start": "npm run build && cp dist/index.js docs/domain-quotes.js && npx serve docs"
12
12
  },
13
- "homepage": "https://namewiz.github.io/domainprices",
13
+ "homepage": "https://namewiz.github.io/domain-quotes",
14
14
  "repository": {
15
15
  "type": "git",
16
- "url": "git+https://github.com/namewiz/domainprices.git"
16
+ "url": "git+https://github.com/namewiz/domain-quotes.git"
17
17
  },
18
18
  "bugs": {
19
- "url": "https://github.com/namewiz/domainprices/issues"
19
+ "url": "https://github.com/namewiz/domain-quotes/issues"
20
20
  },
21
21
  "author": "Justice Ogbonna <dev@justiceo.com>",
22
22
  "keywords": [
23
23
  "domain-name",
24
+ "domain-quotes",
24
25
  "domain-price",
25
26
  "domain-availability",
26
- "price-check"
27
+ "price-check",
28
+ "quote",
29
+ "quote-check"
27
30
  ],
28
31
  "exports": {
29
32
  ".": "./dist/index.js"