@lova/mem-vfs 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.
Files changed (58) hide show
  1. package/README.md +222 -0
  2. package/dist/core/vfs-directory.d.ts +35 -0
  3. package/dist/core/vfs-directory.d.ts.map +1 -0
  4. package/dist/core/vfs-directory.js +78 -0
  5. package/dist/core/vfs-directory.js.map +1 -0
  6. package/dist/core/vfs-file.d.ts +25 -0
  7. package/dist/core/vfs-file.d.ts.map +1 -0
  8. package/dist/core/vfs-file.js +60 -0
  9. package/dist/core/vfs-file.js.map +1 -0
  10. package/dist/core/vfs-node.d.ts +42 -0
  11. package/dist/core/vfs-node.d.ts.map +1 -0
  12. package/dist/core/vfs-node.js +69 -0
  13. package/dist/core/vfs-node.js.map +1 -0
  14. package/dist/core/vfs-symlink.d.ts +21 -0
  15. package/dist/core/vfs-symlink.d.ts.map +1 -0
  16. package/dist/core/vfs-symlink.js +41 -0
  17. package/dist/core/vfs-symlink.js.map +1 -0
  18. package/dist/core/vfs.d.ts +107 -0
  19. package/dist/core/vfs.d.ts.map +1 -0
  20. package/dist/core/vfs.js +775 -0
  21. package/dist/core/vfs.js.map +1 -0
  22. package/dist/errors/file-system-errors.d.ts +79 -0
  23. package/dist/errors/file-system-errors.d.ts.map +1 -0
  24. package/dist/errors/file-system-errors.js +127 -0
  25. package/dist/errors/file-system-errors.js.map +1 -0
  26. package/dist/index.d.ts +20 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +23 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/path/path-normalizer.d.ts +23 -0
  31. package/dist/path/path-normalizer.d.ts.map +1 -0
  32. package/dist/path/path-normalizer.js +159 -0
  33. package/dist/path/path-normalizer.js.map +1 -0
  34. package/dist/path/path-resolver.d.ts +31 -0
  35. package/dist/path/path-resolver.d.ts.map +1 -0
  36. package/dist/path/path-resolver.js +68 -0
  37. package/dist/path/path-resolver.js.map +1 -0
  38. package/dist/path/path-validator.d.ts +12 -0
  39. package/dist/path/path-validator.d.ts.map +1 -0
  40. package/dist/path/path-validator.js +87 -0
  41. package/dist/path/path-validator.js.map +1 -0
  42. package/dist/types/index.d.ts +171 -0
  43. package/dist/types/index.d.ts.map +1 -0
  44. package/dist/types/index.js +29 -0
  45. package/dist/types/index.js.map +1 -0
  46. package/dist/watcher/debouncer.d.ts +31 -0
  47. package/dist/watcher/debouncer.d.ts.map +1 -0
  48. package/dist/watcher/debouncer.js +66 -0
  49. package/dist/watcher/debouncer.js.map +1 -0
  50. package/dist/watcher/watcher-events.d.ts +30 -0
  51. package/dist/watcher/watcher-events.d.ts.map +1 -0
  52. package/dist/watcher/watcher-events.js +52 -0
  53. package/dist/watcher/watcher-events.js.map +1 -0
  54. package/dist/watcher/watcher.d.ts +57 -0
  55. package/dist/watcher/watcher.d.ts.map +1 -0
  56. package/dist/watcher/watcher.js +194 -0
  57. package/dist/watcher/watcher.js.map +1 -0
  58. package/package.json +53 -0
