nodemon starting `node server.js` TypeError: marked is not a function - node.js

I'm creating a blog, using this 'Web Dev Simplified' tutorial:
https://www.youtube.com/watch?v=1NrHkjlWVhM
I've copied the code from git hub https://github.com/WebDevSimplified/Markdown-Blog, installed the node modules and linked it to my mongodb database online.
Node Modules include;
express, mongoose, ejs, --save-dev nodemon, slugify, method-override, dompurify, jsdom.
The database was working and I could save articles, until I added the last part about sanitizing HTML and converting markdown to HTML, this is when the 'TypeError: marked is not a function' comes up, and the save button ceases to work.
Seems a once understood function is now not understood because of a more recent node module dependency, either the dompurify library or jsdom. I'm really out of my depth here! please help!

From Marked Documentation:
https://marked.js.org/#demo
Node JS
import { marked } from 'marked';
// or const { marked } = require('marked');
const html = marked.parse('# Marked in Node.js\n\nRendered by **marked**.');
Your Code:
if (this.markdown) {
this.sanitizedHtml = dompurify.sanitize(marked(this.markdown))
}
try this:
if (this.markdown) {
this.sanitizedHtml = dompurify.sanitize(marked.parse(this.markdown))
}
its work for me

In my case:
const { marked } = require('marked');
instead of
const marked = require('marked')
...
this.sanitizedHTML = dompurify.sanitize(marked.parse(this.markdown))
Per node example documentation at https://marked.js.org/#demo

Related

Can't use crypto in NPM dependency in Electron app

I'm building an Electron app (with Ionic) to digitally sign PDFs with p12 certificates using node-signpdf (https://www.npmjs.com/package/node-signpdf). I've had problems which I solved by using require ('electron').remote for example for fs.
I've also installed the same node version in my OS (MacOS Catalina) as the same one that electron is using (Node v12.4.0).
The problem is that one of the NPM dependencies uses crypto and it shows as undefined with the next error:
HomePage.html:39 ERROR TypeError: _crypto.randomBytes is not a function
at Object.ctx.seedFileSync (prng.js:340)
at _reseedSync (prng.js:210)
at Object.ctx.generateSync (prng.js:163)
at Object.ctx.generate (prng.js:80)
at Object.ctx.getBytes (random.js:92)
at _modPow (rsa.js:431)
at Object.push../node_modules/node-forge/lib/rsa.js.pki.rsa.encrypt (rsa.js:501)
at Object.key.sign (rsa.js:1245)
at addSignerInfos (pkcs7.js:534)
at Object.sign (pkcs7.js:377)
What I can see is that node-signpdf uses node-forge as a dependency, and node-forge loads crypto inside prng.js this way:
var _crypto = null;
if(forge.util.isNodejs && !forge.options.usePureJavaScript &&
!process.versions['node-webkit']) {
_crypto = require('crypto');
}
I've tried changing that part of the code to use crypto-js or browserfy-crypto (this last one doesn't even build and hasn't been updated in years), but I keep getting the error shown above.
EDIT 1:
This is how I'm implementing the signature in my service:
public signFile(pathToFile: string, pathToCert: string): void {
const fs = (<any>window).require('fs');
let certBuffer = fs.readFileSync(pathToCert);
let fileBuffer = fs.readFileSync(pathToFile);
fileBuffer = plainAddPlaceholder({
pdfBuffer: fileBuffer,
reason: 'I have reviewed it.',
signatureLength: 1612,
});
const signedPdf = signer.sign(fileBuffer, certBuffer, {passphrase: 'qwertyui'});
}
The code adds the placeholder to add the signature, the problem comes in signer.sign
EDIT 2:
When I run the app if I type in console: require ('crypto') I see the methods, so it looks like it's loaded in the global scope, the problem seems to be in the NPM dependency of node-forge.
EDIT 3:
I've changed require('crypto') to window.require('crypto') and started working. But I think I'll have to make postinstall script to modify it.
Is there a better way?
-
How can I make this crypto thing work? I ran out of ideas. Maybe you can spare some?
Thanks for your time!

Getting DialogSet.add(): Invalid dialog being added when testing

