'import the current package export by the package.json name

I'm interested to know if there's a convention that allows a person to test the expected usage of a package from within the package. Consider the following package.json:

{
   "name": "@place/fn",
   "version: "1.0.0"
}

From within this very package, I'd like to have a test.js file, with exactly following code:

import mainThing, { anotherThing } from '@place/fn';

Is this possible with the right directory structure or package.json configuration? I'm also fine with CommonJS syntax if that would work better.



Solution 1:[1]

Ok, found an answer on this but there's a ton of other related things I found in the process that could probably help others.

First, now I understand what I wanted to do is install the current package as a local dependency. That can be done in the package.json using the following syntax found in this answer.

{
  "name": "@place/fn",
  "dependencies": {
    "@place/fn": "file:./"
  }
}

Now, I can run npm i to install that change and code the following test file:

import mainThing, { anotherThing } from '@place/fn';

When running the test file, the import will act as if it was installed into another package; better mimicking the intended use.


Another thing I discovered is that you can alias packages installed from npm using the syntax found in this answer.

"dependencies": {
  "case-1.5.3": "npm:case@^1.5.3",
  "kool": "npm:case@^1.6.1"
}

Which then allows you to do the following:

let Case = require('case-1.5.3');
let Kool = require('kool');

And finally, another thing I found is that Node@13 allows for a new key on the package.json which maps directories found in this answer. There are other packages (like module-alias) that do something similar with the big difference being the installed solutions (ie: module-alias) only work from within the package you are working with. It seems like the new exports key on package.json will do the mapping for use in other packages.

// ./node_modules/es-module-package/package.json
{
  "name": "es-module-package",
  "exports": {
    "./my/": "./src/js/lib/my/"
  }
}

import thing from 'es-module-package/my/thing.js';
// Loads ./node_modules/es-module-package/src/js/lib/my/thing.js

Ultimately the purpose of all of this was to test that the style of syntaxes I provide outside the package could be tested from within the package instead of installing into another package and testing there. Now I can check that a common lodash import syntax works for my package.

import get from 'lodash/get'

(I wish I knew what the terminology was for requiring a clean, perhaps aliased, path of a package instead of destructuring the main export.)

Solution 2:[2]

To access the main export of a package from withing the package itself, add a main entry point export to package.json:

{
  "name": "@place/fn",
  "version: "1.0.0",
  "exports": {
    ".": "./index.js"
  }
}

Replace ./index.js with the path to the main module.

Then, in test.js, you can import it with the expected syntax:

import mainThing, { anotherThing } from '@place/fn';

Be careful that when the exports field is defined, all subpaths of the package are no longer available to external importers unless explicitly declared in exports. Typically, you will want at least package.json to be exportable beside the main module:

  "exports": {
    ".": "./index.js",
    "./package.json": "./package.json"
  }

Solution 3:[3]

When you import a package, it's up to the package.json file to tell you where to go... Say you had the following file structure

project
    demo
        demo-index.js
    dist
        project.cjs.js
        project.es.js
        project.umd.js
    src
        index.js
    package.json

You want to code your package inside src, build it (using something like Vite or Bili) and then inside your demo folder, see if the built files (inside dist) work as intended.

So your package.json should have:

{
    "name": "project",
    "version": "1.0.0",
    "main": "dist/project.cjs.js",
    "module": "dist/project.es.js",
    ...
}

Now, inside demo/demo-index.js you could just import from ../src/index.js and use the uncompiled version.

What you can also do is import from your project root directory and get the compiled version:

// demo/demo-index.js
import Project from "../";

This will import via the package.json file and give you the file listed under "module", i.e. dist/project.es.js.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Donnie D'Amato
Solution 2 GOTO 0
Solution 3 floodlitworld