Skip to content

Commit

Permalink
feat: add copyDirs/copyFiles option<templateOptions>
Browse files Browse the repository at this point in the history
  • Loading branch information
zhangfisher committed Jan 18, 2025
1 parent df29143 commit 7f2f02a
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 62 deletions.
79 changes: 47 additions & 32 deletions src/fs/copyDirs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,58 @@ import { getDynamicValue } from "../misc/getDynamicValue";
export type {CopyFileInfo} from "./copyFiles"

export interface CopyDirsOptions {
vars? : Record<string, any> | ((file: string) => Record<string, any> | Promise<Record<string, any>>); // 传递给模板的变量
pattern? : string; // 匹配的文件或文件夹,支持通配符
ignore? : string[]; // 忽略的文件或文件夹,支持通配符
clean? : boolean // 是否清空目标文件夹
overwrite? : boolean | ((filename: string) => boolean | Promise<boolean>); // 是否覆盖已存在的文件,可以是boolean或返回boolean的同步/异步函数
before? : (info:CopyFileInfo) => void | typeof ABORT; // 复制前的回调
after? : (info:CopyFileInfo) => void | typeof ABORT; // 复制后的回调
error? : (error:Error,{source,target}:{source: string, target: string})=>void | typeof ABORT // 复制出错的回调
vars? : Record<string, any> | ((file: string) => Record<string, any> | Promise<Record<string, any>>); // 传递给模板的变量
pattern? : string; // 匹配的文件或文件夹,支持通配符
ignore? : string[]; // 忽略的文件或文件夹,支持通配符
clean? : boolean // 是否清空目标文件夹
overwrite? : boolean | ((filename: string) => boolean | Promise<boolean>); // 是否覆盖已存在的文件,可以是boolean或返回boolean的同步/异步函数
before? : (info:CopyFileInfo) => void | typeof ABORT; // 复制前的回调
after? : (info:CopyFileInfo) => void | typeof ABORT; // 复制后的回调
error? : (error:Error,{source,target}:{source: string, target: string})=>void | typeof ABORT // 复制出错的回调
templateOptions? : Record<string, any> | ((file: string) => Record<string, any> | Promise<Record<string, any>>);
}

