Why does glob promise return an empty string array? - node.js

I am only using typescript, ts-node, npm and path
I am simply trying to return a string array of files defined by my pattern using glob-promise (An npm that I imported which uses glob but its promise based).
I created a custom npm script to run my ts file for the terminal to display info in my package.json below
{
"name": "glob-test",
"version": "1.0.0",
"description": "A Glob Test",
"scripts": {
"build:glob": "ts-node --files globby.ts"
},
"dependencies": {
"glob-promise": "^6.0.1",
"path": "^0.12.7",
"ts-node": "^10.9.1",
"typescript": "^4.9.4"
}
}
And this below is my globby.ts file which runs the glob script
import * as path from 'path';
import glob from 'glob-promise';
const dir = path.dirname(__dirname);
const txtURL = path.resolve(dir, 'glob-test', 'folder-area', '*.txt');
glob(txtURL).then(function (cnt) {
console.log('Path: ' + txtURL);
console.log('Content: ', cnt);
});
My project directory looks like so:
I type in my terminal npm run build:glob but it returns an empty array and the path displays correctly I'm not sure what I am doing wrong. I've attempted to use path.join and path.resolve but either give the same result. It should return the joke.txt file. Anyone have any idea ?

Turns out the answer is that the path module with the glob-promise module are not playing nice in my windows environment. If I use a normal string with or without concats glob will return perfectly anything I ask.
This seems to be a bug/issue or incompatibility within the windows environment most likely. Yet to test on Linux.
e.g: Works below
import * as path from 'path';
import glob from 'glob-promise';
// const dir = path.dirname(__dirname);
const txtURL = path.resolve('folder-area', '*.txt');
const testURL = './folder-area/*.txt';
const returnTxtFiles = async () => {
const txtFiles = await glob(testURL);
console.log(txtFiles);
};
returnTxtFiles();
The above correctly returns ['joke.txt', 'file1.txt']
The other option is replace all the '/' to '' manually to any path.join("string", "string") by adding at the end .replace(/\\/g, "/")
Which is the method I went with as it took much less work adn I think is more understandable as well as it changes the original codebase the least.

Related

Node Environment variable ignored by testing library

I'm implementing Testing Library with Puppeteer and I was trying to use an environment variable, DEBUG_PRINT_LIMIT, to limit the length of the HTML printed to console in case of failure.
But for some reasons, the variable environment is just ignored by the library...
My project:
package.json
{
"scripts": {
"test": "jest --detectOpenHandles"
},
"devDependencies": {
"jest": "^26.6.3",
"pptr-testing-library": "^0.6.4",
"puppeteer": "^2.1.1"
}
}
main.test.js
const puppeteer = require('puppeteer')
require('pptr-testing-library/extend')
test('Should go to the forum', async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto("https://mkpc.malahieude.net");
const $document = await page.getDocument();
const $forum = await $document.getByText("Forum");
});
Now when I run DEBUG_PRINT_LIMIT=10 npm test, the environment variable is just ignored since it prints me the whole HTML instead of just 10 characters...
I tried many things: setting the environment variable in the package.json file, or directly in the code, but nothing works, the variable is just ignored.
However if I change the code of the library (file node_modules/pptr-testing-library/dom-testing-library.js), and I replace process.env.DEBUG_PRINT_LIMIT || 7000 with process.env.DEBUG_PRINT_LIMIT || 10, then it works! So it seems that for some reason the environment variable is not passed correctly to the library.
I'm using node version 12 on a Debian machine (I think it doesn't change anything though).
Can you tell me what I'm doing wrong?
Thanks
If finally figured it out.
It's actually a bug in the library itself: https://github.com/testing-library/pptr-testing-library/issues/55

Syntax error on express.js after migrating to node v14, changing files to type mjs and import statements

I am trying to update my old server to the newer standards by removing require and including import. However the code that I had within the previous files included destructuring of the req.body, which worked fine before. Now I get the error that there is a syntax error. Any ideas?
Quoted error
/controllers/addStemDatabase.mjs:10
} = req.body;
^
SyntaxError: Unexpected token '}'
at Loader.moduleStrategy (internal/modules/esm/translators.js:145:18)
Place where it is used
export const handleAddStemDatabase = (req, res, db) => {
const {
last_modified_email,
name,
project_hash,
filetype,
locked,
downloadable,
private
} = req.body;
};
Package Json has this
"type": "module",
"engines": {
"node": "14.16.1"
},
Import statement
import { addStemDatabase } from "./controllers/addStemDatabase.mjs";
private is a reserved word in JS/ECMAScript (reference). I suspect that your previous version of node wasn't yet based on a version of EMCAScript that considered that word private but that it is now.
Update: After doing some testing I found that private seems to only be considered a reserved word in modules, i.e., .mjs files. Perhaps you previously had this code in a .js file instead?
You'll probably need to rename your variable.
const {
last_modified_email,
name,
project_hash,
filetype,
locked,
downloadable
} = req.body;
const private_field = req.body.private;

