How to structure a simple yarn package for local sharing - javascript

I want to create a simple yarn package that can be installed by multiple local yarn projects using yarn add link:/path/to/package. Imagine the package of the package to be shared looks like this
├── package.json
├── tsconfig.json
└── src
├── generated
│   ├── abc.js
│   ├── abc.d.ts
│   └── def.js
│   └── def.d.ts
My goal is that abc and def should be accessible like this
import * from "myPackage/abc"
Currently if I install the above package with yarn add link:/path/to/package then I have to do
import * from "myPackage/src/generated/abc"
I'm a rookie on making typescript packages so forgive me. Can someone point me in the right direction here?
I've tried the suggestion here but it doesn't make a difference.

So it seems I need to set exports and typesVersions in package.json
"exports": {
"./": "./src/generated/"
},
"typesVersions": {
"*": {
"abc": [
"./src/generated/abc.d.ts"
],
"def": [
"./src/generated/def.d.ts"
],
}
},

Related

What is the proper way to bundle assets with an NPM module?

I have a library, let's call it my-lib. The packaged code contains some JS and type declarations for that code in /dist, as well as a number of SVG files in /assets:
my-lib
├── assets
│   ├── a.svg
│   ├── b.svg
├── dist
│   ├── index.d.ts
│   ├── index.mjs
│   ├── index.umd.js
├── LICENSE
├── package.json
My intention is to have the JS modules exported on the root of the package, my-lib, with the assets importable from my-lib/assets (when using an appropriate plugin for the user's framework and bundler, E.G. vite-plugin-svgr for React+Vite). This seems to work by default in a create-react-app project with Webpack using import { ReactComponent as A } from "my-lib/assets/a.svg"; and the right declaration file to appease TypeScript, but in a Vite project ends up throwing errors:
[vite] Internal server error: Missing "./assets/a.svg" export in "my-lib" package
The important bits of my package.json:
// package.json
{
"main": "./dist/index.umd.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"files": [
"./dist",
"./assets"
],
// ...rest
}
Are there specific fields to use for non-JS assets in package.json? Is this simply an issue with bundler config?
Minimum reproducible example

Is it possible for vscode to auto-import paths in a non-relative way when using app-module-path library?

I'm using app-module-path, for resolving require statements without having to explicitly provide the relative path to the module. But vscode cant recognize the module since it's not relative path. I had tried using jsconfig by following this thread. I created the jsconfig in the root of my project. But the path resolution done by vscode conflicted with app-module-path, since vscode adds a server/ prefix before all paths. What changes should I make to jsconfig.json inorder to make it work with app-module-path?
Context
.
├── jsconfig.json
├── package.json
├── server
│   ├── app.js --------> here I set the app-module-path
│   ├── controllers
│   ├── helpers
│   │   ├── email
│   │   │   ├── fetch.js
│   │   └── urlparser.js
│   └── services
│      └── github
│      └── index.js-> i want import "helpers/email/fetch" from here, not "server/helpers/email/fetch"
└── yarn.lock
With app-module-path set in app.js in base of server, I am able to do the following from server/services/github/index.js:-
const {emailFetch} = require("helpers/email/fetch"); // Note: I cant use the "server/" prefix before "helpers" since app-module-path will lead to error
const {emailFetch} = require("server/helpers/email/fetch"); // This is how vscode auto-imports
This is how I have registered the app-module-path in app.js:-
require("app-module-path").addPath(__dirname);
With the following jsconfig.json, vscode gives intellisense, signature help, go to definition etc even if the path is helpers/email/fetch(without server/ prefix). But how can i make vscode auto-import or fix the require statements, in way such that it doesn't add server prefix before all import statements? Should I use some vscode-extension for doing this job?
{
"compilerOptions": {
"target": "ES6",
"allowSyntheticDefaultImports": true,
"module": "commonjs",
"baseUrl": ".",
"paths": {
"*": [
"*",
"server/*"
]
}
},
"include": [
"server/**/*.js"
]
}
Just posting my answer too over here, so that someone else finds it useful. Currently I have made it to work by changing baseUrl into "server" and removing "server/*" from paths, in jsconfig.json. With this I get correct auto-imports + change in import paths while I move files around too. Do post your answers if you know to do this is in a better way. Cheers!

Import module from npm to javascript file

