@interactive-inc/docs-client 1.0.20 → 1.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/build/doc-file-system-DEmPPJPE.d.ts +205 -0
- package/build/doc-file-system.interface-C5vpYrOL.d.ts +135 -0
- package/build/file-system-json.d.ts +224 -0
- package/build/file-system-json.js +765 -0
- package/build/file-system-mock.d.ts +112 -0
- package/build/file-system-mock.js +513 -0
- package/build/file-system-node.d.ts +16 -0
- package/build/file-system-node.js +544 -0
- package/build/file-system-octokit.d.ts +166 -0
- package/build/file-system-octokit.js +715 -0
- package/build/file-system.d.ts +119 -0
- package/build/file-system.js +523 -0
- package/build/index.d.ts +1236 -2121
- package/build/index.js +3390 -5329
- package/build/models.js +4 -75
- package/package.json +7 -2
- package/tmp/docs-studio/files/a.md +9 -0
- package/tmp/docs-studio/pages/delete-document.md +7 -0
- package/tmp/docs-studio/pages/document-editor.md +9 -0
- package/tmp/docs-studio/pages/edit-document-content.md +7 -0
- package/tmp/docs-studio/pages/index.md +14 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { D as DocFileSystemInterface, a as DocPathSystem } from './doc-file-system.interface-C5vpYrOL.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* In-memory file system for testing
|
|
5
|
+
*/
|
|
6
|
+
declare class DocFileSystemMock implements DocFileSystemInterface {
|
|
7
|
+
private files;
|
|
8
|
+
private readonly pathSystem;
|
|
9
|
+
private readonly basePath;
|
|
10
|
+
constructor(props: {
|
|
11
|
+
basePath: string;
|
|
12
|
+
pathSystem?: DocPathSystem;
|
|
13
|
+
skipDefaultFiles?: boolean;
|
|
14
|
+
});
|
|
15
|
+
/**
|
|
16
|
+
* PathSystem accessor (for testing)
|
|
17
|
+
*/
|
|
18
|
+
getPathSystem(): DocPathSystem;
|
|
19
|
+
/**
|
|
20
|
+
* Get file name from path
|
|
21
|
+
*/
|
|
22
|
+
readFileName(relativePath: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Get file extension from path
|
|
25
|
+
*/
|
|
26
|
+
readFileExtension(relativePath: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* Get directory path where the file exists
|
|
29
|
+
*/
|
|
30
|
+
readFileDirectory(relativePath: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Get base path
|
|
33
|
+
*/
|
|
34
|
+
getBasePath(): string;
|
|
35
|
+
/**
|
|
36
|
+
* Convert relative path to absolute path
|
|
37
|
+
*/
|
|
38
|
+
resolve(relativePath: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* Normalize path using basePath
|
|
41
|
+
*/
|
|
42
|
+
private normalizePath;
|
|
43
|
+
/**
|
|
44
|
+
* Create instance (mock data is automatically loaded)
|
|
45
|
+
*/
|
|
46
|
+
static create(basePath?: string): DocFileSystemMock;
|
|
47
|
+
/**
|
|
48
|
+
* Factory method for testing
|
|
49
|
+
*/
|
|
50
|
+
static createWithFiles(props: {
|
|
51
|
+
basePath?: string;
|
|
52
|
+
fileContents?: Record<string, string>;
|
|
53
|
+
}): DocFileSystemMock;
|
|
54
|
+
readFile(filePath: string): Promise<string | null | Error>;
|
|
55
|
+
writeFile(filePath: string, content: string): Promise<Error | null>;
|
|
56
|
+
deleteFile(filePath: string): Promise<Error | null>;
|
|
57
|
+
exists(filePath: string): Promise<boolean>;
|
|
58
|
+
copyFile(source: string, destination: string): Promise<Error | null>;
|
|
59
|
+
moveFile(source: string, destination: string): Promise<Error | null>;
|
|
60
|
+
readDirectory(directoryPath: string): Promise<string[]>;
|
|
61
|
+
readDirectoryRecursive(directoryPath: string): Promise<string[]>;
|
|
62
|
+
readDirectoryFilePaths(directoryPath: string): Promise<string[] | Error>;
|
|
63
|
+
createEmptyDirectory(_directoryPath: string): Promise<Error | null>;
|
|
64
|
+
deleteDirectory(directoryPath: string): Promise<void>;
|
|
65
|
+
getFileSize(filePath: string): Promise<number | Error>;
|
|
66
|
+
getFileUpdatedTime(filePath: string): Promise<Date | Error>;
|
|
67
|
+
getFileCreatedTime(filePath: string): Promise<Date | Error>;
|
|
68
|
+
isDirectory(relativePath: string): Promise<boolean>;
|
|
69
|
+
isFile(relativePath: string): Promise<boolean>;
|
|
70
|
+
/**
|
|
71
|
+
* Get list of entries in directory
|
|
72
|
+
*/
|
|
73
|
+
readDirectoryFileNames(directoryPath?: string): Promise<string[] | Error>;
|
|
74
|
+
/**
|
|
75
|
+
* Check if directory exists
|
|
76
|
+
*/
|
|
77
|
+
directoryExists(relativePath: string): Promise<boolean>;
|
|
78
|
+
/**
|
|
79
|
+
* Check if file exists
|
|
80
|
+
*/
|
|
81
|
+
fileExists(relativePath: string): Promise<boolean>;
|
|
82
|
+
/**
|
|
83
|
+
* Create directory if it doesn't exist
|
|
84
|
+
*/
|
|
85
|
+
createDirectory(_relativePath: string): Promise<Error | null>;
|
|
86
|
+
/**
|
|
87
|
+
* Clear all files
|
|
88
|
+
*/
|
|
89
|
+
clear(): void;
|
|
90
|
+
/**
|
|
91
|
+
* Check file existence (for testing)
|
|
92
|
+
*/
|
|
93
|
+
hasFile(filePath: string): boolean;
|
|
94
|
+
/**
|
|
95
|
+
* Get file content (sync version, for testing)
|
|
96
|
+
*/
|
|
97
|
+
getFileContent(filePath: string): string | undefined;
|
|
98
|
+
/**
|
|
99
|
+
* Get all file paths (for testing)
|
|
100
|
+
*/
|
|
101
|
+
getAllFilePaths(): string[];
|
|
102
|
+
/**
|
|
103
|
+
* Get file count (for testing)
|
|
104
|
+
*/
|
|
105
|
+
getFileCount(): number;
|
|
106
|
+
/**
|
|
107
|
+
* Setup test data
|
|
108
|
+
*/
|
|
109
|
+
setupTestFiles(files: Record<string, string>): void;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export { DocFileSystemMock };
|
|
@@ -0,0 +1,513 @@
|
|
|
1
|
+
// lib/modules/path-system/doc-path-system.ts
|
|
2
|
+
var DocPathSystem = class {
|
|
3
|
+
separator = "/";
|
|
4
|
+
/**
|
|
5
|
+
* Join paths
|
|
6
|
+
*/
|
|
7
|
+
join(...paths) {
|
|
8
|
+
const parts = [];
|
|
9
|
+
for (const path of paths) {
|
|
10
|
+
if (path === "") continue;
|
|
11
|
+
const segments = path.split(this.separator).filter(Boolean);
|
|
12
|
+
parts.push(...segments);
|
|
13
|
+
}
|
|
14
|
+
if (parts.length === 0) {
|
|
15
|
+
return ".";
|
|
16
|
+
}
|
|
17
|
+
const isAbsolute = paths[0]?.startsWith(this.separator);
|
|
18
|
+
const joined = parts.join(this.separator);
|
|
19
|
+
return isAbsolute ? `${this.separator}${joined}` : joined;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Get filename with extension
|
|
23
|
+
*/
|
|
24
|
+
basename(path, ext) {
|
|
25
|
+
const segments = path.split(this.separator);
|
|
26
|
+
const filename = segments[segments.length - 1] || "";
|
|
27
|
+
if (ext && filename.endsWith(ext)) {
|
|
28
|
+
return filename.slice(0, -ext.length);
|
|
29
|
+
}
|
|
30
|
+
return filename;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get directory name
|
|
34
|
+
*/
|
|
35
|
+
dirname(path) {
|
|
36
|
+
const segments = path.split(this.separator);
|
|
37
|
+
if (segments.length <= 1) {
|
|
38
|
+
return ".";
|
|
39
|
+
}
|
|
40
|
+
segments.pop();
|
|
41
|
+
const dir = segments.join(this.separator);
|
|
42
|
+
return dir || ".";
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get extension
|
|
46
|
+
*/
|
|
47
|
+
extname(path) {
|
|
48
|
+
const basename = this.basename(path);
|
|
49
|
+
const lastDot = basename.lastIndexOf(".");
|
|
50
|
+
if (lastDot <= 0) {
|
|
51
|
+
return "";
|
|
52
|
+
}
|
|
53
|
+
return basename.slice(lastDot);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Calculate relative path
|
|
57
|
+
*/
|
|
58
|
+
relative(from, to) {
|
|
59
|
+
const fromSegments = from.split(this.separator).filter(Boolean);
|
|
60
|
+
const toSegments = to.split(this.separator).filter(Boolean);
|
|
61
|
+
let commonLength = 0;
|
|
62
|
+
for (let i = 0; i < Math.min(fromSegments.length, toSegments.length); i++) {
|
|
63
|
+
if (fromSegments[i] === toSegments[i]) {
|
|
64
|
+
commonLength++;
|
|
65
|
+
} else {
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const upCount = fromSegments.length - commonLength;
|
|
70
|
+
const upSegments = Array(upCount).fill("..");
|
|
71
|
+
const downSegments = toSegments.slice(commonLength);
|
|
72
|
+
const segments = [...upSegments, ...downSegments];
|
|
73
|
+
return segments.length > 0 ? segments.join(this.separator) : ".";
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Convert to absolute path
|
|
77
|
+
*/
|
|
78
|
+
resolve(...paths) {
|
|
79
|
+
let resolved = "";
|
|
80
|
+
for (const path of paths) {
|
|
81
|
+
if (path.startsWith(this.separator)) {
|
|
82
|
+
resolved = path;
|
|
83
|
+
} else if (path !== "") {
|
|
84
|
+
resolved = resolved ? this.join(resolved, path) : path;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return resolved || ".";
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Normalize path
|
|
91
|
+
*/
|
|
92
|
+
normalize(path) {
|
|
93
|
+
const isAbsolute = path.startsWith(this.separator);
|
|
94
|
+
const segments = path.split(this.separator).filter(Boolean);
|
|
95
|
+
const normalized = [];
|
|
96
|
+
for (const segment of segments) {
|
|
97
|
+
if (segment === "..") {
|
|
98
|
+
if (normalized.length > 0 && normalized[normalized.length - 1] !== "..") {
|
|
99
|
+
normalized.pop();
|
|
100
|
+
} else if (!isAbsolute) {
|
|
101
|
+
normalized.push("..");
|
|
102
|
+
}
|
|
103
|
+
} else if (segment !== ".") {
|
|
104
|
+
normalized.push(segment);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (normalized.length === 0) {
|
|
108
|
+
return isAbsolute ? this.separator : ".";
|
|
109
|
+
}
|
|
110
|
+
const result = normalized.join(this.separator);
|
|
111
|
+
return isAbsolute ? `${this.separator}${result}` : result;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Check if path is absolute
|
|
115
|
+
*/
|
|
116
|
+
isAbsolute(path) {
|
|
117
|
+
return path.startsWith(this.separator);
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
// lib/modules/file-system/doc-file-system-mock.ts
|
|
122
|
+
var mockDirectoryData = {
|
|
123
|
+
"docs/index.md": `---
|
|
124
|
+
icon: \u{1F4DA}
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
# Documentation
|
|
128
|
+
|
|
129
|
+
Welcome to the documentation!`,
|
|
130
|
+
"docs/guide/index.md": `---
|
|
131
|
+
icon: \u{1F4D6}
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
# Guide
|
|
135
|
+
|
|
136
|
+
This is a guide.`,
|
|
137
|
+
"docs/guide/getting-started.md": `# Getting Started
|
|
138
|
+
|
|
139
|
+
Let's get started!`,
|
|
140
|
+
"docs/guide/advanced.md": `# Advanced
|
|
141
|
+
|
|
142
|
+
Advanced topics here.`,
|
|
143
|
+
"docs/api/index.md": `---
|
|
144
|
+
icon: \u{1F527}
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
# API
|
|
148
|
+
|
|
149
|
+
API documentation.`,
|
|
150
|
+
"docs/api/reference.md": `# API Reference
|
|
151
|
+
|
|
152
|
+
Complete API reference.`
|
|
153
|
+
};
|
|
154
|
+
var DocFileSystemMock = class _DocFileSystemMock {
|
|
155
|
+
files = /* @__PURE__ */ new Map();
|
|
156
|
+
pathSystem;
|
|
157
|
+
basePath;
|
|
158
|
+
constructor(props) {
|
|
159
|
+
this.pathSystem = props.pathSystem ?? new DocPathSystem();
|
|
160
|
+
this.basePath = props.basePath.endsWith("/") ? props.basePath.slice(0, -1) : props.basePath;
|
|
161
|
+
if (!props.skipDefaultFiles) {
|
|
162
|
+
this.setupTestFiles(mockDirectoryData);
|
|
163
|
+
}
|
|
164
|
+
Object.freeze(this);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* PathSystem accessor (for testing)
|
|
168
|
+
*/
|
|
169
|
+
getPathSystem() {
|
|
170
|
+
return this.pathSystem;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Get file name from path
|
|
174
|
+
*/
|
|
175
|
+
readFileName(relativePath) {
|
|
176
|
+
return this.pathSystem.basename(relativePath);
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Get file extension from path
|
|
180
|
+
*/
|
|
181
|
+
readFileExtension(relativePath) {
|
|
182
|
+
return this.pathSystem.extname(relativePath);
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Get directory path where the file exists
|
|
186
|
+
*/
|
|
187
|
+
readFileDirectory(relativePath) {
|
|
188
|
+
return this.pathSystem.dirname(relativePath);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Get base path
|
|
192
|
+
*/
|
|
193
|
+
getBasePath() {
|
|
194
|
+
return this.basePath;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Convert relative path to absolute path
|
|
198
|
+
*/
|
|
199
|
+
resolve(relativePath) {
|
|
200
|
+
return this.pathSystem.join(this.basePath, relativePath);
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Normalize path using basePath
|
|
204
|
+
*/
|
|
205
|
+
normalizePath(filePath) {
|
|
206
|
+
if (filePath.startsWith(this.basePath)) {
|
|
207
|
+
return filePath;
|
|
208
|
+
}
|
|
209
|
+
const cleanPath = filePath.startsWith("/") ? filePath.slice(1) : filePath;
|
|
210
|
+
return `${this.basePath}/${cleanPath}`;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Create instance (mock data is automatically loaded)
|
|
214
|
+
*/
|
|
215
|
+
static create(basePath = "/test") {
|
|
216
|
+
return new _DocFileSystemMock({ basePath });
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Factory method for testing
|
|
220
|
+
*/
|
|
221
|
+
static createWithFiles(props) {
|
|
222
|
+
const basePath = props.basePath ?? "/test";
|
|
223
|
+
const fileSystem = new _DocFileSystemMock({
|
|
224
|
+
basePath,
|
|
225
|
+
skipDefaultFiles: true
|
|
226
|
+
});
|
|
227
|
+
if (props.fileContents) {
|
|
228
|
+
const now = /* @__PURE__ */ new Date();
|
|
229
|
+
for (const [path, content] of Object.entries(props.fileContents)) {
|
|
230
|
+
const cleanPath = path.startsWith("/") ? path.slice(1) : path;
|
|
231
|
+
const normalizedPath = path.startsWith(basePath) ? path : `${basePath}/${cleanPath}`;
|
|
232
|
+
fileSystem.files.set(normalizedPath, {
|
|
233
|
+
content,
|
|
234
|
+
modifiedTime: now,
|
|
235
|
+
createdTime: now,
|
|
236
|
+
size: new TextEncoder().encode(content).length
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return fileSystem;
|
|
241
|
+
}
|
|
242
|
+
async readFile(filePath) {
|
|
243
|
+
try {
|
|
244
|
+
const normalizedPath = this.normalizePath(filePath);
|
|
245
|
+
const file = this.files.get(normalizedPath);
|
|
246
|
+
return file ? file.content : null;
|
|
247
|
+
} catch (error) {
|
|
248
|
+
return error instanceof Error ? error : new Error(`Failed to read file at ${filePath}`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
async writeFile(filePath, content) {
|
|
252
|
+
try {
|
|
253
|
+
const normalizedPath = this.normalizePath(filePath);
|
|
254
|
+
const now = /* @__PURE__ */ new Date();
|
|
255
|
+
const existing = this.files.get(normalizedPath);
|
|
256
|
+
this.files.set(normalizedPath, {
|
|
257
|
+
content,
|
|
258
|
+
modifiedTime: now,
|
|
259
|
+
createdTime: existing?.createdTime ?? now,
|
|
260
|
+
size: new TextEncoder().encode(content).length
|
|
261
|
+
});
|
|
262
|
+
return null;
|
|
263
|
+
} catch (error) {
|
|
264
|
+
return error instanceof Error ? error : new Error(`Failed to write file at ${filePath}`);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
async deleteFile(filePath) {
|
|
268
|
+
try {
|
|
269
|
+
const normalizedPath = this.normalizePath(filePath);
|
|
270
|
+
this.files.delete(normalizedPath);
|
|
271
|
+
return null;
|
|
272
|
+
} catch (error) {
|
|
273
|
+
return new Error(`Failed to delete file at ${filePath}: ${error}`);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
async exists(filePath) {
|
|
277
|
+
const normalizedPath = this.normalizePath(filePath);
|
|
278
|
+
if (this.files.has(normalizedPath)) {
|
|
279
|
+
return true;
|
|
280
|
+
}
|
|
281
|
+
const dirPath = normalizedPath.endsWith("/") ? normalizedPath : `${normalizedPath}/`;
|
|
282
|
+
for (const path of this.files.keys()) {
|
|
283
|
+
if (path.startsWith(dirPath)) {
|
|
284
|
+
return true;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
async copyFile(source, destination) {
|
|
290
|
+
try {
|
|
291
|
+
const normalizedSource = this.normalizePath(source);
|
|
292
|
+
const normalizedDest = this.normalizePath(destination);
|
|
293
|
+
const file = this.files.get(normalizedSource);
|
|
294
|
+
if (!file) {
|
|
295
|
+
return new Error(`Source file not found: ${normalizedSource}`);
|
|
296
|
+
}
|
|
297
|
+
this.files.set(normalizedDest, {
|
|
298
|
+
...file,
|
|
299
|
+
createdTime: /* @__PURE__ */ new Date()
|
|
300
|
+
});
|
|
301
|
+
return null;
|
|
302
|
+
} catch (error) {
|
|
303
|
+
return error instanceof Error ? error : new Error(`Failed to copy file from ${source} to ${destination}`);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
async moveFile(source, destination) {
|
|
307
|
+
try {
|
|
308
|
+
const normalizedSource = this.normalizePath(source);
|
|
309
|
+
const normalizedDest = this.normalizePath(destination);
|
|
310
|
+
const file = this.files.get(normalizedSource);
|
|
311
|
+
if (!file) {
|
|
312
|
+
return new Error(`Source file not found: ${normalizedSource}`);
|
|
313
|
+
}
|
|
314
|
+
this.files.set(normalizedDest, file);
|
|
315
|
+
this.files.delete(normalizedSource);
|
|
316
|
+
return null;
|
|
317
|
+
} catch (error) {
|
|
318
|
+
return error instanceof Error ? error : new Error(`Failed to move file from ${source} to ${destination}`);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
async readDirectory(directoryPath) {
|
|
322
|
+
const dirPath = directoryPath.endsWith("/") ? directoryPath : `${directoryPath}/`;
|
|
323
|
+
const entries = /* @__PURE__ */ new Set();
|
|
324
|
+
for (const path of this.files.keys()) {
|
|
325
|
+
if (path.startsWith(dirPath)) {
|
|
326
|
+
const relativePath = path.slice(dirPath.length);
|
|
327
|
+
const firstSegment = relativePath.split("/")[0];
|
|
328
|
+
if (firstSegment) {
|
|
329
|
+
entries.add(firstSegment);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
return Array.from(entries).sort();
|
|
334
|
+
}
|
|
335
|
+
async readDirectoryRecursive(directoryPath) {
|
|
336
|
+
const dirPath = directoryPath.endsWith("/") ? directoryPath : `${directoryPath}/`;
|
|
337
|
+
const files = [];
|
|
338
|
+
for (const path of this.files.keys()) {
|
|
339
|
+
if (path.startsWith(dirPath)) {
|
|
340
|
+
files.push(path);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
return files.sort();
|
|
344
|
+
}
|
|
345
|
+
async readDirectoryFilePaths(directoryPath) {
|
|
346
|
+
try {
|
|
347
|
+
const normalizedDir = this.normalizePath(directoryPath);
|
|
348
|
+
const dirPath = normalizedDir.endsWith("/") ? normalizedDir : `${normalizedDir}/`;
|
|
349
|
+
const files = [];
|
|
350
|
+
for (const path of this.files.keys()) {
|
|
351
|
+
if (path.startsWith(dirPath) && !path.slice(dirPath.length).includes("/")) {
|
|
352
|
+
const relativePath = path.startsWith(`${this.basePath}/`) ? path.slice(this.basePath.length + 1) : path;
|
|
353
|
+
files.push(relativePath);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
return files.sort();
|
|
357
|
+
} catch (error) {
|
|
358
|
+
return error instanceof Error ? error : new Error(`Failed to read directory file paths at ${directoryPath}`);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
async createEmptyDirectory(_directoryPath) {
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
async deleteDirectory(directoryPath) {
|
|
365
|
+
const dirPath = directoryPath.endsWith("/") ? directoryPath : `${directoryPath}/`;
|
|
366
|
+
for (const path of this.files.keys()) {
|
|
367
|
+
if (path.startsWith(dirPath)) {
|
|
368
|
+
this.files.delete(path);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
async getFileSize(filePath) {
|
|
373
|
+
try {
|
|
374
|
+
const normalizedPath = this.normalizePath(filePath);
|
|
375
|
+
const file = this.files.get(normalizedPath);
|
|
376
|
+
if (!file) {
|
|
377
|
+
return new Error(`File not found: ${normalizedPath}`);
|
|
378
|
+
}
|
|
379
|
+
return file.size;
|
|
380
|
+
} catch (error) {
|
|
381
|
+
return error instanceof Error ? error : new Error(`Failed to get file size at ${filePath}`);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
async getFileUpdatedTime(filePath) {
|
|
385
|
+
try {
|
|
386
|
+
const normalizedPath = this.normalizePath(filePath);
|
|
387
|
+
const file = this.files.get(normalizedPath);
|
|
388
|
+
if (!file) {
|
|
389
|
+
return new Error(`File not found: ${normalizedPath}`);
|
|
390
|
+
}
|
|
391
|
+
return file.modifiedTime;
|
|
392
|
+
} catch (error) {
|
|
393
|
+
return error instanceof Error ? error : new Error(`Failed to get file modified time at ${filePath}`);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
async getFileCreatedTime(filePath) {
|
|
397
|
+
try {
|
|
398
|
+
const normalizedPath = this.normalizePath(filePath);
|
|
399
|
+
const file = this.files.get(normalizedPath);
|
|
400
|
+
if (!file) {
|
|
401
|
+
return new Error(`File not found: ${normalizedPath}`);
|
|
402
|
+
}
|
|
403
|
+
return file.createdTime;
|
|
404
|
+
} catch (error) {
|
|
405
|
+
return error instanceof Error ? error : new Error(`Failed to get file created time at ${filePath}`);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
async isDirectory(relativePath) {
|
|
409
|
+
const normalizedPath = this.normalizePath(relativePath);
|
|
410
|
+
const dirPath = normalizedPath.endsWith("/") ? normalizedPath : `${normalizedPath}/`;
|
|
411
|
+
for (const path of this.files.keys()) {
|
|
412
|
+
if (path.startsWith(dirPath)) {
|
|
413
|
+
return true;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
return false;
|
|
417
|
+
}
|
|
418
|
+
async isFile(relativePath) {
|
|
419
|
+
const normalizedPath = this.normalizePath(relativePath);
|
|
420
|
+
return this.files.has(normalizedPath);
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Get list of entries in directory
|
|
424
|
+
*/
|
|
425
|
+
async readDirectoryFileNames(directoryPath = "") {
|
|
426
|
+
try {
|
|
427
|
+
const normalizedDir = directoryPath === "" ? this.basePath : this.normalizePath(directoryPath);
|
|
428
|
+
const dirPath = normalizedDir.endsWith("/") ? normalizedDir : `${normalizedDir}/`;
|
|
429
|
+
const entries = /* @__PURE__ */ new Set();
|
|
430
|
+
for (const path of this.files.keys()) {
|
|
431
|
+
if (path.startsWith(dirPath)) {
|
|
432
|
+
const relativePath = path.slice(dirPath.length);
|
|
433
|
+
const firstSegment = relativePath.split("/")[0];
|
|
434
|
+
if (firstSegment) {
|
|
435
|
+
entries.add(firstSegment);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
return Array.from(entries).sort();
|
|
440
|
+
} catch (error) {
|
|
441
|
+
return error instanceof Error ? error : new Error(`Failed to read directory at ${directoryPath}`);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Check if directory exists
|
|
446
|
+
*/
|
|
447
|
+
async directoryExists(relativePath) {
|
|
448
|
+
return this.isDirectory(relativePath);
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Check if file exists
|
|
452
|
+
*/
|
|
453
|
+
async fileExists(relativePath) {
|
|
454
|
+
return this.isFile(relativePath);
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Create directory if it doesn't exist
|
|
458
|
+
*/
|
|
459
|
+
async createDirectory(_relativePath) {
|
|
460
|
+
return null;
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Clear all files
|
|
464
|
+
*/
|
|
465
|
+
clear() {
|
|
466
|
+
this.files.clear();
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Check file existence (for testing)
|
|
470
|
+
*/
|
|
471
|
+
hasFile(filePath) {
|
|
472
|
+
const normalizedPath = this.normalizePath(filePath);
|
|
473
|
+
return this.files.has(normalizedPath);
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Get file content (sync version, for testing)
|
|
477
|
+
*/
|
|
478
|
+
getFileContent(filePath) {
|
|
479
|
+
const normalizedPath = this.normalizePath(filePath);
|
|
480
|
+
return this.files.get(normalizedPath)?.content;
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Get all file paths (for testing)
|
|
484
|
+
*/
|
|
485
|
+
getAllFilePaths() {
|
|
486
|
+
return Array.from(this.files.keys()).map((path) => {
|
|
487
|
+
return path.startsWith(`${this.basePath}/`) ? path.slice(this.basePath.length + 1) : path;
|
|
488
|
+
}).sort();
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Get file count (for testing)
|
|
492
|
+
*/
|
|
493
|
+
getFileCount() {
|
|
494
|
+
return this.files.size;
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* Setup test data
|
|
498
|
+
*/
|
|
499
|
+
setupTestFiles(files) {
|
|
500
|
+
const now = /* @__PURE__ */ new Date();
|
|
501
|
+
for (const [path, content] of Object.entries(files)) {
|
|
502
|
+
const normalizedPath = this.normalizePath(path);
|
|
503
|
+
this.files.set(normalizedPath, {
|
|
504
|
+
content,
|
|
505
|
+
modifiedTime: now,
|
|
506
|
+
createdTime: now,
|
|
507
|
+
size: new TextEncoder().encode(content).length
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
};
|
|
512
|
+
|
|
513
|
+
export { DocFileSystemMock };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { a as DocPathSystem } from './doc-file-system.interface-C5vpYrOL.js';
|
|
2
|
+
import { D as DocFileSystem } from './doc-file-system-DEmPPJPE.js';
|
|
3
|
+
export { DocFileSystemRead as DocFileSystemNodeRead, DocFileSystemWrite as DocFileSystemNodeWrite } from './file-system.js';
|
|
4
|
+
|
|
5
|
+
type Props = {
|
|
6
|
+
basePath: string;
|
|
7
|
+
pathSystem?: DocPathSystem;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Node.js file system with separate read/write components
|
|
11
|
+
*/
|
|
12
|
+
declare class DocFileSystemNode extends DocFileSystem {
|
|
13
|
+
constructor(props: Props);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export { DocFileSystemNode };
|