Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

npm package export path definitions

I'm generating my first set of npm packages to support a react-native environment. I am looking to configure the packages in such a way that the contents is intrinsically organized and can be easily distinguished by import statements on the client end.

Given 4 function definitions defined in my npm package (package name: super-cool-animals):

snakes.ts

export function Boa() {}
export function Anaconda() {}

birds.ts

export function Pigeon() {}
export function Hawk() {}

I would like the consumer of the library to be able to install the library:

npm install --save super-cool-animals

And then import them as such:

import { Boa, Anaconda } from 'super-cool-animals/snakes'
import { Pigeon, Hawk } from 'super-cool-animals/birds'

Pigeon();  // direct access to the function!

I'm having a hard time identifying the proper mechanism to achieve this, and I believe I've seen this mechanism in some environments (ie. angular)

I've seen some suggestions allowing you to combine them into a single variable as a for instance by using index.ts files:

snakes/index.ts

export * from './snakes.ts'

birds/index.ts

export * from './birds.ts

./index.ts

import * as Birds from './birds'
import * as Snakes from './snakes'
export { Birds, Snakes}

But this has an ugly end result, you now have to reference the container to get at the function:

Consumer of the library:

import { Birds } from 'super-cool-animals';

Birds.Pigeon();

Any assistance is appreciated. Thank you.

like image 822
Glorifundel Avatar asked Mar 08 '19 20:03

Glorifundel


1 Answers

Turns out the answer was pretty simple, lets take our example hypothetical where you want each category broken out by animal type, but you only want one package to be installed.

> super-cool-animals
    > snakes
        anaconda.js
        boa.js
        package.json
        index.js
    > birds
        hawk.js
        pigeon.js
        package.json
        index.js
    package.json
    readme.md
    index.js

each index file simply does an export of the files or functions of interest at that level

index.js

import * as Birds from './birds'
import * as Snakes from './snakes'
export { Birds, Snakes}

snakes/index.js

export * from './anaconda.js'
export * from './boa.js'

birds/index.js

export * from './hawk.js'
export * from './pigeon.js'

Now moving on to the package.json files: the top level package file describes any dependencies, author, name of the library to be used in importing etc. The animal - specific - package.json files simply describe the name of the library to import.

package.json

{
  "name": "super-cool-animals",
  "version": "1.0.0",
  "description": "Super cool animal library",
  "main": "index.js",
  "author": "Kevin Quinn <[email protected]>",
  "license": "MIT",
  "dependencies": {},
  "peerDependencies": {},
  "devDependencies": {}
}

The package files found at the lower level (birds and snakes folder) are simply describing the available relative path.

snakes/package.json

{
  "name": "super-cool-animals/snakes",
  "main": "index.js"
}

birds/package.json

{
  "name": "super-cool-animals/birds",
  "main": "index.js"
}

With all that defined, you can now install the npm package, and the client can nicely define their imports:

import { Hawk } from 'super-cool-animals/birds';
const SomeBird = Hawk();

Not sure if this is the best solution, but it seemed to function for me, I hope it is helpful to someone, and if there is a better or cleaner solution please post it and I will be happy to accept a better answer, or update my own answer.

like image 119
Glorifundel Avatar answered Nov 15 '22 09:11

Glorifundel