Skip to content

Commit b2dcc41

Browse files
committed
feat: Add server command & Remove unused commands
1 parent 28259ea commit b2dcc41

File tree

9 files changed

+647
-501
lines changed

9 files changed

+647
-501
lines changed

package-lock.json

+576-353
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@
2424
},
2525
"homepage": "https://github.com/araguma/node-dev-utils#readme",
2626
"devDependencies": {
27-
"@types/fs-extra": "^11.0.1",
27+
"@types/express": "^4.17.17",
2828
"@types/node": "^20.3.1",
2929
"typescript": "^5.1.3"
3030
},
3131
"dependencies": {
3232
"chokidar": "^3.5.3",
3333
"commander": "^11.0.0",
34-
"glob": "^10.3.0"
34+
"express": "^4.18.2"
3535
},
3636
"bin": {
3737
"du": "./dist/bin/src/index.js"

src/commands/cp.ts

+20-40
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,27 @@
11
import fs from 'node:fs';
2-
import { join } from 'node:path';
3-
import { globSync } from 'glob';
4-
import chokidar from 'chokidar';
2+
import path from 'node:path';
3+
import { stringToRegex } from '../utils/regex';
54

6-
/**
7-
* Copy files or directories to another destination
8-
* @param pattern Source files or directories
9-
* @param destPath Destination directory
10-
* @param options Copy options
11-
*/
12-
function cp(pattern: string, destPath: string, options: {
13-
/**
14-
* Copy subdirectories recursively
15-
*/
16-
recursive?: boolean,
17-
/**
18-
* Force copy
19-
*/
20-
force?: boolean,
21-
/**
22-
* Files or directories to ignore
23-
*/
24-
ignore?: string,
25-
/**
26-
* Starts watch mode on source files or directories
27-
*/
28-
watch?: boolean,
5+
function cp(src: string, dest: string, options: {
6+
recursive?: boolean;
7+
force?: boolean;
8+
ignore?: string;
299
}) {
30-
const srcPaths = globSync(pattern, {
31-
ignore: options.ignore,
32-
});
33-
const copytoDestFn = (path: string) => {
34-
fs.cpSync(path, join(destPath, path), {
35-
mode: fs.constants.COPYFILE_FICLONE,
36-
errorOnExist: false,
37-
recursive: options.recursive,
38-
force: options.force,
10+
src = path.normalize(src);
11+
dest = path.normalize(dest);
12+
const ignoreRegex = stringToRegex(options.ignore ?? '/$^/');
13+
14+
fs.readdirSync(src, {
15+
recursive: options.recursive ?? false,
16+
withFileTypes: true,
17+
}).filter((entry) => {
18+
return entry.isFile() && !ignoreRegex.test(entry.name);
19+
}).forEach((entry) => {
20+
const filePath = path.join(entry.path, entry.name);
21+
fs.cpSync(filePath, path.join(dest, filePath), {
22+
force: options.force ?? false,
3923
});
40-
}
41-
srcPaths.forEach(copytoDestFn);
42-
if(options.watch)
43-
chokidar.watch(srcPaths)
44-
.on('change', copytoDestFn);
24+
});
4525
}
4626

4727
export default cp;

src/commands/mkdir.ts

-11
This file was deleted.

src/commands/rm.ts

-34
This file was deleted.

src/commands/server.ts

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { execSync } from 'node:child_process';
2+
import express from 'express';
3+
import chokidar from 'chokidar';
4+
5+
function server(root: string, options: {
6+
port: number;
7+
watch?: string;
8+
command?: string;
9+
}) {
10+
const app = express();
11+
app.use(express.static(root));
12+
app.listen(options.port, () => {
13+
console.log(`Server is listening on localhost:${options.port}`);
14+
});
15+
16+
chokidar.watch(options.watch ?? root).on('change', (path) => {
17+
if(options.command)
18+
execSync(options.command.replace(/\$path/g, path));
19+
});
20+
}
21+
22+
export default server;

src/commands/watch.ts

-28
This file was deleted.

src/index.ts

+16-33
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,34 @@
11
#!/usr/bin/env node
2-
import { version } from '../package.json';
32
import { Command } from 'commander';
4-
import mkdir from './commands/mkdir';
3+
import { version } from '../package.json';
54
import cp from './commands/cp';
6-
import rm from './commands/rm';
7-
import watch from './commands/watch';
5+
import server from './commands/server';
86

97
const program = new Command()
108
.name('fsx')
119
.description('A collection of cross-platform compatible functions and shell commands that aid in npm package development.')
1210
.version(version);
1311

14-
program.command('mkdir')
15-
.description('Create directory at the specified path.')
16-
.argument('<string>', 'Directory path')
17-
.action(mkdir);
18-
1912
program.command('cp')
20-
.description('Copy files or directories to another destination.')
21-
.argument('<string>', 'Source files or directories')
13+
.description('Copy files and directories.')
14+
.argument('<string>', 'Source file or directory')
2215
.argument('<string>', 'Destination directory')
23-
.option('-r, --recursive', 'Copy subdirectories recursively', false)
24-
.option('-f, --force', 'Force copy', false)
25-
.option('-i, --ignore <string>', 'Files or directories to ignore')
26-
.option('-w, --watch', 'Starts watch mode on source files or directories', false)
16+
.option('-r, --recursive', 'Copy directories recursively', false)
17+
.option('-f, --force', 'Overwrite existing files', false)
18+
.option('-i, --ignore <string>', 'Ignore file(s) or directory')
2719
.action(cp);
2820

29-
program.command('rm')
30-
.description('Remove files or directories.')
31-
.argument('<string>', 'Files or directories')
32-
.option('-r, --recursive', 'Remove subdirectories recursively', false)
33-
.option('-f, --force', 'Force remove', false)
34-
.option('-i, --ignore <string>', 'Files or directories to ignore')
35-
.action(rm);
36-
37-
program.command('watch')
38-
.description('Watch a list of files and run a command if any changes occur.')
39-
.argument('<string>', 'Files or directories to watch')
40-
.argument('<string>', 'Command to run if any changes occur')
41-
.option('-i --ignore <string>', 'Files or directories to ignore')
42-
.action(watch);
21+
program.command('server')
22+
.description('Host a static local server using the specified directory as root.')
23+
.argument('<string>', 'Root directory')
24+
.option('-p, --port <number>', 'Port to listen on', '3000')
25+
.option('-w, --watch <string>', 'Watch directory')
26+
.option('-c, --command <string>', 'Command to run on change')
27+
.action(server);
4328

4429
program.parse();
4530

4631
export {
47-
mkdir,
4832
cp,
49-
rm,
50-
watch,
51-
};
33+
server
34+
}

src/utils/regex.ts

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
function stringToRegex(string: string) {
2+
// Matches the pattern in the first group and flags in the third group
3+
const groups = string.match(/^\/(.*)\/(?!.*(.).*\2)([gmiyuvsd]*)$/m);
4+
if(groups === null)
5+
throw new Error(`Invalid regex: ${string}`);
6+
return new RegExp(groups[1], groups[3]);
7+
}
8+
9+
export {
10+
stringToRegex,
11+
}

0 commit comments

Comments
 (0)