@aigne/afs-gcs 1.11.0-beta.10 → 1.11.0-beta.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +5 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +163 -78
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AFSAccessMode, AFSBaseProvider, AFSDeleteResult, AFSEntry, AFSExecResult, AFSExplainResult, AFSListResult, AFSModuleLoadParams, AFSSearchResult, AFSStatResult, AFSWriteEntryPayload, AFSWriteResult, ProviderManifest, RouteContext } from "@aigne/afs";
|
|
1
|
+
import { AFSAccessMode, AFSBaseProvider, AFSDeleteResult, AFSEntry, AFSExecResult, AFSExplainResult, AFSListResult, AFSModuleLoadParams, AFSSearchResult, AFSStatResult, AFSWriteEntryPayload, AFSWriteResult, ProviderManifest, ProviderTreeSchema, RouteContext } from "@aigne/afs";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
|
|
4
4
|
//#region src/types.d.ts
|
|
@@ -113,6 +113,10 @@ declare class AFSGCS extends AFSBaseProvider {
|
|
|
113
113
|
* Provider manifest for URI-based discovery
|
|
114
114
|
*/
|
|
115
115
|
static manifest(): ProviderManifest;
|
|
116
|
+
/**
|
|
117
|
+
* Tree schema for progressive disclosure
|
|
118
|
+
*/
|
|
119
|
+
static treeSchema(): ProviderTreeSchema;
|
|
116
120
|
/**
|
|
117
121
|
* Load from configuration file
|
|
118
122
|
*/
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/gcs-afs.ts"],"mappings":";;;;AAUA;;;AAAA,UAAiB,aAAA;EAEf;EAAA,IAAA;EAMA;EAHA,WAAA;EASA;EANA,MAAA;EAYA;EATA,MAAA;EAeA;EAZA,SAAA;EAcE;EAXF,UAAA;EAeQ;EAZR,QAAA;EAmEe;EAhEf,WAAA;;EAGA,WAAA;IACE,WAAA;IACA,UAAA;EAAA;;EAIF,QAAA;AAAA;;;;UAuDe,YAAA;EACf,MAAA;EACA,MAAA;AAAA;;;;;;;;;;;;;;;;AAFF;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/gcs-afs.ts"],"mappings":";;;;AAUA;;;AAAA,UAAiB,aAAA;EAEf;EAAA,IAAA;EAMA;EAHA,WAAA;EASA;EANA,MAAA;EAYA;EATA,MAAA;EAeA;EAZA,SAAA;EAcE;EAXF,UAAA;EAeQ;EAZR,QAAA;EAmEe;EAhEf,WAAA;;EAGA,WAAA;IACE,WAAA;IACA,UAAA;EAAA;;EAIF,QAAA;AAAA;;;;UAuDe,YAAA;EACf,MAAA;EACA,MAAA;AAAA;;;;;;;;;;;;;;;;AAFF;;;;;;;;ACXA;;;cAAa,MAAA,SAAe,eAAA;EAAA,SACR,IAAA;EAAA,SACA,WAAA;EAAA,SACA,UAAA,EAAY,aAAA;EAAA,QAEtB,OAAA;EAAA,QACA,OAAA;EAAA,QACA,MAAA;EAAA,QACA,SAAA;EAAA,QACA,SAAA;cAEI,OAAA,EAAS,aAAA;IAAkB,GAAA;IAAc,KAAA;IAAgB,IAAA;EAAA;EA8UtC;;;EAAA,OA5SxB,MAAA,CAAA,GAAM,CAAA,CAAA,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAg5BV;;;EAAA,OAz4BI,QAAA,CAAA,GAAY,gBAAA;EAw6BhB;;;EAAA,OAz4BI,UAAA,CAAA,GAAc,kBAAA;EA27BlB;;;EAAA,OAj6BU,IAAA,CAAA;IAAO,QAAA;IAAU;EAAA,IAAU,mBAAA,GAA2B,OAAA,CAAQ,MAAA;EA2iCpE;;;EAAA,QAjiCC,WAAA;EA4kC4C;;;EAAA,QApkC5C,UAAA;EA/HiC;;;EAAA,QAuIjC,eAAA;EApIU;;;EAqJlB,UAAA,CAAA;EASM,WAAA,CAAY,GAAA,EAAK,YAAA;IAAe,IAAA;EAAA,KAAmB,OAAA,CAAQ,aAAA;;;;UAoEnD,iBAAA;EAoHR,mBAAA,CAAoB,GAAA,EAAK,YAAA;IAAe,IAAA;EAAA,KAAkB,OAAA,CAAQ,aAAA;EAgDlE,WAAA,CAAY,GAAA,EAAK,YAAA;IAAe,IAAA;EAAA,KAAkB,OAAA,CAAQ,QAAA;EA8H1D,kBAAA,CACJ,GAAA,EAAK,YAAA;IAAe,IAAA;IAAc,UAAA;EAAA,KACjC,OAAA,CAAQ,QAAA;EA0CL,WAAA,CAAY,GAAA,EAAK,YAAA;IAAe,IAAA;EAAA,KAAmB,OAAA,CAAQ,QAAA;EAmJ3D,WAAA,CAAY,GAAA,EAAK,YAAA;IAAe,IAAA;EAAA,KAAmB,OAAA,CAAQ,aAAA;EAuB3D,YAAA,CACJ,GAAA,EAAK,YAAA;IAAe,IAAA;EAAA,IACpB,OAAA,EAAS,oBAAA,GACR,OAAA,CAAQ,cAAA;EAiEL,aAAA,CAAc,GAAA,EAAK,YAAA;IAAe,IAAA;EAAA,KAAkB,OAAA,CAAQ,eAAA;EA4C5D,kBAAA,CAAmB,GAAA,EAAK,YAAA;IAAe,IAAA;EAAA,KAAkB,OAAA,CAAQ,aAAA;EAgFjE,yBAAA,CACJ,GAAA,EAAK,YAAA;IAAe,IAAA;EAAA,IACpB,IAAA,EAAM,MAAA,oBACL,OAAA,CAAQ,aAAA;EA0BL,uBAAA,CACJ,GAAA,EAAK,YAAA;IAAe,IAAA;EAAA,IACpB,IAAA,EAAM,MAAA,oBACL,OAAA,CAAQ,aAAA;EA4BL,oBAAA,CACJ,GAAA,EAAK,YAAA;IAAe,IAAA;EAAA,IACpB,IAAA,EAAM,MAAA,oBACL,OAAA,CAAQ,aAAA;EA+CL,oBAAA,CACJ,GAAA,EAAK,YAAA;IAAe,IAAA;EAAA,IACpB,IAAA,EAAM,MAAA,oBACL,OAAA,CAAQ,aAAA;EAmDL,cAAA,CAAe,GAAA,EAAK,YAAA;IAAe,IAAA;EAAA,KAAmB,OAAA,CAAQ,gBAAA;EAsF9D,aAAA,CACJ,GAAA,EAAK,YAAA;IAAe,IAAA;EAAA,IACpB,KAAA,WACC,OAAA,CAAQ,eAAA;EAyCL,gBAAA,CAAiB,IAAA,EAAM,YAAA,GAAe,OAAA,CAAQ,QAAA;AAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -352,7 +352,7 @@ var AFSGCS = class AFSGCS extends AFSBaseProvider {
|
|
|
352
352
|
name: "gcs",
|
|
353
353
|
description: "Google Cloud Storage bucket.\n- Browse, read, write, and delete objects; search by key prefix\n- Exec actions: `presign-download`, `presign-upload`, `compose` (concatenate objects), `rewrite` (copy with transform)\n- Path structure: `/{key-prefix}/{object-key}`",
|
|
354
354
|
uriTemplate: "gcs://{bucket}/{prefix+?}",
|
|
355
|
-
category: "
|
|
355
|
+
category: "storage",
|
|
356
356
|
schema: z.object({
|
|
357
357
|
bucket: z.string(),
|
|
358
358
|
prefix: z.string().optional(),
|
|
@@ -364,7 +364,92 @@ var AFSGCS = class AFSGCS extends AFSBaseProvider {
|
|
|
364
364
|
"gcs",
|
|
365
365
|
"cloud",
|
|
366
366
|
"storage"
|
|
367
|
-
]
|
|
367
|
+
],
|
|
368
|
+
capabilityTags: [
|
|
369
|
+
"read-write",
|
|
370
|
+
"crud",
|
|
371
|
+
"search",
|
|
372
|
+
"auth:gcp",
|
|
373
|
+
"remote",
|
|
374
|
+
"cloud",
|
|
375
|
+
"http"
|
|
376
|
+
],
|
|
377
|
+
security: {
|
|
378
|
+
riskLevel: "external",
|
|
379
|
+
resourceAccess: ["cloud-api"],
|
|
380
|
+
requires: ["cloud-credentials"],
|
|
381
|
+
dataSensitivity: ["credentials"]
|
|
382
|
+
},
|
|
383
|
+
capabilities: {
|
|
384
|
+
network: {
|
|
385
|
+
egress: true,
|
|
386
|
+
allowedDomains: ["*.googleapis.com"]
|
|
387
|
+
},
|
|
388
|
+
secrets: ["gcp/credentials"]
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Tree schema for progressive disclosure
|
|
394
|
+
*/
|
|
395
|
+
static treeSchema() {
|
|
396
|
+
return {
|
|
397
|
+
operations: [
|
|
398
|
+
"list",
|
|
399
|
+
"read",
|
|
400
|
+
"write",
|
|
401
|
+
"delete",
|
|
402
|
+
"search",
|
|
403
|
+
"exec",
|
|
404
|
+
"stat",
|
|
405
|
+
"explain"
|
|
406
|
+
],
|
|
407
|
+
tree: {
|
|
408
|
+
"/": {
|
|
409
|
+
kind: "storage:bucket",
|
|
410
|
+
operations: [
|
|
411
|
+
"list",
|
|
412
|
+
"read",
|
|
413
|
+
"search"
|
|
414
|
+
]
|
|
415
|
+
},
|
|
416
|
+
"/{prefix}/": {
|
|
417
|
+
kind: "storage:prefix",
|
|
418
|
+
operations: ["list", "read"]
|
|
419
|
+
},
|
|
420
|
+
"/{key}": {
|
|
421
|
+
kind: "storage:object",
|
|
422
|
+
operations: [
|
|
423
|
+
"read",
|
|
424
|
+
"write",
|
|
425
|
+
"delete"
|
|
426
|
+
],
|
|
427
|
+
actions: [
|
|
428
|
+
"presign-download",
|
|
429
|
+
"presign-upload",
|
|
430
|
+
"compose",
|
|
431
|
+
"rewrite"
|
|
432
|
+
]
|
|
433
|
+
},
|
|
434
|
+
"/{key}/@versions": {
|
|
435
|
+
kind: "storage:version-list",
|
|
436
|
+
operations: ["list"]
|
|
437
|
+
},
|
|
438
|
+
"/{key}/@versions/{generation}": {
|
|
439
|
+
kind: "storage:version",
|
|
440
|
+
operations: ["read"]
|
|
441
|
+
}
|
|
442
|
+
},
|
|
443
|
+
auth: {
|
|
444
|
+
type: "gcp",
|
|
445
|
+
env: ["GOOGLE_APPLICATION_CREDENTIALS"]
|
|
446
|
+
},
|
|
447
|
+
bestFor: [
|
|
448
|
+
"object storage",
|
|
449
|
+
"static assets",
|
|
450
|
+
"data lake"
|
|
451
|
+
],
|
|
452
|
+
notFor: ["relational queries", "real-time sync"]
|
|
368
453
|
};
|
|
369
454
|
}
|
|
370
455
|
/**
|
|
@@ -412,7 +497,8 @@ var AFSGCS = class AFSGCS extends AFSBaseProvider {
|
|
|
412
497
|
try {
|
|
413
498
|
const normalizedPath = (ctx.params.path ?? "").replace(/^\/+/, "").replace(/\/+$/, "");
|
|
414
499
|
const fullPrefix = this.options.prefix ? normalizedPath ? `${this.options.prefix}/${normalizedPath}/` : `${this.options.prefix}/` : normalizedPath ? `${normalizedPath}/` : "";
|
|
415
|
-
const
|
|
500
|
+
const opts = ctx.options;
|
|
501
|
+
const maxChildren = opts?.limit ?? opts?.maxChildren ?? 1e3;
|
|
416
502
|
if (this.listCache) {
|
|
417
503
|
const cacheKey = createCacheKey(this.options.bucket, this.options.prefix ?? "", normalizedPath, JSON.stringify(ctx.options ?? {}));
|
|
418
504
|
const cached = this.listCache.get(cacheKey);
|
|
@@ -1100,86 +1186,85 @@ var AFSGCS = class AFSGCS extends AFSBaseProvider {
|
|
|
1100
1186
|
return { data: results };
|
|
1101
1187
|
}
|
|
1102
1188
|
async readCapabilities(_ctx) {
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
}
|
|
1122
|
-
},
|
|
1123
|
-
{
|
|
1124
|
-
name: "presign-upload",
|
|
1125
|
-
description: "Generate a signed upload URL",
|
|
1126
|
-
inputSchema: {
|
|
1127
|
-
type: "object",
|
|
1128
|
-
properties: {
|
|
1129
|
-
expiresIn: {
|
|
1189
|
+
return {
|
|
1190
|
+
id: ".capabilities",
|
|
1191
|
+
path: "/.meta/.capabilities",
|
|
1192
|
+
content: {
|
|
1193
|
+
schemaVersion: 1,
|
|
1194
|
+
provider: "gcs",
|
|
1195
|
+
description: `GCS bucket: ${this.options.bucket}`,
|
|
1196
|
+
tools: [],
|
|
1197
|
+
operations: this.getOperationsDeclaration(),
|
|
1198
|
+
actions: [{
|
|
1199
|
+
description: "GCS object actions",
|
|
1200
|
+
catalog: [
|
|
1201
|
+
{
|
|
1202
|
+
name: "presign-download",
|
|
1203
|
+
description: "Generate a signed download URL",
|
|
1204
|
+
inputSchema: {
|
|
1205
|
+
type: "object",
|
|
1206
|
+
properties: { expiresIn: {
|
|
1130
1207
|
type: "number",
|
|
1131
|
-
description: "Expiration in seconds"
|
|
1132
|
-
}
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1208
|
+
description: "Expiration in seconds (default: 3600, max: 604800)"
|
|
1209
|
+
} }
|
|
1210
|
+
}
|
|
1211
|
+
},
|
|
1212
|
+
{
|
|
1213
|
+
name: "presign-upload",
|
|
1214
|
+
description: "Generate a signed upload URL",
|
|
1215
|
+
inputSchema: {
|
|
1216
|
+
type: "object",
|
|
1217
|
+
properties: {
|
|
1218
|
+
expiresIn: {
|
|
1219
|
+
type: "number",
|
|
1220
|
+
description: "Expiration in seconds"
|
|
1221
|
+
},
|
|
1222
|
+
contentType: {
|
|
1223
|
+
type: "string",
|
|
1224
|
+
description: "Content-Type for upload"
|
|
1225
|
+
}
|
|
1136
1226
|
}
|
|
1137
1227
|
}
|
|
1138
|
-
}
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
}
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1228
|
+
},
|
|
1229
|
+
{
|
|
1230
|
+
name: "compose",
|
|
1231
|
+
description: "Compose multiple objects into one (max 32 sources)",
|
|
1232
|
+
inputSchema: {
|
|
1233
|
+
type: "object",
|
|
1234
|
+
properties: { sources: {
|
|
1235
|
+
type: "array",
|
|
1236
|
+
description: "Array of source paths (2-32)",
|
|
1237
|
+
items: { type: "string" }
|
|
1238
|
+
} },
|
|
1239
|
+
required: ["sources"]
|
|
1240
|
+
}
|
|
1241
|
+
},
|
|
1242
|
+
{
|
|
1243
|
+
name: "rewrite",
|
|
1244
|
+
description: "Copy/rewrite object to a new location",
|
|
1245
|
+
inputSchema: {
|
|
1246
|
+
type: "object",
|
|
1247
|
+
properties: {
|
|
1248
|
+
destination: {
|
|
1249
|
+
type: "string",
|
|
1250
|
+
description: "Destination path"
|
|
1251
|
+
},
|
|
1252
|
+
storageClass: {
|
|
1253
|
+
type: "string",
|
|
1254
|
+
description: "Target storage class"
|
|
1255
|
+
},
|
|
1256
|
+
contentType: {
|
|
1257
|
+
type: "string",
|
|
1258
|
+
description: "Override content type"
|
|
1259
|
+
}
|
|
1166
1260
|
},
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
description: "Override content type"
|
|
1170
|
-
}
|
|
1171
|
-
},
|
|
1172
|
-
required: ["destination"]
|
|
1261
|
+
required: ["destination"]
|
|
1262
|
+
}
|
|
1173
1263
|
}
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
}
|
|
1178
|
-
};
|
|
1179
|
-
return {
|
|
1180
|
-
id: ".capabilities",
|
|
1181
|
-
path: "/.meta/.capabilities",
|
|
1182
|
-
content: JSON.stringify(capabilities, null, 2),
|
|
1264
|
+
],
|
|
1265
|
+
discovery: { pathTemplate: "/{path}/.actions" }
|
|
1266
|
+
}]
|
|
1267
|
+
},
|
|
1183
1268
|
meta: { kind: "afs:capabilities" }
|
|
1184
1269
|
};
|
|
1185
1270
|
}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["AFSError","files","apiResponse","response","objectCount","prefixCount","lines"],"sources":["../src/cache.ts","../src/client.ts","../src/errors.ts","../src/platform-ref.ts","../src/types.ts","../src/gcs-afs.ts"],"sourcesContent":["/**\n * GCS Response Caching\n *\n * LRU cache with TTL for GCS list and stat results.\n */\n\n/**\n * Cache entry with expiration\n */\ninterface CacheEntry<T> {\n value: T;\n expiresAt: number;\n}\n\n/**\n * LRU Cache with TTL support\n */\nexport class LRUCache<T> {\n private cache = new Map<string, CacheEntry<T>>();\n private maxSize: number;\n private defaultTtl: number;\n\n /**\n * Create a new LRU cache\n *\n * @param maxSize - Maximum number of entries (default: 1000)\n * @param defaultTtl - Default TTL in seconds (default: 60)\n */\n constructor(maxSize = 1000, defaultTtl = 60) {\n this.maxSize = maxSize;\n this.defaultTtl = defaultTtl;\n }\n\n /**\n * Get a value from the cache\n *\n * @param key - Cache key\n * @returns Cached value or undefined if not found/expired\n */\n get(key: string): T | undefined {\n const entry = this.cache.get(key);\n\n if (!entry) {\n return undefined;\n }\n\n // Check if expired\n if (Date.now() > entry.expiresAt) {\n this.cache.delete(key);\n return undefined;\n }\n\n // Move to end (most recently used)\n this.cache.delete(key);\n this.cache.set(key, entry);\n\n return entry.value;\n }\n\n /**\n * Set a value in the cache\n *\n * @param key - Cache key\n * @param value - Value to cache\n * @param ttl - TTL in seconds (optional, uses default)\n */\n set(key: string, value: T, ttl?: number): void {\n // Remove if already exists (to update position)\n if (this.cache.has(key)) {\n this.cache.delete(key);\n }\n\n // Evict oldest entries if at capacity\n while (this.cache.size >= this.maxSize) {\n const oldestKey = this.cache.keys().next().value;\n if (oldestKey) {\n this.cache.delete(oldestKey);\n }\n }\n\n const expiresAt = Date.now() + (ttl ?? this.defaultTtl) * 1000;\n this.cache.set(key, { value, expiresAt });\n }\n\n /**\n * Delete a value from the cache\n *\n * @param key - Cache key\n */\n delete(key: string): void {\n this.cache.delete(key);\n }\n\n /**\n * Delete all entries matching a prefix\n *\n * @param prefix - Key prefix to match\n */\n deleteByPrefix(prefix: string): void {\n for (const key of this.cache.keys()) {\n if (key.startsWith(prefix)) {\n this.cache.delete(key);\n }\n }\n }\n\n /**\n * Clear all entries\n */\n clear(): void {\n this.cache.clear();\n }\n\n /**\n * Get the number of entries in the cache\n */\n get size(): number {\n return this.cache.size;\n }\n\n /**\n * Prune expired entries\n */\n prune(): void {\n const now = Date.now();\n for (const [key, entry] of this.cache.entries()) {\n if (now > entry.expiresAt) {\n this.cache.delete(key);\n }\n }\n }\n}\n\n/**\n * Create a cache key from bucket, prefix, and path\n */\nexport function createCacheKey(\n bucket: string,\n prefix: string,\n path: string,\n suffix?: string,\n): string {\n const base = `${bucket}:${prefix}:${path}`;\n return suffix ? `${base}:${suffix}` : base;\n}\n","/**\n * GCS Client Factory\n *\n * Creates configured Google Cloud Storage clients.\n */\n\nimport { Storage, type StorageOptions } from \"@google-cloud/storage\";\nimport type { AFSGCSOptions } from \"./types.js\";\n\n/**\n * Create a GCS Storage client from options\n *\n * @param options - AFSGCS options\n * @returns Configured Storage client\n */\nexport function createGCSClient(options: AFSGCSOptions): Storage {\n const storageOptions: StorageOptions = {};\n\n // Project ID\n if (options.projectId) {\n storageOptions.projectId = options.projectId;\n }\n\n // Custom endpoint (for fake-gcs-server)\n if (options.endpoint) {\n storageOptions.apiEndpoint = options.endpoint;\n }\n\n // Key file authentication\n if (options.keyFilename) {\n storageOptions.keyFilename = options.keyFilename;\n }\n\n // Explicit credentials\n if (options.credentials) {\n storageOptions.credentials = {\n client_email: options.credentials.clientEmail,\n private_key: options.credentials.privateKey,\n };\n }\n\n return new Storage(storageOptions);\n}\n","/**\n * GCS Provider Error Handling\n *\n * Maps GCS SDK errors to AFS error types.\n */\n\n/**\n * AFS error codes\n */\nexport const AFSErrorCode = {\n ENTRY_NOT_FOUND: \"ENTRY_NOT_FOUND\",\n MODULE_NOT_FOUND: \"MODULE_NOT_FOUND\",\n PERMISSION_DENIED: \"PERMISSION_DENIED\",\n AUTH_ERROR: \"AUTH_ERROR\",\n RATE_LIMIT_EXCEEDED: \"RATE_LIMIT_EXCEEDED\",\n INVALID_OPERATION: \"INVALID_OPERATION\",\n ALREADY_EXISTS: \"ALREADY_EXISTS\",\n SERVICE_UNAVAILABLE: \"SERVICE_UNAVAILABLE\",\n UNKNOWN: \"UNKNOWN\",\n} as const;\n\nexport type AFSErrorCode = (typeof AFSErrorCode)[keyof typeof AFSErrorCode];\n\n/**\n * AFS Error class\n */\nexport class AFSError extends Error {\n readonly code: AFSErrorCode;\n readonly retryAfter?: number;\n\n constructor(code: AFSErrorCode, message: string, options?: { retryAfter?: number }) {\n super(message);\n this.name = \"AFSError\";\n this.code = code;\n this.retryAfter = options?.retryAfter;\n }\n}\n\n/**\n * Custom GCS error class for internal use\n */\nexport class GCSError extends Error {\n constructor(\n message: string,\n public readonly code: number,\n ) {\n super(message);\n this.name = \"GCSError\";\n }\n}\n\n/**\n * Map GCS HTTP status codes to AFS error codes\n */\nconst STATUS_TO_AFS_ERROR: Record<number, AFSErrorCode> = {\n 400: AFSErrorCode.INVALID_OPERATION,\n 401: AFSErrorCode.AUTH_ERROR,\n 403: AFSErrorCode.PERMISSION_DENIED,\n 404: AFSErrorCode.ENTRY_NOT_FOUND,\n 409: AFSErrorCode.ALREADY_EXISTS,\n 429: AFSErrorCode.RATE_LIMIT_EXCEEDED,\n 503: AFSErrorCode.SERVICE_UNAVAILABLE,\n};\n\n/**\n * Map GCS error to AFS error\n *\n * @param error - GCS SDK error or generic error\n * @returns AFSError with appropriate error code\n */\nexport function mapGCSError(error: unknown): AFSError {\n // Handle GCSError\n if (error instanceof GCSError) {\n const afsCode = STATUS_TO_AFS_ERROR[error.code] ?? AFSErrorCode.UNKNOWN;\n return new AFSError(afsCode, error.message);\n }\n\n // Handle GCS SDK ApiError format (has code property)\n if (typeof error === \"object\" && error !== null && \"code\" in error) {\n const err = error as { code: number; message?: string };\n const statusCode = typeof err.code === \"number\" ? err.code : 500;\n const message = err.message ?? \"Unknown GCS error\";\n const afsCode = STATUS_TO_AFS_ERROR[statusCode] ?? AFSErrorCode.UNKNOWN;\n return new AFSError(afsCode, message);\n }\n\n // Handle generic Error\n if (error instanceof Error) {\n return new AFSError(AFSErrorCode.UNKNOWN, error.message);\n }\n\n // Unknown error type\n return new AFSError(AFSErrorCode.UNKNOWN, String(error));\n}\n","/**\n * GCS Platform Reference\n *\n * Generates Google Cloud Console URLs for GCS objects and directories.\n */\n\n/**\n * Platform reference containing console URL\n */\nexport interface GCSPlatformRef {\n consoleUrl: string;\n}\n\n/**\n * Generate platform reference with GCP Console URL\n *\n * @param bucket - GCS bucket name\n * @param prefix - Object prefix/key (without leading slash)\n * @param isDirectory - Whether this is a directory (prefix)\n * @returns Platform reference with console URL\n */\nexport function generatePlatformRef(\n bucket: string,\n prefix: string,\n isDirectory: boolean,\n): GCSPlatformRef {\n // GCS Console URL format:\n // Objects: https://console.cloud.google.com/storage/browser/_details/{bucket}/{path}\n // Folders: https://console.cloud.google.com/storage/browser/{bucket}/{path}\n\n if (isDirectory) {\n // Directory URL\n const normalizedPrefix = prefix.endsWith(\"/\") ? prefix : prefix ? `${prefix}/` : \"\";\n return {\n consoleUrl: `https://console.cloud.google.com/storage/browser/${bucket}/${normalizedPrefix}`,\n };\n }\n\n // File URL\n const encodedPrefix = encodeURIComponent(prefix).replace(/%2F/g, \"/\");\n return {\n consoleUrl: `https://console.cloud.google.com/storage/browser/_details/${bucket}/${encodedPrefix}`,\n };\n}\n","/**\n * AFS GCS Provider Types\n */\n\nimport { camelize, optionalize } from \"@aigne/afs/utils/zod\";\nimport { z } from \"zod\";\n\n/**\n * Configuration options for AFSGCS\n */\nexport interface AFSGCSOptions {\n /** Module name (used as mount path segment) */\n name?: string;\n\n /** Module description */\n description?: string;\n\n /** GCS bucket name */\n bucket: string;\n\n /** Key prefix (optional) */\n prefix?: string;\n\n /** GCP project ID */\n projectId?: string;\n\n /** Access mode */\n accessMode?: \"readonly\" | \"readwrite\";\n\n /** Custom endpoint for GCS-compatible services (fake-gcs-server) */\n endpoint?: string;\n\n /** Path to service account key file */\n keyFilename?: string;\n\n /** Explicit credentials (for programmatic access) */\n credentials?: {\n clientEmail: string;\n privateKey: string;\n };\n\n /** Cache TTL in seconds (0 = no cache) */\n cacheTtl?: number;\n}\n\n/**\n * GCS bucket name validation regex\n * - 3-63 characters\n * - lowercase letters, numbers, hyphens, dots (but not consecutive dots)\n * - must start and end with letter or number\n */\nconst BUCKET_NAME_REGEX = /^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/;\n\n/**\n * Additional validation for bucket names\n */\nfunction isValidBucketName(name: string): boolean {\n // Check basic regex\n if (!BUCKET_NAME_REGEX.test(name)) return false;\n\n // No consecutive dots\n if (name.includes(\"..\")) return false;\n\n // No underscores\n if (name.includes(\"_\")) return false;\n\n return true;\n}\n\n/**\n * Zod schema for options validation\n */\nexport const afsgcsOptionsSchema = camelize(\n z\n .object({\n name: optionalize(z.string()),\n description: optionalize(z.string()),\n bucket: z.string().refine(isValidBucketName, \"Invalid GCS bucket name\"),\n prefix: optionalize(z.string()),\n projectId: optionalize(z.string()),\n accessMode: optionalize(z.enum([\"readonly\", \"readwrite\"])),\n endpoint: optionalize(z.string().url()),\n keyFilename: optionalize(z.string()),\n credentials: optionalize(\n z.object({\n clientEmail: z.string(),\n privateKey: z.string(),\n }),\n ),\n cacheTtl: optionalize(z.number().int().min(0)),\n })\n .strict(),\n);\n\n/**\n * Parsed GCS URI\n */\nexport interface ParsedGCSUri {\n bucket: string;\n prefix: string;\n}\n","/**\n * AFS GCS Provider\n *\n * GCS provider using AFSBaseProvider decorator routing pattern.\n * Provides access to Google Cloud Storage through AFS.\n */\n\nimport {\n Actions,\n type AFSAccessMode,\n AFSBaseProvider,\n type AFSDeleteResult,\n type AFSEntry,\n AFSError,\n type AFSExecResult,\n type AFSExplainResult,\n type AFSListResult,\n type AFSModuleClass,\n type AFSModuleLoadParams,\n AFSNotFoundError,\n type AFSSearchResult,\n type AFSStatResult,\n type AFSWriteEntryPayload,\n type AFSWriteResult,\n type CapabilitiesManifest,\n Delete,\n Explain,\n List,\n Meta,\n type ProviderManifest,\n Read,\n type RouteContext,\n Search,\n Stat,\n Write,\n} from \"@aigne/afs\";\nimport { zodParse } from \"@aigne/afs/utils/zod\";\nimport type { Bucket, Storage } from \"@google-cloud/storage\";\nimport { joinURL } from \"ufo\";\nimport { z } from \"zod\";\nimport { createCacheKey, LRUCache } from \"./cache.js\";\nimport { createGCSClient } from \"./client.js\";\nimport { mapGCSError } from \"./errors.js\";\nimport { generatePlatformRef } from \"./platform-ref.js\";\nimport { type AFSGCSOptions, afsgcsOptionsSchema } from \"./types.js\";\n\n/**\n * Default URL expiration time (1 hour)\n */\nconst DEFAULT_EXPIRES_IN = 3600;\n\n/**\n * Maximum expiration time (7 days)\n */\nconst MAX_EXPIRES_IN = 604800;\n\n/**\n * Maximum sources for compose operation\n */\nconst MAX_COMPOSE_SOURCES = 32;\n\n/**\n * AFSGCS Provider using Base Provider pattern\n *\n * Provides access to Google Cloud Storage through AFS.\n * Uses decorator routing (@List, @Read, @Write, @Delete, @Meta, @Actions).\n *\n * @example\n * ```typescript\n * const gcs = new AFSGCS({\n * bucket: \"my-bucket\",\n * prefix: \"data\",\n * projectId: \"my-project\",\n * });\n *\n * // Mount to AFS\n * afs.mount(gcs);\n *\n * // List objects\n * const result = await afs.list(\"/modules/my-bucket/data\");\n *\n * // Read object\n * const content = await afs.read(\"/modules/my-bucket/data/file.json\");\n * ```\n */\nexport class AFSGCS extends AFSBaseProvider {\n override readonly name: string;\n override readonly description?: string;\n override readonly accessMode: AFSAccessMode;\n\n private options: Required<Pick<AFSGCSOptions, \"bucket\">> & AFSGCSOptions;\n private storage: Storage;\n private bucket: Bucket;\n private listCache?: LRUCache<AFSListResult>;\n private statCache?: LRUCache<AFSEntry>;\n\n constructor(options: AFSGCSOptions & { uri?: string; token?: string; auth?: unknown }) {\n super();\n\n // Strip registry-injected keys before strict schema validation\n const { uri: _uri, token: _token, auth: _auth, ...cleanOptions } = options as any;\n\n // Validate options\n const parsed = afsgcsOptionsSchema.parse(cleanOptions);\n\n this.options = {\n ...parsed,\n bucket: parsed.bucket,\n prefix: parsed.prefix ?? \"\",\n accessMode: parsed.accessMode ?? \"readonly\",\n };\n\n this.name = parsed.name ?? parsed.bucket;\n this.description = parsed.description ?? `GCS bucket: ${parsed.bucket}`;\n this.accessMode = this.options.accessMode ?? \"readonly\";\n\n // Create GCS client\n this.storage = createGCSClient(this.options);\n this.bucket = this.storage.bucket(parsed.bucket);\n\n // Initialize caches if cacheTtl is set\n if (parsed.cacheTtl && parsed.cacheTtl > 0) {\n this.listCache = new LRUCache<AFSListResult>(1000, parsed.cacheTtl);\n this.statCache = new LRUCache<AFSEntry>(5000, parsed.cacheTtl);\n }\n }\n\n /**\n * Schema for configuration validation\n */\n static schema() {\n return afsgcsOptionsSchema;\n }\n\n /**\n * Provider manifest for URI-based discovery\n */\n static manifest(): ProviderManifest {\n return {\n name: \"gcs\",\n description:\n \"Google Cloud Storage bucket.\\n- Browse, read, write, and delete objects; search by key prefix\\n- Exec actions: `presign-download`, `presign-upload`, `compose` (concatenate objects), `rewrite` (copy with transform)\\n- Path structure: `/{key-prefix}/{object-key}`\",\n uriTemplate: \"gcs://{bucket}/{prefix+?}\",\n category: \"cloud-storage\",\n schema: z.object({\n bucket: z.string(),\n prefix: z.string().optional(),\n projectId: z.string().optional(),\n keyFilename: z.string().optional(),\n }),\n tags: [\"gcp\", \"gcs\", \"cloud\", \"storage\"],\n };\n }\n\n /**\n * Load from configuration file\n */\n static async load({ basePath, config }: AFSModuleLoadParams = {}): Promise<AFSGCS> {\n const options = zodParse(afsgcsOptionsSchema, config, { prefix: basePath });\n return new AFSGCS(options);\n }\n\n // ========== Helper Methods ==========\n\n /**\n * Build the full GCS key from a path\n */\n private buildGCSKey(path: string): string {\n const normalizedPath = path.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n return this.options.prefix ? `${this.options.prefix}/${normalizedPath}` : normalizedPath;\n }\n\n /**\n * Generate a unique ID for a GCS object\n */\n private generateId(key: string): string {\n const cleanKey = key.replace(/^\\/+/, \"\");\n return `gcs://${this.options.bucket}/${cleanKey}`;\n }\n\n /**\n * Invalidate caches for a given path\n */\n private invalidateCache(path: string): void {\n if (this.statCache) {\n const statKey = createCacheKey(this.options.bucket, this.options.prefix ?? \"\", path);\n this.statCache.delete(statKey);\n }\n\n if (this.listCache) {\n // Invalidate list cache for parent directory\n const parentPath = path.split(\"/\").slice(0, -1).join(\"/\") || \"/\";\n const listPrefix = createCacheKey(this.options.bucket, this.options.prefix ?? \"\", parentPath);\n this.listCache.deleteByPrefix(listPrefix);\n }\n }\n\n /**\n * Clear all caches\n */\n clearCache(): void {\n this.listCache?.clear();\n this.statCache?.clear();\n }\n\n // ========== List Operations ==========\n\n @List(\"/\")\n @List(\"/:path*\")\n async listHandler(ctx: RouteContext<{ path?: string }>): Promise<AFSListResult> {\n try {\n const path = ctx.params.path ?? \"\";\n const normalizedPath = path.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n\n // Build the full GCS prefix\n const fullPrefix = this.options.prefix\n ? normalizedPath\n ? `${this.options.prefix}/${normalizedPath}/`\n : `${this.options.prefix}/`\n : normalizedPath\n ? `${normalizedPath}/`\n : \"\";\n\n const maxChildren = (ctx.options as { limit?: number } | undefined)?.limit ?? 1000;\n\n // Check cache first\n if (this.listCache) {\n const cacheKey = createCacheKey(\n this.options.bucket,\n this.options.prefix ?? \"\",\n normalizedPath,\n JSON.stringify(ctx.options ?? {}),\n );\n const cached = this.listCache.get(cacheKey);\n if (cached) {\n return cached;\n }\n }\n\n const result = await this.listWithDelimiter(fullPrefix, normalizedPath, maxChildren);\n\n // Cache the result\n if (this.listCache) {\n const cacheKey = createCacheKey(\n this.options.bucket,\n this.options.prefix ?? \"\",\n normalizedPath,\n JSON.stringify(ctx.options ?? {}),\n );\n this.listCache.set(cacheKey, result);\n\n // Also populate stat cache from list results\n if (this.statCache) {\n for (const entry of result.data) {\n const statKey = createCacheKey(\n this.options.bucket,\n this.options.prefix ?? \"\",\n entry.path,\n );\n this.statCache.set(statKey, entry);\n }\n }\n }\n\n return result;\n } catch (error) {\n if (error instanceof AFSNotFoundError) {\n throw error;\n }\n throw mapGCSError(error);\n }\n }\n\n /**\n * List with delimiter (single level)\n */\n private async listWithDelimiter(\n prefix: string,\n basePath: string,\n maxChildren: number,\n ): Promise<AFSListResult> {\n const childEntries: AFSEntry[] = [];\n const bucketName = this.options.bucket;\n\n const [files, , apiResponse] = await this.bucket.getFiles({\n prefix,\n delimiter: \"/\",\n maxResults: maxChildren,\n });\n\n // Add directories from prefixes\n const prefixes = (apiResponse as Record<string, unknown>)?.prefixes as string[] | undefined;\n if (prefixes) {\n for (const dirPrefix of prefixes) {\n if (!dirPrefix) continue;\n\n // Extract directory name\n const dirName = dirPrefix.slice(prefix.length).replace(/\\/$/, \"\");\n if (!dirName) continue;\n\n childEntries.push({\n id: this.generateId(dirPrefix),\n path: joinURL(\"/\", basePath, dirName),\n meta: {\n kind: \"afs:node\",\n childrenCount: -1,\n platformRef: generatePlatformRef(bucketName, dirPrefix, true),\n },\n });\n\n if (childEntries.length >= maxChildren) break;\n }\n }\n\n // Add files from Contents\n for (const file of files) {\n if (!file.name) continue;\n\n // Skip the prefix itself (if it's a \"directory marker\")\n if (file.name === prefix) continue;\n\n // Handle directory markers (ending with /)\n if (file.name.endsWith(\"/\")) {\n const dirName = file.name.slice(prefix.length).replace(/\\/$/, \"\");\n if (!dirName) continue;\n\n childEntries.push({\n id: this.generateId(file.name),\n path: joinURL(\"/\", basePath, dirName),\n updatedAt: file.metadata.updated ? new Date(file.metadata.updated as string) : undefined,\n meta: {\n kind: \"afs:node\",\n childrenCount: -1,\n platformRef: generatePlatformRef(bucketName, file.name, true),\n },\n });\n\n if (childEntries.length >= maxChildren) break;\n continue;\n }\n\n // Extract file name\n const fileName = file.name.slice(prefix.length);\n if (!fileName || fileName.includes(\"/\")) continue;\n\n childEntries.push({\n id: this.generateId(file.name),\n path: joinURL(\"/\", basePath, fileName),\n updatedAt: file.metadata.updated ? new Date(file.metadata.updated as string) : undefined,\n meta: {\n size: file.metadata.size ? Number(file.metadata.size) : undefined,\n contentType: file.metadata.contentType,\n lastModified: file.metadata.updated,\n etag: file.metadata.etag,\n storageClass: file.metadata.storageClass,\n platformRef: generatePlatformRef(bucketName, file.name, false),\n },\n });\n\n if (childEntries.length >= maxChildren) break;\n }\n\n const selfPath = basePath ? (basePath.startsWith(\"/\") ? basePath : `/${basePath}`) : \"/\";\n\n // For non-root paths with no children, check if the path exists\n if (childEntries.length === 0 && basePath) {\n // Check if this path exists as a file\n const key = this.options.prefix ? `${this.options.prefix}/${basePath}` : basePath;\n const file = this.bucket.file(key);\n const [fileExists] = await file.exists();\n\n if (fileExists) {\n // Path exists as an object (file), not a directory - return empty children\n return { data: [] };\n }\n\n // Check for directory marker\n const dirMarker = this.bucket.file(`${key}/`);\n const [dirExists] = await dirMarker.exists();\n\n if (!dirExists) {\n // Neither file nor directory marker exists\n throw new AFSNotFoundError(selfPath);\n }\n }\n\n return { data: childEntries };\n }\n\n // ========== Versioning List ==========\n\n @List(\"/:path*/@versions\")\n async listVersionsHandler(ctx: RouteContext<{ path: string }>): Promise<AFSListResult> {\n try {\n const normalizedPath = ctx.params.path.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n const key = this.options.prefix ? `${this.options.prefix}/${normalizedPath}` : normalizedPath;\n\n // Get all generations of the file\n const [files] = await this.bucket.getFiles({\n prefix: key,\n versions: true,\n });\n\n const entries: AFSEntry[] = [];\n\n for (const versionFile of files) {\n // Only include exact key matches\n if (versionFile.name !== key) continue;\n\n const generation = versionFile.metadata.generation;\n if (!generation) continue;\n\n const versionPath = joinURL(\"/\", normalizedPath, \"@versions\", String(generation));\n const isLive = !versionFile.metadata.timeDeleted;\n\n entries.push({\n id: `${this.generateId(key)}:${generation}`,\n path: versionPath,\n updatedAt: versionFile.metadata.timeCreated\n ? new Date(versionFile.metadata.timeCreated as string)\n : undefined,\n meta: {\n generation: generation,\n isLive,\n timeCreated: versionFile.metadata.timeCreated,\n size: versionFile.metadata.size ? Number(versionFile.metadata.size) : 0,\n etag: versionFile.metadata.etag,\n },\n });\n }\n\n return { data: entries };\n } catch (error) {\n throw mapGCSError(error);\n }\n }\n\n // ========== Read Operations ==========\n\n @Read(\"/:path*\")\n async readHandler(ctx: RouteContext<{ path: string }>): Promise<AFSEntry> {\n try {\n const key = this.buildGCSKey(ctx.params.path);\n const normalizedOutputPath = ctx.path.startsWith(\"/\") ? ctx.path : `/${ctx.path}`;\n const bucketName = this.options.bucket;\n\n // Handle root path - return bucket metadata with childrenCount\n if (!key) {\n const [files, , apiResponse] = await this.bucket.getFiles({\n prefix: this.options.prefix ? `${this.options.prefix}/` : \"\",\n delimiter: \"/\",\n maxResults: 1000,\n });\n const prefixes = (apiResponse as Record<string, unknown>)?.prefixes as string[] | undefined;\n const childrenCount = (prefixes?.length ?? 0) + files.length;\n\n return {\n id: this.generateId(\"/\"),\n path: \"/\",\n content: \"\",\n meta: {\n kind: \"afs:node\",\n childrenCount,\n platformRef: generatePlatformRef(bucketName, \"\", true),\n },\n };\n }\n\n const file = this.bucket.file(key);\n\n // Check if file exists\n const [exists] = await file.exists();\n\n if (exists) {\n const [metadata] = await file.getMetadata();\n\n // Check if this is a directory marker\n if (key.endsWith(\"/\") || metadata.contentType === \"application/x-directory\") {\n // Return directory info instead of throwing\n return {\n id: this.generateId(key),\n path: normalizedOutputPath,\n content: \"\",\n updatedAt: metadata.updated ? new Date(metadata.updated as string) : undefined,\n meta: {\n kind: \"afs:node\",\n childrenCount: -1,\n platformRef: generatePlatformRef(bucketName, key, true),\n },\n };\n }\n\n // Download content\n const [content] = await file.download();\n\n return {\n id: this.generateId(key),\n path: normalizedOutputPath,\n content: content.toString(\"utf-8\"),\n updatedAt: metadata.updated ? new Date(metadata.updated as string) : undefined,\n meta: {\n size: metadata.size ? Number(metadata.size) : undefined,\n mimeType: metadata.contentType,\n contentType: metadata.contentType,\n lastModified: metadata.updated,\n etag: metadata.etag,\n },\n };\n }\n\n // File doesn't exist, check if it's a directory prefix\n const [files, , apiResponse] = await this.bucket.getFiles({\n prefix: `${key}/`,\n delimiter: \"/\",\n maxResults: 1000,\n });\n const prefixes = (apiResponse as Record<string, unknown>)?.prefixes as string[] | undefined;\n const hasChildren = files.length > 0 || (prefixes && prefixes.length > 0);\n\n if (hasChildren) {\n // It's a directory - return directory info\n const childrenCount = (prefixes?.length ?? 0) + files.length;\n return {\n id: this.generateId(`${key}/`),\n path: normalizedOutputPath,\n content: \"\",\n meta: {\n kind: \"afs:node\",\n childrenCount,\n platformRef: generatePlatformRef(bucketName, key, true),\n },\n };\n }\n\n // Also check for directory marker (key ending with /)\n const dirMarker = this.bucket.file(`${key}/`);\n const [dirExists] = await dirMarker.exists();\n\n if (dirExists) {\n const [dirMetadata] = await dirMarker.getMetadata();\n return {\n id: this.generateId(`${key}/`),\n path: normalizedOutputPath,\n content: \"\",\n updatedAt: dirMetadata.updated ? new Date(dirMetadata.updated as string) : undefined,\n meta: {\n kind: \"afs:node\",\n childrenCount: -1,\n platformRef: generatePlatformRef(bucketName, key, true),\n },\n };\n }\n\n // Neither file nor directory exists\n throw new AFSNotFoundError(`/${ctx.params.path}`);\n } catch (error) {\n if (error instanceof AFSError || error instanceof AFSNotFoundError) {\n throw error;\n }\n throw mapGCSError(error);\n }\n }\n\n // ========== Version Read ==========\n\n @Read(\"/:path*/@versions/:generation\")\n async readVersionHandler(\n ctx: RouteContext<{ path: string; generation: string }>,\n ): Promise<AFSEntry> {\n try {\n const normalizedPath = ctx.params.path.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n const key = this.options.prefix ? `${this.options.prefix}/${normalizedPath}` : normalizedPath;\n const generation = ctx.params.generation;\n\n const file = this.bucket.file(key, { generation: parseInt(generation, 10) });\n\n // Check if version exists\n const [exists] = await file.exists();\n if (!exists) {\n throw new AFSNotFoundError(`/${normalizedPath}/@versions/${generation}`);\n }\n\n const [content] = await file.download();\n const [metadata] = await file.getMetadata();\n\n return {\n id: `${this.generateId(key)}:${generation}`,\n path: ctx.path,\n content: content.toString(\"utf-8\"),\n updatedAt: metadata.timeCreated ? new Date(metadata.timeCreated as string) : undefined,\n meta: {\n size: metadata.size ? Number(metadata.size) : undefined,\n contentType: metadata.contentType,\n timeCreated: metadata.timeCreated,\n etag: metadata.etag,\n generation: metadata.generation,\n },\n };\n } catch (error) {\n if (error instanceof AFSNotFoundError) {\n throw error;\n }\n throw mapGCSError(error);\n }\n }\n\n // ========== Meta Operations ==========\n\n @Meta(\"/\")\n @Meta(\"/:path*\")\n async metaHandler(ctx: RouteContext<{ path?: string }>): Promise<AFSEntry> {\n try {\n const path = ctx.params.path ?? \"\";\n const normalizedPath = path.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n const key = this.options.prefix\n ? normalizedPath\n ? `${this.options.prefix}/${normalizedPath}`\n : this.options.prefix\n : normalizedPath;\n\n const bucketName = this.options.bucket;\n\n // Root metadata\n if (!key) {\n const [files, , apiResponse] = await this.bucket.getFiles({\n prefix: this.options.prefix ? `${this.options.prefix}/` : \"\",\n delimiter: \"/\",\n maxResults: 1000,\n });\n const prefixes = (apiResponse as Record<string, unknown>)?.prefixes as string[] | undefined;\n const childrenCount = (prefixes?.length ?? 0) + files.length;\n\n return {\n id: this.generateId(\"/\"),\n path: \"/.meta\",\n meta: {\n kind: \"afs:node\",\n childrenCount,\n platformRef: generatePlatformRef(bucketName, \"\", true),\n },\n };\n }\n\n // Check cache first\n if (this.statCache) {\n const cacheKey = createCacheKey(bucketName, this.options.prefix ?? \"\", path);\n const cached = this.statCache.get(cacheKey);\n if (cached) {\n return {\n id: cached.id,\n path: ctx.path,\n meta: cached.meta,\n };\n }\n }\n\n // Try to get the object directly (file case)\n const file = this.bucket.file(key);\n const [exists] = await file.exists();\n\n if (exists) {\n const [metadata] = await file.getMetadata();\n\n // Check if this is a directory marker\n if (key.endsWith(\"/\") || metadata.contentType === \"application/x-directory\") {\n return {\n id: this.generateId(key),\n path: ctx.path,\n updatedAt: metadata.updated ? new Date(metadata.updated as string) : undefined,\n meta: {\n kind: \"afs:node\",\n childrenCount: -1,\n platformRef: generatePlatformRef(bucketName, key, true),\n },\n };\n }\n\n const result = {\n id: this.generateId(key),\n path: ctx.path,\n updatedAt: metadata.updated ? new Date(metadata.updated as string) : undefined,\n meta: {\n kind: \"afs:document\",\n size: metadata.size ? Number(metadata.size) : undefined,\n contentType: metadata.contentType,\n lastModified: metadata.updated,\n etag: metadata.etag,\n storageClass: metadata.storageClass,\n // GCS-specific fields\n generation: metadata.generation,\n metageneration: metadata.metageneration,\n crc32c: metadata.crc32c,\n md5Hash: metadata.md5Hash,\n platformRef: generatePlatformRef(bucketName, key, false),\n },\n };\n\n // Cache the result\n if (this.statCache) {\n const cacheKey = createCacheKey(bucketName, this.options.prefix ?? \"\", path);\n this.statCache.set(cacheKey, result);\n }\n\n return result;\n }\n\n // File doesn't exist, check if it's a directory prefix\n const [files] = await this.bucket.getFiles({\n prefix: `${key}/`,\n maxResults: 1,\n });\n\n if (files.length > 0) {\n // There are objects under this prefix, so it's a directory\n return {\n id: this.generateId(`${key}/`),\n path: ctx.path,\n meta: {\n kind: \"afs:node\",\n childrenCount: -1,\n platformRef: generatePlatformRef(bucketName, key, true),\n },\n };\n }\n\n // Also check for directory marker (key ending with /)\n const dirMarker = this.bucket.file(`${key}/`);\n const [dirExists] = await dirMarker.exists();\n\n if (dirExists) {\n const [dirMetadata] = await dirMarker.getMetadata();\n return {\n id: this.generateId(`${key}/`),\n path: ctx.path,\n updatedAt: dirMetadata.updated ? new Date(dirMetadata.updated as string) : undefined,\n meta: {\n kind: \"afs:node\",\n childrenCount: -1,\n platformRef: generatePlatformRef(bucketName, key, true),\n },\n };\n }\n\n // Neither file nor directory exists\n throw new AFSNotFoundError(path.startsWith(\"/\") ? path : `/${path}`);\n } catch (error) {\n if (error instanceof AFSNotFoundError) {\n throw error;\n }\n throw mapGCSError(error);\n }\n }\n\n // ========== Stat Operations ==========\n\n @Stat(\"/\")\n @Stat(\"/:path*\")\n async statHandler(ctx: RouteContext<{ path?: string }>): Promise<AFSStatResult> {\n // Delegate to meta handler and convert to stat result\n const metaEntry = await this.metaHandler({\n ...ctx,\n path: ctx.path.endsWith(\"/.meta\") ? ctx.path : `${ctx.path}/.meta`,\n });\n\n // Extract id from path\n const pathSegments = ctx.path.split(\"/\").filter(Boolean);\n const id = pathSegments.length > 0 ? (pathSegments[pathSegments.length - 1] as string) : \"/\";\n\n return {\n data: {\n id,\n path: ctx.path,\n meta: metaEntry.meta as Record<string, unknown>,\n },\n };\n }\n\n // ========== Write Operations ==========\n\n @Write(\"/:path*\")\n async writeHandler(\n ctx: RouteContext<{ path: string }>,\n payload: AFSWriteEntryPayload,\n ): Promise<AFSWriteResult> {\n try {\n const key = this.buildGCSKey(ctx.params.path);\n const file = this.bucket.file(key);\n\n // Prepare content\n let content: string | Buffer;\n if (typeof payload.content === \"string\") {\n content = payload.content;\n } else if (Buffer.isBuffer(payload.content)) {\n content = payload.content;\n } else if (payload.content !== undefined) {\n // JSON content\n content = JSON.stringify(payload.content);\n } else {\n content = \"\";\n }\n\n // Prepare save options\n // Disable validation for fake-gcs-server compatibility (it doesn't properly support CRC32C)\n const saveOptions: {\n contentType?: string;\n metadata?: Record<string, string>;\n validation?: boolean;\n } = {\n validation: false,\n };\n if (payload.meta?.mimeType || payload.meta?.contentType) {\n saveOptions.contentType =\n (payload.meta.mimeType as string) ?? (payload.meta.contentType as string);\n }\n\n // Write content\n await file.save(content, saveOptions);\n\n // Get updated metadata\n const [metadata] = await file.getMetadata();\n\n const normalizedOutputPath = ctx.path.startsWith(\"/\") ? ctx.path : `/${ctx.path}`;\n\n // Invalidate caches for the written path\n this.invalidateCache(ctx.params.path);\n\n return {\n data: {\n id: this.generateId(key),\n path: normalizedOutputPath,\n content: payload.content,\n updatedAt: metadata.updated ? new Date(metadata.updated as string) : new Date(),\n meta: {\n size: metadata.size ? Number(metadata.size) : 0,\n etag: metadata.etag,\n generation: metadata.generation,\n ...payload.meta,\n },\n },\n };\n } catch (error) {\n throw mapGCSError(error);\n }\n }\n\n // ========== Delete Operations ==========\n\n @Delete(\"/:path*\")\n async deleteHandler(ctx: RouteContext<{ path: string }>): Promise<AFSDeleteResult> {\n try {\n const key = this.buildGCSKey(ctx.params.path);\n const file = this.bucket.file(key);\n const [exists] = await file.exists();\n\n if (exists) {\n // It's a file, delete it directly\n await file.delete();\n\n // Invalidate caches for the deleted path\n this.invalidateCache(ctx.params.path);\n\n return {\n message: `Successfully deleted: ${ctx.params.path}`,\n };\n }\n\n // Check if it's a directory (has children)\n const [files] = await this.bucket.getFiles({\n prefix: `${key}/`,\n maxResults: 1,\n });\n\n if (files.length === 0) {\n throw new AFSNotFoundError(`/${ctx.params.path}`);\n }\n\n // Directory with children - need recursive option\n throw new AFSError(\n `Cannot delete non-empty directory: ${ctx.params.path}. Use recursive option.`,\n \"AFS_INVALID_OPERATION\",\n );\n } catch (error) {\n if (error instanceof AFSError || error instanceof AFSNotFoundError) {\n throw error;\n }\n throw mapGCSError(error);\n }\n }\n\n // ========== Action System ==========\n\n @Actions(\"/:path*\")\n async listActionsHandler(ctx: RouteContext<{ path: string }>): Promise<AFSListResult> {\n return {\n data: [\n {\n id: \"presign-download\",\n path: joinURL(ctx.path, \"presign-download\"),\n summary: \"Generate signed download URL\",\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n inputSchema: {\n type: \"object\",\n properties: {\n expiresIn: {\n type: \"number\",\n description: \"Expiration in seconds (default: 3600, max: 604800)\",\n },\n },\n },\n },\n },\n {\n id: \"presign-upload\",\n path: joinURL(ctx.path, \"presign-upload\"),\n summary: \"Generate signed upload URL\",\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n inputSchema: {\n type: \"object\",\n properties: {\n expiresIn: { type: \"number\", description: \"Expiration in seconds\" },\n contentType: { type: \"string\", description: \"Content-Type for upload\" },\n },\n },\n },\n },\n {\n id: \"compose\",\n path: joinURL(ctx.path, \"compose\"),\n summary: \"Compose multiple objects into one\",\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n inputSchema: {\n type: \"object\",\n properties: {\n sources: {\n type: \"array\",\n description: \"Array of source paths (2-32)\",\n items: { type: \"string\" },\n },\n },\n required: [\"sources\"],\n },\n },\n },\n {\n id: \"rewrite\",\n path: joinURL(ctx.path, \"rewrite\"),\n summary: \"Rewrite object to new location\",\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n inputSchema: {\n type: \"object\",\n properties: {\n destination: { type: \"string\", description: \"Destination path\" },\n storageClass: { type: \"string\", description: \"Target storage class\" },\n contentType: { type: \"string\", description: \"Override content type\" },\n },\n required: [\"destination\"],\n },\n },\n },\n ],\n };\n }\n\n @Actions.Exec(\"/:path*\", \"presign-download\")\n async signDownloadActionHandler(\n ctx: RouteContext<{ path: string }>,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const normalizedPath = ctx.params.path.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n const key = this.options.prefix ? `${this.options.prefix}/${normalizedPath}` : normalizedPath;\n const file = this.bucket.file(key);\n\n let expiresIn = (args.expiresIn as number) ?? DEFAULT_EXPIRES_IN;\n if (expiresIn > MAX_EXPIRES_IN) expiresIn = MAX_EXPIRES_IN;\n if (expiresIn < 1) expiresIn = 1;\n\n const expiresAt = Date.now() + expiresIn * 1000;\n\n const [url] = await file.getSignedUrl({\n action: \"read\",\n expires: expiresAt,\n });\n\n return {\n success: true,\n data: {\n url,\n expiresAt: new Date(expiresAt).toISOString(),\n },\n };\n }\n\n @Actions.Exec(\"/:path*\", \"presign-upload\")\n async signUploadActionHandler(\n ctx: RouteContext<{ path: string }>,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const normalizedPath = ctx.params.path.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n const key = this.options.prefix ? `${this.options.prefix}/${normalizedPath}` : normalizedPath;\n const file = this.bucket.file(key);\n\n let expiresIn = (args.expiresIn as number) ?? DEFAULT_EXPIRES_IN;\n if (expiresIn > MAX_EXPIRES_IN) expiresIn = MAX_EXPIRES_IN;\n if (expiresIn < 1) expiresIn = 1;\n\n const expiresAt = Date.now() + expiresIn * 1000;\n const contentType = (args.contentType as string) ?? \"application/octet-stream\";\n\n const [url] = await file.getSignedUrl({\n action: \"write\",\n expires: expiresAt,\n contentType,\n });\n\n return {\n success: true,\n data: {\n url,\n expiresAt: new Date(expiresAt).toISOString(),\n },\n };\n }\n\n @Actions.Exec(\"/:path*\", \"compose\")\n async composeActionHandler(\n ctx: RouteContext<{ path: string }>,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const normalizedPath = ctx.params.path.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n const destinationKey = this.options.prefix\n ? `${this.options.prefix}/${normalizedPath}`\n : normalizedPath;\n\n const sources = args.sources as string[];\n if (!sources || !Array.isArray(sources) || sources.length < 2) {\n throw new AFSError(\"compose requires at least 2 source objects\", \"AFS_INVALID_ARGUMENT\");\n }\n\n if (sources.length > MAX_COMPOSE_SOURCES) {\n throw new AFSError(\n `compose supports maximum ${MAX_COMPOSE_SOURCES} sources`,\n \"AFS_INVALID_ARGUMENT\",\n );\n }\n\n // Build source file references\n const sourceFiles = sources.map((source) => {\n const sourcePath = source.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n const sourceKey = this.options.prefix ? `${this.options.prefix}/${sourcePath}` : sourcePath;\n return this.bucket.file(sourceKey);\n });\n\n const destinationFile = this.bucket.file(destinationKey);\n\n // Compose the files using bucket.combine()\n await this.bucket.combine(sourceFiles, destinationFile);\n\n // Get metadata of the composed file\n const [metadata] = await destinationFile.getMetadata();\n\n // Invalidate cache for destination\n this.invalidateCache(ctx.params.path);\n\n return {\n success: true,\n data: {\n generation: metadata.generation,\n size: metadata.size ? Number(metadata.size) : 0,\n etag: metadata.etag,\n },\n };\n }\n\n @Actions.Exec(\"/:path*\", \"rewrite\")\n async rewriteActionHandler(\n ctx: RouteContext<{ path: string }>,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const normalizedPath = ctx.params.path.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n const sourceKey = this.options.prefix\n ? `${this.options.prefix}/${normalizedPath}`\n : normalizedPath;\n\n const destination = args.destination as string;\n if (!destination) {\n throw new AFSError(\"rewrite requires destination path\", \"AFS_INVALID_ARGUMENT\");\n }\n\n const destPath = destination.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n const destKey = this.options.prefix ? `${this.options.prefix}/${destPath}` : destPath;\n\n const sourceFile = this.bucket.file(sourceKey);\n const destFile = this.bucket.file(destKey);\n\n // Copy options\n const copyOptions: { contentType?: string; metadata?: Record<string, string> } = {};\n if (args.storageClass) {\n copyOptions.metadata = { storageClass: args.storageClass as string };\n }\n if (args.contentType) {\n copyOptions.contentType = args.contentType as string;\n }\n\n // Copy (rewrite) the file\n await sourceFile.copy(destFile, copyOptions);\n\n // Get metadata of the new file\n const [metadata] = await destFile.getMetadata();\n\n // Invalidate cache for destination\n this.invalidateCache(destPath);\n\n return {\n success: true,\n data: {\n destination: `/${destPath}`,\n generation: metadata.generation,\n size: metadata.size ? Number(metadata.size) : 0,\n etag: metadata.etag,\n storageClass: metadata.storageClass,\n },\n };\n }\n\n // ========== Explain Operations ==========\n\n @Explain(\"/\")\n @Explain(\"/:path*\")\n async explainHandler(ctx: RouteContext<{ path?: string }>): Promise<AFSExplainResult> {\n const normalizedPath = (ctx.params.path ?? \"\").replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n\n // Root explain\n if (!normalizedPath) {\n const [files, , response] = await this.bucket.getFiles({\n prefix: this.options.prefix ? `${this.options.prefix}/` : undefined,\n delimiter: \"/\",\n maxResults: 1000,\n });\n\n const objectCount = files.length;\n const prefixCount = (response as any)?.prefixes?.length ?? 0;\n\n const lines: string[] = [];\n lines.push(`# ${this.options.bucket}`);\n lines.push(\"\");\n lines.push(`- **Type**: GCS Bucket`);\n lines.push(`- **Bucket**: ${this.options.bucket}`);\n if (this.options.prefix) {\n lines.push(`- **Prefix**: ${this.options.prefix}`);\n }\n if (this.options.projectId) {\n lines.push(`- **Project**: ${this.options.projectId}`);\n }\n lines.push(`- **Access Mode**: ${this.accessMode}`);\n lines.push(`- **Top-level Objects**: ${objectCount}`);\n lines.push(`- **Top-level Prefixes**: ${prefixCount}`);\n\n return { format: \"markdown\", content: lines.join(\"\\n\") };\n }\n\n const key = this.buildGCSKey(normalizedPath);\n\n // Try as object first\n const file = this.bucket.file(key);\n const [exists] = await file.exists();\n\n if (exists) {\n const [metadata] = await file.getMetadata();\n\n const lines: string[] = [];\n lines.push(`# ${normalizedPath}`);\n lines.push(\"\");\n lines.push(`- **Type**: Object`);\n lines.push(`- **Key**: ${key}`);\n lines.push(`- **Size**: ${metadata.size ?? 0} bytes`);\n if (metadata.contentType) lines.push(`- **Content-Type**: ${metadata.contentType}`);\n if (metadata.storageClass) lines.push(`- **Storage Class**: ${metadata.storageClass}`);\n if (metadata.updated) lines.push(`- **Last Modified**: ${metadata.updated}`);\n if (metadata.etag) lines.push(`- **ETag**: ${metadata.etag}`);\n if (metadata.generation) lines.push(`- **Generation**: ${metadata.generation}`);\n\n return { format: \"markdown\", content: lines.join(\"\\n\") };\n }\n\n // Try as prefix (directory)\n const prefix = key.endsWith(\"/\") ? key : `${key}/`;\n const [files, , response] = await this.bucket.getFiles({\n prefix,\n delimiter: \"/\",\n maxResults: 1000,\n });\n\n const objectCount = files.length;\n const prefixCount = (response as any)?.prefixes?.length ?? 0;\n\n if (objectCount === 0 && prefixCount === 0) {\n throw new AFSNotFoundError(`/${normalizedPath}`, `Path not found: ${normalizedPath}`);\n }\n\n const lines: string[] = [];\n lines.push(`# ${normalizedPath}/`);\n lines.push(\"\");\n lines.push(`- **Type**: Prefix (directory)`);\n lines.push(`- **Prefix**: ${prefix}`);\n lines.push(`- **Objects**: ${objectCount}`);\n lines.push(`- **Sub-prefixes**: ${prefixCount}`);\n\n return { format: \"markdown\", content: lines.join(\"\\n\") };\n }\n\n // ========== Search Operations ==========\n\n @Search(\"/\")\n @Search(\"/:path*\")\n async searchHandler(\n ctx: RouteContext<{ path?: string }>,\n query: string,\n ): Promise<AFSSearchResult> {\n const { minimatch } = await import(\"minimatch\");\n const path = ctx.params.path ?? \"\";\n const normalizedPath = path.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n const prefix = normalizedPath\n ? this.options.prefix\n ? `${this.options.prefix}/${normalizedPath}/`\n : `${normalizedPath}/`\n : this.options.prefix\n ? `${this.options.prefix}/`\n : \"\";\n\n const [files] = await this.bucket.getFiles({\n prefix: prefix || undefined,\n });\n\n const results: AFSEntry[] = [];\n for (const file of files) {\n const relativePath = prefix ? file.name.slice(prefix.length) : file.name;\n if (!relativePath) continue;\n\n if (minimatch(relativePath, query)) {\n const displayPath = joinURL(\"/\", normalizedPath, relativePath);\n results.push({\n id: this.generateId(file.name),\n path: displayPath,\n meta: {\n size: file.metadata?.size ? Number(file.metadata.size) : undefined,\n contentType: file.metadata?.contentType,\n lastModified: file.metadata?.updated,\n },\n });\n }\n }\n\n return { data: results };\n }\n\n // ========== Capabilities ==========\n\n @Read(\"/.meta/.capabilities\")\n async readCapabilities(_ctx: RouteContext): Promise<AFSEntry> {\n const capabilities: CapabilitiesManifest = {\n schemaVersion: 1,\n provider: \"gcs\",\n description: `GCS bucket: ${this.options.bucket}`,\n tools: [],\n operations: this.getOperationsDeclaration(),\n actions: [\n {\n description: \"GCS object actions\",\n catalog: [\n {\n name: \"presign-download\",\n description: \"Generate a signed download URL\",\n inputSchema: {\n type: \"object\",\n properties: {\n expiresIn: {\n type: \"number\",\n description: \"Expiration in seconds (default: 3600, max: 604800)\",\n },\n },\n },\n },\n {\n name: \"presign-upload\",\n description: \"Generate a signed upload URL\",\n inputSchema: {\n type: \"object\",\n properties: {\n expiresIn: { type: \"number\", description: \"Expiration in seconds\" },\n contentType: { type: \"string\", description: \"Content-Type for upload\" },\n },\n },\n },\n {\n name: \"compose\",\n description: \"Compose multiple objects into one (max 32 sources)\",\n inputSchema: {\n type: \"object\",\n properties: {\n sources: {\n type: \"array\",\n description: \"Array of source paths (2-32)\",\n items: { type: \"string\" },\n },\n },\n required: [\"sources\"],\n },\n },\n {\n name: \"rewrite\",\n description: \"Copy/rewrite object to a new location\",\n inputSchema: {\n type: \"object\",\n properties: {\n destination: { type: \"string\", description: \"Destination path\" },\n storageClass: { type: \"string\", description: \"Target storage class\" },\n contentType: { type: \"string\", description: \"Override content type\" },\n },\n required: [\"destination\"],\n },\n },\n ],\n discovery: { pathTemplate: \"/{path}/.actions\" },\n },\n ],\n };\n\n return {\n id: \".capabilities\",\n path: \"/.meta/.capabilities\",\n content: JSON.stringify(capabilities, null, 2),\n meta: { kind: \"afs:capabilities\" },\n };\n }\n}\n\n// Type check: AFSGCS should implement AFSModuleClass\nconst _typeCheck: AFSModuleClass<AFSGCS, AFSGCSOptions> = AFSGCS;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["AFSError","files","apiResponse","response","objectCount","prefixCount","lines"],"sources":["../src/cache.ts","../src/client.ts","../src/errors.ts","../src/platform-ref.ts","../src/types.ts","../src/gcs-afs.ts"],"sourcesContent":["/**\n * GCS Response Caching\n *\n * LRU cache with TTL for GCS list and stat results.\n */\n\n/**\n * Cache entry with expiration\n */\ninterface CacheEntry<T> {\n value: T;\n expiresAt: number;\n}\n\n/**\n * LRU Cache with TTL support\n */\nexport class LRUCache<T> {\n private cache = new Map<string, CacheEntry<T>>();\n private maxSize: number;\n private defaultTtl: number;\n\n /**\n * Create a new LRU cache\n *\n * @param maxSize - Maximum number of entries (default: 1000)\n * @param defaultTtl - Default TTL in seconds (default: 60)\n */\n constructor(maxSize = 1000, defaultTtl = 60) {\n this.maxSize = maxSize;\n this.defaultTtl = defaultTtl;\n }\n\n /**\n * Get a value from the cache\n *\n * @param key - Cache key\n * @returns Cached value or undefined if not found/expired\n */\n get(key: string): T | undefined {\n const entry = this.cache.get(key);\n\n if (!entry) {\n return undefined;\n }\n\n // Check if expired\n if (Date.now() > entry.expiresAt) {\n this.cache.delete(key);\n return undefined;\n }\n\n // Move to end (most recently used)\n this.cache.delete(key);\n this.cache.set(key, entry);\n\n return entry.value;\n }\n\n /**\n * Set a value in the cache\n *\n * @param key - Cache key\n * @param value - Value to cache\n * @param ttl - TTL in seconds (optional, uses default)\n */\n set(key: string, value: T, ttl?: number): void {\n // Remove if already exists (to update position)\n if (this.cache.has(key)) {\n this.cache.delete(key);\n }\n\n // Evict oldest entries if at capacity\n while (this.cache.size >= this.maxSize) {\n const oldestKey = this.cache.keys().next().value;\n if (oldestKey) {\n this.cache.delete(oldestKey);\n }\n }\n\n const expiresAt = Date.now() + (ttl ?? this.defaultTtl) * 1000;\n this.cache.set(key, { value, expiresAt });\n }\n\n /**\n * Delete a value from the cache\n *\n * @param key - Cache key\n */\n delete(key: string): void {\n this.cache.delete(key);\n }\n\n /**\n * Delete all entries matching a prefix\n *\n * @param prefix - Key prefix to match\n */\n deleteByPrefix(prefix: string): void {\n for (const key of this.cache.keys()) {\n if (key.startsWith(prefix)) {\n this.cache.delete(key);\n }\n }\n }\n\n /**\n * Clear all entries\n */\n clear(): void {\n this.cache.clear();\n }\n\n /**\n * Get the number of entries in the cache\n */\n get size(): number {\n return this.cache.size;\n }\n\n /**\n * Prune expired entries\n */\n prune(): void {\n const now = Date.now();\n for (const [key, entry] of this.cache.entries()) {\n if (now > entry.expiresAt) {\n this.cache.delete(key);\n }\n }\n }\n}\n\n/**\n * Create a cache key from bucket, prefix, and path\n */\nexport function createCacheKey(\n bucket: string,\n prefix: string,\n path: string,\n suffix?: string,\n): string {\n const base = `${bucket}:${prefix}:${path}`;\n return suffix ? `${base}:${suffix}` : base;\n}\n","/**\n * GCS Client Factory\n *\n * Creates configured Google Cloud Storage clients.\n */\n\nimport { Storage, type StorageOptions } from \"@google-cloud/storage\";\nimport type { AFSGCSOptions } from \"./types.js\";\n\n/**\n * Create a GCS Storage client from options\n *\n * @param options - AFSGCS options\n * @returns Configured Storage client\n */\nexport function createGCSClient(options: AFSGCSOptions): Storage {\n const storageOptions: StorageOptions = {};\n\n // Project ID\n if (options.projectId) {\n storageOptions.projectId = options.projectId;\n }\n\n // Custom endpoint (for fake-gcs-server)\n if (options.endpoint) {\n storageOptions.apiEndpoint = options.endpoint;\n }\n\n // Key file authentication\n if (options.keyFilename) {\n storageOptions.keyFilename = options.keyFilename;\n }\n\n // Explicit credentials\n if (options.credentials) {\n storageOptions.credentials = {\n client_email: options.credentials.clientEmail,\n private_key: options.credentials.privateKey,\n };\n }\n\n return new Storage(storageOptions);\n}\n","/**\n * GCS Provider Error Handling\n *\n * Maps GCS SDK errors to AFS error types.\n */\n\n/**\n * AFS error codes\n */\nexport const AFSErrorCode = {\n ENTRY_NOT_FOUND: \"ENTRY_NOT_FOUND\",\n MODULE_NOT_FOUND: \"MODULE_NOT_FOUND\",\n PERMISSION_DENIED: \"PERMISSION_DENIED\",\n AUTH_ERROR: \"AUTH_ERROR\",\n RATE_LIMIT_EXCEEDED: \"RATE_LIMIT_EXCEEDED\",\n INVALID_OPERATION: \"INVALID_OPERATION\",\n ALREADY_EXISTS: \"ALREADY_EXISTS\",\n SERVICE_UNAVAILABLE: \"SERVICE_UNAVAILABLE\",\n UNKNOWN: \"UNKNOWN\",\n} as const;\n\nexport type AFSErrorCode = (typeof AFSErrorCode)[keyof typeof AFSErrorCode];\n\n/**\n * AFS Error class\n */\nexport class AFSError extends Error {\n readonly code: AFSErrorCode;\n readonly retryAfter?: number;\n\n constructor(code: AFSErrorCode, message: string, options?: { retryAfter?: number }) {\n super(message);\n this.name = \"AFSError\";\n this.code = code;\n this.retryAfter = options?.retryAfter;\n }\n}\n\n/**\n * Custom GCS error class for internal use\n */\nexport class GCSError extends Error {\n constructor(\n message: string,\n public readonly code: number,\n ) {\n super(message);\n this.name = \"GCSError\";\n }\n}\n\n/**\n * Map GCS HTTP status codes to AFS error codes\n */\nconst STATUS_TO_AFS_ERROR: Record<number, AFSErrorCode> = {\n 400: AFSErrorCode.INVALID_OPERATION,\n 401: AFSErrorCode.AUTH_ERROR,\n 403: AFSErrorCode.PERMISSION_DENIED,\n 404: AFSErrorCode.ENTRY_NOT_FOUND,\n 409: AFSErrorCode.ALREADY_EXISTS,\n 429: AFSErrorCode.RATE_LIMIT_EXCEEDED,\n 503: AFSErrorCode.SERVICE_UNAVAILABLE,\n};\n\n/**\n * Map GCS error to AFS error\n *\n * @param error - GCS SDK error or generic error\n * @returns AFSError with appropriate error code\n */\nexport function mapGCSError(error: unknown): AFSError {\n // Handle GCSError\n if (error instanceof GCSError) {\n const afsCode = STATUS_TO_AFS_ERROR[error.code] ?? AFSErrorCode.UNKNOWN;\n return new AFSError(afsCode, error.message);\n }\n\n // Handle GCS SDK ApiError format (has code property)\n if (typeof error === \"object\" && error !== null && \"code\" in error) {\n const err = error as { code: number; message?: string };\n const statusCode = typeof err.code === \"number\" ? err.code : 500;\n const message = err.message ?? \"Unknown GCS error\";\n const afsCode = STATUS_TO_AFS_ERROR[statusCode] ?? AFSErrorCode.UNKNOWN;\n return new AFSError(afsCode, message);\n }\n\n // Handle generic Error\n if (error instanceof Error) {\n return new AFSError(AFSErrorCode.UNKNOWN, error.message);\n }\n\n // Unknown error type\n return new AFSError(AFSErrorCode.UNKNOWN, String(error));\n}\n","/**\n * GCS Platform Reference\n *\n * Generates Google Cloud Console URLs for GCS objects and directories.\n */\n\n/**\n * Platform reference containing console URL\n */\nexport interface GCSPlatformRef {\n consoleUrl: string;\n}\n\n/**\n * Generate platform reference with GCP Console URL\n *\n * @param bucket - GCS bucket name\n * @param prefix - Object prefix/key (without leading slash)\n * @param isDirectory - Whether this is a directory (prefix)\n * @returns Platform reference with console URL\n */\nexport function generatePlatformRef(\n bucket: string,\n prefix: string,\n isDirectory: boolean,\n): GCSPlatformRef {\n // GCS Console URL format:\n // Objects: https://console.cloud.google.com/storage/browser/_details/{bucket}/{path}\n // Folders: https://console.cloud.google.com/storage/browser/{bucket}/{path}\n\n if (isDirectory) {\n // Directory URL\n const normalizedPrefix = prefix.endsWith(\"/\") ? prefix : prefix ? `${prefix}/` : \"\";\n return {\n consoleUrl: `https://console.cloud.google.com/storage/browser/${bucket}/${normalizedPrefix}`,\n };\n }\n\n // File URL\n const encodedPrefix = encodeURIComponent(prefix).replace(/%2F/g, \"/\");\n return {\n consoleUrl: `https://console.cloud.google.com/storage/browser/_details/${bucket}/${encodedPrefix}`,\n };\n}\n","/**\n * AFS GCS Provider Types\n */\n\nimport { camelize, optionalize } from \"@aigne/afs/utils/zod\";\nimport { z } from \"zod\";\n\n/**\n * Configuration options for AFSGCS\n */\nexport interface AFSGCSOptions {\n /** Module name (used as mount path segment) */\n name?: string;\n\n /** Module description */\n description?: string;\n\n /** GCS bucket name */\n bucket: string;\n\n /** Key prefix (optional) */\n prefix?: string;\n\n /** GCP project ID */\n projectId?: string;\n\n /** Access mode */\n accessMode?: \"readonly\" | \"readwrite\";\n\n /** Custom endpoint for GCS-compatible services (fake-gcs-server) */\n endpoint?: string;\n\n /** Path to service account key file */\n keyFilename?: string;\n\n /** Explicit credentials (for programmatic access) */\n credentials?: {\n clientEmail: string;\n privateKey: string;\n };\n\n /** Cache TTL in seconds (0 = no cache) */\n cacheTtl?: number;\n}\n\n/**\n * GCS bucket name validation regex\n * - 3-63 characters\n * - lowercase letters, numbers, hyphens, dots (but not consecutive dots)\n * - must start and end with letter or number\n */\nconst BUCKET_NAME_REGEX = /^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/;\n\n/**\n * Additional validation for bucket names\n */\nfunction isValidBucketName(name: string): boolean {\n // Check basic regex\n if (!BUCKET_NAME_REGEX.test(name)) return false;\n\n // No consecutive dots\n if (name.includes(\"..\")) return false;\n\n // No underscores\n if (name.includes(\"_\")) return false;\n\n return true;\n}\n\n/**\n * Zod schema for options validation\n */\nexport const afsgcsOptionsSchema = camelize(\n z\n .object({\n name: optionalize(z.string()),\n description: optionalize(z.string()),\n bucket: z.string().refine(isValidBucketName, \"Invalid GCS bucket name\"),\n prefix: optionalize(z.string()),\n projectId: optionalize(z.string()),\n accessMode: optionalize(z.enum([\"readonly\", \"readwrite\"])),\n endpoint: optionalize(z.string().url()),\n keyFilename: optionalize(z.string()),\n credentials: optionalize(\n z.object({\n clientEmail: z.string(),\n privateKey: z.string(),\n }),\n ),\n cacheTtl: optionalize(z.number().int().min(0)),\n })\n .strict(),\n);\n\n/**\n * Parsed GCS URI\n */\nexport interface ParsedGCSUri {\n bucket: string;\n prefix: string;\n}\n","/**\n * AFS GCS Provider\n *\n * GCS provider using AFSBaseProvider decorator routing pattern.\n * Provides access to Google Cloud Storage through AFS.\n */\n\nimport {\n Actions,\n type AFSAccessMode,\n AFSBaseProvider,\n type AFSDeleteResult,\n type AFSEntry,\n AFSError,\n type AFSExecResult,\n type AFSExplainResult,\n type AFSListResult,\n type AFSModuleClass,\n type AFSModuleLoadParams,\n AFSNotFoundError,\n type AFSSearchResult,\n type AFSStatResult,\n type AFSWriteEntryPayload,\n type AFSWriteResult,\n type CapabilitiesManifest,\n Delete,\n Explain,\n List,\n Meta,\n type ProviderManifest,\n type ProviderTreeSchema,\n Read,\n type RouteContext,\n Search,\n Stat,\n Write,\n} from \"@aigne/afs\";\nimport { zodParse } from \"@aigne/afs/utils/zod\";\nimport type { Bucket, Storage } from \"@google-cloud/storage\";\nimport { joinURL } from \"ufo\";\nimport { z } from \"zod\";\nimport { createCacheKey, LRUCache } from \"./cache.js\";\nimport { createGCSClient } from \"./client.js\";\nimport { mapGCSError } from \"./errors.js\";\nimport { generatePlatformRef } from \"./platform-ref.js\";\nimport { type AFSGCSOptions, afsgcsOptionsSchema } from \"./types.js\";\n\n/**\n * Default URL expiration time (1 hour)\n */\nconst DEFAULT_EXPIRES_IN = 3600;\n\n/**\n * Maximum expiration time (7 days)\n */\nconst MAX_EXPIRES_IN = 604800;\n\n/**\n * Maximum sources for compose operation\n */\nconst MAX_COMPOSE_SOURCES = 32;\n\n/**\n * AFSGCS Provider using Base Provider pattern\n *\n * Provides access to Google Cloud Storage through AFS.\n * Uses decorator routing (@List, @Read, @Write, @Delete, @Meta, @Actions).\n *\n * @example\n * ```typescript\n * const gcs = new AFSGCS({\n * bucket: \"my-bucket\",\n * prefix: \"data\",\n * projectId: \"my-project\",\n * });\n *\n * // Mount to AFS\n * afs.mount(gcs);\n *\n * // List objects\n * const result = await afs.list(\"/modules/my-bucket/data\");\n *\n * // Read object\n * const content = await afs.read(\"/modules/my-bucket/data/file.json\");\n * ```\n */\nexport class AFSGCS extends AFSBaseProvider {\n override readonly name: string;\n override readonly description?: string;\n override readonly accessMode: AFSAccessMode;\n\n private options: Required<Pick<AFSGCSOptions, \"bucket\">> & AFSGCSOptions;\n private storage: Storage;\n private bucket: Bucket;\n private listCache?: LRUCache<AFSListResult>;\n private statCache?: LRUCache<AFSEntry>;\n\n constructor(options: AFSGCSOptions & { uri?: string; token?: string; auth?: unknown }) {\n super();\n\n // Strip registry-injected keys before strict schema validation\n const { uri: _uri, token: _token, auth: _auth, ...cleanOptions } = options as any;\n\n // Validate options\n const parsed = afsgcsOptionsSchema.parse(cleanOptions);\n\n this.options = {\n ...parsed,\n bucket: parsed.bucket,\n prefix: parsed.prefix ?? \"\",\n accessMode: parsed.accessMode ?? \"readonly\",\n };\n\n this.name = parsed.name ?? parsed.bucket;\n this.description = parsed.description ?? `GCS bucket: ${parsed.bucket}`;\n this.accessMode = this.options.accessMode ?? \"readonly\";\n\n // Create GCS client\n this.storage = createGCSClient(this.options);\n this.bucket = this.storage.bucket(parsed.bucket);\n\n // Initialize caches if cacheTtl is set\n if (parsed.cacheTtl && parsed.cacheTtl > 0) {\n this.listCache = new LRUCache<AFSListResult>(1000, parsed.cacheTtl);\n this.statCache = new LRUCache<AFSEntry>(5000, parsed.cacheTtl);\n }\n }\n\n /**\n * Schema for configuration validation\n */\n static schema() {\n return afsgcsOptionsSchema;\n }\n\n /**\n * Provider manifest for URI-based discovery\n */\n static manifest(): ProviderManifest {\n return {\n name: \"gcs\",\n description:\n \"Google Cloud Storage bucket.\\n- Browse, read, write, and delete objects; search by key prefix\\n- Exec actions: `presign-download`, `presign-upload`, `compose` (concatenate objects), `rewrite` (copy with transform)\\n- Path structure: `/{key-prefix}/{object-key}`\",\n uriTemplate: \"gcs://{bucket}/{prefix+?}\",\n category: \"storage\",\n schema: z.object({\n bucket: z.string(),\n prefix: z.string().optional(),\n projectId: z.string().optional(),\n keyFilename: z.string().optional(),\n }),\n tags: [\"gcp\", \"gcs\", \"cloud\", \"storage\"],\n capabilityTags: [\"read-write\", \"crud\", \"search\", \"auth:gcp\", \"remote\", \"cloud\", \"http\"],\n security: {\n riskLevel: \"external\",\n resourceAccess: [\"cloud-api\"],\n requires: [\"cloud-credentials\"],\n dataSensitivity: [\"credentials\"],\n },\n capabilities: {\n network: { egress: true, allowedDomains: [\"*.googleapis.com\"] },\n secrets: [\"gcp/credentials\"],\n },\n };\n }\n\n /**\n * Tree schema for progressive disclosure\n */\n static treeSchema(): ProviderTreeSchema {\n return {\n operations: [\"list\", \"read\", \"write\", \"delete\", \"search\", \"exec\", \"stat\", \"explain\"],\n tree: {\n \"/\": { kind: \"storage:bucket\", operations: [\"list\", \"read\", \"search\"] },\n \"/{prefix}/\": { kind: \"storage:prefix\", operations: [\"list\", \"read\"] },\n \"/{key}\": {\n kind: \"storage:object\",\n operations: [\"read\", \"write\", \"delete\"],\n actions: [\"presign-download\", \"presign-upload\", \"compose\", \"rewrite\"],\n },\n \"/{key}/@versions\": { kind: \"storage:version-list\", operations: [\"list\"] },\n \"/{key}/@versions/{generation}\": { kind: \"storage:version\", operations: [\"read\"] },\n },\n auth: {\n type: \"gcp\",\n env: [\"GOOGLE_APPLICATION_CREDENTIALS\"],\n },\n bestFor: [\"object storage\", \"static assets\", \"data lake\"],\n notFor: [\"relational queries\", \"real-time sync\"],\n };\n }\n\n /**\n * Load from configuration file\n */\n static async load({ basePath, config }: AFSModuleLoadParams = {}): Promise<AFSGCS> {\n const options = zodParse(afsgcsOptionsSchema, config, { prefix: basePath });\n return new AFSGCS(options);\n }\n\n // ========== Helper Methods ==========\n\n /**\n * Build the full GCS key from a path\n */\n private buildGCSKey(path: string): string {\n const normalizedPath = path.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n return this.options.prefix ? `${this.options.prefix}/${normalizedPath}` : normalizedPath;\n }\n\n /**\n * Generate a unique ID for a GCS object\n */\n private generateId(key: string): string {\n const cleanKey = key.replace(/^\\/+/, \"\");\n return `gcs://${this.options.bucket}/${cleanKey}`;\n }\n\n /**\n * Invalidate caches for a given path\n */\n private invalidateCache(path: string): void {\n if (this.statCache) {\n const statKey = createCacheKey(this.options.bucket, this.options.prefix ?? \"\", path);\n this.statCache.delete(statKey);\n }\n\n if (this.listCache) {\n // Invalidate list cache for parent directory\n const parentPath = path.split(\"/\").slice(0, -1).join(\"/\") || \"/\";\n const listPrefix = createCacheKey(this.options.bucket, this.options.prefix ?? \"\", parentPath);\n this.listCache.deleteByPrefix(listPrefix);\n }\n }\n\n /**\n * Clear all caches\n */\n clearCache(): void {\n this.listCache?.clear();\n this.statCache?.clear();\n }\n\n // ========== List Operations ==========\n\n @List(\"/\")\n @List(\"/:path*\")\n async listHandler(ctx: RouteContext<{ path?: string }>): Promise<AFSListResult> {\n try {\n const path = ctx.params.path ?? \"\";\n const normalizedPath = path.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n\n // Build the full GCS prefix\n const fullPrefix = this.options.prefix\n ? normalizedPath\n ? `${this.options.prefix}/${normalizedPath}/`\n : `${this.options.prefix}/`\n : normalizedPath\n ? `${normalizedPath}/`\n : \"\";\n\n const opts = ctx.options as { limit?: number; maxChildren?: number } | undefined;\n const maxChildren = opts?.limit ?? opts?.maxChildren ?? 1000;\n\n // Check cache first\n if (this.listCache) {\n const cacheKey = createCacheKey(\n this.options.bucket,\n this.options.prefix ?? \"\",\n normalizedPath,\n JSON.stringify(ctx.options ?? {}),\n );\n const cached = this.listCache.get(cacheKey);\n if (cached) {\n return cached;\n }\n }\n\n const result = await this.listWithDelimiter(fullPrefix, normalizedPath, maxChildren);\n\n // Cache the result\n if (this.listCache) {\n const cacheKey = createCacheKey(\n this.options.bucket,\n this.options.prefix ?? \"\",\n normalizedPath,\n JSON.stringify(ctx.options ?? {}),\n );\n this.listCache.set(cacheKey, result);\n\n // Also populate stat cache from list results\n if (this.statCache) {\n for (const entry of result.data) {\n const statKey = createCacheKey(\n this.options.bucket,\n this.options.prefix ?? \"\",\n entry.path,\n );\n this.statCache.set(statKey, entry);\n }\n }\n }\n\n return result;\n } catch (error) {\n if (error instanceof AFSNotFoundError) {\n throw error;\n }\n throw mapGCSError(error);\n }\n }\n\n /**\n * List with delimiter (single level)\n */\n private async listWithDelimiter(\n prefix: string,\n basePath: string,\n maxChildren: number,\n ): Promise<AFSListResult> {\n const childEntries: AFSEntry[] = [];\n const bucketName = this.options.bucket;\n\n const [files, , apiResponse] = await this.bucket.getFiles({\n prefix,\n delimiter: \"/\",\n maxResults: maxChildren,\n });\n\n // Add directories from prefixes\n const prefixes = (apiResponse as Record<string, unknown>)?.prefixes as string[] | undefined;\n if (prefixes) {\n for (const dirPrefix of prefixes) {\n if (!dirPrefix) continue;\n\n // Extract directory name\n const dirName = dirPrefix.slice(prefix.length).replace(/\\/$/, \"\");\n if (!dirName) continue;\n\n childEntries.push({\n id: this.generateId(dirPrefix),\n path: joinURL(\"/\", basePath, dirName),\n meta: {\n kind: \"afs:node\",\n childrenCount: -1,\n platformRef: generatePlatformRef(bucketName, dirPrefix, true),\n },\n });\n\n if (childEntries.length >= maxChildren) break;\n }\n }\n\n // Add files from Contents\n for (const file of files) {\n if (!file.name) continue;\n\n // Skip the prefix itself (if it's a \"directory marker\")\n if (file.name === prefix) continue;\n\n // Handle directory markers (ending with /)\n if (file.name.endsWith(\"/\")) {\n const dirName = file.name.slice(prefix.length).replace(/\\/$/, \"\");\n if (!dirName) continue;\n\n childEntries.push({\n id: this.generateId(file.name),\n path: joinURL(\"/\", basePath, dirName),\n updatedAt: file.metadata.updated ? new Date(file.metadata.updated as string) : undefined,\n meta: {\n kind: \"afs:node\",\n childrenCount: -1,\n platformRef: generatePlatformRef(bucketName, file.name, true),\n },\n });\n\n if (childEntries.length >= maxChildren) break;\n continue;\n }\n\n // Extract file name\n const fileName = file.name.slice(prefix.length);\n if (!fileName || fileName.includes(\"/\")) continue;\n\n childEntries.push({\n id: this.generateId(file.name),\n path: joinURL(\"/\", basePath, fileName),\n updatedAt: file.metadata.updated ? new Date(file.metadata.updated as string) : undefined,\n meta: {\n size: file.metadata.size ? Number(file.metadata.size) : undefined,\n contentType: file.metadata.contentType,\n lastModified: file.metadata.updated,\n etag: file.metadata.etag,\n storageClass: file.metadata.storageClass,\n platformRef: generatePlatformRef(bucketName, file.name, false),\n },\n });\n\n if (childEntries.length >= maxChildren) break;\n }\n\n const selfPath = basePath ? (basePath.startsWith(\"/\") ? basePath : `/${basePath}`) : \"/\";\n\n // For non-root paths with no children, check if the path exists\n if (childEntries.length === 0 && basePath) {\n // Check if this path exists as a file\n const key = this.options.prefix ? `${this.options.prefix}/${basePath}` : basePath;\n const file = this.bucket.file(key);\n const [fileExists] = await file.exists();\n\n if (fileExists) {\n // Path exists as an object (file), not a directory - return empty children\n return { data: [] };\n }\n\n // Check for directory marker\n const dirMarker = this.bucket.file(`${key}/`);\n const [dirExists] = await dirMarker.exists();\n\n if (!dirExists) {\n // Neither file nor directory marker exists\n throw new AFSNotFoundError(selfPath);\n }\n }\n\n return { data: childEntries };\n }\n\n // ========== Versioning List ==========\n\n @List(\"/:path*/@versions\")\n async listVersionsHandler(ctx: RouteContext<{ path: string }>): Promise<AFSListResult> {\n try {\n const normalizedPath = ctx.params.path.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n const key = this.options.prefix ? `${this.options.prefix}/${normalizedPath}` : normalizedPath;\n\n // Get all generations of the file\n const [files] = await this.bucket.getFiles({\n prefix: key,\n versions: true,\n });\n\n const entries: AFSEntry[] = [];\n\n for (const versionFile of files) {\n // Only include exact key matches\n if (versionFile.name !== key) continue;\n\n const generation = versionFile.metadata.generation;\n if (!generation) continue;\n\n const versionPath = joinURL(\"/\", normalizedPath, \"@versions\", String(generation));\n const isLive = !versionFile.metadata.timeDeleted;\n\n entries.push({\n id: `${this.generateId(key)}:${generation}`,\n path: versionPath,\n updatedAt: versionFile.metadata.timeCreated\n ? new Date(versionFile.metadata.timeCreated as string)\n : undefined,\n meta: {\n generation: generation,\n isLive,\n timeCreated: versionFile.metadata.timeCreated,\n size: versionFile.metadata.size ? Number(versionFile.metadata.size) : 0,\n etag: versionFile.metadata.etag,\n },\n });\n }\n\n return { data: entries };\n } catch (error) {\n throw mapGCSError(error);\n }\n }\n\n // ========== Read Operations ==========\n\n @Read(\"/:path*\")\n async readHandler(ctx: RouteContext<{ path: string }>): Promise<AFSEntry> {\n try {\n const key = this.buildGCSKey(ctx.params.path);\n const normalizedOutputPath = ctx.path.startsWith(\"/\") ? ctx.path : `/${ctx.path}`;\n const bucketName = this.options.bucket;\n\n // Handle root path - return bucket metadata with childrenCount\n if (!key) {\n const [files, , apiResponse] = await this.bucket.getFiles({\n prefix: this.options.prefix ? `${this.options.prefix}/` : \"\",\n delimiter: \"/\",\n maxResults: 1000,\n });\n const prefixes = (apiResponse as Record<string, unknown>)?.prefixes as string[] | undefined;\n const childrenCount = (prefixes?.length ?? 0) + files.length;\n\n return {\n id: this.generateId(\"/\"),\n path: \"/\",\n content: \"\",\n meta: {\n kind: \"afs:node\",\n childrenCount,\n platformRef: generatePlatformRef(bucketName, \"\", true),\n },\n };\n }\n\n const file = this.bucket.file(key);\n\n // Check if file exists\n const [exists] = await file.exists();\n\n if (exists) {\n const [metadata] = await file.getMetadata();\n\n // Check if this is a directory marker\n if (key.endsWith(\"/\") || metadata.contentType === \"application/x-directory\") {\n // Return directory info instead of throwing\n return {\n id: this.generateId(key),\n path: normalizedOutputPath,\n content: \"\",\n updatedAt: metadata.updated ? new Date(metadata.updated as string) : undefined,\n meta: {\n kind: \"afs:node\",\n childrenCount: -1,\n platformRef: generatePlatformRef(bucketName, key, true),\n },\n };\n }\n\n // Download content\n const [content] = await file.download();\n\n return {\n id: this.generateId(key),\n path: normalizedOutputPath,\n content: content.toString(\"utf-8\"),\n updatedAt: metadata.updated ? new Date(metadata.updated as string) : undefined,\n meta: {\n size: metadata.size ? Number(metadata.size) : undefined,\n mimeType: metadata.contentType,\n contentType: metadata.contentType,\n lastModified: metadata.updated,\n etag: metadata.etag,\n },\n };\n }\n\n // File doesn't exist, check if it's a directory prefix\n const [files, , apiResponse] = await this.bucket.getFiles({\n prefix: `${key}/`,\n delimiter: \"/\",\n maxResults: 1000,\n });\n const prefixes = (apiResponse as Record<string, unknown>)?.prefixes as string[] | undefined;\n const hasChildren = files.length > 0 || (prefixes && prefixes.length > 0);\n\n if (hasChildren) {\n // It's a directory - return directory info\n const childrenCount = (prefixes?.length ?? 0) + files.length;\n return {\n id: this.generateId(`${key}/`),\n path: normalizedOutputPath,\n content: \"\",\n meta: {\n kind: \"afs:node\",\n childrenCount,\n platformRef: generatePlatformRef(bucketName, key, true),\n },\n };\n }\n\n // Also check for directory marker (key ending with /)\n const dirMarker = this.bucket.file(`${key}/`);\n const [dirExists] = await dirMarker.exists();\n\n if (dirExists) {\n const [dirMetadata] = await dirMarker.getMetadata();\n return {\n id: this.generateId(`${key}/`),\n path: normalizedOutputPath,\n content: \"\",\n updatedAt: dirMetadata.updated ? new Date(dirMetadata.updated as string) : undefined,\n meta: {\n kind: \"afs:node\",\n childrenCount: -1,\n platformRef: generatePlatformRef(bucketName, key, true),\n },\n };\n }\n\n // Neither file nor directory exists\n throw new AFSNotFoundError(`/${ctx.params.path}`);\n } catch (error) {\n if (error instanceof AFSError || error instanceof AFSNotFoundError) {\n throw error;\n }\n throw mapGCSError(error);\n }\n }\n\n // ========== Version Read ==========\n\n @Read(\"/:path*/@versions/:generation\")\n async readVersionHandler(\n ctx: RouteContext<{ path: string; generation: string }>,\n ): Promise<AFSEntry> {\n try {\n const normalizedPath = ctx.params.path.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n const key = this.options.prefix ? `${this.options.prefix}/${normalizedPath}` : normalizedPath;\n const generation = ctx.params.generation;\n\n const file = this.bucket.file(key, { generation: parseInt(generation, 10) });\n\n // Check if version exists\n const [exists] = await file.exists();\n if (!exists) {\n throw new AFSNotFoundError(`/${normalizedPath}/@versions/${generation}`);\n }\n\n const [content] = await file.download();\n const [metadata] = await file.getMetadata();\n\n return {\n id: `${this.generateId(key)}:${generation}`,\n path: ctx.path,\n content: content.toString(\"utf-8\"),\n updatedAt: metadata.timeCreated ? new Date(metadata.timeCreated as string) : undefined,\n meta: {\n size: metadata.size ? Number(metadata.size) : undefined,\n contentType: metadata.contentType,\n timeCreated: metadata.timeCreated,\n etag: metadata.etag,\n generation: metadata.generation,\n },\n };\n } catch (error) {\n if (error instanceof AFSNotFoundError) {\n throw error;\n }\n throw mapGCSError(error);\n }\n }\n\n // ========== Meta Operations ==========\n\n @Meta(\"/\")\n @Meta(\"/:path*\")\n async metaHandler(ctx: RouteContext<{ path?: string }>): Promise<AFSEntry> {\n try {\n const path = ctx.params.path ?? \"\";\n const normalizedPath = path.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n const key = this.options.prefix\n ? normalizedPath\n ? `${this.options.prefix}/${normalizedPath}`\n : this.options.prefix\n : normalizedPath;\n\n const bucketName = this.options.bucket;\n\n // Root metadata\n if (!key) {\n const [files, , apiResponse] = await this.bucket.getFiles({\n prefix: this.options.prefix ? `${this.options.prefix}/` : \"\",\n delimiter: \"/\",\n maxResults: 1000,\n });\n const prefixes = (apiResponse as Record<string, unknown>)?.prefixes as string[] | undefined;\n const childrenCount = (prefixes?.length ?? 0) + files.length;\n\n return {\n id: this.generateId(\"/\"),\n path: \"/.meta\",\n meta: {\n kind: \"afs:node\",\n childrenCount,\n platformRef: generatePlatformRef(bucketName, \"\", true),\n },\n };\n }\n\n // Check cache first\n if (this.statCache) {\n const cacheKey = createCacheKey(bucketName, this.options.prefix ?? \"\", path);\n const cached = this.statCache.get(cacheKey);\n if (cached) {\n return {\n id: cached.id,\n path: ctx.path,\n meta: cached.meta,\n };\n }\n }\n\n // Try to get the object directly (file case)\n const file = this.bucket.file(key);\n const [exists] = await file.exists();\n\n if (exists) {\n const [metadata] = await file.getMetadata();\n\n // Check if this is a directory marker\n if (key.endsWith(\"/\") || metadata.contentType === \"application/x-directory\") {\n return {\n id: this.generateId(key),\n path: ctx.path,\n updatedAt: metadata.updated ? new Date(metadata.updated as string) : undefined,\n meta: {\n kind: \"afs:node\",\n childrenCount: -1,\n platformRef: generatePlatformRef(bucketName, key, true),\n },\n };\n }\n\n const result = {\n id: this.generateId(key),\n path: ctx.path,\n updatedAt: metadata.updated ? new Date(metadata.updated as string) : undefined,\n meta: {\n kind: \"afs:document\",\n size: metadata.size ? Number(metadata.size) : undefined,\n contentType: metadata.contentType,\n lastModified: metadata.updated,\n etag: metadata.etag,\n storageClass: metadata.storageClass,\n // GCS-specific fields\n generation: metadata.generation,\n metageneration: metadata.metageneration,\n crc32c: metadata.crc32c,\n md5Hash: metadata.md5Hash,\n platformRef: generatePlatformRef(bucketName, key, false),\n },\n };\n\n // Cache the result\n if (this.statCache) {\n const cacheKey = createCacheKey(bucketName, this.options.prefix ?? \"\", path);\n this.statCache.set(cacheKey, result);\n }\n\n return result;\n }\n\n // File doesn't exist, check if it's a directory prefix\n const [files] = await this.bucket.getFiles({\n prefix: `${key}/`,\n maxResults: 1,\n });\n\n if (files.length > 0) {\n // There are objects under this prefix, so it's a directory\n return {\n id: this.generateId(`${key}/`),\n path: ctx.path,\n meta: {\n kind: \"afs:node\",\n childrenCount: -1,\n platformRef: generatePlatformRef(bucketName, key, true),\n },\n };\n }\n\n // Also check for directory marker (key ending with /)\n const dirMarker = this.bucket.file(`${key}/`);\n const [dirExists] = await dirMarker.exists();\n\n if (dirExists) {\n const [dirMetadata] = await dirMarker.getMetadata();\n return {\n id: this.generateId(`${key}/`),\n path: ctx.path,\n updatedAt: dirMetadata.updated ? new Date(dirMetadata.updated as string) : undefined,\n meta: {\n kind: \"afs:node\",\n childrenCount: -1,\n platformRef: generatePlatformRef(bucketName, key, true),\n },\n };\n }\n\n // Neither file nor directory exists\n throw new AFSNotFoundError(path.startsWith(\"/\") ? path : `/${path}`);\n } catch (error) {\n if (error instanceof AFSNotFoundError) {\n throw error;\n }\n throw mapGCSError(error);\n }\n }\n\n // ========== Stat Operations ==========\n\n @Stat(\"/\")\n @Stat(\"/:path*\")\n async statHandler(ctx: RouteContext<{ path?: string }>): Promise<AFSStatResult> {\n // Delegate to meta handler and convert to stat result\n const metaEntry = await this.metaHandler({\n ...ctx,\n path: ctx.path.endsWith(\"/.meta\") ? ctx.path : `${ctx.path}/.meta`,\n });\n\n // Extract id from path\n const pathSegments = ctx.path.split(\"/\").filter(Boolean);\n const id = pathSegments.length > 0 ? (pathSegments[pathSegments.length - 1] as string) : \"/\";\n\n return {\n data: {\n id,\n path: ctx.path,\n meta: metaEntry.meta as Record<string, unknown>,\n },\n };\n }\n\n // ========== Write Operations ==========\n\n @Write(\"/:path*\")\n async writeHandler(\n ctx: RouteContext<{ path: string }>,\n payload: AFSWriteEntryPayload,\n ): Promise<AFSWriteResult> {\n try {\n const key = this.buildGCSKey(ctx.params.path);\n const file = this.bucket.file(key);\n\n // Prepare content\n let content: string | Buffer;\n if (typeof payload.content === \"string\") {\n content = payload.content;\n } else if (Buffer.isBuffer(payload.content)) {\n content = payload.content;\n } else if (payload.content !== undefined) {\n // JSON content\n content = JSON.stringify(payload.content);\n } else {\n content = \"\";\n }\n\n // Prepare save options\n // Disable validation for fake-gcs-server compatibility (it doesn't properly support CRC32C)\n const saveOptions: {\n contentType?: string;\n metadata?: Record<string, string>;\n validation?: boolean;\n } = {\n validation: false,\n };\n if (payload.meta?.mimeType || payload.meta?.contentType) {\n saveOptions.contentType =\n (payload.meta.mimeType as string) ?? (payload.meta.contentType as string);\n }\n\n // Write content\n await file.save(content, saveOptions);\n\n // Get updated metadata\n const [metadata] = await file.getMetadata();\n\n const normalizedOutputPath = ctx.path.startsWith(\"/\") ? ctx.path : `/${ctx.path}`;\n\n // Invalidate caches for the written path\n this.invalidateCache(ctx.params.path);\n\n return {\n data: {\n id: this.generateId(key),\n path: normalizedOutputPath,\n content: payload.content,\n updatedAt: metadata.updated ? new Date(metadata.updated as string) : new Date(),\n meta: {\n size: metadata.size ? Number(metadata.size) : 0,\n etag: metadata.etag,\n generation: metadata.generation,\n ...payload.meta,\n },\n },\n };\n } catch (error) {\n throw mapGCSError(error);\n }\n }\n\n // ========== Delete Operations ==========\n\n @Delete(\"/:path*\")\n async deleteHandler(ctx: RouteContext<{ path: string }>): Promise<AFSDeleteResult> {\n try {\n const key = this.buildGCSKey(ctx.params.path);\n const file = this.bucket.file(key);\n const [exists] = await file.exists();\n\n if (exists) {\n // It's a file, delete it directly\n await file.delete();\n\n // Invalidate caches for the deleted path\n this.invalidateCache(ctx.params.path);\n\n return {\n message: `Successfully deleted: ${ctx.params.path}`,\n };\n }\n\n // Check if it's a directory (has children)\n const [files] = await this.bucket.getFiles({\n prefix: `${key}/`,\n maxResults: 1,\n });\n\n if (files.length === 0) {\n throw new AFSNotFoundError(`/${ctx.params.path}`);\n }\n\n // Directory with children - need recursive option\n throw new AFSError(\n `Cannot delete non-empty directory: ${ctx.params.path}. Use recursive option.`,\n \"AFS_INVALID_OPERATION\",\n );\n } catch (error) {\n if (error instanceof AFSError || error instanceof AFSNotFoundError) {\n throw error;\n }\n throw mapGCSError(error);\n }\n }\n\n // ========== Action System ==========\n\n @Actions(\"/:path*\")\n async listActionsHandler(ctx: RouteContext<{ path: string }>): Promise<AFSListResult> {\n return {\n data: [\n {\n id: \"presign-download\",\n path: joinURL(ctx.path, \"presign-download\"),\n summary: \"Generate signed download URL\",\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n inputSchema: {\n type: \"object\",\n properties: {\n expiresIn: {\n type: \"number\",\n description: \"Expiration in seconds (default: 3600, max: 604800)\",\n },\n },\n },\n },\n },\n {\n id: \"presign-upload\",\n path: joinURL(ctx.path, \"presign-upload\"),\n summary: \"Generate signed upload URL\",\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n inputSchema: {\n type: \"object\",\n properties: {\n expiresIn: { type: \"number\", description: \"Expiration in seconds\" },\n contentType: { type: \"string\", description: \"Content-Type for upload\" },\n },\n },\n },\n },\n {\n id: \"compose\",\n path: joinURL(ctx.path, \"compose\"),\n summary: \"Compose multiple objects into one\",\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n inputSchema: {\n type: \"object\",\n properties: {\n sources: {\n type: \"array\",\n description: \"Array of source paths (2-32)\",\n items: { type: \"string\" },\n },\n },\n required: [\"sources\"],\n },\n },\n },\n {\n id: \"rewrite\",\n path: joinURL(ctx.path, \"rewrite\"),\n summary: \"Rewrite object to new location\",\n meta: {\n kind: \"afs:executable\",\n kinds: [\"afs:executable\", \"afs:node\"],\n inputSchema: {\n type: \"object\",\n properties: {\n destination: { type: \"string\", description: \"Destination path\" },\n storageClass: { type: \"string\", description: \"Target storage class\" },\n contentType: { type: \"string\", description: \"Override content type\" },\n },\n required: [\"destination\"],\n },\n },\n },\n ],\n };\n }\n\n @Actions.Exec(\"/:path*\", \"presign-download\")\n async signDownloadActionHandler(\n ctx: RouteContext<{ path: string }>,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const normalizedPath = ctx.params.path.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n const key = this.options.prefix ? `${this.options.prefix}/${normalizedPath}` : normalizedPath;\n const file = this.bucket.file(key);\n\n let expiresIn = (args.expiresIn as number) ?? DEFAULT_EXPIRES_IN;\n if (expiresIn > MAX_EXPIRES_IN) expiresIn = MAX_EXPIRES_IN;\n if (expiresIn < 1) expiresIn = 1;\n\n const expiresAt = Date.now() + expiresIn * 1000;\n\n const [url] = await file.getSignedUrl({\n action: \"read\",\n expires: expiresAt,\n });\n\n return {\n success: true,\n data: {\n url,\n expiresAt: new Date(expiresAt).toISOString(),\n },\n };\n }\n\n @Actions.Exec(\"/:path*\", \"presign-upload\")\n async signUploadActionHandler(\n ctx: RouteContext<{ path: string }>,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const normalizedPath = ctx.params.path.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n const key = this.options.prefix ? `${this.options.prefix}/${normalizedPath}` : normalizedPath;\n const file = this.bucket.file(key);\n\n let expiresIn = (args.expiresIn as number) ?? DEFAULT_EXPIRES_IN;\n if (expiresIn > MAX_EXPIRES_IN) expiresIn = MAX_EXPIRES_IN;\n if (expiresIn < 1) expiresIn = 1;\n\n const expiresAt = Date.now() + expiresIn * 1000;\n const contentType = (args.contentType as string) ?? \"application/octet-stream\";\n\n const [url] = await file.getSignedUrl({\n action: \"write\",\n expires: expiresAt,\n contentType,\n });\n\n return {\n success: true,\n data: {\n url,\n expiresAt: new Date(expiresAt).toISOString(),\n },\n };\n }\n\n @Actions.Exec(\"/:path*\", \"compose\")\n async composeActionHandler(\n ctx: RouteContext<{ path: string }>,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const normalizedPath = ctx.params.path.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n const destinationKey = this.options.prefix\n ? `${this.options.prefix}/${normalizedPath}`\n : normalizedPath;\n\n const sources = args.sources as string[];\n if (!sources || !Array.isArray(sources) || sources.length < 2) {\n throw new AFSError(\"compose requires at least 2 source objects\", \"AFS_INVALID_ARGUMENT\");\n }\n\n if (sources.length > MAX_COMPOSE_SOURCES) {\n throw new AFSError(\n `compose supports maximum ${MAX_COMPOSE_SOURCES} sources`,\n \"AFS_INVALID_ARGUMENT\",\n );\n }\n\n // Build source file references\n const sourceFiles = sources.map((source) => {\n const sourcePath = source.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n const sourceKey = this.options.prefix ? `${this.options.prefix}/${sourcePath}` : sourcePath;\n return this.bucket.file(sourceKey);\n });\n\n const destinationFile = this.bucket.file(destinationKey);\n\n // Compose the files using bucket.combine()\n await this.bucket.combine(sourceFiles, destinationFile);\n\n // Get metadata of the composed file\n const [metadata] = await destinationFile.getMetadata();\n\n // Invalidate cache for destination\n this.invalidateCache(ctx.params.path);\n\n return {\n success: true,\n data: {\n generation: metadata.generation,\n size: metadata.size ? Number(metadata.size) : 0,\n etag: metadata.etag,\n },\n };\n }\n\n @Actions.Exec(\"/:path*\", \"rewrite\")\n async rewriteActionHandler(\n ctx: RouteContext<{ path: string }>,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const normalizedPath = ctx.params.path.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n const sourceKey = this.options.prefix\n ? `${this.options.prefix}/${normalizedPath}`\n : normalizedPath;\n\n const destination = args.destination as string;\n if (!destination) {\n throw new AFSError(\"rewrite requires destination path\", \"AFS_INVALID_ARGUMENT\");\n }\n\n const destPath = destination.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n const destKey = this.options.prefix ? `${this.options.prefix}/${destPath}` : destPath;\n\n const sourceFile = this.bucket.file(sourceKey);\n const destFile = this.bucket.file(destKey);\n\n // Copy options\n const copyOptions: { contentType?: string; metadata?: Record<string, string> } = {};\n if (args.storageClass) {\n copyOptions.metadata = { storageClass: args.storageClass as string };\n }\n if (args.contentType) {\n copyOptions.contentType = args.contentType as string;\n }\n\n // Copy (rewrite) the file\n await sourceFile.copy(destFile, copyOptions);\n\n // Get metadata of the new file\n const [metadata] = await destFile.getMetadata();\n\n // Invalidate cache for destination\n this.invalidateCache(destPath);\n\n return {\n success: true,\n data: {\n destination: `/${destPath}`,\n generation: metadata.generation,\n size: metadata.size ? Number(metadata.size) : 0,\n etag: metadata.etag,\n storageClass: metadata.storageClass,\n },\n };\n }\n\n // ========== Explain Operations ==========\n\n @Explain(\"/\")\n @Explain(\"/:path*\")\n async explainHandler(ctx: RouteContext<{ path?: string }>): Promise<AFSExplainResult> {\n const normalizedPath = (ctx.params.path ?? \"\").replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n\n // Root explain\n if (!normalizedPath) {\n const [files, , response] = await this.bucket.getFiles({\n prefix: this.options.prefix ? `${this.options.prefix}/` : undefined,\n delimiter: \"/\",\n maxResults: 1000,\n });\n\n const objectCount = files.length;\n const prefixCount = (response as any)?.prefixes?.length ?? 0;\n\n const lines: string[] = [];\n lines.push(`# ${this.options.bucket}`);\n lines.push(\"\");\n lines.push(`- **Type**: GCS Bucket`);\n lines.push(`- **Bucket**: ${this.options.bucket}`);\n if (this.options.prefix) {\n lines.push(`- **Prefix**: ${this.options.prefix}`);\n }\n if (this.options.projectId) {\n lines.push(`- **Project**: ${this.options.projectId}`);\n }\n lines.push(`- **Access Mode**: ${this.accessMode}`);\n lines.push(`- **Top-level Objects**: ${objectCount}`);\n lines.push(`- **Top-level Prefixes**: ${prefixCount}`);\n\n return { format: \"markdown\", content: lines.join(\"\\n\") };\n }\n\n const key = this.buildGCSKey(normalizedPath);\n\n // Try as object first\n const file = this.bucket.file(key);\n const [exists] = await file.exists();\n\n if (exists) {\n const [metadata] = await file.getMetadata();\n\n const lines: string[] = [];\n lines.push(`# ${normalizedPath}`);\n lines.push(\"\");\n lines.push(`- **Type**: Object`);\n lines.push(`- **Key**: ${key}`);\n lines.push(`- **Size**: ${metadata.size ?? 0} bytes`);\n if (metadata.contentType) lines.push(`- **Content-Type**: ${metadata.contentType}`);\n if (metadata.storageClass) lines.push(`- **Storage Class**: ${metadata.storageClass}`);\n if (metadata.updated) lines.push(`- **Last Modified**: ${metadata.updated}`);\n if (metadata.etag) lines.push(`- **ETag**: ${metadata.etag}`);\n if (metadata.generation) lines.push(`- **Generation**: ${metadata.generation}`);\n\n return { format: \"markdown\", content: lines.join(\"\\n\") };\n }\n\n // Try as prefix (directory)\n const prefix = key.endsWith(\"/\") ? key : `${key}/`;\n const [files, , response] = await this.bucket.getFiles({\n prefix,\n delimiter: \"/\",\n maxResults: 1000,\n });\n\n const objectCount = files.length;\n const prefixCount = (response as any)?.prefixes?.length ?? 0;\n\n if (objectCount === 0 && prefixCount === 0) {\n throw new AFSNotFoundError(`/${normalizedPath}`, `Path not found: ${normalizedPath}`);\n }\n\n const lines: string[] = [];\n lines.push(`# ${normalizedPath}/`);\n lines.push(\"\");\n lines.push(`- **Type**: Prefix (directory)`);\n lines.push(`- **Prefix**: ${prefix}`);\n lines.push(`- **Objects**: ${objectCount}`);\n lines.push(`- **Sub-prefixes**: ${prefixCount}`);\n\n return { format: \"markdown\", content: lines.join(\"\\n\") };\n }\n\n // ========== Search Operations ==========\n\n @Search(\"/\")\n @Search(\"/:path*\")\n async searchHandler(\n ctx: RouteContext<{ path?: string }>,\n query: string,\n ): Promise<AFSSearchResult> {\n const { minimatch } = await import(\"minimatch\");\n const path = ctx.params.path ?? \"\";\n const normalizedPath = path.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n const prefix = normalizedPath\n ? this.options.prefix\n ? `${this.options.prefix}/${normalizedPath}/`\n : `${normalizedPath}/`\n : this.options.prefix\n ? `${this.options.prefix}/`\n : \"\";\n\n const [files] = await this.bucket.getFiles({\n prefix: prefix || undefined,\n });\n\n const results: AFSEntry[] = [];\n for (const file of files) {\n const relativePath = prefix ? file.name.slice(prefix.length) : file.name;\n if (!relativePath) continue;\n\n if (minimatch(relativePath, query)) {\n const displayPath = joinURL(\"/\", normalizedPath, relativePath);\n results.push({\n id: this.generateId(file.name),\n path: displayPath,\n meta: {\n size: file.metadata?.size ? Number(file.metadata.size) : undefined,\n contentType: file.metadata?.contentType,\n lastModified: file.metadata?.updated,\n },\n });\n }\n }\n\n return { data: results };\n }\n\n // ========== Capabilities ==========\n\n @Read(\"/.meta/.capabilities\")\n async readCapabilities(_ctx: RouteContext): Promise<AFSEntry> {\n const capabilities: CapabilitiesManifest = {\n schemaVersion: 1,\n provider: \"gcs\",\n description: `GCS bucket: ${this.options.bucket}`,\n tools: [],\n operations: this.getOperationsDeclaration(),\n actions: [\n {\n description: \"GCS object actions\",\n catalog: [\n {\n name: \"presign-download\",\n description: \"Generate a signed download URL\",\n inputSchema: {\n type: \"object\",\n properties: {\n expiresIn: {\n type: \"number\",\n description: \"Expiration in seconds (default: 3600, max: 604800)\",\n },\n },\n },\n },\n {\n name: \"presign-upload\",\n description: \"Generate a signed upload URL\",\n inputSchema: {\n type: \"object\",\n properties: {\n expiresIn: { type: \"number\", description: \"Expiration in seconds\" },\n contentType: { type: \"string\", description: \"Content-Type for upload\" },\n },\n },\n },\n {\n name: \"compose\",\n description: \"Compose multiple objects into one (max 32 sources)\",\n inputSchema: {\n type: \"object\",\n properties: {\n sources: {\n type: \"array\",\n description: \"Array of source paths (2-32)\",\n items: { type: \"string\" },\n },\n },\n required: [\"sources\"],\n },\n },\n {\n name: \"rewrite\",\n description: \"Copy/rewrite object to a new location\",\n inputSchema: {\n type: \"object\",\n properties: {\n destination: { type: \"string\", description: \"Destination path\" },\n storageClass: { type: \"string\", description: \"Target storage class\" },\n contentType: { type: \"string\", description: \"Override content type\" },\n },\n required: [\"destination\"],\n },\n },\n ],\n discovery: { pathTemplate: \"/{path}/.actions\" },\n },\n ],\n };\n\n return {\n id: \".capabilities\",\n path: \"/.meta/.capabilities\",\n content: capabilities,\n meta: { kind: \"afs:capabilities\" },\n };\n }\n}\n\n// Type check: AFSGCS should implement AFSModuleClass\nconst _typeCheck: AFSModuleClass<AFSGCS, AFSGCSOptions> = AFSGCS;\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aigne/afs-gcs",
|
|
3
|
-
"version": "1.11.0-beta.
|
|
3
|
+
"version": "1.11.0-beta.12",
|
|
4
4
|
"description": "AIGNE AFS module for Google Cloud Storage",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"publishConfig": {
|
|
@@ -34,10 +34,10 @@
|
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@google-cloud/storage": "^7.16.0",
|
|
37
|
-
"minimatch": "^10.
|
|
37
|
+
"minimatch": "^10.2.2",
|
|
38
38
|
"ufo": "^1.6.3",
|
|
39
39
|
"zod": "^4.0.0",
|
|
40
|
-
"@aigne/afs": "^1.11.0-beta.
|
|
40
|
+
"@aigne/afs": "^1.11.0-beta.12"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/bun": "^1.3.6",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"rimraf": "^6.1.2",
|
|
46
46
|
"tsdown": "0.20.0-beta.3",
|
|
47
47
|
"typescript": "5.9.2",
|
|
48
|
-
"@aigne/afs-testing": "1.11.0-beta.
|
|
48
|
+
"@aigne/afs-testing": "1.11.0-beta.12",
|
|
49
49
|
"@aigne/scripts": "0.0.0",
|
|
50
50
|
"@aigne/typescript-config": "0.0.0"
|
|
51
51
|
},
|