Skip to content

Commit

Permalink
Refactored the plugin to use the new initialize() method and `this.…
Browse files Browse the repository at this point in the history
…engine` property
  • Loading branch information
JamesMessinger committed Jan 17, 2020
1 parent 9eb7508 commit f19d3fc
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 55 deletions.
28 changes: 11 additions & 17 deletions src/clean.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,28 @@
import { Context } from "@code-engine/types";
import { ono } from "ono";
import { resolve } from "path";
import * as trash from "trash";
import { NormalizedConfig } from "./normalize-config";
import { FSPromises } from "./normalize-config";

/**
* Cleans the destination directory by deleting all of its contents.
*/
export function clean(config: NormalizedConfig) {
return async (context: Context): Promise<void> => {
// Resolve the output path, relative to the config path and/or the CWD
let dir = resolve(context.cwd, config.path);
let exists = await directoryExists(dir, config);
export async function clean(dir: string, fs: FSPromises) {
let exists = await directoryExists(dir, fs);

if (exists) {
// Move the output directory to the OS trash.
// This is safer than permanently deleting it,
// and allows users to roll-back to previous output if they want.
await trash(dir, { glob: false });
}
};
if (exists) {
// Move the output directory to the OS trash.
// This is safer than permanently deleting it,
// and allows users to roll-back to previous output if they want.
await trash(dir, { glob: false });
}
}

/**
* Determines whether the specified directory exists.
* An error is thrown if the path exists and is not a directory.
*/
async function directoryExists(dir: string, config: NormalizedConfig): Promise<boolean> {
async function directoryExists(dir: string, fs: FSPromises): Promise<boolean> {
try {
let stats = await config.fs.promises.stat(dir);
let stats = await fs.promises.stat(dir);

if (stats.isDirectory()) {
// The directory exists
Expand Down
20 changes: 1 addition & 19 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,4 @@
import { Plugin } from "@code-engine/types";
import { clean } from "./clean";
import { FileSystemConfig } from "./config";
import { normalizeConfig } from "./normalize-config";
import { processFile } from "./process-file";

/**
* A CodeEngine plugin that writes files to the filesystem.
*/
function filesystem(conf?: FileSystemConfig): Plugin {
let config = normalizeConfig(conf);

return {
name: "Filesystem Destination",
filter: config.filter,
processFile: processFile(config),
clean: clean(config),
};
}
import { filesystem } from "./plugin";

// Named exports
export * from "./config";
Expand Down
39 changes: 39 additions & 0 deletions src/plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { File, Plugin, Run } from "@code-engine/types";
import { resolve } from "path";
import { clean } from "./clean";
import { FileSystemConfig } from "./config";
import { normalizeConfig } from "./normalize-config";
import { writeFile } from "./write-file";

/**
* A CodeEngine plugin that writes files to the filesystem.
*/
export function filesystem(conf?: FileSystemConfig): Plugin {
let config = normalizeConfig(conf);
let dir: string;

return {
name: "Filesystem Destination",

filter: config.filter,

initialize() {
// Resolve the output directory, relative to the CodeEngine CWD
dir = resolve(this.engine.cwd, config.path);
},

/**
* Writes a file to the filesystem, creating parent directories if needed.
*/
async processFile(file: File, run: Run) {
await writeFile(dir, file, config.fs);
},

/**
* Cleans the destination directory by deleting all of its contents.
*/
async clean() {
await clean(dir, config.fs);
},
};
}
27 changes: 8 additions & 19 deletions src/process-file.ts → src/write-file.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,32 @@
import { Context, File, FileProcessor } from "@code-engine/types";
import { File } from "@code-engine/types";
import { dirname, resolve } from "path";
import { FSPromises, NormalizedConfig } from "./normalize-config";
import { FSPromises } from "./normalize-config";

/**
* Writes a file to the filesystem.
* Writes the given contents to the specified file path, creating the parent directories if needed.
*
* This method is called in parallel by CodeEngine based on the `concurrency` setting.
* All filesystem IO in Node.js is done via the LibUV thread pool, which defaults to 4 threads.
* This means that the number of concurrent file writes is the MINIMUM of CodeEngine's `concurrency`
* setting and LibUV's thread pool size.
*/
export function processFile(config: NormalizedConfig): FileProcessor {
return async (file: File, context: Context): Promise<File> => {
// Resolve the output path, relative to the config path and/or the CWD
let path = resolve(context.cwd, config.path, file.path);

await writeFile(path, file.contents, config.fs);
return file;
};
}
export async function writeFile(baseDir: string, file: File, fs: FSPromises, retry = true): Promise<void> {
let absolutePath = resolve(baseDir, file.path);

/**
* Writes the given contents to the specified file path, creating the parent directories if needed.
*/
async function writeFile(path: string, contents: Buffer, fs: FSPromises, retry = true): Promise<void> {
try {
// Try to write the file
await fs.promises.writeFile(path, contents, { flag: "w" });
await fs.promises.writeFile(absolutePath, file.contents, { flag: "w" });
}
catch (e) {
let error = e as NodeJS.ErrnoException;

if (error && retry && error.code === "ENOENT") {
// The directory path doesn't exist, so create it
let dir = dirname(path);
let dir = dirname(absolutePath);
await fs.promises.mkdir(dir, { recursive: true });

// Now try again to write the file
await writeFile(path, contents, fs, false);
await fs.promises.writeFile(absolutePath, file.contents, { flag: "w" });
}
else {
throw error;
Expand Down

0 comments on commit f19d3fc

Please sign in to comment.