@happyvertical/files 0.80.0 → 0.80.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/base-C9husdYd.js +177 -0
- package/dist/chunks/base-C9husdYd.js.map +1 -0
- package/dist/chunks/types-OwkcCRpq.js +60 -0
- package/dist/chunks/types-OwkcCRpq.js.map +1 -0
- package/dist/cli/claude-context.js +17 -17
- package/dist/cli/claude-context.js.map +1 -1
- package/dist/index.js +2932 -3369
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { r as FilesystemError, s as __require } from "./types-OwkcCRpq.js";
|
|
2
|
+
//#region src/shared/base.ts
|
|
3
|
+
/**
|
|
4
|
+
* Abstract base class for filesystem providers.
|
|
5
|
+
*
|
|
6
|
+
* Implements {@link FilesystemInterface} with shared logic for path normalization,
|
|
7
|
+
* validation, caching, and legacy method adapters. Concrete providers (e.g.
|
|
8
|
+
* {@link LocalFilesystemProvider}, {@link GoogleDriveProvider}) extend this class
|
|
9
|
+
* and implement the abstract methods for their specific storage backend.
|
|
10
|
+
*/
|
|
11
|
+
var BaseFilesystemProvider = class {
|
|
12
|
+
basePath;
|
|
13
|
+
applyBasePath;
|
|
14
|
+
cacheDir;
|
|
15
|
+
createMissing;
|
|
16
|
+
providerType;
|
|
17
|
+
constructor(options = {}) {
|
|
18
|
+
this.basePath = options.basePath || "";
|
|
19
|
+
this.applyBasePath = options.applyBasePath ?? true;
|
|
20
|
+
this.cacheDir = options.cacheDir || this.getDefaultCacheDir();
|
|
21
|
+
this.createMissing = options.createMissing ?? true;
|
|
22
|
+
this.providerType = this.constructor.name.toLowerCase().replace("filesystemprovider", "");
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Get default cache directory for the current context
|
|
26
|
+
*/
|
|
27
|
+
getDefaultCacheDir() {
|
|
28
|
+
try {
|
|
29
|
+
const { getTempDirectory } = __require("@happyvertical/utils");
|
|
30
|
+
return getTempDirectory("files-cache");
|
|
31
|
+
} catch {
|
|
32
|
+
if (process?.versions?.node) try {
|
|
33
|
+
const { tmpdir } = __require("node:os");
|
|
34
|
+
const { join } = __require("node:path");
|
|
35
|
+
return join(tmpdir(), "have-sdk", "files-cache");
|
|
36
|
+
} catch {
|
|
37
|
+
return "./tmp/have-sdk/files-cache";
|
|
38
|
+
}
|
|
39
|
+
return "./tmp/have-sdk/files-cache";
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Throw error for unsupported operations
|
|
44
|
+
*/
|
|
45
|
+
throwUnsupported(operation) {
|
|
46
|
+
throw new FilesystemError(`Operation '${operation}' not supported by ${this.providerType} provider`, "ENOTSUP", void 0, this.providerType);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Normalize path by removing leading/trailing slashes and resolving relative paths
|
|
50
|
+
*/
|
|
51
|
+
normalizePath(path) {
|
|
52
|
+
if (!path) return "";
|
|
53
|
+
let normalized = path.startsWith("/") ? path.slice(1) : path;
|
|
54
|
+
if (this.applyBasePath && this.basePath) normalized = this.joinPaths(this.basePath, normalized);
|
|
55
|
+
return normalized;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Universal path joining function that works in both Node.js and browser
|
|
59
|
+
*/
|
|
60
|
+
joinPaths(...paths) {
|
|
61
|
+
return paths.filter((p) => p && p.length > 0).map((p) => p.replace(/^\/+|\/+$/g, "")).join("/");
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Validate that a path is safe (no directory traversal)
|
|
65
|
+
*/
|
|
66
|
+
validatePath(path) {
|
|
67
|
+
if (!path) throw new FilesystemError("Path cannot be empty", "EINVAL", path);
|
|
68
|
+
if (path.includes("..") || path.includes("~")) throw new FilesystemError("Path contains invalid characters (directory traversal)", "EINVAL", path);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get cache key for a given path
|
|
72
|
+
*/
|
|
73
|
+
getCacheKey(path) {
|
|
74
|
+
return `${this.constructor.name}-${path}`;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Provider methods with default implementations (may be overridden)
|
|
78
|
+
*/
|
|
79
|
+
async upload(_localPath, _remotePath, _options = {}) {
|
|
80
|
+
this.throwUnsupported("upload");
|
|
81
|
+
}
|
|
82
|
+
async download(_remotePath, _localPath, _options = {}) {
|
|
83
|
+
this.throwUnsupported("download");
|
|
84
|
+
}
|
|
85
|
+
async downloadWithCache(remotePath, options = {}) {
|
|
86
|
+
const cacheKey = this.getCacheKey(remotePath);
|
|
87
|
+
if (!options.force) {
|
|
88
|
+
const cached = await this.cache.get(cacheKey, options.expiry);
|
|
89
|
+
if (cached) return cached;
|
|
90
|
+
}
|
|
91
|
+
const localPath = await this.download(remotePath, void 0, options);
|
|
92
|
+
await this.cache.set(cacheKey, localPath);
|
|
93
|
+
return localPath;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Cache implementation - providers can override for their specific storage
|
|
97
|
+
*/
|
|
98
|
+
cache = {
|
|
99
|
+
get: async (_key, _expiry) => {
|
|
100
|
+
this.throwUnsupported("cache.get");
|
|
101
|
+
},
|
|
102
|
+
set: async (_key, _data) => {
|
|
103
|
+
this.throwUnsupported("cache.set");
|
|
104
|
+
},
|
|
105
|
+
clear: async (_key) => {
|
|
106
|
+
this.throwUnsupported("cache.clear");
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Check if a path is a file (legacy)
|
|
111
|
+
*/
|
|
112
|
+
async isFile(file) {
|
|
113
|
+
try {
|
|
114
|
+
const stats = await this.getStats(file);
|
|
115
|
+
return stats.isFile ? stats : false;
|
|
116
|
+
} catch {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Check if a path is a directory (legacy)
|
|
122
|
+
*/
|
|
123
|
+
async isDirectory(dir) {
|
|
124
|
+
try {
|
|
125
|
+
return (await this.getStats(dir)).isDirectory;
|
|
126
|
+
} catch {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Create a directory if it doesn't exist (legacy)
|
|
132
|
+
*/
|
|
133
|
+
async ensureDirectoryExists(dir) {
|
|
134
|
+
if (!await this.isDirectory(dir)) await this.createDirectory(dir, { recursive: true });
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Upload data to a URL using PUT method (legacy)
|
|
138
|
+
*/
|
|
139
|
+
async uploadToUrl(_url, _data) {
|
|
140
|
+
this.throwUnsupported("uploadToUrl");
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Download a file from a URL and save it to a local file (legacy)
|
|
144
|
+
*/
|
|
145
|
+
async downloadFromUrl(_url, _filepath) {
|
|
146
|
+
this.throwUnsupported("downloadFromUrl");
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Download a file with caching support (legacy)
|
|
150
|
+
*/
|
|
151
|
+
async downloadFileWithCache(_url, _targetPath) {
|
|
152
|
+
this.throwUnsupported("downloadFileWithCache");
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* List files in a directory with optional filtering (legacy)
|
|
156
|
+
*/
|
|
157
|
+
async listFiles(dirPath, options = { match: /.*/ }) {
|
|
158
|
+
const fileNames = (await this.list(dirPath)).filter((file) => !file.isDirectory).map((file) => file.name);
|
|
159
|
+
return options.match ? fileNames.filter((name) => options.match?.test(name)) : fileNames;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Get data from cache if available and not expired (legacy)
|
|
163
|
+
*/
|
|
164
|
+
async getCached(file, expiry = 3e5) {
|
|
165
|
+
return await this.cache.get(file, expiry);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Set data in cache (legacy)
|
|
169
|
+
*/
|
|
170
|
+
async setCached(file, data) {
|
|
171
|
+
await this.cache.set(file, data);
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
//#endregion
|
|
175
|
+
export { BaseFilesystemProvider as t };
|
|
176
|
+
|
|
177
|
+
//# sourceMappingURL=base-C9husdYd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-C9husdYd.js","names":[],"sources":["../../src/shared/base.ts"],"sourcesContent":["import {\n type BaseProviderOptions,\n type CacheOptions,\n type CreateDirOptions,\n type DownloadOptions,\n type FileInfo,\n type FileStats,\n type FilesystemCapabilities,\n FilesystemError,\n type FilesystemInterface,\n type ListFilesOptions,\n type ListOptions,\n type ReadOptions,\n type UploadOptions,\n type WriteOptions,\n} from './types';\n\n/**\n * Abstract base class for filesystem providers.\n *\n * Implements {@link FilesystemInterface} with shared logic for path normalization,\n * validation, caching, and legacy method adapters. Concrete providers (e.g.\n * {@link LocalFilesystemProvider}, {@link GoogleDriveProvider}) extend this class\n * and implement the abstract methods for their specific storage backend.\n */\nexport abstract class BaseFilesystemProvider implements FilesystemInterface {\n protected basePath: string;\n protected applyBasePath: boolean;\n protected cacheDir: string;\n protected createMissing: boolean;\n protected providerType: string;\n\n constructor(options: BaseProviderOptions = {}) {\n this.basePath = options.basePath || '';\n this.applyBasePath = options.applyBasePath ?? true;\n // Use a universal cache directory approach - will be context-specific\n this.cacheDir = options.cacheDir || this.getDefaultCacheDir();\n this.createMissing = options.createMissing ?? true;\n this.providerType = this.constructor.name\n .toLowerCase()\n .replace('filesystemprovider', '');\n }\n\n /**\n * Get default cache directory for the current context\n */\n private getDefaultCacheDir(): string {\n // Use context-aware temp directory from utils\n try {\n const { getTempDirectory } = require('@happyvertical/utils');\n return getTempDirectory('files-cache');\n } catch {\n // Fallback if utils not available\n if (process?.versions?.node) {\n try {\n const { tmpdir } = require('node:os');\n const { join } = require('node:path');\n return join(tmpdir(), 'have-sdk', 'files-cache');\n } catch {\n return './tmp/have-sdk/files-cache';\n }\n }\n return './tmp/have-sdk/files-cache';\n }\n }\n\n /**\n * Throw error for unsupported operations\n */\n protected throwUnsupported(operation: string): never {\n throw new FilesystemError(\n `Operation '${operation}' not supported by ${this.providerType} provider`,\n 'ENOTSUP',\n undefined,\n this.providerType,\n );\n }\n\n /**\n * Normalize path by removing leading/trailing slashes and resolving relative paths\n */\n protected normalizePath(path: string): string {\n if (!path) return '';\n\n // Remove leading slash for consistency\n let normalized = path.startsWith('/') ? path.slice(1) : path;\n\n // Combine with base path if configured\n if (this.applyBasePath && this.basePath) {\n normalized = this.joinPaths(this.basePath, normalized);\n }\n\n return normalized;\n }\n\n /**\n * Universal path joining function that works in both Node.js and browser\n */\n private joinPaths(...paths: string[]): string {\n return paths\n .filter((p) => p && p.length > 0)\n .map((p) => p.replace(/^\\/+|\\/+$/g, ''))\n .join('/');\n }\n\n /**\n * Validate that a path is safe (no directory traversal)\n */\n protected validatePath(path: string): void {\n if (!path) {\n throw new FilesystemError('Path cannot be empty', 'EINVAL', path);\n }\n\n // Check for directory traversal attempts\n if (path.includes('..') || path.includes('~')) {\n throw new FilesystemError(\n 'Path contains invalid characters (directory traversal)',\n 'EINVAL',\n path,\n );\n }\n }\n\n /**\n * Get cache key for a given path\n */\n protected getCacheKey(path: string): string {\n return `${this.constructor.name}-${path}`;\n }\n\n /**\n * Abstract methods that must be implemented by providers\n */\n abstract exists(path: string): Promise<boolean>;\n abstract read(path: string, options?: ReadOptions): Promise<string | Buffer>;\n abstract write(\n path: string,\n content: string | Buffer,\n options?: WriteOptions,\n ): Promise<void>;\n abstract delete(path: string): Promise<void>;\n abstract copy(sourcePath: string, destPath: string): Promise<void>;\n abstract move(sourcePath: string, destPath: string): Promise<void>;\n abstract createDirectory(\n path: string,\n options?: CreateDirOptions,\n ): Promise<void>;\n abstract list(path: string, options?: ListOptions): Promise<FileInfo[]>;\n abstract getStats(path: string): Promise<FileStats>;\n abstract getMimeType(path: string): Promise<string>;\n abstract getCapabilities(): Promise<FilesystemCapabilities>;\n\n /**\n * Provider methods with default implementations (may be overridden)\n */\n async upload(\n _localPath: string,\n _remotePath: string,\n _options: UploadOptions = {},\n ): Promise<void> {\n this.throwUnsupported('upload');\n }\n\n async download(\n _remotePath: string,\n _localPath?: string,\n _options: DownloadOptions = {},\n ): Promise<string> {\n this.throwUnsupported('download');\n }\n\n async downloadWithCache(\n remotePath: string,\n options: CacheOptions = {},\n ): Promise<string> {\n const cacheKey = this.getCacheKey(remotePath);\n\n // Check cache first\n if (!options.force) {\n const cached = await this.cache.get(cacheKey, options.expiry);\n if (cached) {\n return cached;\n }\n }\n\n // Download and cache\n const localPath = await this.download(remotePath, undefined, options);\n await this.cache.set(cacheKey, localPath);\n\n return localPath;\n }\n\n /**\n * Cache implementation - providers can override for their specific storage\n */\n cache = {\n get: async (\n _key: string,\n _expiry?: number,\n ): Promise<string | undefined> => {\n // Default implementation - providers should override this\n this.throwUnsupported('cache.get');\n },\n\n set: async (_key: string, _data: string): Promise<void> => {\n // Default implementation - providers should override this\n this.throwUnsupported('cache.set');\n },\n\n clear: async (_key?: string): Promise<void> => {\n // Default implementation - providers should override this\n this.throwUnsupported('cache.clear');\n },\n };\n\n // Legacy method implementations - providers can override or use default ENOTSUP errors\n\n /**\n * Check if a path is a file (legacy)\n */\n async isFile(file: string): Promise<false | FileStats> {\n try {\n const stats = await this.getStats(file);\n return stats.isFile ? stats : false;\n } catch {\n return false;\n }\n }\n\n /**\n * Check if a path is a directory (legacy)\n */\n async isDirectory(dir: string): Promise<boolean> {\n try {\n const stats = await this.getStats(dir);\n return stats.isDirectory;\n } catch {\n return false;\n }\n }\n\n /**\n * Create a directory if it doesn't exist (legacy)\n */\n async ensureDirectoryExists(dir: string): Promise<void> {\n if (!(await this.isDirectory(dir))) {\n await this.createDirectory(dir, { recursive: true });\n }\n }\n\n /**\n * Upload data to a URL using PUT method (legacy)\n */\n async uploadToUrl(_url: string, _data: string | Buffer): Promise<Response> {\n this.throwUnsupported('uploadToUrl');\n }\n\n /**\n * Download a file from a URL and save it to a local file (legacy)\n */\n async downloadFromUrl(_url: string, _filepath: string): Promise<void> {\n this.throwUnsupported('downloadFromUrl');\n }\n\n /**\n * Download a file with caching support (legacy)\n */\n async downloadFileWithCache(\n _url: string,\n _targetPath?: string | null,\n ): Promise<string> {\n this.throwUnsupported('downloadFileWithCache');\n }\n\n /**\n * List files in a directory with optional filtering (legacy)\n */\n async listFiles(\n dirPath: string,\n options: ListFilesOptions = { match: /.*/ },\n ): Promise<string[]> {\n const files = await this.list(dirPath);\n const fileNames = files\n .filter((file) => !file.isDirectory)\n .map((file) => file.name);\n\n return options.match\n ? fileNames.filter((name) => options.match?.test(name))\n : fileNames;\n }\n\n /**\n * Get data from cache if available and not expired (legacy)\n */\n async getCached(file: string, expiry = 300000): Promise<string | undefined> {\n return await this.cache.get(file, expiry);\n }\n\n /**\n * Set data in cache (legacy)\n */\n async setCached(file: string, data: string): Promise<void> {\n await this.cache.set(file, data);\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __exportAll = (all, no_symbols) => {
|
|
4
|
+
let target = {};
|
|
5
|
+
for (var name in all) __defProp(target, name, {
|
|
6
|
+
get: all[name],
|
|
7
|
+
enumerable: true
|
|
8
|
+
});
|
|
9
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
10
|
+
return target;
|
|
11
|
+
};
|
|
12
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof require !== "undefined" ? require : a)[b] }) : x)(function(x) {
|
|
13
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
14
|
+
throw Error("Calling `require` for \"" + x + "\" in an environment that doesn't expose the `require` function. See https://rolldown.rs/in-depth/bundling-cjs#require-external-modules for more details.");
|
|
15
|
+
});
|
|
16
|
+
//#endregion
|
|
17
|
+
//#region src/shared/types.ts
|
|
18
|
+
/**
|
|
19
|
+
* Error types for filesystem operations
|
|
20
|
+
*/
|
|
21
|
+
var FilesystemError = class extends Error {
|
|
22
|
+
code;
|
|
23
|
+
path;
|
|
24
|
+
provider;
|
|
25
|
+
constructor(message, code, path, provider) {
|
|
26
|
+
super(message);
|
|
27
|
+
this.code = code;
|
|
28
|
+
this.path = path;
|
|
29
|
+
this.provider = provider;
|
|
30
|
+
this.name = "FilesystemError";
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
var FileNotFoundError = class extends FilesystemError {
|
|
34
|
+
constructor(path, provider) {
|
|
35
|
+
super(`File not found: ${path}`, "ENOENT", path, provider);
|
|
36
|
+
this.name = "FileNotFoundError";
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
var PermissionError = class extends FilesystemError {
|
|
40
|
+
constructor(path, provider) {
|
|
41
|
+
super(`Permission denied: ${path}`, "EACCES", path, provider);
|
|
42
|
+
this.name = "PermissionError";
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
var DirectoryNotEmptyError = class extends FilesystemError {
|
|
46
|
+
constructor(path, provider) {
|
|
47
|
+
super(`Directory not empty: ${path}`, "ENOTEMPTY", path, provider);
|
|
48
|
+
this.name = "DirectoryNotEmptyError";
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
var InvalidPathError = class extends FilesystemError {
|
|
52
|
+
constructor(path, provider) {
|
|
53
|
+
super(`Invalid path: ${path}`, "EINVAL", path, provider);
|
|
54
|
+
this.name = "InvalidPathError";
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
//#endregion
|
|
58
|
+
export { PermissionError as a, InvalidPathError as i, FileNotFoundError as n, __exportAll as o, FilesystemError as r, __require as s, DirectoryNotEmptyError as t };
|
|
59
|
+
|
|
60
|
+
//# sourceMappingURL=types-OwkcCRpq.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-OwkcCRpq.js","names":[],"sources":["../../src/shared/types.ts"],"sourcesContent":["/**\n * Core types and interfaces for the Files library\n */\n\n/**\n * Options for reading files\n */\nexport interface ReadOptions {\n /**\n * Text encoding for reading the file\n */\n encoding?: BufferEncoding;\n\n /**\n * Whether to return raw buffer data instead of string\n */\n raw?: boolean;\n}\n\n/**\n * Options for writing files\n */\nexport interface WriteOptions {\n /**\n * Text encoding for writing the file\n */\n encoding?: BufferEncoding;\n\n /**\n * File mode (permissions)\n */\n mode?: number;\n\n /**\n * Whether to create parent directories if they don't exist\n */\n createParents?: boolean;\n}\n\n/**\n * Options for creating directories\n */\nexport interface CreateDirOptions {\n /**\n * Whether to create parent directories recursively\n */\n recursive?: boolean;\n\n /**\n * Directory mode (permissions)\n */\n mode?: number;\n}\n\n/**\n * Options for listing directory contents\n */\nexport interface ListOptions {\n /**\n * Whether to include subdirectories\n */\n recursive?: boolean;\n\n /**\n * Filter pattern for file names\n */\n filter?: RegExp | string;\n\n /**\n * Whether to return full file information\n */\n detailed?: boolean;\n}\n\n/**\n * Options for file upload operations\n */\nexport interface UploadOptions {\n /**\n * Content type for the upload\n */\n contentType?: string;\n\n /**\n * Whether to overwrite existing files\n */\n overwrite?: boolean;\n\n /**\n * Custom metadata to attach to the file\n */\n metadata?: Record<string, string>;\n\n /**\n * Progress callback function\n */\n onProgress?: (progress: { loaded: number; total: number }) => void;\n}\n\n/**\n * Options for file download operations\n */\nexport interface DownloadOptions {\n /**\n * Whether to force download even if local copy exists\n */\n force?: boolean;\n\n /**\n * Progress callback function\n */\n onProgress?: (progress: { loaded: number; total: number }) => void;\n}\n\n/**\n * Options for caching operations\n */\nexport interface CacheOptions {\n /**\n * Cache expiry time in milliseconds\n */\n expiry?: number;\n\n /**\n * Whether to force download even if cached\n */\n force?: boolean;\n}\n\n/**\n * Options for listing files (legacy compatibility)\n */\nexport interface ListFilesOptions {\n /**\n * Optional regular expression to filter files by name\n */\n match?: RegExp;\n}\n\n/**\n * File information structure\n */\nexport interface FileInfo {\n /**\n * File name\n */\n name: string;\n\n /**\n * Full path to the file\n */\n path: string;\n\n /**\n * File size in bytes\n */\n size: number;\n\n /**\n * Whether this is a directory\n */\n isDirectory: boolean;\n\n /**\n * Last modified date\n */\n lastModified: Date;\n\n /**\n * MIME type of the file\n */\n mimeType?: string;\n\n /**\n * File extension\n */\n extension?: string;\n}\n\n/**\n * File statistics structure\n */\nexport interface FileStats {\n /**\n * File size in bytes\n */\n size: number;\n\n /**\n * Whether this is a directory\n */\n isDirectory: boolean;\n\n /**\n * Whether this is a regular file\n */\n isFile: boolean;\n\n /**\n * Creation time\n */\n birthtime: Date;\n\n /**\n * Last access time\n */\n atime: Date;\n\n /**\n * Last modification time\n */\n mtime: Date;\n\n /**\n * Last status change time\n */\n ctime: Date;\n\n /**\n * File mode (permissions)\n */\n mode: number;\n\n /**\n * User ID of file owner\n */\n uid: number;\n\n /**\n * Group ID of file owner\n */\n gid: number;\n}\n\n/**\n * Filesystem capabilities structure\n */\nexport interface FilesystemCapabilities {\n /**\n * Whether the filesystem supports streaming\n */\n streaming: boolean;\n\n /**\n * Whether the filesystem supports atomic operations\n */\n atomicOperations: boolean;\n\n /**\n * Whether the filesystem supports file versioning\n */\n versioning: boolean;\n\n /**\n * Whether the filesystem supports sharing/permissions\n */\n sharing: boolean;\n\n /**\n * Whether the filesystem supports real-time synchronization\n */\n realTimeSync: boolean;\n\n /**\n * Whether the filesystem can work offline\n */\n offlineCapable: boolean;\n\n /**\n * Maximum file size supported (in bytes)\n */\n maxFileSize?: number;\n\n /**\n * Supported file operations\n */\n supportedOperations: string[];\n}\n\n/**\n * Core filesystem interface that all providers must implement\n */\nexport interface FilesystemInterface {\n /**\n * Check if a file or directory exists\n */\n exists(path: string): Promise<boolean>;\n\n /**\n * Read file contents\n */\n read(path: string, options?: ReadOptions): Promise<string | Buffer>;\n\n /**\n * Write content to a file\n */\n write(\n path: string,\n content: string | Buffer,\n options?: WriteOptions,\n ): Promise<void>;\n\n /**\n * Delete a file or directory\n */\n delete(path: string): Promise<void>;\n\n /**\n * Copy a file from source to destination\n */\n copy(sourcePath: string, destPath: string): Promise<void>;\n\n /**\n * Move a file from source to destination\n */\n move(sourcePath: string, destPath: string): Promise<void>;\n\n /**\n * Create a directory\n */\n createDirectory(path: string, options?: CreateDirOptions): Promise<void>;\n\n /**\n * List directory contents\n */\n list(path: string, options?: ListOptions): Promise<FileInfo[]>;\n\n /**\n * Get file statistics\n */\n getStats(path: string): Promise<FileStats>;\n\n /**\n * Get MIME type for a file\n */\n getMimeType(path: string): Promise<string>;\n\n /**\n * Upload a file (for remote providers)\n */\n upload(\n localPath: string,\n remotePath: string,\n options?: UploadOptions,\n ): Promise<void>;\n\n /**\n * Download a file (for remote providers)\n */\n download(\n remotePath: string,\n localPath?: string,\n options?: DownloadOptions,\n ): Promise<string>;\n\n /**\n * Download file with caching\n */\n downloadWithCache(\n remotePath: string,\n options?: CacheOptions,\n ): Promise<string>;\n\n /**\n * Caching operations\n */\n cache: {\n get(key: string, expiry?: number): Promise<string | undefined>;\n set(key: string, data: string): Promise<void>;\n clear(key?: string): Promise<void>;\n };\n\n /**\n * Get provider capabilities\n */\n getCapabilities(): Promise<FilesystemCapabilities>;\n\n // Legacy method compatibility - all providers must implement these\n\n /**\n * Check if a path is a file (legacy)\n */\n isFile(file: string): Promise<false | FileStats>;\n\n /**\n * Check if a path is a directory (legacy)\n */\n isDirectory(dir: string): Promise<boolean>;\n\n /**\n * Create a directory if it doesn't exist (legacy)\n */\n ensureDirectoryExists(dir: string): Promise<void>;\n\n /**\n * Upload data to a URL using PUT method (legacy)\n */\n uploadToUrl(url: string, data: string | Buffer): Promise<Response>;\n\n /**\n * Download a file from a URL and save it to a local file (legacy)\n */\n downloadFromUrl(url: string, filepath: string): Promise<void>;\n\n /**\n * Download a file with caching support (legacy)\n */\n downloadFileWithCache(\n url: string,\n targetPath?: string | null,\n ): Promise<string>;\n\n /**\n * List files in a directory with optional filtering (legacy)\n */\n listFiles(dirPath: string, options?: ListFilesOptions): Promise<string[]>;\n\n /**\n * Get data from cache if available and not expired (legacy)\n */\n getCached(file: string, expiry?: number): Promise<string | undefined>;\n\n /**\n * Set data in cache (legacy)\n */\n setCached(file: string, data: string): Promise<void>;\n}\n\n/**\n * Base configuration options for all providers\n */\nexport interface BaseProviderOptions {\n /**\n * Base path for operations\n */\n basePath?: string;\n\n /**\n * Whether shared path normalization should prefix basePath.\n * Providers that map basePath into their own storage root can disable this.\n */\n applyBasePath?: boolean;\n\n /**\n * Cache directory location\n */\n cacheDir?: string;\n\n /**\n * Whether to create missing directories\n */\n createMissing?: boolean;\n}\n\n/**\n * Local filesystem provider options\n */\nexport interface LocalOptions extends BaseProviderOptions {\n type?: 'local';\n}\n\n/**\n * S3-compatible provider options\n */\nexport interface S3Options extends BaseProviderOptions {\n type: 's3';\n region: string;\n bucket: string;\n accessKeyId?: string;\n secretAccessKey?: string;\n endpoint?: string;\n forcePathStyle?: boolean;\n}\n\n/**\n * Google Drive provider options\n *\n * Supports three authentication modes:\n * 1. OAuth2: clientId + clientSecret + refreshToken\n * 2. Service account: serviceAccountKey (JSON string)\n * 3. Access token: accessToken (short-lived, no auto-refresh)\n */\nexport interface GoogleDriveOptions extends BaseProviderOptions {\n type: 'gdrive';\n /** OAuth2 client ID */\n clientId?: string;\n /** OAuth2 client secret */\n clientSecret?: string;\n /** OAuth2 refresh token */\n refreshToken?: string;\n /** Short-lived access token (no auto-refresh) */\n accessToken?: string;\n /** Service account key as JSON string */\n serviceAccountKey?: string;\n /** Root folder ID to scope operations (defaults to 'root') */\n folderId?: string;\n /** OAuth2 scopes (defaults to drive.file) */\n scopes?: string[];\n /** TTL for path-to-ID cache in ms (default 300000 / 5 min) */\n pathCacheTTL?: number;\n /** Page size for list pagination (default 100) */\n pageSize?: number;\n}\n\n/**\n * WebDAV provider options (supports Nextcloud, ownCloud, Apache, etc.)\n */\nexport interface WebDAVOptions extends BaseProviderOptions {\n type: 'webdav';\n baseUrl: string;\n username: string;\n password: string;\n davPath?: string;\n}\n\n/**\n * Browser storage provider options (uses IndexedDB for app storage)\n */\nexport interface BrowserStorageOptions extends BaseProviderOptions {\n type: 'browser-storage';\n /**\n * Database name for IndexedDB\n */\n databaseName?: string;\n /**\n * Maximum storage quota to request (in bytes)\n */\n storageQuota?: number;\n}\n\n/**\n * Union type for all provider options\n */\nexport type GetFilesystemOptions =\n | LocalOptions\n | S3Options\n | GoogleDriveOptions\n | WebDAVOptions\n | BrowserStorageOptions;\n\n/**\n * Error types for filesystem operations\n */\nexport class FilesystemError extends Error {\n constructor(\n message: string,\n public code: string,\n public path?: string,\n public provider?: string,\n ) {\n super(message);\n this.name = 'FilesystemError';\n }\n}\n\nexport class FileNotFoundError extends FilesystemError {\n constructor(path: string, provider?: string) {\n super(`File not found: ${path}`, 'ENOENT', path, provider);\n this.name = 'FileNotFoundError';\n }\n}\n\nexport class PermissionError extends FilesystemError {\n constructor(path: string, provider?: string) {\n super(`Permission denied: ${path}`, 'EACCES', path, provider);\n this.name = 'PermissionError';\n }\n}\n\nexport class DirectoryNotEmptyError extends FilesystemError {\n constructor(path: string, provider?: string) {\n super(`Directory not empty: ${path}`, 'ENOTEMPTY', path, provider);\n this.name = 'DirectoryNotEmptyError';\n }\n}\n\nexport class InvalidPathError extends FilesystemError {\n constructor(path: string, provider?: string) {\n super(`Invalid path: ${path}`, 'EINVAL', path, provider);\n this.name = 'InvalidPathError';\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA+hBA,IAAa,kBAAb,cAAqC,MAAM;CAGhC;CACA;CACA;CAJT,YACE,SACA,MACA,MACA,UACA;EACA,MAAM,OAAO;EAJN,KAAA,OAAA;EACA,KAAA,OAAA;EACA,KAAA,WAAA;EAGP,KAAK,OAAO;CACd;AACF;AAEA,IAAa,oBAAb,cAAuC,gBAAgB;CACrD,YAAY,MAAc,UAAmB;EAC3C,MAAM,mBAAmB,QAAQ,UAAU,MAAM,QAAQ;EACzD,KAAK,OAAO;CACd;AACF;AAEA,IAAa,kBAAb,cAAqC,gBAAgB;CACnD,YAAY,MAAc,UAAmB;EAC3C,MAAM,sBAAsB,QAAQ,UAAU,MAAM,QAAQ;EAC5D,KAAK,OAAO;CACd;AACF;AAEA,IAAa,yBAAb,cAA4C,gBAAgB;CAC1D,YAAY,MAAc,UAAmB;EAC3C,MAAM,wBAAwB,QAAQ,aAAa,MAAM,QAAQ;EACjE,KAAK,OAAO;CACd;AACF;AAEA,IAAa,mBAAb,cAAsC,gBAAgB;CACpD,YAAY,MAAc,UAAmB;EAC3C,MAAM,iBAAiB,QAAQ,UAAU,MAAM,QAAQ;EACvD,KAAK,OAAO;CACd;AACF"}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { existsSync, mkdirSync
|
|
2
|
+
import { copyFileSync, existsSync, mkdirSync } from "node:fs";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
if (existsSync(metaSrc)) {
|
|
18
|
-
copyFileSync(metaSrc, join(targetDir, `have-${pkgName}.meta.json`));
|
|
19
|
-
}
|
|
5
|
+
//#region src/cli/claude-context.ts
|
|
6
|
+
/**
|
|
7
|
+
* CLI script to install agent context for @happyvertical/files
|
|
8
|
+
* Run the published context installer binary for this package.
|
|
9
|
+
*/
|
|
10
|
+
var pkgRoot = join(dirname(fileURLToPath(import.meta.url)), "../..");
|
|
11
|
+
var targetDir = join(process.cwd(), ".claude");
|
|
12
|
+
if (!existsSync(targetDir)) mkdirSync(targetDir, { recursive: true });
|
|
13
|
+
var pkgName = "files";
|
|
14
|
+
var agentMdSrc = existsSync(join(pkgRoot, "AGENT.md")) ? join(pkgRoot, "AGENT.md") : join(pkgRoot, "CLAUDE.md");
|
|
15
|
+
var metaSrc = existsSync(join(pkgRoot, "metadata.json")) ? join(pkgRoot, "metadata.json") : join(pkgRoot, ".claude-meta.json");
|
|
16
|
+
if (existsSync(agentMdSrc)) copyFileSync(agentMdSrc, join(targetDir, `have-${pkgName}.md`));
|
|
17
|
+
if (existsSync(metaSrc)) copyFileSync(metaSrc, join(targetDir, `have-${pkgName}.meta.json`));
|
|
20
18
|
console.log(`✓ Installed @happyvertical/${pkgName} context to .claude/`);
|
|
21
|
-
//#
|
|
19
|
+
//#endregion
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=claude-context.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-context.js","sources":["../../src/cli/claude-context.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * CLI script to install agent context for @happyvertical/files\n * Run the published context installer binary for this package.\n */\nimport { copyFileSync, existsSync, mkdirSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst Dirname = dirname(fileURLToPath(import.meta.url));\nconst pkgRoot = join(Dirname, '../..');\nconst targetDir = join(process.cwd(), '.claude');\n\nif (!existsSync(targetDir)) {\n mkdirSync(targetDir, { recursive: true });\n}\n\nconst pkgName = 'files';\nconst agentMdSrc = existsSync(join(pkgRoot, 'AGENT.md'))\n ? join(pkgRoot, 'AGENT.md')\n : join(pkgRoot, 'CLAUDE.md');\nconst metaSrc = existsSync(join(pkgRoot, 'metadata.json'))\n ? join(pkgRoot, 'metadata.json')\n : join(pkgRoot, '.claude-meta.json');\n\nif (existsSync(agentMdSrc)) {\n copyFileSync(agentMdSrc, join(targetDir, `have-${pkgName}.md`));\n}\n\nif (existsSync(metaSrc)) {\n copyFileSync(metaSrc, join(targetDir, `have-${pkgName}.meta.json`));\n}\n\nconsole.log(`✓ Installed @happyvertical/${pkgName} context to .claude/`);\n"],"
|
|
1
|
+
{"version":3,"file":"claude-context.js","names":[],"sources":["../../src/cli/claude-context.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * CLI script to install agent context for @happyvertical/files\n * Run the published context installer binary for this package.\n */\nimport { copyFileSync, existsSync, mkdirSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst Dirname = dirname(fileURLToPath(import.meta.url));\nconst pkgRoot = join(Dirname, '../..');\nconst targetDir = join(process.cwd(), '.claude');\n\nif (!existsSync(targetDir)) {\n mkdirSync(targetDir, { recursive: true });\n}\n\nconst pkgName = 'files';\nconst agentMdSrc = existsSync(join(pkgRoot, 'AGENT.md'))\n ? join(pkgRoot, 'AGENT.md')\n : join(pkgRoot, 'CLAUDE.md');\nconst metaSrc = existsSync(join(pkgRoot, 'metadata.json'))\n ? join(pkgRoot, 'metadata.json')\n : join(pkgRoot, '.claude-meta.json');\n\nif (existsSync(agentMdSrc)) {\n copyFileSync(agentMdSrc, join(targetDir, `have-${pkgName}.md`));\n}\n\nif (existsSync(metaSrc)) {\n copyFileSync(metaSrc, join(targetDir, `have-${pkgName}.meta.json`));\n}\n\nconsole.log(`✓ Installed @happyvertical/${pkgName} context to .claude/`);\n"],"mappings":";;;;;;;;;AAUA,IAAM,UAAU,KADA,QAAQ,cAAc,OAAO,KAAK,GAAG,CAChC,GAAS,OAAO;AACrC,IAAM,YAAY,KAAK,QAAQ,IAAI,GAAG,SAAS;AAE/C,IAAI,CAAC,WAAW,SAAS,GACvB,UAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAG1C,IAAM,UAAU;AAChB,IAAM,aAAa,WAAW,KAAK,SAAS,UAAU,CAAC,IACnD,KAAK,SAAS,UAAU,IACxB,KAAK,SAAS,WAAW;AAC7B,IAAM,UAAU,WAAW,KAAK,SAAS,eAAe,CAAC,IACrD,KAAK,SAAS,eAAe,IAC7B,KAAK,SAAS,mBAAmB;AAErC,IAAI,WAAW,UAAU,GACvB,aAAa,YAAY,KAAK,WAAW,QAAQ,QAAQ,IAAI,CAAC;AAGhE,IAAI,WAAW,OAAO,GACpB,aAAa,SAAS,KAAK,WAAW,QAAQ,QAAQ,WAAW,CAAC;AAGpE,QAAQ,IAAI,8BAA8B,QAAQ,qBAAqB"}
|