Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './v4' is not defined by "exports" - node.js

I got this error when using uuidv4.
Failure: Package subpath './v4' is not defined by "exports" in C:\Users\mycomp\Desktop\Programming\Javascript\Serverless\Serverless Framework\node_modules\uuid\package.json
Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './v4' is not defined by "exports" in C:\Users\mycomp\Desktop\Programming\Javascript\Serverless\Serverless Framework\node_modules\uuid\package.json
I already installed uuid and require it in my code
const uuidv4 = require('uuid/v4');
Here's the package.json
"dependencies": {
"aws-sdk": "^2.702.0",
"moment": "^2.27.0",
"serverless-offline": "^6.4.0",
"underscore": "^1.10.2",
"uuid": "^8.1.0"
}

ECMAScript Module syntax:
import { v4 as uuidv4 } from 'uuid';
uuidv4(); // ⇨ '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'
CommonJS syntax:
const { v4: uuidv4 } = require('uuid');
uuidv4(); // ⇨ '1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed'

Another option
const uuid = require('uuid');
uuid.v4(); // "c438f870-f2b7-4b2c-a1c3-83bd88bb1d79"

We had the same error with v1 uuid module (v8.3.2).
Solved this, adding following entry to exports section of installed uuid package.json(inside your node_modules):
"./v1": "./dist/v1.js"
Full export section of my projects' node_modules/uuid/package.json:
"exports": {
".": {
"node": {
"module": "./dist/esm-node/index.js",
"require": "./dist/index.js",
"import": "./wrapper.mjs"
},
"default": "./dist/esm-browser/index.js"
},
"./package.json": "./package.json",
"./v1": "./dist/v1.js"
},
The problem remaining i now need to keep this modification across dist installs... :/
This could be fixed with a patch on uuid source itself?
EDIT: Didn't require the module in our own source. It is a dependency of jest (via some jest reporting sub-pkg).
EDIT: Alternatively, rolling back to uuid dep to v7.0.3 may fix this issue too, see comment below.

docs:
https://nodejs.org/api/esm.html
Like in CommonJS, module files within packages can be accessed by appending a path to the package name unless the package's package.json contains an "exports" field, in which case files within packages can only be accessed via the paths defined in "exports".
https://nodejs.org/api/packages.html#main-entry-point-export
When the "exports" field is defined, all subpaths of the package are encapsulated and no longer available to importers. For example, require('pkg/subpath.js') throws an ERR_PACKAGE_PATH_NOT_EXPORTED error.
This encapsulation of exports provides more reliable guarantees about package interfaces for tools and when handling semver upgrades for a package. It is not a strong encapsulation since a direct require of any absolute subpath of the package such as require('/path/to/node_modules/pkg/subpath.js') will still load subpath.js.

Related

Must use import to load ES Module - lowlight with Quasar app [duplicate]

I an SSR Quasar project using Vite. Whenever I try to add the #tiptap/extension-code-block-lowlight extension to my project, build it and then node dist/ssr/index.js it throws the following error:
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /home/whatever/devotto/devotto.com/node_modules/lowlight/lib/common.js
require() of ES modules is not supported.
require() of /home/whatever/devotto/devotto.com/node_modules/lowlight/lib/common.js from /home/whatever/devotto/devotto.com/dist/ssr/server/server-entry.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename common.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /home/whatever/devotto/devotto.com/node_modules/lowlight/package.json.
Upon investigation, I have concluded that the issue is the lowlight library being imported by #tiptap/extension-code-block-lowlight.
If I manually go to my node_modules/#tiptap/extension-code-block-lowlight/package.json AND node_modules/lowlight/package.json and remove the line "type": "module", I can run the project with no problem (e.g. yarn build && node dist/ssr/index.js.
This solution works on my current machine but I shouldn't have to touch the node_modules folder.
I would assume that I have to transpile lowlight library which prompts me to try to alter Vite configuration but no luck there as well
module.exports = function() {
return {
build: {
extendViteConf (viteConf, { isClient, isServer }) {
if (isServer) {
viteConf.optimizeDeps = viteConf.optimizeDeps || {};
viteConf.optimizeDeps.include = ['./node_modules/highlight.js'];
viteConf.build.commonjsOptions = viteConf.build.commonjsOptions || {};
viteConf.build.commonjsOptions.include = [/highlight.js/, /node_modules/];
// viteConf.optimizeDeps.entries = [
// 'node_modules/#tiptap/extension-code-block-lowlight/dist/tiptap-extension-code-block-lowlight.cjs',
// 'node_modules/highlight.js'
// ];
}
},
}
}
}
Is there a solution to this issue without having to manually change node_module folder? Thank you very much in advance.
I didn't exactly solve the question. I only applied an automated way to handle this whenever I run the command to build the server using pre scripts.
On my package.json:
{
"scripts": {
"start:test:webserver": "ENV_FILE=test quasar build --mode ssr --port 3000 && node dist/ssr/index.js",
"prestart:test:webserver": "sed -i '/\"type\": \"module\",/d' node_modules/lowlight/package.json && sed -i '/\"type\": \"module\",/d' node_modules/#tiptap/extension-code-block-lowlight/package.json",
}
}

