nest-schedule npm not working - node.js

I am using nest.js framework for developing a node based application. I am trying to write a scheduler using nest-schedule as mentioned at https://www.npmjs.com/package/nest-schedule.
Somehow the code is not working when used with #Cron or #Schedule. Rest other decorators work's fine. Using the same code base as mentioned in above link. Can anyone help me with setting this up and with exact cron pattern used in nodejs

For current version of Nest may you could use nestjs/schedule. See how I achieve this with nestjs/schedule.
1st: install nestjs cli
npm i -g #nestjs/cli
2nd: Create a new project
nest new schedule-sample
3rd: Install the nestjs schedule
npm install --save #nestjs/schedule
4th: Generate a new service to put your service.
nest generate service cron
Once you have installed the package add it to the app.module as follow below:
import { Module } from '#nestjs/common';
import { ScheduleModule } from '#nestjs/schedule';
import { Logger } from '#nestjs/common';
#Module({
imports: [
ScheduleModule.forRoot()
],
})
export class AppModule {}
5th: you can run it as show bellow (the complete instructions are here https://docs.nestjs.com/techniques/task-scheduling):
#Cron('*/5 * * * * *')
runEvery10Seconds() {
console.log('Run it every 5 seconds');
}
Here is the complete sample (cron.service.ts).
import { Logger } from '#nestjs/common';
import { Injectable } from '#nestjs/common';
import { Cron, Interval } from '#nestjs/schedule';
#Injectable()
export class CronService {
private readonly logger = new Logger(CronService.name);
#Cron('*/5 * * * * *')
runEvery10Seconds() {
this.logger.debug('Run it every 5 seconds');
}
#Cron('10 * * * * *')
handleCron() {
this.logger.debug('Called when the current second is 10');
}
#Interval(10000)
handleInterval() {
this.logger.debug('Called every 10 seconds');
}
}
Final thoughts:
The most sophisticated way to schedule jobs is use dynamic cron jobs. For that you can obtain a reference to a CronJob instance by name from anywhere in your code using the SchedulerRegistry API. First, inject SchedulerRegistry using standard constructor injection:
constructor(private schedulerRegistry: SchedulerRegistry) {}
HINT
Import the SchedulerRegistry from the #nestjs/schedule package.
Then use it in a class as follows. Assume a cron job was created with the following declaration:
#Cron('* * 8 * * *', {
name: 'notifications',
})
triggerNotifications() {}
Access this job using the following:
const job = this.schedulerRegistry.getCronJob('notifications');
job.stop();
console.log(job.lastDate());
I have tested it at the follow versions (package.json)
"#nestjs/common": "^7.6.15",
"#nestjs/core": "^7.6.15",
"#nestjs/schedule": "^0.4.3",

Had the same issue, cron jobs did not start, solved it this way:
async function bootstrap() {
const app = await NestFactory.createApplicationContext(AppModule);
// add this, if network if network listener is needed :
await app.listen(<port>)
// or this if network is not needed :
await app.init()
}
bootstrap();

Have you added your job's service to a module?
Maybe your job is not imported into any module.
https://github.com/nestjs/nest/tree/master/sample/27-scheduling/src/tasks

#Cron() and #Schedule() decorators did not really work until v0.3.1 (github issue).
Could you try the latest version?
package.json
{
...
"dependencies": {
"nest-schedule": "^0.3.1"
...
}
...
}
scheduler.service.ts
import { Injectable } from '#nestjs/common';
import { Cron, NestSchedule } from 'nest-schedule';
#Injectable()
export class SchedulerService extends NestSchedule {
// ...
#Cron('* * * * * *') // Run every second
scheduledJob() {
console.info('[Scheduler]: scheduled jobs has been started');
// ...
}
// ...
}
Works for me.

I had the same issue... Doing some research I found I need to use the latest version of #nestjs/common and #nestjs/core and if used also #nestjs/platform-express

Note that the decorator is used in the declarative definition.
NOT WORKING:
#Cron(CronExpression.EVERY_10_SECONDS)
async task() {
console.log('[Scheduler]: every 10 seconds');
}
WORKING:
#Cron(CronExpression.EVERY_10_SECONDS)
task() {
console.log('[Scheduler]: every 10 seconds');
}

