Skip to content

Commit

Permalink
feat: adds noInstall option for Yarn packager (#421)
Browse files Browse the repository at this point in the history
* feat: adds noInstall option for Yarn packager

* feat: set default value for packagerOptions.noInstall in index
  • Loading branch information
chrishutchinson authored Jan 6, 2023
1 parent aa932b6 commit c1ddff3
Show file tree
Hide file tree
Showing 10 changed files with 41 additions and 14 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ The following `esbuild` options are automatically set.
| Option | Description | Default |
| --------- | ----------------------------------------------------------------------------------------------------- | ----------- |
| `scripts` | A string or array of scripts to be executed, currently only supports 'scripts' for npm, pnpm and yarn | `undefined` |
| `noInstall` | [Yarn only] A boolean that deactivates the install step | `false` |

#### Watch Options

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,4 @@
"engines": {
"node": ">=14.18.0"
}
}
}
4 changes: 3 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,13 +270,15 @@ class EsbuildServerlessPlugin implements ServerlessPlugin {
exclude: ['aws-sdk'],
nativeZip: false,
packager: 'npm',
packagerOptions: {
noInstall: false,
},
installExtraArgs: [],
watch: {
pattern: './**/*.(js|ts)',
ignore: [WORK_FOLDER, 'dist', 'node_modules', BUILD_FOLDER],
},
keepOutputDirectory: false,
packagerOptions: {},
platform: 'node',
outputFileExtension: '.js',
};
Expand Down
2 changes: 1 addition & 1 deletion src/pack-externals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ export async function packExternalModules(this: EsbuildServerlessPlugin) {
assert(packageJsonPath, 'packageJsonPath is not defined');

// Determine and create packager
const packager = await getPackager.call(this, this.buildOptions.packager);
const packager = await getPackager.call(this, this.buildOptions.packager, this.buildOptions.packagerOptions);

// Fetch needed original package.json sections
const sectionNames = packager.copyPackageSectionNames;
Expand Down
2 changes: 1 addition & 1 deletion src/pack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ export async function pack(this: EsbuildServerlessPlugin) {
assertIsString(this.buildOptions?.packager, 'packager is not a string');

// 2) If individually is set, we'll optimize files and zip per-function
const packager = await getPackager.call(this, this.buildOptions.packager);
const packager = await getPackager.call(this, this.buildOptions.packager, this.buildOptions.packagerOptions);

// get a list of every function bundle
const { buildResults } = this;
Expand Down
16 changes: 10 additions & 6 deletions src/packagers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import { memoizeWith } from 'ramda';
import { isPackagerId } from '../type-predicate';

import type EsbuildServerlessPlugin from '../index';
import type { PackagerId } from '../types';
import type { PackagerId, PackagerOptions } from '../types';
import type { Packager } from './packager';

const packagerFactories: Record<PackagerId, () => Promise<Packager>> = {
const packagerFactories: Record<PackagerId, (packgerOptions: PackagerOptions) => Promise<Packager>> = {
async npm() {
const { NPM } = await import('./npm');

Expand All @@ -24,10 +24,10 @@ const packagerFactories: Record<PackagerId, () => Promise<Packager>> = {

return new Pnpm();
},
async yarn() {
async yarn(packgerOptions) {
const { Yarn } = await import('./yarn');

return new Yarn();
return new Yarn(packgerOptions);
},
};

Expand All @@ -40,7 +40,11 @@ const packagerFactories: Record<PackagerId, () => Promise<Packager>> = {
*/
export const getPackager = memoizeWith(
(packagerId) => packagerId,
async function (this: EsbuildServerlessPlugin, packagerId: PackagerId): Promise<Packager> {
async function (
this: EsbuildServerlessPlugin,
packagerId: PackagerId,
packgerOptions: PackagerOptions
): Promise<Packager> {
this.log.debug(`Trying to create packager: ${packagerId}`);

if (!isPackagerId(packagerId)) {
Expand All @@ -49,7 +53,7 @@ export const getPackager = memoizeWith(
throw new this.serverless.classes.Error(`Could not find packager '${packagerId}'`);
}

const packager = await packagerFactories[packagerId]();
const packager = await packagerFactories[packagerId](packgerOptions);

this.log.debug(`Packager created: ${packagerId}`);

Expand Down
12 changes: 11 additions & 1 deletion src/packagers/yarn.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { any, isEmpty, reduce, replace, split, startsWith } from 'ramda';
import { satisfies } from 'semver';

import type { DependenciesResult, DependencyMap } from '../types';
import type { DependenciesResult, DependencyMap, PackagerOptions } from '../types';
import { SpawnError, spawnProcess } from '../utils';
import type { Packager } from './packager';
import { isString } from '../helper';
Expand Down Expand Up @@ -39,6 +39,12 @@ const getNameAndVersion = (name: string): { name: string; version: string } => {
* ignoreScripts (false) - Do not execute scripts during install
*/
export class Yarn implements Packager {
private packagerOptions: PackagerOptions;

constructor(packagerOptions: PackagerOptions) {
this.packagerOptions = packagerOptions;
}

get lockfileName() {
return 'yarn.lock';
}
Expand Down Expand Up @@ -220,6 +226,10 @@ export class Yarn implements Packager {
}

async install(cwd: string, extraArgs: Array<string>, useLockfile = true) {
if (this.packagerOptions.noInstall) {
return;
}

const command = /^win/.test(process.platform) ? 'yarn.cmd' : 'yarn';

const args = useLockfile
Expand Down
2 changes: 1 addition & 1 deletion src/tests/packagers/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ describe('getPackager()', () => {
} as unknown as EsbuildServerlessPlugin;

it('Returns a Packager instance', async () => {
const npm = await getPackager.call(mockPlugin, 'npm');
const npm = await getPackager.call(mockPlugin, 'npm', {});

expect(npm).toEqual(expect.any(Object));
});
Expand Down
11 changes: 10 additions & 1 deletion src/tests/packagers/yarn.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import * as utils from '../../utils';

jest.mock('process');
describe('Yarn Packager', () => {
const yarn = new Yarn();
const yarn = new Yarn({});
const path = './';

let spawnSpy: jest.SpyInstance;
Expand Down Expand Up @@ -231,4 +231,13 @@ describe('Yarn Packager', () => {

expect(result).toStrictEqual(expectedResult);
});

it('should skip install if the noInstall option is true', async () => {
const yarnWithoutInstall = new Yarn({
noInstall: true,
});

await expect(yarnWithoutInstall.install(path, [], false)).resolves.toBeUndefined();
expect(spawnSpy).toBeCalledTimes(0);
});
});
3 changes: 2 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface WatchConfiguration {

export interface PackagerOptions {
scripts?: string[] | string;
noInstall?: boolean;
}

interface NodeExternalsOptions {
Expand All @@ -24,14 +25,14 @@ export type EsbuildOptions = Omit<BuildOptions, 'watch' | 'plugins'>;
export interface Configuration extends EsbuildOptions {
concurrency?: number;
packager: PackagerId;
packagerOptions: PackagerOptions;
packagePath: string;
exclude: '*' | string[];
nativeZip: boolean;
watch: WatchConfiguration;
installExtraArgs: string[];
plugins?: string | Plugin[];
keepOutputDirectory?: boolean;
packagerOptions?: PackagerOptions;
disableIncremental?: boolean;
outputWorkFolder?: string;
outputBuildFolder?: string;
Expand Down

0 comments on commit c1ddff3

Please sign in to comment.