I am trying to import showdown module in my home.js file.
The GitHub installation guide tells me to run npm install showdown and presents a simple example of using the module, as such:
var converter = new showdown.Converter(),
text = '# hello, markdown!',
html = converter.makeHtml(text);
I have installed the module using that command, but now I m not sure how to use this module inside my home.js situated under app/static/js path. I tried using require but it s not a solution since
it does not exist in the browser/client-side JavaScript.
Project Tree
├── app
│   ├── __init__.py
│   ├── routes.py
│   └── static
│   ├── js
│   │   └── home.js
│   └── styles
│   ├── main.css
│   └── normalize.css
├── config.py
├── package-lock.json
├── package.json
├── run.py
└── node_modules
Javascript file home.js
const textEditor = document.querySelector('.text-editor')
const preview = document.querySelector('.preview')
var converter = new showdown.Converter() // <- error fires here
console.log('text-editor', textEditor)
console.log('preview', preview)
textEditor.addEventListener('keyup', event=>{
const {value} = event.target;
const html = converter.makeHtml(value)
preview.innerHtml = html
});
Question: How do I import this showdown inside my index.js so that I can be able to use every function of the module?
You can use Browserify for this.
It allows you to use require() for requiring node_modules.
Here are the steps in which you can use the showdown npm package in your project.
Install browserify globally using: npm install -g browserify
Use require() to include your npm modules in your project.
const showdown = require('showdown');
Prepare a bundle for accessing require() function in your home.js usnig browserify:
browserify js/home.js > bundle.js
Include the bundle.js file created in your code using the script tag.
<script src="bundle.js"></script>
Here are some resources that explain how to use browserify in more detail:
https://medium.com/jeremy-keeshin/hello-world-for-javascript-with-npm-modules-in-the-browser-6020f82d1072
https://github.com/browserify/browserify#usage
Additionally, this article also explains well how to choose the tool for compiling your front-end applications based on your requirements. And it contains detailed information about how to use browserify

Unable to import node_module packages in Jupyter notebook extension

I'm trying to import an external javascript module (e.g., log4js). However, I have issues with loading in javascript packages specified in my package.json into my Jupyter extension. My project setup looks something like this:
├── logger/
│ └── __init__.py
│ └── static/
│ └── main.js
├── node_modules/
│ ├── log4js/
│ └── ...
└── pacakge.json
│
└── setup.py
This is what my main.js looks like:
define([
'base/js/namespace',
'jquery',
'log4js'
], function (Jupyter,$,log4js) {
"use strict";
function load_ipython_extension() {
console.log("Loaded Logger")
// var log4js = require("log4js");
var logger = log4js.getLogger();
}
return {
load_ipython_extension: load_ipython_extension
};
});
I am able to import the jquery variable into $ successfully, however, any other package that is installed inside node_module can not be loaded in and results in the same Error: Script error.
Any idea on how to appropriately place the node_module packages into the scope of the Jupyter extension would be very helpful, thanks!
From the informations you gave here I can guess that you need to setup paths to libraries from node_modules. As you can see you have 404 errors in the browser which means that RequireJS is trying to load the modules but from wrong paths. You can read more about paths on official page: https://requirejs.org/docs/api.html#config-paths

Using a library sibling folder container for shared packages

I have many applications in a mono git repository. I'd like to share some libraries between my applications.
Here is is my directory structure:
.
├── libs
│   └── messages
| ├── package.json
| ├── src
| ├── tsconfig.json
| └── ...all other good things for a library
├── main
│   ├── config
│   ├── dist
│   ├── node_modules
│   ├── package.json
│   ├── package-lock.json
│   ├── src
│   └── tsconfig.json
├── README.md
└── server
├── main.ts
├── node_modules
├── package.json
├── package-lock.json
├── setupEnvVars.js
├── src
└── tsconfig.json
I want to add the library "message" to my project "main" so I tried to add it this way:
{
"name": "me",
"version": "1.0.0",
"main": "index.js",
"private": true,
"dependencies": {
"#me/messages": "../libs/messages/"
}
}
I'm stuck because it doesn't work (but doesn't throw errors either). Can you help me? Thanks!
I'd need to see more about the content of each package.json files and the project overall, but here are some elements which may help you get a goo structure that would accomplish what you have set yourself to do.
If you really want to go the proper monorepo way, you might want to have a look at https://github.com/lerna/lerna which will work well enough for Node 8 and up (e.g. auto-symlink of file dependencies, which is useful during development).
Another way to solve this issue in TypeScript is using paths:
tsconfig.json
{
"compilerOptions": {
// path
"baseUrl": ".",
"paths": {
"#lib/*": ["./*"],
"#shared/*": ["../shared/*"]
}
}
However, depending on how you build and run your projects, paths are sometimes not processed properly. You may need to use tsconfig-paths if you run your project using ts-node, or tsconfig-paths-webpack-plugin if you are using TypeScript as part of a webpack project.

Categories