Skip to content

Commit

Permalink
Merge pull request #303 from tinchoz49/tinchoz49/improve-copy-patterns
Browse files Browse the repository at this point in the history
feat: add watch for copy patterns
  • Loading branch information
floydspace authored May 28, 2022
2 parents fdafcbe + b09ef53 commit 1cb893f
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 26 deletions.
1 change: 1 addition & 0 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
root: true
env:
node: true
ignorePatterns:
Expand Down
13 changes: 7 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"typescript": "^4.0.3"
},
"dependencies": {
"anymatch": "^3.1.2",
"archiver": "^5.3.0",
"bestzip": "^2.2.0",
"chokidar": "^3.4.3",
Expand Down
121 changes: 101 additions & 20 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { concat, always, memoizeWith, mergeRight } from 'ramda';
import Serverless from 'serverless';
import ServerlessPlugin from 'serverless/classes/Plugin';
import chokidar from 'chokidar';
import anymatch from 'anymatch';

import {
buildServerlessV3LoggerFromLegacyLogger,
Expand All @@ -25,6 +26,22 @@ import {
ReturnPluginsFn,
} from './types';

function updateFile(op: string, src: string, dest: string) {
if (['add', 'change', 'addDir'].includes(op)) {
fs.copySync(src, dest, {
dereference: true,
errorOnExist: false,
preserveTimestamps: true,
recursive: true,
});
return;
}

if (['unlink', 'unlinkDir'].includes(op)) {
fs.removeSync(dest);
}
}

class EsbuildServerlessPlugin implements ServerlessPlugin {
serviceDirPath: string;
outputWorkFolder: string;
Expand Down Expand Up @@ -172,6 +189,37 @@ class EsbuildServerlessPlugin implements ServerlessPlugin {
return plugins;
}

get packagePatterns() {
const { service } = this.serverless;
const patterns = [];
const ignored = [];

for (const pattern of service.package.patterns) {
if (pattern.startsWith('!')) {
ignored.push(pattern.slice(1));
} else {
patterns.push(pattern);
}
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
for (const [_, fn] of Object.entries(this.functions)) {
if (fn.package.patterns.length === 0) {
continue;
}

for (const pattern of fn.package.patterns) {
if (pattern.startsWith('!')) {
ignored.push(pattern.slice(1));
} else {
patterns.push(pattern);
}
}
}

return { patterns, ignored };
}

private getCachedOptions = memoizeWith(always('cache'), () => {
const DEFAULT_BUILD_OPTIONS: Partial<Configuration> = {
concurrency: Infinity,
Expand Down Expand Up @@ -214,14 +262,28 @@ class EsbuildServerlessPlugin implements ServerlessPlugin {
}

async watch(): Promise<void> {
let defaultPatterns = this.buildOptions.watch.pattern;

const options = {
ignored: this.buildOptions.watch.ignore,
ignored: this.buildOptions.watch.ignore || [],
awaitWriteFinish: true,
ignoreInitial: true,
};

chokidar.watch(this.buildOptions.watch.pattern, options).on('all', () =>
if (!Array.isArray(defaultPatterns)) {
defaultPatterns = [defaultPatterns];
}

if (!Array.isArray(options.ignored)) {
options.ignored = [options.ignored];
}

const { patterns, ignored } = this.packagePatterns;
defaultPatterns = [...defaultPatterns, ...patterns];
options.ignored = [...options.ignored, ...ignored];
chokidar.watch(defaultPatterns, options).on('all', (eventName, srcPath) =>
this.bundle(true)
.then(() => this.updateFile(eventName, srcPath))
.then(() => this.log.verbose('Watching files for changes...'))
.catch(() => this.log.error('Bundle error, waiting for a file change to reload...'))
);
Expand Down Expand Up @@ -257,6 +319,41 @@ class EsbuildServerlessPlugin implements ServerlessPlugin {
}
}

async updateFile(op: string, filename: string) {
const { service } = this.serverless;

if (
service.package.patterns.length > 0 &&
anymatch(
service.package.patterns.filter((p) => !p.startsWith('!')),
filename
)
) {
const destFileName = path.resolve(path.join(this.buildDirPath, filename));
updateFile(op, path.resolve(filename), destFileName);
return;
}

for (const [functionAlias, fn] of Object.entries(this.functions)) {
if (fn.package.patterns.length === 0) {
continue;
}

if (
anymatch(
fn.package.patterns.filter((p) => !p.startsWith('!')),
filename
)
) {
const destFileName = path.resolve(
path.join(this.buildDirPath, `${ONLY_PREFIX}${functionAlias}`, filename)
);
updateFile(op, path.resolve(filename), destFileName);
return;
}
}
}

/** Link or copy extras such as node_modules or package.patterns definitions */
async copyExtras() {
const { service } = this.serverless;
Expand All @@ -267,15 +364,7 @@ class EsbuildServerlessPlugin implements ServerlessPlugin {

for (const filename of files) {
const destFileName = path.resolve(path.join(this.buildDirPath, filename));
const dirname = path.dirname(destFileName);

if (!fs.existsSync(dirname)) {
fs.mkdirpSync(dirname);
}

if (!fs.existsSync(destFileName)) {
fs.copySync(path.resolve(filename), destFileName);
}
updateFile('add', path.resolve(filename), destFileName);
}
}

Expand All @@ -289,15 +378,7 @@ class EsbuildServerlessPlugin implements ServerlessPlugin {
const destFileName = path.resolve(
path.join(this.buildDirPath, `${ONLY_PREFIX}${functionAlias}`, filename)
);
const dirname = path.dirname(destFileName);

if (!fs.existsSync(dirname)) {
fs.mkdirpSync(dirname);
}

if (!fs.existsSync(destFileName)) {
fs.copySync(path.resolve(filename), destFileName);
}
updateFile('add', path.resolve(filename), destFileName);
}
}
}
Expand Down

0 comments on commit 1cb893f

Please sign in to comment.