@naverpay/nurl 0.0.2

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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 NaverPayDev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,128 @@
1
+ <h1 align="center">@naverpay/nurl</h1>
2
+
3
+ <p align="center">
4
+ <a href="https://www.npmjs.com/package/@naverpay/nurl">
5
+ <img src="https://img.shields.io/npm/v/@naverpay/nurl.svg?style=flat" alt="npm version">
6
+ </a>
7
+ <a href="https://bundlephobia.com/result?p=@naverpay/nurl">
8
+ <img src="https://badgen.net/bundlephobia/minzip/@naverpay/nurl" alt="minzipped size">
9
+ </a>
10
+ </p>
11
+
12
+ NURL is a powerful URL manipulation library that extends the standard URL class. It provides dynamic segment processing and flexible URL creation capabilities.
13
+
14
+ ## Features
15
+
16
+ - Extends and implements the URL class
17
+ - Supports various URL creation methods (string, URL object, custom options object)
18
+ - Provides a factory function NURL.create() for creating instances without the new keyword
19
+ - Dynamic segment processing functionality
20
+ - Setters behave differently from the standard URL
21
+ - Provides decoded hostname for IDN (Internationalized Domain Names) support
22
+
23
+ ## Usage
24
+
25
+ ### Basic Usage
26
+
27
+ ```javascript
28
+ import { NURL } from 'nurl'
29
+
30
+ // Create URL from string
31
+ const url1 = new NURL('https://example.com/users/123?name=John')
32
+
33
+ // Create URL from existing URL object
34
+ const standardUrl = new URL('https://example.com')
35
+ const url2 = new NURL(standardUrl)
36
+
37
+ // Create URL from custom options object
38
+ const url3 = new NURL({
39
+ baseUrl: 'https://example.com',
40
+ pathname: '/users/:id',
41
+ query: { id: '123', name: 'John' }
42
+ })
43
+
44
+ // Create empty URL
45
+ const url4 = new NURL()
46
+
47
+ // Using the factory function
48
+ const url5 = NURL.create('https://example.com')
49
+
50
+ // The factory function also works with options object
51
+ const url6 = NURL.create({
52
+ baseUrl: 'https://example.com',
53
+ pathname: '/users/:id',
54
+ query: { id: '123', name: 'John' }
55
+ })
56
+ ```
57
+
58
+ ### Dynamic Segment Processing
59
+
60
+ NURL processes dynamic segments in the pathname and replaces them with values from the query object. If a dynamic segment doesn't have a corresponding query value, it remains unchanged in the pathname without any encoding:
61
+
62
+ ```javascript
63
+ const url = new NURL({
64
+ baseUrl: 'https://api.example.com',
65
+ pathname: '/users/:a/posts/[b]/[c]',
66
+ query: {
67
+ a: '123',
68
+ b: '456',
69
+ format: 'json'
70
+ }
71
+ })
72
+
73
+ console.log(url.href)
74
+ // Output: https://api.example.com/users/123/posts/456/[c]?format=json
75
+ ```
76
+
77
+ ### IDN Support
78
+
79
+ NURL automatically handles Internationalized Domain Names:
80
+
81
+ ```javascript
82
+ const url = new NURL('https://한글.도메인')
83
+ console.log(url.hostname) // xn--bj0bj06e.xn--hq1bm8jm9l
84
+ console.log(url.decodedHostname) // 한글.도메인 (in human-readable format)
85
+ ```
86
+
87
+ ## API
88
+
89
+ ### `constructor(input?: string | URL | URLOptions)`
90
+
91
+ - `input`: Can be one of the following:
92
+ - `string`: Standard URL string
93
+ - `URL`: Standard URL object
94
+ - `URLOptions`: Custom options object that extends `Partial<URL>` and includes:
95
+ - `baseUrl?: string`: Optional base URL string
96
+ - `query?: Record<string, string>`: Optional object for query parameters
97
+ - Can include any property from the standard URL object (e.g., `pathname`, `protocol`, etc.)
98
+
99
+ ### Dynamic Segments
100
+
101
+ - Supports `:paramName` or `[paramName]` format in the pathname.
102
+ - If a corresponding key exists in the query object or URLOptions, the dynamic segment is replaced with its value.
103
+ - If a corresponding key does not exist, the dynamic segment remains unchanged in the pathname without throwing an error.
104
+
105
+ ### Properties
106
+
107
+ NURL inherits all properties from the standard URL class:
108
+
109
+ - `href`, `origin`, `protocol`, `username`, `password`, `host`, `hostname`, `port`, `pathname`, `search`, `searchParams`, `hash`
110
+
111
+ ### Methods
112
+
113
+ - `toString()`: Returns the URL as a string
114
+ - `toJSON()`: Returns the URL as a JSON representation
115
+
116
+ ## Important Notes
117
+
118
+ 1. NURL's setter methods behave differently from the standard URL. They are designed to consider dynamic segment and query parameter replacement functionality.
119
+ 2. When created with no arguments, all properties are initialized as empty strings.
120
+ 3. When using `URLOptions`, if a query value corresponding to a dynamic segment is missing, the dynamic segment remains unchanged in the pathname.
121
+ 4. Dynamic segments only support the `:paramName` or `[paramName]` format.
122
+
123
+ ## Differences from Standard URL
124
+
125
+ 1. **Constructor Flexibility**: NURL can create a URL from a string, URL object, or custom options object.
126
+ 2. **Empty URL Creation**: NURL can create an empty URL when called with no arguments.
127
+ 3. **Dynamic Segments**: NURL supports dynamic segments in the pathname.
128
+ 4. **Setter Behavior**: NURL's setter methods behave differently from the standard URL, considering dynamic segment processing and query parameter replacement.
@@ -0,0 +1,58 @@
1
+ interface URLOptions extends Partial<URL> {
2
+ baseUrl?: string;
3
+ query?: Record<string, string>;
4
+ }
5
+ declare class NURL implements URL {
6
+ private _href;
7
+ private _protocol;
8
+ private _host;
9
+ private _hostname;
10
+ private _port;
11
+ private _pathname;
12
+ private _search;
13
+ private _hash;
14
+ private _origin;
15
+ private _username;
16
+ private _password;
17
+ private _baseUrl;
18
+ private _searchParams;
19
+ constructor(input?: string | URL | URLOptions);
20
+ static create(input?: string | URL | URLOptions): NURL;
21
+ static canParse(input: string): boolean;
22
+ get baseUrl(): string;
23
+ set baseUrl(value: string);
24
+ get href(): string;
25
+ set href(value: string);
26
+ get protocol(): string;
27
+ set protocol(value: string);
28
+ get host(): string;
29
+ set host(value: string);
30
+ get hostname(): string;
31
+ set hostname(value: string);
32
+ get port(): string;
33
+ set port(value: string);
34
+ get pathname(): string;
35
+ set pathname(pathname: string);
36
+ get search(): string;
37
+ set search(search: string);
38
+ setSearchParams(_params: Record<string, string>): void;
39
+ appendSearchParams(_params: Record<string, string>): void;
40
+ removeSearchParams(..._keys: string[]): void;
41
+ get searchParams(): URLSearchParams;
42
+ get hash(): string;
43
+ set hash(value: string);
44
+ get origin(): string;
45
+ get username(): string;
46
+ set username(value: string);
47
+ get password(): string;
48
+ set password(value: string);
49
+ private updateHref;
50
+ toString(): string;
51
+ toJSON(): string;
52
+ private punycodePrefix;
53
+ private encodeHostname;
54
+ get decodedIDN(): string;
55
+ get decodedHostname(): string;
56
+ }
57
+
58
+ export { NURL as default };
@@ -0,0 +1,2 @@
1
+ "use strict";const i=require("punycode/"),f=/^:/,d=/^\[.*\]$/;function p(h){return f.test(h)||d.test(h)}function o(h){return h.split("/").filter(p)}function n(h){return h.slice(1,f.test(h)?void 0:-1)}function m(h,t){return o(h).reduce((s,e)=>{const r=n(e);return t[r]?s.replace(e,t[r]):s},h)}function u(h,t){return o(h).reduce((s,e)=>{const r=n(e),{[r]:_,...a}=s;return a},t)}const l=127;function P(h){return h.charCodeAt(0)>l}class c{constructor(t){if(this._href="",this._protocol="",this._host="",this._hostname="",this._port="",this._pathname="",this._search="",this._hash="",this._origin="",this._username="",this._password="",this._baseUrl="",this._searchParams=new URLSearchParams,this.punycodePrefix="xn--",this._searchParams=new URLSearchParams,typeof t=="string"||t instanceof URL)this.href=t.toString();else if(t){if(t.baseUrl&&(this.baseUrl=t.baseUrl),t.href&&(this.href=t.href),t.protocol&&(this.protocol=t.protocol),t.host&&(this.host=t.host),t.hostname&&(this.hostname=t.hostname),t.port&&(this.port=t.port),t.pathname&&(this.pathname=m(t.pathname,t.query??{})),t.search&&(this.search=t.search),t.hash&&(this.hash=t.hash),t.username&&(this.username=t.username),t.password&&(this.password=t.password),t.query){const s=u(t.pathname??"",t.query);Object.keys(s).length>0&&(this.search=new URLSearchParams(s).toString())}this.updateHref()}}static create(t){return new c(t)}static canParse(t){if(t.startsWith("/"))return/^\/[^?#]*(\?[^#]*)?(#.*)?$/.test(t);try{return new URL(t),!0}catch{return/^[^:/?#]+(\.[^:/?#]+)+(\/[^?#]*(\?[^#]*)?(#.*)?)?$/.test(t)}}get baseUrl(){return this._baseUrl}set baseUrl(t){this._baseUrl=t;try{const s=new URL(t);this._protocol=s.protocol,this._host=s.host,this._hostname=s.hostname,this._port=s.port,this._origin=s.origin,this._username=s.username,this._password=s.password,s.pathname!=="/"&&(this._pathname=s.pathname),s.search&&(this._search=s.search,this._searchParams=new URLSearchParams(s.search)),s.hash&&(this._hash=s.hash),this.updateHref()}catch(s){console.warn(`Invalid baseUrl: ${t}`,s)}}get href(){return this.pathname.length===1?`${this._href}/`:this._href}set href(t){try{const s=new URL(t);this._href=s.href,this._protocol=s.protocol,this._host=s.host,this._hostname=s.hostname,this._port=s.port,this._pathname=s.pathname,this._search=s.search,this._hash=s.hash,this._origin=s.origin,this._username=s.username,this._password=s.password,this._searchParams=s.searchParams}catch(s){console.warn(`Can not parse ${t}`,s)}}get protocol(){return this._protocol}set protocol(t){this._protocol=t,this.updateHref()}get host(){return this._host}set host(t){const[s,e]=t.split(":"),r=this.encodeHostname(s);this._host=e?`${r}:${e}`:r,this._hostname=r,this._port=e||"",this.updateHref()}get hostname(){return this._hostname}set hostname(t){const s=this.encodeHostname(t);this._hostname=s,this._host=this._port?`${s}:${this._port}`:s,this.updateHref()}get port(){return this._port}set port(t){this._port=t,this._host=`${this._hostname}${t?":"+t:""}`,this.updateHref()}get pathname(){return this._pathname}set pathname(t){const s=t.split("/").map(e=>p(e)?e:encodeURI(e)).join("/");this._pathname=s.startsWith("/")?s:`/${s}`,this.updateHref()}get search(){return this._search}set search(t){const s=encodeURI(t);this._search=s.startsWith("?")?s:`?${s}`,this._searchParams=new URLSearchParams(s),this.updateHref()}setSearchParams(t){const s=new URLSearchParams(t);this._search=s.toString()?`?${s.toString()}`:"",this._searchParams=s,this.updateHref()}appendSearchParams(t){const s=new URLSearchParams(this._searchParams),e=o(this._pathname).map(n);Object.keys(t).forEach(r=>{e.includes(r)?this._pathname=m(this._pathname,{[r]:t[r]}):s.append(r,t[r])}),this._search=s.toString()?`?${s.toString()}`:"",this._searchParams=s,this.updateHref()}removeSearchParams(...t){const s=new URLSearchParams(this._searchParams);t.forEach(e=>{s.delete(e)}),this._search=s.toString()?`?${s.toString()}`:"",this._searchParams=s,this.updateHref()}get searchParams(){return new Proxy(this._searchParams,{get:(t,s,e)=>{const r=Reflect.get(t,s,e);return typeof r=="function"?(..._)=>{const a=r.apply(t,_);return this._search=this._searchParams.toString()?`?${this._searchParams.toString()}`:"",this.updateHref(),a}:r}})}get hash(){return this._hash}set hash(t){this._hash=t.startsWith("#")?t:`#${t}`,this.updateHref()}get origin(){return this._origin}get username(){return this._username}set username(t){this._username=t,this.updateHref()}get password(){return this._password}set password(t){this._password=t,this.updateHref()}updateHref(){if(this._baseUrl){const t=new URL(this._baseUrl);t.pathname=this._pathname,t.search=this._search,t.hash=this._hash,this._href=t.href,this._origin=t.origin}else this._href=`${this._protocol}${this._protocol&&"//"}${this._username}${this._password?":"+this._password:""}${this._username||this._password?"@":""}${this._hostname}${this._port?":"+this._port:""}${this._pathname==="/"?"":this._pathname}${this._search}${this._hash}`,this._origin=`${this._protocol}//${this._hostname}${this._port?":"+this._port:""}`}toString(){return this.href}toJSON(){return this.href}encodeHostname(t){return t.split(".").map(s=>{for(const e of s)if(P(e))return`${this.punycodePrefix}${i.encode(s)}`;return s}).join(".")}get decodedIDN(){let t=this._href;return this._hostname.split(".").forEach(s=>{t=t.replace(s,i.decode(s.replace(this.punycodePrefix,"")))}),t}get decodedHostname(){return this._hostname.split(".").map(t=>i.decode(t.replace(this.punycodePrefix,""))).join(".")}}module.exports=c;
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../src/utils.ts","../../src/nurl.ts"],"sourcesContent":["const DYNAMIC_PATH_COLON_REGEXP = /^:/\nconst DYNAMIC_PATH_BRACKETS_REGEXP = /^\\[.*\\]$/\n\nexport function isDynamicPath(path: string) {\n return DYNAMIC_PATH_COLON_REGEXP.test(path) || DYNAMIC_PATH_BRACKETS_REGEXP.test(path)\n}\n\nexport function getDynamicPaths(pathname: string): string[] {\n return pathname.split('/').filter(isDynamicPath)\n}\n\nexport function extractPathKey(path: string): string {\n return path.slice(1, DYNAMIC_PATH_COLON_REGEXP.test(path) ? undefined : -1)\n}\n\n/**\n * Replaces dynamic paths in the pathname with values from the query\n * @param {string} pathname\n * @param {Record<string, string>} query\n * @returns {string} refined pathname\n */\nexport function refinePathnameWithQuery(pathname: string, query: Record<string, string>): string {\n return getDynamicPaths(pathname).reduce((acc, path) => {\n const pathKey = extractPathKey(path)\n return query[pathKey] ? acc.replace(path, query[pathKey]) : acc\n }, pathname)\n}\n\n/**\n * Removes queries that have already been used in the pathname.\n * @param {string} pathname\n * @param {Record<string, string>} query\n * @returns {Record<string, string>} refined query\n */\nexport function refineQueryWithPathname(pathname: string, query: Record<string, string>): Record<string, string> {\n return getDynamicPaths(pathname).reduce((acc, path) => {\n const pathKey = extractPathKey(path)\n const {[pathKey]: _, ...remainingQuery} = acc\n return remainingQuery\n }, query)\n}\n\nconst MAX_ASCII_CODE = 127\nexport function isASCIICodeChar(char: string) {\n return char.charCodeAt(0) > MAX_ASCII_CODE\n}\n","/**\n * Note: The trailing slash in the import path 'punycode/' is intentional.\n * It ensures that this third-party module is used instead of the built-in\n * Node.js 'punycode' module, which has been deprecated since Node.js v7.0.0.\n * @see https://github.com/mathiasbynens/punycode.js#installation\n * @see https://nodejs.org/api/punycode.html for deprecation info\n */\nimport {decode, encode} from 'punycode/'\n\nimport {\n extractPathKey,\n getDynamicPaths,\n isASCIICodeChar,\n isDynamicPath,\n refinePathnameWithQuery,\n refineQueryWithPathname,\n} from './utils'\n\ninterface URLOptions extends Partial<URL> {\n baseUrl?: string\n query?: Record<string, string>\n}\n\nexport default class NURL implements URL {\n private _href: string = ''\n private _protocol: string = ''\n private _host: string = ''\n private _hostname: string = ''\n private _port: string = ''\n private _pathname: string = ''\n private _search: string = ''\n private _hash: string = ''\n private _origin: string = ''\n private _username: string = ''\n private _password: string = ''\n private _baseUrl: string = ''\n private _searchParams: URLSearchParams = new URLSearchParams()\n\n constructor(input?: string | URL | URLOptions) {\n this._searchParams = new URLSearchParams()\n if (typeof input === 'string' || input instanceof URL) {\n this.href = input.toString()\n } else if (input) {\n if (input.baseUrl) {\n this.baseUrl = input.baseUrl\n }\n if (input.href) {\n this.href = input.href\n }\n if (input.protocol) {\n this.protocol = input.protocol\n }\n if (input.host) {\n this.host = input.host\n }\n if (input.hostname) {\n this.hostname = input.hostname\n }\n if (input.port) {\n this.port = input.port\n }\n if (input.pathname) {\n this.pathname = refinePathnameWithQuery(input.pathname, input.query ?? {})\n }\n if (input.search) {\n this.search = input.search\n }\n if (input.hash) {\n this.hash = input.hash\n }\n if (input.username) {\n this.username = input.username\n }\n if (input.password) {\n this.password = input.password\n }\n if (input.query) {\n const refinedQuery = refineQueryWithPathname(input.pathname ?? '', input.query)\n if (Object.keys(refinedQuery).length > 0) {\n this.search = new URLSearchParams(refinedQuery).toString()\n }\n }\n this.updateHref()\n }\n }\n\n static create(input?: string | URL | URLOptions) {\n return new NURL(input)\n }\n\n static canParse(input: string): boolean {\n if (input.startsWith('/')) {\n return /^\\/[^?#]*(\\?[^#]*)?(#.*)?$/.test(input)\n }\n\n try {\n // eslint-disable-next-line no-new\n new URL(input)\n return true\n } catch {\n // URL 생성자로 파싱할 수 없는 경우, 추가적인 검사를 수행\n // 예: 'example.com' 또는 'example.com/path'와 같은 형식 허용\n return /^[^:/?#]+(\\.[^:/?#]+)+(\\/[^?#]*(\\?[^#]*)?(#.*)?)?$/.test(input)\n }\n }\n\n get baseUrl(): string {\n return this._baseUrl\n }\n\n set baseUrl(value: string) {\n this._baseUrl = value\n try {\n const url = new URL(value)\n this._protocol = url.protocol\n this._host = url.host\n this._hostname = url.hostname\n this._port = url.port\n this._origin = url.origin\n this._username = url.username\n this._password = url.password\n if (url.pathname !== '/') {\n this._pathname = url.pathname\n }\n if (url.search) {\n this._search = url.search\n this._searchParams = new URLSearchParams(url.search)\n }\n if (url.hash) {\n this._hash = url.hash\n }\n this.updateHref()\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn(`Invalid baseUrl: ${value}`, error)\n }\n }\n\n get href(): string {\n return this.pathname.length === 1 ? `${this._href}/` : this._href\n }\n\n set href(value: string) {\n try {\n const url = new URL(value)\n this._href = url.href\n this._protocol = url.protocol\n this._host = url.host\n this._hostname = url.hostname\n this._port = url.port\n this._pathname = url.pathname\n this._search = url.search\n this._hash = url.hash\n this._origin = url.origin\n this._username = url.username\n this._password = url.password\n this._searchParams = url.searchParams\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn(`Can not parse ${value}`, error)\n }\n }\n\n get protocol(): string {\n return this._protocol\n }\n\n set protocol(value: string) {\n this._protocol = value\n this.updateHref()\n }\n\n get host(): string {\n return this._host\n }\n\n set host(value: string) {\n const [hostname, port] = value.split(':')\n\n const encodedHostname = this.encodeHostname(hostname)\n\n this._host = port ? `${encodedHostname}:${port}` : encodedHostname\n this._hostname = encodedHostname\n this._port = port || ''\n this.updateHref()\n }\n\n get hostname(): string {\n return this._hostname\n }\n\n set hostname(value: string) {\n const encodedHostname = this.encodeHostname(value)\n\n this._hostname = encodedHostname\n this._host = this._port ? `${encodedHostname}:${this._port}` : encodedHostname\n this.updateHref()\n }\n\n get port(): string {\n return this._port\n }\n\n set port(value: string) {\n this._port = value\n this._host = `${this._hostname}${value ? ':' + value : ''}`\n this.updateHref()\n }\n\n get pathname(): string {\n return this._pathname\n }\n\n set pathname(pathname: string) {\n const encodedPathname = pathname\n .split('/')\n .map((segment) => (isDynamicPath(segment) ? segment : encodeURI(segment)))\n .join('/')\n\n this._pathname = encodedPathname.startsWith('/') ? encodedPathname : `/${encodedPathname}`\n this.updateHref()\n }\n\n get search(): string {\n return this._search\n }\n\n set search(search: string) {\n const encodedSearch = encodeURI(search)\n this._search = encodedSearch.startsWith('?') ? encodedSearch : `?${encodedSearch}`\n this._searchParams = new URLSearchParams(encodedSearch)\n this.updateHref()\n }\n\n setSearchParams(_params: Record<string, string>): void {\n const searchParams = new URLSearchParams(_params)\n\n this._search = searchParams.toString() ? `?${searchParams.toString()}` : ''\n this._searchParams = searchParams\n this.updateHref()\n }\n\n appendSearchParams(_params: Record<string, string>): void {\n const searchParams = new URLSearchParams(this._searchParams)\n const dynamicRoutes = getDynamicPaths(this._pathname).map(extractPathKey)\n\n Object.keys(_params).forEach((key) => {\n if (dynamicRoutes.includes(key)) {\n this._pathname = refinePathnameWithQuery(this._pathname, {[key]: _params[key]})\n } else {\n searchParams.append(key, _params[key])\n }\n })\n\n this._search = searchParams.toString() ? `?${searchParams.toString()}` : ''\n this._searchParams = searchParams\n this.updateHref()\n }\n\n removeSearchParams(..._keys: string[]): void {\n const searchParams = new URLSearchParams(this._searchParams)\n\n _keys.forEach((key) => {\n searchParams.delete(key)\n })\n\n this._search = searchParams.toString() ? `?${searchParams.toString()}` : ''\n this._searchParams = searchParams\n this.updateHref()\n }\n\n get searchParams(): URLSearchParams {\n return new Proxy(this._searchParams, {\n get: (target, prop, receiver) => {\n const value = Reflect.get(target, prop, receiver)\n if (typeof value === 'function') {\n return (...args: unknown[]) => {\n const result = value.apply(target, args)\n this._search = this._searchParams.toString() ? `?${this._searchParams.toString()}` : ''\n this.updateHref()\n return result\n }\n }\n return value\n },\n })\n }\n\n get hash(): string {\n return this._hash\n }\n\n set hash(value: string) {\n this._hash = value.startsWith('#') ? value : `#${value}`\n this.updateHref()\n }\n\n get origin(): string {\n return this._origin\n }\n\n get username(): string {\n return this._username\n }\n\n set username(value: string) {\n this._username = value\n this.updateHref()\n }\n\n get password(): string {\n return this._password\n }\n\n set password(value: string) {\n this._password = value\n this.updateHref()\n }\n\n private updateHref() {\n if (this._baseUrl) {\n const baseUrl = new URL(this._baseUrl)\n baseUrl.pathname = this._pathname\n baseUrl.search = this._search\n baseUrl.hash = this._hash\n this._href = baseUrl.href\n this._origin = baseUrl.origin\n } else {\n this._href = `${this._protocol}${this._protocol && '//'}${this._username}${this._password ? ':' + this._password : ''}${\n this._username || this._password ? '@' : ''\n }${this._hostname}${this._port ? ':' + this._port : ''}${this._pathname === '/' ? '' : this._pathname}${this._search}${this._hash}`\n\n this._origin = `${this._protocol}//${this._hostname}${this._port ? ':' + this._port : ''}`\n }\n }\n\n toString(): string {\n return this.href\n }\n\n toJSON(): string {\n return this.href\n }\n\n private punycodePrefix = 'xn--'\n\n private encodeHostname(hostname: string): string {\n return hostname\n .split('.')\n .map((segment) => {\n for (const char of segment) {\n if (isASCIICodeChar(char)) {\n return `${this.punycodePrefix}${encode(segment)}`\n }\n }\n return segment\n })\n .join('.')\n }\n\n get decodedIDN(): string {\n let href = this._href\n\n this._hostname.split('.').forEach((segment) => {\n href = href.replace(segment, decode(segment.replace(this.punycodePrefix, '')))\n })\n\n return href\n }\n\n get decodedHostname(): string {\n return this._hostname\n .split('.')\n .map((segment) => decode(segment.replace(this.punycodePrefix, '')))\n .join('.')\n }\n}\n"],"names":["DYNAMIC_PATH_COLON_REGEXP","DYNAMIC_PATH_BRACKETS_REGEXP","isDynamicPath","path","test","getDynamicPaths","pathname","split","filter","extractPathKey","slice","refinePathnameWithQuery","query","reduce","acc","pathKey","replace","refineQueryWithPathname","_","remainingQuery","MAX_ASCII_CODE","isASCIICodeChar","char","charCodeAt","NURL","constructor","input","_href","_protocol","_host","_hostname","_port","_pathname","_search","_hash","_origin","_username","_password","_baseUrl","_searchParams","URLSearchParams","punycodePrefix","URL","href","toString","baseUrl","protocol","host","hostname","port","search","hash","username","password","refinedQuery","Object","keys","length","updateHref","create","canParse","startsWith","value","url","origin","error","console","warn","searchParams","encodedHostname","encodeHostname","encodedPathname","map","segment","encodeURI","join","encodedSearch","setSearchParams","_params","appendSearchParams","dynamicRoutes","forEach","key","includes","append","removeSearchParams","_keys","delete","Proxy","get","target","prop","receiver","Reflect","args","result","apply","toJSON","encode","decodedIDN","decode","decodedHostname"],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ interface URLOptions extends Partial<URL> {
2
+ baseUrl?: string;
3
+ query?: Record<string, string>;
4
+ }
5
+ declare class NURL implements URL {
6
+ private _href;
7
+ private _protocol;
8
+ private _host;
9
+ private _hostname;
10
+ private _port;
11
+ private _pathname;
12
+ private _search;
13
+ private _hash;
14
+ private _origin;
15
+ private _username;
16
+ private _password;
17
+ private _baseUrl;
18
+ private _searchParams;
19
+ constructor(input?: string | URL | URLOptions);
20
+ static create(input?: string | URL | URLOptions): NURL;
21
+ static canParse(input: string): boolean;
22
+ get baseUrl(): string;
23
+ set baseUrl(value: string);
24
+ get href(): string;
25
+ set href(value: string);
26
+ get protocol(): string;
27
+ set protocol(value: string);
28
+ get host(): string;
29
+ set host(value: string);
30
+ get hostname(): string;
31
+ set hostname(value: string);
32
+ get port(): string;
33
+ set port(value: string);
34
+ get pathname(): string;
35
+ set pathname(pathname: string);
36
+ get search(): string;
37
+ set search(search: string);
38
+ setSearchParams(_params: Record<string, string>): void;
39
+ appendSearchParams(_params: Record<string, string>): void;
40
+ removeSearchParams(..._keys: string[]): void;
41
+ get searchParams(): URLSearchParams;
42
+ get hash(): string;
43
+ set hash(value: string);
44
+ get origin(): string;
45
+ get username(): string;
46
+ set username(value: string);
47
+ get password(): string;
48
+ set password(value: string);
49
+ private updateHref;
50
+ toString(): string;
51
+ toJSON(): string;
52
+ private punycodePrefix;
53
+ private encodeHostname;
54
+ get decodedIDN(): string;
55
+ get decodedHostname(): string;
56
+ }
57
+
58
+ export { NURL as default };
@@ -0,0 +1,202 @@
1
+ import { encode as d, decode as c } from "punycode/";
2
+ const m = /^:/, u = /^\[.*\]$/;
3
+ function f(h) {
4
+ return m.test(h) || u.test(h);
5
+ }
6
+ function i(h) {
7
+ return h.split("/").filter(f);
8
+ }
9
+ function o(h) {
10
+ return h.slice(1, m.test(h) ? void 0 : -1);
11
+ }
12
+ function _(h, t) {
13
+ return i(h).reduce((s, e) => {
14
+ const r = o(e);
15
+ return t[r] ? s.replace(e, t[r]) : s;
16
+ }, h);
17
+ }
18
+ function l(h, t) {
19
+ return i(h).reduce((s, e) => {
20
+ const r = o(e), {
21
+ [r]: n,
22
+ ...a
23
+ } = s;
24
+ return a;
25
+ }, t);
26
+ }
27
+ const P = 127;
28
+ function g(h) {
29
+ return h.charCodeAt(0) > P;
30
+ }
31
+ class p {
32
+ constructor(t) {
33
+ if (this._href = "", this._protocol = "", this._host = "", this._hostname = "", this._port = "", this._pathname = "", this._search = "", this._hash = "", this._origin = "", this._username = "", this._password = "", this._baseUrl = "", this._searchParams = new URLSearchParams(), this.punycodePrefix = "xn--", this._searchParams = new URLSearchParams(), typeof t == "string" || t instanceof URL)
34
+ this.href = t.toString();
35
+ else if (t) {
36
+ if (t.baseUrl && (this.baseUrl = t.baseUrl), t.href && (this.href = t.href), t.protocol && (this.protocol = t.protocol), t.host && (this.host = t.host), t.hostname && (this.hostname = t.hostname), t.port && (this.port = t.port), t.pathname && (this.pathname = _(t.pathname, t.query ?? {})), t.search && (this.search = t.search), t.hash && (this.hash = t.hash), t.username && (this.username = t.username), t.password && (this.password = t.password), t.query) {
37
+ const s = l(t.pathname ?? "", t.query);
38
+ Object.keys(s).length > 0 && (this.search = new URLSearchParams(s).toString());
39
+ }
40
+ this.updateHref();
41
+ }
42
+ }
43
+ static create(t) {
44
+ return new p(t);
45
+ }
46
+ static canParse(t) {
47
+ if (t.startsWith("/"))
48
+ return /^\/[^?#]*(\?[^#]*)?(#.*)?$/.test(t);
49
+ try {
50
+ return new URL(t), !0;
51
+ } catch {
52
+ return /^[^:/?#]+(\.[^:/?#]+)+(\/[^?#]*(\?[^#]*)?(#.*)?)?$/.test(t);
53
+ }
54
+ }
55
+ get baseUrl() {
56
+ return this._baseUrl;
57
+ }
58
+ set baseUrl(t) {
59
+ this._baseUrl = t;
60
+ try {
61
+ const s = new URL(t);
62
+ this._protocol = s.protocol, this._host = s.host, this._hostname = s.hostname, this._port = s.port, this._origin = s.origin, this._username = s.username, this._password = s.password, s.pathname !== "/" && (this._pathname = s.pathname), s.search && (this._search = s.search, this._searchParams = new URLSearchParams(s.search)), s.hash && (this._hash = s.hash), this.updateHref();
63
+ } catch (s) {
64
+ console.warn(`Invalid baseUrl: ${t}`, s);
65
+ }
66
+ }
67
+ get href() {
68
+ return this.pathname.length === 1 ? `${this._href}/` : this._href;
69
+ }
70
+ set href(t) {
71
+ try {
72
+ const s = new URL(t);
73
+ this._href = s.href, this._protocol = s.protocol, this._host = s.host, this._hostname = s.hostname, this._port = s.port, this._pathname = s.pathname, this._search = s.search, this._hash = s.hash, this._origin = s.origin, this._username = s.username, this._password = s.password, this._searchParams = s.searchParams;
74
+ } catch (s) {
75
+ console.warn(`Can not parse ${t}`, s);
76
+ }
77
+ }
78
+ get protocol() {
79
+ return this._protocol;
80
+ }
81
+ set protocol(t) {
82
+ this._protocol = t, this.updateHref();
83
+ }
84
+ get host() {
85
+ return this._host;
86
+ }
87
+ set host(t) {
88
+ const [s, e] = t.split(":"), r = this.encodeHostname(s);
89
+ this._host = e ? `${r}:${e}` : r, this._hostname = r, this._port = e || "", this.updateHref();
90
+ }
91
+ get hostname() {
92
+ return this._hostname;
93
+ }
94
+ set hostname(t) {
95
+ const s = this.encodeHostname(t);
96
+ this._hostname = s, this._host = this._port ? `${s}:${this._port}` : s, this.updateHref();
97
+ }
98
+ get port() {
99
+ return this._port;
100
+ }
101
+ set port(t) {
102
+ this._port = t, this._host = `${this._hostname}${t ? ":" + t : ""}`, this.updateHref();
103
+ }
104
+ get pathname() {
105
+ return this._pathname;
106
+ }
107
+ set pathname(t) {
108
+ const s = t.split("/").map((e) => f(e) ? e : encodeURI(e)).join("/");
109
+ this._pathname = s.startsWith("/") ? s : `/${s}`, this.updateHref();
110
+ }
111
+ get search() {
112
+ return this._search;
113
+ }
114
+ set search(t) {
115
+ const s = encodeURI(t);
116
+ this._search = s.startsWith("?") ? s : `?${s}`, this._searchParams = new URLSearchParams(s), this.updateHref();
117
+ }
118
+ setSearchParams(t) {
119
+ const s = new URLSearchParams(t);
120
+ this._search = s.toString() ? `?${s.toString()}` : "", this._searchParams = s, this.updateHref();
121
+ }
122
+ appendSearchParams(t) {
123
+ const s = new URLSearchParams(this._searchParams), e = i(this._pathname).map(o);
124
+ Object.keys(t).forEach((r) => {
125
+ e.includes(r) ? this._pathname = _(this._pathname, {
126
+ [r]: t[r]
127
+ }) : s.append(r, t[r]);
128
+ }), this._search = s.toString() ? `?${s.toString()}` : "", this._searchParams = s, this.updateHref();
129
+ }
130
+ removeSearchParams(...t) {
131
+ const s = new URLSearchParams(this._searchParams);
132
+ t.forEach((e) => {
133
+ s.delete(e);
134
+ }), this._search = s.toString() ? `?${s.toString()}` : "", this._searchParams = s, this.updateHref();
135
+ }
136
+ get searchParams() {
137
+ return new Proxy(this._searchParams, {
138
+ get: (t, s, e) => {
139
+ const r = Reflect.get(t, s, e);
140
+ return typeof r == "function" ? (...n) => {
141
+ const a = r.apply(t, n);
142
+ return this._search = this._searchParams.toString() ? `?${this._searchParams.toString()}` : "", this.updateHref(), a;
143
+ } : r;
144
+ }
145
+ });
146
+ }
147
+ get hash() {
148
+ return this._hash;
149
+ }
150
+ set hash(t) {
151
+ this._hash = t.startsWith("#") ? t : `#${t}`, this.updateHref();
152
+ }
153
+ get origin() {
154
+ return this._origin;
155
+ }
156
+ get username() {
157
+ return this._username;
158
+ }
159
+ set username(t) {
160
+ this._username = t, this.updateHref();
161
+ }
162
+ get password() {
163
+ return this._password;
164
+ }
165
+ set password(t) {
166
+ this._password = t, this.updateHref();
167
+ }
168
+ updateHref() {
169
+ if (this._baseUrl) {
170
+ const t = new URL(this._baseUrl);
171
+ t.pathname = this._pathname, t.search = this._search, t.hash = this._hash, this._href = t.href, this._origin = t.origin;
172
+ } else
173
+ this._href = `${this._protocol}${this._protocol && "//"}${this._username}${this._password ? ":" + this._password : ""}${this._username || this._password ? "@" : ""}${this._hostname}${this._port ? ":" + this._port : ""}${this._pathname === "/" ? "" : this._pathname}${this._search}${this._hash}`, this._origin = `${this._protocol}//${this._hostname}${this._port ? ":" + this._port : ""}`;
174
+ }
175
+ toString() {
176
+ return this.href;
177
+ }
178
+ toJSON() {
179
+ return this.href;
180
+ }
181
+ encodeHostname(t) {
182
+ return t.split(".").map((s) => {
183
+ for (const e of s)
184
+ if (g(e))
185
+ return `${this.punycodePrefix}${d(s)}`;
186
+ return s;
187
+ }).join(".");
188
+ }
189
+ get decodedIDN() {
190
+ let t = this._href;
191
+ return this._hostname.split(".").forEach((s) => {
192
+ t = t.replace(s, c(s.replace(this.punycodePrefix, "")));
193
+ }), t;
194
+ }
195
+ get decodedHostname() {
196
+ return this._hostname.split(".").map((t) => c(t.replace(this.punycodePrefix, ""))).join(".");
197
+ }
198
+ }
199
+ export {
200
+ p as default
201
+ };
202
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../../src/utils.ts","../../src/nurl.ts"],"sourcesContent":["const DYNAMIC_PATH_COLON_REGEXP = /^:/\nconst DYNAMIC_PATH_BRACKETS_REGEXP = /^\\[.*\\]$/\n\nexport function isDynamicPath(path: string) {\n return DYNAMIC_PATH_COLON_REGEXP.test(path) || DYNAMIC_PATH_BRACKETS_REGEXP.test(path)\n}\n\nexport function getDynamicPaths(pathname: string): string[] {\n return pathname.split('/').filter(isDynamicPath)\n}\n\nexport function extractPathKey(path: string): string {\n return path.slice(1, DYNAMIC_PATH_COLON_REGEXP.test(path) ? undefined : -1)\n}\n\n/**\n * Replaces dynamic paths in the pathname with values from the query\n * @param {string} pathname\n * @param {Record<string, string>} query\n * @returns {string} refined pathname\n */\nexport function refinePathnameWithQuery(pathname: string, query: Record<string, string>): string {\n return getDynamicPaths(pathname).reduce((acc, path) => {\n const pathKey = extractPathKey(path)\n return query[pathKey] ? acc.replace(path, query[pathKey]) : acc\n }, pathname)\n}\n\n/**\n * Removes queries that have already been used in the pathname.\n * @param {string} pathname\n * @param {Record<string, string>} query\n * @returns {Record<string, string>} refined query\n */\nexport function refineQueryWithPathname(pathname: string, query: Record<string, string>): Record<string, string> {\n return getDynamicPaths(pathname).reduce((acc, path) => {\n const pathKey = extractPathKey(path)\n const {[pathKey]: _, ...remainingQuery} = acc\n return remainingQuery\n }, query)\n}\n\nconst MAX_ASCII_CODE = 127\nexport function isASCIICodeChar(char: string) {\n return char.charCodeAt(0) > MAX_ASCII_CODE\n}\n","/**\n * Note: The trailing slash in the import path 'punycode/' is intentional.\n * It ensures that this third-party module is used instead of the built-in\n * Node.js 'punycode' module, which has been deprecated since Node.js v7.0.0.\n * @see https://github.com/mathiasbynens/punycode.js#installation\n * @see https://nodejs.org/api/punycode.html for deprecation info\n */\nimport {decode, encode} from 'punycode/'\n\nimport {\n extractPathKey,\n getDynamicPaths,\n isASCIICodeChar,\n isDynamicPath,\n refinePathnameWithQuery,\n refineQueryWithPathname,\n} from './utils'\n\ninterface URLOptions extends Partial<URL> {\n baseUrl?: string\n query?: Record<string, string>\n}\n\nexport default class NURL implements URL {\n private _href: string = ''\n private _protocol: string = ''\n private _host: string = ''\n private _hostname: string = ''\n private _port: string = ''\n private _pathname: string = ''\n private _search: string = ''\n private _hash: string = ''\n private _origin: string = ''\n private _username: string = ''\n private _password: string = ''\n private _baseUrl: string = ''\n private _searchParams: URLSearchParams = new URLSearchParams()\n\n constructor(input?: string | URL | URLOptions) {\n this._searchParams = new URLSearchParams()\n if (typeof input === 'string' || input instanceof URL) {\n this.href = input.toString()\n } else if (input) {\n if (input.baseUrl) {\n this.baseUrl = input.baseUrl\n }\n if (input.href) {\n this.href = input.href\n }\n if (input.protocol) {\n this.protocol = input.protocol\n }\n if (input.host) {\n this.host = input.host\n }\n if (input.hostname) {\n this.hostname = input.hostname\n }\n if (input.port) {\n this.port = input.port\n }\n if (input.pathname) {\n this.pathname = refinePathnameWithQuery(input.pathname, input.query ?? {})\n }\n if (input.search) {\n this.search = input.search\n }\n if (input.hash) {\n this.hash = input.hash\n }\n if (input.username) {\n this.username = input.username\n }\n if (input.password) {\n this.password = input.password\n }\n if (input.query) {\n const refinedQuery = refineQueryWithPathname(input.pathname ?? '', input.query)\n if (Object.keys(refinedQuery).length > 0) {\n this.search = new URLSearchParams(refinedQuery).toString()\n }\n }\n this.updateHref()\n }\n }\n\n static create(input?: string | URL | URLOptions) {\n return new NURL(input)\n }\n\n static canParse(input: string): boolean {\n if (input.startsWith('/')) {\n return /^\\/[^?#]*(\\?[^#]*)?(#.*)?$/.test(input)\n }\n\n try {\n // eslint-disable-next-line no-new\n new URL(input)\n return true\n } catch {\n // URL 생성자로 파싱할 수 없는 경우, 추가적인 검사를 수행\n // 예: 'example.com' 또는 'example.com/path'와 같은 형식 허용\n return /^[^:/?#]+(\\.[^:/?#]+)+(\\/[^?#]*(\\?[^#]*)?(#.*)?)?$/.test(input)\n }\n }\n\n get baseUrl(): string {\n return this._baseUrl\n }\n\n set baseUrl(value: string) {\n this._baseUrl = value\n try {\n const url = new URL(value)\n this._protocol = url.protocol\n this._host = url.host\n this._hostname = url.hostname\n this._port = url.port\n this._origin = url.origin\n this._username = url.username\n this._password = url.password\n if (url.pathname !== '/') {\n this._pathname = url.pathname\n }\n if (url.search) {\n this._search = url.search\n this._searchParams = new URLSearchParams(url.search)\n }\n if (url.hash) {\n this._hash = url.hash\n }\n this.updateHref()\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn(`Invalid baseUrl: ${value}`, error)\n }\n }\n\n get href(): string {\n return this.pathname.length === 1 ? `${this._href}/` : this._href\n }\n\n set href(value: string) {\n try {\n const url = new URL(value)\n this._href = url.href\n this._protocol = url.protocol\n this._host = url.host\n this._hostname = url.hostname\n this._port = url.port\n this._pathname = url.pathname\n this._search = url.search\n this._hash = url.hash\n this._origin = url.origin\n this._username = url.username\n this._password = url.password\n this._searchParams = url.searchParams\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn(`Can not parse ${value}`, error)\n }\n }\n\n get protocol(): string {\n return this._protocol\n }\n\n set protocol(value: string) {\n this._protocol = value\n this.updateHref()\n }\n\n get host(): string {\n return this._host\n }\n\n set host(value: string) {\n const [hostname, port] = value.split(':')\n\n const encodedHostname = this.encodeHostname(hostname)\n\n this._host = port ? `${encodedHostname}:${port}` : encodedHostname\n this._hostname = encodedHostname\n this._port = port || ''\n this.updateHref()\n }\n\n get hostname(): string {\n return this._hostname\n }\n\n set hostname(value: string) {\n const encodedHostname = this.encodeHostname(value)\n\n this._hostname = encodedHostname\n this._host = this._port ? `${encodedHostname}:${this._port}` : encodedHostname\n this.updateHref()\n }\n\n get port(): string {\n return this._port\n }\n\n set port(value: string) {\n this._port = value\n this._host = `${this._hostname}${value ? ':' + value : ''}`\n this.updateHref()\n }\n\n get pathname(): string {\n return this._pathname\n }\n\n set pathname(pathname: string) {\n const encodedPathname = pathname\n .split('/')\n .map((segment) => (isDynamicPath(segment) ? segment : encodeURI(segment)))\n .join('/')\n\n this._pathname = encodedPathname.startsWith('/') ? encodedPathname : `/${encodedPathname}`\n this.updateHref()\n }\n\n get search(): string {\n return this._search\n }\n\n set search(search: string) {\n const encodedSearch = encodeURI(search)\n this._search = encodedSearch.startsWith('?') ? encodedSearch : `?${encodedSearch}`\n this._searchParams = new URLSearchParams(encodedSearch)\n this.updateHref()\n }\n\n setSearchParams(_params: Record<string, string>): void {\n const searchParams = new URLSearchParams(_params)\n\n this._search = searchParams.toString() ? `?${searchParams.toString()}` : ''\n this._searchParams = searchParams\n this.updateHref()\n }\n\n appendSearchParams(_params: Record<string, string>): void {\n const searchParams = new URLSearchParams(this._searchParams)\n const dynamicRoutes = getDynamicPaths(this._pathname).map(extractPathKey)\n\n Object.keys(_params).forEach((key) => {\n if (dynamicRoutes.includes(key)) {\n this._pathname = refinePathnameWithQuery(this._pathname, {[key]: _params[key]})\n } else {\n searchParams.append(key, _params[key])\n }\n })\n\n this._search = searchParams.toString() ? `?${searchParams.toString()}` : ''\n this._searchParams = searchParams\n this.updateHref()\n }\n\n removeSearchParams(..._keys: string[]): void {\n const searchParams = new URLSearchParams(this._searchParams)\n\n _keys.forEach((key) => {\n searchParams.delete(key)\n })\n\n this._search = searchParams.toString() ? `?${searchParams.toString()}` : ''\n this._searchParams = searchParams\n this.updateHref()\n }\n\n get searchParams(): URLSearchParams {\n return new Proxy(this._searchParams, {\n get: (target, prop, receiver) => {\n const value = Reflect.get(target, prop, receiver)\n if (typeof value === 'function') {\n return (...args: unknown[]) => {\n const result = value.apply(target, args)\n this._search = this._searchParams.toString() ? `?${this._searchParams.toString()}` : ''\n this.updateHref()\n return result\n }\n }\n return value\n },\n })\n }\n\n get hash(): string {\n return this._hash\n }\n\n set hash(value: string) {\n this._hash = value.startsWith('#') ? value : `#${value}`\n this.updateHref()\n }\n\n get origin(): string {\n return this._origin\n }\n\n get username(): string {\n return this._username\n }\n\n set username(value: string) {\n this._username = value\n this.updateHref()\n }\n\n get password(): string {\n return this._password\n }\n\n set password(value: string) {\n this._password = value\n this.updateHref()\n }\n\n private updateHref() {\n if (this._baseUrl) {\n const baseUrl = new URL(this._baseUrl)\n baseUrl.pathname = this._pathname\n baseUrl.search = this._search\n baseUrl.hash = this._hash\n this._href = baseUrl.href\n this._origin = baseUrl.origin\n } else {\n this._href = `${this._protocol}${this._protocol && '//'}${this._username}${this._password ? ':' + this._password : ''}${\n this._username || this._password ? '@' : ''\n }${this._hostname}${this._port ? ':' + this._port : ''}${this._pathname === '/' ? '' : this._pathname}${this._search}${this._hash}`\n\n this._origin = `${this._protocol}//${this._hostname}${this._port ? ':' + this._port : ''}`\n }\n }\n\n toString(): string {\n return this.href\n }\n\n toJSON(): string {\n return this.href\n }\n\n private punycodePrefix = 'xn--'\n\n private encodeHostname(hostname: string): string {\n return hostname\n .split('.')\n .map((segment) => {\n for (const char of segment) {\n if (isASCIICodeChar(char)) {\n return `${this.punycodePrefix}${encode(segment)}`\n }\n }\n return segment\n })\n .join('.')\n }\n\n get decodedIDN(): string {\n let href = this._href\n\n this._hostname.split('.').forEach((segment) => {\n href = href.replace(segment, decode(segment.replace(this.punycodePrefix, '')))\n })\n\n return href\n }\n\n get decodedHostname(): string {\n return this._hostname\n .split('.')\n .map((segment) => decode(segment.replace(this.punycodePrefix, '')))\n .join('.')\n }\n}\n"],"names":["DYNAMIC_PATH_COLON_REGEXP","DYNAMIC_PATH_BRACKETS_REGEXP","isDynamicPath","path","test","getDynamicPaths","pathname","split","filter","extractPathKey","slice","refinePathnameWithQuery","query","reduce","acc","pathKey","replace","refineQueryWithPathname","_","remainingQuery","MAX_ASCII_CODE","isASCIICodeChar","char","charCodeAt","NURL","constructor","input","_href","_protocol","_host","_hostname","_port","_pathname","_search","_hash","_origin","_username","_password","_baseUrl","_searchParams","URLSearchParams","punycodePrefix","URL","href","toString","baseUrl","protocol","host","hostname","port","search","hash","username","password","refinedQuery","Object","keys","length","updateHref","create","canParse","startsWith","value","url","origin","error","console","warn","searchParams","encodedHostname","encodeHostname","encodedPathname","map","segment","encodeURI","join","encodedSearch","setSearchParams","_params","appendSearchParams","dynamicRoutes","forEach","key","includes","append","removeSearchParams","_keys","delete","Proxy","get","target","prop","receiver","Reflect","args","result","apply","toJSON","encode","decodedIDN","decode","decodedHostname"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "@naverpay/nurl",
3
+ "version": "0.0.2",
4
+ "description": "URL build library",
5
+ "main": "./dist/cjs/index.js",
6
+ "module": "./dist/module/index.js",
7
+ "exports": {
8
+ ".": {
9
+ "import": {
10
+ "types": "./dist/esm/index.d.mts",
11
+ "default": "./dist/esm/index.mjs"
12
+ },
13
+ "require": {
14
+ "types": "./dist/cjs/index.d.ts",
15
+ "default": "./dist/cjs/index.js"
16
+ }
17
+ },
18
+ "./package.json": "./package.json"
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "sideEffects": false,
24
+ "keywords": [
25
+ "url",
26
+ "uri"
27
+ ],
28
+ "author": "@NaverPayDev/frontend",
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://github.com/NaverPayDev/nurl.git"
32
+ },
33
+ "license": "MIT",
34
+ "dependencies": {
35
+ "@babel/runtime-corejs3": "^7.25.6",
36
+ "punycode": "^2.3.1"
37
+ },
38
+ "devDependencies": {
39
+ "@babel/plugin-transform-runtime": "^7.25.4",
40
+ "@babel/preset-env": "^7.25.4",
41
+ "@babel/runtime-corejs3": "^7.25.6",
42
+ "@changesets/cli": "^2.27.7",
43
+ "@naverpay/browserslist-config": "^1.6.1",
44
+ "@naverpay/editorconfig": "^0.0.4",
45
+ "@naverpay/eslint-config": "^1.0.7",
46
+ "@naverpay/markdown-lint": "^0.0.3",
47
+ "@naverpay/prettier-config": "^1.0.0",
48
+ "@rollup/plugin-babel": "^6.0.4",
49
+ "@types/punycode": "^2.1.4",
50
+ "browserslist-to-esbuild": "^2.1.1",
51
+ "tsup": "^8.2.4",
52
+ "typescript": "^5.5.4",
53
+ "vite": "^5.4.3",
54
+ "vitest": "^2.0.5"
55
+ },
56
+ "scripts": {
57
+ "clean": "rm -rf dist",
58
+ "build": "pnpm clean && vite build -c vite.config.mts && pnpm build-declarations",
59
+ "build-declarations:cjs": "tsup src/index.ts --format cjs --dts-only --out-dir ./dist/cjs --minify",
60
+ "build-declarations:esm": "tsup src/index.ts --format esm --dts-only --out-dir ./dist/esm --minify",
61
+ "build-declarations": "pnpm build-declarations:cjs && pnpm build-declarations:esm",
62
+ "test": "vitest run",
63
+ "test:watch": "vitest watch",
64
+ "lint": "eslint '**/*.{js,jsx,ts,tsx}'",
65
+ "lint:fix": "pnpm run lint --fix",
66
+ "prettier": "prettier --check '**/*.{json,yaml,md,ts,tsx,js,jsx}'",
67
+ "prettier:fix": "prettier --write '**/*.{json,yaml,md,ts,tsx,js,jsx}'",
68
+ "release": "changeset publish",
69
+ "markdownlint": "markdownlint '**/*.md' '#.changeset' '#**/CHANGELOG.md'",
70
+ "markdownlint:fix": "markdownlint --fix '**/*.md' '#.changeset' '#**/CHANGELOG.md'"
71
+ }
72
+ }