I have two npm projects, one is a Gatsby project called web-project
and another one is Express project called server-project
.
This is the file structure of the projects:
- projects
- web-project
- public
- package.json
- server-project
- package.json
- public
If I run command npm run build
in web-project/package.json
, I would like to generate build files for web-project, delete content in folder server-project/public
and copy content from web-project/public
to server-project/public
.
I tried to use shx, which is installed locally in web-project
, but it doesn’t work. Gatsby generates build files, but shx doesn’t copy them.
web-project/package.json
"scripts": {
"build": "gatsby build && (shx find ../server-project/public -type f -delete && shx cp -R public/* ../server-project/public)"
...
},
npm debug log file:
0 info it worked if it ends with ok
1 verbose cli [
1 verbose cli '/usr/local/Cellar/node/12.1.0/bin/node',
1 verbose cli '/usr/local/bin/npm',
1 verbose cli 'run',
1 verbose cli 'build'
1 verbose cli ]
2 info using [email protected]
3 info using [email protected]
4 verbose run-script [ 'prebuild', 'build', 'postbuild' ]
5 info lifecycle [email protected]~prebuild: [email protected]
6 info lifecycle [email protected]~build: [email protected]
7 verbose lifecycle [email protected]~build: unsafe-perm in lifecycle true
8 verbose lifecycle [email protected]~build: PATH: /usr/local/lib/node_modules/npm/node_modules/npm-lifecycle/node-gyp-bin:/Users/and/devel/tau/web-project/node_modules/.bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
9 verbose lifecycle [email protected]~build: CWD: /Users/and/devel/tau/web-project
10 silly lifecycle [email protected]~build: Args: [
10 silly lifecycle '-c',
10 silly lifecycle 'gatsby build && (shx find ../server-project/public -type ' +
10 silly lifecycle 'f -delete && shx cp -R public/* ../server-project/public)'
10 silly lifecycle ]
11 silly lifecycle [email protected]~build: Returned: code: 1 signal: null
12 info lifecycle [email protected]~build: Failed to exec build script
13 verbose stack Error: [email protected] build: `gatsby build && (shx find ../server-project/public -type f -delete && shx cp -R public/* ../server-project/public)`
13 verbose stack Exit status 1
13 verbose stack at EventEmitter.<anonymous> (/usr/local/lib/node_modules/npm/node_modules/npm-lifecycle/index.js:301:16)
13 verbose stack at EventEmitter.emit (events.js:196:13)
13 verbose stack at ChildProcess.<anonymous> (/usr/local/lib/node_modules/npm/node_modules/npm-lifecycle/lib/spawn.js:55:14)
13 verbose stack at ChildProcess.emit (events.js:196:13)
13 verbose stack at maybeClose (internal/child_process.js:1000:16)
13 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:267:5)
14 verbose pkgid [email protected]
15 verbose cwd /Users/and/devel/tau/web-project
16 verbose Darwin 18.7.0
17 verbose argv "/usr/local/Cellar/node/12.1.0/bin/node" "/usr/local/bin/npm" "run" "build"
18 verbose node v12.1.0
19 verbose npm v6.9.0
20 error code ELIFECYCLE
21 error errno 1
22 error [email protected] build: `gatsby build && (shx find ../server-project/public -type f -delete && shx cp -R public/* ../server-project/public)`
22 error Exit status 1
23 error Failed at the [email protected] build script.
23 error This is probably not a problem with npm. There is likely additional logging output above.
24 verbose exit [ 1, true ]
I tried to change build command to only copy files from one folder to another folder:
web-project/package.json
{
"name": "tau",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"develop": "gatsby develop",
"build": "shx cp -R public/* ../server-project/public",
"serve": "gatsby serve",
"start": "node server.js",
"gh-pages": "gatsby build --prefix-paths && gh-pages -d public",
"lint": "eslint src --fix",
"dev": "(shx --silent rm -rf public .cache || shx true) && gatsby develop",
"server": "cross-env NODE_ENV=development DEBUG=api nodemon server.js"
},
"author": "PI",
"license": "MIT",
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.25",
"@fortawesome/free-brands-svg-icons": "^5.12.0",
"@fortawesome/free-solid-svg-icons": "^5.11.2",
"@fortawesome/react-fontawesome": "^0.1.7",
"@kunukn/react-collapse": "1",
"@material-ui/core": "^4.9.5",
"@popperjs/core": "^2.3.3",
"add": "^2.0.6",
"axios": "^0.19.0",
"basic-auth": "^2.0.1",
"bootstrap": "4.2.1",
"chart.js": "^2.9.3",
"d3-node": "^2.2.1",
"debug": "^4.1.1",
"font-awesome": "4.7.0",
"framer-motion": "^1.10.3",
"gatsby": "^2.18.12",
"gatsby-plugin-canonical-urls": "^2.3.0",
"gatsby-plugin-dark-mode": "^1.1.0",
"gatsby-source-prismic-graphql": "^3.5.0",
"gatsby-transformer-remark": "^2.6.53",
"lodash.get": "^4.4.2",
"lodash.groupby": "^4.6.0",
"lodash.pickby": "^4.6.0",
"marked": "^0.8.0",
"moment": "^2.24.0",
"prismic-reactjs": "^1.3.1",
"prop-types": "^15.7.2",
"react-chartjs-2": "^2.8.0",
"react-collapsible": "^2.6.3",
"react-d3-components": "^0.9.1",
"react-d3-library": "^1.1.8",
"react-headroom": "^3.0.0",
"react-helmet": "^5.2.0",
"react-lazyload": "^2.6.5",
"react-moment": "^0.9.6",
"react-onclickout": "^2.0.8",
"react-popper": "^2.2.3",
"react-popper-tooltip": "^2.11.1",
"react-responsive": "^8.0.1",
"react-scroll-to": "^3.0.0-beta.3",
"react-sidebar": "^3.0.2",
"react-slick": "^0.25.2",
"react-svg-donuts": "^1.0.0",
"react-telegram-embed": "^0.0.10",
"react-toastify": "^5.4.1",
"react-twitter-embed": "^3.0.3",
"react-window": "^1.8.5",
"reactstrap": "^8.4.1",
"slick-carousel": "^1.8.1",
"underscore": "^1.9.1",
"yarn": "^1.21.1"
},
"devDependencies": {
"@prototype-interactive/eslint-config": "^0.1.1",
"autoprefixer": "^9.4.4",
"dotenv": "^8.2.0",
"eslint": "^5.12.0",
"gatsby-plugin-google-analytics": "^2.3.0",
"gatsby-plugin-postcss": "^2.0.2",
"gatsby-plugin-postcss-sass": "^1.0.22",
"gatsby-plugin-react-helmet": "^3.0.5",
"gatsby-plugin-sass": "^2.0.7",
"gatsby-source-filesystem": "^2.2.2",
"gatsby-transformer-json": "^2.1.7",
"gh-pages": "^2.0.1",
"husky": "^1.3.1",
"prettier": "^1.15.3",
"pretty-quick": "^1.8.0",
"react": "^16.7.0",
"react-dom": "^16.7.0",
"shx": "^0.3.2",
"svg-sprite-loader": "^4.1.3"
},
"repository": {
"type": "git",
"url": "git+https://github.com/PI/gatsby-react-boilerplate.git"
},
"bugs": {
"url": "https://github.com/PI/gatsby-react-boilerplate/issues"
},
"homepage": "https://github.com/PI/gatsby-react-boilerplate#readme"
}
npm debug log file:
0 info it worked if it ends with ok
1 verbose cli [
1 verbose cli '/usr/local/Cellar/node/12.1.0/bin/node',
1 verbose cli '/usr/local/bin/npm',
1 verbose cli 'run',
1 verbose cli 'build'
1 verbose cli ]
2 info using [email protected]
3 info using [email protected]
4 verbose run-script [ 'prebuild', 'build', 'postbuild' ]
5 info lifecycle [email protected]~prebuild: [email protected]
6 info lifecycle [email protected]~build: [email protected]
7 verbose lifecycle [email protected]~build: unsafe-perm in lifecycle true
8 verbose lifecycle [email protected]~build: PATH: /usr/local/lib/node_modules/npm/node_modules/npm-lifecycle/node-gyp-bin:/Users/and/devel/tau/web-project/node_modules/.bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
9 verbose lifecycle [email protected]~build: CWD: /Users/and/devel/tau/web-project
10 silly lifecycle [email protected]~build: Args: [ '-c', 'shx cp -R public/* ../web-project-project/public' ]
11 silly lifecycle [email protected]~build: Returned: code: 1 signal: null
12 info lifecycle [email protected]~build: Failed to exec build script
13 verbose stack Error: [email protected] build: `shx cp -R public/* ../web-project-project/public`
13 verbose stack Exit status 1
13 verbose stack at EventEmitter.<anonymous> (/usr/local/lib/node_modules/npm/node_modules/npm-lifecycle/index.js:301:16)
13 verbose stack at EventEmitter.emit (events.js:196:13)
13 verbose stack at ChildProcess.<anonymous> (/usr/local/lib/node_modules/npm/node_modules/npm-lifecycle/lib/spawn.js:55:14)
13 verbose stack at ChildProcess.emit (events.js:196:13)
13 verbose stack at maybeClose (internal/child_process.js:1000:16)
13 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:267:5)
14 verbose pkgid [email protected]
15 verbose cwd /Users/and/devel/tau/web-project
16 verbose Darwin 18.7.0
17 verbose argv "/usr/local/Cellar/node/12.1.0/bin/node" "/usr/local/bin/npm" "run" "build"
18 verbose node v12.1.0
19 verbose npm v6.9.0
20 error code ELIFECYCLE
21 error errno 1
22 error [email protected] build: `shx cp -R public/* ../web-project-project/public`
22 error Exit status 1
23 error Failed at the [email protected] build script.
23 error This is probably not a problem with npm. There is likely additional logging output above.
24 verbose exit [ 1, true ]
3
Answers
You can drop the wildcard from
shx cp -R public/* ../server-project/public
, as the recursive flag will pick up everything in the source directory. This should get you what you are after –It looks like you are already using
find
in your build system. I leverage tar and find heavily in some of the build systems I maintain, and this works well for me. tar handles a really wide variety of edge cases very nicely, since it was originally written as a backup utility.in tar, – is the filename that means stdin or stdout, -T specifies the list of files to backup, and -C specifies its working directory. This lets you glue a bunch of stuff together with the pipeline and some pretty cool stuff done. For example,
This will preserve ownership, group membership, permissions, symlinks, directory structure, the whole nine yards for you. Even filenames with spaces won’t mess it up. 🙂
The main issue exists in this part:
The
-type f
flag is not supported inshx
(see issue #177). Presumably, the-delete
flag is also not supported.Consider replacing that part with a node.js script that does the following:
find
method.forEach()
.forEach
callback checks whether it’s a file and deletes accordingly.For instance, putting it altogether into a single npm script named
build
:Notes:
Your attempted usage of
find ../server-project/public -type f -delete
in your OP implies that your intention is to delete all files (only) from../server-project/public
(n levels deep) – but don’t delete any folders in../server-project/public
(again n levels deep). This is what thenode -e "..."
command in the aforementioned example replicates.The nodejs command line option
-e
is utilized to evaluate the inline Javascript, which is essentially this:As you can see, a combination of the Logical NOT (
!
) operator, thefs.statSync
method andisDirectory()
are utilized to ascertain whether the pathname is a file and not a directory/folder.The file is deleted using the shelljs
rm
method.The globstar (
*
) in your finalshx cp -R ...
command, and the parentheses(...)
encasing the compound commands, have been omitted.