nestjs graphql query/mutation complexity - nestjs

I'm trying to implement query complexity for my nestjs v8 graphql queries, but I can't find a fully working example...
Following the docs (https://docs.nestjs.com/graphql/complexity) I created my ComplexityPlugin
import { GraphQLSchemaHost } from '#nestjs/graphql';
import { Plugin } from '#nestjs/apollo';
import {
ApolloServerPlugin,
BaseContext,
GraphQLRequestContext,
GraphQLRequestListener,
} from 'apollo-server-plugin-base';
import { GraphQLError } from 'graphql';
import {
fieldExtensionsEstimator,
getComplexity,
simpleEstimator,
} from 'graphql-query-complexity';
#Plugin()
export class ComplexityPlugin implements ApolloServerPlugin {
constructor(private gqlSchemaHost: GraphQLSchemaHost) {}
requestDidStart(
requestContext: GraphQLRequestContext<BaseContext>,
): void | GraphQLRequestListener<BaseContext> {
const maxComplexity = 20;
const { schema } = this.gqlSchemaHost;
return {
async didResolveOperation({ request, document }) {
const complexity = getComplexity({
schema,
operationName: request.operationName,
query: document,
variables: request.variables,
estimators: [
fieldExtensionsEstimator(),
simpleEstimator({ defaultComplexity: 1 }),
],
});
if (complexity > maxComplexity) {
throw new GraphQLError(
`Query is too complex: ${complexity}. Maximum allowed complexity: ${maxComplexity}`,
);
}
console.log('Query Complexity:', complexity);
},
};
}
}
then added in my module as a provider
and then in my app.module.ts -> imports ->
GraphQLModule.forRoot({
...
plugins: [new ComplexityPlugin()],
...
}),
but new ComplexityPlugin() expects a GraphQLSchemaHost object as parameter... now what?
If I don't add it as a plugin into GraphQLModule.forRoot, I get this error:
TypeError: Class extends value undefined is not a constructor or null
at Object.<anonymous> (/home/johnykes/code/my-service/node_modules/#nestjs/apollo/dist/services/plugins-explorer.service.js:6:48)
at Module._compile (node:internal/modules/cjs/loader:1105:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
at Module.load (node:internal/modules/cjs/loader:981:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Module.require (node:internal/modules/cjs/loader:1005:19)
at require (node:internal/modules/cjs/helpers:102:18)
at Object.<anonymous> (/home/johnykes/code/my-service/node_modules/#nestjs/apollo/dist/drivers/apollo-federation.driver.js:9:36)
at Module._compile (node:internal/modules/cjs/loader:1105:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
at Module.load (node:internal/modules/cjs/loader:981:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Module.require (node:internal/modules/cjs/loader:1005:19)
at require (node:internal/modules/cjs/helpers:102:18)
at Object.<anonymous> (/home/johnykes/code/my-service/node_modules/#nestjs/apollo/dist/drivers/index.js:4:22)
at Module._compile (node:internal/modules/cjs/loader:1105:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
at Module.load (node:internal/modules/cjs/loader:981:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Module.require (node:internal/modules/cjs/loader:1005:19)
at require (node:internal/modules/cjs/helpers:102:18)
at Object.<anonymous> (/home/johnykes/code/my-service/node_modules/#nestjs/apollo/dist/index.js:5:22)

From the docs you could just add the ComplexityPlugin as a provider in the providers array.

My colleague just found the solution:
npm i package "graphql-query-complexity": "...,
create plugin
import { Plugin } from '#nestjs/graphql';
import {
ApolloServerPlugin,
GraphQLRequestListener,
GraphQLServiceContext,
} from 'apollo-server-plugin-base';
import { GraphQLError, GraphQLSchema } from 'graphql';
import {
fieldExtensionsEstimator,
getComplexity,
simpleEstimator,
} from 'graphql-query-complexity';
#Plugin()
export class ComplexityPlugin implements ApolloServerPlugin {
private schema: GraphQLSchema;
constructor() {}
async serverWillStart(service: GraphQLServiceContext) {
this.schema = service.schema;
}
async requestDidStart(): Promise<GraphQLRequestListener> {
const maxComplexity = 100;
const schema = this.schema;
return {
async didResolveOperation({ request, document }) {
const complexity = getComplexity({
schema,
operationName: request.operationName,
query: document,
variables: request.variables,
estimators: [
fieldExtensionsEstimator(),
simpleEstimator({ defaultComplexity: 1 }),
],
});
if (complexity > maxComplexity) {
throw new GraphQLError(
`Query is too complex: ${complexity}. Maximum allowed complexity: ${maxComplexity}`,
);
}
},
};
}
}
in app.module.ts, add:
import { ComplexityPlugin } from './modules/common/complexity.plugin';
...
GraphQLModule.forRoot({
...
plugins: [new ComplexityPlugin()],
formatError: (error: GraphQLError) => {
const graphQLFormattedError: GraphQLFormattedError = {
...error,
message:
error.extensions?.exception?.response?.message || error.message,
};
console.error(graphQLFormattedError);
return {
...graphQLFormattedError,
extensions: { ...graphQLFormattedError.extensions, exception: null },
};
},
}),
in your graphql input args, add:
import { IsOptional, Max } from 'class-validator';
...
#IsOptional()
#Max(100)
#Field(() => Int, { nullable: true, description: 'Paginate first' })
public first?: number = 10;
...

Related

TypeError: (intermediate value).setName(...).setDescription(...).addStringOption(...).addChoices is not a function discord.js

I am trying to make a command with choices that the user can pick from in my discord bot, but I am getting this error.
.addChoices(
^
TypeError: (intermediate value).setName(...).setDescription(...).addStringOption(...).addChoices is not a function
at Object.<anonymous> (C:\Users\dhart\Desktop\Projects\ExistentialThreat\commands\coinflip.js:10:4)
at Module._compile (node:internal/modules/cjs/loader:1105:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
at Module.load (node:internal/modules/cjs/loader:981:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Module.require (node:internal/modules/cjs/loader:1005:19)
at require (node:internal/modules/cjs/helpers:102:18)
at c:\Users\dhart\Desktop\Projects\ExistentialThreat\handler\index.js:13:18
at Array.map (<anonymous>)
at module.exports (c:\Users\dhart\Desktop\Projects\ExistentialThreat\handler\index.js:12:17)
My code is:
const { EmbedBuilder } = require("discord.js");
const { SlashCommandBuilder } = require('#discordjs/builders');
module.exports = {
data: new SlashCommandBuilder()
.setName('coinflip')
.setDescription('Returns value heads or tails.')
.addStringOption((option) => option.setName('guess')
.setDescription('Enter heads or tails.').setRequired(true))
.addChoices(
{ name: 'Heads', value: 'Guess_heads'},
{ name: 'Tails', value: 'Guess_tails'},
),
async execute(interaction) {
let coinflip = (Math.random() * 100).toFixed(0) % 2;
I am new to discord.js and I would appreciate some help.
The fact you put a ) after .setRequired(true) makes it that you are trying to use .addChoices on the slash command builder itself instead of the string option. A simply typo, just remove the trailing ) and put it at the end of the SlashCommandBuilder like so :
const { EmbedBuilder } = require("discord.js");
const { SlashCommandBuilder } = require('#discordjs/builders');
module.exports = {
data: new SlashCommandBuilder()
.setName('coinflip')
.setDescription('Returns value heads or tails.')
.addStringOption((option) => option.setName('guess')
.setDescription('Enter heads or tails.')
.setRequired(true)
.addChoices(
{ name: 'Heads', value: 'Guess_heads'},
{ name: 'Tails', value: 'Guess_tails'},
)),

extracting methods in their own files in ExpressJS: Cannot use import statement outside a module

I made my first app today, with ExpressJS.
Problem is index.js is too big (600 lines), I would like to organize my code into differents files.
The easiest part are static dates functions. I have 5 functions, and I'd like to put them into a separate file:
dates.js
import moment from "moment";
module.exports = {
getNextMonday: (firstDate) => {
let firstMonday = firstDate.add(1, "day").startOf('isoWeek');
if (!firstDate.isSame(firstMonday)) {
firstMonday = firstMonday.add(7, "day");
}
return firstMonday;
},
// Get the days in a array
getDays: (conso) => {
let days = conso.map(value => moment(value['date'], "DD-MM-YYYY HH:mm").format("DD"));
return days.filter(function (elem, pos) {
return days.indexOf(elem) === pos;
});
},
// Get the days in a array
getDaysWithHours: (conso) => {
let days = conso.map(value => value['date']);
// console.log(days);
return days.filter(function (elem, pos) {
return days.indexOf(elem) === pos;
});
},
getHourlyData: (data, monday) => {
return data.filter(item => {
const date = moment(item.date, "DD-MM-YYYY HH:mm");
// if moment(item.date, "DD-MM-YYYY HH:mm") + 7
if (isSameWeek(monday, date)) return item;
});
},
isSameWeek: (firstDay, secondDay) => {
let firstMoment = moment(firstDay);
let secondMoment = moment(secondDay);
return firstMoment.startOf('isoWeek').isSame(secondMoment.startOf('isoWeek'));
}
};
And then in index.js, I try to use them:
let date = require('./dates.js');
...
const monday = date.getNextMonday(firstDay);
But I get an error:
import moment from "moment";
^^^^^^
SyntaxError: Cannot use import statement outside a module
at Module._compile (internal/modules/cjs/loader.js:891:18)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:991:10)
at Module.load (internal/modules/cjs/loader.js:811:32)
at Function.Module._load (internal/modules/cjs/loader.js:723:14)
at Module.require (internal/modules/cjs/loader.js:848:19)
at require (internal/modules/cjs/helpers.js:74:18)
at Object.<anonymous> (/home/julien/Code/customer_recap/index.js:13:12)
at Module._compile (internal/modules/cjs/loader.js:955:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:991:10)
at Module.load (internal/modules/cjs/loader.js:811:32)
[nodemon] app crashed - waiting for file changes before starting...
It seems I can't import moment lib into my new local module.
Why ? How should I do it ?

Nest.js - Imported service not recognized by another service

I am attempting to reuse a service (Inventory) in another service (Order) class like so
order.module.ts
import { InventoryModule } from '../inventory/inventory.module';
#Module({
imports: [TypeOrmModule.forFeature([OrderEntity]), InventoryModule],
controllers: [OrderController],
providers: [OrderService],
})
export class OrderModule {}
and then use InventoryService methods inside OrderService like so
#Injectable()
export class OrderService {
constructor(
#InjectRepository(OrderEntity) private orderRepository: Repository<OrderEntity>,
private inventoryService: InventoryService) {}
/**
* Add order item
* #param data Object
*/
async add(data: OrderDTO) {
const { inventory_item_id } = data
const inventoryItem = await this.inventoryService.getOne(inventory_item_id)
if (inventoryItem.quantity_available <= 0) {
throw new Error('Cannot add item to order, insufficient quantities!')
}
const orderItem = await this.orderRepository.create(data)
if (orderItem) {
const updatedInventoryItemQuantity = inventoryItem.quantity_available - 1
const updatedInventoryItem = await this.inventoryService.edit(inventory_item_id, {
quantity_available: updatedInventoryItemQuantity,
})
}
await this.orderRepository.save(orderItem)
return orderItem
}
but I get the following stack trace:
Require stack:
- /Users/jred/workspace/projects/my-proj/dist/order/order.service.js
- /Users/jred/workspace/projects/my-proj/dist/order/order.controller.js
- /Users/jred/workspace/projects/my-proj/dist/order/order.module.js
- /Users/jred/workspace/projects/my-proj/dist/app.module.js
- /Users/jred/workspace/projects/my-proj/dist/main.js
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:623:15)
at Function.Module._load (internal/modules/cjs/loader.js:527:27)
at Module.require (internal/modules/cjs/loader.js:681:19)
at require (internal/modules/cjs/helpers.js:16:16)
at Object.<anonymous> (/Users/jred/workspace/projects/my-proj/dist/order/order.service.js:19:29)
at Module._compile (internal/modules/cjs/loader.js:774:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:785:10)
at Module.load (internal/modules/cjs/loader.js:641:32)
at Function.Module._load (internal/modules/cjs/loader.js:556:12)
at Module.require (internal/modules/cjs/loader.js:681:19) {
code: 'MODULE_NOT_FOUND',
requireStack: [
'/Users/jred/workspace/projects/my-proj/dist/order/order.service.js',
'/Users/jred/workspace/projects/my-proj/dist/order/order.controller.js',
'/Users/jred/workspace/projects/my-proj/dist/order/order.module.js',
'/Users/jred/workspace/projects/my-proj/dist/app.module.js',
'/Users/jred/workspace/projects/my-proj/dist/main.js'
]
}
anyone experience this? what is the correct way to call an imported service in another module?
Check your app.module.ts.
Make sure you added InventoryModule in the imports array.
And also, make sure you are exporting InventoryService from InventoryModule.
// app.module.ts
#Module({
imports: [InventoryModule, ...othermodules],
exports: [],
providers: []
})
export class ApplicationModule {}
// inventory.module.ts
#Module({
imports: [...yourModules],
exports: [InventoryService],
providers: [InventoryService]
})
export class InventoryModule {}
the problem was within my Order.service.ts file with the auto import syntax
this import that included src
import { InventoryService } from 'src/inventory/inventory.service';
had to be changed to this
import { InventoryService } from '../inventory/inventory.service';

problems with exporting function with babel and nodejs

I am using babeljs with webstorm.
The arguments to babel are:
--source-maps --out-file $FileNameWithoutExtension$-compiled.js $FilePath$
I have the following es6 code:
export function primeFactors(num) {
let res = [];
let n = 2;
while (num > 1) {
while(num%n ===0) {
res.push(n);
}
n++;
}
return res;
}
it gets transpiled to
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.primeFactors = primeFactors;
function primeFactors(num) {
var res = [];
var n = 2;
while (num > 1) {
while (num % n === 0) {
res.push(n);
}
n++;
}
return res;
}
//# sourceMappingURL=numUtils-compiled.js.map
I have a script which requires the file
import {primeFactors} from "lib/numUtils";
It gets transpiled to
"use strict";
var _libNumUtils = require("lib/numUtils");
//# sourceMappingURL=ex3-compiled.js.map
When i run the script with nodejs i get
export function primeFactors(num) {
^^^^^^
SyntaxError: Unexpected reserved word
at exports.runInThisContext (vm.js:73:16)
at Module._compile (module.js:443:25)
at Object.Module._extensions..js (module.js:478:10)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
at Module.require (module.js:365:17)
at require (module.js:384:17)
at Object. (J:\webstorm_workspace\euler\ex3-compiled.js:3:20)
at Module._compile (module.js:460:26)
at Object.Module._extensions..js (module.js:478:10)
What could be the reason?

Protractor addLocator : how to get the object for the document

Im trying to create a custom locator in protractor using addLocator
My conf.js is
// An example configuration file.
exports.config = {
directConnect: true,
// Capabilities to be passed to the webdriver instance.
capabilities: {
'browserName': 'chrome'
},
//multiCapabilities: [{
// browserName: 'firefox'
// }, {
// browserName: 'chrome'
//}],
// Spec patterns are relative to the current working directly when
// protractor is called.
specs: ['DriverSpec.js'],
onPrepare: function () {
require('tech')(protractor);
}
//function (protractor) {
protractor.by.addLocator('test', function (toState, opt_parentElement) {
var using = opt_parentElement || document;
var possibleAnchors = using.querySelectorAll( toState );
var result = undefined;
if (possibleAnchors.length === 0) {
result = null;
} else if (possibleAnchors.length === 1) {
result = possibleAnchors[0];
} else {
result = possibleAnchors;
}
return result;
});
//};// The protractor object is available here.
// Options to be passed to Jasmine-node.
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 1000000
}
};
Error shown :
C:\Users\jeevan.s\AppData\Roaming\npm\node_modules\protractor\conf\addLocator\Ne
w folder\conf.js:18
By.addLocator('customLink',
^
SyntaxError: Unexpected token .
at Module._compile (module.js:439:25)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at ConfigParser.addFileConfig (C:\Users\jeevan.s\AppData\Roaming\npm\node_mo
dules\protractor\lib\configParser.js:183:20)
at Object.init (C:\Users\jeevan.s\AppData\Roaming\npm\node_modules\protracto
r\lib\launcher.js:35:18)
at Object.<anonymous> (C:\Users\jeevan.s\AppData\Roaming\npm\node_modules\pr
otractor\lib\cli.js:129:23)
at Module._compile (module.js:456:26)
Issues :
1) How to create a Protractor object
2) Trying to build object opt_parentElement by using this code lines
var using = browser.driver.findElement(By.css(".nav"));
buttons = using.querySelectorAll('active')
Its throwing the error as the "querySelectorAll" not found in the "using OBJECT"
Not able to access querySelectorAll method.
3). Could anyone can please help us addLocator with executable example. It would be great!!

Resources