Cannot find module 'node:url' when executing typescript from webstorm

I have written this small typescript hello world example
import axios from 'axios';
import { wrapper } from 'axios-cookiejar-support';
import { CookieJar } from 'tough-cookie';
const jar = new CookieJar();
const client = wrapper(axios.create({ jar }));
client.get('https://example.com');
when I run this from webstorm i get the following error
/usr/bin/node /usr/local/lib/node_modules/ts-node/dist/bin.js /home/nayana/WebstormProjects/hello-world/hello.ts
Error: Cannot find module 'node:url'
anyone have idea on how to resolve this?
I already tried npm install node:url and url
i have isolated the error to this line
const client = wrapper(axios.create({ jar }));
The issue maybe is related to the node version.
The axios-cookiejar-support requires a specific node version ("node": ">=14.18.0 <15.0.0 || >=16.0.0").
Check node --version and package-lock.json.
Sample:
"node_modules/axios-cookiejar-support": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/axios-cookiejar-support/-/axios-cookiejar-support-4.0.3.tgz",
"integrity": "sha512-fMQc0mPR1CikWZEwVC6Av+sD4cJuV2eo06HFA+DfhY54uRcO43ILGxaq7YAMTiM0V0SdJCV4NhE1bOsQYlfSkg==",
"dependencies": {
"http-cookie-agent": "^4.0.2"
},
"engines": {
"node": ">=14.18.0 <15.0.0 || >=16.0.0"
},
"peerDependencies": {
"axios": ">=0.20.0",
"tough-cookie": ">=4.0.0"
}
},
You might need to install a later version of node.js.
I was running 14.17.6 and after installing 16.17.0 with nvm then I was able to run the project.
If you have nvm installed you can install a specific version of node e.g.
nvm install 16.17.0
make sure the types array in your tsconfig.json file contains "node"
{
"compilerOptions": {
"types": [
// ... your other types
"node"
],
// ... your other settings
},
}
The only thing you need to do, if you didn't install typescript is to change in the vite.config.js file, the import line like this:
import { fileURLToPath, URL } from 'node:url'
To:
import { fileURLToPath, URL } from 'url'

npm package.json aliases like webpack

i am trying to alias a module however i am not sure how to do that with package.json
in webpack you would do something like this:
module.exports = {
//...
resolve: {
alias: {
'pixi.js': 'pixi.js-legacy'
}
}
};
But what is the equivalent without webpack?
Since NPM Version 6.9 of March 2019 it is supported without installing any additional packages (see the RFC):
npm i aliasName#npm:packageToInstall
⬇⬇⬇
// package.json
"dependencies": {
"aliasName": "npm:packageToInstall#^1.6.1"
}
The idea seems to be that npm: is a URI-like scheme in a dependency version specifier.
Usage:
const alias = require( 'aliasName' );
There is a npm package for this: module-alias.
After installing it you can add your aliases to the package.json, like so:
"_moduleAliases": {
"#root" : ".", // Application's root
"#deep" : "src/some/very/deep/directory/or/file",
"#my_module" : "lib/some-file.js",
"something" : "src/foo", // Or without #. Actually, it could be any string
}
Make sure to add this line at the top of your app's main file:
require('module-alias/register');
You should only use this in final products (and not packages you intend to publish in npm or use elsewhere) - it modifies the behavior of require.

Multiple NPM repos in one GitHub repo with scoping?

