How can I import a component directly instead of from the root index file? - node.js

I wrote myself a small package which I use to share different React components between my projects.
The "exports" field in my package.json looks like this:
Since this is a TypeScript project, the transpiled .js in the output directory are specified below.
"exports": {
".": "./lib/index.js"
}
My index.ts file looks like this:
export * from "./Grids";
Then inside my Grids folder i have another index.ts file with the following content:
export * from "./UniversalGrid";
And finally inside the UniversalGrid folder, there is another index.ts file, in which the actual components is getting exported:
export * from "./UniversalGrid";
Now when I want to use the component in my app, I am shown two import suggestions, namely:
import {UniversalGrid} from "#privateComponents/react-components"
and
import {UniversalGrid} from "#privateComponents/react-components/lib/Grids/UniversalGrid"
The first approach (import from /react-components), works without problems.
However, with the second possible import statement (import from /react-components/lib/Grids/UniversalGrid) the following occurs:
Module not found: Error: Package path ./lib/Grids/UniversalGrid is not exported from package C:\Users\<user>\WebstormProjects\PKD\node_modules\#privateComponents\react-components
However, this way the component can be imported without any problems, and also when I select "Jump to definition" I am led to the correct file.
Now I have two questions, first, why is this happening?
And second, how can I import/export my components separately.
Say: Grid1 should be imported from /Grids/Grid1.
Grid 2 should be imported from /Grids/Grid2.
But none of the modules should be imported directly from the /Grids folder.
Thank you very much in advance!

Just dont export Grid in Grids/index.ts, change your transpiled to this
"exports": {
".": "./lib/index.js",
"./Grids/Grid1": "./lib/Grids/Grid1/index.js",
"./Grids/Grid2": "./lib/Grids/Grid2/index.js"
...
},
Now you can import Grid1 from /Grids/Grid1 not from /Grids

Related

NodeJS `"imports"` field on `package.json` for more than 1 file-tree level

I try to convert some references on my node projects to Node 19. In particular, the feature "imports" on the file package.json made me wonder on how to import files with an alias.
Example: For a project with source folder src with folders fruits and vegetables, I add the configuration on json content first-order key-values.
"imports": {
"#fruits/*": "./src/fruits/*.js",
"#fruits/*.js": "./src/fruits/*.js",
"#vegetables/*": "./src/vegetables/*.js",
"#vegetables/*.js": "./src/vegetables/*.js",
},
With that, I am able to use import * from "#fruits/fruits.js" or import * from "#vegetables/vegetables.js"
By experience, I learned that I cannot user it more than 1 level of folder-tree level. It means, in case there is still a folder src/fruits/pseudo, I am unable to use import * from "#fruits/pseudo/pseudofruits.js". Is this correct or should I be able to import pseudofruits from the alias?
Your understanding is correct that you can only import files one level deep with configuration you have. One workaround in this situation is to use the relative path instead like:
import * as pseudofruits from "../../fruits/pseudo/pseudofruits.js";

Create own class

created a new project in expressjs. I want to create my own class. So I created a file MyClass.js in /routes/.
class MyClass {
constructor() {
}
}
export default MyClass;
And in /routes/index.js i added:
import MyClass from './MyClass';
And I have an error:
import MyClass from './MyClass;
^^^^^^
SyntaxError: Cannot use import statement outside a module
[...]
What I'm doing wrong?
Your project is not set up properly to interpret the file that has the error as an ESM module file. It is, instead, being interpreted as a CommonJS module (where you use require(), not import) which is the nodejs default.
There are a number of ways to tell nodejs that your file is supposed to be an ESM module.
You can give it a file extension of .mjs.
You can add "type": "module" to your package.json file.
You can use the --input-type=module command line argument when starting node.js if this file is your top level file you're executing.
See nodejs doc here on this subject.
FYI, you could just switch to the CommonJS syntax of using require() and module.exports instead of import and export, but I assume what you really want to do is to tell nodejs that you want to use ESM modules so you can use the more modern import and export syntax.
Well first of all to export your class you suppose to use exports or module.export
and to import it you suppose to use require('') not import.
Those features are only available with .mjs or if you will setup babel though soome es6 features are yet to land in

Importing node modules once for whole project

