touch-all 2.1.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/index.js +1 -1
- package/dist/lib/symlinkGuard.d.ts +1 -1
- package/dist/slim/touch-all.js +20 -16
- package/package.json +1 -1
package/dist/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { Path, Terminal } from '@effect/platform';
|
|
2
2
|
import { Effect } from 'effect';
|
|
3
3
|
import { type ParserResult } from './types';
|
|
4
|
-
export declare const
|
|
4
|
+
export declare const parseAndGuardSymlinks: (treeString: string, projectRoot: string, yes: boolean) => Effect.Effect<ParserResult, Error, Path.Path | Terminal.Terminal>;
|
package/dist/slim/touch-all.js
CHANGED
|
@@ -805,7 +805,7 @@ class PathTraversalError {
|
|
|
805
805
|
this.path = path;
|
|
806
806
|
}
|
|
807
807
|
toString() {
|
|
808
|
-
return `${this._tag}:
|
|
808
|
+
return `${this._tag}: path escapes root — ${this.path}`;
|
|
809
809
|
}
|
|
810
810
|
}
|
|
811
811
|
|
|
@@ -920,7 +920,7 @@ function countLeadingSpaces(str) {
|
|
|
920
920
|
}
|
|
921
921
|
|
|
922
922
|
// src/symlinkGuard.ts
|
|
923
|
-
var
|
|
923
|
+
var parseAndGuardSymlinks = (treeString, projectRoot, yes) => Effect5.gen(function* () {
|
|
924
924
|
const nodePath = yield* exports_Path.Path;
|
|
925
925
|
const items = parserFolderStructure(treeString);
|
|
926
926
|
const resolvedRoot = nodePath.resolve(projectRoot);
|
|
@@ -932,13 +932,13 @@ var checkOutsideSymlinks = (treeString, projectRoot, yes) => Effect5.gen(functio
|
|
|
932
932
|
return items;
|
|
933
933
|
const listing = outsideSymlinks.map((item) => ` ${item.path} -> ${item.target}`).join(`
|
|
934
934
|
`);
|
|
935
|
-
yield* Console2.
|
|
935
|
+
yield* Console2.error(`Warning: the following symlinks point outside PROJECT_ROOT (${resolvedRoot}):
|
|
936
936
|
${listing}`);
|
|
937
937
|
const terminal = yield* exports_Terminal.Terminal;
|
|
938
938
|
yield* terminal.display("Proceed? (y/N) ");
|
|
939
939
|
const answer = yield* terminal.readLine.pipe(Effect5.catchTag("QuitException", () => Effect5.fail(new Error(`Non-interactive mode: use --yes to allow symlinks outside project root`))));
|
|
940
940
|
if (answer.trim().toLowerCase() !== "y") {
|
|
941
|
-
yield* Console2.
|
|
941
|
+
yield* Console2.error("Aborted.");
|
|
942
942
|
return yield* Effect5.fail(new Error("Aborted by user"));
|
|
943
943
|
}
|
|
944
944
|
return items;
|
|
@@ -948,19 +948,23 @@ ${listing}`);
|
|
|
948
948
|
import { createInterface } from "node:readline";
|
|
949
949
|
import { Effect as Effect6 } from "effect";
|
|
950
950
|
var readStdin = Effect6.tryPromise({
|
|
951
|
-
try: () => new Promise((resolve3) => {
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
951
|
+
try: () => new Promise((resolve3, reject) => {
|
|
952
|
+
try {
|
|
953
|
+
const rl = createInterface({ input: process.stdin });
|
|
954
|
+
const lines = [];
|
|
955
|
+
rl.on("line", (line) => lines.push(line));
|
|
956
|
+
rl.on("close", () => resolve3(lines.join(`
|
|
956
957
|
`)));
|
|
958
|
+
} catch (e) {
|
|
959
|
+
reject(e);
|
|
960
|
+
}
|
|
957
961
|
}),
|
|
958
962
|
catch: (e) => new Error(`Failed to read stdin: ${String(e)}`)
|
|
959
963
|
});
|
|
960
964
|
// package.json
|
|
961
965
|
var package_default = {
|
|
962
966
|
name: "touch-all",
|
|
963
|
-
version: "2.1.
|
|
967
|
+
version: "2.1.1",
|
|
964
968
|
description: "CLI tool to create folder structures from markdown tree representations",
|
|
965
969
|
keywords: [
|
|
966
970
|
"cli",
|
|
@@ -1036,24 +1040,24 @@ var command = Command2.make(name, {
|
|
|
1036
1040
|
dryRun: dryRunOption,
|
|
1037
1041
|
verbose: verboseOption,
|
|
1038
1042
|
yes: yesOption
|
|
1039
|
-
}).pipe(Command2.withDescription("Create directory structure from a tree representation"), Command2.withHandler(({ tree, path: targetPath, dryRun
|
|
1043
|
+
}).pipe(Command2.withDescription("Create directory structure from a tree representation"), Command2.withHandler(({ tree, path: targetPath, dryRun, verbose, yes }) => {
|
|
1040
1044
|
const program = Effect7.gen(function* () {
|
|
1041
1045
|
const rawTree = Option2.isSome(tree) ? tree.value : yield* readStdin;
|
|
1042
1046
|
const treeString = Option2.isSome(tree) ? rawTree.replace(/\\(\\|n)/g, (_, c) => c === "n" ? `
|
|
1043
1047
|
` : "\\") : rawTree;
|
|
1044
1048
|
if (dryRun) {
|
|
1045
|
-
yield* Effect7.logInfo("
|
|
1049
|
+
yield* Effect7.logInfo("Dry run: no changes will be made to the file system.");
|
|
1046
1050
|
}
|
|
1047
1051
|
yield* Effect7.logInfo("Parsing tree structure...");
|
|
1048
|
-
const items = yield*
|
|
1052
|
+
const items = yield* parseAndGuardSymlinks(treeString, targetPath, yes);
|
|
1049
1053
|
if (items.length === 0) {
|
|
1050
1054
|
yield* Console3.error("No valid items found in the tree structure");
|
|
1051
1055
|
return yield* Effect7.fail(new Error("Invalid tree structure"));
|
|
1052
1056
|
}
|
|
1053
1057
|
yield* Effect7.logInfo(`Found ${items.length} items to create`);
|
|
1054
|
-
yield* Effect7.logInfo(`Found:
|
|
1055
|
-
${items.map((i) =>
|
|
1056
|
-
`)
|
|
1058
|
+
yield* Effect7.logInfo(`Found:
|
|
1059
|
+
${items.map((i) => i.path).join(`
|
|
1060
|
+
`)}`);
|
|
1057
1061
|
if (!dryRun) {
|
|
1058
1062
|
yield* fileStructureCreator(items, targetPath, { allowOutsideSymlinks: yes });
|
|
1059
1063
|
}
|