зеркало из https://github.com/microsoft/just.git
Copy instructions task: advanced mode copy task (#95)
* adding a new copy-instructions task * change file * adding some instructions * adding exports so consumers can use this task
This commit is contained in:
Родитель
c267e7995c
Коммит
f4283da114
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"changes": [
|
||||
{
|
||||
"packageName": "just-scripts",
|
||||
"comment": "adds a new advanced copy task",
|
||||
"type": "minor"
|
||||
}
|
||||
],
|
||||
"packageName": "just-scripts",
|
||||
"email": "kchau@microsoft.com"
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
import { join, basename, normalize } from 'path';
|
||||
import { readdirSync } from 'fs';
|
||||
import { arrayify } from './arrayify';
|
||||
|
||||
export interface CopyInstruction {
|
||||
/**
|
||||
* The path+filename of the source files. If more than one file is provided, the files will be merged in order
|
||||
* and output to a file in the destination path.
|
||||
*/
|
||||
sourceFilePath: string | string[];
|
||||
|
||||
/**
|
||||
* The path+filename of the destination file.
|
||||
*/
|
||||
destinationFilePath: string;
|
||||
}
|
||||
|
||||
export interface CopyConfig {
|
||||
copyInstructions: CopyInstruction[];
|
||||
}
|
||||
|
||||
export interface LocalizedFileInfo {
|
||||
/**
|
||||
* The base path of where the localized files are located.
|
||||
*/
|
||||
baseDirectory: string;
|
||||
|
||||
/**
|
||||
* The name of the localized file to be copied, without extension (.js or .min.js will be added).
|
||||
*/
|
||||
baseFileName: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies files into a destination directory with the same names.
|
||||
* For example copyFilesToDestinationDirectory(['some/path/foo.js', 'bar.js'], 'dest/target') would result in the creation of
|
||||
* files 'dest/target/foo.js' and 'dest/target/bar.js'.
|
||||
*/
|
||||
export function copyFilesToDestinationDirectory(sourceFilePaths: string | string[], destinationDirectory: string): CopyInstruction[] {
|
||||
return arrayify(sourceFilePaths).map(sourceName => ({
|
||||
sourceFilePath: normalize(sourceName),
|
||||
destinationFilePath: join(destinationDirectory, basename(sourceName))
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies a file into a destination directory with a different name.
|
||||
* For example copyFileToDestinationDirectoryWithRename('some/path/foo.js', 'bar.js', 'dest/target') would result in the creation of
|
||||
* the file 'dest/target/bar.js'.
|
||||
*/
|
||||
export function copyFileToDestinationDirectoryWithRename(
|
||||
sourceFilePath: string,
|
||||
destinationName: string,
|
||||
destinationDirectory: string
|
||||
): CopyInstruction[] {
|
||||
return [{ sourceFilePath, destinationFilePath: join(destinationDirectory, destinationName) }];
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies files into a destination directory with different names.
|
||||
* For example copyFilesToDestinationDirectoryWithRename([{sourceFilePath:'some/path/foo.js', destinationName:'bar.js'}], 'dest/target')
|
||||
* would result in the creation of the file 'dest/target/bar.js'.
|
||||
*/
|
||||
export function copyFilesToDestinationDirectoryWithRename(
|
||||
instrs: { sourceFilePath: string; destinationName: string }[],
|
||||
destinationDirectory: string
|
||||
): CopyInstruction[] {
|
||||
return instrs.map(instr => ({
|
||||
sourceFilePath: instr.sourceFilePath,
|
||||
destinationFilePath: join(destinationDirectory, instr.destinationName)
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies all the files in a directory to the output folder.
|
||||
* You can optionally provide a filter function that determines which files to copy.
|
||||
*/
|
||||
export function copyFilesInDirectory(
|
||||
sourceDirectoryPath: string,
|
||||
outputDirectoryPath: string,
|
||||
filterFunction?: (file: string) => boolean
|
||||
): CopyInstruction[] {
|
||||
let files = readdirSync(sourceDirectoryPath);
|
||||
|
||||
if (filterFunction) {
|
||||
files = files.filter(filterFunction);
|
||||
}
|
||||
return files.map(file => ({
|
||||
sourceFilePath: join(sourceDirectoryPath, file),
|
||||
destinationFilePath: join(outputDirectoryPath, file)
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges the contents of multiple files and places them in the output folder.
|
||||
* This should only be used for text files and it should not be used for JavaScript
|
||||
* files that we care about the sourcemap information since this does not merge sourcemaps.
|
||||
*/
|
||||
export function mergeFiles(sourceFilePaths: string[], destinationFilePath: string): CopyInstruction {
|
||||
return {
|
||||
sourceFilePath: sourceFilePaths,
|
||||
destinationFilePath
|
||||
};
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
import { copyFilesToDestinationDirectory } from '../CopyInstruction';
|
||||
import { normalize } from 'path';
|
||||
|
||||
describe('CopyInstruction tests', () => {
|
||||
it('copies files with the same name to the target directory', () => {
|
||||
const result = copyFilesToDestinationDirectory(['files/foo.js', 'my/path/bar.js'], 'dist/lib/');
|
||||
|
||||
expect(result.length).toEqual(2);
|
||||
expect(result[0].sourceFilePath).toEqual(normalize('files/foo.js'));
|
||||
expect(result[0].destinationFilePath).toEqual(normalize('dist/lib/foo.js'));
|
||||
expect(result[1].sourceFilePath).toEqual(normalize('my/path/bar.js'));
|
||||
expect(result[1].destinationFilePath).toEqual(normalize('dist/lib/bar.js'));
|
||||
});
|
||||
});
|
|
@ -0,0 +1,3 @@
|
|||
export function arrayify<T>(obj: T | T[]): T[] {
|
||||
return Array.isArray(obj) ? obj : [obj];
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
import { dirname } from 'path';
|
||||
import { readFile, writeFile, copy, ensureDir } from 'fs-extra';
|
||||
import { CopyInstruction, CopyConfig } from './CopyInstruction';
|
||||
import { arrayify } from './arrayify';
|
||||
import { uniqueValues } from './uniqueValues';
|
||||
|
||||
/**
|
||||
* Function containing the core code for the copy task with a given config.
|
||||
*/
|
||||
export async function executeCopyInstructions(config: CopyConfig | undefined) {
|
||||
if (config && config.copyInstructions) {
|
||||
await createDirectories(config.copyInstructions);
|
||||
await Promise.all(config.copyInstructions.map(executeSingleCopyInstruction));
|
||||
}
|
||||
}
|
||||
|
||||
function createDirectories(copyInstructions: CopyInstruction[]) {
|
||||
return Promise.all(
|
||||
uniqueValues(copyInstructions.map(instruction => dirname(instruction.destinationFilePath))).map(dirname => ensureDir(dirname))
|
||||
);
|
||||
}
|
||||
|
||||
function executeSingleCopyInstruction(copyInstruction: CopyInstruction) {
|
||||
const sourceFileNames = arrayify(copyInstruction.sourceFilePath);
|
||||
|
||||
// source and dest are 1-to-1? perform binary copy.
|
||||
if (sourceFileNames.length === 1) {
|
||||
return copy(sourceFileNames[0], copyInstruction.destinationFilePath);
|
||||
}
|
||||
|
||||
// perform text merge operation.
|
||||
return Promise.all(sourceFileNames.map(fileName => readFile(fileName))).then(fileContents => {
|
||||
writeFile(copyInstruction.destinationFilePath, fileContents.join('\n'));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* Removes duplicate numbers from an array
|
||||
* @param array - The array possibly containing duplicate values
|
||||
*/
|
||||
export function uniqueValues<T>(array: T[]): T[] {
|
||||
return Array.from(new Set<T>(array));
|
||||
}
|
|
@ -21,3 +21,6 @@ export const webpackOverlays = {
|
|||
|
||||
import webpackMerge from 'webpack-merge';
|
||||
export { webpackMerge };
|
||||
|
||||
import * as copyInstructions from './copy/CopyInstruction';
|
||||
export { copyInstructions };
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
import { executeCopyInstructions } from '../copy/executeCopyInstructions';
|
||||
import { CopyConfig } from '../copy/CopyInstruction';
|
||||
|
||||
/**
|
||||
* This is an advanced copy task that allows more advanced usage beyond simple copies.
|
||||
* It allows for copy renames. It takes in a config that can be generated dynamically with code at build time.
|
||||
*
|
||||
* @param config Copy instructions configuration
|
||||
*/
|
||||
export function copyInstructionsTask(config?: CopyConfig) {
|
||||
return function copyInstructions() {
|
||||
return executeCopyInstructions(config);
|
||||
};
|
||||
}
|
|
@ -9,3 +9,4 @@ export * from './apiExtractorTask';
|
|||
export * from './addPackageTask';
|
||||
export * from './upgradeRepoTask';
|
||||
export * from './upgradeStackTask';
|
||||
export * from './copyInstructionsTask';
|
||||
|
|
Загрузка…
Ссылка в новой задаче