Scenario
So, I have initialised a Node project with npm. I have setup my package.json accordingly. I am using typescript, so I have also setup tsconfig.json.
I have a few dependencies (npm packages) that I will need to use multiple times in multiple files of my project.
index.ts is the root of my project. I can import these libraries in index.js and other files also.
Problem
Is there any way to include or import these libraries in the project only once so that I can use them in any file of the project without having to import a single thing anywhere.
I tried searching for various ways to do this using -
CommonJS module syntax, NodeJS module syntax, global modules - but none of it can provide me the way I want it.
For Ex -
Most of the answers or solutions I got were like this
Export all the libraries through a single file
import abc from 'abc';
import xyz from 'xyz';
module.exports = {
abc, xyz
};
Use these libraries in other files like
import modules from 'src/modules.ts'
var wantSome = modules.abc.getSome();
But, this still has an overhead of importing modules file and accessing it like modules.abc.
Do we have any way to make these imports available globally through out the project.
P.S. - This scenario is somewhat similar to ngModules in Angular 2+, where we can import whatever we want inside ngModules and it is then available to all the components under that module.
Doing this is going to cause you all sorts of problems in the long run.
you'll end up with one monolithic file containing all your exports, which will become onerous to maintain
if you decide to modularise your code, it will be more difficult since you won't explicitly know which modules a file uses
if you were able to include to the point where you simply use the modules with no reference, code clarity will suffer
name clashes might occur
The best I believe you'll get in node is to declare all the includes in a single module, and then destructure within your own file.
import abc from 'abc';
import xyz from 'xyz';
module.exports = {
abc, xyz
};
Then
import modules from 'src/modules.ts'
{ abc: { getSome } } = modules
But I strongly suggest using the standard patterns for importing. It will make your code much cleaner and easier to maintain
N/B - Thats a bad way to design your app.
In node, you can set global variables via the "global" or "GLOBAL" object:
You could import all your dependencies in your app entry file, and store them in a Global variable
index.js
import abc from 'abc';
import xyz from 'xyz';
global.abc = abc
global.xyz = xyz
someotherfile.js
//access abc import
global.abc
Export all the libraries through a single file
import abc from 'abc';
import xyz from 'xyz';
module.exports = {
abc, xyz
};
Use these libraries in other files like
import {abc, xyz} from 'src/modules.ts'
var wantSome = abc.getSome();

Change routes realative in React Js

I have these import:
import {Input, InputTxtCenter} from '../../../components/forms/input/input.js';
import {ButtonRed} from '../../../components/buttons/';
import {TxtCenter} from '../../../components/misc/texts/texts.js';
and I want to transform these routes into something similar to this
import {ButtonRed, ButtonWarning} from 'buttons';
import {TxtCenter} from 'misc/text';
import {TxtCenter} from 'forms/input';
that is, that the system knows that importing will always be from the "components" folder
Is it possible to do this?
Without having to create the component in node_modules?
I think this less of a React question, and more of a module resolution/aliasing one.
I assume that you are using some tool like babel, in which you can try babel-plugin-module-resolver.
The main idea is to define aliases in your .babelrc file so that you can avoid keeping track of relative directory structure when importing.
You can create .env file containing NODE_PATH=src if you're using create-react-app.
I recommend you to start any project using CRA with possible eject option if you really require customization.

Python import scheme

I am trying to write a python library, where some files depend on other files, for example:
I have folder structure:
../libname
../libname/core.py
../libname/supplementary1.py
../libname/supplementary2.py
../libname/__init__.py
where libname is where I import from.
the core.py file begins with:
import supplementary1
import supplementary2
...some code...
and this works fine, if I test it in the main of the core.py
Let's say I want to use libname as library in my project. My folder structure is then:
./libname
./main.py
where main.py calls functions from core.py, which in fact need functions from supplementary1 and supplementary2.
Currently, it throws me an error, saying there is no supplementary1, if I try (in main.py)
from core.py import function1
My question is, how do I import files from my library then? I mean one option would be to copy all the code from e.g. supplementary1 to the core.py, but I wish to maintain my code elegantly separated, if possible.
So in other words, how does one import a file, which already imports some files from a local library?
Thank you very much.
In import ... and from ... import ... you need to write not the filename, but module name. Instead of core.py you should say libname.core, meaning "module core, from package libname" (libname will be searched in all module paths, that normally includes the directory of the script you've started, i.e. where your main.py is).
tl;dr: a simple answer to your question is to write from libname.core import function1 instead.
Also, I'd suggest to use relative imports and instead of import supplementary1 write from . import supplementary1 - here, from . means "from the current package - where this file (module) resides in".
Consider reading Python documentation on modules - there are a lot of examples and explanations there.

Resources