Related

Why I can not use " import { createSlice, configureStore } from '#reduxjs/toolkit' " in Node.js

guys
I am learning redux, and try to run a very simple example code in node.js environment. I got the following error when I try to use :
import { createSlice, configureStore } from '#reduxjs/toolkit' .
The errors is:
import { createSlice, configureStore } from '#reduxjs/toolkit'
^^^^^^^^^^^
SyntaxError: Named export 'createSlice' not found. The requested module '#reduxjs/toolkit' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:
import pkg from '#reduxjs/toolkit';
const { createSlice, configureStore } = pkg;
at ModuleJob._instantiate (internal/modules/esm/module_job.js:120:21)
at async ModuleJob.run (internal/modules/esm/module_job.js:165:5)
at async Loader.import (internal/modules/esm/loader.js:177:24)
at async Object.loadESM (internal/process/esm_loader.js:68:5)
If I use import like what the error tip says:
import pkg from '#reduxjs/toolkit';
const { createSlice, configureStore } = pkg;
All is OK.
What I want to ask is:
It gives me a wrong example in the official website of Redux? Or Just I run the example with a wrong way?
The following is the detail information.
My Node.js version is: v14.17.3
1 Init a node project:
mkdir redux_01
cd redux_01
yarn init
yarn add #reduxjs/toolkit
2 Modify the 'package.json', add a line in it:
"type":"module"
3 Create a file 'index.js' with the "Redux Toolkit Example" code parsed from https://redux.js.org/introduction/getting-started.
import { createSlice, configureStore } from '#reduxjs/toolkit'
const counterSlice = createSlice({
name: 'counter',
initialState: {
value: 0
},
reducers: {
incremented: state => {
// Redux Toolkit allows us to write "mutating" logic in reducers. It
// doesn't actually mutate the state because it uses the Immer library,
// which detects changes to a "draft state" and produces a brand new
// immutable state based off those changes
state.value += 1
},
decremented: state => {
state.value -= 1
}
}
})
export const { incremented, decremented } = counterSlice.actions
const store = configureStore({
reducer: counterSlice.reducer
})
// Can still subscribe to the store
store.subscribe(() => console.log(store.getState()))
// Still pass action objects to `dispatch`, but they're created for us
store.dispatch(incremented())
// {value: 1}
store.dispatch(incremented())
// {value: 2}
store.dispatch(decremented())
// {value: 1}
4 Now I run it like this:
node index.js
I then got that error message that I just mentioned.
The reason for the error is explained here:
https://lightrun.com/answers/reduxjs-redux-toolkit-cannot-import-redux-toolkit-from-a-nodejs-esm-module "here"
solution:
import * as toolkitRaw from '#reduxjs/toolkit';
const { createSlice,configureStore } = toolkitRaw.default ?? toolkitRaw;
or in Typescript:
import * as toolkitRaw from '#reduxjs/toolkit';

Connection "default" was not found - TypeORM, NestJS and external NPM Package