I'm trying to build some tests for my bot dialogs. I'm using the same test code (and modified test data) with two different bots with the identical dialog names. As such, the test.js file is the same for both bots. However, when I try to run my tests via Mocha on the second bot, I am getting an Error: DialogSet.add(): Invalid dialog being added. message for each test. This does not happen with my first bot. I even tried replacing the dialog file in the second bot with the one from the (working) first, and I still got the same error. As such I can't find anything different between the bots. I even replaced all of the files in question (the test, the test data/conversation, and the dialog itself) with the files from the first bot and still got the same error. Lastly, all botbuilder packages and other dependencies are the same version between the bots. I'm at a loss here...anyone have any ideas?
Here is the dialog that is being called. I left out the actual dialog steps but that shouldn't be relevant to the issue since all of the Dialog add activity happens in the constructor.
const { TextPrompt, ChoicePrompt, ConfirmPrompt, ChoiceFactory, ComponentDialog, WaterfallDialog, DialogSet, DialogTurnStatus } = require('botbuilder-dialogs');
const { VistaServiceHelper } = require('../helpers/vistaServiceHelper');
const { TrackingServiceHelper } = require('../helpers/trackingServiceHelper');
const { CosmosDbStorage } = require('botbuilder-azure');
const LINE_PROMPT = 'linePrompt';
const ORDER_PROMPT = 'orderPrompt';
const CRITERIA_PROMPT = 'criteriaPrompt';
const SEARCH_CRITERIA = ['GO', 'PO'];
const WATERFALL_DIALOG = 'waterfallDialog';
const CONFIRM_PROMPT = 'confirmPrompt';
// Static texts
const escalateMessage = `Escalation message here`
const msDay = 86400000;
class viewOrderDialog extends ComponentDialog {
constructor(dialogId, userDialogStateAccessor, userState) {
super(dialogId);
this.addDialog(new ChoicePrompt(CRITERIA_PROMPT));
this.addDialog(new TextPrompt(ORDER_PROMPT));
this.addDialog(new TextPrompt(LINE_PROMPT, this.validateLineNumber));
this.addDialog(new ConfirmPrompt(CONFIRM_PROMPT));
this.addDialog(new WaterfallDialog(WATERFALL_DIALOG, [
this.requestOrderNumber.bind(this),
this.selectSearchCriteria.bind(this),
this.displayLineItems.bind(this),
this.displayLineStatus.bind(this),
this.loopStep.bind(this)
]));
this.initialDialogId = WATERFALL_DIALOG;
this.integrationLog = new CosmosDbStorage({
serviceEndpoint: process.env.ACTUAL_SERVICE_ENDPOINT,
authKey: process.env.ACTUAL_AUTH_KEY,
databaseId: process.env.DATABASE,
collectionId: 'integration-logs'
});
this.queryData = {};
} // End constructor
I was able to fix this by deleting the botbuilder-testing folder inside the project's node_modules folder and rerunning npm install botbuilder-testing (even though I had already confirmed version in package.json and package-lock.json were showing latest version and had run npm install and npm update).
It appears this did stem from some sort of versioning issue and for whatever reason, only completely deleting the folder and reinstalling fixed it.
You may want to also verify the version of botbuilder inside your package.json file, because all of this packages must be at the same version
Ex:
"botbuilder": "~4.10.3",
"botbuilder-ai": "~4.10.3",
"botbuilder-dialogs": "~4.10.3",
"botbuilder-testing": "~4.10.3",
I Believe the accepted answer does not work in all cases . the correct answer would be to have the same botbuilder and botbuilder-testing versions .
I had the same problem and putting the same versions (or at least not putting a botbuilder-testing version above botbuilder worked)
Example
Here are example versions that work together :
"botbuilder": "~4.13.6",
"botbuilder-dialogs": "~4.13.6",
"botbuilder-testing": "^4.13.6",

node.js (using ts-node) referencing local TypeScript module causing TypeError for constructor

I'm building a project ReactJS and TypeScript and want to use a module I will share between my web application and API server.
I've used create-react-app with ts-scripts for my web app. I've made my shared module without using a starter project because it's pretty simple.
My web application references my shared module using NPM's local packages feature, the command npm install --save <path/to/shared/package>
When I do npm run start for my react app I get the error
TypeError: __WEBPACK_IMPORTED_MODULE_3_validation_shared__.ValidEmail is not a constructor
validation_shared is my unimaginative module name.
The TypeScript causing the error is
const valid_email = new ValidEmail("john.doe#example.com");
Is there anything I can change in my configs or setup to get this working? I would love to use typescript & ts-node, and have shared modules.
Edit - adding code for ValidEmail and the other function in that file.
export function validate(email_address: string): boolean {
return email_address.indexOf("#") !== -1;
}
export class ValidEmail {
public email_address: string;
constructor(email_address: string) {
if(validate(email_address)) {
this.email_address = email_address;
} else {
throw new TypeError("Invalid value for email address param, it must contains an # symbol.");
}
}
}
After more investigation it looks like whatever webpack/bundling process create-react-app uses is bundling the import definitions with the front-end code but not adding the actual class & function definitions.
I found this out by checking the generated code that is loaded into chrome and looking for actual class name "ValidEmail" which isn't present.
Edit # 2 - console.log output
I updated my App.tsx to this
import { HeaderBar, IHeaderBarProps } from "./components/headerbar";
import * as vs from "validate-shared";
class App extends React.Component {
public render() {
console.log(vs);
And the result of console.log(vs) is:
/static/media/index.9d88054a.ts
When I look at the contents of the file I see only
export * from "./ValidEmail";
export * from "./User";
This makes sense because it's the contents of my index.ts file for that module. I can't find the "meat" of the files ValidEmail or User anywhere. It looks like the actual code for those classes isn't included anywhere.

Why is `window` undefined when running my Webpack plug-in after upgrading to Webpack 4?

I've written a plug-in for Webpack that takes my generated React component, renders it in Node, and then inserts it into the generated HTML document.
This used to work fine in Webpack 3. To upgrade it to Webpack 4, I replaced
compiler.plugin("after-emit", compilation => {
with
compiler.hooks.afterEmit.tap('prerender-plugin', (compilation) => {
which, as far as I can see, should be sufficient.
In the plug-in, I ask Webpack for the path to my generated bundle and then require that, roughly as follows:
const assetHash = Object.keys(compilation.assets).filter(asset => /app(.*).js/.test(asset))[0];
const appFilePath = compilation.assets[assetHash].existsAt;
// The `.default` is needed because it's an ES2015 module
const App = require(appFilePath).default;
However, I then all of a sudden hit errors like the following as a result of the require:
ReferenceError: window is not defined
at Object.<anonymous> (/home/vincent/Workspace/Flockademic/stacks/frontend/dist/app.da5512cf55a3c4446086.js:1:286)
...
The offending code seems to be some standard Webpack top matter:
!function(e,i){if("object"==typeof exports&&"object"==typeof module)module.exports=i();else if("function"==typeof define&&define.amd)define([],i);else{var a=i();for(var o in a)("object"==typeof exports?exports:e)[o]=a[o]}}(window,function(){return function(e){var i={};function a(o){if
(Note that this sample is up to the supposedly-offending column. As you can see, window is not actually referred to on column 286.)
I'm not that familiar with Webpack, and documentation on plug-ins relatively scarce, so any pointers on how to get closer to solving this are very much welcome/
Add this at your root .js file will probably work.
if (typeof window === 'undefined') {
global.window = {};
}

Jest can not deal with insertAdjacentElement?

I want to test a quite simple JS function
export function displaySpinner() {
const loadingOverlayDOM = document.createElement('DIV');
const spinner = document.createElement('IMG');
loadingOverlayDOM.id = 'overlay-spinner';
loadingOverlayDOM.className = 'content-overlay';
spinner.className = 'is-spinning';
spinner.setAttribute('src', '/assets/img/svg/icons/spinner.svg');
l loadingOverlayDOM.insertAdjacentElement('beforeend', spinner);
document.body.insertAdjacentElement('beforeend', loadingOverlayDOM);
}
with this (for the purpose of this issue stripped down) Jest test code:
test('displaySpinner displays the spinner overlay in the current page', () => {
utils.displaySpinner();
});
But the test run yells at me:
FAIL app/helper/utils.test.js
● utils › displaySpinner displays the spinner overlay in the current page
TypeError: loadingOverlayDOM.insertAdjacentElement is not a function
at Object.displaySpinner (app/helper/utils.js:185:439)
at Object.<anonymous> (app/helper/utils.test.js:87:15)
at Promise.resolve.then.el (node_modules/p-map/index.js:42:16)
at process._tickCallback (internal/process/next_tick.js:109:7)
Is this an error in Jest or am I missing something here?
I finally found the answer myself:
Jest uses jsdom which does not yet support the DOM function insertAdjacentElement (see this issue on GitHub and it's references). So I'll have to wait until jsdom implements it or use another method in my JS.
You can replace the default version of jsdom with an up-to-date version (e.g. 14) by installing the corresponding module:
npm install --save-dev jest-environment-jsdom-fourteen
or using yarn:
yarn add jest-environment-jsdom-fourteen --dev
and then using the jest testEnvironment config parameter:
{
"testEnvironment": "jest-environment-jsdom-fourteen"
}
Note that if you launch jest with the --env=jsdom argument, this will override the config file, so you need to remove it.

Resources