puppeteer files from lib folder not exist on server side install - node.js

On my windows machine I got a lot of files in my lib folder:
./node_modules/puppeteer/lib
However when I install puppeteer on my ubuntu server (Ubuntu 20.04 LTS) all of those files does not exist. There is only a cjs & esm folder.
I got a custom function in my script which access the lib files like this:
// extract the Page class
const { Page } = require("puppeteer/lib/Page");
/**
* #name elementContains
* #param {String} selector specific selector globally search and match
* #param {String} text filter the elements with the specified text
* #returns {Promise} elementHandle
*/
Page.prototype.elementContains = function elementContains(...args) {
return this.evaluateHandle((selector, text) => {
// get all selectors for this specific selector
const elements = [...document.querySelectorAll(selector)];
// find element by text
const results = elements.filter(element => element.innerText.includes(text));
// get the last element because that's how querySelectorAll serializes the result
return results[results.length-1];
}, ...args);
};
/**
* Replicate the .get function
* gets an element from the executionContext
* #param {String} selector
* #returns {Promise}
*/
const { JSHandle } = require("puppeteer/lib/JSHandle");
JSHandle.prototype.get = function get(selector) {
// get the context and evaluate inside
return this._context.evaluateHandle(
(element, selector) => {
return element.querySelector(selector);
},
// pass the JSHandle which is itself
this,
selector
);
};
Everything works fine on my windows machine. However on my ubuntu server it does not work because those files does not exist. I manually uploaded all files into this folder from my windows machine however I get then:
-TypeError: page.elementContains is not a function
Can you help me please why does the lib folder doesn´t contain the needed files on linux?

Related

How to use JSDoc with destructured imports?