I'm using NestJs to create a couple of applications and I want to move the code from a NestInterceptor for an external NPM Package so I can use the same interceptor in multiple applications.
The problem is that the same code that works when used "locally" just stop working when moved to the external package.
Here's the code for the interceptor:
import { Injectable, NestInterceptor, CallHandler, ExecutionContext } from '#nestjs/common'
import { map } from 'rxjs/operators'
import { getManager } from 'typeorm'
import jwt_decode from 'jwt-decode'
#Injectable()
export class MyInterceptor implements NestInterceptor {
entity: any
constructor(entity: any) {
this.entity = entity
}
async intercept(context: ExecutionContext, next: CallHandler): Promise<any> {
const request = context.switchToHttp().getRequest()
const repository = getManager().getRepository(this.entity)
return next.handle().pipe(map((data) => data))
}
}
Here's a given controller:
import { myInterceptor } from "../src/interceptors/interceptor.ts";
#UseInterceptors(new CompanyIdInterceptor(User))
export class UserController {
}
This works fine, but if a move the file to an external NPM package and import from it like this:
import { myInterceptor } from "mynpmpackage";
I get the following error:
[Nest] 24065 - 04/18/2019, 10:04 AM [ExceptionsHandler] Connection "default" was not found. +26114ms
ConnectionNotFoundError: Connection "default" was not found.
at new ConnectionNotFoundError (/home/andre/Services/npm-sdk/src/error/ConnectionNotFoundError.ts:8:9)
at ConnectionManager.get (/home/andre/Services/npm-sdk/src/connection/ConnectionManager.ts:40:19)
Any ideas, on what causes this and how to solve it?
This might not be your problem exactly, but I had a similar problem when moving things to external packages with TypeORM. Make sure all packages from parent project are using the same version of the TypeORM package.
In my case, using yarn why typeorm showed me two different versions were being installed. One of them was used to register the entities, while the framework connected to the SQL database using another version, generating this clash.
Check your versions using yarn why [pkg-name] or if you're using NPM, try npx npm-why [pkg-name] or install globally from https://www.npmjs.com/package/npm-why.
After verifying TypeOrm versions is same in both the packages i.e- external package and consumer repository as mentioned by #Luís Brito still issue persist then issue could be-
Basically when we create an external package - TypeORM tries to get the "default" connection option, but If not found then throws an error:
ConnectionNotFoundError: Connection "default" was not found.
We can solve this issue by doing some kind of sanity check before establishing a connection - luckily we have .has() method on getConnectionManager().
import { Connection, getConnectionManager, getConnectionOptions,
createConnection, getConnection, QueryRunner } from 'typeorm';
async init() {
let connection: Connection;
let queryRunner: QueryRunner;
if (!getConnectionManager().has('default')) {
const connectionOptions = await getConnectionOptions();
connection = await createConnection(connectionOptions);
} else {
connection = getConnection();
}
queryRunner = connection.createQueryRunner();
}
Above is a quick code-snippet which was the actual root cause for this issue but If you are interested to see complete working repositories (different example) -
External NPM Package :
Git Repo : git-unit-of-work (specific file- src/providers/typeorm/typeorm-uow.ts)
Published in NPM : npm-unit-of-work
Consumer of above package : nest-typeorm-postgre (specific files- package.json, src/countries/countries.service.ts & countries.module.ts)

cant import createBatchingNetworkInterface from apollo-client

I am trying to integrate graphql with my vue project.
I am following these instructions: https://github.com/Akryum/vue-apollo
I have npm installed 'apollo-client' as required, but for some reason i can't import 'createBatchingNetworkInterface'.
this is my main.js file:
import Vue from 'vue'
import { ApolloClient, createBatchingNetworkInterface } from 'apollo-client'
import VueApollo from 'vue-apollo'
import App from './App'
import router from './router'
and this is the index.d.ts file of my apollo-client:
export { print as printAST } from 'graphql/language/printer';
export { ObservableQuery, FetchMoreOptions, UpdateQueryOptions, ApolloCurrentResult } from './core/ObservableQuery';
export { WatchQueryOptions, MutationOptions, SubscriptionOptions, FetchPolicy, FetchMoreQueryOptions, SubscribeToMoreOptions, MutationUpdaterFn } from './core/watchQueryOptions';
export { NetworkStatus } from './core/networkStatus';
export * from './core/types';
export { ApolloError } from './errors/ApolloError';
import ApolloClient, { ApolloClientOptions } from './ApolloClient';
export { ApolloClientOptions };
export { ApolloClient };
export default ApolloClient;
I don't see here the 'createBatchingNetworkInterface' desired object.
I don't know what am i doing wrong here.
It sounds like you're using Apollo Client 2.0.You should downgrade to an older version (1.9.3) to continue using network interfaces, including the batching one.
The newest version of the client uses Links instead. You can check out the upgrade guide here if you are interested. you can still batch requests in 2.0 using apollo-link-batch-http.

Angular 2 - Import html2canvas

