Skip to content

Commit

Permalink
refactor(public/fs): armonizes callbacks behavior for fs functions
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Callbacks for fs functions now receive an object with the appropriate data for each
case
  • Loading branch information
rafamel committed May 20, 2019
1 parent d6bbd0a commit 74f0bec
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 40 deletions.
8 changes: 4 additions & 4 deletions src/public/fs/read/index.ts
@@ -1,6 +1,6 @@
import expose from '~/utils/expose';
import { TScript } from '~/types';
import { TSource, IFsReadOptions } from '../types';
import { TSource, IFsReadOptions, TReadFn } from '../types';
import trunk from './read';

export default expose(read);
Expand All @@ -11,13 +11,13 @@ export default expose(read);
* @returns An asynchronous function -hence, calling `read` won't have any effect until the returned function is called.
*/
function read(
file: TSource,
fn: (raw?: string) => TScript,
src: TSource,
fn: TReadFn,
options?: IFsReadOptions
): () => Promise<TScript> {
return async () => {
return trunk(
typeof file === 'function' ? await file() : await file,
typeof src === 'function' ? await src() : await src,
fn,
options
);
Expand Down
24 changes: 12 additions & 12 deletions src/public/fs/read/read.ts
@@ -1,27 +1,27 @@
import fs from 'fs-extra';
import { exists, absolute } from '~/utils/file';
import { IFsReadOptions } from '../types';
import { IFsReadOptions, TReadFn } from '../types';
import { TScript } from '~/types';

export default async function read(
file: string | string[],
fn: (raw?: string) => TScript,
src: string | string[],
fn: TReadFn,
options: IFsReadOptions = {}
): Promise<TScript> {
return Array.isArray(file)
? Promise.all(file.map((item) => each(item, fn, options)))
: each(file, fn, options);
return Array.isArray(src)
? Promise.all(src.map((file) => each(file, fn, options)))
: each(src, fn, options);
}

export async function each(
file: string,
fn: (raw?: string) => TScript,
src: string,
fn: TReadFn,
options: IFsReadOptions
): Promise<TScript> {
const cwd = process.cwd();
file = absolute({ path: file, cwd });
const doesExist = await exists(file, { fail: options.fail });
const raw = doesExist ? await fs.readFile(file).then(String) : undefined;
src = absolute({ path: src, cwd });
const doesExist = await exists(src, { fail: options.fail });
const raw = doesExist ? await fs.readFile(src).then(String) : undefined;

return fn(raw);
return fn({ src, raw });
}
9 changes: 9 additions & 0 deletions src/public/fs/types.ts
Expand Up @@ -12,6 +12,15 @@ export type TCopyFilterFn =
| ((src: string, dest: string) => boolean)
| ((src: string, dest: string) => Promise<boolean>);

export type TReadFn = (data: {
src: string;
raw?: string;
}) => TScript | Promise<TScript>;

export type TWriteFn = (data: {
dest: string;
}) => string | void | Promise<string | void>;

export type TReadWriteFn = (data: {
src: string;
dest: string;
Expand Down
18 changes: 9 additions & 9 deletions src/public/fs/write/index.ts
@@ -1,36 +1,36 @@
import expose, { TExposedOverload } from '~/utils/expose';
import { IFsUpdateOptions, TContentFn, TSource } from '../types';
import { IFsUpdateOptions, TWriteFn, TSource } from '../types';
import trunk from './write';

export default expose(write) as TExposedOverload<
typeof write,
| [TSource]
| [TSource, undefined | string | TContentFn]
| [TSource, undefined | string | TWriteFn]
| [TSource, IFsUpdateOptions]
| [TSource, undefined | string | TContentFn, IFsUpdateOptions]
| [TSource, undefined | string | TWriteFn, IFsUpdateOptions]
>;

function write(file: TSource, raw?: string | TContentFn): () => Promise<void>;
function write(file: TSource, options?: IFsUpdateOptions): () => Promise<void>;
function write(dest: TSource, content?: string | TWriteFn): () => Promise<void>;
function write(dest: TSource, options?: IFsUpdateOptions): () => Promise<void>;
function write(
file: TSource,
raw?: string | TContentFn,
dest: TSource,
content?: string | TWriteFn,
options?: IFsUpdateOptions
): () => Promise<void>;
/**
* Writes a `file` with `raw`. If no `raw` content is passed, it will overwrite with no content.
* It is an *exposed* function: call `write.fn()`, which takes the same arguments, in order to execute on call.
* @returns An asynchronous function -hence, calling `write` won't have any effect until the returned function is called.
*/
function write(file: TSource, ...args: any[]): () => Promise<void> {
function write(dest: TSource, ...args: any[]): () => Promise<void> {
return async () => {
const hasRaw =
typeof args[0] === 'string' ||
typeof args[0] === 'function' ||
typeof args[0] === 'undefined';

return trunk(
typeof file === 'function' ? await file() : await file,
typeof dest === 'function' ? await dest() : await dest,
hasRaw ? args[0] : undefined,
hasRaw ? args[1] : args[0]
);
Expand Down
30 changes: 15 additions & 15 deletions src/public/fs/write/write.ts
@@ -1,41 +1,41 @@
import fs from 'fs-extra';
import path from 'path';
import { IFsUpdateOptions, TContentFn } from '../types';
import { IFsUpdateOptions, TWriteFn } from '../types';
import { exists, absolute } from '~/utils/file';
import confirm from '~/utils/confirm';
import { open } from '~/utils/errors';
import { log } from '../utils';

export default async function write(
file: string | string[],
raw?: string | TContentFn,
dest: string | string[],
content?: string | TWriteFn,
options: IFsUpdateOptions = {}
): Promise<void> {
options = Object.assign({ overwrite: true }, options);

Array.isArray(file)
? await Promise.all(file.map((item) => each(item, raw, options)))
: await each(file, raw, options);
Array.isArray(dest)
? await Promise.all(dest.map((file) => each(file, content, options)))
: await each(dest, content, options);
}

export async function each(
file: string,
raw: void | string | TContentFn,
dest: string,
content: void | string | TWriteFn,
options: IFsUpdateOptions
): Promise<void> {
const cwd = process.cwd();
file = absolute({ path: file, cwd });
const relative = './' + path.relative(process.cwd(), file);
dest = absolute({ path: dest, cwd });
const relative = './' + path.relative(process.cwd(), dest);

if (typeof raw === 'function') {
if (typeof content === 'function') {
try {
raw = await raw({ file });
content = await content({ dest });
} catch (err) {
throw open(err);
}
}

const doesExist = await exists(file);
const doesExist = await exists(dest);
if (options.fail && doesExist) {
throw Error(`File already exists: ${relative}`);
}
Expand All @@ -47,7 +47,7 @@ export async function each(

if (!(await confirm(`Write "${relative}"?`, options))) return;

await fs.ensureDir(path.parse(file).dir);
await fs.writeFile(file, raw ? String(raw) : '');
await fs.ensureDir(path.dirname(dest));
await fs.writeFile(dest, content ? String(content) : '');
log(options, 'info')(`Written: ${relative}`);
}

0 comments on commit 74f0bec

Please sign in to comment.