mirror of
				https://codeberg.org/ashley/poke
				synced 2025-07-17 16:52:11 +00:00 
			
		
		
		
	Create node-superfetch.js
This commit is contained in:
		
							parent
							
								
									0256b96674
								
							
						
					
					
						commit
						d2cb3337e1
					
				
							
								
								
									
										168
									
								
								src/modules/node-superfetch.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								src/modules/node-superfetch.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,168 @@ | |||||||
|  | /* | ||||||
|  | Internet Systems Consortium license | ||||||
|  | =================================== | ||||||
|  | 
 | ||||||
|  | Copyright (c) 2017-2018, dragonfire535 | ||||||
|  | 
 | ||||||
|  | https://github.com/dragonfire535/node-superfetch
 | ||||||
|  | 
 | ||||||
|  | Permission to use, copy, modify, and/or distribute this software for any purpose | ||||||
|  | with or without fee is hereby granted, provided that the above copyright notice | ||||||
|  | and this permission notice appear in all copies. | ||||||
|  | 
 | ||||||
|  | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH | ||||||
|  | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | ||||||
|  | FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, | ||||||
|  | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS | ||||||
|  | OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | ||||||
|  | TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF | ||||||
|  | THIS SOFTWARE. | ||||||
|  | 
 | ||||||
|  |   */ | ||||||
|  | const fetch = require('node-fetch'); | ||||||
|  | const FormData = require('form-data'); | ||||||
|  | const { URL } = require('url'); | ||||||
|  | const { METHODS } = require('http'); | ||||||
|  |   | ||||||
|  | class Request { | ||||||
|  | 	constructor(options) { | ||||||
|  | 		if (!options.url) throw new Error('The "url" option is required.'); | ||||||
|  | 		this.url = new URL(options.url); | ||||||
|  | 		this.method = options.method ? options.method.toUpperCase() : 'GET'; | ||||||
|  | 		if (!METHODS.includes(this.method)) throw new Error(`The method "${this.method}" is not supported.`); | ||||||
|  | 		this.headers = options.headers || {}; | ||||||
|  | 		this.body = options.body || null; | ||||||
|  | 		this.redirectCount = typeof options.redirects === 'undefined' ? 20 : options.redirects; | ||||||
|  | 		this.agent = options.agent || null; | ||||||
|  | 		this.noResultData = options.noResultData || false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	async _request() { | ||||||
|  | 		const response = await fetch(this.url.toString(), { | ||||||
|  | 			method: this.method, | ||||||
|  | 			headers: this.headers, | ||||||
|  | 			follow: this.redirectCount, | ||||||
|  | 			body: this.body, | ||||||
|  | 			agent: this.agent | ||||||
|  | 		}); | ||||||
|  | 		let raw = null; | ||||||
|  | 		if (!this.noResultData) raw = await response.buffer(); | ||||||
|  | 		const headers = {}; | ||||||
|  | 		for (const [header, value] of response.headers.entries()) headers[header] = value; | ||||||
|  | 		const res = { | ||||||
|  | 			status: response.status, | ||||||
|  | 			statusText: response.statusText, | ||||||
|  | 			headers, | ||||||
|  | 			url: response.url, | ||||||
|  | 			redirected: response.redirected, | ||||||
|  | 			ok: response.ok, | ||||||
|  | 			raw, | ||||||
|  | 			get text() { | ||||||
|  | 				if (this.noResultData) return null; | ||||||
|  | 				return raw.toString(); | ||||||
|  | 			}, | ||||||
|  | 			get body() { | ||||||
|  | 				if (this.noResultData) return null; | ||||||
|  | 				if (/application\/json/gi.test(headers['content-type'])) { | ||||||
|  | 					try { | ||||||
|  | 						return JSON.parse(raw.toString()); | ||||||
|  | 					} catch (err) { | ||||||
|  | 						return raw.toString(); | ||||||
|  | 					} | ||||||
|  | 				} else { | ||||||
|  | 					return raw; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		}; | ||||||
|  | 		if (!response.ok) { | ||||||
|  | 			const err = new Error(`${res.status} ${res.statusText}`); | ||||||
|  | 			Object.assign(err, res); | ||||||
|  | 			throw err; | ||||||
|  | 		} | ||||||
|  | 		return res; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	then(resolver, rejector) { | ||||||
|  | 		return this._request().then(resolver, rejector); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	catch(rejector) { | ||||||
|  | 		return this.then(null, rejector); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	end(cb) { | ||||||
|  | 		return this.then( | ||||||
|  | 			response => cb ? cb(null, response) : response, | ||||||
|  | 			err => cb ? cb(err, err.status ? err : null) : err | ||||||
|  | 		); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	query(queryOrName, value) { | ||||||
|  | 		if (typeof queryOrName === 'object') { | ||||||
|  | 			for (const [param, val] of Object.entries(queryOrName)) this.url.searchParams.append(param, val); | ||||||
|  | 		} else if (typeof queryOrName === 'string' && value) { | ||||||
|  | 			this.url.searchParams.append(queryOrName, value); | ||||||
|  | 		} else { | ||||||
|  | 			throw new TypeError('The "query" parameter must be either an object or a query field.'); | ||||||
|  | 		} | ||||||
|  | 		return this; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	set(headersOrName, value) { | ||||||
|  | 		if (typeof headersOrName === 'object') { | ||||||
|  | 			for (const [header, val] of Object.entries(headersOrName)) this.headers[header] = val; | ||||||
|  | 		} else if (typeof headersOrName === 'string' && value) { | ||||||
|  | 			this.headers[headersOrName] = value; | ||||||
|  | 		} else { | ||||||
|  | 			throw new TypeError('The "headers" parameter must be either an object or a header field.'); | ||||||
|  | 		} | ||||||
|  | 		return this; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	attach(...args) { | ||||||
|  | 		if (!this.body || !(this.body instanceof FormData)) this.body = new FormData(); | ||||||
|  | 		if (typeof args[0] === 'object') { | ||||||
|  | 			for (const [key, val] of Object.entries(args[0])) this.attach(key, val); | ||||||
|  | 		} else { | ||||||
|  | 			this.body.append(...args); | ||||||
|  | 		} | ||||||
|  | 		this.set(this.body.getHeaders()); | ||||||
|  | 		this.set('content-length', this.body.getLengthSync()); | ||||||
|  | 		return this; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	send(body, raw = false) { | ||||||
|  | 		if (body instanceof FormData) raw = true; | ||||||
|  | 		if (!raw && body !== null && typeof body === 'object') { | ||||||
|  | 			const header = this.headers['content-type']; | ||||||
|  | 			if (header) { | ||||||
|  | 				if (/application\/json/gi.test(header)) body = JSON.stringify(body); | ||||||
|  | 			} else { | ||||||
|  | 				this.set('content-type', 'application/json'); | ||||||
|  | 				body = JSON.stringify(body); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		this.body = body; | ||||||
|  | 		return this; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	redirects(amount) { | ||||||
|  | 		if (typeof amount !== 'number') throw new TypeError('The "amount" parameter must be a number.'); | ||||||
|  | 		this.redirectCount = amount; | ||||||
|  | 		return this; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	agent(agent) { | ||||||
|  | 		this.agent = agent; | ||||||
|  | 		return this; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | for (const method of METHODS) { | ||||||
|  | 	if (!/^[A-Z$_]+$/gi.test(method)) continue; | ||||||
|  | 	Request[method.toLowerCase()] = (url, options) => new Request({ url, method, ...options }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Request.version = "1.0.0"; | ||||||
|  | 
 | ||||||
|  | module.exports = Request; | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Ashley
						Ashley