29

I want to automatically copy certain files from an npm package to user's local directory after running

npm install my-package

I can get them installed by declaring "files" inside package.json. The problem is --- the files are not put in the local directory. So I need to run postinstall script.

But now I don't know where the package is installed (maybe higher up the directory tree), so how can I reliably access the files and copy them to the local directory via the script?

(By local directory I mean --- from where I run npm install my-package as user consuming the package.)

UPDATE. It seems the postinstall script runs as npm owned process with home directory being node_modules/my-package, so I still don't know how to access user's home directory other than with naive ../../.

Dmitri Zaitsev
  • 13,548
  • 11
  • 76
  • 110

4 Answers4

17

Since npm 3.4 you can use the $INIT_CWD envar: https://blog.npmjs.org/post/164504728630/v540-2017-08-22

When running lifecycle scripts, INIT_CWD will now contain the original working directory that npm was executed from.

To fix you issue add to your postinstall script in package.json the following:

  "scripts": {
    "postinstall": "cp fileYouWantToCopy $INIT_CWD",
  },
jordins
  • 390
  • 1
  • 5
  • 12
11

After a lot of searching I found this works cross platform

"scripts":
  "postinstall": "node ./post-install.js",

// post-install.js

/**
 * Script to run after npm install
 *
 * Copy selected files to user's directory
 */

'use strict'

var gentlyCopy = require('gently-copy')

var filesToCopy = ['.my-env-file', 'demo']

// User's local directory
var userPath = process.env.INIT_CWD

// Moving files to user's local directory
gentlyCopy(filesToCopy, userPath)
David Bradshaw
  • 11,859
  • 3
  • 41
  • 70
3

var cwd = require('path').resolve();

Note: If the arguments to resolve have zero-length strings then the current working directory will be used instead of them.

from https://nodejs.org/api/path.html

hexagoncode
  • 141
  • 2
  • 6
  • I am still confused which is `cwd` inside the `postinstall` script --- the local directory or where the installed files are sitting? – Dmitri Zaitsev Jan 14 '16 at 08:05
  • `cwd` is always where a program was executed from. If you need a path to current js file from a file itself there are `__filename` and `__dirname` variables available in every file. – hexagoncode Jan 15 '16 at 04:29
  • I need path to the local directory, see last line in my question to define what I mean. – Dmitri Zaitsev Jan 15 '16 at 08:07
  • Unfortunately this method does not solve the problem. As the `node` scripts are executed from their package directory under `node_modules`, their `cwd` will never point to the local directory from where the user ran `npm install`. – Dmitri Zaitsev Apr 11 '17 at 09:12
2

I would use shellscript/bash

-package.json

"scripts":
  "postinstall": "./postinstall.sh",

-postinstall.sh

#!/bin/bash

# go to YOUR_NEEDED_DIRECTORY .e.g "dist" or $INIT_CWD/dist
cd YOUR_NEEDED_DIRECTORY

# copy each file/dir to user dir(~/)
for node in `ls`
do
  cp -R $node ~/$node
done

Don't forget to!

chmod +x postinstall.sh
Graham P Heath
  • 7,009
  • 3
  • 31
  • 45
nothing-special-here
  • 11,230
  • 13
  • 64
  • 94