As per Apollo Documentation adding Custom Directive is as follow:
class isAuth extends SchemaDirectiveVisitor {
// field defination for resolving
// directive.
public visitFieldDefinition(field) {
// overspreading.
const { resolve = defaultFieldResolver } = field;
// resolve field.
field.resolve = async function(__, Context) {
// check if Context
// contain's user object
// which was resolved by jwt.
if(!Context.user){
throw new Error('User not authenticated');
}
// resolve return awaited resolve call.
return await resolve.apply(this, __);
};
}
}
but using this will going to result in an unexpected token error.
class isAuth extends SchemaDirectiveVisitor {
// field defination for resolving
// directive.
visitFieldDefinition(field) { <---- Removed Public keyword
// overspreading.
const { resolve = defaultFieldResolver } = field;
// resolve field.
field.resolve = async function(__, Context) {
// check if Context
// contain's user object
// which was resolved by jwt.
if(!Context.user){
throw new Error('User not authenticated');
}
// resolve return awaited resolve call.
return await resolve.apply(this, __);
};
}
}
this will going to work but not for apollo Package.
please note: Apollo is graphql library
public keyword is present in JavaScript but it is reserved for future use.
Therefore as of 2019, any JavaScript parser will always give you unexpected token error.
Related
not sure what I am doing wrong but it seems fairly simple in my head. I have a class that creates a new Session class inside it. If the MainClass 's foo function throws, session's deleteEmpty function is called.
I am trying in my test to ensure that thrown has a value and that the deleteEmpty is called. When I have the thrown assertion itself, it passes. When I add the assertion to check deleteEmpty is called, it fails but the console has no output as to why.
MainClass
const token = "12345";
const data = { /// };
const session = new Session(token, data);
async function foo() {
try {
//
} catch(error) {
await this.session.deleteEmpty();
throw error;
}
}
testFile
const sessionMock = Sinon.createStubInstance(Session)
let thrown: Error | undefined = undefined;
sandbox.stub(MainClass, 'foo').throws();
try {
await MainClass.foo();
} catch(error) {
thrown = error;
}
expect(sessionMock.deleteEmpty).calledOnce;
expect(thrown).to.not.be.undefined;
I have a Node server where I want to integrate Paypal. I have one module that is supposed to return the access token from paypal. This module has one async function and looks something like this:
let token: string | null = null;
export async function getToken() {
if (token === null) {
token = await requestTokenFromPaypal()
}
return token;
}
export function resetToken() { token = null }
main:
getToken()
getToken()
getToken()
// -> I want all calls to wait until the first request for the token is finished and then resolve to the token
// -> Currently the token will be requested three times
The resetToken function is called if the other requests yield 401 and the token is invalid. So a new token is needed. But now every call to the getToken will result in a token request until the first request is finished and saved to token.
So how can I wait for the result from another function that was called from a different piece of code? I have already thought about saving the promise or something like that but I cant wrap my head around it.
I also tried to google it but only get the standart async code questions. Please refer me if you find other similar questions.
Instead of checking whether the token is available, you could check whether the request for the token has already been started.
You can do this by checking on the tokenPromise that is basically just a wrapper around the token.
let tokenPromise = null
export async function getToken() {
if (!tokenPromise) {
tokenPromise = requestTokenFromPaypal()
}
return tokenPromise
}
export function resetToken() { tokenPromise = null }
In case you wonder, directly returning the tokenPromise without awaiting for it will actually have the same effect as awaiting for it and then returning the token.
Simply return a promise, and .then it.
let token: string | null = null;
export async function getToken() {
if (token === null) {
return requestTokenFromPaypal() // this function should return a promise
/* (node-fetch would be the easiest way to do that, but whatever works) */
}
return Promise.resolve(token);
}
export function resetToken() { token = null }
//later, somewhere else in your code
getToken().then(function(token) {
//do something with 'token'
});
My store's processAction() function calls a private async function in a fire-and-forget manner which then does a fetch. processAction() itself does not handle any error handling, and--in the browser--if the fetch fails, an external library handles any and all uncaught promise rejections.
So, if I mock my fetch to reject, the private function--the effects of which I am testing--will reject. Since I don't have a reference to the promise created by my async function call, I have no way of catching the rejection within the test, but the test fails because there was an unhandled rejection.
How can I tell jest to be okay with this short of calling the private function itself rather than just triggering the action that calls it?
actions.ts
const actions = {
doTheThing() {
dispatch({ type: 'DO_THE_THING' });
},
};
export default actions;
store.ts
import fetch from './fetch';
class Store {
isFetching = false;
// ...
processAction({ type, payload }: { type: string, payload: any }) {
switch (type) {
case 'DO_THE_THING':
this.fetchTheThing();
break;
}
}
private async fetchTheThing() {
try {
this.isFetching = true;
const result = await fetch(myUrl);
// ...
} finally {
this.isFetching = false;
}
}
}
export default new Store();
__mocks__/fetch.ts
let val: any;
interface fetch {
__setVal(value: any): void;
}
export default async function fetch() {
return val;
}
fetch.__setVal = function(value: any) {
val = value;
};
store.test.ts
import actions from './actions';
import store from './store';
const fetch = (require('./fetch') as import('./__mocks__/fetch')).default;
jest.mock('./fetch');
test('it sets/unsets isFetching on failure', async () => {
let rej: () => void;
fetch.__setVal(new Promise((_, reject) => rej = reject));
expect(store.isFetching).toBe(false);
Actions.doTheThing();
await Promise.sleep(); // helper function
expect(store.isFetching).toBe(true);
rej(); // <---- test fails here
await Promise.sleep();
expect(store.isFetching).toBe(false);
});
processAction is synchronous and unaware of promises and this results in a dangling promise. Dangling promises should never reject because this results in unhandled rejection, which is a kind of exception. This may cause an application to crash depending on the environment. Even if exceptions are handled globally, this shouldn't be an reason to not handle errors where they are expected.
A correct way to do this is to suppress a rejection explicitly either in fetchTheThing where it occurs:
private async fetchTheThing() {
try {
...
} catch {} finally {
this.isFetching = false;
}
}
Or in this case, it's more like processAction that results in dangling promise:
this.fetchTheThing().catch(() => {});
Otherwise unhandled rejection event is dispatched.
Without that, it could be tested by listening for the event:
...
let onRej = jest.fn();
process.once('unhandledRejection', onRej);
rej();
await Promise.sleep();
expect(onRej).toBeCalled();
expect(store.isFetching).toBe(false);
This won't work as intended if there's already another unhandledRejection listener, which can be expected in a good Jest setup. If this is the case, the only workaround that won't affect other tests is to reset them before the test and re-add afterwards:
let listeners;
beforeEach(() => {
listeners = process.rawListeners('unhandledRejection');
process.removeAllListeners('unhandledRejection');
});
afterEach(() => {
(typeof listeners === 'function' ? [listeners] : listeners).forEach(listener => {
process.on('unhandledRejection', listener);
});
})
This isn't recommended and should be used at own risk because this indicates a deeper problem with error handling that is not generally acceptable in properly designed JavaScript application.
My function calls a private async function in a fire-and-forget manner, and does not add any error handling.
Don't do that.
An external library handles any and all uncaught promise rejections. In production, I want the shell to handle it, so I do not want to handle it in the function itself.
Don't rely on this external library.
You should have your own global error handling function that you use in your function.
In production, have that error handling function simply rethrow the exception so that it gets picked up by the environment, or better, do call the shell error handling function directly if possible.
In the tests, you can mock out your own global handler, and assert that it is called with the expected arguments.
I know that ESLint/TSLint rulest cannot be "right" for 100% of situations. However I need to decide which rules I really don't need.
In ElectonJS, it's not recommended to use Node.js modules in Renderer Process. Instead, Renderer process should send request to Main Process and listen for the response. Below TypeScript class takes care about this routine. (I hope my variable names make code does not need comments, but those are hard to understand, please let me to know in comments)
import { ipcRenderer as IpcRenderer } from "electron";
import InterProcessDataTransferProtocol from "#ProjectInitializer:Root/InterProcessDataTransferProtocol";
import CheckingPathForWriteAccess = InterProcessDataTransferProtocol.CheckingPathForWriteAccess;
import MainProcessEvents = InterProcessDataTransferProtocol.MainProcessEvents;
import Timeout = NodeJS.Timeout;
export default abstract class InterProcessFacilitator {
private static readonly IS_PATH_WRITABLE__RESPONSE_WAITING_PERIOD__MILLISECONDS: number = 10000;
public static async requestCheckingPathForAccessToWrite(targetPath: string): Promise<boolean> {
IpcRenderer.send(
InterProcessDataTransferProtocol.RendererProcessEvents.checkingPathForWriteAccessRequestSent,
{ targetPath }
);
const responseWaitingTimeout: Timeout = setTimeout(
() => { throw new Error("No response from Main Process"); },
InterProcessFacilitator.IS_PATH_WRITABLE__RESPONSE_WAITING_PERIOD__MILLISECONDS
);
return await new Promise<boolean>((resolve: (isWritable: boolean) => void): void => {
IpcRenderer.on(
MainProcessEvents.checkingPathForWriteAccessDone,
(_event: Electron.Event, responsePayload: CheckingPathForWriteAccess.ResponsePayload) =>
{
clearTimeout(responseWaitingTimeout);
if (responsePayload.targetPath === targetPath) {
resolve(responsePayload.isWritable);
}
});
});
}
}
Currently, method requestCheckingPathForAccessToWrite violates no-return-await, the ESLint rules. However it could be used as:
async function checkTheDefaultPathForWrightPermission(): Promise<void> {
try {
const pickedPathIsWritable: boolean = await InterProcessFacilitator
.requestCheckingPathForAccessToWrite(DEFAULT_PATH);
pickedPathIsWritable ?
this.relatedStoreModule.reportAboutUnableToWriteToDirectoryErrorResolution() :
this.relatedStoreModule.reportAboutUnableToWriteToDirectoryErrorOccurrence();
} catch (error) {
console.error(`unable to check wright permission for path ${DEFAULT_PATH}`);
console.error(error);
}
}
From ESLint documentation:
Inside an async function, return await is seldom useful. Since the
return value of an async function is always wrapped in
Promise.resolve, return await doesn’t actually do anything except add
extra time before the overarching Promise resolves or rejects. The
only valid exception is if return await is used in a try/catch
statement to catch errors from another Promise-based function.
Can you criticize either my solution or this ESLint rule, and in first case, suggest the refactoring?
What is the most up to date method to ensure that some asynchronous code completes in a class constructor before that class is subsequently used?
Specifically, how would an API client class retrieve an access token before allowing more method calls, as shown below?
class API_Client {
constructor(...) {
# Below should 'block' other method calls until token is assigned
this.login().then(res => {
this.token = res.data.token;
});
}
async login() {
return makeRequest(...) # <-- Promise which returns access token data
}
}
const client = new API_Client(...);
client.someAuthOnlyMethod() # <-- Should only happen after the `login` method completes.
I found older answers, yet couldn't quite understand how to solve the problem posed in the first comment left on the linked answer.
The most up-to-date method is still not to put any asynchronous stuff in the constructor. In your specific case, that's
class API_Client {
constructor(token) {
this.token = token;
}
static async createLoggedIn(…) {
const res = await makeRequest(...) # <-- Promise which returns access token data
return new this(res.data.token);
}
}
const client = await API_Client.createLoggedIn(…);
client.someAuthOnlyMethod()
You could store the token as a promise:
class API_Client {
constructor(...) {
# Below should 'block' other method calls until token is assigned
this.token = this.login()
.then(res => res.data.token)
}
async someAuthOnlyMethod() {
let token = await this.token;
//...continue
}
async login() {
return makeRequest(...) # <-- Promise which returns access token data
}
}
const client = new API_Client(...);
client.someAuthOnlyMethod() # <-- Should only happen after the `login` method completes.
You shouldn't be calling any asynchronous code from a constructor to begin with. In the case above, your makeRequest function would worry about the login token.
There is also no real value in a class in this case. You should just export a series of functions to make the API calls.