How set graphql-js module in debug mode - javascript

i'm new in graphql and setting up server graphql api use [https://github.com/graphql/graphql-js] graphql-js.
I followed their document and everything work, expect 1 problem:
when make query and got error from deep module, graphql-js try catch error and return result with errors: [...] property, but in terminal console say nothing. I would like force grahql-js return actual Error object so i can debug issue when looking to stack.
this is code in api
query: (ctx) -> (
await graphql(
schema
query
context
graphContext
variables
)
)
I search a lot of topic but no ones say about set this package in debug mode, also no see any parameter allow set debug. Anyone know about this?
Thanks !

Normally, you would use a library like express-graphql or apollo-server (or apollo-server-express, apollo-server-hapi, etc.) to provide an endpoint for your GraphQL API. Unless your use case prohibits you from doing so, I would strongly encourage you to utilize one of these libraries since they provide a number of additional features that are helpful in both development and production.
You can add logging to your endpoint when using one of these libraries simply by providing a custom formatError function in your configuration. See each library's documentation here and here. As a bonus, if you use Apollo, then the full stack trace will be exposed inside of your errors array anyway, but only in development.
If you're calling the graphql function directly in your code somewhere, then you can just log the errors yourself. The call to graphql returns a Promise that resolves to a ExecutionResult object, which includes both your data and errors. So you can do something like:
const result = await graphql(/* your args */)
if (result.errors) {
result.errors.forEach((error) => {
// log the error
})
}

You have to instantiate the graph object with the debug option enabled, like this
var graph = graphql("/api", { debug: true })

Related

NestJs ParseEnumPipe can't be resolve

I am using the NestJs framework (love it by the way) and I want to check the incoming data so it conforms with an Enum in Typscript. So I have the following:
enum ProductAction {
PURCHASE = 'PURCHASE',
}
#Patch('products/:uuid')
async patchProducts(
#Param('uuid', ParseUUIDPipe) uuid: string,
#Body('action', ParseEnumPipe) action: ProductAction,
) {
switch(action) {
... code
}
The weird thing is that when I run this code, the first pipe gets compiled
2022-07-21 16:53:51 [error] [ExceptionHandler] Nest can't resolve dependencies of the ParseEnumPipe (?, Object). Please make sure that the argument Object at index [0] is available in the FriendsModule context.
What I am doing wrong?
You should use #Body('action', new ParseEnumPipe(ProductAction)) action: ProductAction because enums aren't directly reflected for Nest to read the metadata of, and because Nest is otherwise trying to figure out how to inject Object when it really should be injecting the enum.

how to scan all decorators value at runtime in nestjs

I have to collect all decorator value that appears in different place in my app as string and then saving them to database at runtime, i don't have to add them twice (in database and in code),
i have tried to do it but i could not figure out i use
Reflector api from nestjs as following
this.reflector.getAll<string>('access', context.getHandler())
but i could not get context.getHandler() during run time
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe());
// Here is where i want to save
await app.listen(3000);
}
bootstrap();
here is my decorator
#HashPermission('access_value')
Please assist
For something like this, you'll either need to make use of something like Nest's undocumented DiscoveryService or a package like #golevelup/nestjs-discovery which is a friendly wrapper around Nest's package. You can then make use of methods like this.discoveryService.methodsAndControllerMethodsWithMetaAtKey to get the classes and methods that have that metadata, then you can use the reflector class on each method to get the metadata value.

Is there any way to access `__filename` in Next.js?

