forked from hadarge/yoshi
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8663931
commit fd0a092
Showing
5 changed files
with
222 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
{ | ||
"name": "yoshi-serverless-client", | ||
"version": "4.105.0", | ||
"main": "build/index.js", | ||
"sideEffects": false, | ||
"keywords": [ | ||
"yoshi", | ||
"server" | ||
], | ||
"author": "Yaniv Efraim", | ||
"license": "ISC", | ||
"dependencies": { | ||
"@types/node-fetch": "1.6.9", | ||
"@wix/headers": "^1.7.0", | ||
"isomorphic-unfetch": "3.0.0", | ||
"toastify-js": "1.8.0" | ||
}, | ||
"peerDependencies": { | ||
"yoshi-serverless": "^4.14.0" | ||
}, | ||
"devDependencies": { | ||
"yoshi-serverless": "4.106.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
declare module 'toastify-js'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import unfetch from 'isomorphic-unfetch'; | ||
import { | ||
FunctionArgs, | ||
FunctionResult, | ||
UnpackPromise, | ||
DSL, | ||
RequestPayload, | ||
} from 'yoshi-serverless/types'; | ||
import { createHeaders } from '@wix/headers'; | ||
import { joinUrls, showToast } from './utils'; | ||
|
||
type Options = { | ||
baseUrl?: string; | ||
}; | ||
|
||
export interface HttpClient { | ||
request<Result extends FunctionResult, Args extends FunctionArgs>( | ||
method: DSL<Result, Args>, | ||
options?: { headers?: { [index: string]: string } }, | ||
): (...args: Args) => Promise<UnpackPromise<Result>>; | ||
} | ||
|
||
// https://github.com/developit/unfetch/issues/46 | ||
const fetch = unfetch; | ||
const serverlessBase = process.env.YOSHI_SERVERLESS_BASE; | ||
|
||
const defaultBaseUrl = serverlessBase | ||
? serverlessBase | ||
: `/_api/${process.env.PACKAGE_NAME}`; | ||
|
||
export default class implements HttpClient { | ||
private baseUrl: string; | ||
|
||
constructor({ baseUrl = defaultBaseUrl }: Options = {}) { | ||
this.baseUrl = baseUrl; | ||
} | ||
|
||
private getWixHeaders() { | ||
const wixHeaders = createHeaders(); | ||
if (process.env.NODE_ENV === 'development') { | ||
delete wixHeaders['x-xsrf-token']; | ||
} | ||
return wixHeaders as Record<string, string>; | ||
} | ||
|
||
request<Result extends FunctionResult, Args extends FunctionArgs>( | ||
method: DSL<Result, Args>, | ||
options?: { headers?: { [index: string]: string } }, | ||
): (...args: Args) => Promise<UnpackPromise<Result>> { | ||
return async (...args: Args) => { | ||
const url = joinUrls(this.baseUrl, '/_api_'); | ||
const { fileName, functionName } = method; | ||
const body: RequestPayload = { fileName, functionName, args }; | ||
|
||
const res = await fetch(url, { | ||
credentials: 'same-origin', | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
// WixHeaders has ? for each key. Here, keys which are undefined will be filtered automatically | ||
...this.getWixHeaders(), | ||
...options?.headers, | ||
}, | ||
body: JSON.stringify(body), | ||
}); | ||
|
||
if (!res.ok) { | ||
if (res.headers.get('content-type')?.includes('application/json')) { | ||
const error = await res.json(); | ||
if (process.env.NODE_ENV !== 'production') { | ||
if (process.env.browser) { | ||
showToast(error, method, args, this.baseUrl); | ||
} | ||
console.error(error); | ||
} | ||
throw new Error(JSON.stringify(error)); | ||
} else { | ||
const error = await res.text(); | ||
const errorMessage = ` | ||
Yoshi Server: the server returned a non JSON response. | ||
This is probable due to an error in one of the middlewares before Yoshi Server. | ||
${error} | ||
`; | ||
if (process.env.NODE_ENV !== 'production') { | ||
console.error(error); | ||
} | ||
|
||
throw new Error(errorMessage); | ||
} | ||
} | ||
|
||
const result = await res.json(); | ||
|
||
return result.payload; | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import unfetch from 'isomorphic-unfetch'; | ||
import { DSL, FunctionResult, FunctionArgs } from 'yoshi-serverless/types'; | ||
// https://github.com/developit/unfetch/issues/46 | ||
const fetch = unfetch; | ||
|
||
export function joinUrls(baseUrl: string, relativeUrl: string) { | ||
return baseUrl.replace(/\/+$/, '') + '/' + relativeUrl.replace(/^\/+/, ''); | ||
} | ||
|
||
export function showToast< | ||
Result extends FunctionResult, | ||
Args extends FunctionArgs | ||
>(error: any, method: DSL<Result, Args>, args: any, baseUrl: string) { | ||
const Toastify = require('toastify-js'); | ||
|
||
createCss(); | ||
|
||
Toastify({ | ||
duration: 60000, | ||
gravity: 'bottom', | ||
position: 'right', | ||
stopOnFocus: true, | ||
close: true, | ||
text: `😱😱😱 There was an error on your server function call. Click to open on your IDE<BR/> | ||
File: <b style="color: blue;cursor: pointer;"><u>${method.fileName}</u></b>, method: <b>${method.functionName}</b>: <BR/> | ||
Arguments: <b>${args}</b> <BR/> | ||
Error: ${error.errors[0].message} | ||
`, | ||
className: 'popover', | ||
async onClick() { | ||
const [, file, line, col] = error.errors[0].stack.match( | ||
/\/([/\w-_.]+\.[j|t]sx?):(\d*):(\d*)/, | ||
); | ||
await fetch( | ||
baseUrl + `/_launchEditor_?file=${file}&line=${line}&col=${col}`, | ||
{ | ||
credentials: 'same-origin', | ||
method: 'GET', | ||
}, | ||
); | ||
}, | ||
}).showToast(); | ||
} | ||
|
||
function createCss() { | ||
const toastStyle = 'toast-style'; | ||
if (document.querySelector(`#${toastStyle}`)) { | ||
return; | ||
} | ||
const css = document.createElement('style'); | ||
css.id = toastStyle; | ||
css.textContent = ` | ||
.toast-close { | ||
position: absolute; | ||
top: 0px; | ||
right: 0px; | ||
margin: 5px; | ||
cursor: pointer; | ||
} | ||
.popover { | ||
position: absolute; | ||
right: 20px; | ||
padding: 10px 20px; | ||
max-width: 500px; | ||
background: #fff; | ||
color: #000; | ||
font: initial; | ||
cursor: initial; | ||
letter-spacing: initial; | ||
text-shadow: initial; | ||
text-transform: initial; | ||
visibility: initial; | ||
font-size: 12px; | ||
line-height: 1.5; | ||
align-items: center; | ||
box-shadow: 0 11px 40px 0 rgba(0, 0, 0, 0.25), 0 2px 10px 0 rgba(0, 0, 0, 0.12); | ||
transition: bottom 1.5s ease; | ||
} | ||
`; | ||
|
||
document.body.appendChild(css); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
{ | ||
"extends": "../../tsconfig.json", | ||
"compilerOptions": { | ||
"rootDir": "src", | ||
"outDir": "build", | ||
"target": "es5" | ||
}, | ||
"include": [ | ||
"src/**/*", | ||
"src/**/*.json" | ||
], | ||
"files": [ | ||
"./src/external-types.d.ts", | ||
], | ||
"references": [ | ||
{ "path": "../yoshi-serverless" } | ||
] | ||
} |