I am using VSCode as my NodeJS editor and the Preview JSDOC extension.
I wonder how I can use JSDoc with restructured imports. See the example below.
I created a module, Module A:
/**
* Some function description
* #return a string + 1234
*/
const myFuncA = (someParams) => {
return `${someParams} 1234` // or whatever
};
/**
* This is a string.
*/
const myPropB = "A string";
// ...
module.exports = {
myFuncA,
myPropB
}
In module B, I'd like to use some properties or functions from module A:
Module B:
const { myFuncA } = require('../moduleA');
const propA = myFuncA(4321);
However, when hovering over myFuncA (or when typing myFuncA(...), the description is not shown.
I'm new to JSDoc, however, their docs don't cover my specific case.
I was searching for answer for this as well, and I think the best thing for this solution is to use the #memberof module:<your-module-name> syntax.
So in Module B at the top you would add something like this
/** module MyModuleName */
const { myFuncA } = require('../moduleA');
Then in Module A you would add the #memberof module:<module-name> decorator.
/**
* Some function description
* #return a string + 1234
* #memberof module:MyModuleName
*/
const myFuncA = (someParams) => {
return `${someParams} 1234` // or whatever
};
Extra Information:
As I was looking for a solution to this problem, I had the assumption that JSDoc would resolve imports. JSDoc does not resolve imports, which makes a lot of sense. If you want a function to belong to another module, you have to let JSDocs know. Credit to this github issue thread which helped me settle on this answer.

How to specify another disk for fs.readdir(path) in Electron-vue app?

Problem:
I have a breadcrumbs component (I'm using file explorer functionality from this project). The problem is I don't know how to change the disk it's displaying.
When I click on any path in it, I get this:
Uncaught (in promise) Error: Path does not exist
So in ls.js file I changed this code:
export function readdir (path) {
return pathExists(path)
? fs.readdir(path)
: Promise.reject(new Error('Path does not exist'))
}
To this code to see what it's trying to read:
export function readdir (path) {
return fs.readdir(path)
}
So it turns out it's hardcoded to display C: disk. I don't know how to make it dynamic (to display content of any specified disk).
Right now if I, for example, click on C: > Users path in the breadcrumbs component, I get:
Uncaught (in promise) Error: ENOENT: no such file or directory, scandir 'E:\Users'
I've tried doing this: fs.readdir("/" + path) but it gives me this error:
Uncaught (in promise) Error: ENOENT: no such file or directory, scandir 'E:\C:\Users\
The project folder is located on that E: disk
while the breadcrumbs displaying contents of C: disk
ls.js file:
import fs from 'fs-extra'
import { join } from 'path'
/**
* Get Array for path contents. Checks if path exists
* #param {String} path
* #return {Promise}
*/
export function readdir (path) {
return fs.readdir(path)
}
/**
* Alias of fs.existsSync
* #param {String} path
* #return {Boolean}
*/
export function pathExists (path) {
return fs.existsSync(path)
}
/**
* Get path stat
* #param {String} path
* #return {Promise}
*/
export function stat (path) {
return fs.stat(path)
}
/**
* Take in file path and return contents with stat
* #param {String} path
* #return {Array}
*/
export default path => {
return new Promise((resolve, reject) => {
const contents = []
readdir(path).then(files => {
let statsPromises = []
files.forEach(file => {
statsPromises.push(stat(join(path, file)))
})
Promise.all(statsPromises).then(stats => {
stats.forEach((stat, i) => {
contents.push({
name: files[i],
path: join(path, files[i]),
stat
})
})
resolve(contents)
})
})
})
}
If you look at the Breadcrumbs.vue you will see the following method at the botton.
placePath () {
return this.$store.state.Place.path
}
There you can see that the path is taken from the state. The state is in Place.js file.
This path in state is initialized in Place.vue file. There you'll see a method as follows.
load (path = this.$electron.remote.app.getPath('home')) {
path = join(path)
this.$store.dispatch('getContents', path).then(() => {
this.$store.commit('setPlacePath', path)
}, err => {
console.error(err)
this.$route.push('/')
})
}
The path is coming from the following line.
this.$electron.remote.app.getPath('home')
Electron documentation for the above app.getPath() method is as follows.
app.getPath(name)
name String
Returns String - A path to a special directory or file associated
with name. On failure an Error is thrown.
You can request the following paths by the name:
home User's home directory.
appData Per-user application data directory, which by default points to: * %APPDATA% on Windows * $XDG_CONFIG_HOME or
~/.config on Linux * ~/Library/Application Support on macOS
userData The directory for storing your app's configuration files, which by default it is the appData directory appended with your
app's name.
temp Temporary directory.
exe The current executable file.
module The libchromiumcontent library.
desktop The current user's Desktop directory.
documents Directory for a user's "My Documents".
downloads Directory for a user's downloads.
music Directory for a user's music.
pictures Directory for a user's pictures.
videos Directory for a user's videos.
logs Directory for your app's log folder.
pepperFlashSystemPlugin Full path to the system version of the Pepper Flash plugin.
So those are the options you have as the starting directory.
UPDATE:
this.$electron.remote.app.getAppPath() will return the current application directory.
load (path = this.$electron.remote.app.getAppPath()) {
path = join(path)
this.$store.dispatch('getContents', path).then(() => {
this.$store.commit('setPlacePath', path)
}, err => {
console.error(err)
this.$route.push('/')
})
}
UPDATE 2:
Please note that I'm new to electron as well. It seems like app.getPath method is used to get the path application is running. If you want a different path you can just hard code it there.
Example:
Note '/home/rajind' hardcoded as default value for path parameter.
In Place.js file,
getContents ({ commit }, path = '/home/rajind') {
return new Promise((resolve, reject) => {
ls(path).then(contents => {
commit('setContents', contents)
resolve()
}, err => {
reject(err)
})
})
}
and in Place.vue file,
load (path = '/home/rajind') {
path = join(path)
this.$store.dispatch('getContents', path).then(() => {
this.$store.commit('setPlacePath', path)
}, err => {
console.error(err)
this.$route.push('/')
})
}

Unable to recognize WORKSPACE as directory using Jenkinsfile/pipline plugin

I am trying to search a file recursively inside a directory hence cannot use findFiles.
I have seen the directories via manually login in to the slave but it cannot be recognized in the code below. When I use isDirectory() it says false hence later while using dir.listFiles() it return null.
Below is the code:
def recursiveFileSearch(File dir, filename, filesPath) {
File[] files = dir.listFiles() // It returns null here as it cannot recognize it as directory
echo "$files"
for (int i=0; i < files.size(); i++) {
if (files[i].isDirectory()) {
recursiveFileSearch(files[i], filename, filesPath)
} else {
if (files[i].getAbsolutePath().contains(filename)) {
filesPath.add(files[i].getAbsolutePath())
return filesPath
}
}
}
return filesPath
}
node('maven') {
git 'https://github.com/rupalibehera/t3d.git'
sh 'mvn clean install'
File currentDir = new File(pwd())
def isdir = currentDir.isDirectory()
println "isdir:${isdir}" // The output here is False
def isexist = currentDir.exists()
println "isexist:${isexist}" // The output here is False
def canread = currentDir.canRead()
println "canread:${canread}" // The output here is False
def filesPath = []
def openshiftYaml = recursiveFileSearch(currentDir, "openshift.yml", filesPath)
}
I am not sure what is going wrong here.
But below are some observations:
When I do File currentDir = new File("."), it returns / and starts reading complete root directory which I don't want and in that also it does not recognize WORKSPACE as directory
It executes well if I run it on Master node, but in my use case it will be always a slave.
I have also checked the permissions of directory the user has read/write/execute permissions.
Any pointers/help is appreciated
Generally, run a sh step to do whatever work you need. You may not use java.io.File or the like from Pipeline script. It does not run on the agent, and is also insecure, which is why any such attempt will be rejected when the sandbox mode is left on (the default).
you are running into the Using File in Pipeline Description problem. I know it all too well. File objects and NIO work fine for breaking up paths, but their isDirectory, exists and other methods run on master as a part of the Jenkinsfile and not on the node. So, all use on master looks great, because the files are in the workspace. All use on a node, fails.
In short, don't do that. Use fileExists(), pwd(), findFiles etc
If you created a shareLibrary and want to use unit tests on the code outside of Jenkins, then you can create a fascade which relies on the script object ('this' from a pipeline)
Class for shared lib
class PipelineUtils implements Serializable {
static def pipelineScript = null;
/**
* Setup this fascade with access to pipeline script methods
* #param jenkinsPipelineScript
* #return
*/
static initialize(def jenkinsPipelineScript) {
pipelineScript = jenkinsPipelineScript
}
/**
* Use pipelineScript object ('this' from pipeline) to access fileExists
* We cannot use Java File objects for detection as the pipeline script runs on master and uses delegation/serialization to
* get to the node. So, File.exists() will be false if the file was generated on the node and that node isn't master.
* https://support.cloudbees.com/hc/en-us/articles/230922128-Pipeline-Using-java-io-File-in-a-Pipeline-description
* #param target
* #return true if path exists
*/
static boolean exists(Path target) {
if (!pipelineScript) {
throw new Exception("PipelineUtils.initialize with pipeline script not called - access to pipeline 'this' required for access to file detection routines")
}
if (! target.parent) {
throw new Exception('Please use absolutePaths with ${env.WORKSPACE}/path-to-file')
}
return pipelineScript.fileExists(target.toAbsolutePath().toString())
}
/**
* Convert workspace relative path to absolute path
* #param path relative path
* #return node specific absolute path
*/
static def relativeWorkspaceToAbsolutePath(String path) {
Path pwd = Paths.get(pipelineScript.pwd())
return pwd.resolve(path).toAbsolutePath().toString()
}
static void echo(def message) {
pipelineScript.echo(message)
}
}
class for tests
class JenkinsStep {
static boolean fileExists(def path) {
return new File(path).exists()
}
static def pwd() {
return System.getProperty("user.dir")
}
static def echo(def message) {
println "${message}"
}
}
usage in jenkins
PipelineUtils.initialize(this)
println PipelineUtils.exists(".")
// calls jenkins fileExists()
usage in unit tests
PipelineUtils.initialize(new JenkinsStep())
println PipelineUtils.exists(".")
// calls File.exists
I found the answer,
for searching any file in your workspace from Jenkinsfile you can use findFiles step,
I did try this but I was passing the incorrect glob for the same. Now I just do
def files = findFiles(glob: '**/openshift.yml') \\ it returns the path of file

JSDoc when exporting a function constructor in node.js

I'm just starting to add some JSDoc comments to a code base I've been working on, for the most part this seems to work, but there's one area that's causing me some difficulties.
If I describe a function constructor in a file, and then export it on the module.exports, when I later require() that module, I get no documentation on the type and the inferred type is set as |exports. Clicking on the doesn't take me anywhere. I currently have:
/**
* Creates an instance of the StatusCodeErrorItem
* #param {string} message The message for this error
* #param {object} params The parameters that caused this error to occur
* #alias lib/common/StatusCodeErrorItem.StatusCodeErrorItem
* #returns {StatusCodeErrorItem}
* #constructor
*/
function StatusCodeErrorItem(message, params) {
this.message = message;
this.params = params;
}
/**
* Holds information about an error
* #module lib/common/StatusCodeErrorItem
*/
module.exports = StatusCodeErrorItem;
and in the file that uses it:
var StatusCodeErrorItem = require('./StatusCodeErrorItem');
I'd thought at this point that'd I'd be able to press f1 to bring up the inline documentation, and see the definition of StatusCodeErrorItem as described in that file. But instead I only see: inferred type StatusCodeErrorItem|exports
Webstorm 9
Node.js 0.10.36 (I know both are old)
Any thoughts on what I'm doing wrong? Is what I'm after even possible? Are my versions simply too old?
Cheers
Webstorm 2016.1.1 solves the issue. The below JSDoc gets correctly assigned to types pulled in by require. I'll now be pestering people to get me a new license.
'use strict';
/**
* Creates an instance of the StatusCodeErrorItem
* #memberof common
* #constructor
* #classdesc A class for holding information about an error. The params object allows the tracking of the function
* parameters that caused the error, but should not be used to store large objects.
* #description Creates an instance of the StatusCodeErrorItem with the given message and optional params object
* #param {string} message The message for this error
* #param {object} [params] The parameters that caused this error to occur
* #returns {StatusCodeErrorItem}
* #see {#link module:lib/common/StatusCodeError.StatusCodeError|StatusCodeError}
*/
function StatusCodeErrorItem(message, params) {
this.message = message;
this.params = params;
}
/**
* Surfaces a class that holds information about an error
* #module lib/common/StatusCodeErrorItem
*/
module.exports = StatusCodeErrorItem;

nodejs error: spawn ENOENT

I am very newbie with nodejs, I am trying to run it:
I obtain:
events.js:72
throw er; // Unhandled 'error' event
^
Error: spawn ENOENT
at errnoException (child_process.js:980:11)
at Process.ChildProcess._handle.onexit (child_process.js:771:34)
How Can I solve?
May be the problem is inside this code:
/**
*/
/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define, require, module, process */
var childprocess = require("child_process"),
util = require("util"),
fs = require("fs");
var procWrapper = require("./processwrapper");
var spawn = childprocess.spawn;
module.exports = function () {
"use strict";
var pvs = procWrapper();
var o = {},
output = [],
readyString = "<PVSio>",
wordsIgnored = ["", "==>", readyString],
restarting = false,
sourceCode,
filename,
processReady = false,
pvsio,
workspaceDir = process.cwd() + "/public/";
/**
* get or set the workspace dir. this is the base directory of the pvs source code
* #param {String} dir
* #return {String} the current workspace directory
*/
o.workspaceDir = function (dir) {
if (dir) {util.log("OK");
dir = dir.substr(-1) !== "/" ? (dir + "/") : dir;
workspaceDir = dir;
util.log("OOO");
return o;
}
util.log("IIII");
return workspaceDir;
};
/**
* starts the pvs process with the given sourcefile
* #param {String} filename source file to load with pvsio
* #param {function({type:string, data:array})} callback function to call when any data is received in the stdout
* #param {function} callback to call when processis ready
*/
o.start = function (file, callback, processReadyCallback) {
filename = o.workspaceDir() + file;
function onDataReceived(data) {
var lines = data.split("\n").map(function (d) {
return d.trim();
});
var lastLine = lines[lines.length - 1];
//copy lines into the output list ignoring the exit string, the startoutput string '==>'
//and any blank lines
output = output.concat(lines.filter(function (d) {
return wordsIgnored.indexOf(d) < 0;
}));
if (processReady && lastLine.indexOf(readyString) > -1) {
var outString = output.join("").replace(/,/g, ", ").replace(/\s+\:\=/g, ":=").replace(/\:\=\s+/g, ":=");
//This is a hack to remove garbage collection messages from the output string before we send to the client
var croppedString = outString.substring(0, outString.indexOf("(#"));
outString = outString.substring(outString.indexOf("(#"));
util.log(outString);
callback({type: "pvsoutput", data: [outString]});
//clear the output
output = [];
} else if (lastLine.indexOf(readyString) > -1) {
//last line of the output is the ready string
processReadyCallback({type: "processReady", data: output});
processReady = true;
output = [];
}
}
function onProcessExited(code) {
processReady = false;
var msg = "pvsio process exited with code " + code;
util.log(msg);
callback({type: "processExited", data: msg, code: code});
}
pvs.start({processName: "pvsio", args: [filename],
onDataReceived: onDataReceived,
onProcessExited: onProcessExited});
util.log("pvsio process started with file " + filename + "; process working directory is :" + o.workspaceDir());
util.log("OK");
return o;
};
/**
* sends a command to the pvsio process. This method returns immediately. The result of the command
* will be by the 'on data' event of the process standard output stream
* #param {string} command the command to send to pvsio
*/
o.sendCommand = function (command) {
util.log("sending command " + command + " to process");
pvs.sendCommand(command);
return o;
};
/**
* gets the source code pvs io is executing
* #param {string} path the path the to file whose content is to be fetched
* #param {function({type:string, data, message:string})} callback callback to execute when sourcecode has been loaded
* #returns {this}
*/
o.readFile = function (path, callback) {
pvs.readFile(path, callback);
return o;
};
/**
* writes the file passed to the disk
* #param {fileName:string, fileContent: string} data Object representing the sourcecode to save
* #param {function ({type: string, data: {fileName: string}})} callback function to invoke when the file has been saved
*/
o.writeFile = function (path, data, callback) {
pvs.writeFile(path, data, callback);
return o;
};
/**
* closes the pvsio process
* #param {string} signal The signal to send to the kill process. Default is 'SIGTERM'
*/
o.close = function (signal) {
signal = signal || 'SIGTERM';
pvs.kill(signal);
return o;
};
return o;
};
After have started it , I go to localhost:8082 and it crashes!
That's all.
I' am sorry, it's possible that throw this little information you can't help me.
I got the same error, after updating a lot of programs on my Windows 7 machine. Luckily I could remember that I removed git and installed it again using a newer version and different installation options. The difference was to select the 3rd option in "Adjusting PATH environment" settings ("Use Git and optional Unix tools from the Windows Command Prompt").
After updating node.js to a newer version (actually 0.10.31) the problem still exists. So I deciced to remove git again, and et'voila, socket server is working again. Now I will install git again with the default options, which do not to modify the PATH environment variable.
So the problem comes from unix tools accessible through PATH variable such as installed by MinGW, Git or Cygwin (probably - not tested).
Read readme
Try to install this using npm install pvsio-web -g or (if your /usr/local/ directory is owned by root) sudo npm install pvsio-web -g
You should installed pvs and pvsio on your computer
You should ensure that pvsio is available as a command on your path
If you don't want to install pvsio globally you can run it from node_modules/.bin
You should have to register to 'error' events of spawn, see: NodeJS: throw er; //Unhandled 'error' event (events.js:72) when using child_process spawn method
A very simple cause of this error: you're installing an application on a new server and the code is trying to run a linux CLI program that hasn't yet been installed on that particular server.
In my case, the code was spawning a process running inotify. So going to the linux command line and running
apt-get install inotify-tools
resolved the error.

Resources