Let's say I have a client, awesome-service that composes of different types of services, http-service, log-service, etc...
I want to have the option of either including each individual service (and a specific version), or just require all of the awesome-services, so in effect I want something like:
const awesomeService = require('#awesome-service');
// Now awesomeService has
// awesomeService.httpService;
// awesomeService.logService;
// etc
// or individually
const httpService = require('#awesome-service/http-service');
Is this possible? What would the package.json and the GitHub organization look like? Maybe this is package.json?
"dependencies": {
"awesome-service": "#awesome-service"
// OR if individually importing them
"http-service": "#awesome-service/http-service#1.0.0"
}
How can this be accomplished, or rather can this be accomplished?
Is this possible?
Yes, it's possible.
What would the package.json and the GitHub organization look like?
The package should have the following structure:
- awesome-service
- index.js // main module
- package.json // package.json of the main package
- http-service
- index.js // implementation of `http` service
- package.json // package.json of `http` package
- log-service
- index.js // implementation of `log` service
- package.json // package.json of `log` package
As you see there are three package.json files. The root is used for main package, others for each service.
In each package.json, set main field to index.js and set a correct name for each package:
{
"name": "awesome-service",
"main": "index.js",
...
}
{
"name": "awesome-service#http-service",
"main": "index.js",
...
}
{
"name": "awesome-service#log-service",
"main": "index.js",
...
}
In index.js of the root package export the object with the fields - required services (I don't specify index.js in requires, because this module will be loaded by default):
module.exports = {
httpService: require('./http-service'),
logService: require('./log-service')
};
To use these three package separately, you should add all of them in npm, or use github with a proper url:
"dependencies": {
"awesome-service": "awesome-service"
"http-service": "awesome-service#http-service#1.0.0",
"log-service": "git+https://github.com/yourAccount/awesome-service/log-service.git"
}

Importing typescript from external node modules

I want to split my application into different node modules and have a main module which builds all other modules as well and I want to use typescript with es6 modules.
Here is my planned project structure:
main
node_modules
dep-a
dep-b
framework
interfaces
IComponent.ts
dep-a
components
test.ts
node_modules
framework
index.ts
dep-b
node_modules
framework
I want to be able to define interfaces in framework which can be consumed in dep-a, dep-b and main.
How do I set up this correctly? Can I compile everything from my main-module? Do I need to create different bundles for framework, dep-a, ... and another typing file? What is the best approach for this?
I already set up some test files and folders and used npm link to link the dependencies and webpack to bundle the files and I am always running into issues with files not being found:
error TS2307: Cannot find module 'framework/interfaces/IComponent'
and
Module not found: Error: Cannot resolve 'file' or 'directory' ./components/test
TL;DR generate declarations for the modules using declaration: true in tsconfig.json and specify the file for your generated typings in the typings entry of the package.json file
framework
Use a tsconfig file similar to this:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"declaration": true,
"noImplicitAny": true,
"removeComments": true,
"outDir": "dist",
...
},
"files": [
...
]
}
The important bit is declaration: true which will generate internal declarations in the dist directory
Assuming there is an index.ts file which (re)exports all the interesting parts of framework, create a package.json file with a main and typings entry pointing to, respectively, the generated js and the generated declaration, i.e.
{
"name": "framework",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
...
}
Commit this module to a git repo, say bitbucket at : "https://myUser#bitbucket.org/myUser/framework.git"
dep-a
in package.json create a dependency to framework
{
"dependencies": {
"framework": "https://myUser#bitbucket.org/myUser/framework.git"
},
}
That is it.
import * from 'framework'
will pull the dependency with the typings, automatically
Obviously, it is possible to do with dep-a what was done with framework i.e. generate the declarations, update package.json and use dep-a as a module with embedded typings in main
note: a file URL will do in package.json/dependencies if you do not want go to via an external git repo
What arrived in TypeScript 1.6 is typings property in package.json module. You can check the relevant issue on GitHub.
So assuming you want to create separate modules ( dep-a, framework ). You can do the following :
main.ts // (1)
package.json // (2)
node_modules/
dep_a/
index.js // (3)
index.d.ts // (4)
package.json // (5)
node_modules/
framework/
index.js // (6)
index.d.ts // (7)
package.json // (8)
So let's see what you have in your files :
//(1) main.ts
import * as depA from "depA";
console.log(depA({ a : true, b : 2 }) === true) // true;
//(2) package.json
{
name: "main",
dependencies: {
"dep_a" : "0.0.1"
}
...
}
For depA
//(3) dep_a/index.js
module.exports = function a(options) { return true; };
//(4) dep_a/index.d.ts;
import * as framework from "framework";
export interface IDepA extends framework.IFramework {
a : boolean
}
export default function a(options: IDepA) : boolean;
//(5) dep_a/package.json
{
name: "dep_a",
dependencies: {
"framework" : "0.0.1"
},
...
typings : "index.d.ts" // < Magic happens here
}
For framework
//(6) dep_a/node_modules/framework/index.js
module.exports = true // we need index.js here, but we will only use definition file
//(7) dep_a/node_modules/framework/index.d.ts;
export interface IFramework {
b : number;
}
//(8) dep_a/node_modules/framework/package.json
{
name: "framework"
...
typings : "index.d.ts"
}
What I don't include in this answer ( for clarity ) is another compilation phase, so you could actually write the modules ( dep_a, framework ) with typescript and then compile them to index.js before you use them.
For a detailed explanation and some background also see: https://medium.com/#mweststrate/how-to-create-strongly-typed-npm-modules-1e1bda23a7f4

Resources