@reliverse/relifso 1.4.5 → 2.2.8
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/README.md +365 -447
- package/dist/copy.d.ts +3 -0
- package/dist/copy.js +95 -0
- package/dist/dir.d.ts +13 -0
- package/dist/dir.js +113 -0
- package/dist/file.d.ts +12 -0
- package/dist/file.js +169 -0
- package/dist/helpers.d.ts +3 -0
- package/dist/helpers.js +38 -0
- package/dist/internal/fs.d.ts +16 -0
- package/dist/internal/fs.js +32 -0
- package/dist/internal/path.d.ts +3 -0
- package/dist/internal/path.js +11 -0
- package/dist/links.d.ts +3 -0
- package/dist/links.js +74 -0
- package/dist/mod.d.ts +40 -0
- package/dist/mod.js +77 -0
- package/dist/types.d.ts +50 -0
- package/dist/types.js +0 -0
- package/package.json +15 -42
- package/LICENSE +0 -21
- package/LICENSES +0 -16
- package/bin/impl/bun.d.ts +0 -11
- package/bin/impl/bun.js +0 -23
- package/bin/impl/copy.d.ts +0 -40
- package/bin/impl/copy.js +0 -229
- package/bin/impl/create.d.ts +0 -34
- package/bin/impl/create.js +0 -54
- package/bin/impl/dive.d.ts +0 -27
- package/bin/impl/dive.js +0 -145
- package/bin/impl/empty.d.ts +0 -28
- package/bin/impl/empty.js +0 -75
- package/bin/impl/extras.d.ts +0 -35
- package/bin/impl/extras.js +0 -112
- package/bin/impl/json-utils.d.ts +0 -30
- package/bin/impl/json-utils.js +0 -46
- package/bin/impl/mkdirs.d.ts +0 -7
- package/bin/impl/mkdirs.js +0 -28
- package/bin/impl/move.d.ts +0 -28
- package/bin/impl/move.js +0 -140
- package/bin/impl/output-file.d.ts +0 -17
- package/bin/impl/output-file.js +0 -15
- package/bin/impl/output-json.d.ts +0 -21
- package/bin/impl/output-json.js +0 -77
- package/bin/impl/path-exists.d.ts +0 -2
- package/bin/impl/path-exists.js +0 -16
- package/bin/impl/read-file.d.ts +0 -31
- package/bin/impl/read-file.js +0 -165
- package/bin/impl/read-json.d.ts +0 -31
- package/bin/impl/read-json.js +0 -241
- package/bin/impl/remove.d.ts +0 -2
- package/bin/impl/remove.js +0 -8
- package/bin/impl/stats.d.ts +0 -31
- package/bin/impl/stats.js +0 -141
- package/bin/impl/write-file.d.ts +0 -31
- package/bin/impl/write-file.js +0 -177
- package/bin/impl/write-json.d.ts +0 -41
- package/bin/impl/write-json.js +0 -135
- package/bin/mod.d.ts +0 -253
- package/bin/mod.js +0 -514
- package/bin/utils/json/helpers/JSONRepairError.d.ts +0 -4
- package/bin/utils/json/helpers/JSONRepairError.js +0 -7
- package/bin/utils/json/helpers/JsonSchemaError.d.ts +0 -6
- package/bin/utils/json/helpers/JsonSchemaError.js +0 -6
- package/bin/utils/json/helpers/stringUtils.d.ts +0 -64
- package/bin/utils/json/helpers/stringUtils.js +0 -87
- package/bin/utils/json/regular/jsonc.d.ts +0 -45
- package/bin/utils/json/regular/jsonc.js +0 -88
- package/bin/utils/json/regular/jsonrepair.d.ts +0 -17
- package/bin/utils/json/regular/jsonrepair.js +0 -576
- package/bin/utils/json/regular/validate.d.ts +0 -22
- package/bin/utils/json/regular/validate.js +0 -52
- package/bin/utils/json/stream/JsonStreamError.d.ts +0 -6
- package/bin/utils/json/stream/JsonStreamError.js +0 -6
- package/bin/utils/json/stream/buffer/InputBuffer.d.ts +0 -13
- package/bin/utils/json/stream/buffer/InputBuffer.js +0 -68
- package/bin/utils/json/stream/buffer/OutputBuffer.d.ts +0 -17
- package/bin/utils/json/stream/buffer/OutputBuffer.js +0 -101
- package/bin/utils/json/stream/core.d.ts +0 -10
- package/bin/utils/json/stream/core.js +0 -695
- package/bin/utils/json/stream/jsonl.d.ts +0 -21
- package/bin/utils/json/stream/jsonl.js +0 -55
- package/bin/utils/json/stream/parser.d.ts +0 -14
- package/bin/utils/json/stream/parser.js +0 -81
- package/bin/utils/json/stream/stack.d.ts +0 -19
- package/bin/utils/json/stream/stack.js +0 -43
- package/bin/utils/json/stream/stream.d.ts +0 -6
- package/bin/utils/json/stream/stream.js +0 -30
- package/bin/utils/json/stream/writer.d.ts +0 -14
- package/bin/utils/json/stream/writer.js +0 -44
- package/bin/utils/log.d.ts +0 -1
- package/bin/utils/log.js +0 -7
package/bin/impl/dive.js
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import { readdirSync, statSync } from "node:fs";
|
|
2
|
-
import { readdir as nodeReaddirInternal, stat as nodeStatInternal } from "node:fs/promises";
|
|
3
|
-
import { join } from "node:path";
|
|
4
|
-
import { join as pathJoin } from "node:path";
|
|
5
|
-
import { isBun } from "./bun.js";
|
|
6
|
-
import { getStats } from "./stats.js";
|
|
7
|
-
export function* diveSync(dir, callbackOrOptions, options) {
|
|
8
|
-
const currentDepth = 0;
|
|
9
|
-
let actualOptions = {
|
|
10
|
-
recursive: true,
|
|
11
|
-
files: true,
|
|
12
|
-
directories: false
|
|
13
|
-
// fs-extra's dive by default only yields files
|
|
14
|
-
};
|
|
15
|
-
let callback;
|
|
16
|
-
if (typeof callbackOrOptions === "function") {
|
|
17
|
-
callback = callbackOrOptions;
|
|
18
|
-
if (options) {
|
|
19
|
-
actualOptions = { ...actualOptions, ...options };
|
|
20
|
-
}
|
|
21
|
-
} else if (typeof callbackOrOptions === "object") {
|
|
22
|
-
actualOptions = { ...actualOptions, ...callbackOrOptions };
|
|
23
|
-
}
|
|
24
|
-
function* walk(currentPath, depth) {
|
|
25
|
-
if (actualOptions.depth !== void 0 && depth > actualOptions.depth) {
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
const entries = readdirSync(currentPath, { withFileTypes: true });
|
|
29
|
-
for (const entry of entries) {
|
|
30
|
-
const entryPath = join(currentPath, entry.name);
|
|
31
|
-
if (!actualOptions.all && entry.name.startsWith(".")) {
|
|
32
|
-
continue;
|
|
33
|
-
}
|
|
34
|
-
if (actualOptions.ignore) {
|
|
35
|
-
if (Array.isArray(actualOptions.ignore) && actualOptions.ignore.includes(entry.name)) {
|
|
36
|
-
continue;
|
|
37
|
-
}
|
|
38
|
-
if (actualOptions.ignore instanceof RegExp && actualOptions.ignore.test(entryPath)) {
|
|
39
|
-
continue;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
const stat = statSync(entryPath);
|
|
43
|
-
if (entry.isFile()) {
|
|
44
|
-
if (actualOptions.files) {
|
|
45
|
-
if (callback) callback(entryPath, stat);
|
|
46
|
-
yield entryPath;
|
|
47
|
-
}
|
|
48
|
-
} else if (entry.isDirectory()) {
|
|
49
|
-
if (actualOptions.directories) {
|
|
50
|
-
if (callback) callback(entryPath, stat);
|
|
51
|
-
yield entryPath;
|
|
52
|
-
}
|
|
53
|
-
if (actualOptions.recursive) {
|
|
54
|
-
yield* walk(entryPath, depth + 1);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
yield* walk(dir, currentDepth);
|
|
60
|
-
}
|
|
61
|
-
async function* _diveWorker(currentPath, options, currentDepth) {
|
|
62
|
-
const maxDepth = options.depth ?? Number.POSITIVE_INFINITY;
|
|
63
|
-
if (currentDepth > maxDepth) {
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
let entries;
|
|
67
|
-
try {
|
|
68
|
-
entries = await nodeReaddirInternal(currentPath, { withFileTypes: true });
|
|
69
|
-
} catch (_err) {
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
for (const entry of entries) {
|
|
73
|
-
const entryPath = pathJoin(currentPath, entry.name);
|
|
74
|
-
if (!(options.all ?? false) && entry.name.startsWith(".")) {
|
|
75
|
-
continue;
|
|
76
|
-
}
|
|
77
|
-
if (options.ignore) {
|
|
78
|
-
if (Array.isArray(options.ignore) && options.ignore.some((pattern) => entry.name.includes(pattern))) {
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
81
|
-
if (options.ignore instanceof RegExp && options.ignore.test(entryPath)) {
|
|
82
|
-
continue;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
let entryStat;
|
|
86
|
-
try {
|
|
87
|
-
if (isBun) {
|
|
88
|
-
try {
|
|
89
|
-
entryStat = await getStats(entryPath);
|
|
90
|
-
} catch (_error) {
|
|
91
|
-
entryStat = await nodeStatInternal(entryPath);
|
|
92
|
-
}
|
|
93
|
-
} else {
|
|
94
|
-
entryStat = await nodeStatInternal(entryPath);
|
|
95
|
-
}
|
|
96
|
-
} catch (_err) {
|
|
97
|
-
continue;
|
|
98
|
-
}
|
|
99
|
-
if (entry.isDirectory()) {
|
|
100
|
-
if (options.directories ?? false) {
|
|
101
|
-
yield { file: entryPath, stat: entryStat };
|
|
102
|
-
}
|
|
103
|
-
if (options.recursive ?? true) {
|
|
104
|
-
if (currentDepth < maxDepth) {
|
|
105
|
-
yield* _diveWorker(entryPath, options, currentDepth + 1);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
} else if (entry.isFile()) {
|
|
109
|
-
if (options.files ?? true) {
|
|
110
|
-
yield { file: entryPath, stat: entryStat };
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
export async function dive(directory, actionOrOptions, optionsOnly) {
|
|
116
|
-
let action;
|
|
117
|
-
let options;
|
|
118
|
-
if (typeof actionOrOptions === "function") {
|
|
119
|
-
action = actionOrOptions;
|
|
120
|
-
options = optionsOnly;
|
|
121
|
-
} else {
|
|
122
|
-
options = actionOrOptions;
|
|
123
|
-
}
|
|
124
|
-
const currentOptions = {
|
|
125
|
-
recursive: true,
|
|
126
|
-
files: true,
|
|
127
|
-
directories: false,
|
|
128
|
-
all: false,
|
|
129
|
-
depth: Number.POSITIVE_INFINITY,
|
|
130
|
-
...options
|
|
131
|
-
// User options override defaults
|
|
132
|
-
};
|
|
133
|
-
if (action) {
|
|
134
|
-
for await (const { file, stat: entryStat } of _diveWorker(directory, currentOptions, 0)) {
|
|
135
|
-
await action(file, entryStat);
|
|
136
|
-
}
|
|
137
|
-
return;
|
|
138
|
-
} else {
|
|
139
|
-
const results = [];
|
|
140
|
-
for await (const { file } of _diveWorker(directory, currentOptions, 0)) {
|
|
141
|
-
results.push(file);
|
|
142
|
-
}
|
|
143
|
-
return results;
|
|
144
|
-
}
|
|
145
|
-
}
|
package/bin/impl/empty.d.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
interface EmptyFileOptions {
|
|
2
|
-
/**
|
|
3
|
-
* If true, will replace all object literals with empty objects {}
|
|
4
|
-
* Only works with JSON files
|
|
5
|
-
*/
|
|
6
|
-
emptyObjects?: boolean;
|
|
7
|
-
}
|
|
8
|
-
export declare function emptyDirSync(dir: string): void;
|
|
9
|
-
export declare function emptyDir(dir: string): Promise<void>;
|
|
10
|
-
/**
|
|
11
|
-
* Empties an object by removing all its properties
|
|
12
|
-
* @param obj The object to empty
|
|
13
|
-
* @returns The empty object
|
|
14
|
-
*/
|
|
15
|
-
export declare function emptyObject<T extends object>(obj: T): T;
|
|
16
|
-
/**
|
|
17
|
-
* Empties a file by removing all its contents
|
|
18
|
-
* @param filePath Path to the file
|
|
19
|
-
* @param options Options for emptying the file
|
|
20
|
-
*/
|
|
21
|
-
export declare function emptyFile(filePath: string, options?: EmptyFileOptions): Promise<void>;
|
|
22
|
-
/**
|
|
23
|
-
* Synchronous version of emptyFile
|
|
24
|
-
* @param filePath Path to the file
|
|
25
|
-
* @param options Options for emptying the file
|
|
26
|
-
*/
|
|
27
|
-
export declare function emptyFileSync(filePath: string, options?: EmptyFileOptions): void;
|
|
28
|
-
export {};
|
package/bin/impl/empty.js
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { existsSync, readdirSync, rmSync, writeFileSync, readFileSync } from "node:fs";
|
|
2
|
-
import { readdir, rm, stat, writeFile, readFile } from "node:fs/promises";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
export function emptyDirSync(dir) {
|
|
5
|
-
if (!existsSync(dir)) {
|
|
6
|
-
return;
|
|
7
|
-
}
|
|
8
|
-
for (const file of readdirSync(dir)) {
|
|
9
|
-
rmSync(path.resolve(dir, file), { recursive: true, force: true });
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
export async function emptyDir(dir) {
|
|
13
|
-
try {
|
|
14
|
-
await stat(dir);
|
|
15
|
-
} catch (error) {
|
|
16
|
-
if (error.code === "ENOENT") {
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
throw error;
|
|
20
|
-
}
|
|
21
|
-
for (const file of await readdir(dir)) {
|
|
22
|
-
await rm(path.resolve(dir, file), { recursive: true, force: true });
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
export function emptyObject(obj) {
|
|
26
|
-
for (const key in obj) {
|
|
27
|
-
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
28
|
-
delete obj[key];
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return obj;
|
|
32
|
-
}
|
|
33
|
-
export async function emptyFile(filePath, options = {}) {
|
|
34
|
-
try {
|
|
35
|
-
await stat(filePath);
|
|
36
|
-
} catch (error) {
|
|
37
|
-
if (error.code === "ENOENT") {
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
throw error;
|
|
41
|
-
}
|
|
42
|
-
if (options.emptyObjects && filePath.toLowerCase().endsWith(".json")) {
|
|
43
|
-
try {
|
|
44
|
-
const content = await readFile(filePath, "utf-8");
|
|
45
|
-
const data = JSON.parse(content);
|
|
46
|
-
if (typeof data === "object" && data !== null) {
|
|
47
|
-
const emptyData = emptyObject(data);
|
|
48
|
-
await writeFile(filePath, JSON.stringify(emptyData, null, 2));
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
} catch (error) {
|
|
52
|
-
console.warn(`Failed to parse JSON file ${filePath}, falling back to regular file emptying:`, error);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
await writeFile(filePath, "");
|
|
56
|
-
}
|
|
57
|
-
export function emptyFileSync(filePath, options = {}) {
|
|
58
|
-
if (!existsSync(filePath)) {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
if (options.emptyObjects && filePath.toLowerCase().endsWith(".json")) {
|
|
62
|
-
try {
|
|
63
|
-
const content = readFileSync(filePath, "utf-8");
|
|
64
|
-
const data = JSON.parse(content);
|
|
65
|
-
if (typeof data === "object" && data !== null) {
|
|
66
|
-
const emptyData = emptyObject(data);
|
|
67
|
-
writeFileSync(filePath, JSON.stringify(emptyData, null, 2));
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
} catch (error) {
|
|
71
|
-
console.warn(`Failed to parse JSON file ${filePath}, falling back to regular file emptying:`, error);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
writeFileSync(filePath, "");
|
|
75
|
-
}
|
package/bin/impl/extras.d.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { exec } from "node:child_process";
|
|
2
|
-
export declare function readText(filePath: string, options?: BufferEncoding | {
|
|
3
|
-
encoding?: BufferEncoding | null;
|
|
4
|
-
flag?: string;
|
|
5
|
-
}): Promise<string>;
|
|
6
|
-
export declare function readTextSync(filePath: string, options?: BufferEncoding | {
|
|
7
|
-
encoding?: BufferEncoding | null;
|
|
8
|
-
flag?: string;
|
|
9
|
-
}): string;
|
|
10
|
-
export declare function readLines(filePath: string, options?: BufferEncoding | {
|
|
11
|
-
encoding?: BufferEncoding | null;
|
|
12
|
-
flag?: string;
|
|
13
|
-
}): Promise<string[]>;
|
|
14
|
-
export declare function readLinesSync(filePath: string, options?: BufferEncoding | {
|
|
15
|
-
encoding?: BufferEncoding | null;
|
|
16
|
-
flag?: string;
|
|
17
|
-
}): string[];
|
|
18
|
-
export declare function isDirectory(filePath: string): Promise<boolean>;
|
|
19
|
-
export declare function isDirectorySync(filePath: string): boolean;
|
|
20
|
-
export declare function isSymlink(filePath: string): Promise<boolean>;
|
|
21
|
-
export declare function isSymlinkSync(filePath: string): boolean;
|
|
22
|
-
export declare const execAsync: typeof exec.__promisify__;
|
|
23
|
-
export declare function setHiddenAttribute(folderPath: string): Promise<void>;
|
|
24
|
-
export declare function isHiddenAttribute(filePath: string): Promise<boolean>;
|
|
25
|
-
/**
|
|
26
|
-
* Checks if a directory is empty
|
|
27
|
-
* @param directory Path to the directory
|
|
28
|
-
* @returns Boolean indicating if the directory is empty
|
|
29
|
-
*/
|
|
30
|
-
export declare function isDirectoryEmpty(directory: string): Promise<boolean>;
|
|
31
|
-
/**
|
|
32
|
-
* Removes the specified directory if it exists and then ensures it exists.
|
|
33
|
-
* @param dir - The directory to remove and ensure.
|
|
34
|
-
*/
|
|
35
|
-
export declare function rmEnsureDir(dir: string): Promise<void>;
|
package/bin/impl/extras.js
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { ensuredir } from "@reliverse/relifso";
|
|
2
|
-
import { exec } from "node:child_process";
|
|
3
|
-
import { statSync, lstatSync } from "node:fs";
|
|
4
|
-
import { readdir } from "node:fs/promises";
|
|
5
|
-
import { stat, lstat } from "node:fs/promises";
|
|
6
|
-
import { promisify } from "node:util";
|
|
7
|
-
import { pathExists } from "./path-exists.js";
|
|
8
|
-
import { remove } from "./remove.js";
|
|
9
|
-
import { readFile, readFileSync } from "./read-file.js";
|
|
10
|
-
export async function readText(filePath, options = "utf8") {
|
|
11
|
-
const effectiveOptions = typeof options === "string" ? { encoding: options } : { ...options, encoding: options.encoding || "utf8" };
|
|
12
|
-
return readFile(filePath, effectiveOptions);
|
|
13
|
-
}
|
|
14
|
-
export function readTextSync(filePath, options = "utf8") {
|
|
15
|
-
const effectiveOptions = typeof options === "string" ? { encoding: options } : { ...options, encoding: options.encoding || "utf8" };
|
|
16
|
-
return readFileSync(filePath, effectiveOptions);
|
|
17
|
-
}
|
|
18
|
-
export async function readLines(filePath, options = { encoding: "utf8" }) {
|
|
19
|
-
const effectiveOptions = typeof options === "string" ? { encoding: options } : options;
|
|
20
|
-
const contentBuffer = await readFile(filePath, { ...effectiveOptions, encoding: null });
|
|
21
|
-
return contentBuffer.toString().split(/\r?\n/);
|
|
22
|
-
}
|
|
23
|
-
export function readLinesSync(filePath, options = { encoding: "utf8" }) {
|
|
24
|
-
const effectiveOptions = typeof options === "string" ? { encoding: options } : options;
|
|
25
|
-
const contentBuffer = readFileSync(filePath, { ...effectiveOptions, encoding: null });
|
|
26
|
-
return contentBuffer.toString().split(/\r?\n/);
|
|
27
|
-
}
|
|
28
|
-
export async function isDirectory(filePath) {
|
|
29
|
-
try {
|
|
30
|
-
const stats = await stat(filePath);
|
|
31
|
-
return stats.isDirectory();
|
|
32
|
-
} catch (error) {
|
|
33
|
-
if (error.code === "ENOENT" || error.code === "ENOTDIR") {
|
|
34
|
-
return false;
|
|
35
|
-
}
|
|
36
|
-
throw error;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
export function isDirectorySync(filePath) {
|
|
40
|
-
try {
|
|
41
|
-
const stats = statSync(filePath);
|
|
42
|
-
return stats.isDirectory();
|
|
43
|
-
} catch (error) {
|
|
44
|
-
if (error.code === "ENOENT" || error.code === "ENOTDIR") {
|
|
45
|
-
return false;
|
|
46
|
-
}
|
|
47
|
-
throw error;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
export async function isSymlink(filePath) {
|
|
51
|
-
try {
|
|
52
|
-
const stats = await lstat(filePath);
|
|
53
|
-
return stats.isSymbolicLink();
|
|
54
|
-
} catch (error) {
|
|
55
|
-
if (error.code === "ENOENT") {
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
58
|
-
throw error;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
export function isSymlinkSync(filePath) {
|
|
62
|
-
try {
|
|
63
|
-
const stats = lstatSync(filePath);
|
|
64
|
-
return stats.isSymbolicLink();
|
|
65
|
-
} catch (error) {
|
|
66
|
-
if (error.code === "ENOENT") {
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
throw error;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
export const execAsync = promisify(exec);
|
|
73
|
-
export async function setHiddenAttribute(folderPath) {
|
|
74
|
-
if (process.platform === "win32") {
|
|
75
|
-
try {
|
|
76
|
-
if (await pathExists(folderPath)) {
|
|
77
|
-
const isAlreadyHidden = await isHiddenAttribute(folderPath);
|
|
78
|
-
if (!isAlreadyHidden) {
|
|
79
|
-
await execAsync(`attrib +h "${folderPath}"`);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
} catch (error) {
|
|
83
|
-
console.warn("Failed to set hidden attribute:", String(error));
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
export async function isHiddenAttribute(filePath) {
|
|
88
|
-
if (process.platform === "win32") {
|
|
89
|
-
const attributes = await execAsync(`attrib "${filePath}"`);
|
|
90
|
-
return attributes.stdout.includes("H");
|
|
91
|
-
}
|
|
92
|
-
return false;
|
|
93
|
-
}
|
|
94
|
-
export async function isDirectoryEmpty(directory) {
|
|
95
|
-
try {
|
|
96
|
-
const files = await readdir(directory);
|
|
97
|
-
return files.length === 0;
|
|
98
|
-
} catch (_error) {
|
|
99
|
-
return false;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
export async function rmEnsureDir(dir) {
|
|
103
|
-
try {
|
|
104
|
-
if (await pathExists(dir)) {
|
|
105
|
-
await remove(dir);
|
|
106
|
-
}
|
|
107
|
-
await ensuredir(dir);
|
|
108
|
-
} catch (error) {
|
|
109
|
-
console.error(`Error while removing/ensuring directory ${dir}: ${error}`);
|
|
110
|
-
throw error;
|
|
111
|
-
}
|
|
112
|
-
}
|
package/bin/impl/json-utils.d.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import type { WriteJsonOptions } from "./write-json.js";
|
|
2
|
-
export interface JsonUtilsOptions extends WriteJsonOptions {
|
|
3
|
-
/**
|
|
4
|
-
* Whether to preserve comments when reading JSONC files
|
|
5
|
-
* @default false
|
|
6
|
-
*/
|
|
7
|
-
preserveComments?: boolean;
|
|
8
|
-
/**
|
|
9
|
-
* Whether to include comments when writing JSONC files
|
|
10
|
-
* @default false
|
|
11
|
-
*/
|
|
12
|
-
includeComments?: boolean;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Validates and repairs JSON/JSONC data if necessary.
|
|
16
|
-
* @param data - The JSON/JSONC data to validate and repair
|
|
17
|
-
* @param options - Options for validation and repair
|
|
18
|
-
* @returns The repaired JSON/JSONC data if needed, or the original data if valid
|
|
19
|
-
*/
|
|
20
|
-
export declare function validateAndRepairJson(data: unknown, options?: JsonUtilsOptions): unknown;
|
|
21
|
-
/**
|
|
22
|
-
* Ensures that the directory for the JSON/JSONC file exists and then writes the data to the file.
|
|
23
|
-
* This is a utility function to avoid circular dependencies.
|
|
24
|
-
*/
|
|
25
|
-
export declare function ensureJsonFileSync(file: string, data: unknown, options?: JsonUtilsOptions): void;
|
|
26
|
-
/**
|
|
27
|
-
* Ensures that the directory for the JSON/JSONC file exists and then asynchronously writes the data to the file.
|
|
28
|
-
* This is a utility function to avoid circular dependencies.
|
|
29
|
-
*/
|
|
30
|
-
export declare function ensureJsonFile(file: string, data: unknown, options?: JsonUtilsOptions): Promise<void>;
|
package/bin/impl/json-utils.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { dirname } from "node:path";
|
|
2
|
-
import { extname } from "node:path";
|
|
3
|
-
import { parseJsonc, isValidJsonc } from "../utils/json/regular/jsonc.js";
|
|
4
|
-
import { jsonrepair } from "../utils/json/regular/jsonrepair.js";
|
|
5
|
-
import { mkdirsSync } from "./mkdirs.js";
|
|
6
|
-
import { mkdirs } from "./mkdirs.js";
|
|
7
|
-
import { writeJsonSync } from "./write-json.js";
|
|
8
|
-
import { writeJson } from "./write-json.js";
|
|
9
|
-
export function validateAndRepairJson(data, options = {}) {
|
|
10
|
-
if (typeof data === "string") {
|
|
11
|
-
try {
|
|
12
|
-
JSON.parse(data);
|
|
13
|
-
return data;
|
|
14
|
-
} catch {
|
|
15
|
-
const isJsonc = extname(data).toLowerCase() === ".jsonc" || isValidJsonc(data);
|
|
16
|
-
if (isJsonc) {
|
|
17
|
-
try {
|
|
18
|
-
return parseJsonc(data, { preserveComments: options.preserveComments });
|
|
19
|
-
} catch {
|
|
20
|
-
return jsonrepair(data);
|
|
21
|
-
}
|
|
22
|
-
} else {
|
|
23
|
-
return jsonrepair(data);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
return data;
|
|
28
|
-
}
|
|
29
|
-
export function ensureJsonFileSync(file, data, options) {
|
|
30
|
-
const dir = dirname(file);
|
|
31
|
-
mkdirsSync(dir);
|
|
32
|
-
const repairedData = validateAndRepairJson(data, options);
|
|
33
|
-
writeJsonSync(file, repairedData, {
|
|
34
|
-
...options,
|
|
35
|
-
spaces: 2
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
export async function ensureJsonFile(file, data, options) {
|
|
39
|
-
const dir = dirname(file);
|
|
40
|
-
await mkdirs(dir);
|
|
41
|
-
const repairedData = validateAndRepairJson(data, options);
|
|
42
|
-
await writeJson(file, repairedData, {
|
|
43
|
-
...options,
|
|
44
|
-
spaces: 2
|
|
45
|
-
});
|
|
46
|
-
}
|
package/bin/impl/mkdirs.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
interface MakeDirectoryOptions {
|
|
2
|
-
recursive?: boolean;
|
|
3
|
-
mode?: number | string;
|
|
4
|
-
}
|
|
5
|
-
export declare function mkdirsSync(dir: string, options?: MakeDirectoryOptions): string | undefined;
|
|
6
|
-
export declare function mkdirs(dir: string, options?: MakeDirectoryOptions): Promise<string | undefined>;
|
|
7
|
-
export {};
|
package/bin/impl/mkdirs.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { mkdirSync, existsSync } from "node:fs";
|
|
2
|
-
import { mkdir, stat } from "node:fs/promises";
|
|
3
|
-
export function mkdirsSync(dir, options) {
|
|
4
|
-
try {
|
|
5
|
-
if (existsSync(dir)) {
|
|
6
|
-
return;
|
|
7
|
-
}
|
|
8
|
-
return mkdirSync(dir, { recursive: true, mode: options?.mode });
|
|
9
|
-
} catch (error) {
|
|
10
|
-
if (error.code === "EEXIST") {
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
throw error;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
export async function mkdirs(dir, options) {
|
|
17
|
-
try {
|
|
18
|
-
const dirStat = await stat(dir);
|
|
19
|
-
if (dirStat.isDirectory()) {
|
|
20
|
-
return void 0;
|
|
21
|
-
}
|
|
22
|
-
} catch (error) {
|
|
23
|
-
if (error.code !== "ENOENT") {
|
|
24
|
-
throw error;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
return mkdir(dir, { recursive: true, mode: options?.mode });
|
|
28
|
-
}
|
package/bin/impl/move.d.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
export interface MoveOptions {
|
|
2
|
-
/** @deprecated Use `overwrite` instead. This option will be removed in a future. */
|
|
3
|
-
force?: boolean;
|
|
4
|
-
/** Whether to overwrite existing files. Default: false */
|
|
5
|
-
overwrite?: boolean;
|
|
6
|
-
/** @deprecated Use `overwrite`. */
|
|
7
|
-
clobber?: boolean;
|
|
8
|
-
/** Maximum number of retries for EBUSY errors (default: 3) */
|
|
9
|
-
maxRetries?: number;
|
|
10
|
-
/** Delay between retries in milliseconds (default: 100) */
|
|
11
|
-
retryDelay?: number;
|
|
12
|
-
/** Whether to ensure source exists before moving (default: true) */
|
|
13
|
-
ensureSource?: boolean;
|
|
14
|
-
/** Whether to ensure destination directory exists (default: true) */
|
|
15
|
-
ensureDest?: boolean;
|
|
16
|
-
/** Whether to verify operation success (default: true) */
|
|
17
|
-
verify?: boolean;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Moves a file or directory. If the destination is a directory, the source is moved into it.
|
|
21
|
-
* If the destination exists and is a file, it will be overwritten if `overwrite` is true.
|
|
22
|
-
*
|
|
23
|
-
* @param src - The source path.
|
|
24
|
-
* @param dest - The destination path.
|
|
25
|
-
* @param options - Options for the move operation.
|
|
26
|
-
*/
|
|
27
|
-
export declare function moveSync(src: string, dest: string, options?: MoveOptions): void;
|
|
28
|
-
export declare function move(src: string, dest: string, options?: MoveOptions): Promise<void>;
|
package/bin/impl/move.js
DELETED
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import { renameSync, statSync, unlinkSync, copyFileSync } from "node:fs";
|
|
2
|
-
import { rename, stat, unlink, copyFile } from "node:fs/promises";
|
|
3
|
-
import { dirname, basename, join as joinPath } from "node:path";
|
|
4
|
-
import { mkdirsSync } from "./mkdirs.js";
|
|
5
|
-
import { mkdirs } from "./mkdirs.js";
|
|
6
|
-
import { pathExists, pathExistsSync } from "./path-exists.js";
|
|
7
|
-
export function moveSync(src, dest, options = {}) {
|
|
8
|
-
const {
|
|
9
|
-
overwrite = options.clobber ?? false,
|
|
10
|
-
maxRetries = 3,
|
|
11
|
-
retryDelay = 100,
|
|
12
|
-
ensureSource = true,
|
|
13
|
-
ensureDest = true,
|
|
14
|
-
verify = true
|
|
15
|
-
} = options;
|
|
16
|
-
if (ensureSource && !pathExistsSync(src)) {
|
|
17
|
-
throw new Error(`Source ${src} does not exist.`);
|
|
18
|
-
}
|
|
19
|
-
const srcStat = statSync(src, { throwIfNoEntry: false });
|
|
20
|
-
if (!srcStat) {
|
|
21
|
-
throw new Error(`Source ${src} does not exist.`);
|
|
22
|
-
}
|
|
23
|
-
let destFinal = dest;
|
|
24
|
-
const destStat = statSync(dest, { throwIfNoEntry: false });
|
|
25
|
-
if (destStat?.isDirectory()) {
|
|
26
|
-
destFinal = joinPath(dest, basename(src));
|
|
27
|
-
}
|
|
28
|
-
if (statSync(destFinal, { throwIfNoEntry: false }) && !overwrite) {
|
|
29
|
-
throw new Error(`Destination ${destFinal} already exists and overwrite is false.`);
|
|
30
|
-
}
|
|
31
|
-
if (ensureDest) {
|
|
32
|
-
const destDir = dirname(destFinal);
|
|
33
|
-
mkdirsSync(destDir);
|
|
34
|
-
}
|
|
35
|
-
let lastError = null;
|
|
36
|
-
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
37
|
-
try {
|
|
38
|
-
renameSync(src, destFinal);
|
|
39
|
-
if (verify && !pathExistsSync(destFinal)) {
|
|
40
|
-
throw new Error(`Move operation failed: destination ${destFinal} does not exist after move`);
|
|
41
|
-
}
|
|
42
|
-
return;
|
|
43
|
-
} catch (err) {
|
|
44
|
-
lastError = err;
|
|
45
|
-
if (err.code === "EXDEV") {
|
|
46
|
-
copyFileSync(src, destFinal);
|
|
47
|
-
unlinkSync(src);
|
|
48
|
-
if (verify && !pathExistsSync(destFinal)) {
|
|
49
|
-
throw new Error(`Copy and unlink operation failed: destination ${destFinal} does not exist after operation`);
|
|
50
|
-
}
|
|
51
|
-
return;
|
|
52
|
-
} else if (err.code === "EISDIR" || err.code === "EPERM") {
|
|
53
|
-
copyFileSync(src, destFinal);
|
|
54
|
-
unlinkSync(src);
|
|
55
|
-
if (verify && !pathExistsSync(destFinal)) {
|
|
56
|
-
throw new Error(`Copy and unlink operation failed: destination ${destFinal} does not exist after operation`);
|
|
57
|
-
}
|
|
58
|
-
return;
|
|
59
|
-
} else if (err.code === "EBUSY" && attempt < maxRetries - 1) {
|
|
60
|
-
const start = Date.now();
|
|
61
|
-
while (Date.now() - start < retryDelay) {
|
|
62
|
-
}
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
throw err;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
throw lastError;
|
|
69
|
-
}
|
|
70
|
-
export async function move(src, dest, options = {}) {
|
|
71
|
-
const {
|
|
72
|
-
overwrite = options.clobber ?? false,
|
|
73
|
-
maxRetries = 3,
|
|
74
|
-
retryDelay = 100,
|
|
75
|
-
ensureSource = true,
|
|
76
|
-
ensureDest = true,
|
|
77
|
-
verify = true
|
|
78
|
-
} = options;
|
|
79
|
-
if (ensureSource && !await pathExists(src)) {
|
|
80
|
-
throw new Error(`Source ${src} does not exist.`);
|
|
81
|
-
}
|
|
82
|
-
const srcStat = await stat(src).catch((e) => {
|
|
83
|
-
if (e.code === "ENOENT") return null;
|
|
84
|
-
throw e;
|
|
85
|
-
});
|
|
86
|
-
if (!srcStat) {
|
|
87
|
-
throw new Error(`Source ${src} does not exist.`);
|
|
88
|
-
}
|
|
89
|
-
let destFinal = dest;
|
|
90
|
-
const destStat = await stat(dest).catch((e) => {
|
|
91
|
-
if (e.code === "ENOENT") return null;
|
|
92
|
-
throw e;
|
|
93
|
-
});
|
|
94
|
-
if (destStat?.isDirectory()) {
|
|
95
|
-
destFinal = joinPath(dest, basename(src));
|
|
96
|
-
}
|
|
97
|
-
const destFinalStat = await stat(destFinal).catch((e) => {
|
|
98
|
-
if (e.code === "ENOENT") return null;
|
|
99
|
-
throw e;
|
|
100
|
-
});
|
|
101
|
-
if (destFinalStat && !overwrite) {
|
|
102
|
-
throw new Error(`Destination ${destFinal} already exists and overwrite is false.`);
|
|
103
|
-
}
|
|
104
|
-
if (ensureDest) {
|
|
105
|
-
const destDir = dirname(destFinal);
|
|
106
|
-
await mkdirs(destDir);
|
|
107
|
-
}
|
|
108
|
-
let lastError = null;
|
|
109
|
-
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
110
|
-
try {
|
|
111
|
-
await rename(src, destFinal);
|
|
112
|
-
if (verify && !await pathExists(destFinal)) {
|
|
113
|
-
throw new Error(`Move operation failed: destination ${destFinal} does not exist after move`);
|
|
114
|
-
}
|
|
115
|
-
return;
|
|
116
|
-
} catch (err) {
|
|
117
|
-
lastError = err;
|
|
118
|
-
if (err.code === "EXDEV") {
|
|
119
|
-
await copyFile(src, destFinal);
|
|
120
|
-
await unlink(src);
|
|
121
|
-
if (verify && !await pathExists(destFinal)) {
|
|
122
|
-
throw new Error(`Copy and unlink operation failed: destination ${destFinal} does not exist after operation`);
|
|
123
|
-
}
|
|
124
|
-
return;
|
|
125
|
-
} else if (err.code === "EISDIR" || err.code === "EPERM") {
|
|
126
|
-
await copyFile(src, destFinal);
|
|
127
|
-
await unlink(src);
|
|
128
|
-
if (verify && !await pathExists(destFinal)) {
|
|
129
|
-
throw new Error(`Copy and unlink operation failed: destination ${destFinal} does not exist after operation`);
|
|
130
|
-
}
|
|
131
|
-
return;
|
|
132
|
-
} else if (err.code === "EBUSY" && attempt < maxRetries - 1) {
|
|
133
|
-
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
134
|
-
continue;
|
|
135
|
-
}
|
|
136
|
-
throw err;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
throw lastError;
|
|
140
|
-
}
|