From a0d7f88d9b8fec370d5e24f41ff2f827f4e73d8f Mon Sep 17 00:00:00 2001 From: chrishutchinson Date: Wed, 4 Jan 2023 12:32:48 +0000 Subject: [PATCH 1/2] feat: adds noInstall option for Yarn packager --- README.md | 1 + package.json | 2 +- src/pack-externals.ts | 2 +- src/packagers/index.ts | 16 ++++++++++------ src/packagers/yarn.ts | 14 +++++++++++++- src/tests/packagers/yarn.test.ts | 9 +++++++++ src/types.ts | 1 + 7 files changed, 36 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 7cac9c78..637347f8 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/package.json b/package.json index 3f18d704..ca24a69f 100644 --- a/package.json +++ b/package.json @@ -107,4 +107,4 @@ "engines": { "node": ">=14.18.0" } -} +} \ No newline at end of file diff --git a/src/pack-externals.ts b/src/pack-externals.ts index d3950902..222e51c8 100644 --- a/src/pack-externals.ts +++ b/src/pack-externals.ts @@ -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; diff --git a/src/packagers/index.ts b/src/packagers/index.ts index 7070caa8..d962e30b 100644 --- a/src/packagers/index.ts +++ b/src/packagers/index.ts @@ -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 Promise> = { +const packagerFactories: Record Promise> = { async npm() { const { NPM } = await import('./npm'); @@ -24,10 +24,10 @@ const packagerFactories: Record Promise> = { return new Pnpm(); }, - async yarn() { + async yarn(packgerOptions) { const { Yarn } = await import('./yarn'); - return new Yarn(); + return new Yarn(packgerOptions); }, }; @@ -40,7 +40,11 @@ const packagerFactories: Record Promise> = { */ export const getPackager = memoizeWith( (packagerId) => packagerId, - async function (this: EsbuildServerlessPlugin, packagerId: PackagerId): Promise { + async function ( + this: EsbuildServerlessPlugin, + packagerId: PackagerId, + packgerOptions?: PackagerOptions + ): Promise { this.log.debug(`Trying to create packager: ${packagerId}`); if (!isPackagerId(packagerId)) { @@ -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}`); diff --git a/src/packagers/yarn.ts b/src/packagers/yarn.ts index 89d89f3f..68a34b79 100644 --- a/src/packagers/yarn.ts +++ b/src/packagers/yarn.ts @@ -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'; @@ -39,6 +39,14 @@ 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 || { + noInstall: false, + }; + } + get lockfileName() { return 'yarn.lock'; } @@ -220,6 +228,10 @@ export class Yarn implements Packager { } async install(cwd: string, extraArgs: Array, useLockfile = true) { + if (this.packagerOptions.noInstall) { + return; + } + const command = /^win/.test(process.platform) ? 'yarn.cmd' : 'yarn'; const args = useLockfile diff --git a/src/tests/packagers/yarn.test.ts b/src/tests/packagers/yarn.test.ts index 8cba3607..1df57706 100644 --- a/src/tests/packagers/yarn.test.ts +++ b/src/tests/packagers/yarn.test.ts @@ -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); + }); }); diff --git a/src/types.ts b/src/types.ts index c3ce6ea8..c0406c1a 100644 --- a/src/types.ts +++ b/src/types.ts @@ -13,6 +13,7 @@ export interface WatchConfiguration { export interface PackagerOptions { scripts?: string[] | string; + noInstall?: boolean; } interface NodeExternalsOptions { From 4b527a9497c43e9cf88796479bd3a9cc0d8825ca Mon Sep 17 00:00:00 2001 From: chrishutchinson Date: Fri, 6 Jan 2023 17:34:14 +0000 Subject: [PATCH 2/2] feat: set default value for packagerOptions.noInstall in index --- src/index.ts | 4 +++- src/pack.ts | 2 +- src/packagers/index.ts | 4 ++-- src/packagers/yarn.ts | 6 ++---- src/tests/packagers/index.test.ts | 2 +- src/tests/packagers/yarn.test.ts | 2 +- src/types.ts | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/index.ts b/src/index.ts index d0d40b09..c0ea0bcf 100644 --- a/src/index.ts +++ b/src/index.ts @@ -250,13 +250,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', }; diff --git a/src/pack.ts b/src/pack.ts index c88bdafa..43101635 100644 --- a/src/pack.ts +++ b/src/pack.ts @@ -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; diff --git a/src/packagers/index.ts b/src/packagers/index.ts index d962e30b..e3aa1759 100644 --- a/src/packagers/index.ts +++ b/src/packagers/index.ts @@ -13,7 +13,7 @@ import type EsbuildServerlessPlugin from '../index'; import type { PackagerId, PackagerOptions } from '../types'; import type { Packager } from './packager'; -const packagerFactories: Record Promise> = { +const packagerFactories: Record Promise> = { async npm() { const { NPM } = await import('./npm'); @@ -43,7 +43,7 @@ export const getPackager = memoizeWith( async function ( this: EsbuildServerlessPlugin, packagerId: PackagerId, - packgerOptions?: PackagerOptions + packgerOptions: PackagerOptions ): Promise { this.log.debug(`Trying to create packager: ${packagerId}`); diff --git a/src/packagers/yarn.ts b/src/packagers/yarn.ts index 68a34b79..ed0a5bd4 100644 --- a/src/packagers/yarn.ts +++ b/src/packagers/yarn.ts @@ -41,10 +41,8 @@ const getNameAndVersion = (name: string): { name: string; version: string } => { export class Yarn implements Packager { private packagerOptions: PackagerOptions; - constructor(packagerOptions?: PackagerOptions) { - this.packagerOptions = packagerOptions || { - noInstall: false, - }; + constructor(packagerOptions: PackagerOptions) { + this.packagerOptions = packagerOptions; } get lockfileName() { diff --git a/src/tests/packagers/index.test.ts b/src/tests/packagers/index.test.ts index 7f929f2d..d52e8079 100644 --- a/src/tests/packagers/index.test.ts +++ b/src/tests/packagers/index.test.ts @@ -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)); }); diff --git a/src/tests/packagers/yarn.test.ts b/src/tests/packagers/yarn.test.ts index 1df57706..68101516 100644 --- a/src/tests/packagers/yarn.test.ts +++ b/src/tests/packagers/yarn.test.ts @@ -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; diff --git a/src/types.ts b/src/types.ts index c0406c1a..4cc65a65 100644 --- a/src/types.ts +++ b/src/types.ts @@ -25,6 +25,7 @@ export type EsbuildOptions = Omit; export interface Configuration extends EsbuildOptions { concurrency?: number; packager: PackagerId; + packagerOptions: PackagerOptions; packagePath: string; exclude: '*' | string[]; nativeZip: boolean; @@ -32,7 +33,6 @@ export interface Configuration extends EsbuildOptions { installExtraArgs: string[]; plugins?: string | Plugin[]; keepOutputDirectory?: boolean; - packagerOptions?: PackagerOptions; disableIncremental?: boolean; outputWorkFolder?: string; outputBuildFolder?: string;