UNPKG

3.5 kBPlain TextView Raw
1import * as path from 'path'
2import { _since } from '@naturalcycles/js-lib'
3import * as cpFile from 'cp-file'
4import * as fs from 'fs-extra'
5import * as moveFile from 'move-file'
6import { boldWhite, dimGrey, grey, yellow } from '../colors'
7import { globby } from '../index'
8
9/**
10 * Everything defaults to `undefined`.
11 */
12export interface KpyOptions {
13 /**
14 * @default . (cwd)
15 */
16 baseDir: string
17
18 /**
19 * @default to `**` (everything, including sub-dirs)
20 */
21 inputPatterns?: string[]
22
23 /**
24 * @default . (cwd)
25 */
26 outputDir: string
27
28 silent?: boolean
29 verbose?: boolean
30
31 /**
32 * Safety setting
33 *
34 * @default false
35 */
36 noOverwrite?: boolean
37
38 dotfiles?: boolean
39 flat?: boolean
40 dry?: boolean
41
42 /**
43 * Will Move instead of Copy
44 */
45 move?: boolean
46}
47
48export async function kpy(opt: KpyOptions): Promise<void> {
49 const started = Date.now()
50
51 kpyPrepare(opt)
52
53 const filenames = await globby(opt.inputPatterns!, {
54 cwd: opt.baseDir,
55 dot: opt.dotfiles,
56 })
57
58 kpyLogFilenames(opt, filenames)
59
60 const overwrite = !opt.noOverwrite
61
62 await Promise.all(
63 filenames.map(async filename => {
64 const basename = path.basename(filename)
65 const srcFilename = path.resolve(opt.baseDir, filename)
66 const destFilename = path.resolve(opt.outputDir, opt.flat ? basename : filename)
67
68 if (!opt.dry) {
69 if (opt.move) {
70 await moveFile(srcFilename, destFilename, { overwrite })
71 } else {
72 await cpFile(srcFilename, destFilename, { overwrite })
73 }
74 }
75
76 if (opt.verbose) {
77 console.log(grey(` ${filename}`))
78 }
79 }),
80 )
81
82 kpyLogResult(opt, filenames, started)
83}
84
85export function kpySync(opt: KpyOptions): void {
86 const started = Date.now()
87
88 kpyPrepare(opt)
89
90 const filenames = globby.sync(opt.inputPatterns!, {
91 cwd: opt.baseDir,
92 dot: opt.dotfiles,
93 })
94
95 kpyLogFilenames(opt, filenames)
96
97 const overwrite = !opt.noOverwrite
98
99 filenames.forEach(filename => {
100 const basename = path.basename(filename)
101 const srcFilename = path.resolve(opt.baseDir, filename)
102 const destFilename = path.resolve(opt.outputDir, opt.flat ? basename : filename)
103
104 if (!opt.dry) {
105 if (opt.move) {
106 moveFile.sync(srcFilename, destFilename, { overwrite })
107 } else {
108 cpFile.sync(srcFilename, destFilename, { overwrite })
109 }
110 }
111
112 if (opt.verbose) {
113 console.log(grey(` ${filename}`))
114 }
115 })
116
117 kpyLogResult(opt, filenames, started)
118}
119
120function kpyPrepare(opt: KpyOptions): void {
121 // Default pattern
122 if (!opt.inputPatterns?.length) opt.inputPatterns = ['**']
123
124 // default to cwd
125 opt.baseDir ||= '.'
126 opt.outputDir ||= '.'
127
128 if (!fs.existsSync(opt.baseDir)) {
129 console.log(`kpy: baseDir doesn't exist: ${boldWhite(opt.baseDir)}`)
130 return
131 }
132
133 fs.ensureDirSync(opt.outputDir)
134}
135
136function kpyLogFilenames(opt: KpyOptions, filenames: string[]): void {
137 if (opt.silent) return
138
139 // console.log({filenames})
140 console.log(
141 `Will ${opt.move ? 'move' : 'copy'} ${yellow(filenames.length)} files from ${dimGrey(
142 opt.baseDir,
143 )} to ${dimGrey(opt.outputDir)} (${dimGrey(opt.inputPatterns!.join(' '))})`,
144 )
145}
146
147function kpyLogResult(opt: KpyOptions, filenames: string[], started: number): void {
148 if (opt.silent || filenames.length === 0) return
149
150 console.log(
151 `${opt.move ? 'Moved' : 'Copied'} ${yellow(filenames.length)} files to ${dimGrey(
152 opt.outputDir,
153 )} ${dimGrey(_since(started))}`,
154 )
155}