Importing from lower level of node package

I have a node package (lets call it my-package) that currently looks like the following
src/
index.js
generators/
generate-stuff.js
index.js looks like the following
module.exports={
"some": {
"json": "objects",
...
},
"other": {
"json": "things",
...
}
};
Now I can import this file very easily in other packages by doing the following
const myPackage = require('my-package');
And myPackage will have the contents of that JSON you see above
However what I really want to import is a function that exists in generate-stuff.js (The structure of this package is inherited and I cannot easily change it)
That file looks like the following
module.exports = { functionIWantToExport(input1, input2){
return {
// do stuff with said inputs
};
}
}
However when I do something like
const functionIWant = require('my-package/generators/generate-stuff');
I get the following failure.
Cannot find module 'my-package/generators/generate-stuff'
Is there any way I can pull out the function I need from this package?
I can see in my node_modules that the module.exports is on the file I need
So was able to figure out the source of my problem. And it has do with the main in package.json
In my package.json there is the following
"main": "src/index.js"
So that's why just doing require('my-package'); works. But if I want to use the relative path it's still from above the src folder, so what I really need is
const functionIWant = require('my-package/src/generators/generate-stuff');
Doing this resolved my issue

Mocha testing path argument in package.json

Note: I'm a complete noob to nodejs. Please explain your answer in such a way somebody who has experience in other programming languages, but creates his very first nodejs application can understand =).
I'm trying to write a simple test application which should automate testing an external service against an OpenApi 3.0 specification.
I've pulled together some example code in order to attempt to automate testing the OpenApi spec against an external service which implements the API using mocha and chai.
My problem seems now that my mocha test modules cannot be found.
I get the following error message:
> client_test#1.0.0 test /Users/user1/dev/app/app-rt/client_test
> mocha ./test/**/*.test.js
/Users/user1/dev/app/app-rt/client_test/node_modules/yargs/yargs.js:1163
else throw err
^
Error: The "path" argument must be an absolute filepath
My package.json:
{
"name": "client_test",
"version": "1.0.0",
"description": "Client Tester",
"main": "index.js",
"scripts": {
"test": "mocha ./test/**/*.test.js"
},
"license": "UNLICENSED",
"dependencies": {
"chai-http": "^4.3.0",
"chai-openapi-response-validator": "^0.2.4",
"mocha": "^6.2.0",
"nock": "^11.3.2"
}
}
The little test application in test/client_all.test.js:
// Set up Chai
const chai = require('chai');
const expect = chai.expect;
// Import this plugin
const chaiResponseValidator = require('chai-openapi-response-validator');
const baseUrl = 'http://localhost:8081';
// Load an OpenAPI file (YAML or JSON) into this plugin
chai.use(chaiResponseValidator('./spec/app.json'));
// Get an HTTP response using chai-http
chai.use(require('chai-http'));
// Write your test (e.g. using Mocha)
describe('GET /zones', function() {
it('should satisfy OpenAPI spec', async function() {
const res = chai.request(baseUrl).get('/zones');
expect(res.status).to.equal(200);
// Assert that the HTTP response satisfies the OpenAPI spec
expect(res).to.satisfyApiSpec;
});
});
Can you help me figure out why the paths cannot resolved, and how to fix it? Feel free to comment on the test code as well, if you think I'm doing it wrong.
The problem is with the package chai-openapi-response-validator. Try something like this:
// Import this plugin
const chaiResponseValidator = require('chai-openapi-response-validator');
const baseUrl = 'http://localhost:8081';
// New code
const path = require('path')
const specPath = path.resolve('./spec/app.json')
// Load an OpenAPI file (YAML or JSON) into this plugin
chai.use(chaiResponseValidator(specPath));
Make sure the path to the app.json file is relative to the package.json file, or use another method to convert it to an absolute path.

Create a TypeScript Library and use it from Node.js with ES6 and TypeScript

