diff --git a/README.md b/README.md index 5059139..dcd1ac9 100644 --- a/README.md +++ b/README.md @@ -290,7 +290,7 @@ interesting approach to organizing build tasks. - 🪺 [recursive-exec](https://github.com/center-key/recursive-exec):  _Run a command on each file in a folder and its subfolders_ - 🔍 [replacer-util](https://github.com/center-key/replacer-util):  _Find and replace strings or template outputs in text files_ - 🔢 [rev-web-assets](https://github.com/center-key/rev-web-assets):  _Revision web asset filenames with cache busting content hash fingerprints_ - - 🚆 [run-scripts-util](https://github.com/center-key/run-scripts-util):  _Organize npm package.json scripts into named groups of easy to manage commands_ + - 🚆 [run-scripts-util](https://github.com/center-key/run-scripts-util):  _Organize npm package.json scripts into groups of easy to manage commands_ - 🚦 [w3c-html-validator](https://github.com/center-key/w3c-html-validator):  _Check the markup validity of HTML files using the W3C validator_
diff --git a/dist/fetch-json.d.ts b/dist/fetch-json.d.ts index a2a8b04..cb94130 100644 --- a/dist/fetch-json.d.ts +++ b/dist/fetch-json.d.ts @@ -1,4 +1,4 @@ -//! fetch-json v3.3.1 ~~ https://fetch-json.js.org ~~ MIT License +//! fetch-json v3.3.2 ~~ https://fetch-json.js.org ~~ MIT License export type Json = string | number | boolean | null | undefined | JsonObject | Json[]; export type JsonObject = { @@ -13,7 +13,6 @@ export type FetchJsonMethod = string; export type FetchJsonParams = { [field: string]: string | number | boolean | null | undefined; }; -export type FetchJsonParsedResponse = Json | any; export type FetchJsonAltResponse = { ok: boolean; error: boolean; @@ -23,20 +22,19 @@ export type FetchJsonAltResponse = { data: Json | null; response: Response; }; -export type FetchJsonResponse = FetchJsonParsedResponse | FetchJsonAltResponse; export type FetchJsonLogger = (dateIso: string, type?: 'response' | 'request', method?: FetchJsonMethod, domain?: string, url?: string, ok?: boolean, status?: number, statusText?: string, contentType?: string | null) => void; declare const fetchJson: { version: string; baseOptions: FetchJsonOptions; getBaseOptions(): FetchJsonOptions; setBaseOptions(options: FetchJsonOptions): FetchJsonOptions; - request(method: FetchJsonMethod, url: string, data?: FetchJsonParams | Json | T, options?: FetchJsonOptions): Promise; - get(url: string, params?: FetchJsonParams, options?: FetchJsonOptions): Promise; - post(url: string, resource?: Json | T, options?: FetchJsonOptions): Promise; - put(url: string, resource?: Json | T, options?: FetchJsonOptions): Promise; - patch(url: string, resource?: Json | T, options?: FetchJsonOptions): Promise; - delete(url: string, resource?: Json | T, options?: FetchJsonOptions): Promise; - head(url: string, params?: FetchJsonParams, options?: FetchJsonOptions): Promise; + request(method: FetchJsonMethod, url: string, data?: unknown, options?: FetchJsonOptions): Promise; + get(url: string, params?: FetchJsonParams, options?: FetchJsonOptions): Promise; + post(url: string, resource?: unknown, options?: FetchJsonOptions): Promise; + put(url: string, resource?: unknown, options?: FetchJsonOptions): Promise; + patch(url: string, resource?: unknown, options?: FetchJsonOptions): Promise; + delete(url: string, resource?: unknown, options?: FetchJsonOptions): Promise; + head(url: string, params?: FetchJsonParams, options?: FetchJsonOptions): Promise; logger: FetchJsonLogger | null; getLogHeaders(): string[]; getLogHeaderIndexMap(): { diff --git a/dist/fetch-json.dev.js b/dist/fetch-json.dev.js index c736b41..c6e9bd4 100644 --- a/dist/fetch-json.dev.js +++ b/dist/fetch-json.dev.js @@ -1,7 +1,7 @@ -//! fetch-json v3.3.1 ~~ https://fetch-json.js.org ~~ MIT License +//! fetch-json v3.3.2 ~~ https://fetch-json.js.org ~~ MIT License const fetchJson = { - version: '3.3.1', + version: '3.3.2', baseOptions: {}, getBaseOptions() { return this.baseOptions; @@ -18,9 +18,9 @@ const fetchJson = { }; const settings = { ...defaults, ...this.baseOptions, ...options }; if (!settings.method || typeof settings.method !== 'string') - throw Error('[fetch-json] HTTP method missing or invalid.'); + throw new Error('[fetch-json] HTTP method missing or invalid.'); if (typeof url !== 'string') - throw Error('[fetch-json] URL must be a string.'); + throw new Error('[fetch-json] URL must be a string.'); const httpMethod = settings.method.trim().toUpperCase(); const isGetRequest = httpMethod === 'GET'; const jsonHeaders = { Accept: 'application/json' }; @@ -66,7 +66,7 @@ const fetchJson = { }); log('response', response.ok, response.status, response.statusText, contentType); if (settings.strictErrors && !response.ok) - throw Error('[fetch-json] HTTP response status ("strictErrors" mode enabled): ' + response.status); + throw new Error(`[fetch-json] HTTP response status ("strictErrors" mode enabled): ${response.status}`); return isHead ? response.text().then(headersObj) : isJson ? response.json().then(jsonToObj).catch(errToObj) : response.text().then(textToObj); }; diff --git a/dist/fetch-json.js b/dist/fetch-json.js index c9123bc..cc144ad 100644 --- a/dist/fetch-json.js +++ b/dist/fetch-json.js @@ -1,7 +1,7 @@ -//! fetch-json v3.3.1 ~~ https://fetch-json.js.org ~~ MIT License +//! fetch-json v3.3.2 ~~ https://fetch-json.js.org ~~ MIT License const fetchJson = { - version: '3.3.1', + version: '3.3.2', baseOptions: {}, getBaseOptions() { return this.baseOptions; @@ -18,9 +18,9 @@ const fetchJson = { }; const settings = { ...defaults, ...this.baseOptions, ...options }; if (!settings.method || typeof settings.method !== 'string') - throw Error('[fetch-json] HTTP method missing or invalid.'); + throw new Error('[fetch-json] HTTP method missing or invalid.'); if (typeof url !== 'string') - throw Error('[fetch-json] URL must be a string.'); + throw new Error('[fetch-json] URL must be a string.'); const httpMethod = settings.method.trim().toUpperCase(); const isGetRequest = httpMethod === 'GET'; const jsonHeaders = { Accept: 'application/json' }; @@ -66,7 +66,7 @@ const fetchJson = { }); log('response', response.ok, response.status, response.statusText, contentType); if (settings.strictErrors && !response.ok) - throw Error('[fetch-json] HTTP response status ("strictErrors" mode enabled): ' + response.status); + throw new Error(`[fetch-json] HTTP response status ("strictErrors" mode enabled): ${response.status}`); return isHead ? response.text().then(headersObj) : isJson ? response.json().then(jsonToObj).catch(errToObj) : response.text().then(textToObj); }; diff --git a/dist/fetch-json.min.js b/dist/fetch-json.min.js index 6bc7781..8e324a0 100644 --- a/dist/fetch-json.min.js +++ b/dist/fetch-json.min.js @@ -1,2 +1,2 @@ -//! fetch-json v3.3.1 ~~ https://fetch-json.js.org ~~ MIT License -const fetchJson={version:"3.3.1",baseOptions:{},getBaseOptions(){return this.baseOptions},setBaseOptions(options){this.baseOptions=options;return this.baseOptions},request(method,url,data,options){const defaults={method:method,credentials:"same-origin",strictErrors:false};const settings={...defaults,...this.baseOptions,...options};if(!settings.method||typeof settings.method!=="string")throw Error("[fetch-json] HTTP method missing or invalid.");if(typeof url!=="string")throw Error("[fetch-json] URL must be a string.");const httpMethod=settings.method.trim().toUpperCase();const isGetRequest=httpMethod==="GET";const jsonHeaders={Accept:"application/json"};if(!isGetRequest&&data)jsonHeaders["Content-Type"]="application/json";settings.headers={...jsonHeaders,...settings.headers};const paramKeys=isGetRequest&&data?Object.keys(data):[];const getValue=key=>data?data[key]:"";const toPair=key=>key+"="+encodeURIComponent(getValue(key));const params=()=>paramKeys.map(toPair).join("&");const requestUrl=!paramKeys.length?url:url+(url.includes("?")?"&":"?")+params();settings.body=!isGetRequest&&data?JSON.stringify(data):null;const log=(type,...items)=>{const logUrl=url.replace(/[?].*/,"");const domain=logUrl.replace(/.*:[/][/]/,"").replace(/[:/].*/,"");if(this.logger)this.logger((new Date).toISOString(),type,httpMethod,domain,logUrl,...items)};const toJson=value=>{const response=value;const contentType=response.headers.get("content-type");const isHead=httpMethod==="HEAD";const isJson=!!contentType&&/json|javascript/.test(contentType);const headersObj=()=>Object.fromEntries(response.headers.entries());const textToObj=(httpBody,data)=>({ok:response.ok,error:!response.ok,status:response.status,contentType:contentType,bodyText:httpBody,data:data??null,response:response});const jsonToObj=data=>response.ok?data:textToObj(JSON.stringify(data),data);const errToObj=error=>({ok:false,error:true,status:500,contentType:contentType,bodyText:"Invalid JSON ["+error.toString()+"]",data:null,response:response});log("response",response.ok,response.status,response.statusText,contentType);if(settings.strictErrors&&!response.ok)throw Error('[fetch-json] HTTP response status ("strictErrors" mode enabled): '+response.status);return isHead?response.text().then(headersObj):isJson?response.json().then(jsonToObj).catch(errToObj):response.text().then(textToObj)};log("request");const settingsRequestInit=JSON.parse(JSON.stringify(settings));return fetch(requestUrl,settingsRequestInit).then(toJson)},get(url,params,options){return this.request("GET",url,params,options)},post(url,resource,options){return this.request("POST",url,resource,options)},put(url,resource,options){return this.request("PUT",url,resource,options)},patch(url,resource,options){return this.request("PATCH",url,resource,options)},delete(url,resource,options){return this.request("DELETE",url,resource,options)},head(url,params,options){return this.request("HEAD",url,params,options)},logger:null,getLogHeaders(){return["Timestamp","HTTP","Method","Domain","URL","Ok","Status","Text","Type"]},getLogHeaderIndexMap(){return{timestamp:0,http:1,method:2,domain:3,url:4,ok:5,status:6,text:7,type:8}},enableLogger(customLogger){this.logger=customLogger??console.log;return this.logger},disableLogger(){this.logger=null}};class FetchJson{constructor(options){this.fetchJson={...fetchJson};this.fetchJson.setBaseOptions(options||{})}}globalThis.fetchJson=fetchJson;globalThis.FetchJson=FetchJson; +//! fetch-json v3.3.2 ~~ https://fetch-json.js.org ~~ MIT License +const fetchJson={version:"3.3.2",baseOptions:{},getBaseOptions(){return this.baseOptions},setBaseOptions(options){this.baseOptions=options;return this.baseOptions},request(method,url,data,options){const defaults={method:method,credentials:"same-origin",strictErrors:false};const settings={...defaults,...this.baseOptions,...options};if(!settings.method||typeof settings.method!=="string")throw new Error("[fetch-json] HTTP method missing or invalid.");if(typeof url!=="string")throw new Error("[fetch-json] URL must be a string.");const httpMethod=settings.method.trim().toUpperCase();const isGetRequest=httpMethod==="GET";const jsonHeaders={Accept:"application/json"};if(!isGetRequest&&data)jsonHeaders["Content-Type"]="application/json";settings.headers={...jsonHeaders,...settings.headers};const paramKeys=isGetRequest&&data?Object.keys(data):[];const getValue=key=>data?data[key]:"";const toPair=key=>key+"="+encodeURIComponent(getValue(key));const params=()=>paramKeys.map(toPair).join("&");const requestUrl=!paramKeys.length?url:url+(url.includes("?")?"&":"?")+params();settings.body=!isGetRequest&&data?JSON.stringify(data):null;const log=(type,...items)=>{const logUrl=url.replace(/[?].*/,"");const domain=logUrl.replace(/.*:[/][/]/,"").replace(/[:/].*/,"");if(this.logger)this.logger((new Date).toISOString(),type,httpMethod,domain,logUrl,...items)};const toJson=value=>{const response=value;const contentType=response.headers.get("content-type");const isHead=httpMethod==="HEAD";const isJson=!!contentType&&/json|javascript/.test(contentType);const headersObj=()=>Object.fromEntries(response.headers.entries());const textToObj=(httpBody,data)=>({ok:response.ok,error:!response.ok,status:response.status,contentType:contentType,bodyText:httpBody,data:data??null,response:response});const jsonToObj=data=>response.ok?data:textToObj(JSON.stringify(data),data);const errToObj=error=>({ok:false,error:true,status:500,contentType:contentType,bodyText:"Invalid JSON ["+error.toString()+"]",data:null,response:response});log("response",response.ok,response.status,response.statusText,contentType);if(settings.strictErrors&&!response.ok)throw new Error(`[fetch-json] HTTP response status ("strictErrors" mode enabled): ${response.status}`);return isHead?response.text().then(headersObj):isJson?response.json().then(jsonToObj).catch(errToObj):response.text().then(textToObj)};log("request");const settingsRequestInit=JSON.parse(JSON.stringify(settings));return fetch(requestUrl,settingsRequestInit).then(toJson)},get(url,params,options){return this.request("GET",url,params,options)},post(url,resource,options){return this.request("POST",url,resource,options)},put(url,resource,options){return this.request("PUT",url,resource,options)},patch(url,resource,options){return this.request("PATCH",url,resource,options)},delete(url,resource,options){return this.request("DELETE",url,resource,options)},head(url,params,options){return this.request("HEAD",url,params,options)},logger:null,getLogHeaders(){return["Timestamp","HTTP","Method","Domain","URL","Ok","Status","Text","Type"]},getLogHeaderIndexMap(){return{timestamp:0,http:1,method:2,domain:3,url:4,ok:5,status:6,text:7,type:8}},enableLogger(customLogger){this.logger=customLogger??console.log;return this.logger},disableLogger(){this.logger=null}};class FetchJson{constructor(options){this.fetchJson={...fetchJson};this.fetchJson.setBaseOptions(options||{})}}globalThis.fetchJson=fetchJson;globalThis.FetchJson=FetchJson; diff --git a/docs/index.html b/docs/index.html index d3351d3..4a9a648 100644 --- a/docs/index.html +++ b/docs/index.html @@ -20,7 +20,7 @@ fetch-json • A wrapper around Fetch just for JSON - + diff --git a/package.json b/package.json index 2e91176..2a293f6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "fetch-json", "description": "A wrapper around Fetch just for JSON", - "version": "3.3.1", + "version": "3.3.2", "license": "MIT", "type": "module", "module": "dist/fetch-json.js",