I'm working on a custom i18n module and would love to replace this code (this is a an "about-us" page):
const messages = (await import(`./about-us.${locale}.json`))
.default as Messages;
By
const messages = (
await import(`./${__filename.replace('.tsx', `.${locale}.json`)}`)
).default as Messages;
Unfortunately __filename resolves to /index.js (I guess because of Webpack?) - is there any way to achieve what am I trying to do in my example or this would need to be built-in Next.js directly to work?
Refactor this so consumers don't know about the filesystem
Spoiler: I'm not going to tell you how to access __filename with Next.js; I don't know anything about that.
Here's a pattern that is better than what you propose, and which evades the problem entirely.
First, setup: it sounds like you've got a folder filled with these JSON files. I imagine this:
l10n/
about-us.en-US.json
about-us.fr-FR.json
contact-us.en-US.json
contact-us.fr-FR.json
... <package>.<locale>.json
That file organization is nice, but it's a mistake to make every would-be l10n consumer know about it.
What if you change the naming scheme later? Are you going to hand-edit every file that imports localized text? Why would you treat Future-You so poorly?
If a particular locale file doesn't exist, would you prefer the app crash, or just fall back to some other language?1
It's better to create a function that takes packageName and localeCode as arguments, and returns the desired content. That function then becomes the only part of the app that has to know about filenames, fallback logic, etc.
// l10n/index.js
export default function getLang( packageName, localeCode ) {
let contentPath = `${packageName}.${localeCode}.json`
// TODO: fallback logic
return JSON.parse(FS.readFileSync(contentPath, 'utf8'))
}
It is a complex job to locate and read the desired data while also ensuring that no request ever gets an empty payload and that each text key resolves to a value. Dynamic import + sane filesystem is a good start (:applause:), but that combination is not nearly robust-enough on its own.
At a previous job, we built an entire microservice just to do this one thing. (We also built a separate service for obtaining translations, and a few private npm packages to allow webapps to request and use language packs from our CMS.) You don't have to take it that far, but it hopefully illustrates that the problem space is not tiny.
1 Fallback logic: e.g. en-UK & en-US are usually interchangeable; some clusters of Romance languages might be acceptable in an emergency (Spanish/Portuguese/Brazilian come to mind); also Germanic languages, etc. What works and doesn't depends on the content and context, but no version of fallback will fit into a dynamic import.
You can access __filename in getStaticProps and getServerSideProps if that helps?
I pass __filename to a function that needs it (which has a local API fetch in it), before returning the results to the render.
export async function getStaticProps(context) {
return {
props: {
html: await getData({ page: __filename })
}, // will be passed to the page component as props
};
}
After a long search, the solution was to write a useMessages hook that would be "injected" with the correct strings using a custom Babel plugin.
A Webpack loader didn't seem like the right option as the loader only has access to the content of the file it loads. By using Babel, we have a lot more options to inject code into the final compiled version.

What is the way to create unit-test for sailsJS (or another framework)