I want to create a TypeScript library as private npm package which can be used in Node.js (including 6.x) using ES6 with #types support and TypeScript.
The goal of the library is to extend the Request type from express and provide additional properties.
I created a new Node.js project and add this tsconfig.json:
{
"compilerOptions": {
"target": "es2015",
"module": "commonjs",
"sourceMap": true,
"declaration": true,
"outDir": "./dist",
"strict": true,
"types": ["mocha"]
}
}
These are the relevant parts of the package.json:
{
"name": "#myscope/my-lib",
"main": "dist",
"scripts": {
"build": "rm -rf ./dist && ./node_modules/.bin/tsc",
"test": "./node_modules/.bin/mocha test"
},
"private": true,
"dependencies": {
"joi": "11.4.0"
},
"devDependencies": {
"mocha": "^5.2.0",
"express": "^4.16.4",
"#types/express": "^4.16.1",
"#types/joi": "^14.3.0",
"#types/mocha": "^5.2.5",
"typescript": "^3.2.4"
}
}
My folder structure is this:
- dist
- src
- http
- security
- test
I created a new TypeScript file AuthenticatedRequest.ts in src/http:
import {Request} from "express";
import {UserReference} from "../security/UserReference";
export interface AuthenticatedRequest extends Request {
user: UserReference
}
src/security contains a UserReference.ts:
import {Claim} from "./Claim";
export interface UserReference {
claims: Claim[];
}
and a Claim.ts:
import {IClaim} from "./IClaim";
export class Claim implements IClaim {
type: string;
value: string;
constructor(type: string, value: string) {
this.type = type;
this.value = value;
}
}
IClaim.ts looks like this:
export interface IClaim {
type: string,
value: string
}
In test, I created AuthenticatedRequestTests.js (plain ES6, no TypeScript here to validation code completion and usage from ES6):
'use strict';
const assert = require('assert');
const Claim = require("../dist/security/Claim").Claim;
describe('req', () => {
it('should ', done => {
/** #type {AuthenticatedRequest} */
const req = {};
req.user = { claims: [new Claim('tenantId', '123')] };
assert.equal(req.user.claims[ 0 ].type, 'tenantId');
assert.equal(req.user.claims[ 0 ].value, '123');
return done();
});
});
Now I have sevaral questions:
Is this the expected TypeScript way to solve this?
Is it possible to just use require("../dist/security/Claim"); instead of require("../dist/security/Claim").Claim;?
Instead of using this jsdoc statement /** #type {AuthenticatedRequest} */ I would like to use /** #type {myLib.http.AuthenticatedRequest} */
I also created a local test project for integration and installed my library via npm link.
But instead of using
const Claim = require("#scope/my-lib/security/Claim").Claim; I have to use
const Claim = require("#scope/my-lib/dist/security/Claim").Claim;
How can I get rid of the dist folder name here?
Also, using the jsdoc comment for AuthenticatedRequest in the integration test project, I get the error that the type cannot be found:
package.json
There should be a field called types (or typings) telling your library consumers where are the type definitions for your project. If they are generated by TypeScript and saved to dist/index.d.ts, then that's the path that should be used.
"types": "./dist/index.d.ts"
There should be a field called files containing an array of files/directories that will be delivered to your end users.
Running tests
Is this the expected TypeScript way to solve this?
If you're using TypeScript to develop your library, there is no reason not to use TypeScript for your tests. There are TypeScript-compliant test runners out there (ts-jest used to be popular, and now Jest is capable of understanding TypeScript out of the box).
Is it possible to just use require("../dist/security/Claim"); instead of require("../dist/security/Claim").Claim;?
With TypeScript, a few kinds of syntax are possible. You could export Claim using a default export and do:
import Claim from "../dist/security/Claim";
or:
const Claim = require("../dist/security/Claim");
Instead of using this jsdoc statement /** #type {AuthenticatedRequest} */ I would like to use /** #type {myLib.http.AuthenticatedRequest} */.
You will need an import type. They look like that:
/**
* #type {import('path/to/AuthenticatedRequest')}
*/
const req {}
The path can be relative or absolute. If you'd like to treat the local codebase as if it were installed from npm, you can create another package.json file in your test directory and use a relative path to resolve your library module.
"dependencies": {
"my-library": "../path/to/the/root"
}
Also, using the jsdoc comment for AuthenticatedRequest in the integration test project, I get the error that the type cannot be found:
That's also solved by import types. Unless a type is not in the global scope, you need to import it before you can use it. Use import('path/to/AuthenticatedRequest') instead.
There are a few things going on. If you could create a public repository to demonstrate your problems, I'm sure it would be easier for us to help you address them.
I have an alternate answer for one part of your question. You asked
instead of using
const Claim = require("#scope/my-lib/security/Claim").Claim; I have to use
const Claim = require("#scope/my-lib/dist/security/Claim").Claim;
How can I get rid of the dist folder name here?
As Karol points out, you can use files in package.json so that when your library is published, you send the dist directory as the package root (plus package.json, README, etc). This is a great, established pattern, but has some downsides: installing the package from github: instead of NPM won't work, nor will npm link for local development.
As of very recent Node versions, you can use the exports property instead:
{
"exports": {
"./": "./dist/"
}
}
Now, require("my_lib/security/Claim") resolves to node_modules/my_lib/dist/security/Claim. It would be great if Typescript handled this automatically, but as far as I can tell you also have to specify a baseUrl and paths in your tsconfig.json, at least for now.

Resources