@mastra/gcs 0.0.1 → 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 +70 -0
- package/dist/filesystem/index.d.ts +9 -5
- package/dist/filesystem/index.d.ts.map +1 -1
- package/dist/index.cjs +11 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +12 -4
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,75 @@
|
|
|
1
1
|
# @mastra/gcs
|
|
2
2
|
|
|
3
|
+
## 0.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Updated minimum `@mastra/core` peer dependency to support the new `FilesystemLifecycle` and `SandboxLifecycle` interfaces and `onInit` / `onDestroy` lifecycle callbacks. ([#12978](https://github.com/mastra-ai/mastra/pull/12978))
|
|
8
|
+
|
|
9
|
+
See the `@mastra/s3` and `@mastra/gcs` patch changesets for usage examples.
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- dependencies updates: ([#12931](https://github.com/mastra-ai/mastra/pull/12931))
|
|
14
|
+
- Updated dependency [`@google-cloud/storage@^7.19.0` ↗︎](https://www.npmjs.com/package/@google-cloud/storage/v/7.19.0) (from `^7.18.0`, in `dependencies`)
|
|
15
|
+
|
|
16
|
+
- Add typed metadata to getInfo() return type and ensure all common FilesystemInfo fields (error, readOnly) are returned. ([#12971](https://github.com/mastra-ai/mastra/pull/12971))
|
|
17
|
+
|
|
18
|
+
- Added `overwrite: false` support to `writeFile` and `copyFile`. Previously, the `overwrite` option was ignored, allowing files to be silently overwritten. Now throws `FileExistsError` when `overwrite` is set to `false` and the destination file already exists. ([#12912](https://github.com/mastra-ai/mastra/pull/12912))
|
|
19
|
+
|
|
20
|
+
- Added optional `onInit` and `onDestroy` lifecycle callbacks to `GCSFilesystemOptions`. ([#12978](https://github.com/mastra-ai/mastra/pull/12978))
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
const fs = new GCSFilesystem({
|
|
24
|
+
bucket: 'my-bucket',
|
|
25
|
+
projectId: 'my-project',
|
|
26
|
+
onInit: ({ filesystem }) => {
|
|
27
|
+
console.log('GCS filesystem ready:', filesystem.status);
|
|
28
|
+
},
|
|
29
|
+
onDestroy: ({ filesystem }) => {
|
|
30
|
+
console.log('GCS filesystem shutting down');
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
- Updated dependencies [[`7ef618f`](https://github.com/mastra-ai/mastra/commit/7ef618f3c49c27e2f6b27d7f564c557c0734325b), [`b373564`](https://github.com/mastra-ai/mastra/commit/b37356491d43b4d53067f10cb669abaf2502f218), [`927c2af`](https://github.com/mastra-ai/mastra/commit/927c2af9792286c122e04409efce0f3c804f777f), [`b896b41`](https://github.com/mastra-ai/mastra/commit/b896b41343de7fcc14442fb40fe82d189e65bbe2), [`6415277`](https://github.com/mastra-ai/mastra/commit/6415277a438faa00db2af850ead5dee25f40c428), [`0831bbb`](https://github.com/mastra-ai/mastra/commit/0831bbb5bc750c18e9b22b45f18687c964b70828), [`63f7eda`](https://github.com/mastra-ai/mastra/commit/63f7eda605eb3e0c8c35ee3912ffe7c999c69f69), [`a5b67a3`](https://github.com/mastra-ai/mastra/commit/a5b67a3589a74415feb663a55d1858324a2afde9), [`877b02c`](https://github.com/mastra-ai/mastra/commit/877b02cdbb15e199184c7f2b8f217be8d3ebada7), [`7567222`](https://github.com/mastra-ai/mastra/commit/7567222b1366f0d39980594792dd9d5060bfe2ab), [`af71458`](https://github.com/mastra-ai/mastra/commit/af71458e3b566f09c11d0e5a0a836dc818e7a24a), [`eb36bd8`](https://github.com/mastra-ai/mastra/commit/eb36bd8c52fcd6ec9674ac3b7a6412405b5983e1), [`3cbf121`](https://github.com/mastra-ai/mastra/commit/3cbf121f55418141924754a83102aade89835947)]:
|
|
36
|
+
- @mastra/core@1.4.0
|
|
37
|
+
|
|
38
|
+
## 0.1.0-alpha.0
|
|
39
|
+
|
|
40
|
+
### Minor Changes
|
|
41
|
+
|
|
42
|
+
- Updated minimum `@mastra/core` peer dependency to support the new `FilesystemLifecycle` and `SandboxLifecycle` interfaces and `onInit` / `onDestroy` lifecycle callbacks. ([#12978](https://github.com/mastra-ai/mastra/pull/12978))
|
|
43
|
+
|
|
44
|
+
See the `@mastra/s3` and `@mastra/gcs` patch changesets for usage examples.
|
|
45
|
+
|
|
46
|
+
### Patch Changes
|
|
47
|
+
|
|
48
|
+
- dependencies updates: ([#12931](https://github.com/mastra-ai/mastra/pull/12931))
|
|
49
|
+
- Updated dependency [`@google-cloud/storage@^7.19.0` ↗︎](https://www.npmjs.com/package/@google-cloud/storage/v/7.19.0) (from `^7.18.0`, in `dependencies`)
|
|
50
|
+
|
|
51
|
+
- Add typed metadata to getInfo() return type and ensure all common FilesystemInfo fields (error, readOnly) are returned. ([#12971](https://github.com/mastra-ai/mastra/pull/12971))
|
|
52
|
+
|
|
53
|
+
- Added `overwrite: false` support to `writeFile` and `copyFile`. Previously, the `overwrite` option was ignored, allowing files to be silently overwritten. Now throws `FileExistsError` when `overwrite` is set to `false` and the destination file already exists. ([#12912](https://github.com/mastra-ai/mastra/pull/12912))
|
|
54
|
+
|
|
55
|
+
- Added optional `onInit` and `onDestroy` lifecycle callbacks to `GCSFilesystemOptions`. ([#12978](https://github.com/mastra-ai/mastra/pull/12978))
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
const fs = new GCSFilesystem({
|
|
59
|
+
bucket: 'my-bucket',
|
|
60
|
+
projectId: 'my-project',
|
|
61
|
+
onInit: ({ filesystem }) => {
|
|
62
|
+
console.log('GCS filesystem ready:', filesystem.status);
|
|
63
|
+
},
|
|
64
|
+
onDestroy: ({ filesystem }) => {
|
|
65
|
+
console.log('GCS filesystem shutting down');
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
- Updated dependencies [[`7ef618f`](https://github.com/mastra-ai/mastra/commit/7ef618f3c49c27e2f6b27d7f564c557c0734325b), [`b373564`](https://github.com/mastra-ai/mastra/commit/b37356491d43b4d53067f10cb669abaf2502f218), [`927c2af`](https://github.com/mastra-ai/mastra/commit/927c2af9792286c122e04409efce0f3c804f777f), [`b896b41`](https://github.com/mastra-ai/mastra/commit/b896b41343de7fcc14442fb40fe82d189e65bbe2), [`6415277`](https://github.com/mastra-ai/mastra/commit/6415277a438faa00db2af850ead5dee25f40c428), [`0831bbb`](https://github.com/mastra-ai/mastra/commit/0831bbb5bc750c18e9b22b45f18687c964b70828), [`63f7eda`](https://github.com/mastra-ai/mastra/commit/63f7eda605eb3e0c8c35ee3912ffe7c999c69f69), [`a5b67a3`](https://github.com/mastra-ai/mastra/commit/a5b67a3589a74415feb663a55d1858324a2afde9), [`877b02c`](https://github.com/mastra-ai/mastra/commit/877b02cdbb15e199184c7f2b8f217be8d3ebada7), [`7567222`](https://github.com/mastra-ai/mastra/commit/7567222b1366f0d39980594792dd9d5060bfe2ab), [`af71458`](https://github.com/mastra-ai/mastra/commit/af71458e3b566f09c11d0e5a0a836dc818e7a24a), [`eb36bd8`](https://github.com/mastra-ai/mastra/commit/eb36bd8c52fcd6ec9674ac3b7a6412405b5983e1), [`3cbf121`](https://github.com/mastra-ai/mastra/commit/3cbf121f55418141924754a83102aade89835947)]:
|
|
71
|
+
- @mastra/core@1.4.0-alpha.0
|
|
72
|
+
|
|
3
73
|
## 0.0.1
|
|
4
74
|
|
|
5
75
|
### Patch Changes
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* A filesystem implementation backed by Google Cloud Storage.
|
|
5
5
|
*/
|
|
6
|
-
import type { FileContent, FileStat, FileEntry, ReadOptions, WriteOptions, ListOptions, RemoveOptions, CopyOptions, FilesystemInfo, FilesystemMountConfig, FilesystemIcon, ProviderStatus } from '@mastra/core/workspace';
|
|
6
|
+
import type { FileContent, FileStat, FileEntry, ReadOptions, WriteOptions, ListOptions, RemoveOptions, CopyOptions, FilesystemInfo, FilesystemMountConfig, FilesystemIcon, ProviderStatus, MastraFilesystemOptions } from '@mastra/core/workspace';
|
|
7
7
|
import { MastraFilesystem } from '@mastra/core/workspace';
|
|
8
8
|
/**
|
|
9
9
|
* GCS mount configuration.
|
|
@@ -19,7 +19,7 @@ export interface GCSMountConfig extends FilesystemMountConfig {
|
|
|
19
19
|
/**
|
|
20
20
|
* GCS filesystem provider configuration.
|
|
21
21
|
*/
|
|
22
|
-
export interface GCSFilesystemOptions {
|
|
22
|
+
export interface GCSFilesystemOptions extends MastraFilesystemOptions {
|
|
23
23
|
/** Unique identifier for this filesystem instance */
|
|
24
24
|
id?: string;
|
|
25
25
|
/** GCS bucket name */
|
|
@@ -75,7 +75,11 @@ export declare class GCSFilesystem extends MastraFilesystem {
|
|
|
75
75
|
/**
|
|
76
76
|
* Get filesystem info for status reporting.
|
|
77
77
|
*/
|
|
78
|
-
getInfo(): FilesystemInfo
|
|
78
|
+
getInfo(): FilesystemInfo<{
|
|
79
|
+
bucket: string;
|
|
80
|
+
endpoint?: string;
|
|
81
|
+
prefix?: string;
|
|
82
|
+
}>;
|
|
79
83
|
/**
|
|
80
84
|
* Get instructions describing this GCS filesystem.
|
|
81
85
|
* Used by agents to understand storage semantics.
|
|
@@ -90,10 +94,10 @@ export declare class GCSFilesystem extends MastraFilesystem {
|
|
|
90
94
|
private getReadyBucket;
|
|
91
95
|
private toKey;
|
|
92
96
|
readFile(path: string, options?: ReadOptions): Promise<string | Buffer>;
|
|
93
|
-
writeFile(path: string, content: FileContent,
|
|
97
|
+
writeFile(path: string, content: FileContent, options?: WriteOptions): Promise<void>;
|
|
94
98
|
appendFile(path: string, content: FileContent): Promise<void>;
|
|
95
99
|
deleteFile(path: string, options?: RemoveOptions): Promise<void>;
|
|
96
|
-
copyFile(src: string, dest: string,
|
|
100
|
+
copyFile(src: string, dest: string, options?: CopyOptions): Promise<void>;
|
|
97
101
|
moveFile(src: string, dest: string, options?: CopyOptions): Promise<void>;
|
|
98
102
|
mkdir(_path: string, _options?: {
|
|
99
103
|
recursive?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/filesystem/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EACV,WAAW,EACX,QAAQ,EACR,SAAS,EACT,WAAW,EACX,YAAY,EACZ,WAAW,EACX,aAAa,EACb,WAAW,EACX,cAAc,EACd,qBAAqB,EACrB,cAAc,EACd,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/filesystem/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.cjs
CHANGED
|
@@ -71,7 +71,7 @@ var GCSFilesystem = class extends workspace.MastraFilesystem {
|
|
|
71
71
|
_storage = null;
|
|
72
72
|
_bucket = null;
|
|
73
73
|
constructor(options) {
|
|
74
|
-
super({ name: "GCSFilesystem" });
|
|
74
|
+
super({ ...options, name: "GCSFilesystem" });
|
|
75
75
|
this.id = options.id ?? `gcs-fs-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
76
76
|
this.bucketName = options.bucket;
|
|
77
77
|
this.projectId = options.projectId;
|
|
@@ -106,6 +106,8 @@ var GCSFilesystem = class extends workspace.MastraFilesystem {
|
|
|
106
106
|
name: this.name,
|
|
107
107
|
provider: this.provider,
|
|
108
108
|
status: this.status,
|
|
109
|
+
error: this.error,
|
|
110
|
+
readOnly: this.readOnly,
|
|
109
111
|
icon: this.icon,
|
|
110
112
|
metadata: {
|
|
111
113
|
bucket: this.bucketName,
|
|
@@ -178,9 +180,12 @@ var GCSFilesystem = class extends workspace.MastraFilesystem {
|
|
|
178
180
|
throw error;
|
|
179
181
|
}
|
|
180
182
|
}
|
|
181
|
-
async writeFile(path, content,
|
|
183
|
+
async writeFile(path, content, options) {
|
|
182
184
|
const bucket = await this.getReadyBucket();
|
|
183
185
|
const file = bucket.file(this.toKey(path));
|
|
186
|
+
if (options?.overwrite === false && await this.exists(path)) {
|
|
187
|
+
throw new workspace.FileExistsError(path);
|
|
188
|
+
}
|
|
184
189
|
const body = typeof content === "string" ? Buffer.from(content, "utf-8") : Buffer.from(content);
|
|
185
190
|
const contentType = getMimeType(path);
|
|
186
191
|
await file.save(body, {
|
|
@@ -219,10 +224,13 @@ var GCSFilesystem = class extends workspace.MastraFilesystem {
|
|
|
219
224
|
}
|
|
220
225
|
}
|
|
221
226
|
}
|
|
222
|
-
async copyFile(src, dest,
|
|
227
|
+
async copyFile(src, dest, options) {
|
|
223
228
|
const bucket = await this.getReadyBucket();
|
|
224
229
|
const srcFile = bucket.file(this.toKey(src));
|
|
225
230
|
const destFile = bucket.file(this.toKey(dest));
|
|
231
|
+
if (options?.overwrite === false && await this.exists(dest)) {
|
|
232
|
+
throw new workspace.FileExistsError(dest);
|
|
233
|
+
}
|
|
226
234
|
try {
|
|
227
235
|
await srcFile.copy(destFile);
|
|
228
236
|
} catch (error) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/filesystem/index.ts"],"names":["MastraFilesystem","Storage","FileNotFoundError","bucket","prefix"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * GCS Filesystem Provider\n *\n * A filesystem implementation backed by Google Cloud Storage.\n */\n\nimport { Storage } from '@google-cloud/storage';\nimport type { Bucket } from '@google-cloud/storage';\n\nimport type {\n FileContent,\n FileStat,\n FileEntry,\n ReadOptions,\n WriteOptions,\n ListOptions,\n RemoveOptions,\n CopyOptions,\n FilesystemInfo,\n FilesystemMountConfig,\n FilesystemIcon,\n ProviderStatus,\n} from '@mastra/core/workspace';\nimport { MastraFilesystem, FileNotFoundError } from '@mastra/core/workspace';\n\n/**\n * GCS mount configuration.\n * Returned by GCSFilesystem.getMountConfig() for FUSE mounting in sandboxes.\n */\nexport interface GCSMountConfig extends FilesystemMountConfig {\n type: 'gcs';\n /** GCS bucket name */\n bucket: string;\n /** Service account key JSON (optional - omit for public buckets or ADC) */\n serviceAccountKey?: string;\n}\n\n/**\n * Common MIME types by file extension.\n */\nconst MIME_TYPES: Record<string, string> = {\n // Text\n '.txt': 'text/plain',\n '.md': 'text/markdown',\n '.markdown': 'text/markdown',\n '.html': 'text/html',\n '.htm': 'text/html',\n '.css': 'text/css',\n '.csv': 'text/csv',\n '.xml': 'text/xml',\n // Code\n '.js': 'text/javascript',\n '.mjs': 'text/javascript',\n '.ts': 'text/typescript',\n '.tsx': 'text/typescript',\n '.jsx': 'text/javascript',\n '.json': 'application/json',\n '.yaml': 'text/yaml',\n '.yml': 'text/yaml',\n '.py': 'text/x-python',\n '.rb': 'text/x-ruby',\n '.sh': 'text/x-shellscript',\n '.bash': 'text/x-shellscript',\n // Images\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.svg': 'image/svg+xml',\n '.webp': 'image/webp',\n '.ico': 'image/x-icon',\n // Documents\n '.pdf': 'application/pdf',\n // Archives\n '.zip': 'application/zip',\n '.gz': 'application/gzip',\n '.tar': 'application/x-tar',\n};\n\n/**\n * Get MIME type from file path extension.\n */\nfunction getMimeType(path: string): string {\n const ext = path.toLowerCase().match(/\\.[^.]+$/)?.[0];\n return ext ? (MIME_TYPES[ext] ?? 'application/octet-stream') : 'application/octet-stream';\n}\n\n/**\n * GCS filesystem provider configuration.\n */\nexport interface GCSFilesystemOptions {\n /** Unique identifier for this filesystem instance */\n id?: string;\n /** GCS bucket name */\n bucket: string;\n /** Human-friendly display name for the UI */\n displayName?: string;\n /** Icon identifier for the UI (defaults to 'gcs') */\n icon?: FilesystemIcon;\n /** Description shown in tooltips */\n description?: string;\n /**\n * GCS project ID.\n * Required when using service account credentials.\n */\n projectId?: string;\n /**\n * Service account key JSON object or path to key file.\n * If not provided, uses Application Default Credentials (ADC).\n */\n credentials?: object | string;\n /** Optional prefix for all keys (acts like a subdirectory) */\n prefix?: string;\n /** Mount as read-only (blocks write operations, mounts read-only in sandboxes) */\n readOnly?: boolean;\n /**\n * Custom API endpoint URL.\n * Used for local development with emulators like fake-gcs-server.\n */\n endpoint?: string;\n}\n\n/**\n * GCS filesystem implementation.\n *\n * Stores files in a Google Cloud Storage bucket.\n * Supports mounting into E2B sandboxes via gcsfuse.\n *\n * @example Using Application Default Credentials\n * ```typescript\n * import { GCSFilesystem } from '@mastra/gcs';\n *\n * // Uses ADC (gcloud auth application-default login)\n * const fs = new GCSFilesystem({\n * bucket: 'my-bucket',\n * projectId: 'my-project',\n * });\n * ```\n *\n * @example Using Service Account Key\n * ```typescript\n * import { GCSFilesystem } from '@mastra/gcs';\n *\n * const fs = new GCSFilesystem({\n * bucket: 'my-bucket',\n * projectId: 'my-project',\n * credentials: {\n * type: 'service_account',\n * project_id: 'my-project',\n * private_key_id: '...',\n * private_key: '-----BEGIN PRIVATE KEY-----\\n...',\n * client_email: '...@...iam.gserviceaccount.com',\n * // ... rest of service account key\n * },\n * });\n * ```\n *\n * @example Using Key File Path\n * ```typescript\n * import { GCSFilesystem } from '@mastra/gcs';\n *\n * const fs = new GCSFilesystem({\n * bucket: 'my-bucket',\n * projectId: 'my-project',\n * credentials: '/path/to/service-account-key.json',\n * });\n * ```\n */\n\n/** Trim leading and trailing slashes without regex (avoids polynomial regex on user input). */\nfunction trimSlashes(s: string): string {\n let start = 0;\n let end = s.length;\n while (start < end && s[start] === '/') start++;\n while (end > start && s[end - 1] === '/') end--;\n return s.slice(start, end);\n}\n\nexport class GCSFilesystem extends MastraFilesystem {\n readonly id: string;\n readonly name = 'GCSFilesystem';\n readonly provider = 'gcs';\n readonly readOnly?: boolean;\n\n status: ProviderStatus = 'pending';\n\n // Display metadata for UI\n readonly displayName?: string;\n readonly icon: FilesystemIcon = 'gcs';\n readonly description?: string;\n\n private readonly bucketName: string;\n private readonly projectId?: string;\n private readonly credentials?: object | string;\n private readonly prefix: string;\n private readonly endpoint?: string;\n\n private _storage: Storage | null = null;\n private _bucket: Bucket | null = null;\n\n constructor(options: GCSFilesystemOptions) {\n super({ name: 'GCSFilesystem' });\n this.id = options.id ?? `gcs-fs-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n this.bucketName = options.bucket;\n this.projectId = options.projectId;\n this.credentials = options.credentials;\n // Trim leading/trailing slashes from prefix using iterative approach (avoids polynomial regex)\n this.prefix = options.prefix ? trimSlashes(options.prefix) + '/' : '';\n this.endpoint = options.endpoint;\n\n // Display metadata\n this.displayName = options.displayName ?? 'Google Cloud Storage';\n this.icon = options.icon ?? 'gcs';\n this.description = options.description;\n this.readOnly = options.readOnly;\n }\n\n /**\n * Get mount configuration for E2B sandbox.\n * Returns GCS-compatible config that works with gcsfuse.\n */\n getMountConfig(): GCSMountConfig {\n const config: GCSMountConfig = {\n type: 'gcs',\n bucket: this.bucketName,\n };\n\n // Include service account key if credentials are an object\n if (this.credentials && typeof this.credentials === 'object') {\n config.serviceAccountKey = JSON.stringify(this.credentials);\n }\n\n return config;\n }\n\n /**\n * Get filesystem info for status reporting.\n */\n getInfo(): FilesystemInfo {\n return {\n id: this.id,\n name: this.name,\n provider: this.provider,\n status: this.status,\n icon: this.icon,\n metadata: {\n bucket: this.bucketName,\n ...(this.endpoint && { endpoint: this.endpoint }),\n ...(this.prefix && { prefix: this.prefix }),\n },\n };\n }\n\n /**\n * Get instructions describing this GCS filesystem.\n * Used by agents to understand storage semantics.\n */\n getInstructions(): string {\n const access = this.readOnly ? 'Read-only' : 'Persistent';\n return `Google Cloud Storage in bucket \"${this.bucketName}\". ${access} storage - files are retained across sessions.`;\n }\n\n private getStorage(): Storage {\n if (this._storage) return this._storage;\n\n const options: { projectId?: string; credentials?: object; keyFilename?: string; apiEndpoint?: string } = {};\n\n if (this.projectId) {\n options.projectId = this.projectId;\n }\n\n if (this.credentials) {\n if (typeof this.credentials === 'string') {\n // Path to key file\n options.keyFilename = this.credentials;\n } else {\n // Credentials object\n options.credentials = this.credentials;\n }\n }\n\n if (this.endpoint) {\n options.apiEndpoint = this.endpoint;\n }\n\n this._storage = new Storage(options);\n return this._storage;\n }\n\n private getBucket(): Bucket {\n if (this._bucket) return this._bucket;\n\n const storage = this.getStorage();\n this._bucket = storage.bucket(this.bucketName);\n return this._bucket;\n }\n\n /**\n * Ensure the filesystem is initialized and return the bucket.\n * Uses base class ensureReady() for status management, then returns bucket.\n */\n private async getReadyBucket(): Promise<Bucket> {\n await this.ensureReady();\n return this.getBucket();\n }\n\n private toKey(path: string): string {\n // Remove leading slash and add prefix\n const cleanPath = path.replace(/^\\/+/, '');\n return this.prefix + cleanPath;\n }\n\n // ---------------------------------------------------------------------------\n // File Operations\n // ---------------------------------------------------------------------------\n\n async readFile(path: string, options?: ReadOptions): Promise<string | Buffer> {\n const bucket = await this.getReadyBucket();\n const file = bucket.file(this.toKey(path));\n\n try {\n const [content] = await file.download();\n\n if (options?.encoding) {\n return content.toString(options.encoding);\n }\n return content;\n } catch (error: unknown) {\n if (error && typeof error === 'object' && 'code' in error && error.code === 404) {\n throw new FileNotFoundError(path);\n }\n throw error;\n }\n }\n\n async writeFile(path: string, content: FileContent, _options?: WriteOptions): Promise<void> {\n const bucket = await this.getReadyBucket();\n const file = bucket.file(this.toKey(path));\n\n const body = typeof content === 'string' ? Buffer.from(content, 'utf-8') : Buffer.from(content);\n const contentType = getMimeType(path);\n\n await file.save(body, {\n contentType,\n resumable: false,\n });\n }\n\n async appendFile(path: string, content: FileContent): Promise<void> {\n // GCS doesn't support append, so read + write\n let existing = '';\n try {\n existing = (await this.readFile(path, { encoding: 'utf-8' })) as string;\n } catch (error) {\n if (error instanceof FileNotFoundError) {\n // File doesn't exist, start fresh\n } else {\n throw error;\n }\n }\n\n const appendContent = typeof content === 'string' ? content : Buffer.from(content).toString('utf-8');\n await this.writeFile(path, existing + appendContent);\n }\n\n async deleteFile(path: string, options?: RemoveOptions): Promise<void> {\n // Check if this is a directory - if so, use rmdir instead\n const isDir = await this.isDirectory(path);\n if (isDir) {\n await this.rmdir(path, { recursive: true, force: options?.force });\n return;\n }\n\n const bucket = await this.getReadyBucket();\n const file = bucket.file(this.toKey(path));\n\n try {\n await file.delete();\n } catch (error: unknown) {\n if (!options?.force) {\n if (error && typeof error === 'object' && 'code' in error && error.code === 404) {\n throw new FileNotFoundError(path);\n }\n throw error;\n }\n }\n }\n\n async copyFile(src: string, dest: string, _options?: CopyOptions): Promise<void> {\n const bucket = await this.getReadyBucket();\n const srcFile = bucket.file(this.toKey(src));\n const destFile = bucket.file(this.toKey(dest));\n\n try {\n await srcFile.copy(destFile);\n } catch (error: unknown) {\n if (error && typeof error === 'object' && 'code' in error && error.code === 404) {\n throw new FileNotFoundError(src);\n }\n throw error;\n }\n }\n\n async moveFile(src: string, dest: string, options?: CopyOptions): Promise<void> {\n await this.copyFile(src, dest, options);\n await this.deleteFile(src, { force: true });\n }\n\n // ---------------------------------------------------------------------------\n // Directory Operations\n // ---------------------------------------------------------------------------\n\n async mkdir(_path: string, _options?: { recursive?: boolean }): Promise<void> {\n // GCS doesn't have real directories - they're just key prefixes\n // No-op, directories are created implicitly when files are written\n }\n\n async rmdir(path: string, options?: RemoveOptions): Promise<void> {\n if (!options?.recursive) {\n // Quick emptiness check — only fetch one object instead of full readdir\n const bucket = await this.getReadyBucket();\n const prefix = this.toKey(path).replace(/\\/$/, '') + '/';\n const [files] = await bucket.getFiles({ prefix, maxResults: 1 });\n if (files.length > 0) {\n throw new Error(`Directory not empty: ${path}`);\n }\n return;\n }\n\n // Delete all objects with this prefix\n const bucket = await this.getReadyBucket();\n const prefix = this.toKey(path).replace(/\\/$/, '') + '/';\n\n await bucket.deleteFiles({ prefix });\n }\n\n async readdir(path: string, options?: ListOptions): Promise<FileEntry[]> {\n const bucket = await this.getReadyBucket();\n\n const prefix = this.toKey(path).replace(/\\/$/, '');\n const searchPrefix = prefix ? prefix + '/' : '';\n\n const entries: FileEntry[] = [];\n const seenDirs = new Set<string>();\n\n const [files] = await bucket.getFiles({\n prefix: searchPrefix,\n autoPaginate: true,\n });\n\n for (const file of files) {\n const key = file.name;\n if (!key || key === searchPrefix) continue;\n\n const relativePath = key.slice(searchPrefix.length);\n if (!relativePath) continue;\n\n // Skip if this looks like a directory marker\n if (relativePath.endsWith('/')) {\n const dirName = relativePath.slice(0, -1);\n if (!seenDirs.has(dirName)) {\n seenDirs.add(dirName);\n entries.push({ name: dirName, type: 'directory' });\n }\n continue;\n }\n\n const name = options?.recursive ? relativePath : relativePath.split('/')[0];\n\n // Skip if name is undefined or empty\n if (!name) continue;\n\n // For non-recursive listing, if there's a slash, it's a directory\n if (!options?.recursive && relativePath.includes('/')) {\n if (!seenDirs.has(name)) {\n seenDirs.add(name);\n entries.push({ name, type: 'directory' });\n }\n continue;\n }\n\n // Filter by extension if specified\n if (options?.extension) {\n const extensions = Array.isArray(options.extension) ? options.extension : [options.extension];\n if (!extensions.some(ext => name.endsWith(ext))) {\n continue;\n }\n }\n\n entries.push({\n name,\n type: 'file',\n size: file.metadata.size != null ? Number(file.metadata.size) : undefined,\n });\n }\n\n return entries;\n }\n\n // ---------------------------------------------------------------------------\n // Path Operations\n // ---------------------------------------------------------------------------\n\n async exists(path: string): Promise<boolean> {\n const key = this.toKey(path);\n\n // Root path always exists (it's the bucket itself)\n if (!key) return true;\n\n const bucket = await this.getReadyBucket();\n const file = bucket.file(key);\n\n // Check if it's a file\n const [exists] = await file.exists();\n if (exists) return true;\n\n // Check if it's a \"directory\" (has objects with this prefix)\n const [files] = await bucket.getFiles({\n prefix: key.replace(/\\/$/, '') + '/',\n maxResults: 1,\n });\n\n return files.length > 0;\n }\n\n async stat(path: string): Promise<FileStat> {\n const key = this.toKey(path);\n\n // Root path is always a directory\n if (!key) {\n return {\n name: '',\n path,\n type: 'directory',\n size: 0,\n createdAt: new Date(),\n modifiedAt: new Date(),\n };\n }\n\n const bucket = await this.getReadyBucket();\n const file = bucket.file(key);\n\n const [exists] = await file.exists();\n if (exists) {\n const [metadata] = await file.getMetadata();\n const name = path.split('/').pop() ?? '';\n\n return {\n name,\n path,\n type: 'file',\n size: Number(metadata.size) || 0,\n createdAt: metadata.timeCreated ? new Date(metadata.timeCreated) : new Date(),\n modifiedAt: metadata.updated ? new Date(metadata.updated) : new Date(),\n };\n }\n\n // Check if it's a directory\n const isDir = await this.isDirectory(path);\n if (isDir) {\n const name = path.split('/').filter(Boolean).pop() ?? '';\n return {\n name,\n path,\n type: 'directory',\n size: 0,\n createdAt: new Date(),\n modifiedAt: new Date(),\n };\n }\n\n throw new FileNotFoundError(path);\n }\n\n async isFile(path: string): Promise<boolean> {\n const key = this.toKey(path);\n if (!key) return false; // Root is a directory, not a file\n\n const bucket = await this.getReadyBucket();\n const file = bucket.file(key);\n\n const [exists] = await file.exists();\n return exists;\n }\n\n async isDirectory(path: string): Promise<boolean> {\n const key = this.toKey(path);\n if (!key) return true; // Root is always a directory\n\n const bucket = await this.getReadyBucket();\n\n const [files] = await bucket.getFiles({\n prefix: key.replace(/\\/$/, '') + '/',\n maxResults: 1,\n });\n\n return files.length > 0;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle (overrides base class protected methods)\n // ---------------------------------------------------------------------------\n\n /**\n * Initialize the GCS client.\n * Status management is handled by the base class.\n */\n async init(): Promise<void> {\n // Verify we can access the bucket\n const bucket = this.getBucket();\n try {\n const [exists] = await bucket.exists();\n if (!exists) {\n const err = new Error(`Bucket \"${this.bucketName}\" does not exist`) as Error & { status?: number };\n err.status = 404;\n throw err;\n }\n } catch (error) {\n // Check if error already has status (from our 404 throw above)\n if ((error as { status?: number }).status) {\n throw error;\n }\n // Extract status code from GCS errors and add to error for proper HTTP response\n const code = (error as { code?: number }).code;\n if (typeof code === 'number') {\n const message = error instanceof Error ? error.message : String(error);\n const err = new Error(\n message,\n // code === 403\n // ? `Access denied to bucket \"${this.bucketName}\" - check credentials and permissions`\n // : message,\n ) as Error & { status?: number };\n err.status = code;\n throw err;\n }\n throw error;\n }\n }\n\n /**\n * Clean up the GCS client.\n * Status management is handled by the base class.\n */\n async destroy(): Promise<void> {\n this._storage = null;\n this._bucket = null;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/filesystem/index.ts"],"names":["MastraFilesystem","Storage","FileNotFoundError","FileExistsError","bucket","prefix"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * GCS Filesystem Provider\n *\n * A filesystem implementation backed by Google Cloud Storage.\n */\n\nimport { Storage } from '@google-cloud/storage';\nimport type { Bucket } from '@google-cloud/storage';\n\nimport type {\n FileContent,\n FileStat,\n FileEntry,\n ReadOptions,\n WriteOptions,\n ListOptions,\n RemoveOptions,\n CopyOptions,\n FilesystemInfo,\n FilesystemMountConfig,\n FilesystemIcon,\n ProviderStatus,\n MastraFilesystemOptions,\n} from '@mastra/core/workspace';\nimport { MastraFilesystem, FileNotFoundError, FileExistsError } from '@mastra/core/workspace';\n\n/**\n * GCS mount configuration.\n * Returned by GCSFilesystem.getMountConfig() for FUSE mounting in sandboxes.\n */\nexport interface GCSMountConfig extends FilesystemMountConfig {\n type: 'gcs';\n /** GCS bucket name */\n bucket: string;\n /** Service account key JSON (optional - omit for public buckets or ADC) */\n serviceAccountKey?: string;\n}\n\n/**\n * Common MIME types by file extension.\n */\nconst MIME_TYPES: Record<string, string> = {\n // Text\n '.txt': 'text/plain',\n '.md': 'text/markdown',\n '.markdown': 'text/markdown',\n '.html': 'text/html',\n '.htm': 'text/html',\n '.css': 'text/css',\n '.csv': 'text/csv',\n '.xml': 'text/xml',\n // Code\n '.js': 'text/javascript',\n '.mjs': 'text/javascript',\n '.ts': 'text/typescript',\n '.tsx': 'text/typescript',\n '.jsx': 'text/javascript',\n '.json': 'application/json',\n '.yaml': 'text/yaml',\n '.yml': 'text/yaml',\n '.py': 'text/x-python',\n '.rb': 'text/x-ruby',\n '.sh': 'text/x-shellscript',\n '.bash': 'text/x-shellscript',\n // Images\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.svg': 'image/svg+xml',\n '.webp': 'image/webp',\n '.ico': 'image/x-icon',\n // Documents\n '.pdf': 'application/pdf',\n // Archives\n '.zip': 'application/zip',\n '.gz': 'application/gzip',\n '.tar': 'application/x-tar',\n};\n\n/**\n * Get MIME type from file path extension.\n */\nfunction getMimeType(path: string): string {\n const ext = path.toLowerCase().match(/\\.[^.]+$/)?.[0];\n return ext ? (MIME_TYPES[ext] ?? 'application/octet-stream') : 'application/octet-stream';\n}\n\n/**\n * GCS filesystem provider configuration.\n */\nexport interface GCSFilesystemOptions extends MastraFilesystemOptions {\n /** Unique identifier for this filesystem instance */\n id?: string;\n /** GCS bucket name */\n bucket: string;\n /** Human-friendly display name for the UI */\n displayName?: string;\n /** Icon identifier for the UI (defaults to 'gcs') */\n icon?: FilesystemIcon;\n /** Description shown in tooltips */\n description?: string;\n /**\n * GCS project ID.\n * Required when using service account credentials.\n */\n projectId?: string;\n /**\n * Service account key JSON object or path to key file.\n * If not provided, uses Application Default Credentials (ADC).\n */\n credentials?: object | string;\n /** Optional prefix for all keys (acts like a subdirectory) */\n prefix?: string;\n /** Mount as read-only (blocks write operations, mounts read-only in sandboxes) */\n readOnly?: boolean;\n /**\n * Custom API endpoint URL.\n * Used for local development with emulators like fake-gcs-server.\n */\n endpoint?: string;\n}\n\n/**\n * GCS filesystem implementation.\n *\n * Stores files in a Google Cloud Storage bucket.\n * Supports mounting into E2B sandboxes via gcsfuse.\n *\n * @example Using Application Default Credentials\n * ```typescript\n * import { GCSFilesystem } from '@mastra/gcs';\n *\n * // Uses ADC (gcloud auth application-default login)\n * const fs = new GCSFilesystem({\n * bucket: 'my-bucket',\n * projectId: 'my-project',\n * });\n * ```\n *\n * @example Using Service Account Key\n * ```typescript\n * import { GCSFilesystem } from '@mastra/gcs';\n *\n * const fs = new GCSFilesystem({\n * bucket: 'my-bucket',\n * projectId: 'my-project',\n * credentials: {\n * type: 'service_account',\n * project_id: 'my-project',\n * private_key_id: '...',\n * private_key: '-----BEGIN PRIVATE KEY-----\\n...',\n * client_email: '...@...iam.gserviceaccount.com',\n * // ... rest of service account key\n * },\n * });\n * ```\n *\n * @example Using Key File Path\n * ```typescript\n * import { GCSFilesystem } from '@mastra/gcs';\n *\n * const fs = new GCSFilesystem({\n * bucket: 'my-bucket',\n * projectId: 'my-project',\n * credentials: '/path/to/service-account-key.json',\n * });\n * ```\n */\n\n/** Trim leading and trailing slashes without regex (avoids polynomial regex on user input). */\nfunction trimSlashes(s: string): string {\n let start = 0;\n let end = s.length;\n while (start < end && s[start] === '/') start++;\n while (end > start && s[end - 1] === '/') end--;\n return s.slice(start, end);\n}\n\nexport class GCSFilesystem extends MastraFilesystem {\n readonly id: string;\n readonly name = 'GCSFilesystem';\n readonly provider = 'gcs';\n readonly readOnly?: boolean;\n\n status: ProviderStatus = 'pending';\n\n // Display metadata for UI\n readonly displayName?: string;\n readonly icon: FilesystemIcon = 'gcs';\n readonly description?: string;\n\n private readonly bucketName: string;\n private readonly projectId?: string;\n private readonly credentials?: object | string;\n private readonly prefix: string;\n private readonly endpoint?: string;\n\n private _storage: Storage | null = null;\n private _bucket: Bucket | null = null;\n\n constructor(options: GCSFilesystemOptions) {\n super({ ...options, name: 'GCSFilesystem' });\n this.id = options.id ?? `gcs-fs-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n this.bucketName = options.bucket;\n this.projectId = options.projectId;\n this.credentials = options.credentials;\n // Trim leading/trailing slashes from prefix using iterative approach (avoids polynomial regex)\n this.prefix = options.prefix ? trimSlashes(options.prefix) + '/' : '';\n this.endpoint = options.endpoint;\n\n // Display metadata\n this.displayName = options.displayName ?? 'Google Cloud Storage';\n this.icon = options.icon ?? 'gcs';\n this.description = options.description;\n this.readOnly = options.readOnly;\n }\n\n /**\n * Get mount configuration for E2B sandbox.\n * Returns GCS-compatible config that works with gcsfuse.\n */\n getMountConfig(): GCSMountConfig {\n const config: GCSMountConfig = {\n type: 'gcs',\n bucket: this.bucketName,\n };\n\n // Include service account key if credentials are an object\n if (this.credentials && typeof this.credentials === 'object') {\n config.serviceAccountKey = JSON.stringify(this.credentials);\n }\n\n return config;\n }\n\n /**\n * Get filesystem info for status reporting.\n */\n getInfo(): FilesystemInfo<{\n bucket: string;\n endpoint?: string;\n prefix?: string;\n }> {\n return {\n id: this.id,\n name: this.name,\n provider: this.provider,\n status: this.status,\n error: this.error,\n readOnly: this.readOnly,\n icon: this.icon,\n metadata: {\n bucket: this.bucketName,\n ...(this.endpoint && { endpoint: this.endpoint }),\n ...(this.prefix && { prefix: this.prefix }),\n },\n };\n }\n\n /**\n * Get instructions describing this GCS filesystem.\n * Used by agents to understand storage semantics.\n */\n getInstructions(): string {\n const access = this.readOnly ? 'Read-only' : 'Persistent';\n return `Google Cloud Storage in bucket \"${this.bucketName}\". ${access} storage - files are retained across sessions.`;\n }\n\n private getStorage(): Storage {\n if (this._storage) return this._storage;\n\n const options: { projectId?: string; credentials?: object; keyFilename?: string; apiEndpoint?: string } = {};\n\n if (this.projectId) {\n options.projectId = this.projectId;\n }\n\n if (this.credentials) {\n if (typeof this.credentials === 'string') {\n // Path to key file\n options.keyFilename = this.credentials;\n } else {\n // Credentials object\n options.credentials = this.credentials;\n }\n }\n\n if (this.endpoint) {\n options.apiEndpoint = this.endpoint;\n }\n\n this._storage = new Storage(options);\n return this._storage;\n }\n\n private getBucket(): Bucket {\n if (this._bucket) return this._bucket;\n\n const storage = this.getStorage();\n this._bucket = storage.bucket(this.bucketName);\n return this._bucket;\n }\n\n /**\n * Ensure the filesystem is initialized and return the bucket.\n * Uses base class ensureReady() for status management, then returns bucket.\n */\n private async getReadyBucket(): Promise<Bucket> {\n await this.ensureReady();\n return this.getBucket();\n }\n\n private toKey(path: string): string {\n // Remove leading slash and add prefix\n const cleanPath = path.replace(/^\\/+/, '');\n return this.prefix + cleanPath;\n }\n\n // ---------------------------------------------------------------------------\n // File Operations\n // ---------------------------------------------------------------------------\n\n async readFile(path: string, options?: ReadOptions): Promise<string | Buffer> {\n const bucket = await this.getReadyBucket();\n const file = bucket.file(this.toKey(path));\n\n try {\n const [content] = await file.download();\n\n if (options?.encoding) {\n return content.toString(options.encoding);\n }\n return content;\n } catch (error: unknown) {\n if (error && typeof error === 'object' && 'code' in error && error.code === 404) {\n throw new FileNotFoundError(path);\n }\n throw error;\n }\n }\n\n async writeFile(path: string, content: FileContent, options?: WriteOptions): Promise<void> {\n const bucket = await this.getReadyBucket();\n const file = bucket.file(this.toKey(path));\n\n if (options?.overwrite === false && (await this.exists(path))) {\n throw new FileExistsError(path);\n }\n\n const body = typeof content === 'string' ? Buffer.from(content, 'utf-8') : Buffer.from(content);\n const contentType = getMimeType(path);\n\n await file.save(body, {\n contentType,\n resumable: false,\n });\n }\n\n async appendFile(path: string, content: FileContent): Promise<void> {\n // GCS doesn't support append, so read + write\n let existing = '';\n try {\n existing = (await this.readFile(path, { encoding: 'utf-8' })) as string;\n } catch (error) {\n if (error instanceof FileNotFoundError) {\n // File doesn't exist, start fresh\n } else {\n throw error;\n }\n }\n\n const appendContent = typeof content === 'string' ? content : Buffer.from(content).toString('utf-8');\n await this.writeFile(path, existing + appendContent);\n }\n\n async deleteFile(path: string, options?: RemoveOptions): Promise<void> {\n // Check if this is a directory - if so, use rmdir instead\n const isDir = await this.isDirectory(path);\n if (isDir) {\n await this.rmdir(path, { recursive: true, force: options?.force });\n return;\n }\n\n const bucket = await this.getReadyBucket();\n const file = bucket.file(this.toKey(path));\n\n try {\n await file.delete();\n } catch (error: unknown) {\n if (!options?.force) {\n if (error && typeof error === 'object' && 'code' in error && error.code === 404) {\n throw new FileNotFoundError(path);\n }\n throw error;\n }\n }\n }\n\n async copyFile(src: string, dest: string, options?: CopyOptions): Promise<void> {\n const bucket = await this.getReadyBucket();\n const srcFile = bucket.file(this.toKey(src));\n const destFile = bucket.file(this.toKey(dest));\n\n if (options?.overwrite === false && (await this.exists(dest))) {\n throw new FileExistsError(dest);\n }\n\n try {\n await srcFile.copy(destFile);\n } catch (error: unknown) {\n if (error && typeof error === 'object' && 'code' in error && error.code === 404) {\n throw new FileNotFoundError(src);\n }\n throw error;\n }\n }\n\n async moveFile(src: string, dest: string, options?: CopyOptions): Promise<void> {\n await this.copyFile(src, dest, options);\n await this.deleteFile(src, { force: true });\n }\n\n // ---------------------------------------------------------------------------\n // Directory Operations\n // ---------------------------------------------------------------------------\n\n async mkdir(_path: string, _options?: { recursive?: boolean }): Promise<void> {\n // GCS doesn't have real directories - they're just key prefixes\n // No-op, directories are created implicitly when files are written\n }\n\n async rmdir(path: string, options?: RemoveOptions): Promise<void> {\n if (!options?.recursive) {\n // Quick emptiness check — only fetch one object instead of full readdir\n const bucket = await this.getReadyBucket();\n const prefix = this.toKey(path).replace(/\\/$/, '') + '/';\n const [files] = await bucket.getFiles({ prefix, maxResults: 1 });\n if (files.length > 0) {\n throw new Error(`Directory not empty: ${path}`);\n }\n return;\n }\n\n // Delete all objects with this prefix\n const bucket = await this.getReadyBucket();\n const prefix = this.toKey(path).replace(/\\/$/, '') + '/';\n\n await bucket.deleteFiles({ prefix });\n }\n\n async readdir(path: string, options?: ListOptions): Promise<FileEntry[]> {\n const bucket = await this.getReadyBucket();\n\n const prefix = this.toKey(path).replace(/\\/$/, '');\n const searchPrefix = prefix ? prefix + '/' : '';\n\n const entries: FileEntry[] = [];\n const seenDirs = new Set<string>();\n\n const [files] = await bucket.getFiles({\n prefix: searchPrefix,\n autoPaginate: true,\n });\n\n for (const file of files) {\n const key = file.name;\n if (!key || key === searchPrefix) continue;\n\n const relativePath = key.slice(searchPrefix.length);\n if (!relativePath) continue;\n\n // Skip if this looks like a directory marker\n if (relativePath.endsWith('/')) {\n const dirName = relativePath.slice(0, -1);\n if (!seenDirs.has(dirName)) {\n seenDirs.add(dirName);\n entries.push({ name: dirName, type: 'directory' });\n }\n continue;\n }\n\n const name = options?.recursive ? relativePath : relativePath.split('/')[0];\n\n // Skip if name is undefined or empty\n if (!name) continue;\n\n // For non-recursive listing, if there's a slash, it's a directory\n if (!options?.recursive && relativePath.includes('/')) {\n if (!seenDirs.has(name)) {\n seenDirs.add(name);\n entries.push({ name, type: 'directory' });\n }\n continue;\n }\n\n // Filter by extension if specified\n if (options?.extension) {\n const extensions = Array.isArray(options.extension) ? options.extension : [options.extension];\n if (!extensions.some(ext => name.endsWith(ext))) {\n continue;\n }\n }\n\n entries.push({\n name,\n type: 'file',\n size: file.metadata.size != null ? Number(file.metadata.size) : undefined,\n });\n }\n\n return entries;\n }\n\n // ---------------------------------------------------------------------------\n // Path Operations\n // ---------------------------------------------------------------------------\n\n async exists(path: string): Promise<boolean> {\n const key = this.toKey(path);\n\n // Root path always exists (it's the bucket itself)\n if (!key) return true;\n\n const bucket = await this.getReadyBucket();\n const file = bucket.file(key);\n\n // Check if it's a file\n const [exists] = await file.exists();\n if (exists) return true;\n\n // Check if it's a \"directory\" (has objects with this prefix)\n const [files] = await bucket.getFiles({\n prefix: key.replace(/\\/$/, '') + '/',\n maxResults: 1,\n });\n\n return files.length > 0;\n }\n\n async stat(path: string): Promise<FileStat> {\n const key = this.toKey(path);\n\n // Root path is always a directory\n if (!key) {\n return {\n name: '',\n path,\n type: 'directory',\n size: 0,\n createdAt: new Date(),\n modifiedAt: new Date(),\n };\n }\n\n const bucket = await this.getReadyBucket();\n const file = bucket.file(key);\n\n const [exists] = await file.exists();\n if (exists) {\n const [metadata] = await file.getMetadata();\n const name = path.split('/').pop() ?? '';\n\n return {\n name,\n path,\n type: 'file',\n size: Number(metadata.size) || 0,\n createdAt: metadata.timeCreated ? new Date(metadata.timeCreated) : new Date(),\n modifiedAt: metadata.updated ? new Date(metadata.updated) : new Date(),\n };\n }\n\n // Check if it's a directory\n const isDir = await this.isDirectory(path);\n if (isDir) {\n const name = path.split('/').filter(Boolean).pop() ?? '';\n return {\n name,\n path,\n type: 'directory',\n size: 0,\n createdAt: new Date(),\n modifiedAt: new Date(),\n };\n }\n\n throw new FileNotFoundError(path);\n }\n\n async isFile(path: string): Promise<boolean> {\n const key = this.toKey(path);\n if (!key) return false; // Root is a directory, not a file\n\n const bucket = await this.getReadyBucket();\n const file = bucket.file(key);\n\n const [exists] = await file.exists();\n return exists;\n }\n\n async isDirectory(path: string): Promise<boolean> {\n const key = this.toKey(path);\n if (!key) return true; // Root is always a directory\n\n const bucket = await this.getReadyBucket();\n\n const [files] = await bucket.getFiles({\n prefix: key.replace(/\\/$/, '') + '/',\n maxResults: 1,\n });\n\n return files.length > 0;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle (overrides base class protected methods)\n // ---------------------------------------------------------------------------\n\n /**\n * Initialize the GCS client.\n * Status management is handled by the base class.\n */\n async init(): Promise<void> {\n // Verify we can access the bucket\n const bucket = this.getBucket();\n try {\n const [exists] = await bucket.exists();\n if (!exists) {\n const err = new Error(`Bucket \"${this.bucketName}\" does not exist`) as Error & { status?: number };\n err.status = 404;\n throw err;\n }\n } catch (error) {\n // Check if error already has status (from our 404 throw above)\n if ((error as { status?: number }).status) {\n throw error;\n }\n // Extract status code from GCS errors and add to error for proper HTTP response\n const code = (error as { code?: number }).code;\n if (typeof code === 'number') {\n const message = error instanceof Error ? error.message : String(error);\n const err = new Error(\n message,\n // code === 403\n // ? `Access denied to bucket \"${this.bucketName}\" - check credentials and permissions`\n // : message,\n ) as Error & { status?: number };\n err.status = code;\n throw err;\n }\n throw error;\n }\n }\n\n /**\n * Clean up the GCS client.\n * Status management is handled by the base class.\n */\n async destroy(): Promise<void> {\n this._storage = null;\n this._bucket = null;\n }\n}\n"]}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Storage } from '@google-cloud/storage';
|
|
2
|
-
import { MastraFilesystem, FileNotFoundError } from '@mastra/core/workspace';
|
|
2
|
+
import { MastraFilesystem, FileNotFoundError, FileExistsError } from '@mastra/core/workspace';
|
|
3
3
|
|
|
4
4
|
// src/filesystem/index.ts
|
|
5
5
|
var MIME_TYPES = {
|
|
@@ -69,7 +69,7 @@ var GCSFilesystem = class extends MastraFilesystem {
|
|
|
69
69
|
_storage = null;
|
|
70
70
|
_bucket = null;
|
|
71
71
|
constructor(options) {
|
|
72
|
-
super({ name: "GCSFilesystem" });
|
|
72
|
+
super({ ...options, name: "GCSFilesystem" });
|
|
73
73
|
this.id = options.id ?? `gcs-fs-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
74
74
|
this.bucketName = options.bucket;
|
|
75
75
|
this.projectId = options.projectId;
|
|
@@ -104,6 +104,8 @@ var GCSFilesystem = class extends MastraFilesystem {
|
|
|
104
104
|
name: this.name,
|
|
105
105
|
provider: this.provider,
|
|
106
106
|
status: this.status,
|
|
107
|
+
error: this.error,
|
|
108
|
+
readOnly: this.readOnly,
|
|
107
109
|
icon: this.icon,
|
|
108
110
|
metadata: {
|
|
109
111
|
bucket: this.bucketName,
|
|
@@ -176,9 +178,12 @@ var GCSFilesystem = class extends MastraFilesystem {
|
|
|
176
178
|
throw error;
|
|
177
179
|
}
|
|
178
180
|
}
|
|
179
|
-
async writeFile(path, content,
|
|
181
|
+
async writeFile(path, content, options) {
|
|
180
182
|
const bucket = await this.getReadyBucket();
|
|
181
183
|
const file = bucket.file(this.toKey(path));
|
|
184
|
+
if (options?.overwrite === false && await this.exists(path)) {
|
|
185
|
+
throw new FileExistsError(path);
|
|
186
|
+
}
|
|
182
187
|
const body = typeof content === "string" ? Buffer.from(content, "utf-8") : Buffer.from(content);
|
|
183
188
|
const contentType = getMimeType(path);
|
|
184
189
|
await file.save(body, {
|
|
@@ -217,10 +222,13 @@ var GCSFilesystem = class extends MastraFilesystem {
|
|
|
217
222
|
}
|
|
218
223
|
}
|
|
219
224
|
}
|
|
220
|
-
async copyFile(src, dest,
|
|
225
|
+
async copyFile(src, dest, options) {
|
|
221
226
|
const bucket = await this.getReadyBucket();
|
|
222
227
|
const srcFile = bucket.file(this.toKey(src));
|
|
223
228
|
const destFile = bucket.file(this.toKey(dest));
|
|
229
|
+
if (options?.overwrite === false && await this.exists(dest)) {
|
|
230
|
+
throw new FileExistsError(dest);
|
|
231
|
+
}
|
|
224
232
|
try {
|
|
225
233
|
await srcFile.copy(destFile);
|
|
226
234
|
} catch (error) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/filesystem/index.ts"],"names":["bucket","prefix"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * GCS Filesystem Provider\n *\n * A filesystem implementation backed by Google Cloud Storage.\n */\n\nimport { Storage } from '@google-cloud/storage';\nimport type { Bucket } from '@google-cloud/storage';\n\nimport type {\n FileContent,\n FileStat,\n FileEntry,\n ReadOptions,\n WriteOptions,\n ListOptions,\n RemoveOptions,\n CopyOptions,\n FilesystemInfo,\n FilesystemMountConfig,\n FilesystemIcon,\n ProviderStatus,\n} from '@mastra/core/workspace';\nimport { MastraFilesystem, FileNotFoundError } from '@mastra/core/workspace';\n\n/**\n * GCS mount configuration.\n * Returned by GCSFilesystem.getMountConfig() for FUSE mounting in sandboxes.\n */\nexport interface GCSMountConfig extends FilesystemMountConfig {\n type: 'gcs';\n /** GCS bucket name */\n bucket: string;\n /** Service account key JSON (optional - omit for public buckets or ADC) */\n serviceAccountKey?: string;\n}\n\n/**\n * Common MIME types by file extension.\n */\nconst MIME_TYPES: Record<string, string> = {\n // Text\n '.txt': 'text/plain',\n '.md': 'text/markdown',\n '.markdown': 'text/markdown',\n '.html': 'text/html',\n '.htm': 'text/html',\n '.css': 'text/css',\n '.csv': 'text/csv',\n '.xml': 'text/xml',\n // Code\n '.js': 'text/javascript',\n '.mjs': 'text/javascript',\n '.ts': 'text/typescript',\n '.tsx': 'text/typescript',\n '.jsx': 'text/javascript',\n '.json': 'application/json',\n '.yaml': 'text/yaml',\n '.yml': 'text/yaml',\n '.py': 'text/x-python',\n '.rb': 'text/x-ruby',\n '.sh': 'text/x-shellscript',\n '.bash': 'text/x-shellscript',\n // Images\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.svg': 'image/svg+xml',\n '.webp': 'image/webp',\n '.ico': 'image/x-icon',\n // Documents\n '.pdf': 'application/pdf',\n // Archives\n '.zip': 'application/zip',\n '.gz': 'application/gzip',\n '.tar': 'application/x-tar',\n};\n\n/**\n * Get MIME type from file path extension.\n */\nfunction getMimeType(path: string): string {\n const ext = path.toLowerCase().match(/\\.[^.]+$/)?.[0];\n return ext ? (MIME_TYPES[ext] ?? 'application/octet-stream') : 'application/octet-stream';\n}\n\n/**\n * GCS filesystem provider configuration.\n */\nexport interface GCSFilesystemOptions {\n /** Unique identifier for this filesystem instance */\n id?: string;\n /** GCS bucket name */\n bucket: string;\n /** Human-friendly display name for the UI */\n displayName?: string;\n /** Icon identifier for the UI (defaults to 'gcs') */\n icon?: FilesystemIcon;\n /** Description shown in tooltips */\n description?: string;\n /**\n * GCS project ID.\n * Required when using service account credentials.\n */\n projectId?: string;\n /**\n * Service account key JSON object or path to key file.\n * If not provided, uses Application Default Credentials (ADC).\n */\n credentials?: object | string;\n /** Optional prefix for all keys (acts like a subdirectory) */\n prefix?: string;\n /** Mount as read-only (blocks write operations, mounts read-only in sandboxes) */\n readOnly?: boolean;\n /**\n * Custom API endpoint URL.\n * Used for local development with emulators like fake-gcs-server.\n */\n endpoint?: string;\n}\n\n/**\n * GCS filesystem implementation.\n *\n * Stores files in a Google Cloud Storage bucket.\n * Supports mounting into E2B sandboxes via gcsfuse.\n *\n * @example Using Application Default Credentials\n * ```typescript\n * import { GCSFilesystem } from '@mastra/gcs';\n *\n * // Uses ADC (gcloud auth application-default login)\n * const fs = new GCSFilesystem({\n * bucket: 'my-bucket',\n * projectId: 'my-project',\n * });\n * ```\n *\n * @example Using Service Account Key\n * ```typescript\n * import { GCSFilesystem } from '@mastra/gcs';\n *\n * const fs = new GCSFilesystem({\n * bucket: 'my-bucket',\n * projectId: 'my-project',\n * credentials: {\n * type: 'service_account',\n * project_id: 'my-project',\n * private_key_id: '...',\n * private_key: '-----BEGIN PRIVATE KEY-----\\n...',\n * client_email: '...@...iam.gserviceaccount.com',\n * // ... rest of service account key\n * },\n * });\n * ```\n *\n * @example Using Key File Path\n * ```typescript\n * import { GCSFilesystem } from '@mastra/gcs';\n *\n * const fs = new GCSFilesystem({\n * bucket: 'my-bucket',\n * projectId: 'my-project',\n * credentials: '/path/to/service-account-key.json',\n * });\n * ```\n */\n\n/** Trim leading and trailing slashes without regex (avoids polynomial regex on user input). */\nfunction trimSlashes(s: string): string {\n let start = 0;\n let end = s.length;\n while (start < end && s[start] === '/') start++;\n while (end > start && s[end - 1] === '/') end--;\n return s.slice(start, end);\n}\n\nexport class GCSFilesystem extends MastraFilesystem {\n readonly id: string;\n readonly name = 'GCSFilesystem';\n readonly provider = 'gcs';\n readonly readOnly?: boolean;\n\n status: ProviderStatus = 'pending';\n\n // Display metadata for UI\n readonly displayName?: string;\n readonly icon: FilesystemIcon = 'gcs';\n readonly description?: string;\n\n private readonly bucketName: string;\n private readonly projectId?: string;\n private readonly credentials?: object | string;\n private readonly prefix: string;\n private readonly endpoint?: string;\n\n private _storage: Storage | null = null;\n private _bucket: Bucket | null = null;\n\n constructor(options: GCSFilesystemOptions) {\n super({ name: 'GCSFilesystem' });\n this.id = options.id ?? `gcs-fs-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n this.bucketName = options.bucket;\n this.projectId = options.projectId;\n this.credentials = options.credentials;\n // Trim leading/trailing slashes from prefix using iterative approach (avoids polynomial regex)\n this.prefix = options.prefix ? trimSlashes(options.prefix) + '/' : '';\n this.endpoint = options.endpoint;\n\n // Display metadata\n this.displayName = options.displayName ?? 'Google Cloud Storage';\n this.icon = options.icon ?? 'gcs';\n this.description = options.description;\n this.readOnly = options.readOnly;\n }\n\n /**\n * Get mount configuration for E2B sandbox.\n * Returns GCS-compatible config that works with gcsfuse.\n */\n getMountConfig(): GCSMountConfig {\n const config: GCSMountConfig = {\n type: 'gcs',\n bucket: this.bucketName,\n };\n\n // Include service account key if credentials are an object\n if (this.credentials && typeof this.credentials === 'object') {\n config.serviceAccountKey = JSON.stringify(this.credentials);\n }\n\n return config;\n }\n\n /**\n * Get filesystem info for status reporting.\n */\n getInfo(): FilesystemInfo {\n return {\n id: this.id,\n name: this.name,\n provider: this.provider,\n status: this.status,\n icon: this.icon,\n metadata: {\n bucket: this.bucketName,\n ...(this.endpoint && { endpoint: this.endpoint }),\n ...(this.prefix && { prefix: this.prefix }),\n },\n };\n }\n\n /**\n * Get instructions describing this GCS filesystem.\n * Used by agents to understand storage semantics.\n */\n getInstructions(): string {\n const access = this.readOnly ? 'Read-only' : 'Persistent';\n return `Google Cloud Storage in bucket \"${this.bucketName}\". ${access} storage - files are retained across sessions.`;\n }\n\n private getStorage(): Storage {\n if (this._storage) return this._storage;\n\n const options: { projectId?: string; credentials?: object; keyFilename?: string; apiEndpoint?: string } = {};\n\n if (this.projectId) {\n options.projectId = this.projectId;\n }\n\n if (this.credentials) {\n if (typeof this.credentials === 'string') {\n // Path to key file\n options.keyFilename = this.credentials;\n } else {\n // Credentials object\n options.credentials = this.credentials;\n }\n }\n\n if (this.endpoint) {\n options.apiEndpoint = this.endpoint;\n }\n\n this._storage = new Storage(options);\n return this._storage;\n }\n\n private getBucket(): Bucket {\n if (this._bucket) return this._bucket;\n\n const storage = this.getStorage();\n this._bucket = storage.bucket(this.bucketName);\n return this._bucket;\n }\n\n /**\n * Ensure the filesystem is initialized and return the bucket.\n * Uses base class ensureReady() for status management, then returns bucket.\n */\n private async getReadyBucket(): Promise<Bucket> {\n await this.ensureReady();\n return this.getBucket();\n }\n\n private toKey(path: string): string {\n // Remove leading slash and add prefix\n const cleanPath = path.replace(/^\\/+/, '');\n return this.prefix + cleanPath;\n }\n\n // ---------------------------------------------------------------------------\n // File Operations\n // ---------------------------------------------------------------------------\n\n async readFile(path: string, options?: ReadOptions): Promise<string | Buffer> {\n const bucket = await this.getReadyBucket();\n const file = bucket.file(this.toKey(path));\n\n try {\n const [content] = await file.download();\n\n if (options?.encoding) {\n return content.toString(options.encoding);\n }\n return content;\n } catch (error: unknown) {\n if (error && typeof error === 'object' && 'code' in error && error.code === 404) {\n throw new FileNotFoundError(path);\n }\n throw error;\n }\n }\n\n async writeFile(path: string, content: FileContent, _options?: WriteOptions): Promise<void> {\n const bucket = await this.getReadyBucket();\n const file = bucket.file(this.toKey(path));\n\n const body = typeof content === 'string' ? Buffer.from(content, 'utf-8') : Buffer.from(content);\n const contentType = getMimeType(path);\n\n await file.save(body, {\n contentType,\n resumable: false,\n });\n }\n\n async appendFile(path: string, content: FileContent): Promise<void> {\n // GCS doesn't support append, so read + write\n let existing = '';\n try {\n existing = (await this.readFile(path, { encoding: 'utf-8' })) as string;\n } catch (error) {\n if (error instanceof FileNotFoundError) {\n // File doesn't exist, start fresh\n } else {\n throw error;\n }\n }\n\n const appendContent = typeof content === 'string' ? content : Buffer.from(content).toString('utf-8');\n await this.writeFile(path, existing + appendContent);\n }\n\n async deleteFile(path: string, options?: RemoveOptions): Promise<void> {\n // Check if this is a directory - if so, use rmdir instead\n const isDir = await this.isDirectory(path);\n if (isDir) {\n await this.rmdir(path, { recursive: true, force: options?.force });\n return;\n }\n\n const bucket = await this.getReadyBucket();\n const file = bucket.file(this.toKey(path));\n\n try {\n await file.delete();\n } catch (error: unknown) {\n if (!options?.force) {\n if (error && typeof error === 'object' && 'code' in error && error.code === 404) {\n throw new FileNotFoundError(path);\n }\n throw error;\n }\n }\n }\n\n async copyFile(src: string, dest: string, _options?: CopyOptions): Promise<void> {\n const bucket = await this.getReadyBucket();\n const srcFile = bucket.file(this.toKey(src));\n const destFile = bucket.file(this.toKey(dest));\n\n try {\n await srcFile.copy(destFile);\n } catch (error: unknown) {\n if (error && typeof error === 'object' && 'code' in error && error.code === 404) {\n throw new FileNotFoundError(src);\n }\n throw error;\n }\n }\n\n async moveFile(src: string, dest: string, options?: CopyOptions): Promise<void> {\n await this.copyFile(src, dest, options);\n await this.deleteFile(src, { force: true });\n }\n\n // ---------------------------------------------------------------------------\n // Directory Operations\n // ---------------------------------------------------------------------------\n\n async mkdir(_path: string, _options?: { recursive?: boolean }): Promise<void> {\n // GCS doesn't have real directories - they're just key prefixes\n // No-op, directories are created implicitly when files are written\n }\n\n async rmdir(path: string, options?: RemoveOptions): Promise<void> {\n if (!options?.recursive) {\n // Quick emptiness check — only fetch one object instead of full readdir\n const bucket = await this.getReadyBucket();\n const prefix = this.toKey(path).replace(/\\/$/, '') + '/';\n const [files] = await bucket.getFiles({ prefix, maxResults: 1 });\n if (files.length > 0) {\n throw new Error(`Directory not empty: ${path}`);\n }\n return;\n }\n\n // Delete all objects with this prefix\n const bucket = await this.getReadyBucket();\n const prefix = this.toKey(path).replace(/\\/$/, '') + '/';\n\n await bucket.deleteFiles({ prefix });\n }\n\n async readdir(path: string, options?: ListOptions): Promise<FileEntry[]> {\n const bucket = await this.getReadyBucket();\n\n const prefix = this.toKey(path).replace(/\\/$/, '');\n const searchPrefix = prefix ? prefix + '/' : '';\n\n const entries: FileEntry[] = [];\n const seenDirs = new Set<string>();\n\n const [files] = await bucket.getFiles({\n prefix: searchPrefix,\n autoPaginate: true,\n });\n\n for (const file of files) {\n const key = file.name;\n if (!key || key === searchPrefix) continue;\n\n const relativePath = key.slice(searchPrefix.length);\n if (!relativePath) continue;\n\n // Skip if this looks like a directory marker\n if (relativePath.endsWith('/')) {\n const dirName = relativePath.slice(0, -1);\n if (!seenDirs.has(dirName)) {\n seenDirs.add(dirName);\n entries.push({ name: dirName, type: 'directory' });\n }\n continue;\n }\n\n const name = options?.recursive ? relativePath : relativePath.split('/')[0];\n\n // Skip if name is undefined or empty\n if (!name) continue;\n\n // For non-recursive listing, if there's a slash, it's a directory\n if (!options?.recursive && relativePath.includes('/')) {\n if (!seenDirs.has(name)) {\n seenDirs.add(name);\n entries.push({ name, type: 'directory' });\n }\n continue;\n }\n\n // Filter by extension if specified\n if (options?.extension) {\n const extensions = Array.isArray(options.extension) ? options.extension : [options.extension];\n if (!extensions.some(ext => name.endsWith(ext))) {\n continue;\n }\n }\n\n entries.push({\n name,\n type: 'file',\n size: file.metadata.size != null ? Number(file.metadata.size) : undefined,\n });\n }\n\n return entries;\n }\n\n // ---------------------------------------------------------------------------\n // Path Operations\n // ---------------------------------------------------------------------------\n\n async exists(path: string): Promise<boolean> {\n const key = this.toKey(path);\n\n // Root path always exists (it's the bucket itself)\n if (!key) return true;\n\n const bucket = await this.getReadyBucket();\n const file = bucket.file(key);\n\n // Check if it's a file\n const [exists] = await file.exists();\n if (exists) return true;\n\n // Check if it's a \"directory\" (has objects with this prefix)\n const [files] = await bucket.getFiles({\n prefix: key.replace(/\\/$/, '') + '/',\n maxResults: 1,\n });\n\n return files.length > 0;\n }\n\n async stat(path: string): Promise<FileStat> {\n const key = this.toKey(path);\n\n // Root path is always a directory\n if (!key) {\n return {\n name: '',\n path,\n type: 'directory',\n size: 0,\n createdAt: new Date(),\n modifiedAt: new Date(),\n };\n }\n\n const bucket = await this.getReadyBucket();\n const file = bucket.file(key);\n\n const [exists] = await file.exists();\n if (exists) {\n const [metadata] = await file.getMetadata();\n const name = path.split('/').pop() ?? '';\n\n return {\n name,\n path,\n type: 'file',\n size: Number(metadata.size) || 0,\n createdAt: metadata.timeCreated ? new Date(metadata.timeCreated) : new Date(),\n modifiedAt: metadata.updated ? new Date(metadata.updated) : new Date(),\n };\n }\n\n // Check if it's a directory\n const isDir = await this.isDirectory(path);\n if (isDir) {\n const name = path.split('/').filter(Boolean).pop() ?? '';\n return {\n name,\n path,\n type: 'directory',\n size: 0,\n createdAt: new Date(),\n modifiedAt: new Date(),\n };\n }\n\n throw new FileNotFoundError(path);\n }\n\n async isFile(path: string): Promise<boolean> {\n const key = this.toKey(path);\n if (!key) return false; // Root is a directory, not a file\n\n const bucket = await this.getReadyBucket();\n const file = bucket.file(key);\n\n const [exists] = await file.exists();\n return exists;\n }\n\n async isDirectory(path: string): Promise<boolean> {\n const key = this.toKey(path);\n if (!key) return true; // Root is always a directory\n\n const bucket = await this.getReadyBucket();\n\n const [files] = await bucket.getFiles({\n prefix: key.replace(/\\/$/, '') + '/',\n maxResults: 1,\n });\n\n return files.length > 0;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle (overrides base class protected methods)\n // ---------------------------------------------------------------------------\n\n /**\n * Initialize the GCS client.\n * Status management is handled by the base class.\n */\n async init(): Promise<void> {\n // Verify we can access the bucket\n const bucket = this.getBucket();\n try {\n const [exists] = await bucket.exists();\n if (!exists) {\n const err = new Error(`Bucket \"${this.bucketName}\" does not exist`) as Error & { status?: number };\n err.status = 404;\n throw err;\n }\n } catch (error) {\n // Check if error already has status (from our 404 throw above)\n if ((error as { status?: number }).status) {\n throw error;\n }\n // Extract status code from GCS errors and add to error for proper HTTP response\n const code = (error as { code?: number }).code;\n if (typeof code === 'number') {\n const message = error instanceof Error ? error.message : String(error);\n const err = new Error(\n message,\n // code === 403\n // ? `Access denied to bucket \"${this.bucketName}\" - check credentials and permissions`\n // : message,\n ) as Error & { status?: number };\n err.status = code;\n throw err;\n }\n throw error;\n }\n }\n\n /**\n * Clean up the GCS client.\n * Status management is handled by the base class.\n */\n async destroy(): Promise<void> {\n this._storage = null;\n this._bucket = null;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/filesystem/index.ts"],"names":["bucket","prefix"],"mappings":";;;;AAyCA,IAAM,UAAA,GAAqC;AAAA;AAAA,EAEzC,MAAA,EAAQ,YAAA;AAAA,EACR,KAAA,EAAO,eAAA;AAAA,EACP,WAAA,EAAa,eAAA;AAAA,EACb,OAAA,EAAS,WAAA;AAAA,EACT,MAAA,EAAQ,WAAA;AAAA,EACR,MAAA,EAAQ,UAAA;AAAA,EACR,MAAA,EAAQ,UAAA;AAAA,EACR,MAAA,EAAQ,UAAA;AAAA;AAAA,EAER,KAAA,EAAO,iBAAA;AAAA,EACP,MAAA,EAAQ,iBAAA;AAAA,EACR,KAAA,EAAO,iBAAA;AAAA,EACP,MAAA,EAAQ,iBAAA;AAAA,EACR,MAAA,EAAQ,iBAAA;AAAA,EACR,OAAA,EAAS,kBAAA;AAAA,EACT,OAAA,EAAS,WAAA;AAAA,EACT,MAAA,EAAQ,WAAA;AAAA,EACR,KAAA,EAAO,eAAA;AAAA,EACP,KAAA,EAAO,aAAA;AAAA,EACP,KAAA,EAAO,oBAAA;AAAA,EACP,OAAA,EAAS,oBAAA;AAAA;AAAA,EAET,MAAA,EAAQ,WAAA;AAAA,EACR,MAAA,EAAQ,YAAA;AAAA,EACR,OAAA,EAAS,YAAA;AAAA,EACT,MAAA,EAAQ,WAAA;AAAA,EACR,MAAA,EAAQ,eAAA;AAAA,EACR,OAAA,EAAS,YAAA;AAAA,EACT,MAAA,EAAQ,cAAA;AAAA;AAAA,EAER,MAAA,EAAQ,iBAAA;AAAA;AAAA,EAER,MAAA,EAAQ,iBAAA;AAAA,EACR,KAAA,EAAO,kBAAA;AAAA,EACP,MAAA,EAAQ;AACV,CAAA;AAKA,SAAS,YAAY,IAAA,EAAsB;AACzC,EAAA,MAAM,MAAM,IAAA,CAAK,WAAA,GAAc,KAAA,CAAM,UAAU,IAAI,CAAC,CAAA;AACpD,EAAA,OAAO,GAAA,GAAO,UAAA,CAAW,GAAG,CAAA,IAAK,0BAAA,GAA8B,0BAAA;AACjE;AAqFA,SAAS,YAAY,CAAA,EAAmB;AACtC,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,IAAI,MAAM,CAAA,CAAE,MAAA;AACZ,EAAA,OAAO,KAAA,GAAQ,GAAA,IAAO,CAAA,CAAE,KAAK,MAAM,GAAA,EAAK,KAAA,EAAA;AACxC,EAAA,OAAO,MAAM,KAAA,IAAS,CAAA,CAAE,GAAA,GAAM,CAAC,MAAM,GAAA,EAAK,GAAA,EAAA;AAC1C,EAAA,OAAO,CAAA,CAAE,KAAA,CAAM,KAAA,EAAO,GAAG,CAAA;AAC3B;AAEO,IAAM,aAAA,GAAN,cAA4B,gBAAA,CAAiB;AAAA,EACzC,EAAA;AAAA,EACA,IAAA,GAAO,eAAA;AAAA,EACP,QAAA,GAAW,KAAA;AAAA,EACX,QAAA;AAAA,EAET,MAAA,GAAyB,SAAA;AAAA;AAAA,EAGhB,WAAA;AAAA,EACA,IAAA,GAAuB,KAAA;AAAA,EACvB,WAAA;AAAA,EAEQ,UAAA;AAAA,EACA,SAAA;AAAA,EACA,WAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA;AAAA,EAET,QAAA,GAA2B,IAAA;AAAA,EAC3B,OAAA,GAAyB,IAAA;AAAA,EAEjC,YAAY,OAAA,EAA+B;AACzC,IAAA,KAAA,CAAM,EAAE,GAAG,OAAA,EAAS,IAAA,EAAM,iBAAiB,CAAA;AAC3C,IAAA,IAAA,CAAK,EAAA,GAAK,QAAQ,EAAA,IAAM,CAAA,OAAA,EAAU,KAAK,GAAA,EAAI,CAAE,SAAS,EAAE,CAAC,IAAI,IAAA,CAAK,MAAA,GAAS,QAAA,CAAS,EAAE,EAAE,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,CAAA;AACnG,IAAA,IAAA,CAAK,aAAa,OAAA,CAAQ,MAAA;AAC1B,IAAA,IAAA,CAAK,YAAY,OAAA,CAAQ,SAAA;AACzB,IAAA,IAAA,CAAK,cAAc,OAAA,CAAQ,WAAA;AAE3B,IAAA,IAAA,CAAK,SAAS,OAAA,CAAQ,MAAA,GAAS,YAAY,OAAA,CAAQ,MAAM,IAAI,GAAA,GAAM,EAAA;AACnE,IAAA,IAAA,CAAK,WAAW,OAAA,CAAQ,QAAA;AAGxB,IAAA,IAAA,CAAK,WAAA,GAAc,QAAQ,WAAA,IAAe,sBAAA;AAC1C,IAAA,IAAA,CAAK,IAAA,GAAO,QAAQ,IAAA,IAAQ,KAAA;AAC5B,IAAA,IAAA,CAAK,cAAc,OAAA,CAAQ,WAAA;AAC3B,IAAA,IAAA,CAAK,WAAW,OAAA,CAAQ,QAAA;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAA,GAAiC;AAC/B,IAAA,MAAM,MAAA,GAAyB;AAAA,MAC7B,IAAA,EAAM,KAAA;AAAA,MACN,QAAQ,IAAA,CAAK;AAAA,KACf;AAGA,IAAA,IAAI,IAAA,CAAK,WAAA,IAAe,OAAO,IAAA,CAAK,gBAAgB,QAAA,EAAU;AAC5D,MAAA,MAAA,CAAO,iBAAA,GAAoB,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,WAAW,CAAA;AAAA,IAC5D;AAEA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAA,GAIG;AACD,IAAA,OAAO;AAAA,MACL,IAAI,IAAA,CAAK,EAAA;AAAA,MACT,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,QAAA,EAAU;AAAA,QACR,QAAQ,IAAA,CAAK,UAAA;AAAA,QACb,GAAI,IAAA,CAAK,QAAA,IAAY,EAAE,QAAA,EAAU,KAAK,QAAA,EAAS;AAAA,QAC/C,GAAI,IAAA,CAAK,MAAA,IAAU,EAAE,MAAA,EAAQ,KAAK,MAAA;AAAO;AAC3C,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAA,GAA0B;AACxB,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,QAAA,GAAW,WAAA,GAAc,YAAA;AAC7C,IAAA,OAAO,CAAA,gCAAA,EAAmC,IAAA,CAAK,UAAU,CAAA,GAAA,EAAM,MAAM,CAAA,8CAAA,CAAA;AAAA,EACvE;AAAA,EAEQ,UAAA,GAAsB;AAC5B,IAAA,IAAI,IAAA,CAAK,QAAA,EAAU,OAAO,IAAA,CAAK,QAAA;AAE/B,IAAA,MAAM,UAAoG,EAAC;AAE3G,IAAA,IAAI,KAAK,SAAA,EAAW;AAClB,MAAA,OAAA,CAAQ,YAAY,IAAA,CAAK,SAAA;AAAA,IAC3B;AAEA,IAAA,IAAI,KAAK,WAAA,EAAa;AACpB,MAAA,IAAI,OAAO,IAAA,CAAK,WAAA,KAAgB,QAAA,EAAU;AAExC,QAAA,OAAA,CAAQ,cAAc,IAAA,CAAK,WAAA;AAAA,MAC7B,CAAA,MAAO;AAEL,QAAA,OAAA,CAAQ,cAAc,IAAA,CAAK,WAAA;AAAA,MAC7B;AAAA,IACF;AAEA,IAAA,IAAI,KAAK,QAAA,EAAU;AACjB,MAAA,OAAA,CAAQ,cAAc,IAAA,CAAK,QAAA;AAAA,IAC7B;AAEA,IAAA,IAAA,CAAK,QAAA,GAAW,IAAI,OAAA,CAAQ,OAAO,CAAA;AACnC,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,EACd;AAAA,EAEQ,SAAA,GAAoB;AAC1B,IAAA,IAAI,IAAA,CAAK,OAAA,EAAS,OAAO,IAAA,CAAK,OAAA;AAE9B,IAAA,MAAM,OAAA,GAAU,KAAK,UAAA,EAAW;AAChC,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA,CAAQ,MAAA,CAAO,IAAA,CAAK,UAAU,CAAA;AAC7C,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,cAAA,GAAkC;AAC9C,IAAA,MAAM,KAAK,WAAA,EAAY;AACvB,IAAA,OAAO,KAAK,SAAA,EAAU;AAAA,EACxB;AAAA,EAEQ,MAAM,IAAA,EAAsB;AAElC,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA;AACzC,IAAA,OAAO,KAAK,MAAA,GAAS,SAAA;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,QAAA,CAAS,IAAA,EAAc,OAAA,EAAiD;AAC5E,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,cAAA,EAAe;AACzC,IAAA,MAAM,OAAO,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,KAAA,CAAM,IAAI,CAAC,CAAA;AAEzC,IAAA,IAAI;AACF,MAAA,MAAM,CAAC,OAAO,CAAA,GAAI,MAAM,KAAK,QAAA,EAAS;AAEtC,MAAA,IAAI,SAAS,QAAA,EAAU;AACrB,QAAA,OAAO,OAAA,CAAQ,QAAA,CAAS,OAAA,CAAQ,QAAQ,CAAA;AAAA,MAC1C;AACA,MAAA,OAAO,OAAA;AAAA,IACT,SAAS,KAAA,EAAgB;AACvB,MAAA,IAAI,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,IAAY,UAAU,KAAA,IAAS,KAAA,CAAM,SAAS,GAAA,EAAK;AAC/E,QAAA,MAAM,IAAI,kBAAkB,IAAI,CAAA;AAAA,MAClC;AACA,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,SAAA,CAAU,IAAA,EAAc,OAAA,EAAsB,OAAA,EAAuC;AACzF,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,cAAA,EAAe;AACzC,IAAA,MAAM,OAAO,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,KAAA,CAAM,IAAI,CAAC,CAAA;AAEzC,IAAA,IAAI,SAAS,SAAA,KAAc,KAAA,IAAU,MAAM,IAAA,CAAK,MAAA,CAAO,IAAI,CAAA,EAAI;AAC7D,MAAA,MAAM,IAAI,gBAAgB,IAAI,CAAA;AAAA,IAChC;AAEA,IAAA,MAAM,IAAA,GAAO,OAAO,OAAA,KAAY,QAAA,GAAW,MAAA,CAAO,IAAA,CAAK,OAAA,EAAS,OAAO,CAAA,GAAI,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA;AAC9F,IAAA,MAAM,WAAA,GAAc,YAAY,IAAI,CAAA;AAEpC,IAAA,MAAM,IAAA,CAAK,KAAK,IAAA,EAAM;AAAA,MACpB,WAAA;AAAA,MACA,SAAA,EAAW;AAAA,KACZ,CAAA;AAAA,EACH;AAAA,EAEA,MAAM,UAAA,CAAW,IAAA,EAAc,OAAA,EAAqC;AAElE,IAAA,IAAI,QAAA,GAAW,EAAA;AACf,IAAA,IAAI;AACF,MAAA,QAAA,GAAY,MAAM,IAAA,CAAK,QAAA,CAAS,MAAM,EAAE,QAAA,EAAU,SAAS,CAAA;AAAA,IAC7D,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,iBAAiB,iBAAA,EAAmB,CAExC,MAAO;AACL,QAAA,MAAM,KAAA;AAAA,MACR;AAAA,IACF;AAEA,IAAA,MAAM,aAAA,GAAgB,OAAO,OAAA,KAAY,QAAA,GAAW,OAAA,GAAU,OAAO,IAAA,CAAK,OAAO,CAAA,CAAE,QAAA,CAAS,OAAO,CAAA;AACnG,IAAA,MAAM,IAAA,CAAK,SAAA,CAAU,IAAA,EAAM,QAAA,GAAW,aAAa,CAAA;AAAA,EACrD;AAAA,EAEA,MAAM,UAAA,CAAW,IAAA,EAAc,OAAA,EAAwC;AAErE,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,WAAA,CAAY,IAAI,CAAA;AACzC,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,MAAM,IAAA,CAAK,MAAM,IAAA,EAAM,EAAE,WAAW,IAAA,EAAM,KAAA,EAAO,OAAA,EAAS,KAAA,EAAO,CAAA;AACjE,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,cAAA,EAAe;AACzC,IAAA,MAAM,OAAO,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,KAAA,CAAM,IAAI,CAAC,CAAA;AAEzC,IAAA,IAAI;AACF,MAAA,MAAM,KAAK,MAAA,EAAO;AAAA,IACpB,SAAS,KAAA,EAAgB;AACvB,MAAA,IAAI,CAAC,SAAS,KAAA,EAAO;AACnB,QAAA,IAAI,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,IAAY,UAAU,KAAA,IAAS,KAAA,CAAM,SAAS,GAAA,EAAK;AAC/E,UAAA,MAAM,IAAI,kBAAkB,IAAI,CAAA;AAAA,QAClC;AACA,QAAA,MAAM,KAAA;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,QAAA,CAAS,GAAA,EAAa,IAAA,EAAc,OAAA,EAAsC;AAC9E,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,cAAA,EAAe;AACzC,IAAA,MAAM,UAAU,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,KAAA,CAAM,GAAG,CAAC,CAAA;AAC3C,IAAA,MAAM,WAAW,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,KAAA,CAAM,IAAI,CAAC,CAAA;AAE7C,IAAA,IAAI,SAAS,SAAA,KAAc,KAAA,IAAU,MAAM,IAAA,CAAK,MAAA,CAAO,IAAI,CAAA,EAAI;AAC7D,MAAA,MAAM,IAAI,gBAAgB,IAAI,CAAA;AAAA,IAChC;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,CAAQ,KAAK,QAAQ,CAAA;AAAA,IAC7B,SAAS,KAAA,EAAgB;AACvB,MAAA,IAAI,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,IAAY,UAAU,KAAA,IAAS,KAAA,CAAM,SAAS,GAAA,EAAK;AAC/E,QAAA,MAAM,IAAI,kBAAkB,GAAG,CAAA;AAAA,MACjC;AACA,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,QAAA,CAAS,GAAA,EAAa,IAAA,EAAc,OAAA,EAAsC;AAC9E,IAAA,MAAM,IAAA,CAAK,QAAA,CAAS,GAAA,EAAK,IAAA,EAAM,OAAO,CAAA;AACtC,IAAA,MAAM,KAAK,UAAA,CAAW,GAAA,EAAK,EAAE,KAAA,EAAO,MAAM,CAAA;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,KAAA,CAAM,KAAA,EAAe,QAAA,EAAmD;AAAA,EAG9E;AAAA,EAEA,MAAM,KAAA,CAAM,IAAA,EAAc,OAAA,EAAwC;AAChE,IAAA,IAAI,CAAC,SAAS,SAAA,EAAW;AAEvB,MAAA,MAAMA,OAAAA,GAAS,MAAM,IAAA,CAAK,cAAA,EAAe;AACzC,MAAA,MAAMC,OAAAA,GAAS,KAAK,KAAA,CAAM,IAAI,EAAE,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA,GAAI,GAAA;AACrD,MAAA,MAAM,CAAC,KAAK,CAAA,GAAI,MAAMD,OAAAA,CAAO,QAAA,CAAS,EAAE,MAAA,EAAAC,OAAAA,EAAQ,UAAA,EAAY,CAAA,EAAG,CAAA;AAC/D,MAAA,IAAI,KAAA,CAAM,SAAS,CAAA,EAAG;AACpB,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,qBAAA,EAAwB,IAAI,CAAA,CAAE,CAAA;AAAA,MAChD;AACA,MAAA;AAAA,IACF;AAGA,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,cAAA,EAAe;AACzC,IAAA,MAAM,MAAA,GAAS,KAAK,KAAA,CAAM,IAAI,EAAE,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA,GAAI,GAAA;AAErD,IAAA,MAAM,MAAA,CAAO,WAAA,CAAY,EAAE,MAAA,EAAQ,CAAA;AAAA,EACrC;AAAA,EAEA,MAAM,OAAA,CAAQ,IAAA,EAAc,OAAA,EAA6C;AACvE,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,cAAA,EAAe;AAEzC,IAAA,MAAM,SAAS,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,CAAE,OAAA,CAAQ,OAAO,EAAE,CAAA;AACjD,IAAA,MAAM,YAAA,GAAe,MAAA,GAAS,MAAA,GAAS,GAAA,GAAM,EAAA;AAE7C,IAAA,MAAM,UAAuB,EAAC;AAC9B,IAAA,MAAM,QAAA,uBAAe,GAAA,EAAY;AAEjC,IAAA,MAAM,CAAC,KAAK,CAAA,GAAI,MAAM,OAAO,QAAA,CAAS;AAAA,MACpC,MAAA,EAAQ,YAAA;AAAA,MACR,YAAA,EAAc;AAAA,KACf,CAAA;AAED,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,MAAA,MAAM,MAAM,IAAA,CAAK,IAAA;AACjB,MAAA,IAAI,CAAC,GAAA,IAAO,GAAA,KAAQ,YAAA,EAAc;AAElC,MAAA,MAAM,YAAA,GAAe,GAAA,CAAI,KAAA,CAAM,YAAA,CAAa,MAAM,CAAA;AAClD,MAAA,IAAI,CAAC,YAAA,EAAc;AAGnB,MAAA,IAAI,YAAA,CAAa,QAAA,CAAS,GAAG,CAAA,EAAG;AAC9B,QAAA,MAAM,OAAA,GAAU,YAAA,CAAa,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AACxC,QAAA,IAAI,CAAC,QAAA,CAAS,GAAA,CAAI,OAAO,CAAA,EAAG;AAC1B,UAAA,QAAA,CAAS,IAAI,OAAO,CAAA;AACpB,UAAA,OAAA,CAAQ,KAAK,EAAE,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,aAAa,CAAA;AAAA,QACnD;AACA,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,IAAA,GAAO,SAAS,SAAA,GAAY,YAAA,GAAe,aAAa,KAAA,CAAM,GAAG,EAAE,CAAC,CAAA;AAG1E,MAAA,IAAI,CAAC,IAAA,EAAM;AAGX,MAAA,IAAI,CAAC,OAAA,EAAS,SAAA,IAAa,YAAA,CAAa,QAAA,CAAS,GAAG,CAAA,EAAG;AACrD,QAAA,IAAI,CAAC,QAAA,CAAS,GAAA,CAAI,IAAI,CAAA,EAAG;AACvB,UAAA,QAAA,CAAS,IAAI,IAAI,CAAA;AACjB,UAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,IAAA,EAAM,IAAA,EAAM,aAAa,CAAA;AAAA,QAC1C;AACA,QAAA;AAAA,MACF;AAGA,MAAA,IAAI,SAAS,SAAA,EAAW;AACtB,QAAA,MAAM,UAAA,GAAa,KAAA,CAAM,OAAA,CAAQ,OAAA,CAAQ,SAAS,IAAI,OAAA,CAAQ,SAAA,GAAY,CAAC,OAAA,CAAQ,SAAS,CAAA;AAC5F,QAAA,IAAI,CAAC,WAAW,IAAA,CAAK,CAAA,GAAA,KAAO,KAAK,QAAA,CAAS,GAAG,CAAC,CAAA,EAAG;AAC/C,UAAA;AAAA,QACF;AAAA,MACF;AAEA,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,IAAA;AAAA,QACA,IAAA,EAAM,MAAA;AAAA,QACN,IAAA,EAAM,KAAK,QAAA,CAAS,IAAA,IAAQ,OAAO,MAAA,CAAO,IAAA,CAAK,QAAA,CAAS,IAAI,CAAA,GAAI;AAAA,OACjE,CAAA;AAAA,IACH;AAEA,IAAA,OAAO,OAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,OAAO,IAAA,EAAgC;AAC3C,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAG3B,IAAA,IAAI,CAAC,KAAK,OAAO,IAAA;AAEjB,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,cAAA,EAAe;AACzC,IAAA,MAAM,IAAA,GAAO,MAAA,CAAO,IAAA,CAAK,GAAG,CAAA;AAG5B,IAAA,MAAM,CAAC,MAAM,CAAA,GAAI,MAAM,KAAK,MAAA,EAAO;AACnC,IAAA,IAAI,QAAQ,OAAO,IAAA;AAGnB,IAAA,MAAM,CAAC,KAAK,CAAA,GAAI,MAAM,OAAO,QAAA,CAAS;AAAA,MACpC,MAAA,EAAQ,GAAA,CAAI,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA,GAAI,GAAA;AAAA,MACjC,UAAA,EAAY;AAAA,KACb,CAAA;AAED,IAAA,OAAO,MAAM,MAAA,GAAS,CAAA;AAAA,EACxB;AAAA,EAEA,MAAM,KAAK,IAAA,EAAiC;AAC1C,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAG3B,IAAA,IAAI,CAAC,GAAA,EAAK;AACR,MAAA,OAAO;AAAA,QACL,IAAA,EAAM,EAAA;AAAA,QACN,IAAA;AAAA,QACA,IAAA,EAAM,WAAA;AAAA,QACN,IAAA,EAAM,CAAA;AAAA,QACN,SAAA,sBAAe,IAAA,EAAK;AAAA,QACpB,UAAA,sBAAgB,IAAA;AAAK,OACvB;AAAA,IACF;AAEA,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,cAAA,EAAe;AACzC,IAAA,MAAM,IAAA,GAAO,MAAA,CAAO,IAAA,CAAK,GAAG,CAAA;AAE5B,IAAA,MAAM,CAAC,MAAM,CAAA,GAAI,MAAM,KAAK,MAAA,EAAO;AACnC,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,MAAM,CAAC,QAAQ,CAAA,GAAI,MAAM,KAAK,WAAA,EAAY;AAC1C,MAAA,MAAM,OAAO,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA,CAAE,KAAI,IAAK,EAAA;AAEtC,MAAA,OAAO;AAAA,QACL,IAAA;AAAA,QACA,IAAA;AAAA,QACA,IAAA,EAAM,MAAA;AAAA,QACN,IAAA,EAAM,MAAA,CAAO,QAAA,CAAS,IAAI,CAAA,IAAK,CAAA;AAAA,QAC/B,SAAA,EAAW,SAAS,WAAA,GAAc,IAAI,KAAK,QAAA,CAAS,WAAW,CAAA,mBAAI,IAAI,IAAA,EAAK;AAAA,QAC5E,UAAA,EAAY,SAAS,OAAA,GAAU,IAAI,KAAK,QAAA,CAAS,OAAO,CAAA,mBAAI,IAAI,IAAA;AAAK,OACvE;AAAA,IACF;AAGA,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,WAAA,CAAY,IAAI,CAAA;AACzC,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,MAAM,IAAA,GAAO,KAAK,KAAA,CAAM,GAAG,EAAE,MAAA,CAAO,OAAO,CAAA,CAAE,GAAA,EAAI,IAAK,EAAA;AACtD,MAAA,OAAO;AAAA,QACL,IAAA;AAAA,QACA,IAAA;AAAA,QACA,IAAA,EAAM,WAAA;AAAA,QACN,IAAA,EAAM,CAAA;AAAA,QACN,SAAA,sBAAe,IAAA,EAAK;AAAA,QACpB,UAAA,sBAAgB,IAAA;AAAK,OACvB;AAAA,IACF;AAEA,IAAA,MAAM,IAAI,kBAAkB,IAAI,CAAA;AAAA,EAClC;AAAA,EAEA,MAAM,OAAO,IAAA,EAAgC;AAC3C,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAC3B,IAAA,IAAI,CAAC,KAAK,OAAO,KAAA;AAEjB,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,cAAA,EAAe;AACzC,IAAA,MAAM,IAAA,GAAO,MAAA,CAAO,IAAA,CAAK,GAAG,CAAA;AAE5B,IAAA,MAAM,CAAC,MAAM,CAAA,GAAI,MAAM,KAAK,MAAA,EAAO;AACnC,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEA,MAAM,YAAY,IAAA,EAAgC;AAChD,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAC3B,IAAA,IAAI,CAAC,KAAK,OAAO,IAAA;AAEjB,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,cAAA,EAAe;AAEzC,IAAA,MAAM,CAAC,KAAK,CAAA,GAAI,MAAM,OAAO,QAAA,CAAS;AAAA,MACpC,MAAA,EAAQ,GAAA,CAAI,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA,GAAI,GAAA;AAAA,MACjC,UAAA,EAAY;AAAA,KACb,CAAA;AAED,IAAA,OAAO,MAAM,MAAA,GAAS,CAAA;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,IAAA,GAAsB;AAE1B,IAAA,MAAM,MAAA,GAAS,KAAK,SAAA,EAAU;AAC9B,IAAA,IAAI;AACF,MAAA,MAAM,CAAC,MAAM,CAAA,GAAI,MAAM,OAAO,MAAA,EAAO;AACrC,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,MAAM,MAAM,IAAI,KAAA,CAAM,CAAA,QAAA,EAAW,IAAA,CAAK,UAAU,CAAA,gBAAA,CAAkB,CAAA;AAClE,QAAA,GAAA,CAAI,MAAA,GAAS,GAAA;AACb,QAAA,MAAM,GAAA;AAAA,MACR;AAAA,IACF,SAAS,KAAA,EAAO;AAEd,MAAA,IAAK,MAA8B,MAAA,EAAQ;AACzC,QAAA,MAAM,KAAA;AAAA,MACR;AAEA,MAAA,MAAM,OAAQ,KAAA,CAA4B,IAAA;AAC1C,MAAA,IAAI,OAAO,SAAS,QAAA,EAAU;AAC5B,QAAA,MAAM,UAAU,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AACrE,QAAA,MAAM,MAAM,IAAI,KAAA;AAAA,UACd;AAAA;AAAA;AAAA;AAAA,SAIF;AACA,QAAA,GAAA,CAAI,MAAA,GAAS,IAAA;AACb,QAAA,MAAM,GAAA;AAAA,MACR;AACA,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,OAAA,GAAyB;AAC7B,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAChB,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AAAA,EACjB;AACF","file":"index.js","sourcesContent":["/**\n * GCS Filesystem Provider\n *\n * A filesystem implementation backed by Google Cloud Storage.\n */\n\nimport { Storage } from '@google-cloud/storage';\nimport type { Bucket } from '@google-cloud/storage';\n\nimport type {\n FileContent,\n FileStat,\n FileEntry,\n ReadOptions,\n WriteOptions,\n ListOptions,\n RemoveOptions,\n CopyOptions,\n FilesystemInfo,\n FilesystemMountConfig,\n FilesystemIcon,\n ProviderStatus,\n MastraFilesystemOptions,\n} from '@mastra/core/workspace';\nimport { MastraFilesystem, FileNotFoundError, FileExistsError } from '@mastra/core/workspace';\n\n/**\n * GCS mount configuration.\n * Returned by GCSFilesystem.getMountConfig() for FUSE mounting in sandboxes.\n */\nexport interface GCSMountConfig extends FilesystemMountConfig {\n type: 'gcs';\n /** GCS bucket name */\n bucket: string;\n /** Service account key JSON (optional - omit for public buckets or ADC) */\n serviceAccountKey?: string;\n}\n\n/**\n * Common MIME types by file extension.\n */\nconst MIME_TYPES: Record<string, string> = {\n // Text\n '.txt': 'text/plain',\n '.md': 'text/markdown',\n '.markdown': 'text/markdown',\n '.html': 'text/html',\n '.htm': 'text/html',\n '.css': 'text/css',\n '.csv': 'text/csv',\n '.xml': 'text/xml',\n // Code\n '.js': 'text/javascript',\n '.mjs': 'text/javascript',\n '.ts': 'text/typescript',\n '.tsx': 'text/typescript',\n '.jsx': 'text/javascript',\n '.json': 'application/json',\n '.yaml': 'text/yaml',\n '.yml': 'text/yaml',\n '.py': 'text/x-python',\n '.rb': 'text/x-ruby',\n '.sh': 'text/x-shellscript',\n '.bash': 'text/x-shellscript',\n // Images\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.svg': 'image/svg+xml',\n '.webp': 'image/webp',\n '.ico': 'image/x-icon',\n // Documents\n '.pdf': 'application/pdf',\n // Archives\n '.zip': 'application/zip',\n '.gz': 'application/gzip',\n '.tar': 'application/x-tar',\n};\n\n/**\n * Get MIME type from file path extension.\n */\nfunction getMimeType(path: string): string {\n const ext = path.toLowerCase().match(/\\.[^.]+$/)?.[0];\n return ext ? (MIME_TYPES[ext] ?? 'application/octet-stream') : 'application/octet-stream';\n}\n\n/**\n * GCS filesystem provider configuration.\n */\nexport interface GCSFilesystemOptions extends MastraFilesystemOptions {\n /** Unique identifier for this filesystem instance */\n id?: string;\n /** GCS bucket name */\n bucket: string;\n /** Human-friendly display name for the UI */\n displayName?: string;\n /** Icon identifier for the UI (defaults to 'gcs') */\n icon?: FilesystemIcon;\n /** Description shown in tooltips */\n description?: string;\n /**\n * GCS project ID.\n * Required when using service account credentials.\n */\n projectId?: string;\n /**\n * Service account key JSON object or path to key file.\n * If not provided, uses Application Default Credentials (ADC).\n */\n credentials?: object | string;\n /** Optional prefix for all keys (acts like a subdirectory) */\n prefix?: string;\n /** Mount as read-only (blocks write operations, mounts read-only in sandboxes) */\n readOnly?: boolean;\n /**\n * Custom API endpoint URL.\n * Used for local development with emulators like fake-gcs-server.\n */\n endpoint?: string;\n}\n\n/**\n * GCS filesystem implementation.\n *\n * Stores files in a Google Cloud Storage bucket.\n * Supports mounting into E2B sandboxes via gcsfuse.\n *\n * @example Using Application Default Credentials\n * ```typescript\n * import { GCSFilesystem } from '@mastra/gcs';\n *\n * // Uses ADC (gcloud auth application-default login)\n * const fs = new GCSFilesystem({\n * bucket: 'my-bucket',\n * projectId: 'my-project',\n * });\n * ```\n *\n * @example Using Service Account Key\n * ```typescript\n * import { GCSFilesystem } from '@mastra/gcs';\n *\n * const fs = new GCSFilesystem({\n * bucket: 'my-bucket',\n * projectId: 'my-project',\n * credentials: {\n * type: 'service_account',\n * project_id: 'my-project',\n * private_key_id: '...',\n * private_key: '-----BEGIN PRIVATE KEY-----\\n...',\n * client_email: '...@...iam.gserviceaccount.com',\n * // ... rest of service account key\n * },\n * });\n * ```\n *\n * @example Using Key File Path\n * ```typescript\n * import { GCSFilesystem } from '@mastra/gcs';\n *\n * const fs = new GCSFilesystem({\n * bucket: 'my-bucket',\n * projectId: 'my-project',\n * credentials: '/path/to/service-account-key.json',\n * });\n * ```\n */\n\n/** Trim leading and trailing slashes without regex (avoids polynomial regex on user input). */\nfunction trimSlashes(s: string): string {\n let start = 0;\n let end = s.length;\n while (start < end && s[start] === '/') start++;\n while (end > start && s[end - 1] === '/') end--;\n return s.slice(start, end);\n}\n\nexport class GCSFilesystem extends MastraFilesystem {\n readonly id: string;\n readonly name = 'GCSFilesystem';\n readonly provider = 'gcs';\n readonly readOnly?: boolean;\n\n status: ProviderStatus = 'pending';\n\n // Display metadata for UI\n readonly displayName?: string;\n readonly icon: FilesystemIcon = 'gcs';\n readonly description?: string;\n\n private readonly bucketName: string;\n private readonly projectId?: string;\n private readonly credentials?: object | string;\n private readonly prefix: string;\n private readonly endpoint?: string;\n\n private _storage: Storage | null = null;\n private _bucket: Bucket | null = null;\n\n constructor(options: GCSFilesystemOptions) {\n super({ ...options, name: 'GCSFilesystem' });\n this.id = options.id ?? `gcs-fs-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n this.bucketName = options.bucket;\n this.projectId = options.projectId;\n this.credentials = options.credentials;\n // Trim leading/trailing slashes from prefix using iterative approach (avoids polynomial regex)\n this.prefix = options.prefix ? trimSlashes(options.prefix) + '/' : '';\n this.endpoint = options.endpoint;\n\n // Display metadata\n this.displayName = options.displayName ?? 'Google Cloud Storage';\n this.icon = options.icon ?? 'gcs';\n this.description = options.description;\n this.readOnly = options.readOnly;\n }\n\n /**\n * Get mount configuration for E2B sandbox.\n * Returns GCS-compatible config that works with gcsfuse.\n */\n getMountConfig(): GCSMountConfig {\n const config: GCSMountConfig = {\n type: 'gcs',\n bucket: this.bucketName,\n };\n\n // Include service account key if credentials are an object\n if (this.credentials && typeof this.credentials === 'object') {\n config.serviceAccountKey = JSON.stringify(this.credentials);\n }\n\n return config;\n }\n\n /**\n * Get filesystem info for status reporting.\n */\n getInfo(): FilesystemInfo<{\n bucket: string;\n endpoint?: string;\n prefix?: string;\n }> {\n return {\n id: this.id,\n name: this.name,\n provider: this.provider,\n status: this.status,\n error: this.error,\n readOnly: this.readOnly,\n icon: this.icon,\n metadata: {\n bucket: this.bucketName,\n ...(this.endpoint && { endpoint: this.endpoint }),\n ...(this.prefix && { prefix: this.prefix }),\n },\n };\n }\n\n /**\n * Get instructions describing this GCS filesystem.\n * Used by agents to understand storage semantics.\n */\n getInstructions(): string {\n const access = this.readOnly ? 'Read-only' : 'Persistent';\n return `Google Cloud Storage in bucket \"${this.bucketName}\". ${access} storage - files are retained across sessions.`;\n }\n\n private getStorage(): Storage {\n if (this._storage) return this._storage;\n\n const options: { projectId?: string; credentials?: object; keyFilename?: string; apiEndpoint?: string } = {};\n\n if (this.projectId) {\n options.projectId = this.projectId;\n }\n\n if (this.credentials) {\n if (typeof this.credentials === 'string') {\n // Path to key file\n options.keyFilename = this.credentials;\n } else {\n // Credentials object\n options.credentials = this.credentials;\n }\n }\n\n if (this.endpoint) {\n options.apiEndpoint = this.endpoint;\n }\n\n this._storage = new Storage(options);\n return this._storage;\n }\n\n private getBucket(): Bucket {\n if (this._bucket) return this._bucket;\n\n const storage = this.getStorage();\n this._bucket = storage.bucket(this.bucketName);\n return this._bucket;\n }\n\n /**\n * Ensure the filesystem is initialized and return the bucket.\n * Uses base class ensureReady() for status management, then returns bucket.\n */\n private async getReadyBucket(): Promise<Bucket> {\n await this.ensureReady();\n return this.getBucket();\n }\n\n private toKey(path: string): string {\n // Remove leading slash and add prefix\n const cleanPath = path.replace(/^\\/+/, '');\n return this.prefix + cleanPath;\n }\n\n // ---------------------------------------------------------------------------\n // File Operations\n // ---------------------------------------------------------------------------\n\n async readFile(path: string, options?: ReadOptions): Promise<string | Buffer> {\n const bucket = await this.getReadyBucket();\n const file = bucket.file(this.toKey(path));\n\n try {\n const [content] = await file.download();\n\n if (options?.encoding) {\n return content.toString(options.encoding);\n }\n return content;\n } catch (error: unknown) {\n if (error && typeof error === 'object' && 'code' in error && error.code === 404) {\n throw new FileNotFoundError(path);\n }\n throw error;\n }\n }\n\n async writeFile(path: string, content: FileContent, options?: WriteOptions): Promise<void> {\n const bucket = await this.getReadyBucket();\n const file = bucket.file(this.toKey(path));\n\n if (options?.overwrite === false && (await this.exists(path))) {\n throw new FileExistsError(path);\n }\n\n const body = typeof content === 'string' ? Buffer.from(content, 'utf-8') : Buffer.from(content);\n const contentType = getMimeType(path);\n\n await file.save(body, {\n contentType,\n resumable: false,\n });\n }\n\n async appendFile(path: string, content: FileContent): Promise<void> {\n // GCS doesn't support append, so read + write\n let existing = '';\n try {\n existing = (await this.readFile(path, { encoding: 'utf-8' })) as string;\n } catch (error) {\n if (error instanceof FileNotFoundError) {\n // File doesn't exist, start fresh\n } else {\n throw error;\n }\n }\n\n const appendContent = typeof content === 'string' ? content : Buffer.from(content).toString('utf-8');\n await this.writeFile(path, existing + appendContent);\n }\n\n async deleteFile(path: string, options?: RemoveOptions): Promise<void> {\n // Check if this is a directory - if so, use rmdir instead\n const isDir = await this.isDirectory(path);\n if (isDir) {\n await this.rmdir(path, { recursive: true, force: options?.force });\n return;\n }\n\n const bucket = await this.getReadyBucket();\n const file = bucket.file(this.toKey(path));\n\n try {\n await file.delete();\n } catch (error: unknown) {\n if (!options?.force) {\n if (error && typeof error === 'object' && 'code' in error && error.code === 404) {\n throw new FileNotFoundError(path);\n }\n throw error;\n }\n }\n }\n\n async copyFile(src: string, dest: string, options?: CopyOptions): Promise<void> {\n const bucket = await this.getReadyBucket();\n const srcFile = bucket.file(this.toKey(src));\n const destFile = bucket.file(this.toKey(dest));\n\n if (options?.overwrite === false && (await this.exists(dest))) {\n throw new FileExistsError(dest);\n }\n\n try {\n await srcFile.copy(destFile);\n } catch (error: unknown) {\n if (error && typeof error === 'object' && 'code' in error && error.code === 404) {\n throw new FileNotFoundError(src);\n }\n throw error;\n }\n }\n\n async moveFile(src: string, dest: string, options?: CopyOptions): Promise<void> {\n await this.copyFile(src, dest, options);\n await this.deleteFile(src, { force: true });\n }\n\n // ---------------------------------------------------------------------------\n // Directory Operations\n // ---------------------------------------------------------------------------\n\n async mkdir(_path: string, _options?: { recursive?: boolean }): Promise<void> {\n // GCS doesn't have real directories - they're just key prefixes\n // No-op, directories are created implicitly when files are written\n }\n\n async rmdir(path: string, options?: RemoveOptions): Promise<void> {\n if (!options?.recursive) {\n // Quick emptiness check — only fetch one object instead of full readdir\n const bucket = await this.getReadyBucket();\n const prefix = this.toKey(path).replace(/\\/$/, '') + '/';\n const [files] = await bucket.getFiles({ prefix, maxResults: 1 });\n if (files.length > 0) {\n throw new Error(`Directory not empty: ${path}`);\n }\n return;\n }\n\n // Delete all objects with this prefix\n const bucket = await this.getReadyBucket();\n const prefix = this.toKey(path).replace(/\\/$/, '') + '/';\n\n await bucket.deleteFiles({ prefix });\n }\n\n async readdir(path: string, options?: ListOptions): Promise<FileEntry[]> {\n const bucket = await this.getReadyBucket();\n\n const prefix = this.toKey(path).replace(/\\/$/, '');\n const searchPrefix = prefix ? prefix + '/' : '';\n\n const entries: FileEntry[] = [];\n const seenDirs = new Set<string>();\n\n const [files] = await bucket.getFiles({\n prefix: searchPrefix,\n autoPaginate: true,\n });\n\n for (const file of files) {\n const key = file.name;\n if (!key || key === searchPrefix) continue;\n\n const relativePath = key.slice(searchPrefix.length);\n if (!relativePath) continue;\n\n // Skip if this looks like a directory marker\n if (relativePath.endsWith('/')) {\n const dirName = relativePath.slice(0, -1);\n if (!seenDirs.has(dirName)) {\n seenDirs.add(dirName);\n entries.push({ name: dirName, type: 'directory' });\n }\n continue;\n }\n\n const name = options?.recursive ? relativePath : relativePath.split('/')[0];\n\n // Skip if name is undefined or empty\n if (!name) continue;\n\n // For non-recursive listing, if there's a slash, it's a directory\n if (!options?.recursive && relativePath.includes('/')) {\n if (!seenDirs.has(name)) {\n seenDirs.add(name);\n entries.push({ name, type: 'directory' });\n }\n continue;\n }\n\n // Filter by extension if specified\n if (options?.extension) {\n const extensions = Array.isArray(options.extension) ? options.extension : [options.extension];\n if (!extensions.some(ext => name.endsWith(ext))) {\n continue;\n }\n }\n\n entries.push({\n name,\n type: 'file',\n size: file.metadata.size != null ? Number(file.metadata.size) : undefined,\n });\n }\n\n return entries;\n }\n\n // ---------------------------------------------------------------------------\n // Path Operations\n // ---------------------------------------------------------------------------\n\n async exists(path: string): Promise<boolean> {\n const key = this.toKey(path);\n\n // Root path always exists (it's the bucket itself)\n if (!key) return true;\n\n const bucket = await this.getReadyBucket();\n const file = bucket.file(key);\n\n // Check if it's a file\n const [exists] = await file.exists();\n if (exists) return true;\n\n // Check if it's a \"directory\" (has objects with this prefix)\n const [files] = await bucket.getFiles({\n prefix: key.replace(/\\/$/, '') + '/',\n maxResults: 1,\n });\n\n return files.length > 0;\n }\n\n async stat(path: string): Promise<FileStat> {\n const key = this.toKey(path);\n\n // Root path is always a directory\n if (!key) {\n return {\n name: '',\n path,\n type: 'directory',\n size: 0,\n createdAt: new Date(),\n modifiedAt: new Date(),\n };\n }\n\n const bucket = await this.getReadyBucket();\n const file = bucket.file(key);\n\n const [exists] = await file.exists();\n if (exists) {\n const [metadata] = await file.getMetadata();\n const name = path.split('/').pop() ?? '';\n\n return {\n name,\n path,\n type: 'file',\n size: Number(metadata.size) || 0,\n createdAt: metadata.timeCreated ? new Date(metadata.timeCreated) : new Date(),\n modifiedAt: metadata.updated ? new Date(metadata.updated) : new Date(),\n };\n }\n\n // Check if it's a directory\n const isDir = await this.isDirectory(path);\n if (isDir) {\n const name = path.split('/').filter(Boolean).pop() ?? '';\n return {\n name,\n path,\n type: 'directory',\n size: 0,\n createdAt: new Date(),\n modifiedAt: new Date(),\n };\n }\n\n throw new FileNotFoundError(path);\n }\n\n async isFile(path: string): Promise<boolean> {\n const key = this.toKey(path);\n if (!key) return false; // Root is a directory, not a file\n\n const bucket = await this.getReadyBucket();\n const file = bucket.file(key);\n\n const [exists] = await file.exists();\n return exists;\n }\n\n async isDirectory(path: string): Promise<boolean> {\n const key = this.toKey(path);\n if (!key) return true; // Root is always a directory\n\n const bucket = await this.getReadyBucket();\n\n const [files] = await bucket.getFiles({\n prefix: key.replace(/\\/$/, '') + '/',\n maxResults: 1,\n });\n\n return files.length > 0;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle (overrides base class protected methods)\n // ---------------------------------------------------------------------------\n\n /**\n * Initialize the GCS client.\n * Status management is handled by the base class.\n */\n async init(): Promise<void> {\n // Verify we can access the bucket\n const bucket = this.getBucket();\n try {\n const [exists] = await bucket.exists();\n if (!exists) {\n const err = new Error(`Bucket \"${this.bucketName}\" does not exist`) as Error & { status?: number };\n err.status = 404;\n throw err;\n }\n } catch (error) {\n // Check if error already has status (from our 404 throw above)\n if ((error as { status?: number }).status) {\n throw error;\n }\n // Extract status code from GCS errors and add to error for proper HTTP response\n const code = (error as { code?: number }).code;\n if (typeof code === 'number') {\n const message = error instanceof Error ? error.message : String(error);\n const err = new Error(\n message,\n // code === 403\n // ? `Access denied to bucket \"${this.bucketName}\" - check credentials and permissions`\n // : message,\n ) as Error & { status?: number };\n err.status = code;\n throw err;\n }\n throw error;\n }\n }\n\n /**\n * Clean up the GCS client.\n * Status management is handled by the base class.\n */\n async destroy(): Promise<void> {\n this._storage = null;\n this._bucket = null;\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/gcs",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Google Cloud Storage filesystem provider for Mastra workspaces",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
},
|
|
21
21
|
"license": "Apache-2.0",
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@google-cloud/storage": "^7.
|
|
23
|
+
"@google-cloud/storage": "^7.19.0"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@types/node": "22.19.7",
|
|
@@ -31,13 +31,13 @@
|
|
|
31
31
|
"tsup": "^8.5.1",
|
|
32
32
|
"typescript": "^5.9.3",
|
|
33
33
|
"vitest": "4.0.16",
|
|
34
|
-
"@internal/lint": "0.0.
|
|
35
|
-
"@internal/types-builder": "0.0.
|
|
36
|
-
"@internal/workspace-test-utils": "0.0.
|
|
37
|
-
"@mastra/core": "1.
|
|
34
|
+
"@internal/lint": "0.0.59",
|
|
35
|
+
"@internal/types-builder": "0.0.34",
|
|
36
|
+
"@internal/workspace-test-utils": "0.0.3",
|
|
37
|
+
"@mastra/core": "1.4.0"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
|
-
"@mastra/core": ">=1.
|
|
40
|
+
"@mastra/core": ">=1.4.0-0 <2.0.0-0"
|
|
41
41
|
},
|
|
42
42
|
"files": [
|
|
43
43
|
"dist",
|