Is there a way to have 2 package.json files, one for publishing and one for the project itself? - npm

What I want to achieve is to have 2 folders, one containing the source code(modules, controllers, service classes, etc.) and one folder containing DTO classes. The pkg folder would be what would be provided if the project is set as a dependency in another project. The file structure goes as such:
pkg
│ └── package files . . .
src
│ └── project files . . .
├── package.pkg.json
└── package.src.json
// package.pkg.json
{
"name": "#example/service-a"
"version": "1.0.0",
"files": [
"dist/pkg"
],
"main": "dist/pkg/index.js",
"types": "dist/pkg/index.d.ts"
}
// package.src.json
{
"name": "#example/service-a"
"version": "1.0.0",
"main": "dist/src/main.js",
"dependencies": {
"some-dependency": "1.0.0",
"another-dependency": "1.0.0"
}
}
The main reason I want to separate the package.json into two is because when the service is downloaded as a package it also install the production dependencies of the service.
If we're able to do this then, for example, if we had service A and service B, where B would request some information from service A, there wouldn't be a conjoining dependency which would expose what service A could provide to service B.
Is there a way to achieve this?

Related

When using npm workspaces, how to force a package to be installed in the relative node_modules?

Here are some related questions:
When using yarn workspaces, how to force a package to be installed in the relative node_modules?
NPM 7 Workspaces - Multiple node_modules?
Should I have to use no-hoist for all packages in a monorepo with react-native-web?
I'm using npm workspaces to organise multiple packages. The issue is that my main package don't have its dependency's(which is also one of the workspaces) source code in local node_modules. I know the dependency is installed in root node_modules, the thing is that I need to visit it by relative path from the main package.
Here is the project structure after running npm install in root dir:
root
├── package.json -> { "workspaces": ["packages/*"] }
├── node_modules
│ ├── dependency-A
│ ├── dependency-B
└── packages
├── main-package
├── dependency-A
└── dependency-B
package.json in root dir:
{
"workspaces": [
"packages/main-package",
"packages/dependency-A",
"packages/dependency-B"
]
}
package.json in "packages/main-package":
{
"dependencies": {
"dependency-A": "0.1.0",
"dependency-B": "0.1.0"
}
}
webpack.config.js in "packages/main-package":
{
plugins: [
new CopyWebpackPlugin({
patterns: [
{
from: "node_modules/dependency-A/media",
to: "static/dependency-A-media",
},
],
}),
new CopyWebpackPlugin({
patterns: [
{
context: "node_modules/dependency-B/dist",
from: "research-data.json",
},
],
}),
]
}
When I run webapck in main-package, the error message is:
ERROR in unable to locate '/Users/trumangao/myApp/packages/main-package/node_modules/dependency-A/media' glob
ERROR in unable to locate '/Users/trumangao/myApp/packages/main-package/node_modules/dependency-B/dist/research-data.json' glob
I'm wondering what is the best practice to resolve such question? The option "nohoist" of Yarn inspired me but I can't find it in npm. I also tried to run install in package dir but it will break their symlink. How could I install dependencies of each package in their local node_modules while maintain their links like lerna#4?
Tried versions:
node.js#16.13.0
npm#8.1.0
&
node.js#18.14.0
npm#9.3.1
Hope I've made myself plain with my poor English LoL, thanks a lot.

How to install an executable in yarn workspace that is specified in a package inside of it?

Following folder structure and files are given:
.
├── package.json
└── scripts
├── hello-word.js
└── package.json
// package.json
{
"name": "yarn-bin",
"version": "1.0.0",
"private": true,
"license": "ISC",
"workspaces": [
"scripts"
]
}
// scripts/package.json
{
"name": "#yarn-bin/scripts",
"version": "1.0.0",
"license": "ISC",
"bin": {
"hello-world": "./hello-world.js"
}
}
// scripts/hello-world.js
#!/usr/bin/env -S npx node
console.log("Hello World")
This is a very simple yarn workspace setup where an executable is specified in a workspace package ("bin" in scripts/package.json).
Executing ./hello-world.js works just fine (with prior chmod +x hello-world.js).
Question
Is it possible to install this executable in the workspace itself?
(To break it down: I would like to execute the script from anywhere in the workspace e.g. with npx hello-world)
Like I said in the comments what you got here is almost complete.
You did have a typo in your file name but I assume that's a typo that happened while you copied this over to SO.
I did change the hash bang to make sure you run this via node.
You cannot run this via npx as npx will go online and look through the registry.
.
├── package.json
└── scripts
├── hello-world.js # not "hello-word.js"
└── package.json
Root package.json:
{
"name": "yarn-bin",
"version": "1.0.0",
"private": true,
"license": "ISC",
"scripts": {
"hello": "yarn hello-world"
},
"workspaces": [
"scripts"
]
}
scripts/package.json
{
"name": "#yarn-bin/scripts",
"version": "1.0.0",
"license": "ISC",
"bin": {
"hello-world": "./hello-world.js"
}
}
And script/hello-world.js
#!/usr/bin/env node
console.log("Hello World")
With that setup running yarn hello in the root folder will yield:
$ yarn hello
yarn run v1.22.10
$ yarn hello-world
$ /path/to/folder/node_modules/.bin/hello-world
Hello World
✨ Done in 0.25s.
While I added an npm script into the root package.json you can also execute bins via just running yarn hello-world anywhere from within your project.