Well I embraced test-driven-development in the past year while learning C# (those seem to go hand in hand). In javascript however I am struggling to find a good workflow for tdd. This is mainly due to the combination of many frameworks which seemingly consider testing a second class citizen.
As an example consider a class worker. This class would have some functionality to act upon a database. So how would I write unit tests for the functionality of this class?
In c# (and rest of C/JAVA family) I'd write this class in such a way that the constructor would take a database-connection parameter. Then during test runs the object is called with a mock-database-connection object instead of the real object. Thus no modification of the source.
In python a similar approach can be used, however apart from providing a mocking object to the constructor to handle HAS_A dependencies, we can also use dependency injection to mock IS_A dependencies.
Now apply this in javascript, and sailsJS in particular (Though a similar problem occurs with sencha and other frameworks). It seems that the code is so tightly coupled to the library/framework that I can't create manual stubs/mocks? - Other than by actually using a pre-run task to modify the source/config.js?
In sails an object (say worker, a controller) has to reside in a specific folder to work, and it "connects" automatically to the database, without me providing any notion of a database object. (Thus preventing me from actually supplying it with my own object).
Say I have a database with a table "Students", then a controller would look something like (With Students being a model defined in api/models:
const request = require('request');
module.exports = {
updateData: function (req, res) {
let idx = params.jobNumber;
Students.find({Nr:idx})
.exec(function (err, result) {
//....
});
},
};
So how would I load above function into a (mocha) test? And how would I decouple the database (used implicitly by sails) so that I can mock the functionality? - And what should I actually mock?
I of course don't wish to do integration tests, so I shouldn't build a "development database" as I don't wish to test the connection, I wish to test the controller functions.
In the documentation, they provide a nice quick example of how to set up testing using Mocha: https://sailsjs.com/documentation/concepts/testing
In the bootstrap.test.js file, all they're doing is lifting and lowering your application with Sails, just so your application has access to controllers/models/etc. within its test environment. They also show how to test individual controllers, which is essentially just making requests that hit the endpoints to fire off the controller's actions. To avoid testing the full lifecycle of a request, you can just require the controller file within a *.test.js file and test any exported action. Remember, though, Sails builds the request and response objects that get passed to the controllers. So, if you want all of the correct data and have those objects be valid, it's best to just let Sails handle it, and you only make a request to the endpoint, unless if you know exactly how to build the request and response objects. But, that's the point of a framework: you use it as intended, and test against/with it. You don't use your version of how it may work. TDD is in all languages and frameworks, you just need to fit it within your technology.
If you don't want to use a database for your test environment, you can tell it to use the sails-disk adapter by creating an environment file under config/env/ for the test environment and forcing that environment to use sails-disk.
For example...
config/env/test.js --> test environment file
module.exports = {
models: {
connection: 'localDiskDb',
migrate: 'drop',
},
port: 1337,
host: '127.0.0.1',
};
In config/connections.js the below to connections object (if not already there)...
localDiskDb: {
adapter: 'sails-disk'
},
And finally, we need to tell it to use that environment when running the tests. Modify test/bootstrap.test.js like the following...
var sails = require('sails');
before(function(done) {
// Increase the Mocha timeout so that Sails has enough time to lift.
this.timeout(10000);
// Set environment to testing
process.env.NODE_ENV = 'test';
sails.lift({
// configuration for testing purposes
}, function(err) {
if (err) {
return done(err);
}
//...
done(err, sails);
});
});
after(function(done) {
// here you can clear fixtures, etc.
// This will "refresh" the memory store so you
// have a clean test datastore every time you run tests
sails.once('hook:orm:reloaded', () => {
sails.lower((err) => {
done();
if (err) {
process.exit(1);
} else {
process.exit(0);
}
});
});
sails.emit('hook:orm:reload');
});
Adding Jason's suggestion in an "answer" format, so that others may find it more easily.
sails-mock-models allows simple mocking for sails model queries, based on sinon
Mock any of the standard query methods (ie 'find', 'count', 'update') They will be called with no side effects.
I haven't actually tried it yet (just found this question), but I'll edit this if/when I have any problems.
Sails Unit Test is perfectly explained in the following blog.
https://www.packtpub.com/books/content/how-add-unit-tests-sails-framework-application
Please refer to it.

Test Meteor server method calling in client code with authenticated users

In a Meteor app, I need to test some client code that has statements such as
Meteor.call('foo', param1, param2, (error, result) => { .... });
And, in these methods, I have security checks to make sure that the method can only be called by authenticated users. However, all these tests fail during tests because no user is authenticated.
In each server methods, I check users like this
if (!Roles.userIsInRole(this.userId, [ ...roles ], group)) {
throw new Meteor.Error('restricted', 'Access denied');
}
I have read that we should directly export the server methods and test them directly, and I actually do this for server methods testing, but it is not possible, here, since I need to test client code that depend on Meteor.call.
I also would certainly not want to have if (Meteor.isTest || Meteor.isAppTest) { ... } all over the place....
I thought perhaps wrapping my exported methods like this :
export default function methodsWrapper(methods) {
Object.keys(methods).forEach(method => {
const fn = methods[method];
methods[method] = (...args) => {
const user = Factory.create('user', { roles: { 'default': [ 'admin' ] } });
return fn.call({ userId: user._id }, ...args);
};
});
};
But it only works when calling the methods directly.
I'm not sure how I can test my client code with correct security validations. How can I test my client code with authenticated users?
Part I: Making the function an exported function
You just need to add the exported method also to meteor methods.
imports/api/foo.js
export const foo = function(param1, param2){
if (!Roles.userIsInRole(this.userId, [ ...roles ], group)) {
throw new Meteor.Error('restricted', 'Access denied');
}
//....and other code
};
This method can then be imported in your server script:
imports/startup/methods.js
import {foo} from '../api/foo.js'
Meteor.methods({
'foo' : foo
});
So it is available to be called via Mateor.call('foo'...). Note that the callback has not to be defined in foo's function header, since it is wrapped automatically by meteor.
imports/api/foo.tests.js
import {foo} from './foo.js'
if (Meteor.isServer) {
// ... your test setup
const result = foo(...) // call foo directly in your test.
}
This is only on the server, now here is the thing for testing on the client: you will not come around calling it via Meteor.call and test the callback result. So on your client you still would test like:
imports/api/foo.tests.js
if (Meteor.isClient) {
// ... your test setup
Meteor.call('foo', ..., function(err, res) {
// assert no err and res...
});
}
Additional info:
I would advice you to use mdg:validated-method which allows the same functionality above PLUS gives you more sophisticated control over method execution, document schema validation and flexibility. It is also documented well enough to allow you to implement your above described requirement.
See: https://github.com/meteor/validated-method
Part II: Running you integration test with user auth
You have two options here to test your user authentication. They have both advantages and disadvantages and there debates about what is the better approach. No mater which one of both you will test, you need to write a server method, that adds an existing user to given set of roles.
Approach 1 - Mocking Meteor.user() and Meter.userid()
This is basically described/discussed in the following resources:
A complete gist example
An example of using either mdg:validated-method or plain methods
Using sinon spy and below also an answer from myself by mocking it manually but this may not apply for your case because it is client-only. Using sinon requires the following package: https://github.com/practicalmeteor/meteor-sinon
Approach 2 - Copying the "real" application behavior
In this case you completely test without mocking anything. You create real users and use their data in other tests as well.
In any case you need a server method, that creates a new user by given name and roles. Note that it should only be in a file with .test.js as name. Otherwise it can be considered a risk for security.
/imports/api/accounts/accounts.tests.js
Meteor.methods({
createtestUser(name,password, roles, group);
const userId = Accounts.createUser({username:name, password:password});
Roles.addUserToRoles(userId, roles, group);
return userId;
});
Note: I often heard that this is bad testing, which I disagree. Especially integration testing should mime the real behavior as good as possible und should use less mocking/spying as unit tests do.

Categories