Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support to custom package.json install and watch. #489

Merged
merged 1 commit into from
Sep 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 57 additions & 33 deletions src/environment-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,59 @@ export default class EnvironmentBase extends EventEmitter implements BaseEnviron
}, match);
}

/**
* Watch for package.json and queue package manager install task.
*/
public watchForPackageManagerInstall({
cwd,
queueTask,
installTask,
}: {
cwd?: string;
queueTask?: boolean;
installTask?: (nodePackageManager: string | undefined, defaultTask: () => Promise<boolean>) => void | Promise<void>;
} = {}) {
if (cwd && !installTask) {
throw new Error(`installTask is required when using a custom cwd`);
}

const npmCwd = cwd ?? this.cwd;

const queueInstallTask = () => {
this.queueTask(
'install',
async () => {
if (this.compatibilityMode === 'v4') {
debug('Running in generator < 5 compatibility. Package manager install is done by the generator.');
return;
}

const { adapter, sharedFs: memFs } = this;
const { skipInstall, nodePackageManager } = this.options;
await packageManagerInstallTask({
adapter,
memFs,
packageJsonLocation: npmCwd,
skipInstall,
nodePackageManager,
customInstallTask: installTask ?? this.composedStore.customInstallTask,
});
},
{ once: `package manager install ${npmCwd}` },
);
};

this.sharedFs.on('change', file => {
if (file === join(npmCwd, 'package.json')) {
queueInstallTask();
}
});

if (queueTask) {
queueInstallTask();
}
}

/**
* Start Environment queue
* @param {Object} options - Conflicter options.
Expand All @@ -751,7 +804,10 @@ export default class EnvironmentBase extends EventEmitter implements BaseEnviron
this.conflicterOptions.cwd = this.logCwd;

this.queueCommit();
this.queuePackageManagerInstall();
this.queueTask('install', () => {
// Postpone watchForPackageManagerInstall to install priority since env's cwd can be changed by generators
this.watchForPackageManagerInstall({ queueTask: true });
});

/*
* Listen to errors and reject if emmited.
Expand Down Expand Up @@ -834,38 +890,6 @@ export default class EnvironmentBase extends EventEmitter implements BaseEnviron
queueCommit();
}

/**
* Queue environment's package manager install task.
*/
protected queuePackageManagerInstall() {
this.queueTask(
'install',
async () => {
if (this.compatibilityMode === 'v4') {
debug('Running in generator < 5 compatibility. Package manager install is done by the generator.');
return;
}

const { adapter, sharedFs: memFs } = this;
const { skipInstall, nodePackageManager } = this.options;
const { customInstallTask } = this.composedStore;
await packageManagerInstallTask({
adapter,
memFs,
packageJsonLocation: this.cwd,
skipInstall,
nodePackageManager,
customInstallTask,
});

memFs.once('change', file => {
if (file === join(this.cwd, 'package.json')) this.queuePackageManagerInstall();
});
},
{ once: 'package manager install' },
);
}

/**
* Registers a specific `generator` to this environment. This generator is stored under
* provided namespace, or a default namespace format if none if available.
Expand Down
54 changes: 53 additions & 1 deletion test/generator-features.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,6 @@ describe('environment (generator-features)', () => {
}

packageJsonTask() {
console.log('foo');
this.packageJson.set({ name: 'foo' });
}
},
Expand All @@ -223,5 +222,58 @@ describe('environment (generator-features)', () => {
assert.equal(typeof customInstallTask.getCall(0).args[1], 'function');
});
});

describe('with function customInstallTask and custom path', () => {
let runContext;
let customInstallTask;
let installTask;
beforeEach(async () => {
customInstallTask = sinon.stub();
installTask = (pm, defaultTask) => defaultTask(pm);
runContext = helpers
.create('custom-install', undefined, { createEnv: getCreateEnv(BasicEnvironment) })
.withOptions({ skipInstall: false })
.withGenerators([
[
class extends FeaturesGenerator {
constructor(args, options) {
super(args, options, { customInstallTask });
this.destinationRoot(this.destinationPath('foo'));
this.env.watchForPackageManagerInstall({
cwd: this.destinationPath(),
installTask,
});
}

packageJsonTask() {
this.packageJson.set({ name: 'foo' });
}
},
{ namespace: 'custom-install:app' },
],
]);
await runContext.run();
});

it('should not call customInstallTask', () => {
assert.equal(customInstallTask.callCount, 0, 'should not have been called');
});

it('should call packageManagerInstallTask twice', () => {
expect(packageManagerInstallTask).toHaveBeenCalledTimes(2);
expect(packageManagerInstallTask).toHaveBeenNthCalledWith(
2,
expect.objectContaining({
customInstallTask,
}),
);
expect(packageManagerInstallTask).toHaveBeenNthCalledWith(
1,
expect.objectContaining({
customInstallTask: installTask,
}),
);
});
});
});
});
Loading