Use local folder as package.json repository

Is there a way to setup a local folder to be used as package.json repository. The goal is to be able to use the cloud repository (https://www.npmjs.com/package) but the modules which are not found there to be searched and installed from a local folder.
Example package.json:
{
"name": "myproject",
"version": "0.0.0",
"dependencies": {
"standard-npm-module": "1.0.0", // installed from https://www.npmjs.com/package/standard-npm-module
"local-module": "1.0.0", // installed from local folder because it wont be found in https://www.npmjs.com/package/local-module
}
}
PS Yarn or npm any solution will be OK.
you can use local paths. for instance, see the package.json snippet below.
{
"name": "baz",
"dependencies": {
"bar": "file:../foo/bar"
}
}
you can also leverage npm, for instance:
npm install --save /path/to/module

Go to definition not working on my project (vue & sass file) [visual-studio-code]

I am disappointed on two points by developing a Nuxt project on vscode.
On vscode my jsconfig.js is the default one :
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"~/*": ["./*"],
"#/*": ["./*"],
"~~/*": ["./*"],
"##/*": ["./*"]
}
},
"exclude": ["node_modules", ".nuxt", "dist"]
}
It's working on vue file for autocompletion to import some components for example (with ctrl+space)
But impossible to go to definition next with cmd+click. I do not understand why and this is really annoying.
I can't post image (need 10 reputation), but here is my import on vue file (with no definition found for ...)
import PldFooter from '#/components/Footer';
Other point, I use sass files on assests folder. Compilation working well but I cannot access by cmd+click to the file from node_modules. Here is an example of import :
#import "~bulma/sass/base/helpers.sass";
==> No definition found for helpers.sass
Thank you for your help,
Ben.
Have you opened multiple folders (projects) in a window?
I'm not sure whether your issue the same as me. I got an issue "Go to Definition not working" in Visual Studio Code when I opened multiples folders (projects) and I resolved.
I have used the plugin Vetur to support the .vue file.
There are 2 ways which work well:
Open only one project in a window
You can open multiple projects in a window but the project you want to "Go to Definition" works well which must be the first project in the folder tree in the EXPLORER tab.
It seems the plugin Vetur picks up the first project in multiple projects to be the root folder.
My file tsconfig.json
{
...
"compilerOptions": {
"baseUrl": "./",
"paths": {
"#/*": ["src/*"],
}
},
"exclude": ["node_modules", "dist"]
...
}
Reference:
https://github.com/vuejs/vetur/issues/423#issuecomment-405415204
I apologize if my answer which cannot help you.
According to the Vetur setup guide:
If you are using Webpack's alias or TypeScript's path mapping to resolve components, you need to update Vetur's tsconfig.json or jsconfig.json
For example:
└── src
├── components
│ ├── a.vue
│ └── b.vue
├── containers
│ └── index.vue
├── index.js
└── jsconfig.json
jsconfig.json:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"components/*": [
"src/components/*"
]
}
}
}
index.vue
import a from 'components/a.vue'
import b from 'components/b.vue'
It solved the problem in my case.

What are phantomChildren in package.json?

When I install a module, a list of phantomChildren appears in the package.json file. What are phantomChildren?
I didn't find official documentation for npm package phantomChildren. But encountered some other explanation: https://rushjs.io/pages/advanced/phantom_deps/. It is about rast, but explains behavior of npm dependencies pretty well.
For example library A might import definitions from libraries B and C, but then B and C can both import from D, which creates a “diamond dependency” between these four packages.
A “phantom dependency” occurs when a project uses a package that is
not defined in its package.json file.
Some live example:
my-library/package.json
{
"name": "my-library",
"version": "1.0.0",
"main": "lib/index.js",
"dependencies": {
"minimatch": "^3.0.4"
},
"devDependencies": {
"rimraf": "^2.6.2"
}
}
my-library/lib/index.js
var minimatch = require("minimatch")
var expand = require("brace-expansion"); // ???
var glob = require("glob") // ???
Wait a sec – two of these libraries are not declared as dependencies
in the package.json file. How is this working at all!? It turns out
that brace-expansion is a dependency of minimatch, and glob is a
dependency of rimraf. During installation, NPM has flattened their
folders to be under my-library/node_modules. The NodeJS require()
function finds them there because it probes for folders without
considering the package.json files at all.
To summarize: if package uses dependencies of it's own dependencies, it can be treated as phantomChildren. Package doesn't have such dependencies directly but uses it from other places.