Skip to content

Commit

Permalink
fix: add "postinstall" script to workaround npm install/npm pack
Browse files Browse the repository at this point in the history
…behaviour with ignorefiles
  • Loading branch information
jdbruijn committed Oct 28, 2023
1 parent ab19040 commit 62fce82
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 0 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"build": "tsc",
"format": "prettier --ignore-path .gitignore --write \"**/*.{vue,css,less,scss,html,htm,json,md,markdown,yml,yaml}\" --log-level warn",
"format:check": "prettier --ignore-path .gitignore --check \"**/*.{vue,css,less,scss,html,htm,json,md,markdown,yml,yaml}\" --log-level warn",
"postinstall": "node ./dist/scripts/postinstall.js",
"lint": "npm run format:check && xo",
"lint:fix": "npm run format && xo --fix",
"prepare": "husky install .github/husky",
Expand Down
3 changes: 3 additions & 0 deletions src/content/package.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ test(sets, 'author', options.author, '"author" option');
test('does not include "bin"', (t) => {
t.is(packageJson().bin, undefined);
});
test('does not include "postinstall" script', (t) => {
t.is(packageJson().scripts.postinstall, undefined);
});
test('does not include "dependencies"', (t) => {
t.is(packageJson().dependencies, undefined);
});
Expand Down
2 changes: 2 additions & 0 deletions src/content/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const schema = z
lint: z.literal('npm run format:check && xo'),
// eslint-disable-next-line @typescript-eslint/naming-convention
'lint:fix': z.literal('npm run format && xo --fix'),
postinstall: z.string().optional(),
prepare: z.literal('husky install .github/husky'),
test: z.string().min(1),
})
Expand Down Expand Up @@ -86,6 +87,7 @@ class Package extends File {
};
delete this._package.bin;
delete this._package.dependencies;
delete this._package.scripts.postinstall;
if (this._options.public) {
delete this._package.private;
} else {
Expand Down
36 changes: 36 additions & 0 deletions src/scripts/postinstall.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import fs from 'node:fs';
import {stub, match, type SinonStub, restore} from 'sinon';
import anyTest, {type TestFn} from 'ava';
import {gitIgnore, npmIgnore, postinstall} from './postinstall.js';

const test = anyTest as TestFn<{existsSync: SinonStub; renameSync: SinonStub}>;
test.beforeEach((t) => {
t.context.existsSync = stub(fs, 'existsSync');
t.context.renameSync = stub(fs, 'renameSync');
});
test.afterEach.always(() => {
restore();
});

const gitToNpm = '".gitignore" to ".npmignore"';
test.serial(`renames ${gitToNpm}`, (t) => {
t.context.existsSync.withArgs(gitIgnore).returns(false);
t.context.existsSync.withArgs(npmIgnore).returns(true);
postinstall();
t.is(t.context.renameSync.callCount, 1);
t.deepEqual(t.context.renameSync.firstCall.args, [npmIgnore, gitIgnore]);
});

test.serial(`does not rename ${gitToNpm} when ".gitignore" exists`, (t) => {
t.context.existsSync.withArgs(gitIgnore).returns(true);
t.context.existsSync.withArgs(npmIgnore).returns(true);
postinstall();
t.is(t.context.renameSync.callCount, 0);
});

test.serial(`does not rename ${gitToNpm} without ".npmignore"`, (t) => {
t.context.existsSync.withArgs(gitIgnore).returns(false);
t.context.existsSync.withArgs(npmIgnore).returns(false);
postinstall();
t.is(t.context.renameSync.callCount, 0);
});
32 changes: 32 additions & 0 deletions src/scripts/postinstall.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {join} from 'node:path';
import fs from 'node:fs';
import {fileURLToPath} from 'node:url';
import {argv} from 'node:process';
import rootPath from '../root-path.js';

const gitIgnore = join(rootPath, '.gitignore');
const npmIgnore = join(rootPath, '.npmignore');

/**
* Workaround for [Rename `.gitignore` to `.npmignore` in package if no
* `.npmignore` found](https://github.com/npm/npm/issues/1862) and ['npm pack'/
* `publish` option to not rename or keep a copy of `.gitignore` files](
* https://github.com/npm/npm/issues/7252) issues. With npm v9 or newer, the
* `npm pack` includes the `.gitignore` in the tarball and `npm install` renames
* the file to `.npmignore`. This script simply reverts that rename if it has
* occurred.
*/
function postinstall(): void {
if (fs.existsSync(npmIgnore) && !fs.existsSync(gitIgnore)) {
fs.renameSync(npmIgnore, gitIgnore);
}
}

if (
import.meta.url.startsWith('file:') &&
fileURLToPath(import.meta.url) === argv.at(1)
) {
postinstall();
}

export {gitIgnore, npmIgnore, postinstall};

0 comments on commit 62fce82

Please sign in to comment.