export async function copyDirs(
srcDir: string,
targetDir: string,
options?: CopyDirsOptions
) {

async function copyTemplateFile(fileInfo: Required<CopyFileInfo>, opts: CopyDirsOptions) {
const targetFile = path.join(
path.dirname(fileInfo.target),
path.basename(fileInfo.target, ".art")
);
const shouldOverwrite = typeof opts.overwrite === 'function'
? await Promise.resolve(opts.overwrite(targetFile))
: opts.overwrite;
if (shouldOverwrite === false && existsSync(targetFile)) {
return;
}
const template = artTemplate(fileInfo.source);
template.defaults.imports.json=(v:any)=>{
try{
return JSON.stringify(v,null,4)
}catch{
return v
}
}
const templateVars = await getDynamicValue.call(opts, opts.vars, [fileInfo.file]);
const templateOptions = await getDynamicValue.call(opts, opts.templateOptions, [fileInfo.file]);
await writeFile(targetFile, template(templateVars, templateOptions), {encoding:"utf-8"});
}

async function copyRegularFile(fileInfo: Required<CopyFileInfo>, opts: CopyDirsOptions) {
const shouldOverwrite = await getDynamicValue.call(opts, opts.overwrite, [fileInfo.file]) as boolean;
if (shouldOverwrite === false && existsSync(fileInfo.target)) {
return;
}
await copyFile(fileInfo.source, fileInfo.target);
}


export async function copyDirs( srcDir: string, targetDir: string, options?: CopyDirsOptions) {
const opts = assignObject({
pattern: "**/*.*",
ignore:[],
clean:false
}, options);
const { ignore, pattern,vars={} } = opts;
const { ignore, pattern } = opts;

if (!existsSync(srcDir)) throw new Error(`srcDir=${srcDir} not exists`);
if (!path.isAbsolute(targetDir))
Expand Down Expand Up @@ -81,25 +112,9 @@ export async function copyDirs(
}
try {
if (file.endsWith(".art")) {// 模板文件
const targetFile = path.join(
path.dirname(fileInfo.target),
path.basename(fileInfo.target, ".art")
);
const shouldOverwrite = typeof opts.overwrite === 'function'
? await Promise.resolve(opts.overwrite(targetFile))
: opts.overwrite;
if (shouldOverwrite === false && existsSync(targetFile)) {
continue;
}
const template = artTemplate(fileInfo.source);
const templateVars =await getDynamicValue.call(opts,opts.vars,[file]);
await writeFile(targetFile, template(templateVars), {encoding:"utf-8"});
await copyTemplateFile(fileInfo, opts);
}else{// 普通文件
const shouldOverwrite = await getDynamicValue.call(opts,opts.overwrite,[file]) as boolean
if (shouldOverwrite === false && existsSync(fileInfo.target)) {
continue;
}
await copyFile(fileInfo.source, fileInfo.target);
await copyRegularFile(fileInfo, opts);
}
if (typeof options?.after == "function") {
if(options.after(fileInfo)===ABORT){
Expand Down
76 changes: 46 additions & 30 deletions src/fs/copyFiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ export interface CopyFileInfo{
}

export interface CopyFilesOptions {
vars? : Record<string, any> | ((file: string) => Record<string, any> | Promise<Record<string, any>>); // 传递给模板的变量
ignore? : string[]; // 忽略的文件或文件夹,支持通配符
clean? : boolean; // 是否清空目标文件夹
cwd? : string; // pattern的cwd
overwrite?: boolean | ((filename: string) => boolean | Promise<boolean>); // 是否覆盖已存在的文件,可以是boolean或返回boolean的同步/异步函数
before? : (info:CopyFileInfo) => void | typeof ABORT; // 复制前的回调
after? : (info:CopyFileInfo) => void | typeof ABORT; // 复制后的回调
error? : (error:Error,{source,target}:{source: string, target: string})=>void | typeof ABORT // 复制出错的回调
template?: Record<string, any> | ((file: string) => Record<string, any> | Promise<Record<string, any>>);
vars? : Record<string, any> | ((file: string) => Record<string, any> | Promise<Record<string, any>>); // 传递给模板的变量
ignore? : string[]; // 忽略的文件或文件夹,支持通配符
clean? : boolean; // 是否清空目标文件夹
cwd? : string; // pattern的cwd
overwrite? : boolean | ((filename: string) => boolean | Promise<boolean>); // 是否覆盖已存在的文件,可以是boolean或返回boolean的同步/异步函数
before? : (info:CopyFileInfo) => void | typeof ABORT; // 复制前的回调
after? : (info:CopyFileInfo) => void | typeof ABORT; // 复制后的回调
error? : (error:Error,{source,target}:{source: string, target: string})=>void | typeof ABORT // 复制出错的回调
templateOptions?: Record<string, any> | ((file: string) => Record<string, any> | Promise<Record<string, any>>);
}

export async function copyFiles(
Expand All @@ -52,7 +52,7 @@ export async function copyFiles(
clean : false
}, options);

const { ignore, vars={}, cwd=process.cwd() } = opts;
const { ignore, cwd=process.cwd() } = opts;

const srcDir = path.isAbsolute(pattern) ? path.dirname(pattern) : cwd;

Expand Down Expand Up @@ -93,26 +93,10 @@ export async function copyFiles(
}
}
try {
if (file.endsWith(".art")) {// 模板文件
const targetFile = path.join(
path.dirname(fileInfo.target),
path.basename(fileInfo.target, ".art")
);
const shouldOverwrite = typeof opts.overwrite === 'function'
? await Promise.resolve(opts.overwrite(targetFile))
: opts.overwrite;
if (shouldOverwrite === false && existsSync(targetFile)) {
continue;
}
const template = artTemplate(fileInfo.source);
const templateVars = await getDynamicValue.call(opts,opts.vars,[file]);
await writeFile(targetFile, template(templateVars), {encoding:"utf-8"});
}else{// 模板文件
const shouldOverwrite = await getDynamicValue.call(opts,opts.overwrite,[file]) as boolean
if (shouldOverwrite === false && existsSync(fileInfo.target)) {
continue;
}
await copyFile(fileInfo.source, fileInfo.target);
if (file.endsWith(".art")) {
await copyTemplateFile(fileInfo, opts);
} else {
await copyRegularFile(fileInfo, opts);
}
if (typeof options?.after == "function") {
if(options.after(fileInfo)===ABORT){
Expand All @@ -132,6 +116,38 @@ export async function copyFiles(
});
}

async function copyTemplateFile( fileInfo: Required<CopyFileInfo>,opts: CopyFilesOptions) {
const targetFile = path.join(
path.dirname(fileInfo.target),
path.basename(fileInfo.target, ".art")
);
const shouldOverwrite = typeof opts.overwrite === 'function'
? await Promise.resolve(opts.overwrite(targetFile))
: opts.overwrite;
if (shouldOverwrite === false && existsSync(targetFile)) {
return;
}
const template = artTemplate(fileInfo.source);
template.defaults.imports.json=(v:any)=>{
try{
return JSON.stringify(v,null,4)
}catch{
return v
}
}
const templateVars = await getDynamicValue.call(opts,opts.vars,[fileInfo.file]);
const templateOptions = await getDynamicValue.call(opts,opts.templateOptions,[fileInfo.file]);
await writeFile(targetFile, template(templateVars,templateOptions), { encoding:"utf-8" });
}

async function copyRegularFile( fileInfo: Required<CopyFileInfo>, opts: CopyFilesOptions) {
const shouldOverwrite = await getDynamicValue.call(opts,opts.overwrite,[fileInfo.file]) as boolean
if (shouldOverwrite === false && existsSync(fileInfo.target)) {
return;
}
await copyFile(fileInfo.source, fileInfo.target);
}

export { ABORT } from "../consts";


Expand Down

0 comments on commit 7f2f02a

Please sign in to comment.