I have installed html2canvas on my angular 2 project using npm install html2canvas --save. If I now go to any file and write import * as html2canvas from 'html2canvas' it gives the error:
Cannot find module 'html2canvas'
My package file looks like this:
{
...
"scripts": {
...
},
"dependencies": {
...
"html2canvas": "^0.5.0-beta4",
...
},
"devDependencies": {
...
}
}
The file on which I'm trying to import the html2canvas is:
import { Injectable } from '#angular/core';
import * as jsPDF from 'jspdf';
import * as html2canvas from 'html2canvas';
#Injectable ()
export class pdfGeneratorService {
...
}
Since Angular2 uses typescript, you need to install the typescript definition files for that module.
It can be installed from #types (if it exists). If it doesn't you can create your own definition file and include it in your project.
in angular 9 i use it this way:
import html2canvas from 'html2canvas';
....
html2canvas(this.head2print.nativeElement).then(_canvas => {
hdr = _canvas.toDataURL("image/png");
});
Also, the onrendered option for callback function may not work. Instead, you may use "then" as below:
html2canvas(document.body).then((canvas) => {
document.body.appendChild(canvas);
});
https://stackoverflow.com/a/45366038/3119507
Ran into the same issue running Angular 8. It still didn't work after installing the #types. What worked for me was to include the html2canvas library using require instead.
const html2canvas = require('../../../node_modules/html2canvas');
Then to take the screenshot:
#ViewChild('screenshotCanvas') screenCanvas: ElementRef;
html2canvas(this.screenCanvas.nativeElement).then(canvas => {
var imgData = canvas.toDataURL("image/png");
console.log("ENTER takeScreenshot: ",imgData )
document.body.appendChild(imgData);
})

How to load google maps javascript api in Aurelia javascript application?

I found npm module google-maps-api and installed it (npm install google-maps-api) but I can't figure out how to import it with systemjs/jspm (jspm cannot find this module). Here's the configuration from my config.js:
"paths": {
"*": "app/dist/*.js",
"github:*": "app/jspm_packages/github/*.js",
"npm:*": "app/jspm_packages/npm/*.js" }
So, when I try do something like this:
import {mapsapi} from 'google-maps-api';
I get the following error in browser console:
GET https://localhost:44308/app/dist/google-maps-api.js 404 (Not Found)
Looking at the filesystem I see that npm installed the module under app/node_modules/google-maps-api so how do I reference it in the import clause from Aurelia module?
I found a solution and answering my own question here:
I finally figured how to install it with jspm, so you just need to give a hint to jspm to install it from npm like so:
jspm install npm:google-maps-api
After jspm completes installation, import (no {} syntax) works fine:
import mapsapi from 'google-maps-api';
then I inject it in constructor and instantiate geocoder api:
#inject(mapsapi('InsertYourGMAPIKeyHere'))
export class MyClass {
constructor(mapsapi) {
let that = this;
let maps = mapsapi.then( function(maps) {
that.maps = maps;
that.geocoder = new google.maps.Geocoder();
});
...
}
In order to create map on a div I use EventAggregator to subscribe for router:navigation:complete event and use setTimeout to schedule map creation:
this.eventAggregator.subscribe('router:navigation:complete', function (e) {
if (e.instruction.fragment === "/yourRouteHere") {
setTimeout(function() {
that.map = new google.maps.Map(document.getElementById('map-div'),
{
center: new google.maps.LatLng(38.8977, -77.0366),
zoom: 15
});
}, 200);
}
});
Here's a complete view-model example that uses attached() to link to your view.
import {inject} from 'aurelia-framework';
import mapsapi from 'google-maps-api';
#inject(mapsapi('your map key here'))
export class MapClass {
constructor(mapsAPI) {
this.mapLoadingPromise = mapsAPI.then(maps => {
this.maps = maps;
});
}
attached() {
this.mapLoadingPromise.then(() => {
var startCoords = {
lat: 0,
long: 0
};
new this.maps.Map(document.getElementById('map-div'), {
center: new this.maps.LatLng(startCoords.lat, startCoords.long),
zoom: 15
});
});
}
}
For everyone using Typescript and getting "Cannot find module 'google-maps-api'" error,
you need to add typings to the solution. Something like this works
declare module 'google-maps-api' {
function mapsapi(apikey: string, libraries?, onComplete?);
namespace mapsapi {
}
export = mapsapi;
}
and then import it like this
import * as mapsapi from 'google-maps-api';

Resources