Skip to content

Commit

Permalink
chore: localize fetch-jsonp
Browse files Browse the repository at this point in the history
  • Loading branch information
ghiscoding committed Dec 13, 2024
1 parent ec2e01f commit 2dccc2a
Show file tree
Hide file tree
Showing 8 changed files with 248 additions and 75 deletions.
59 changes: 27 additions & 32 deletions webpack-bs5-demo-with-locales/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion webpack-bs5-demo-with-locales/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
"aurelia-slickgrid": "^8.10.2",
"bootstrap": "^5.3.3",
"dompurify": "^3.2.2",
"fetch-jsonp": "^1.3.0",
"rxjs": "^7.8.1",
"tslib": "^2.8.1"
},
Expand Down
92 changes: 92 additions & 0 deletions webpack-bs5-demo-with-locales/src/examples/jsonp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* copied and rewritten as ESM (just a simple rewrite as ESM to avoid loading a CJS package)
* https://github.com/camsong/fetch-jsonp/blob/master/src/fetch-jsonp.js
*/

interface JsonpOptions {
timeout: number;
jsonpCallback: string;
jsonpCallbackFunction: string;
charset: string;
nonce: string;
referrerPolicy: string;
crossorigin: boolean;
}

const defaultOptions = {
timeout: 5000,
jsonpCallback: 'callback',
jsonpCallbackFunction: null,
};
const generateCallbackFunction = () => `jsonp_${Date.now()}_${Math.ceil(Math.random() * 100000)}`;
const clearFunction = (functionName: string) => delete (window as any)[functionName];
const removeScript = (scriptId: string) => {
const script = document.getElementById(scriptId);
if (script) {
document.getElementsByTagName('head')[0].removeChild(script);
}
};

function fetchJsonp<T = any>(
_url: string,
options: Partial<JsonpOptions> = {}
): Promise<{ ok: boolean; json: () => Promise<T> }> {
// to avoid param reassign
let url = _url;
const timeout = options.timeout || defaultOptions.timeout;
const jsonpCallback = options.jsonpCallback || defaultOptions.jsonpCallback;
let timeoutId: any;

return new Promise((resolve, reject) => {
const callbackFunction = options.jsonpCallbackFunction || generateCallbackFunction();
const scriptId = `${jsonpCallback}_${callbackFunction}`;

(window as any)[callbackFunction] = (response: T) => {
// keep consistent with fetch API
resolve({ ok: true, json: () => Promise.resolve(response) });
if (timeoutId) { clearTimeout(timeoutId); }
removeScript(scriptId);
clearFunction(callbackFunction);
};

// Check if the user set their own params, and if not add a ? to start a list of params
url += url.indexOf('?') === -1 ? '?' : '&';

const jsonpScript = document.createElement('script');
jsonpScript.setAttribute('src', `${url}${jsonpCallback}=${callbackFunction}`);
if (options.charset) {
jsonpScript.setAttribute('charset', options.charset);
}
if (options.nonce) {
jsonpScript.setAttribute('nonce', options.nonce);
}
if (options.referrerPolicy) {
jsonpScript.setAttribute('referrerPolicy', options.referrerPolicy);
}
if (options.crossorigin) {
jsonpScript.setAttribute('crossorigin', 'true');
}
jsonpScript.id = scriptId;
document.getElementsByTagName('head')[0].appendChild(jsonpScript);

timeoutId = setTimeout(() => {
reject(new Error(`JSONP request to ${_url} timed out`));

clearFunction(callbackFunction);
removeScript(scriptId);
(window as any)[callbackFunction] = () => {
clearFunction(callbackFunction);
};
}, timeout);

// Caught if got 404/500
jsonpScript.onerror = () => {
reject(new Error(`JSONP request to ${_url} failed`));
clearFunction(callbackFunction);
removeScript(scriptId);
if (timeoutId) { clearTimeout(timeoutId); }
};
});
}

export default fetchJsonp;
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { IHttpClient } from '@aurelia/fetch-client';
import { newInstanceOf, resolve } from '@aurelia/kernel';
import fetchJsonp from 'fetch-jsonp';

import {
type AureliaGridInstance,
type AutocompleterOption,
Expand All @@ -19,8 +17,10 @@ import {
SortComparers,
type VanillaCalendarOption,
} from 'aurelia-slickgrid';

import { CustomInputEditor } from './custom-inputEditor';
import { CustomInputFilter } from './custom-inputFilter';
import fetchJsonp from '../jsonp';

const NB_ITEMS = 100;
const URL_SAMPLE_COLLECTION_DATA = 'assets/data/collection_100_numbers.json';
Expand Down Expand Up @@ -278,7 +278,7 @@ export class Example3 {
// this.http.get(`http://gd.geobytes.com/AutoCompleteCity?q=${searchText}`).subscribe(data => updateCallback(data));

/** with JSONP AJAX will work locally but not on the GitHub demo because of CORS */
fetchJsonp(`http://gd.geobytes.com/AutoCompleteCity?q=${searchText}`)
fetchJsonp<string[]>(`http://gd.geobytes.com/AutoCompleteCity?q=${searchText}`, { crossorigin: true })
.then((response: { json: () => Promise<any[]> }) => response.json())
.then((json: any[]) => updateCallback(json))
.catch((ex) => console.log('invalid JSONP response', ex));
Expand All @@ -297,7 +297,7 @@ export class Example3 {
filterOptions: {
minLength: 3,
fetch: (searchText: string, updateCallback: (items: false | any[]) => void) => {
fetchJsonp(`http://gd.geobytes.com/AutoCompleteCity?q=${searchText}`)
fetchJsonp<string[]>(`http://gd.geobytes.com/AutoCompleteCity?q=${searchText}`, { crossorigin: true })
.then((response: { json: () => Promise<any[]> }) => response.json())
.then((json: any[]) => updateCallback(json))
.catch((ex: any) => console.log('invalid JSONP response', ex));
Expand Down
Loading

0 comments on commit 2dccc2a

Please sign in to comment.