@openclaw/fs-safe 0.1.0
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/CHANGELOG.md +15 -0
- package/LICENSE +21 -0
- package/README.md +390 -0
- package/SECURITY.md +12 -0
- package/dist/absolute-path.d.ts +19 -0
- package/dist/absolute-path.d.ts.map +1 -0
- package/dist/absolute-path.js +98 -0
- package/dist/advanced.d.ts +22 -0
- package/dist/advanced.d.ts.map +1 -0
- package/dist/advanced.js +24 -0
- package/dist/archive-entry.d.ts +13 -0
- package/dist/archive-entry.d.ts.map +1 -0
- package/dist/archive-entry.js +47 -0
- package/dist/archive-kind.d.ts +8 -0
- package/dist/archive-kind.d.ts.map +1 -0
- package/dist/archive-kind.js +58 -0
- package/dist/archive-limits.d.ts +40 -0
- package/dist/archive-limits.d.ts.map +1 -0
- package/dist/archive-limits.js +92 -0
- package/dist/archive-staging.d.ts +26 -0
- package/dist/archive-staging.d.ts.map +1 -0
- package/dist/archive-staging.js +171 -0
- package/dist/archive-tar.d.ts +14 -0
- package/dist/archive-tar.d.ts.map +1 -0
- package/dist/archive-tar.js +52 -0
- package/dist/archive-utils.d.ts +3 -0
- package/dist/archive-utils.d.ts.map +1 -0
- package/dist/archive-utils.js +26 -0
- package/dist/archive-zip-preflight.d.ts +7 -0
- package/dist/archive-zip-preflight.d.ts.map +1 -0
- package/dist/archive-zip-preflight.js +170 -0
- package/dist/archive.d.ts +24 -0
- package/dist/archive.d.ts.map +1 -0
- package/dist/archive.js +251 -0
- package/dist/async-lock.d.ts +2 -0
- package/dist/async-lock.d.ts.map +1 -0
- package/dist/async-lock.js +17 -0
- package/dist/atomic.d.ts +5 -0
- package/dist/atomic.d.ts.map +1 -0
- package/dist/atomic.js +4 -0
- package/dist/boundary-file-read.d.ts +44 -0
- package/dist/boundary-file-read.d.ts.map +1 -0
- package/dist/boundary-file-read.js +129 -0
- package/dist/boundary-path.d.ts +39 -0
- package/dist/boundary-path.d.ts.map +1 -0
- package/dist/boundary-path.js +598 -0
- package/dist/config.d.ts +2 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +1 -0
- package/dist/errors.d.ts +11 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +20 -0
- package/dist/file-identity.d.ts +6 -0
- package/dist/file-identity.d.ts.map +1 -0
- package/dist/file-identity.js +14 -0
- package/dist/file-lock.d.ts +20 -0
- package/dist/file-lock.d.ts.map +1 -0
- package/dist/file-lock.js +34 -0
- package/dist/file-store.d.ts +66 -0
- package/dist/file-store.d.ts.map +1 -0
- package/dist/file-store.js +436 -0
- package/dist/file-url.d.ts +2 -0
- package/dist/file-url.d.ts.map +1 -0
- package/dist/file-url.js +1 -0
- package/dist/filename.d.ts +2 -0
- package/dist/filename.d.ts.map +1 -0
- package/dist/filename.js +25 -0
- package/dist/fs-pinned-path-helper.d.ts +7 -0
- package/dist/fs-pinned-path-helper.d.ts.map +1 -0
- package/dist/fs-pinned-path-helper.js +182 -0
- package/dist/fs-pinned-write-helper.d.ts +21 -0
- package/dist/fs-pinned-write-helper.d.ts.map +1 -0
- package/dist/fs-pinned-write-helper.js +263 -0
- package/dist/fs.d.ts +13 -0
- package/dist/fs.d.ts.map +1 -0
- package/dist/fs.js +30 -0
- package/dist/hardlink-guards.d.ts +7 -0
- package/dist/hardlink-guards.d.ts.map +1 -0
- package/dist/hardlink-guards.js +30 -0
- package/dist/home-dir.d.ts +22 -0
- package/dist/home-dir.d.ts.map +1 -0
- package/dist/home-dir.js +107 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/install-path.d.ts +20 -0
- package/dist/install-path.d.ts.map +1 -0
- package/dist/install-path.js +94 -0
- package/dist/install-safe-path.d.ts +20 -0
- package/dist/install-safe-path.d.ts.map +1 -0
- package/dist/install-safe-path.js +94 -0
- package/dist/json-document-store.d.ts +30 -0
- package/dist/json-document-store.d.ts.map +1 -0
- package/dist/json-document-store.js +68 -0
- package/dist/json-file.d.ts +3 -0
- package/dist/json-file.d.ts.map +1 -0
- package/dist/json-file.js +123 -0
- package/dist/json-files.d.ts +20 -0
- package/dist/json-files.d.ts.map +1 -0
- package/dist/json-files.js +153 -0
- package/dist/json-store.d.ts +9 -0
- package/dist/json-store.d.ts.map +1 -0
- package/dist/json-store.js +12 -0
- package/dist/json.d.ts +17 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +198 -0
- package/dist/local-file-access.d.ts +8 -0
- package/dist/local-file-access.d.ts.map +1 -0
- package/dist/local-file-access.js +73 -0
- package/dist/local-roots.d.ts +26 -0
- package/dist/local-roots.d.ts.map +1 -0
- package/dist/local-roots.js +150 -0
- package/dist/mode.d.ts +2 -0
- package/dist/mode.d.ts.map +1 -0
- package/dist/mode.js +3 -0
- package/dist/move-path.d.ts +6 -0
- package/dist/move-path.d.ts.map +1 -0
- package/dist/move-path.js +18 -0
- package/dist/path-alias-guards.d.ts +19 -0
- package/dist/path-alias-guards.d.ts.map +1 -0
- package/dist/path-alias-guards.js +21 -0
- package/dist/path-guards.d.ts +7 -0
- package/dist/path-guards.d.ts.map +1 -0
- package/dist/path-guards.js +49 -0
- package/dist/path-policy.d.ts +25 -0
- package/dist/path-policy.d.ts.map +1 -0
- package/dist/path-policy.js +50 -0
- package/dist/path-safety.d.ts +12 -0
- package/dist/path-safety.d.ts.map +1 -0
- package/dist/path-safety.js +50 -0
- package/dist/path-scope.d.ts +2 -0
- package/dist/path-scope.d.ts.map +1 -0
- package/dist/path-scope.js +1 -0
- package/dist/path.d.ts +18 -0
- package/dist/path.d.ts.map +1 -0
- package/dist/path.js +123 -0
- package/dist/permissions-public.d.ts +2 -0
- package/dist/permissions-public.d.ts.map +1 -0
- package/dist/permissions-public.js +1 -0
- package/dist/permissions.d.ts +86 -0
- package/dist/permissions.d.ts.map +1 -0
- package/dist/permissions.js +435 -0
- package/dist/pinned-helper.d.ts +9 -0
- package/dist/pinned-helper.d.ts.map +1 -0
- package/dist/pinned-helper.js +19 -0
- package/dist/pinned-open.d.ts +24 -0
- package/dist/pinned-open.d.ts.map +1 -0
- package/dist/pinned-open.js +71 -0
- package/dist/pinned-path.d.ts +7 -0
- package/dist/pinned-path.d.ts.map +1 -0
- package/dist/pinned-path.js +21 -0
- package/dist/pinned-python-config.d.ts +9 -0
- package/dist/pinned-python-config.d.ts.map +1 -0
- package/dist/pinned-python-config.js +39 -0
- package/dist/pinned-python.d.ts +12 -0
- package/dist/pinned-python.d.ts.map +1 -0
- package/dist/pinned-python.js +599 -0
- package/dist/pinned-write.d.ts +33 -0
- package/dist/pinned-write.d.ts.map +1 -0
- package/dist/pinned-write.js +198 -0
- package/dist/private-file-store.d.ts +60 -0
- package/dist/private-file-store.d.ts.map +1 -0
- package/dist/private-file-store.js +233 -0
- package/dist/private-temp-workspace.d.ts +39 -0
- package/dist/private-temp-workspace.d.ts.map +1 -0
- package/dist/private-temp-workspace.js +185 -0
- package/dist/regular-file.d.ts +38 -0
- package/dist/regular-file.d.ts.map +1 -0
- package/dist/regular-file.js +239 -0
- package/dist/replace-directory.d.ts +7 -0
- package/dist/replace-directory.d.ts.map +1 -0
- package/dist/replace-directory.js +32 -0
- package/dist/replace-file.d.ts +41 -0
- package/dist/replace-file.d.ts.map +1 -0
- package/dist/replace-file.js +325 -0
- package/dist/root-file.d.ts +44 -0
- package/dist/root-file.d.ts.map +1 -0
- package/dist/root-file.js +129 -0
- package/dist/root-path.d.ts +39 -0
- package/dist/root-path.d.ts.map +1 -0
- package/dist/root-path.js +598 -0
- package/dist/root-paths.d.ts +92 -0
- package/dist/root-paths.d.ts.map +1 -0
- package/dist/root-paths.js +338 -0
- package/dist/root.d.ts +108 -0
- package/dist/root.d.ts.map +1 -0
- package/dist/root.js +1332 -0
- package/dist/safe-open-sync.d.ts +24 -0
- package/dist/safe-open-sync.d.ts.map +1 -0
- package/dist/safe-open-sync.js +71 -0
- package/dist/safe-root.d.ts +123 -0
- package/dist/safe-root.d.ts.map +1 -0
- package/dist/safe-root.js +1060 -0
- package/dist/secret-file.d.ts +17 -0
- package/dist/secret-file.d.ts.map +1 -0
- package/dist/secret-file.js +232 -0
- package/dist/secret.d.ts +2 -0
- package/dist/secret.d.ts.map +1 -0
- package/dist/secret.js +1 -0
- package/dist/secure-file.d.ts +32 -0
- package/dist/secure-file.d.ts.map +1 -0
- package/dist/secure-file.js +163 -0
- package/dist/secure-temp-dir.d.ts +27 -0
- package/dist/secure-temp-dir.d.ts.map +1 -0
- package/dist/secure-temp-dir.js +155 -0
- package/dist/secure-temp-workspace.d.ts +25 -0
- package/dist/secure-temp-workspace.d.ts.map +1 -0
- package/dist/secure-temp-workspace.js +136 -0
- package/dist/sibling-temp-file.d.ts +16 -0
- package/dist/sibling-temp-file.d.ts.map +1 -0
- package/dist/sibling-temp-file.js +73 -0
- package/dist/sibling-temp-write.d.ts +8 -0
- package/dist/sibling-temp-write.d.ts.map +1 -0
- package/dist/sibling-temp-write.js +40 -0
- package/dist/sibling-temp.d.ts +23 -0
- package/dist/sibling-temp.d.ts.map +1 -0
- package/dist/sibling-temp.js +119 -0
- package/dist/sidecar-lock.d.ts +50 -0
- package/dist/sidecar-lock.d.ts.map +1 -0
- package/dist/sidecar-lock.js +235 -0
- package/dist/store.d.ts +3 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +2 -0
- package/dist/string-coerce.d.ts +14 -0
- package/dist/string-coerce.d.ts.map +1 -0
- package/dist/string-coerce.js +72 -0
- package/dist/symlink-parents.d.ts +12 -0
- package/dist/symlink-parents.d.ts.map +1 -0
- package/dist/symlink-parents.js +78 -0
- package/dist/temp-cleanup.d.ts +6 -0
- package/dist/temp-cleanup.d.ts.map +1 -0
- package/dist/temp-cleanup.js +42 -0
- package/dist/temp-target.d.ts +28 -0
- package/dist/temp-target.d.ts.map +1 -0
- package/dist/temp-target.js +84 -0
- package/dist/temp.d.ts +3 -0
- package/dist/temp.d.ts.map +1 -0
- package/dist/temp.js +2 -0
- package/dist/test-hooks.d.ts +9 -0
- package/dist/test-hooks.d.ts.map +1 -0
- package/dist/test-hooks.js +13 -0
- package/dist/text-atomic.d.ts +7 -0
- package/dist/text-atomic.d.ts.map +1 -0
- package/dist/text-atomic.js +13 -0
- package/dist/timing.d.ts +6 -0
- package/dist/timing.d.ts.map +1 -0
- package/dist/timing.js +24 -0
- package/dist/trash.d.ts +5 -0
- package/dist/trash.d.ts.map +1 -0
- package/dist/trash.js +127 -0
- package/dist/types.d.ts +23 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/dist/walk.d.ts +26 -0
- package/dist/walk.d.ts.map +1 -0
- package/dist/walk.js +169 -0
- package/dist/write-queue.d.ts +2 -0
- package/dist/write-queue.d.ts.map +1 -0
- package/dist/write-queue.js +18 -0
- package/package.json +117 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import fsSync from "node:fs";
|
|
3
|
+
import fs from "node:fs/promises";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { fileStore, fileStoreSync, } from "./file-store.js";
|
|
6
|
+
import { registerTempPathForExit } from "./temp-cleanup.js";
|
|
7
|
+
function sanitizeTempPrefix(prefix) {
|
|
8
|
+
const sanitized = prefix.trim().replace(/[^a-zA-Z0-9._-]/g, "-");
|
|
9
|
+
if (!sanitized || sanitized === "." || sanitized === "..") {
|
|
10
|
+
return "fs-safe-";
|
|
11
|
+
}
|
|
12
|
+
return sanitized.endsWith("-") ? sanitized : `${sanitized}-`;
|
|
13
|
+
}
|
|
14
|
+
function resolveWorkspaceLeaf(dir, fileName) {
|
|
15
|
+
const raw = fileName.trim();
|
|
16
|
+
if (!raw ||
|
|
17
|
+
raw === "." ||
|
|
18
|
+
raw === ".." ||
|
|
19
|
+
raw.includes("\0") ||
|
|
20
|
+
raw.includes("/") ||
|
|
21
|
+
raw.includes("\\") ||
|
|
22
|
+
path.basename(raw) !== raw) {
|
|
23
|
+
throw new Error(`Invalid temp workspace file name: ${JSON.stringify(fileName)}`);
|
|
24
|
+
}
|
|
25
|
+
return path.join(dir, raw);
|
|
26
|
+
}
|
|
27
|
+
function assertWorkspaceFileName(fileName) {
|
|
28
|
+
resolveWorkspaceLeaf(".", fileName);
|
|
29
|
+
return fileName.trim();
|
|
30
|
+
}
|
|
31
|
+
async function ensurePrivateDirectory(dir, mode) {
|
|
32
|
+
await fs.mkdir(dir, { recursive: true, mode });
|
|
33
|
+
const stat = await fs.stat(dir);
|
|
34
|
+
if (!stat.isDirectory()) {
|
|
35
|
+
throw new Error(`Temp root must be a directory: ${dir}`);
|
|
36
|
+
}
|
|
37
|
+
await fs.chmod(dir, mode).catch(() => undefined);
|
|
38
|
+
}
|
|
39
|
+
function ensurePrivateDirectorySync(dir, mode) {
|
|
40
|
+
fsSync.mkdirSync(dir, { recursive: true, mode });
|
|
41
|
+
const stat = fsSync.statSync(dir);
|
|
42
|
+
if (!stat.isDirectory()) {
|
|
43
|
+
throw new Error(`Temp root must be a directory: ${dir}`);
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
fsSync.chmodSync(dir, mode);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// Best-effort on platforms that do not enforce POSIX modes.
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async function createTempWorkspace(options) {
|
|
53
|
+
const dirMode = options.dirMode ?? 0o700;
|
|
54
|
+
const mode = options.mode ?? 0o600;
|
|
55
|
+
const requestedRoot = path.resolve(options.rootDir);
|
|
56
|
+
const root = await fs.realpath(requestedRoot).catch(() => requestedRoot);
|
|
57
|
+
await ensurePrivateDirectory(root, dirMode);
|
|
58
|
+
const dir = await fs.mkdtemp(path.join(root, sanitizeTempPrefix(options.prefix)));
|
|
59
|
+
const unregisterTempDir = registerTempPathForExit(dir, { recursive: true });
|
|
60
|
+
await fs.chmod(dir, dirMode).catch(() => undefined);
|
|
61
|
+
const stat = await fs.lstat(dir);
|
|
62
|
+
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
63
|
+
throw new Error(`Temp workspace must be a directory: ${dir}`);
|
|
64
|
+
}
|
|
65
|
+
const store = fileStore({ rootDir: dir, private: true, dirMode, mode });
|
|
66
|
+
return {
|
|
67
|
+
dir,
|
|
68
|
+
store,
|
|
69
|
+
path: (fileName) => resolveWorkspaceLeaf(dir, fileName),
|
|
70
|
+
write: async (fileName, data) => await store.write(assertWorkspaceFileName(fileName), data, { mode }),
|
|
71
|
+
writeText: async (fileName, data) => await store.writeText(assertWorkspaceFileName(fileName), data, { mode }),
|
|
72
|
+
writeJson: async (fileName, data, writeOptions) => await store.writeJson(assertWorkspaceFileName(fileName), data, {
|
|
73
|
+
mode,
|
|
74
|
+
trailingNewline: writeOptions?.trailingNewline,
|
|
75
|
+
}),
|
|
76
|
+
copyIn: async (fileName, sourcePath) => await store.copyIn(assertWorkspaceFileName(fileName), sourcePath, { mode }),
|
|
77
|
+
read: async (fileName) => await store.readBytes(assertWorkspaceFileName(fileName)),
|
|
78
|
+
cleanup: async () => {
|
|
79
|
+
try {
|
|
80
|
+
await fs.rm(dir, { recursive: true, force: true }).catch(() => undefined);
|
|
81
|
+
}
|
|
82
|
+
finally {
|
|
83
|
+
unregisterTempDir();
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
[Symbol.asyncDispose]: async () => {
|
|
87
|
+
try {
|
|
88
|
+
await fs.rm(dir, { recursive: true, force: true }).catch(() => undefined);
|
|
89
|
+
}
|
|
90
|
+
finally {
|
|
91
|
+
unregisterTempDir();
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
export async function tempWorkspace(options) {
|
|
97
|
+
return await createTempWorkspace(options);
|
|
98
|
+
}
|
|
99
|
+
export async function withTempWorkspace(options, run) {
|
|
100
|
+
const workspace = await createTempWorkspace({
|
|
101
|
+
...options,
|
|
102
|
+
prefix: `${sanitizeTempPrefix(options.prefix)}${randomUUID()}-`,
|
|
103
|
+
});
|
|
104
|
+
try {
|
|
105
|
+
return await run(workspace);
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
await workspace.cleanup();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
export function tempWorkspaceSync(options) {
|
|
112
|
+
const dirMode = options.dirMode ?? 0o700;
|
|
113
|
+
const mode = options.mode ?? 0o600;
|
|
114
|
+
const requestedRoot = path.resolve(options.rootDir);
|
|
115
|
+
let root = requestedRoot;
|
|
116
|
+
try {
|
|
117
|
+
root = fsSync.realpathSync.native(requestedRoot);
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
root = requestedRoot;
|
|
121
|
+
}
|
|
122
|
+
ensurePrivateDirectorySync(root, dirMode);
|
|
123
|
+
const dir = fsSync.mkdtempSync(path.join(root, sanitizeTempPrefix(options.prefix)));
|
|
124
|
+
const unregisterTempDir = registerTempPathForExit(dir, { recursive: true });
|
|
125
|
+
try {
|
|
126
|
+
fsSync.chmodSync(dir, dirMode);
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
// Best-effort on platforms that do not enforce POSIX modes.
|
|
130
|
+
}
|
|
131
|
+
const stat = fsSync.lstatSync(dir);
|
|
132
|
+
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
133
|
+
throw new Error(`Temp workspace must be a directory: ${dir}`);
|
|
134
|
+
}
|
|
135
|
+
const store = fileStoreSync({ rootDir: dir, private: true, dirMode, mode });
|
|
136
|
+
return {
|
|
137
|
+
dir,
|
|
138
|
+
store,
|
|
139
|
+
path: (fileName) => resolveWorkspaceLeaf(dir, fileName),
|
|
140
|
+
write: (fileName, data) => store.write(assertWorkspaceFileName(fileName), data, { mode }),
|
|
141
|
+
writeText: (fileName, data) => store.writeText(assertWorkspaceFileName(fileName), data, { mode }),
|
|
142
|
+
writeJson: (fileName, data, writeOptions) => store.writeJson(assertWorkspaceFileName(fileName), data, {
|
|
143
|
+
mode,
|
|
144
|
+
trailingNewline: writeOptions?.trailingNewline,
|
|
145
|
+
}),
|
|
146
|
+
read: (fileName) => {
|
|
147
|
+
const filePath = store.path(assertWorkspaceFileName(fileName));
|
|
148
|
+
return fsSync.readFileSync(filePath);
|
|
149
|
+
},
|
|
150
|
+
cleanup: () => {
|
|
151
|
+
try {
|
|
152
|
+
fsSync.rmSync(dir, { recursive: true, force: true });
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
// Best-effort cleanup.
|
|
156
|
+
}
|
|
157
|
+
finally {
|
|
158
|
+
unregisterTempDir();
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
[Symbol.dispose]: () => {
|
|
162
|
+
try {
|
|
163
|
+
fsSync.rmSync(dir, { recursive: true, force: true });
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
// Best-effort cleanup.
|
|
167
|
+
}
|
|
168
|
+
finally {
|
|
169
|
+
unregisterTempDir();
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
export function withTempWorkspaceSync(options, run) {
|
|
175
|
+
const workspace = tempWorkspaceSync({
|
|
176
|
+
...options,
|
|
177
|
+
prefix: `${sanitizeTempPrefix(options.prefix)}${randomUUID()}-`,
|
|
178
|
+
});
|
|
179
|
+
try {
|
|
180
|
+
return run(workspace);
|
|
181
|
+
}
|
|
182
|
+
finally {
|
|
183
|
+
workspace.cleanup();
|
|
184
|
+
}
|
|
185
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Stats } from "node:fs";
|
|
2
|
+
import fsSync from "node:fs";
|
|
3
|
+
export type RegularFileStatResult = {
|
|
4
|
+
missing: true;
|
|
5
|
+
} | {
|
|
6
|
+
missing: false;
|
|
7
|
+
stat: Stats;
|
|
8
|
+
};
|
|
9
|
+
type RegularFileAppendFlagConstants = Pick<typeof fsSync.constants, "O_APPEND" | "O_CREAT" | "O_WRONLY"> & Partial<Pick<typeof fsSync.constants, "O_NOFOLLOW">>;
|
|
10
|
+
export type AppendRegularFileOptions = {
|
|
11
|
+
filePath: string;
|
|
12
|
+
content: string | Uint8Array;
|
|
13
|
+
encoding?: BufferEncoding;
|
|
14
|
+
maxFileBytes?: number;
|
|
15
|
+
mode?: number;
|
|
16
|
+
rejectSymlinkParents?: boolean;
|
|
17
|
+
};
|
|
18
|
+
export declare function resolveRegularFileAppendFlags(constants?: RegularFileAppendFlagConstants): number;
|
|
19
|
+
export declare function statRegularFile(filePath: string): Promise<RegularFileStatResult>;
|
|
20
|
+
export declare function statRegularFileSync(filePath: string): RegularFileStatResult;
|
|
21
|
+
export declare function readRegularFile(params: {
|
|
22
|
+
filePath: string;
|
|
23
|
+
maxBytes?: number;
|
|
24
|
+
}): Promise<{
|
|
25
|
+
buffer: Buffer;
|
|
26
|
+
stat: Stats;
|
|
27
|
+
}>;
|
|
28
|
+
export declare function readRegularFileSync(params: {
|
|
29
|
+
filePath: string;
|
|
30
|
+
maxBytes?: number;
|
|
31
|
+
}): {
|
|
32
|
+
buffer: Buffer;
|
|
33
|
+
stat: Stats;
|
|
34
|
+
};
|
|
35
|
+
export declare function appendRegularFile(options: AppendRegularFileOptions): Promise<void>;
|
|
36
|
+
export declare function appendRegularFileSync(options: AppendRegularFileOptions): void;
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=regular-file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"regular-file.d.ts","sourceRoot":"","sources":["../src/regular-file.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,MAAM,MAAM,SAAS,CAAC;AAO7B,MAAM,MAAM,qBAAqB,GAAG;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC;AAExF,KAAK,8BAA8B,GAAG,IAAI,CACxC,OAAO,MAAM,CAAC,SAAS,EACvB,UAAU,GAAG,SAAS,GAAG,UAAU,CACpC,GACC,OAAO,CAAC,IAAI,CAAC,OAAO,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC;AAEvD,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,UAAU,CAAC;IAC7B,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC,CAAC;AAEF,wBAAgB,6BAA6B,CAC3C,SAAS,GAAE,8BAAiD,GAC3D,MAAM,CAQR;AAWD,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CActF;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,qBAAqB,CAc3E;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC,CA6B3C;AA0CD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG;IACpF,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,KAAK,CAAC;CACb,CAoBA;AAmBD,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuDxF;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,wBAAwB,GAAG,IAAI,CA2D7E"}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import fsSync from "node:fs";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { sameFileIdentity } from "./file-identity.js";
|
|
5
|
+
import { isNotFoundPathError } from "./path.js";
|
|
6
|
+
import { assertNoSymlinkParents, assertNoSymlinkParentsSync } from "./symlink-parents.js";
|
|
7
|
+
export function resolveRegularFileAppendFlags(constants = fsSync.constants) {
|
|
8
|
+
const noFollow = constants.O_NOFOLLOW;
|
|
9
|
+
return (constants.O_CREAT |
|
|
10
|
+
constants.O_APPEND |
|
|
11
|
+
constants.O_WRONLY |
|
|
12
|
+
(typeof noFollow === "number" ? noFollow : 0));
|
|
13
|
+
}
|
|
14
|
+
function resolveRegularFileReadFlags() {
|
|
15
|
+
return (fsSync.constants.O_RDONLY |
|
|
16
|
+
(typeof fsSync.constants.O_NOFOLLOW === "number" && process.platform !== "win32"
|
|
17
|
+
? fsSync.constants.O_NOFOLLOW
|
|
18
|
+
: 0));
|
|
19
|
+
}
|
|
20
|
+
export async function statRegularFile(filePath) {
|
|
21
|
+
let stat;
|
|
22
|
+
try {
|
|
23
|
+
stat = await fs.lstat(filePath);
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
if (isNotFoundPathError(err)) {
|
|
27
|
+
return { missing: true };
|
|
28
|
+
}
|
|
29
|
+
throw err;
|
|
30
|
+
}
|
|
31
|
+
if (stat.isSymbolicLink() || !stat.isFile()) {
|
|
32
|
+
throw new Error("path must be a regular file");
|
|
33
|
+
}
|
|
34
|
+
return { missing: false, stat };
|
|
35
|
+
}
|
|
36
|
+
export function statRegularFileSync(filePath) {
|
|
37
|
+
let stat;
|
|
38
|
+
try {
|
|
39
|
+
stat = fsSync.lstatSync(filePath);
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
if (isNotFoundPathError(err)) {
|
|
43
|
+
return { missing: true };
|
|
44
|
+
}
|
|
45
|
+
throw err;
|
|
46
|
+
}
|
|
47
|
+
if (stat.isSymbolicLink() || !stat.isFile()) {
|
|
48
|
+
throw new Error("path must be a regular file");
|
|
49
|
+
}
|
|
50
|
+
return { missing: false, stat };
|
|
51
|
+
}
|
|
52
|
+
export async function readRegularFile(params) {
|
|
53
|
+
const result = await statRegularFile(params.filePath);
|
|
54
|
+
if (result.missing) {
|
|
55
|
+
throw Object.assign(new Error(`File not found: ${params.filePath}`), { code: "ENOENT" });
|
|
56
|
+
}
|
|
57
|
+
if (params.maxBytes !== undefined && result.stat.size > params.maxBytes) {
|
|
58
|
+
throw new Error(`File exceeds ${params.maxBytes} bytes: ${params.filePath}`);
|
|
59
|
+
}
|
|
60
|
+
const handle = await fs.open(params.filePath, resolveRegularFileReadFlags());
|
|
61
|
+
try {
|
|
62
|
+
const stat = await handle.stat();
|
|
63
|
+
verifyStableReadTarget({
|
|
64
|
+
filePath: params.filePath,
|
|
65
|
+
pathStat: await fs.lstat(params.filePath),
|
|
66
|
+
postOpenStat: stat,
|
|
67
|
+
preOpenStat: result.stat,
|
|
68
|
+
});
|
|
69
|
+
if (params.maxBytes !== undefined && stat.size > params.maxBytes) {
|
|
70
|
+
throw new Error(`File exceeds ${params.maxBytes} bytes: ${params.filePath}`);
|
|
71
|
+
}
|
|
72
|
+
const buffer = await handle.readFile();
|
|
73
|
+
if (params.maxBytes !== undefined && buffer.byteLength > params.maxBytes) {
|
|
74
|
+
throw new Error(`File exceeds ${params.maxBytes} bytes: ${params.filePath}`);
|
|
75
|
+
}
|
|
76
|
+
return { buffer, stat };
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
await handle.close();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function verifyStableReadTarget(params) {
|
|
83
|
+
if (!params.postOpenStat.isFile() || params.pathStat.isSymbolicLink() || !params.pathStat.isFile()) {
|
|
84
|
+
throw new Error(`File is not a regular file: ${params.filePath}`);
|
|
85
|
+
}
|
|
86
|
+
if (!sameFileIdentity(params.preOpenStat, params.postOpenStat) ||
|
|
87
|
+
!sameFileIdentity(params.pathStat, params.postOpenStat)) {
|
|
88
|
+
throw new Error(`File changed during read: ${params.filePath}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function readOpenedRegularFileSync(params) {
|
|
92
|
+
const stat = fsSync.fstatSync(params.fd);
|
|
93
|
+
verifyStableReadTarget({
|
|
94
|
+
filePath: params.filePath,
|
|
95
|
+
pathStat: fsSync.lstatSync(params.filePath),
|
|
96
|
+
postOpenStat: stat,
|
|
97
|
+
preOpenStat: params.preOpenStat,
|
|
98
|
+
});
|
|
99
|
+
if (params.maxBytes !== undefined && stat.size > params.maxBytes) {
|
|
100
|
+
throw new Error(`File exceeds ${params.maxBytes} bytes: ${params.filePath}`);
|
|
101
|
+
}
|
|
102
|
+
const buffer = fsSync.readFileSync(params.fd);
|
|
103
|
+
if (params.maxBytes !== undefined && buffer.byteLength > params.maxBytes) {
|
|
104
|
+
throw new Error(`File exceeds ${params.maxBytes} bytes: ${params.filePath}`);
|
|
105
|
+
}
|
|
106
|
+
return { buffer, stat };
|
|
107
|
+
}
|
|
108
|
+
export function readRegularFileSync(params) {
|
|
109
|
+
const result = statRegularFileSync(params.filePath);
|
|
110
|
+
if (result.missing) {
|
|
111
|
+
throw Object.assign(new Error(`File not found: ${params.filePath}`), { code: "ENOENT" });
|
|
112
|
+
}
|
|
113
|
+
if (params.maxBytes !== undefined && result.stat.size > params.maxBytes) {
|
|
114
|
+
throw new Error(`File exceeds ${params.maxBytes} bytes: ${params.filePath}`);
|
|
115
|
+
}
|
|
116
|
+
const fd = fsSync.openSync(params.filePath, resolveRegularFileReadFlags());
|
|
117
|
+
try {
|
|
118
|
+
return readOpenedRegularFileSync({
|
|
119
|
+
fd,
|
|
120
|
+
filePath: params.filePath,
|
|
121
|
+
preOpenStat: result.stat,
|
|
122
|
+
maxBytes: params.maxBytes,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
finally {
|
|
126
|
+
fsSync.closeSync(fd);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function verifyStableAppendTarget(params) {
|
|
130
|
+
if (!params.postOpenStat.isFile()) {
|
|
131
|
+
throw new Error(`Refusing to append to non-file: ${params.filePath}`);
|
|
132
|
+
}
|
|
133
|
+
if (params.postOpenStat.nlink > 1) {
|
|
134
|
+
throw new Error(`Refusing to append to hardlinked file: ${params.filePath}`);
|
|
135
|
+
}
|
|
136
|
+
const pre = params.preOpenStat;
|
|
137
|
+
if (pre && (pre.dev !== params.postOpenStat.dev || pre.ino !== params.postOpenStat.ino)) {
|
|
138
|
+
throw new Error(`Refusing to append after file changed: ${params.filePath}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
export async function appendRegularFile(options) {
|
|
142
|
+
if (options.rejectSymlinkParents === true) {
|
|
143
|
+
const resolvedDir = path.resolve(path.dirname(options.filePath));
|
|
144
|
+
await assertNoSymlinkParents({
|
|
145
|
+
rootDir: path.parse(resolvedDir).root,
|
|
146
|
+
targetPath: resolvedDir,
|
|
147
|
+
allowMissing: false,
|
|
148
|
+
allowRootChildSymlink: true,
|
|
149
|
+
requireDirectories: true,
|
|
150
|
+
messagePrefix: "Refusing to append under",
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
let preOpenStat;
|
|
154
|
+
try {
|
|
155
|
+
const stat = await fs.lstat(options.filePath);
|
|
156
|
+
if (stat.isSymbolicLink()) {
|
|
157
|
+
throw new Error(`Refusing to append through symlink: ${options.filePath}`);
|
|
158
|
+
}
|
|
159
|
+
if (!stat.isFile()) {
|
|
160
|
+
throw new Error(`Refusing to append to non-file: ${options.filePath}`);
|
|
161
|
+
}
|
|
162
|
+
preOpenStat = stat;
|
|
163
|
+
}
|
|
164
|
+
catch (err) {
|
|
165
|
+
if (!isNotFoundPathError(err)) {
|
|
166
|
+
throw err;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
const contentBytes = Buffer.isBuffer(options.content)
|
|
170
|
+
? options.content.byteLength
|
|
171
|
+
: Buffer.byteLength(options.content, options.encoding ?? "utf8");
|
|
172
|
+
if (options.maxFileBytes !== undefined &&
|
|
173
|
+
(preOpenStat?.size ?? 0) + contentBytes > options.maxFileBytes) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
const handle = await fs.open(options.filePath, resolveRegularFileAppendFlags(), options.mode ?? 0o600);
|
|
177
|
+
try {
|
|
178
|
+
const stat = await handle.stat();
|
|
179
|
+
verifyStableAppendTarget({ preOpenStat, postOpenStat: stat, filePath: options.filePath });
|
|
180
|
+
if (options.maxFileBytes !== undefined && stat.size + contentBytes > options.maxFileBytes) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
await handle.chmod(options.mode ?? 0o600);
|
|
184
|
+
await handle.appendFile(options.content, options.encoding ?? "utf8");
|
|
185
|
+
}
|
|
186
|
+
finally {
|
|
187
|
+
await handle.close();
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
export function appendRegularFileSync(options) {
|
|
191
|
+
if (options.rejectSymlinkParents === true) {
|
|
192
|
+
const resolvedDir = path.resolve(path.dirname(options.filePath));
|
|
193
|
+
assertNoSymlinkParentsSync({
|
|
194
|
+
rootDir: path.parse(resolvedDir).root,
|
|
195
|
+
targetPath: resolvedDir,
|
|
196
|
+
allowMissing: false,
|
|
197
|
+
allowRootChildSymlink: true,
|
|
198
|
+
requireDirectories: true,
|
|
199
|
+
messagePrefix: "Refusing to append under",
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
let preOpenStat;
|
|
203
|
+
try {
|
|
204
|
+
const stat = fsSync.lstatSync(options.filePath);
|
|
205
|
+
if (stat.isSymbolicLink()) {
|
|
206
|
+
throw new Error(`Refusing to append through symlink: ${options.filePath}`);
|
|
207
|
+
}
|
|
208
|
+
if (!stat.isFile()) {
|
|
209
|
+
throw new Error(`Refusing to append to non-file: ${options.filePath}`);
|
|
210
|
+
}
|
|
211
|
+
preOpenStat = stat;
|
|
212
|
+
}
|
|
213
|
+
catch (err) {
|
|
214
|
+
if (!isNotFoundPathError(err)) {
|
|
215
|
+
throw err;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
const contentBuffer = typeof options.content === "string"
|
|
219
|
+
? Buffer.from(options.content, options.encoding ?? "utf8")
|
|
220
|
+
: Buffer.from(options.content);
|
|
221
|
+
if (options.maxFileBytes !== undefined &&
|
|
222
|
+
(preOpenStat?.size ?? 0) + contentBuffer.byteLength > options.maxFileBytes) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
const fd = fsSync.openSync(options.filePath, resolveRegularFileAppendFlags(), options.mode ?? 0o600);
|
|
226
|
+
try {
|
|
227
|
+
const stat = fsSync.fstatSync(fd);
|
|
228
|
+
verifyStableAppendTarget({ preOpenStat, postOpenStat: stat, filePath: options.filePath });
|
|
229
|
+
if (options.maxFileBytes !== undefined &&
|
|
230
|
+
stat.size + contentBuffer.byteLength > options.maxFileBytes) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
fsSync.fchmodSync(fd, options.mode ?? 0o600);
|
|
234
|
+
fsSync.writeSync(fd, contentBuffer, 0, contentBuffer.byteLength);
|
|
235
|
+
}
|
|
236
|
+
finally {
|
|
237
|
+
fsSync.closeSync(fd);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type ReplaceDirectoryAtomicOptions = {
|
|
2
|
+
stagedDir: string;
|
|
3
|
+
targetDir: string;
|
|
4
|
+
backupPrefix?: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function replaceDirectoryAtomic(options: ReplaceDirectoryAtomicOptions): Promise<void>;
|
|
7
|
+
//# sourceMappingURL=replace-directory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replace-directory.d.ts","sourceRoot":"","sources":["../src/replace-directory.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,6BAA6B,GAAG;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,IAAI,CAAC,CAiCf"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
export async function replaceDirectoryAtomic(options) {
|
|
4
|
+
const targetDir = path.resolve(options.targetDir);
|
|
5
|
+
const stagedDir = path.resolve(options.stagedDir);
|
|
6
|
+
const parentDir = path.dirname(targetDir);
|
|
7
|
+
const backupDir = path.join(parentDir, `${options.backupPrefix ?? ".fs-safe-dir-backup-"}${process.pid}-${Date.now()}`);
|
|
8
|
+
let backupCreated = false;
|
|
9
|
+
await fs.mkdir(parentDir, { recursive: true });
|
|
10
|
+
try {
|
|
11
|
+
await fs.rename(targetDir, backupDir);
|
|
12
|
+
backupCreated = true;
|
|
13
|
+
}
|
|
14
|
+
catch (err) {
|
|
15
|
+
if (err.code !== "ENOENT") {
|
|
16
|
+
throw err;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
await fs.rename(stagedDir, targetDir);
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
if (backupCreated) {
|
|
24
|
+
await fs.rename(backupDir, targetDir).catch(() => undefined);
|
|
25
|
+
backupCreated = false;
|
|
26
|
+
}
|
|
27
|
+
throw err;
|
|
28
|
+
}
|
|
29
|
+
if (backupCreated) {
|
|
30
|
+
await fs.rm(backupDir, { recursive: true, force: true });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import syncFs from "node:fs";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
export type ReplaceFileAtomicFileSystem = {
|
|
4
|
+
promises: Pick<typeof fs, "mkdir" | "chmod" | "writeFile" | "rename" | "copyFile" | "unlink" | "rm" | "open" | "stat" | "lstat">;
|
|
5
|
+
};
|
|
6
|
+
export type ReplaceFileAtomicSyncFileSystem = Pick<typeof syncFs, "mkdirSync" | "chmodSync" | "writeFileSync" | "renameSync" | "copyFileSync" | "unlinkSync" | "rmSync" | "openSync" | "fsyncSync" | "closeSync" | "statSync" | "lstatSync">;
|
|
7
|
+
type ReplaceFileAtomicBaseOptions = {
|
|
8
|
+
filePath: string;
|
|
9
|
+
content: string | Uint8Array;
|
|
10
|
+
dirMode?: number;
|
|
11
|
+
mode?: number;
|
|
12
|
+
preserveExistingMode?: boolean;
|
|
13
|
+
tempPrefix?: string;
|
|
14
|
+
renameMaxRetries?: number;
|
|
15
|
+
renameRetryBaseDelayMs?: number;
|
|
16
|
+
copyFallbackOnPermissionError?: boolean;
|
|
17
|
+
syncTempFile?: boolean;
|
|
18
|
+
syncParentDir?: boolean;
|
|
19
|
+
throwOnCleanupError?: boolean;
|
|
20
|
+
};
|
|
21
|
+
export type ReplaceFileAtomicOptions = ReplaceFileAtomicBaseOptions & {
|
|
22
|
+
fileSystem?: ReplaceFileAtomicFileSystem;
|
|
23
|
+
beforeRename?: (params: {
|
|
24
|
+
filePath: string;
|
|
25
|
+
tempPath: string;
|
|
26
|
+
}) => Promise<void>;
|
|
27
|
+
};
|
|
28
|
+
export type ReplaceFileAtomicSyncOptions = ReplaceFileAtomicBaseOptions & {
|
|
29
|
+
fileSystem?: ReplaceFileAtomicSyncFileSystem;
|
|
30
|
+
beforeRename?: (params: {
|
|
31
|
+
filePath: string;
|
|
32
|
+
tempPath: string;
|
|
33
|
+
}) => void;
|
|
34
|
+
};
|
|
35
|
+
export type ReplaceFileAtomicResult = {
|
|
36
|
+
method: "rename" | "copy-fallback";
|
|
37
|
+
};
|
|
38
|
+
export declare function replaceFileAtomic(options: ReplaceFileAtomicOptions): Promise<ReplaceFileAtomicResult>;
|
|
39
|
+
export declare function replaceFileAtomicSync(options: ReplaceFileAtomicSyncOptions): ReplaceFileAtomicResult;
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=replace-file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replace-file.d.ts","sourceRoot":"","sources":["../src/replace-file.ts"],"names":[],"mappings":"AACA,OAAO,MAAM,MAAM,SAAS,CAAC;AAE7B,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAKlC,MAAM,MAAM,2BAA2B,GAAG;IACxC,QAAQ,EAAE,IAAI,CACZ,OAAO,EAAE,EACP,OAAO,GACP,OAAO,GACP,WAAW,GACX,QAAQ,GACR,UAAU,GACV,QAAQ,GACR,IAAI,GACJ,MAAM,GACN,MAAM,GACN,OAAO,CACV,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,+BAA+B,GAAG,IAAI,CAChD,OAAO,MAAM,EACX,WAAW,GACX,WAAW,GACX,eAAe,GACf,YAAY,GACZ,cAAc,GACd,YAAY,GACZ,QAAQ,GACR,UAAU,GACV,WAAW,GACX,WAAW,GACX,UAAU,GACV,WAAW,CACd,CAAC;AAEF,KAAK,4BAA4B,GAAG;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,UAAU,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,6BAA6B,CAAC,EAAE,OAAO,CAAC;IACxC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG,4BAA4B,GAAG;IACpE,UAAU,CAAC,EAAE,2BAA2B,CAAC;IACzC,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAClF,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG,4BAA4B,GAAG;IACxE,UAAU,CAAC,EAAE,+BAA+B,CAAC;IAC7C,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CACzE,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,EAAE,QAAQ,GAAG,eAAe,CAAC;CACpC,CAAC;AA+NF,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,uBAAuB,CAAC,CAMlC;AAyDD,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,4BAA4B,GACpC,uBAAuB,CAiEzB"}
|