@@ -0,0 +1,12 @@
1
+ /**
2
+ * 路徑驗證工具
3
+ */
4
+ /** 驗證路徑 */
5
+ export declare function validatePath(inputPath: string): void;
6
+ /** 驗證檔案名稱 */
7
+ export declare function validateFileName(name: string): void;
8
+ /** 是否為有效路徑(不拋出錯誤) */
9
+ export declare function isValidPath(inputPath: string): boolean;
10
+ /** 是否為有效檔案名稱(不拋出錯誤) */
11
+ export declare function isValidFileName(name: string): boolean;
12
+ //# sourceMappingURL=path-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-validator.d.ts","sourceRoot":"","sources":["../../src/path/path-validator.ts"],"names":[],"mappings":"AAAA;;GAEG;AAcH,WAAW;AACX,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CA6BpD;AAuBD,aAAa;AACb,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAWnD;AAED,qBAAqB;AACrB,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAOtD;AAED,uBAAuB;AACvB,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOrD"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * 路徑驗證工具
3
+ */
4
+ import { InvalidPathError } from '../errors/file-system-errors.js';
5
+ /** 無效的路徑字元 */
6
+ const INVALID_CHARS = /[\x00-\x1f]/;
7
+ /** 保留的檔案名稱(Windows 相容) */
8
+ const RESERVED_NAMES = new Set([
9
+ 'CON', 'PRN', 'AUX', 'NUL',
10
+ 'COM1', 'COM2', 'COM3', 'COM4', 'COM5', 'COM6', 'COM7', 'COM8', 'COM9',
11
+ 'LPT1', 'LPT2', 'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9',
12
+ ]);
13
+ /** 驗證路徑 */
14
+ export function validatePath(inputPath) {
15
+ if (!inputPath) {
16
+ throw new InvalidPathError('', 'Path cannot be empty');
17
+ }
18
+ if (typeof inputPath !== 'string') {
19
+ throw new InvalidPathError(String(inputPath), 'Path must be a string');
20
+ }
21
+ // 檢查無效字元
22
+ if (INVALID_CHARS.test(inputPath)) {
23
+ throw new InvalidPathError(inputPath, 'Path contains invalid characters');
24
+ }
25
+ // 檢查路徑長度
26
+ if (inputPath.length > 4096) {
27
+ throw new InvalidPathError(inputPath, 'Path is too long (max 4096 characters)');
28
+ }
29
+ // 檢查各個部分(跳過 . 和 .. 因為這些是合法的路徑導航元素)
30
+ const parts = inputPath.split('/').filter(Boolean);
31
+ for (const part of parts) {
32
+ // 跳過 . 和 .. 路徑導航元素
33
+ if (part === '.' || part === '..') {
34
+ continue;
35
+ }
36
+ validatePathSegment(part, inputPath);
37
+ }
38
+ }
39
+ /** 驗證路徑段落 */
40
+ function validatePathSegment(segment, fullPath) {
41
+ // 檢查段落長度
42
+ if (segment.length > 255) {
43
+ throw new InvalidPathError(fullPath, `Path segment "${segment}" is too long (max 255 characters)`);
44
+ }
45
+ // 檢查保留名稱(不區分大小寫)
46
+ const upperSegment = segment.toUpperCase();
47
+ const baseSegment = upperSegment.split('.')[0];
48
+ if (RESERVED_NAMES.has(baseSegment)) {
49
+ throw new InvalidPathError(fullPath, `"${segment}" is a reserved name`);
50
+ }
51
+ // 檢查結尾空格或句點
52
+ if (segment.endsWith(' ') || segment.endsWith('.')) {
53
+ throw new InvalidPathError(fullPath, `Path segment cannot end with space or period: "${segment}"`);
54
+ }
55
+ }
56
+ /** 驗證檔案名稱 */
57
+ export function validateFileName(name) {
58
+ if (!name) {
59
+ throw new InvalidPathError('', 'File name cannot be empty');
60
+ }
61
+ // 不能包含斜線
62
+ if (name.includes('/') || name.includes('\\')) {
63
+ throw new InvalidPathError(name, 'File name cannot contain path separators');
64
+ }
65
+ validatePathSegment(name, name);
66
+ }
67
+ /** 是否為有效路徑(不拋出錯誤) */
68
+ export function isValidPath(inputPath) {
69
+ try {
70
+ validatePath(inputPath);
71
+ return true;
72
+ }
73
+ catch {
74
+ return false;
75
+ }
76
+ }
77
+ /** 是否為有效檔案名稱(不拋出錯誤) */
78
+ export function isValidFileName(name) {
79
+ try {
80
+ validateFileName(name);
81
+ return true;
82
+ }
83
+ catch {
84
+ return false;
85
+ }
86
+ }
87
+ //# sourceMappingURL=path-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-validator.js","sourceRoot":"","sources":["../../src/path/path-validator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,171 @@
1
+ /**
2
+ * mem-vfs 型別定義
3
+ */
4
+ /** 目錄項目 */
5
+ export interface DirectoryEntry {
6
+ /** 檔案/目錄名稱 */
7
+ name: string;
8
+ /** 完整路徑 */
9
+ path: string;
10
+ /** 是否為檔案 */
11
+ isFile: boolean;
12
+ /** 是否為目錄 */
13
+ isDirectory: boolean;
14
+ /** 是否為符號連結 */
15
+ isSymlink: boolean;
16
+ /** 檔案大小(位元組) */
17
+ size?: number;
18
+ /** 修改時間 */
19
+ modifiedTime?: Date;
20
+ }
21
+ /** 檔案統計資訊 */
22
+ export interface FileStats {
23
+ /** 是否為檔案 */
24
+ isFile: boolean;
25
+ /** 是否為目錄 */
26
+ isDirectory: boolean;
27
+ /** 是否為符號連結 */
28
+ isSymlink: boolean;
29
+ /** 檔案大小(位元組) */
30
+ size: number;
31
+ /** 建立時間 */
32
+ createdTime: Date;
33
+ /** 修改時間 */
34
+ modifiedTime: Date;
35
+ /** 存取時間 */
36
+ accessedTime: Date;
37
+ /** 檔案模式 */
38
+ mode: number;
39
+ /** 使用者 ID */
40
+ uid?: number;
41
+ /** 群組 ID */
42
+ gid?: number;
43
+ }
44
+ /** Glob 選項 */
45
+ export interface GlobOptions {
46
+ /** 工作目錄 */
47
+ cwd?: string;
48
+ /** 忽略的 pattern */
49
+ ignore?: string[];
50
+ /** 是否包含 dot 檔案 */
51
+ dot?: boolean;
52
+ /** 是否回傳絕對路徑 */
53
+ absolute?: boolean;
54
+ /** 僅回傳檔案 */
55
+ onlyFiles?: boolean;
56
+ /** 僅回傳目錄 */
57
+ onlyDirectories?: boolean;
58
+ /** 是否追蹤符號連結 */
59
+ followSymlinks?: boolean;
60
+ /** 最大深度限制 */
61
+ maxDepth?: number;
62
+ }
63
+ /** 監聽選項 */
64
+ export interface WatchOptions {
65
+ /** 是否持續監聽 */
66
+ persistent?: boolean;
67
+ /** 是否遞迴監聽 */
68
+ recursive?: boolean;
69
+ /** 是否忽略初始事件 */
70
+ ignoreInitial?: boolean;
71
+ /** 是否追蹤符號連結 */
72
+ followSymlinks?: boolean;
73
+ /** 忽略的 pattern */
74
+ ignored?: string | string[] | ((path: string) => boolean);
75
+ /** debounce 延遲(毫秒) */
76
+ debounce?: number;
77
+ /** 最大深度 */
78
+ depth?: number;
79
+ }
80
+ /** 檔案變更事件類型 */
81
+ export declare enum FileChangeType {
82
+ Add = "add",
83
+ Change = "change",
84
+ Unlink = "unlink",
85
+ AddDir = "addDir",
86
+ UnlinkDir = "unlinkDir",
87
+ Ready = "ready",
88
+ Error = "error"
89
+ }
90
+ /** 檔案變更事件 */
91
+ export interface FileChangeEvent {
92
+ /** 事件類型 */
93
+ type: FileChangeType;
94
+ /** 檔案路徑 */
95
+ path: string;
96
+ /** 檔案統計(如果可用) */
97
+ stats?: FileStats;
98
+ /** 錯誤(如果是錯誤事件) */
99
+ error?: Error;
100
+ }
101
+ /** 監聽事件處理器 */
102
+ export type FileWatcherEventListener = (event: FileChangeEvent) => void;
103
+ /** 快照 ID */
104
+ export type SnapshotId = string;
105
+ /** 快照資訊 */
106
+ export interface SnapshotInfo {
107
+ /** 快照 ID */
108
+ id: SnapshotId;
109
+ /** 快照名稱 */
110
+ name?: string;
111
+ /** 建立時間 */
112
+ createdAt: Date;
113
+ /** 檔案數量 */
114
+ fileCount: number;
115
+ /** 目錄數量 */
116
+ directoryCount: number;
117
+ /** 總大小(位元組) */
118
+ totalSize: number;
119
+ }
120
+ /** 檔案差異類型 */
121
+ export declare enum DiffType {
122
+ Added = "added",
123
+ Modified = "modified",
124
+ Deleted = "deleted"
125
+ }
126
+ /** 檔案差異 */
127
+ export interface FileDiff {
128
+ /** 差異類型 */
129
+ type: DiffType;
130
+ /** 檔案路徑 */
131
+ path: string;
132
+ /** 舊內容(如果是修改或刪除) */
133
+ oldContent?: Buffer;
134
+ /** 新內容(如果是新增或修改) */
135
+ newContent?: Buffer;
136
+ /** 舊統計資訊 */
137
+ oldStats?: FileStats;
138
+ /** 新統計資訊 */
139
+ newStats?: FileStats;
140
+ }
141
+ /** VFS 選項 */
142
+ export interface VFSOptions {
143
+ /** 是否區分大小寫(預設 true) */
144
+ caseSensitive?: boolean;
145
+ /** 預設檔案模式 */
146
+ defaultFileMode?: number;
147
+ /** 預設目錄模式 */
148
+ defaultDirectoryMode?: number;
149
+ /** 符號連結最大解析深度(預設 40) */
150
+ maxSymlinkDepth?: number;
151
+ }
152
+ /** 原子寫入選項 */
153
+ export interface AtomicWriteOptions {
154
+ /** 臨時檔案後綴 */
155
+ tempSuffix?: string;
156
+ /** 是否 fsync */
157
+ fsync?: boolean;
158
+ /** 編碼 */
159
+ encoding?: BufferEncoding;
160
+ }
161
+ /** 目錄 JSON 結構 */
162
+ export interface DirectoryJSON {
163
+ [path: string]: string | Buffer | null | DirectoryJSON;
164
+ }
165
+ /** VFS 節點類型 */
166
+ export declare enum VFSNodeType {
167
+ File = "file",
168
+ Directory = "directory",
169
+ Symlink = "symlink"
170
+ }
171
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * mem-vfs 型別定義
3
+ */
4
+ /** 檔案變更事件類型 */
5
+ export var FileChangeType;
6
+ (function (FileChangeType) {
7
+ FileChangeType["Add"] = "add";
8
+ FileChangeType["Change"] = "change";
9
+ FileChangeType["Unlink"] = "unlink";
10
+ FileChangeType["AddDir"] = "addDir";
11
+ FileChangeType["UnlinkDir"] = "unlinkDir";
12
+ FileChangeType["Ready"] = "ready";
13
+ FileChangeType["Error"] = "error";
14
+ })(FileChangeType || (FileChangeType = {}));
15
+ /** 檔案差異類型 */
16
+ export var DiffType;
17
+ (function (DiffType) {
18
+ DiffType["Added"] = "added";
19
+ DiffType["Modified"] = "modified";
20
+ DiffType["Deleted"] = "deleted";
21
+ })(DiffType || (DiffType = {}));
22
+ /** VFS 節點類型 */
23
+ export var VFSNodeType;
24
+ (function (VFSNodeType) {
25
+ VFSNodeType["File"] = "file";
26
+ VFSNodeType["Directory"] = "directory";
27
+ VFSNodeType["Symlink"] = "symlink";
28
+ })(VFSNodeType || (VFSNodeType = {}));
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAkFH,eAAe;AACf,MAAM,CAAN,IAAY,cAQX;AARD,WAAY,cAAc;IACxB,6BAAW,CAAA;IACX,mCAAiB,CAAA;IACjB,mCAAiB,CAAA;IACjB,mCAAiB,CAAA;IACjB,yCAAuB,CAAA;IACvB,iCAAe,CAAA;IACf,iCAAe,CAAA;AACjB,CAAC,EARW,cAAc,KAAd,cAAc,QAQzB;AAoCD,aAAa;AACb,MAAM,CAAN,IAAY,QAIX;AAJD,WAAY,QAAQ;IAClB,2BAAe,CAAA;IACf,iCAAqB,CAAA;IACrB,+BAAmB,CAAA;AACrB,CAAC,EAJW,QAAQ,KAAR,QAAQ,QAInB;AA6CD,eAAe;AACf,MAAM,CAAN,IAAY,WAIX;AAJD,WAAY,WAAW;IACrB,4BAAa,CAAA;IACb,sCAAuB,CAAA;IACvB,kCAAmB,CAAA;AACrB,CAAC,EAJW,WAAW,KAAX,WAAW,QAItB"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Debouncer
3
+ * 事件防抖動處理
4
+ */
5
+ /** Debouncer 類別 */
6
+ export declare class Debouncer<T> {
7
+ /** 待處理項目 */
8
+ private pending;
9
+ /** 計時器 */
10
+ private timer;
11
+ /** 回呼函數 */
12
+ private readonly callback;
13
+ /** 延遲時間(毫秒) */
14
+ private readonly delay;
15
+ constructor(callback: (items: Map<string, T>) => void, delay?: number);
16
+ /** 加入項目 */
17
+ add(key: string, item: T): void;
18
+ /** 移除項目 */
19
+ remove(key: string): void;
20
+ /** 取消所有待處理項目 */
21
+ cancel(): void;
22
+ /** 立即執行 */
23
+ flush(): void;
24
+ /** 排程執行 */
25
+ private scheduleFlush;
26
+ /** 是否有待處理項目 */
27
+ get hasPending(): boolean;
28
+ /** 待處理項目數量 */
29
+ get pendingCount(): number;
30
+ }
31
+ //# sourceMappingURL=debouncer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debouncer.d.ts","sourceRoot":"","sources":["../../src/watcher/debouncer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,mBAAmB;AACnB,qBAAa,SAAS,CAAC,CAAC;IACtB,YAAY;IACZ,OAAO,CAAC,OAAO,CAA6B;IAE5C,UAAU;IACV,OAAO,CAAC,KAAK,CAA8C;IAE3D,WAAW;IACX,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkC;IAE3D,eAAe;IACf,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAEnB,QAAQ,EAAE,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,IAAI,EAAE,KAAK,GAAE,MAAY;IAK1E,WAAW;IACX,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI;IAK/B,WAAW;IACX,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIzB,gBAAgB;IAChB,MAAM,IAAI,IAAI;IAQd,WAAW;IACX,KAAK,IAAI,IAAI;IAab,WAAW;IACX,OAAO,CAAC,aAAa;IAUrB,eAAe;IACf,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,cAAc;IACd,IAAI,YAAY,IAAI,MAAM,CAEzB;CACF"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Debouncer
3
+ * 事件防抖動處理
4
+ */
5
+ /** Debouncer 類別 */
6
+ export class Debouncer {
7
+ /** 待處理項目 */
8
+ pending = new Map();
9
+ /** 計時器 */
10
+ timer = null;
11
+ /** 回呼函數 */
12
+ callback;
13
+ /** 延遲時間(毫秒) */
14
+ delay;
15
+ constructor(callback, delay = 100) {
16
+ this.callback = callback;
17
+ this.delay = delay;
18
+ }
19
+ /** 加入項目 */
20
+ add(key, item) {
21
+ this.pending.set(key, item);
22
+ this.scheduleFlush();
23
+ }
24
+ /** 移除項目 */
25
+ remove(key) {
26
+ this.pending.delete(key);
27
+ }
28
+ /** 取消所有待處理項目 */
29
+ cancel() {
30
+ if (this.timer) {
31
+ clearTimeout(this.timer);
32
+ this.timer = null;
33
+ }
34
+ this.pending.clear();
35
+ }
36
+ /** 立即執行 */
37
+ flush() {
38
+ if (this.timer) {
39
+ clearTimeout(this.timer);
40
+ this.timer = null;
41
+ }
42
+ if (this.pending.size > 0) {
43
+ const items = new Map(this.pending);
44
+ this.pending.clear();
45
+ this.callback(items);
46
+ }
47
+ }
48
+ /** 排程執行 */
49
+ scheduleFlush() {
50
+ if (this.timer) {
51
+ clearTimeout(this.timer);
52
+ }
53
+ this.timer = setTimeout(() => {
54
+ this.flush();
55
+ }, this.delay);
56
+ }
57
+ /** 是否有待處理項目 */
58
+ get hasPending() {
59
+ return this.pending.size > 0;
60
+ }
61
+ /** 待處理項目數量 */
62
+ get pendingCount() {
63
+ return this.pending.size;
64
+ }
65
+ }
66
+ //# sourceMappingURL=debouncer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debouncer.js","sourceRoot":"","sources":["../../src/watcher/debouncer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,mBAAmB;AACnB,MAAM,OAAO,SAAS;IACpB,YAAY;IACJ,OAAO,GAAmB,IAAI,GAAG,EAAE,CAAC;IAE5C,UAAU;IACF,KAAK,GAAyC,IAAI,CAAC;IAE3D,WAAW;IACM,QAAQ,CAAkC;IAE3D,eAAe;IACE,KAAK,CAAS;IAE/B,YAAY,QAAyC,EAAE,QAAgB,GAAG;QACxE,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,WAAW;IACX,GAAG,CAAC,GAAW,EAAE,IAAO;QACtB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC5B,IAAI,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC;IAED,WAAW;IACX,MAAM,CAAC,GAAW;QAChB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAED,gBAAgB;IAChB,MAAM;QACJ,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACzB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;IAED,WAAW;IACX,KAAK;QACH,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACzB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YAC1B,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACpC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACrB,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,WAAW;IACH,aAAa;QACnB,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;QAED,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC3B,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IACjB,CAAC;IAED,eAAe;IACf,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC;IAC/B,CAAC;IAED,cAAc;IACd,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;CACF"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Watcher Events
3
+ * 監聽事件定義
4
+ */
5
+ import type { FileStats, FileChangeType } from '../types/index.js';
6
+ /** 監聽事件 */
7
+ export interface WatcherEvent {
8
+ /** 事件類型 */
9
+ type: FileChangeType;
10
+ /** 檔案路徑 */
11
+ path: string;
12
+ /** 檔案統計(如果可用) */
13
+ stats?: FileStats;
14
+ }
15
+ /** 事件處理器 */
16
+ export type WatcherEventHandler = (event: WatcherEvent) => void;
17
+ /** 錯誤處理器 */
18
+ export type WatcherErrorHandler = (error: Error) => void;
19
+ /** 簡單事件發射器實作 */
20
+ export declare class SimpleEventEmitter {
21
+ private handlers;
22
+ on(event: string, handler: (...args: unknown[]) => void): this;
23
+ off(event: string, handler: (...args: unknown[]) => void): this;
24
+ emit(event: string, ...args: unknown[]): boolean;
25
+ /** 移除所有處理器 */
26
+ removeAllListeners(event?: string): this;
27
+ /** 取得處理器數量 */
28
+ listenerCount(event: string): number;
29
+ }
30
+ //# sourceMappingURL=watcher-events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher-events.d.ts","sourceRoot":"","sources":["../../src/watcher/watcher-events.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnE,WAAW;AACX,MAAM,WAAW,YAAY;IAC3B,WAAW;IACX,IAAI,EAAE,cAAc,CAAC;IACrB,WAAW;IACX,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB;IACjB,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED,YAAY;AACZ,MAAM,MAAM,mBAAmB,GAAG,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;AAEhE,YAAY;AACZ,MAAM,MAAM,mBAAmB,GAAG,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;AAEzD,gBAAgB;AAChB,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAA6D;IAE7E,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI;IAQ9D,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI;IAQ/D,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO;IAiBhD,cAAc;IACd,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IASxC,cAAc;IACd,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;CAGrC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Watcher Events
3
+ * 監聽事件定義
4
+ */
5
+ /** 簡單事件發射器實作 */
6
+ export class SimpleEventEmitter {
7
+ handlers = new Map();
8
+ on(event, handler) {
9
+ if (!this.handlers.has(event)) {
10
+ this.handlers.set(event, new Set());
11
+ }
12
+ this.handlers.get(event).add(handler);
13
+ return this;
14
+ }
15
+ off(event, handler) {
16
+ const handlers = this.handlers.get(event);
17
+ if (handlers) {
18
+ handlers.delete(handler);
19
+ }
20
+ return this;
21
+ }
22
+ emit(event, ...args) {
23
+ const handlers = this.handlers.get(event);
24
+ if (!handlers || handlers.size === 0) {
25
+ return false;
26
+ }
27
+ for (const handler of handlers) {
28
+ try {
29
+ handler(...args);
30
+ }
31
+ catch (error) {
32
+ console.error(`Error in event handler for "${event}":`, error);
33
+ }
34
+ }
35
+ return true;
36
+ }
37
+ /** 移除所有處理器 */
38
+ removeAllListeners(event) {
39
+ if (event) {
40
+ this.handlers.delete(event);
41
+ }
42
+ else {
43
+ this.handlers.clear();
44
+ }
45
+ return this;
46
+ }
47
+ /** 取得處理器數量 */
48
+ listenerCount(event) {
49
+ return this.handlers.get(event)?.size ?? 0;
50
+ }
51
+ }
52
+ //# sourceMappingURL=watcher-events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher-events.js","sourceRoot":"","sources":["../../src/watcher/watcher-events.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAoBH,gBAAgB;AAChB,MAAM,OAAO,kBAAkB;IACrB,QAAQ,GAAmD,IAAI,GAAG,EAAE,CAAC;IAE7E,EAAE,CAAC,KAAa,EAAE,OAAqC;QACrD,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;QACtC,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACvC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,GAAG,CAAC,KAAa,EAAE,OAAqC;QACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC3B,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC,KAAa,EAAE,GAAG,IAAe;QACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACrC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,IAAI,CAAC;gBACH,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;YACnB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,+BAA+B,KAAK,IAAI,EAAE,KAAK,CAAC,CAAC;YACjE,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED,cAAc;IACd,kBAAkB,CAAC,KAAc;QAC/B,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACxB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,cAAc;IACd,aAAa,CAAC,KAAa;QACzB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,IAAI,IAAI,CAAC,CAAC;IAC7C,CAAC;CACF"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * VFSWatcher
3
+ * 虛擬檔案系統監聽器
4
+ */
5
+ import type { WatchOptions, FileStats } from '../types/index.js';
6
+ import { SimpleEventEmitter } from './watcher-events.js';
7
+ /** VFS Watcher 類別 */
8
+ export declare class VFSWatcher extends SimpleEventEmitter {
9
+ /** 監聽路徑 */
10
+ private readonly watchPath;
11
+ /** 選項 */
12
+ private readonly options;
13
+ /** 是否已關閉 */
14
+ private closed;
15
+ /** 事件防抖器 */
16
+ private readonly debouncer;
17
+ /** 已知路徑快取(用於判斷新增或修改) */
18
+ private knownPaths;
19
+ /** 預設選項 */
20
+ private static readonly DEFAULT_OPTIONS;
21
+ constructor(watchPath: string, options?: WatchOptions);
22
+ /** 通知檔案變更 */
23
+ notifyChange(path: string, stats?: FileStats): void;
24
+ /** 通知檔案刪除 */
25
+ notifyUnlink(path: string, isDirectory?: boolean): void;
26
+ /** 通知目錄新增 */
27
+ notifyAddDir(path: string, stats?: FileStats): void;
28
+ /** 發送 ready 事件 */
29
+ emitReady(): void;
30
+ /** 發送錯誤事件 */
31
+ emitError(error: Error): void;
32
+ /** 註冊已知路徑 */
33
+ registerPath(path: string): void;
34
+ /** 取消註冊路徑 */
35
+ unregisterPath(path: string): void;
36
+ /** 關閉監聽器 */
37
+ close(): void;
38
+ /** 是否已關閉 */
39
+ get isClosed(): boolean;
40
+ /** 監聽的路徑 */
41
+ get path(): string;
42
+ /** 覆寫 on 方法 */
43
+ on(event: string, handler: (...args: unknown[]) => void): this;
44
+ /** 檢查路徑是否應該被監聽 */
45
+ private shouldWatch;
46
+ /** 計算相對於監聽路徑的深度 */
47
+ private getPathDepth;
48
+ /** 檢查是否被忽略 */
49
+ private isIgnored;
50
+ /** 簡單的 pattern 匹配 */
51
+ private matchPattern;
52
+ /** 批量發送事件 */
53
+ private flushEvents;
54
+ }
55
+ /** 建立 VFSWatcher 實例 */
56
+ export declare function createWatcher(path: string, options?: WatchOptions): VFSWatcher;
57
+ //# sourceMappingURL=watcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../../src/watcher/watcher.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEjE,OAAO,EAAE,kBAAkB,EAAqB,MAAM,qBAAqB,CAAC;AAI5E,qBAAqB;AACrB,qBAAa,UAAW,SAAQ,kBAAkB;IAChD,WAAW;IACX,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IAEnC,SAAS;IACT,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IAEjD,YAAY;IACZ,OAAO,CAAC,MAAM,CAAS;IAEvB,YAAY;IACZ,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA0B;IAEpD,wBAAwB;IACxB,OAAO,CAAC,UAAU,CAA0B;IAE5C,WAAW;IACX,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAQrC;gBAEU,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;IAWrD,aAAa;IACb,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI;IAkBnD,aAAa;IACb,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,UAAQ,GAAG,IAAI;IAgBrD,aAAa;IACb,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI;IAiBnD,kBAAkB;IAClB,SAAS,IAAI,IAAI;IAKjB,aAAa;IACb,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAK7B,aAAa;IACb,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIhC,aAAa;IACb,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIlC,YAAY;IACZ,KAAK,IAAI,IAAI;IASb,YAAY;IACZ,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,YAAY;IACZ,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,eAAe;IACN,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI;IAIvE,kBAAkB;IAClB,OAAO,CAAC,WAAW;IAoBnB,mBAAmB;IACnB,OAAO,CAAC,YAAY;IASpB,cAAc;IACd,OAAO,CAAC,SAAS;IAsBjB,qBAAqB;IACrB,OAAO,CAAC,YAAY;IAQpB,aAAa;IACb,OAAO,CAAC,WAAW;CAQpB;AAED,uBAAuB;AACvB,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,UAAU,CAE9E"}