@aigne/afs-gce 1.11.0-beta.6

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/LICENSE.md ADDED
@@ -0,0 +1,26 @@
1
+ # Proprietary License
2
+
3
+ Copyright (c) 2024-2025 ArcBlock, Inc. All Rights Reserved.
4
+
5
+ This software and associated documentation files (the "Software") are proprietary
6
+ and confidential. Unauthorized copying, modification, distribution, or use of
7
+ this Software, via any medium, is strictly prohibited.
8
+
9
+ The Software is provided for internal use only within ArcBlock, Inc. and its
10
+ authorized affiliates.
11
+
12
+ ## No License Granted
13
+
14
+ No license, express or implied, is granted to any party for any purpose.
15
+ All rights are reserved by ArcBlock, Inc.
16
+
17
+ ## Public Artifact Distribution
18
+
19
+ Portions of this Software may be released publicly under separate open-source
20
+ licenses (such as MIT License) through designated public repositories. Such
21
+ public releases are governed by their respective licenses and do not affect
22
+ the proprietary nature of this repository.
23
+
24
+ ## Contact
25
+
26
+ For licensing inquiries, contact: legal@arcblock.io
@@ -0,0 +1,137 @@
1
+ import { z } from "zod";
2
+ import { AFSListOptions, AFSListResult, AFSModule, AFSReadOptions, AFSReadResult, AFSStatResult, AFSWriteEntryPayload, AFSWriteOptions, AFSWriteResult } from "@aigne/afs";
3
+
4
+ //#region src/types.d.ts
5
+ /**
6
+ * Configuration options for AFSGCE
7
+ */
8
+ interface AFSGCEOptions {
9
+ /** Module name (used as mount path segment) */
10
+ name?: string;
11
+ /** Module description */
12
+ description?: string;
13
+ /** GCP project ID */
14
+ projectId: string;
15
+ /** GCE zone (e.g., us-central1-a) */
16
+ zone: string;
17
+ /** Access mode */
18
+ accessMode?: "readonly" | "readwrite";
19
+ /** Path to service account key file */
20
+ keyFilename?: string;
21
+ /** Explicit credentials (for programmatic access) */
22
+ credentials?: {
23
+ clientEmail: string;
24
+ privateKey: string;
25
+ };
26
+ /** Cache TTL in seconds (0 = no cache) */
27
+ cacheTtl?: number;
28
+ }
29
+ /**
30
+ * Zod schema for options validation
31
+ */
32
+ declare const afsgceOptionsSchema: z.ZodEffects<z.ZodObject<{
33
+ name: z.ZodType<string | undefined, z.ZodTypeDef, string | undefined>;
34
+ description: z.ZodType<string | undefined, z.ZodTypeDef, string | undefined>;
35
+ projectId: z.ZodString;
36
+ zone: z.ZodString;
37
+ accessMode: z.ZodType<"readonly" | "readwrite" | undefined, z.ZodTypeDef, "readonly" | "readwrite" | undefined>;
38
+ keyFilename: z.ZodType<string | undefined, z.ZodTypeDef, string | undefined>;
39
+ credentials: z.ZodType<{
40
+ clientEmail: string;
41
+ privateKey: string;
42
+ } | undefined, z.ZodTypeDef, {
43
+ clientEmail: string;
44
+ privateKey: string;
45
+ } | undefined>;
46
+ cacheTtl: z.ZodType<number | undefined, z.ZodTypeDef, number | undefined>;
47
+ }, "strict", z.ZodTypeAny, {
48
+ projectId: string;
49
+ zone: string;
50
+ name?: string | undefined;
51
+ description?: string | undefined;
52
+ accessMode?: "readonly" | "readwrite" | undefined;
53
+ keyFilename?: string | undefined;
54
+ credentials?: {
55
+ clientEmail: string;
56
+ privateKey: string;
57
+ } | undefined;
58
+ cacheTtl?: number | undefined;
59
+ }, {
60
+ projectId: string;
61
+ zone: string;
62
+ name?: string | undefined;
63
+ description?: string | undefined;
64
+ accessMode?: "readonly" | "readwrite" | undefined;
65
+ keyFilename?: string | undefined;
66
+ credentials?: {
67
+ clientEmail: string;
68
+ privateKey: string;
69
+ } | undefined;
70
+ cacheTtl?: number | undefined;
71
+ }>, {
72
+ projectId: string;
73
+ zone: string;
74
+ name?: string | undefined;
75
+ description?: string | undefined;
76
+ accessMode?: "readonly" | "readwrite" | undefined;
77
+ keyFilename?: string | undefined;
78
+ credentials?: {
79
+ clientEmail: string;
80
+ privateKey: string;
81
+ } | undefined;
82
+ cacheTtl?: number | undefined;
83
+ }, any>;
84
+ //#endregion
85
+ //#region src/index.d.ts
86
+ /**
87
+ * AFS GCE Provider
88
+ *
89
+ * Provides a file-system-like interface to GCE instances.
90
+ *
91
+ * @example
92
+ * ```typescript
93
+ * const provider = new AFSGCE({
94
+ * projectId: 'my-project',
95
+ * zone: 'us-central1-a',
96
+ * });
97
+ *
98
+ * // List instances
99
+ * const instances = await provider.list('/instances');
100
+ *
101
+ * // Get instance metadata
102
+ * const metadata = await provider.read('/instances/my-vm/metadata.json');
103
+ *
104
+ * // Start an instance (requires readwrite mode)
105
+ * await provider.write('/instances/my-vm/actions/start', {});
106
+ * ```
107
+ */
108
+ declare class AFSGCE implements AFSModule {
109
+ readonly name: string;
110
+ readonly description?: string;
111
+ readonly accessMode: "readonly" | "readwrite";
112
+ private readonly client;
113
+ private readonly projectId;
114
+ private readonly zone;
115
+ constructor(options: AFSGCEOptions);
116
+ /**
117
+ * List GCE resources
118
+ */
119
+ list(path: string, options?: AFSListOptions): Promise<AFSListResult>;
120
+ /**
121
+ * Get metadata for a GCE resource
122
+ */
123
+ stat(path: string): Promise<AFSStatResult>;
124
+ /**
125
+ * Read GCE resource data
126
+ */
127
+ read(path: string, options?: AFSReadOptions): Promise<AFSReadResult>;
128
+ /**
129
+ * Write/execute action on GCE resource
130
+ *
131
+ * In GCE, write is used to execute actions (start, stop, reset)
132
+ */
133
+ write(path: string, _content: AFSWriteEntryPayload, _options?: AFSWriteOptions): Promise<AFSWriteResult>;
134
+ }
135
+ //#endregion
136
+ export { AFSGCE, type AFSGCEOptions, afsgceOptionsSchema };
137
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/index.ts"],"mappings":";;;;AAUA;;;AAAA,UAAiB,aAAA;EAEf;EAAA,IAAA;EAMA;EAHA,WAAA;EASA;EANA,SAAA;EAYA;EATA,IAAA;EAWE;EARF,UAAA;EAYQ;EATR,WAAA;EAqBW;EAlBX,WAAA;IACE,WAAA;IACA,UAAA;EAAA;;EAIF,QAAA;AAAA;;;;cAYW,mBAAA,EAAmB,CAAA,CAAA,UAAA,CAAA,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAhC;;;;;;;;;cCAa,MAAA,YAAkB,SAAA;EAAA,SACpB,IAAA;EAAA,SACA,WAAA;EAAA,SACA,UAAA;EAAA,iBAEQ,MAAA;EAAA,iBACA,SAAA;EAAA,iBACA,IAAA;cAEL,OAAA,EAAS,aAAA;;;;EAyBf,IAAA,CAAK,IAAA,UAAc,OAAA,GAAU,cAAA,GAAiB,OAAA,CAAQ,aAAA;EDlC9B;;;ECyCxB,IAAA,CAAK,IAAA,WAAe,OAAA,CAAQ,aAAA;EDzCJ;;;ECuDxB,IAAA,CAAK,IAAA,UAAc,OAAA,GAAU,cAAA,GAAiB,OAAA,CAAQ,aAAA;;;;;;EAStD,KAAA,CACJ,IAAA,UACA,QAAA,EAAU,oBAAA,EACV,QAAA,GAAW,eAAA,GACV,OAAA,CAAQ,cAAA;AAAA"}
package/dist/index.mjs ADDED
@@ -0,0 +1,837 @@
1
+ import { InstancesClient } from "@google-cloud/compute";
2
+ import { camelize, optionalize } from "@aigne/afs/utils/zod";
3
+ import { z } from "zod";
4
+
5
+ //#region src/errors.ts
6
+ /**
7
+ * GCE Provider Error Handling
8
+ *
9
+ * Maps GCE SDK errors to AFS error types.
10
+ */
11
+ /**
12
+ * AFS error codes
13
+ */
14
+ const AFSErrorCode = {
15
+ ENTRY_NOT_FOUND: "ENTRY_NOT_FOUND",
16
+ MODULE_NOT_FOUND: "MODULE_NOT_FOUND",
17
+ PERMISSION_DENIED: "PERMISSION_DENIED",
18
+ AUTH_ERROR: "AUTH_ERROR",
19
+ RATE_LIMIT_EXCEEDED: "RATE_LIMIT_EXCEEDED",
20
+ INVALID_OPERATION: "INVALID_OPERATION",
21
+ ALREADY_EXISTS: "ALREADY_EXISTS",
22
+ SERVICE_UNAVAILABLE: "SERVICE_UNAVAILABLE",
23
+ UNKNOWN: "UNKNOWN"
24
+ };
25
+ /**
26
+ * AFS Error class
27
+ */
28
+ var AFSError = class extends Error {
29
+ code;
30
+ retryAfter;
31
+ constructor(code, message, options) {
32
+ super(message);
33
+ this.name = "AFSError";
34
+ this.code = code;
35
+ this.retryAfter = options?.retryAfter;
36
+ }
37
+ };
38
+ /**
39
+ * Map GCE HTTP status codes to AFS error codes
40
+ */
41
+ const STATUS_TO_AFS_ERROR = {
42
+ 400: AFSErrorCode.INVALID_OPERATION,
43
+ 401: AFSErrorCode.AUTH_ERROR,
44
+ 403: AFSErrorCode.PERMISSION_DENIED,
45
+ 404: AFSErrorCode.ENTRY_NOT_FOUND,
46
+ 409: AFSErrorCode.ALREADY_EXISTS,
47
+ 429: AFSErrorCode.RATE_LIMIT_EXCEEDED,
48
+ 503: AFSErrorCode.SERVICE_UNAVAILABLE
49
+ };
50
+ /**
51
+ * Map GCE error to AFS error
52
+ *
53
+ * @param error - GCE SDK error or generic error
54
+ * @returns AFSError with appropriate error code
55
+ */
56
+ function mapGCEError(error) {
57
+ if (typeof error === "object" && error !== null && "code" in error) {
58
+ const err = error;
59
+ const statusCode = typeof err.code === "number" ? err.code : 500;
60
+ const message = err.message ?? "Unknown GCE error";
61
+ return new AFSError(STATUS_TO_AFS_ERROR[statusCode] ?? AFSErrorCode.UNKNOWN, message);
62
+ }
63
+ if (error instanceof Error) return new AFSError(AFSErrorCode.UNKNOWN, error.message);
64
+ return new AFSError(AFSErrorCode.UNKNOWN, String(error));
65
+ }
66
+
67
+ //#endregion
68
+ //#region src/path-resolver.ts
69
+ /**
70
+ * Parse an AFS path into GCE resource identifiers
71
+ *
72
+ * Path structure:
73
+ * / - root
74
+ * /instances - list all instances
75
+ * /instances/{name} - specific instance
76
+ * /instances/{name}/metadata.json - instance metadata
77
+ * /instances/{name}/actions - list available actions
78
+ * /instances/{name}/actions/{action} - specific action
79
+ * /actions - global actions list
80
+ * /actions/{action} - global action
81
+ *
82
+ * @param path - AFS path
83
+ * @returns Parsed path with type and identifiers
84
+ */
85
+ function parsePath(path) {
86
+ const segments = path.replace(/^\/+/, "").replace(/\/+$/, "").split("/").filter(Boolean);
87
+ if (segments.length === 0) return {
88
+ type: "root",
89
+ raw: path
90
+ };
91
+ const [first, second, third, fourth] = segments;
92
+ if (first === "instances") {
93
+ if (!second) return {
94
+ type: "instances",
95
+ raw: path
96
+ };
97
+ if (!third) return {
98
+ type: "instance",
99
+ instanceName: second,
100
+ raw: path
101
+ };
102
+ if (third === "metadata.json") return {
103
+ type: "instance-metadata",
104
+ instanceName: second,
105
+ fileName: third,
106
+ raw: path
107
+ };
108
+ if (third === "actions") {
109
+ if (!fourth) return {
110
+ type: "instance-actions",
111
+ instanceName: second,
112
+ raw: path
113
+ };
114
+ return {
115
+ type: "instance-action",
116
+ instanceName: second,
117
+ action: fourth,
118
+ raw: path
119
+ };
120
+ }
121
+ return {
122
+ type: "unknown",
123
+ raw: path
124
+ };
125
+ }
126
+ if (first === "actions") {
127
+ if (!second) return {
128
+ type: "actions",
129
+ raw: path
130
+ };
131
+ return {
132
+ type: "global-action",
133
+ action: second,
134
+ raw: path
135
+ };
136
+ }
137
+ return {
138
+ type: "unknown",
139
+ raw: path
140
+ };
141
+ }
142
+ /**
143
+ * Build an AFS path from components
144
+ */
145
+ function buildPath(...segments) {
146
+ return `/${segments.filter(Boolean).join("/")}`;
147
+ }
148
+
149
+ //#endregion
150
+ //#region src/operations/actions.ts
151
+ /**
152
+ * Execute an action on a GCE resource
153
+ *
154
+ * @param client - GCE InstancesClient
155
+ * @param projectId - GCP project ID
156
+ * @param zone - GCE zone
157
+ * @param path - AFS path to the action
158
+ * @returns Action result
159
+ */
160
+ async function executeAction(client, projectId, zone, path) {
161
+ try {
162
+ const parsed = parsePath(path);
163
+ switch (parsed.type) {
164
+ case "instance-action": return executeInstanceAction(client, projectId, zone, parsed.instanceName, parsed.action);
165
+ case "global-action": return executeGlobalAction(parsed.action);
166
+ default: throw new Error(`Cannot execute action on path: ${path}`);
167
+ }
168
+ } catch (error) {
169
+ throw mapGCEError(error);
170
+ }
171
+ }
172
+ /**
173
+ * Execute an action on a specific instance
174
+ */
175
+ async function executeInstanceAction(client, projectId, zone, instanceName, action) {
176
+ const [instance] = await client.get({
177
+ project: projectId,
178
+ zone,
179
+ instance: instanceName
180
+ });
181
+ const status = instance.status;
182
+ switch (action) {
183
+ case "start": return startInstance(client, projectId, zone, instanceName, status);
184
+ case "stop": return stopInstance(client, projectId, zone, instanceName, status);
185
+ case "reset": return resetInstance(client, projectId, zone, instanceName, status);
186
+ default: return {
187
+ success: false,
188
+ action,
189
+ error: `Unknown action: ${action}`
190
+ };
191
+ }
192
+ }
193
+ /**
194
+ * Start an instance
195
+ */
196
+ async function startInstance(client, projectId, zone, instanceName, currentStatus) {
197
+ if (currentStatus !== "STOPPED" && currentStatus !== "TERMINATED") return {
198
+ success: false,
199
+ action: "start",
200
+ error: `Cannot start instance in ${currentStatus} state. Instance must be STOPPED or TERMINATED.`
201
+ };
202
+ const [operation] = await client.start({
203
+ project: projectId,
204
+ zone,
205
+ instance: instanceName
206
+ });
207
+ return {
208
+ success: true,
209
+ action: "start",
210
+ operationName: operation.latestResponse?.name || "unknown"
211
+ };
212
+ }
213
+ /**
214
+ * Stop an instance
215
+ */
216
+ async function stopInstance(client, projectId, zone, instanceName, currentStatus) {
217
+ if (currentStatus !== "RUNNING") return {
218
+ success: false,
219
+ action: "stop",
220
+ error: `Cannot stop instance in ${currentStatus} state. Instance must be RUNNING.`
221
+ };
222
+ const [operation] = await client.stop({
223
+ project: projectId,
224
+ zone,
225
+ instance: instanceName
226
+ });
227
+ return {
228
+ success: true,
229
+ action: "stop",
230
+ operationName: operation.latestResponse?.name || "unknown"
231
+ };
232
+ }
233
+ /**
234
+ * Reset an instance
235
+ */
236
+ async function resetInstance(client, projectId, zone, instanceName, currentStatus) {
237
+ if (currentStatus !== "RUNNING") return {
238
+ success: false,
239
+ action: "reset",
240
+ error: `Cannot reset instance in ${currentStatus} state. Instance must be RUNNING.`
241
+ };
242
+ const [operation] = await client.reset({
243
+ project: projectId,
244
+ zone,
245
+ instance: instanceName
246
+ });
247
+ return {
248
+ success: true,
249
+ action: "reset",
250
+ operationName: operation.latestResponse?.name || "unknown"
251
+ };
252
+ }
253
+ /**
254
+ * Execute a global action
255
+ */
256
+ function executeGlobalAction(action) {
257
+ switch (action) {
258
+ case "refresh": return {
259
+ success: true,
260
+ action: "refresh"
261
+ };
262
+ default: return {
263
+ success: false,
264
+ action,
265
+ error: `Unknown global action: ${action}`
266
+ };
267
+ }
268
+ }
269
+
270
+ //#endregion
271
+ //#region src/platform-ref.ts
272
+ /**
273
+ * Generate platform reference with GCP Console URL for an instance
274
+ *
275
+ * @param projectId - GCP project ID
276
+ * @param zone - GCE zone
277
+ * @param instanceName - Instance name
278
+ * @returns Platform reference with console URL
279
+ */
280
+ function generateInstancePlatformRef(projectId, zone, instanceName) {
281
+ return { consoleUrl: `https://console.cloud.google.com/compute/instancesDetail/zones/${zone}/instances/${instanceName}?project=${projectId}` };
282
+ }
283
+ /**
284
+ * Generate platform reference with GCP Console URL for instances list
285
+ *
286
+ * @param projectId - GCP project ID
287
+ * @returns Platform reference with console URL
288
+ */
289
+ function generateInstancesListPlatformRef(projectId) {
290
+ return { consoleUrl: `https://console.cloud.google.com/compute/instances?project=${projectId}` };
291
+ }
292
+
293
+ //#endregion
294
+ //#region src/types.ts
295
+ /**
296
+ * AFS GCE Provider Types
297
+ */
298
+ /**
299
+ * GCE zone validation regex
300
+ * Format: region-zone (e.g., us-central1-a, europe-west1-b)
301
+ */
302
+ const ZONE_REGEX = /^[a-z]+-[a-z]+\d+-[a-z]$/;
303
+ /**
304
+ * Zod schema for options validation
305
+ */
306
+ const afsgceOptionsSchema = camelize(z.object({
307
+ name: optionalize(z.string()),
308
+ description: optionalize(z.string()),
309
+ projectId: z.string().min(1),
310
+ zone: z.string().regex(ZONE_REGEX, "Invalid GCE zone format (e.g., us-central1-a)"),
311
+ accessMode: optionalize(z.enum(["readonly", "readwrite"])),
312
+ keyFilename: optionalize(z.string()),
313
+ credentials: optionalize(z.object({
314
+ clientEmail: z.string(),
315
+ privateKey: z.string()
316
+ })),
317
+ cacheTtl: optionalize(z.number().int().min(0))
318
+ }).strict());
319
+ /**
320
+ * Kind constants for GCE resources
321
+ */
322
+ const KINDS = {
323
+ INSTANCE: "gce:instance",
324
+ ACTION: "gce:action",
325
+ EXECUTABLE: "afs:executable",
326
+ NODE: "afs:node",
327
+ GCP_RESOURCE: "gcp:resource"
328
+ };
329
+
330
+ //#endregion
331
+ //#region src/operations/list.ts
332
+ /**
333
+ * List GCE resources
334
+ *
335
+ * @param client - GCE InstancesClient
336
+ * @param projectId - GCP project ID
337
+ * @param zone - GCE zone
338
+ * @param path - AFS path
339
+ * @param options - List options
340
+ * @returns List result with entries
341
+ */
342
+ async function list(client, projectId, zone, path, options) {
343
+ try {
344
+ const parsed = parsePath(path);
345
+ switch (parsed.type) {
346
+ case "root": return listRoot(projectId);
347
+ case "instances": return listInstances(client, projectId, zone, options);
348
+ case "instance": return listInstanceChildren(client, projectId, zone, parsed.instanceName);
349
+ case "instance-actions": return listInstanceActions(client, projectId, zone, parsed.instanceName);
350
+ case "actions": return listGlobalActions(projectId);
351
+ default: return { data: [] };
352
+ }
353
+ } catch (error) {
354
+ throw mapGCEError(error);
355
+ }
356
+ }
357
+ /**
358
+ * List root directory
359
+ */
360
+ function listRoot(projectId) {
361
+ return { data: [{
362
+ id: `gce://${projectId}/instances`,
363
+ path: "/instances",
364
+ metadata: {
365
+ kind: KINDS.NODE,
366
+ kinds: [KINDS.NODE],
367
+ childrenCount: 0,
368
+ description: "GCE Instances",
369
+ platformRef: generateInstancesListPlatformRef(projectId)
370
+ }
371
+ }, {
372
+ id: `gce://${projectId}/actions`,
373
+ path: "/actions",
374
+ metadata: {
375
+ kind: KINDS.NODE,
376
+ kinds: [KINDS.NODE],
377
+ childrenCount: 0,
378
+ description: "Global Actions"
379
+ }
380
+ }] };
381
+ }
382
+ /**
383
+ * List all instances
384
+ */
385
+ async function listInstances(client, projectId, zone, options) {
386
+ const maxChildren = options?.maxChildren ?? 1e3;
387
+ const [instances] = await client.list({
388
+ project: projectId,
389
+ zone,
390
+ maxResults: maxChildren
391
+ });
392
+ return { data: (instances || []).map((instance) => {
393
+ const name = instance.name;
394
+ const machineType = instance.machineType?.split("/").pop() || "unknown";
395
+ return {
396
+ id: `gce://${projectId}/${zone}/${name}`,
397
+ path: buildPath("instances", name),
398
+ metadata: {
399
+ kind: KINDS.INSTANCE,
400
+ kinds: [
401
+ KINDS.INSTANCE,
402
+ KINDS.GCP_RESOURCE,
403
+ KINDS.NODE
404
+ ],
405
+ childrenCount: 2,
406
+ status: instance.status,
407
+ machineType,
408
+ privateIp: instance.networkInterfaces?.[0]?.networkIP,
409
+ publicIp: instance.networkInterfaces?.[0]?.accessConfigs?.[0]?.natIP,
410
+ createdAt: instance.creationTimestamp,
411
+ labels: instance.labels,
412
+ platformRef: generateInstancePlatformRef(projectId, zone, name)
413
+ }
414
+ };
415
+ }) };
416
+ }
417
+ /**
418
+ * List instance children (metadata.json, actions)
419
+ */
420
+ async function listInstanceChildren(client, projectId, zone, instanceName) {
421
+ await client.get({
422
+ project: projectId,
423
+ zone,
424
+ instance: instanceName
425
+ });
426
+ return { data: [{
427
+ id: `gce://${projectId}/${zone}/${instanceName}/metadata.json`,
428
+ path: buildPath("instances", instanceName, "metadata.json"),
429
+ metadata: {
430
+ kind: KINDS.NODE,
431
+ kinds: [KINDS.NODE],
432
+ description: "Instance metadata"
433
+ }
434
+ }, {
435
+ id: `gce://${projectId}/${zone}/${instanceName}/actions`,
436
+ path: buildPath("instances", instanceName, "actions"),
437
+ metadata: {
438
+ kind: KINDS.NODE,
439
+ kinds: [KINDS.NODE],
440
+ childrenCount: 0,
441
+ description: "Instance actions"
442
+ }
443
+ }] };
444
+ }
445
+ /**
446
+ * List available actions for an instance
447
+ */
448
+ async function listInstanceActions(client, projectId, zone, instanceName) {
449
+ const [instance] = await client.get({
450
+ project: projectId,
451
+ zone,
452
+ instance: instanceName
453
+ });
454
+ const status = instance.status;
455
+ const actions = [];
456
+ switch (status) {
457
+ case "RUNNING":
458
+ actions.push("stop", "reset");
459
+ break;
460
+ case "STOPPED":
461
+ case "TERMINATED":
462
+ actions.push("start");
463
+ break;
464
+ case "SUSPENDED":
465
+ actions.push("resume");
466
+ break;
467
+ default: break;
468
+ }
469
+ return { data: actions.map((action) => ({
470
+ id: `gce://${projectId}/${zone}/${instanceName}/actions/${action}`,
471
+ path: buildPath("instances", instanceName, "actions", action),
472
+ metadata: {
473
+ kind: KINDS.ACTION,
474
+ kinds: [
475
+ KINDS.ACTION,
476
+ KINDS.EXECUTABLE,
477
+ KINDS.NODE
478
+ ],
479
+ description: `${action.charAt(0).toUpperCase() + action.slice(1)} the instance`
480
+ }
481
+ })) };
482
+ }
483
+ /**
484
+ * List global actions
485
+ */
486
+ function listGlobalActions(projectId) {
487
+ return { data: [{
488
+ id: `gce://${projectId}/actions/refresh`,
489
+ path: "/actions/refresh",
490
+ metadata: {
491
+ kind: KINDS.ACTION,
492
+ kinds: [
493
+ KINDS.ACTION,
494
+ KINDS.EXECUTABLE,
495
+ KINDS.NODE
496
+ ],
497
+ description: "Refresh instance cache"
498
+ }
499
+ }] };
500
+ }
501
+
502
+ //#endregion
503
+ //#region src/operations/read.ts
504
+ /**
505
+ * Read GCE resource data
506
+ *
507
+ * @param client - GCE InstancesClient
508
+ * @param projectId - GCP project ID
509
+ * @param zone - GCE zone
510
+ * @param path - AFS path
511
+ * @param options - Read options
512
+ * @returns Read result with content
513
+ */
514
+ async function read(client, projectId, zone, path, _options) {
515
+ try {
516
+ const parsed = parsePath(path);
517
+ switch (parsed.type) {
518
+ case "instance-metadata": return readInstanceMetadata(client, projectId, zone, parsed.instanceName);
519
+ default: throw new Error(`Cannot read path: ${path}`);
520
+ }
521
+ } catch (error) {
522
+ throw mapGCEError(error);
523
+ }
524
+ }
525
+ /**
526
+ * Read instance metadata as JSON
527
+ */
528
+ async function readInstanceMetadata(client, projectId, zone, instanceName) {
529
+ const [instance] = await client.get({
530
+ project: projectId,
531
+ zone,
532
+ instance: instanceName
533
+ });
534
+ return { data: {
535
+ id: `gce://${projectId}/${zone}/${instanceName}/metadata.json`,
536
+ path: buildPath("instances", instanceName, "metadata.json"),
537
+ metadata: {
538
+ kind: KINDS.NODE,
539
+ kinds: [KINDS.NODE],
540
+ description: "Instance metadata"
541
+ },
542
+ content: JSON.stringify(instance, null, 2)
543
+ } };
544
+ }
545
+
546
+ //#endregion
547
+ //#region src/operations/stat.ts
548
+ /**
549
+ * Get metadata for a GCE resource
550
+ *
551
+ * @param client - GCE InstancesClient
552
+ * @param projectId - GCP project ID
553
+ * @param zone - GCE zone
554
+ * @param path - AFS path
555
+ * @returns Entry with metadata
556
+ */
557
+ async function stat(client, projectId, zone, path) {
558
+ try {
559
+ const parsed = parsePath(path);
560
+ switch (parsed.type) {
561
+ case "root": return statRoot(projectId);
562
+ case "instances": return statInstances(projectId);
563
+ case "instance": return statInstance(client, projectId, zone, parsed.instanceName);
564
+ case "instance-metadata": return statInstanceMetadata(client, projectId, zone, parsed.instanceName);
565
+ case "instance-actions": return statInstanceActions(client, projectId, zone, parsed.instanceName);
566
+ case "instance-action": return statInstanceAction(client, projectId, zone, parsed.instanceName, parsed.action);
567
+ case "actions": return statGlobalActions(projectId);
568
+ case "global-action": return statGlobalAction(projectId, parsed.action);
569
+ default: throw new Error(`Path not found: ${path}`);
570
+ }
571
+ } catch (error) {
572
+ throw mapGCEError(error);
573
+ }
574
+ }
575
+ /**
576
+ * Stat root directory
577
+ */
578
+ function statRoot(projectId) {
579
+ return {
580
+ id: `gce://${projectId}/`,
581
+ path: "/",
582
+ metadata: {
583
+ kind: KINDS.NODE,
584
+ kinds: [KINDS.NODE],
585
+ childrenCount: 2,
586
+ description: "GCE Root"
587
+ }
588
+ };
589
+ }
590
+ /**
591
+ * Stat instances directory
592
+ */
593
+ function statInstances(projectId) {
594
+ return {
595
+ id: `gce://${projectId}/instances`,
596
+ path: "/instances",
597
+ metadata: {
598
+ kind: KINDS.NODE,
599
+ kinds: [KINDS.NODE],
600
+ childrenCount: 0,
601
+ description: "GCE Instances",
602
+ platformRef: generateInstancesListPlatformRef(projectId)
603
+ }
604
+ };
605
+ }
606
+ /**
607
+ * Stat a specific instance
608
+ */
609
+ async function statInstance(client, projectId, zone, instanceName) {
610
+ const [instance] = await client.get({
611
+ project: projectId,
612
+ zone,
613
+ instance: instanceName
614
+ });
615
+ const machineType = instance.machineType?.split("/").pop() || "unknown";
616
+ return {
617
+ id: `gce://${projectId}/${zone}/${instanceName}`,
618
+ path: buildPath("instances", instanceName),
619
+ metadata: {
620
+ kind: KINDS.INSTANCE,
621
+ kinds: [
622
+ KINDS.INSTANCE,
623
+ KINDS.GCP_RESOURCE,
624
+ KINDS.NODE
625
+ ],
626
+ childrenCount: 2,
627
+ status: instance.status,
628
+ machineType,
629
+ privateIp: instance.networkInterfaces?.[0]?.networkIP,
630
+ publicIp: instance.networkInterfaces?.[0]?.accessConfigs?.[0]?.natIP,
631
+ createdAt: instance.creationTimestamp,
632
+ labels: instance.labels,
633
+ platformRef: generateInstancePlatformRef(projectId, zone, instanceName)
634
+ }
635
+ };
636
+ }
637
+ /**
638
+ * Stat instance metadata.json file
639
+ */
640
+ async function statInstanceMetadata(client, projectId, zone, instanceName) {
641
+ await client.get({
642
+ project: projectId,
643
+ zone,
644
+ instance: instanceName
645
+ });
646
+ return {
647
+ id: `gce://${projectId}/${zone}/${instanceName}/metadata.json`,
648
+ path: buildPath("instances", instanceName, "metadata.json"),
649
+ metadata: {
650
+ kind: KINDS.NODE,
651
+ kinds: [KINDS.NODE],
652
+ description: "Instance metadata"
653
+ }
654
+ };
655
+ }
656
+ /**
657
+ * Stat instance actions directory
658
+ */
659
+ async function statInstanceActions(client, projectId, zone, instanceName) {
660
+ await client.get({
661
+ project: projectId,
662
+ zone,
663
+ instance: instanceName
664
+ });
665
+ return {
666
+ id: `gce://${projectId}/${zone}/${instanceName}/actions`,
667
+ path: buildPath("instances", instanceName, "actions"),
668
+ metadata: {
669
+ kind: KINDS.NODE,
670
+ kinds: [KINDS.NODE],
671
+ childrenCount: 0,
672
+ description: "Instance actions"
673
+ }
674
+ };
675
+ }
676
+ /**
677
+ * Stat a specific instance action
678
+ */
679
+ async function statInstanceAction(client, projectId, zone, instanceName, action) {
680
+ await client.get({
681
+ project: projectId,
682
+ zone,
683
+ instance: instanceName
684
+ });
685
+ return {
686
+ id: `gce://${projectId}/${zone}/${instanceName}/actions/${action}`,
687
+ path: buildPath("instances", instanceName, "actions", action),
688
+ metadata: {
689
+ kind: KINDS.ACTION,
690
+ kinds: [
691
+ KINDS.ACTION,
692
+ KINDS.EXECUTABLE,
693
+ KINDS.NODE
694
+ ],
695
+ description: `${action.charAt(0).toUpperCase() + action.slice(1)} the instance`
696
+ }
697
+ };
698
+ }
699
+ /**
700
+ * Stat global actions directory
701
+ */
702
+ function statGlobalActions(projectId) {
703
+ return {
704
+ id: `gce://${projectId}/actions`,
705
+ path: "/actions",
706
+ metadata: {
707
+ kind: KINDS.NODE,
708
+ kinds: [KINDS.NODE],
709
+ childrenCount: 1,
710
+ description: "Global Actions"
711
+ }
712
+ };
713
+ }
714
+ /**
715
+ * Stat a specific global action
716
+ */
717
+ function statGlobalAction(projectId, action) {
718
+ return {
719
+ id: `gce://${projectId}/actions/${action}`,
720
+ path: buildPath("actions", action),
721
+ metadata: {
722
+ kind: KINDS.ACTION,
723
+ kinds: [
724
+ KINDS.ACTION,
725
+ KINDS.EXECUTABLE,
726
+ KINDS.NODE
727
+ ],
728
+ description: `${action.charAt(0).toUpperCase() + action.slice(1)} action`
729
+ }
730
+ };
731
+ }
732
+
733
+ //#endregion
734
+ //#region src/index.ts
735
+ /**
736
+ * AFS GCE Provider
737
+ *
738
+ * Provides a file-system-like interface to GCE instances.
739
+ *
740
+ * @example
741
+ * ```typescript
742
+ * const provider = new AFSGCE({
743
+ * projectId: 'my-project',
744
+ * zone: 'us-central1-a',
745
+ * });
746
+ *
747
+ * // List instances
748
+ * const instances = await provider.list('/instances');
749
+ *
750
+ * // Get instance metadata
751
+ * const metadata = await provider.read('/instances/my-vm/metadata.json');
752
+ *
753
+ * // Start an instance (requires readwrite mode)
754
+ * await provider.write('/instances/my-vm/actions/start', {});
755
+ * ```
756
+ */
757
+ var AFSGCE = class {
758
+ name;
759
+ description;
760
+ accessMode;
761
+ client;
762
+ projectId;
763
+ zone;
764
+ constructor(options) {
765
+ const validated = afsgceOptionsSchema.parse(options);
766
+ this.name = validated.name || "gce";
767
+ this.description = validated.description;
768
+ this.accessMode = validated.accessMode || "readonly";
769
+ this.projectId = validated.projectId;
770
+ this.zone = validated.zone;
771
+ this.client = new InstancesClient({
772
+ keyFilename: validated.keyFilename,
773
+ credentials: validated.credentials ? {
774
+ client_email: validated.credentials.clientEmail,
775
+ private_key: validated.credentials.privateKey
776
+ } : void 0
777
+ });
778
+ }
779
+ /**
780
+ * List GCE resources
781
+ */
782
+ async list(path, options) {
783
+ return list(this.client, this.projectId, this.zone, path, options);
784
+ }
785
+ /**
786
+ * Get metadata for a GCE resource
787
+ */
788
+ async stat(path) {
789
+ const entry = await stat(this.client, this.projectId, this.zone, path);
790
+ return { data: {
791
+ path: entry.path,
792
+ childrenCount: entry.metadata?.childrenCount,
793
+ meta: entry.metadata
794
+ } };
795
+ }
796
+ /**
797
+ * Read GCE resource data
798
+ */
799
+ async read(path, options) {
800
+ return read(this.client, this.projectId, this.zone, path, options);
801
+ }
802
+ /**
803
+ * Write/execute action on GCE resource
804
+ *
805
+ * In GCE, write is used to execute actions (start, stop, reset)
806
+ */
807
+ async write(path, _content, _options) {
808
+ if (this.accessMode !== "readwrite") throw mapGCEError(/* @__PURE__ */ new Error("Write operations require readwrite access mode"));
809
+ const parsed = parsePath(path);
810
+ if (parsed.type === "instance-action" || parsed.type === "global-action") {
811
+ const result = await executeAction(this.client, this.projectId, this.zone, path);
812
+ return {
813
+ data: {
814
+ id: `gce://${this.projectId}/${this.zone}/${path}`,
815
+ path,
816
+ metadata: {
817
+ kind: KINDS.ACTION,
818
+ kinds: [
819
+ KINDS.ACTION,
820
+ KINDS.EXECUTABLE,
821
+ KINDS.NODE
822
+ ],
823
+ success: result.success,
824
+ operationName: result.operationName,
825
+ error: result.error
826
+ }
827
+ },
828
+ message: result.success ? `Action ${result.action} executed successfully` : `Action ${result.action} failed: ${result.error}`
829
+ };
830
+ }
831
+ throw mapGCEError(/* @__PURE__ */ new Error(`Cannot write to path: ${path}`));
832
+ }
833
+ };
834
+
835
+ //#endregion
836
+ export { AFSGCE, afsgceOptionsSchema };
837
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/errors.ts","../src/path-resolver.ts","../src/operations/actions.ts","../src/platform-ref.ts","../src/types.ts","../src/operations/list.ts","../src/operations/read.ts","../src/operations/stat.ts","../src/index.ts"],"sourcesContent":["/**\n * GCE Provider Error Handling\n *\n * Maps GCE 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 * Map GCE 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 GCE error to AFS error\n *\n * @param error - GCE SDK error or generic error\n * @returns AFSError with appropriate error code\n */\nexport function mapGCEError(error: unknown): AFSError {\n // Handle GCE SDK errors (they have 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 GCE 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 * GCE Path Resolver\n *\n * Parses AFS paths into GCE resource identifiers.\n */\n\nimport type { ParsedPath } from \"./types.js\";\n\n/**\n * Parse an AFS path into GCE resource identifiers\n *\n * Path structure:\n * / - root\n * /instances - list all instances\n * /instances/{name} - specific instance\n * /instances/{name}/metadata.json - instance metadata\n * /instances/{name}/actions - list available actions\n * /instances/{name}/actions/{action} - specific action\n * /actions - global actions list\n * /actions/{action} - global action\n *\n * @param path - AFS path\n * @returns Parsed path with type and identifiers\n */\nexport function parsePath(path: string): ParsedPath {\n const normalizedPath = path.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n const segments = normalizedPath.split(\"/\").filter(Boolean);\n\n if (segments.length === 0) {\n return { type: \"root\", raw: path };\n }\n\n const [first, second, third, fourth] = segments;\n\n // /instances\n if (first === \"instances\") {\n if (!second) {\n return { type: \"instances\", raw: path };\n }\n\n // /instances/{name}\n if (!third) {\n return { type: \"instance\", instanceName: second, raw: path };\n }\n\n // /instances/{name}/metadata.json\n if (third === \"metadata.json\") {\n return { type: \"instance-metadata\", instanceName: second, fileName: third, raw: path };\n }\n\n // /instances/{name}/actions\n if (third === \"actions\") {\n if (!fourth) {\n return { type: \"instance-actions\", instanceName: second, raw: path };\n }\n // /instances/{name}/actions/{action}\n return { type: \"instance-action\", instanceName: second, action: fourth, raw: path };\n }\n\n return { type: \"unknown\", raw: path };\n }\n\n // /actions\n if (first === \"actions\") {\n if (!second) {\n return { type: \"actions\", raw: path };\n }\n // /actions/{action}\n return { type: \"global-action\", action: second, raw: path };\n }\n\n return { type: \"unknown\", raw: path };\n}\n\n/**\n * Build an AFS path from components\n */\nexport function buildPath(...segments: (string | undefined)[]): string {\n return `/${segments.filter(Boolean).join(\"/\")}`;\n}\n","/**\n * GCE Actions\n *\n * Executes actions on GCE resources (start, stop, reset, etc.)\n */\n\nimport type { InstancesClient } from \"@google-cloud/compute\";\nimport { mapGCEError } from \"../errors.js\";\nimport { parsePath } from \"../path-resolver.js\";\nimport type { GCEInstanceState } from \"../types.js\";\n\n/**\n * Action result\n */\nexport interface ActionResult {\n success: boolean;\n action: string;\n operationName?: string;\n error?: string;\n}\n\n/**\n * Execute an action on a GCE resource\n *\n * @param client - GCE InstancesClient\n * @param projectId - GCP project ID\n * @param zone - GCE zone\n * @param path - AFS path to the action\n * @returns Action result\n */\nexport async function executeAction(\n client: InstancesClient,\n projectId: string,\n zone: string,\n path: string,\n): Promise<ActionResult> {\n try {\n const parsed = parsePath(path);\n\n switch (parsed.type) {\n case \"instance-action\":\n return executeInstanceAction(client, projectId, zone, parsed.instanceName!, parsed.action!);\n\n case \"global-action\":\n return executeGlobalAction(parsed.action!);\n\n default:\n throw new Error(`Cannot execute action on path: ${path}`);\n }\n } catch (error) {\n throw mapGCEError(error);\n }\n}\n\n/**\n * Execute an action on a specific instance\n */\nasync function executeInstanceAction(\n client: InstancesClient,\n projectId: string,\n zone: string,\n instanceName: string,\n action: string,\n): Promise<ActionResult> {\n // Get current instance state\n const [instance] = await client.get({\n project: projectId,\n zone,\n instance: instanceName,\n });\n\n const status = instance.status as GCEInstanceState;\n\n switch (action) {\n case \"start\":\n return startInstance(client, projectId, zone, instanceName, status);\n\n case \"stop\":\n return stopInstance(client, projectId, zone, instanceName, status);\n\n case \"reset\":\n return resetInstance(client, projectId, zone, instanceName, status);\n\n default:\n return {\n success: false,\n action,\n error: `Unknown action: ${action}`,\n };\n }\n}\n\n/**\n * Start an instance\n */\nasync function startInstance(\n client: InstancesClient,\n projectId: string,\n zone: string,\n instanceName: string,\n currentStatus: GCEInstanceState,\n): Promise<ActionResult> {\n // Can only start stopped or terminated instances\n if (currentStatus !== \"STOPPED\" && currentStatus !== \"TERMINATED\") {\n return {\n success: false,\n action: \"start\",\n error: `Cannot start instance in ${currentStatus} state. Instance must be STOPPED or TERMINATED.`,\n };\n }\n\n const [operation] = await client.start({\n project: projectId,\n zone,\n instance: instanceName,\n });\n\n return {\n success: true,\n action: \"start\",\n operationName: (operation as any).latestResponse?.name || \"unknown\",\n };\n}\n\n/**\n * Stop an instance\n */\nasync function stopInstance(\n client: InstancesClient,\n projectId: string,\n zone: string,\n instanceName: string,\n currentStatus: GCEInstanceState,\n): Promise<ActionResult> {\n // Can only stop running instances\n if (currentStatus !== \"RUNNING\") {\n return {\n success: false,\n action: \"stop\",\n error: `Cannot stop instance in ${currentStatus} state. Instance must be RUNNING.`,\n };\n }\n\n const [operation] = await client.stop({\n project: projectId,\n zone,\n instance: instanceName,\n });\n\n return {\n success: true,\n action: \"stop\",\n operationName: (operation as any).latestResponse?.name || \"unknown\",\n };\n}\n\n/**\n * Reset an instance\n */\nasync function resetInstance(\n client: InstancesClient,\n projectId: string,\n zone: string,\n instanceName: string,\n currentStatus: GCEInstanceState,\n): Promise<ActionResult> {\n // Can only reset running instances\n if (currentStatus !== \"RUNNING\") {\n return {\n success: false,\n action: \"reset\",\n error: `Cannot reset instance in ${currentStatus} state. Instance must be RUNNING.`,\n };\n }\n\n const [operation] = await client.reset({\n project: projectId,\n zone,\n instance: instanceName,\n });\n\n return {\n success: true,\n action: \"reset\",\n operationName: (operation as any).latestResponse?.name || \"unknown\",\n };\n}\n\n/**\n * Execute a global action\n */\nfunction executeGlobalAction(action: string): ActionResult {\n switch (action) {\n case \"refresh\":\n // Refresh is a no-op for now - cache clearing would happen at provider level\n return {\n success: true,\n action: \"refresh\",\n };\n\n default:\n return {\n success: false,\n action,\n error: `Unknown global action: ${action}`,\n };\n }\n}\n","/**\n * GCE Platform Reference\n *\n * Generates Google Cloud Console URLs for GCE resources.\n */\n\n/**\n * Platform reference containing console URL\n */\nexport interface GCEPlatformRef {\n consoleUrl: string;\n}\n\n/**\n * Generate platform reference with GCP Console URL for an instance\n *\n * @param projectId - GCP project ID\n * @param zone - GCE zone\n * @param instanceName - Instance name\n * @returns Platform reference with console URL\n */\nexport function generateInstancePlatformRef(\n projectId: string,\n zone: string,\n instanceName: string,\n): GCEPlatformRef {\n return {\n consoleUrl: `https://console.cloud.google.com/compute/instancesDetail/zones/${zone}/instances/${instanceName}?project=${projectId}`,\n };\n}\n\n/**\n * Generate platform reference with GCP Console URL for instances list\n *\n * @param projectId - GCP project ID\n * @returns Platform reference with console URL\n */\nexport function generateInstancesListPlatformRef(projectId: string): GCEPlatformRef {\n return {\n consoleUrl: `https://console.cloud.google.com/compute/instances?project=${projectId}`,\n };\n}\n","/**\n * AFS GCE Provider Types\n */\n\nimport { camelize, optionalize } from \"@aigne/afs/utils/zod\";\nimport { z } from \"zod\";\n\n/**\n * Configuration options for AFSGCE\n */\nexport interface AFSGCEOptions {\n /** Module name (used as mount path segment) */\n name?: string;\n\n /** Module description */\n description?: string;\n\n /** GCP project ID */\n projectId: string;\n\n /** GCE zone (e.g., us-central1-a) */\n zone: string;\n\n /** Access mode */\n accessMode?: \"readonly\" | \"readwrite\";\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 * GCE zone validation regex\n * Format: region-zone (e.g., us-central1-a, europe-west1-b)\n */\nconst ZONE_REGEX = /^[a-z]+-[a-z]+\\d+-[a-z]$/;\n\n/**\n * Zod schema for options validation\n */\nexport const afsgceOptionsSchema = camelize(\n z\n .object({\n name: optionalize(z.string()),\n description: optionalize(z.string()),\n projectId: z.string().min(1),\n zone: z.string().regex(ZONE_REGEX, \"Invalid GCE zone format (e.g., us-central1-a)\"),\n accessMode: optionalize(z.enum([\"readonly\", \"readwrite\"])),\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 * GCE instance states\n */\nexport const GCE_INSTANCE_STATES = [\n \"PROVISIONING\",\n \"STAGING\",\n \"RUNNING\",\n \"STOPPING\",\n \"STOPPED\",\n \"SUSPENDING\",\n \"SUSPENDED\",\n \"TERMINATED\",\n] as const;\n\nexport type GCEInstanceState = (typeof GCE_INSTANCE_STATES)[number];\n\n/**\n * Path types for GCE resources\n */\nexport type PathType =\n | \"root\"\n | \"instances\"\n | \"instance\"\n | \"instance-metadata\"\n | \"instance-actions\"\n | \"instance-action\"\n | \"actions\"\n | \"global-action\"\n | \"unknown\";\n\nexport interface ParsedPath {\n type: PathType;\n instanceName?: string;\n action?: string;\n fileName?: string;\n raw: string;\n}\n\n/**\n * Kind constants for GCE resources\n */\nexport const KINDS = {\n INSTANCE: \"gce:instance\",\n ACTION: \"gce:action\",\n EXECUTABLE: \"afs:executable\",\n NODE: \"afs:node\",\n GCP_RESOURCE: \"gcp:resource\",\n} as const;\n","/**\n * GCE List Operation\n *\n * Lists GCE resources.\n */\n\nimport type { AFSEntry, AFSListOptions, AFSListResult } from \"@aigne/afs\";\nimport type { InstancesClient } from \"@google-cloud/compute\";\nimport { mapGCEError } from \"../errors.js\";\nimport { buildPath, parsePath } from \"../path-resolver.js\";\nimport { generateInstancePlatformRef, generateInstancesListPlatformRef } from \"../platform-ref.js\";\nimport { type GCEInstanceState, KINDS } from \"../types.js\";\n\n/**\n * List GCE resources\n *\n * @param client - GCE InstancesClient\n * @param projectId - GCP project ID\n * @param zone - GCE zone\n * @param path - AFS path\n * @param options - List options\n * @returns List result with entries\n */\nexport async function list(\n client: InstancesClient,\n projectId: string,\n zone: string,\n path: string,\n options?: AFSListOptions,\n): Promise<AFSListResult> {\n try {\n const parsed = parsePath(path);\n\n switch (parsed.type) {\n case \"root\":\n return listRoot(projectId);\n\n case \"instances\":\n return listInstances(client, projectId, zone, options);\n\n case \"instance\":\n return listInstanceChildren(client, projectId, zone, parsed.instanceName!);\n\n case \"instance-actions\":\n return listInstanceActions(client, projectId, zone, parsed.instanceName!);\n\n case \"actions\":\n return listGlobalActions(projectId);\n\n default:\n return { data: [] };\n }\n } catch (error) {\n throw mapGCEError(error);\n }\n}\n\n/**\n * List root directory\n */\nfunction listRoot(projectId: string): AFSListResult {\n const entries: AFSEntry[] = [\n {\n id: `gce://${projectId}/instances`,\n path: \"/instances\",\n metadata: {\n kind: KINDS.NODE,\n kinds: [KINDS.NODE],\n childrenCount: 0,\n description: \"GCE Instances\",\n platformRef: generateInstancesListPlatformRef(projectId),\n },\n },\n {\n id: `gce://${projectId}/actions`,\n path: \"/actions\",\n metadata: {\n kind: KINDS.NODE,\n kinds: [KINDS.NODE],\n childrenCount: 0,\n description: \"Global Actions\",\n },\n },\n ];\n\n return { data: entries };\n}\n\n/**\n * List all instances\n */\nasync function listInstances(\n client: InstancesClient,\n projectId: string,\n zone: string,\n options?: AFSListOptions,\n): Promise<AFSListResult> {\n const maxChildren = options?.maxChildren ?? 1000;\n\n const [instances] = await client.list({\n project: projectId,\n zone,\n maxResults: maxChildren,\n });\n\n const entries: AFSEntry[] = (instances || []).map((instance) => {\n const name = instance.name!;\n const machineType = instance.machineType?.split(\"/\").pop() || \"unknown\";\n\n return {\n id: `gce://${projectId}/${zone}/${name}`,\n path: buildPath(\"instances\", name),\n metadata: {\n kind: KINDS.INSTANCE,\n kinds: [KINDS.INSTANCE, KINDS.GCP_RESOURCE, KINDS.NODE],\n childrenCount: 2, // metadata.json and actions\n status: instance.status as GCEInstanceState,\n machineType,\n privateIp: instance.networkInterfaces?.[0]?.networkIP,\n publicIp: instance.networkInterfaces?.[0]?.accessConfigs?.[0]?.natIP,\n createdAt: instance.creationTimestamp,\n labels: instance.labels,\n platformRef: generateInstancePlatformRef(projectId, zone, name),\n },\n };\n });\n\n return { data: entries };\n}\n\n/**\n * List instance children (metadata.json, actions)\n */\nasync function listInstanceChildren(\n client: InstancesClient,\n projectId: string,\n zone: string,\n instanceName: string,\n): Promise<AFSListResult> {\n // Verify instance exists\n await client.get({\n project: projectId,\n zone,\n instance: instanceName,\n });\n\n const entries: AFSEntry[] = [\n {\n id: `gce://${projectId}/${zone}/${instanceName}/metadata.json`,\n path: buildPath(\"instances\", instanceName, \"metadata.json\"),\n metadata: {\n kind: KINDS.NODE,\n kinds: [KINDS.NODE],\n description: \"Instance metadata\",\n },\n },\n {\n id: `gce://${projectId}/${zone}/${instanceName}/actions`,\n path: buildPath(\"instances\", instanceName, \"actions\"),\n metadata: {\n kind: KINDS.NODE,\n kinds: [KINDS.NODE],\n childrenCount: 0,\n description: \"Instance actions\",\n },\n },\n ];\n\n return { data: entries };\n}\n\n/**\n * List available actions for an instance\n */\nasync function listInstanceActions(\n client: InstancesClient,\n projectId: string,\n zone: string,\n instanceName: string,\n): Promise<AFSListResult> {\n const [instance] = await client.get({\n project: projectId,\n zone,\n instance: instanceName,\n });\n\n const status = instance.status as GCEInstanceState;\n const actions: string[] = [];\n\n // Available actions depend on instance state\n switch (status) {\n case \"RUNNING\":\n actions.push(\"stop\", \"reset\");\n break;\n case \"STOPPED\":\n case \"TERMINATED\":\n actions.push(\"start\");\n break;\n case \"SUSPENDED\":\n actions.push(\"resume\");\n break;\n default:\n // No actions available during transitional states\n break;\n }\n\n const entries: AFSEntry[] = actions.map((action) => ({\n id: `gce://${projectId}/${zone}/${instanceName}/actions/${action}`,\n path: buildPath(\"instances\", instanceName, \"actions\", action),\n metadata: {\n kind: KINDS.ACTION,\n kinds: [KINDS.ACTION, KINDS.EXECUTABLE, KINDS.NODE],\n description: `${action.charAt(0).toUpperCase() + action.slice(1)} the instance`,\n },\n }));\n\n return { data: entries };\n}\n\n/**\n * List global actions\n */\nfunction listGlobalActions(projectId: string): AFSListResult {\n const entries: AFSEntry[] = [\n {\n id: `gce://${projectId}/actions/refresh`,\n path: \"/actions/refresh\",\n metadata: {\n kind: KINDS.ACTION,\n kinds: [KINDS.ACTION, KINDS.EXECUTABLE, KINDS.NODE],\n description: \"Refresh instance cache\",\n },\n },\n ];\n\n return { data: entries };\n}\n","/**\n * GCE Read Operation\n *\n * Reads GCE resource data.\n */\n\nimport type { AFSReadOptions, AFSReadResult } from \"@aigne/afs\";\nimport type { InstancesClient } from \"@google-cloud/compute\";\nimport { mapGCEError } from \"../errors.js\";\nimport { buildPath, parsePath } from \"../path-resolver.js\";\nimport { KINDS } from \"../types.js\";\n\n/**\n * Read GCE resource data\n *\n * @param client - GCE InstancesClient\n * @param projectId - GCP project ID\n * @param zone - GCE zone\n * @param path - AFS path\n * @param options - Read options\n * @returns Read result with content\n */\nexport async function read(\n client: InstancesClient,\n projectId: string,\n zone: string,\n path: string,\n _options?: AFSReadOptions,\n): Promise<AFSReadResult> {\n try {\n const parsed = parsePath(path);\n\n switch (parsed.type) {\n case \"instance-metadata\":\n return readInstanceMetadata(client, projectId, zone, parsed.instanceName!);\n\n default:\n throw new Error(`Cannot read path: ${path}`);\n }\n } catch (error) {\n throw mapGCEError(error);\n }\n}\n\n/**\n * Read instance metadata as JSON\n */\nasync function readInstanceMetadata(\n client: InstancesClient,\n projectId: string,\n zone: string,\n instanceName: string,\n): Promise<AFSReadResult> {\n const [instance] = await client.get({\n project: projectId,\n zone,\n instance: instanceName,\n });\n\n // Return full instance data as JSON content\n return {\n data: {\n id: `gce://${projectId}/${zone}/${instanceName}/metadata.json`,\n path: buildPath(\"instances\", instanceName, \"metadata.json\"),\n metadata: {\n kind: KINDS.NODE,\n kinds: [KINDS.NODE],\n description: \"Instance metadata\",\n },\n content: JSON.stringify(instance, null, 2),\n },\n };\n}\n","/**\n * GCE Stat Operation\n *\n * Returns metadata for GCE resources.\n */\n\nimport type { AFSEntry } from \"@aigne/afs\";\nimport type { InstancesClient } from \"@google-cloud/compute\";\nimport { mapGCEError } from \"../errors.js\";\nimport { buildPath, parsePath } from \"../path-resolver.js\";\nimport { generateInstancePlatformRef, generateInstancesListPlatformRef } from \"../platform-ref.js\";\nimport { type GCEInstanceState, KINDS } from \"../types.js\";\n\n/**\n * Get metadata for a GCE resource\n *\n * @param client - GCE InstancesClient\n * @param projectId - GCP project ID\n * @param zone - GCE zone\n * @param path - AFS path\n * @returns Entry with metadata\n */\nexport async function stat(\n client: InstancesClient,\n projectId: string,\n zone: string,\n path: string,\n): Promise<AFSEntry> {\n try {\n const parsed = parsePath(path);\n\n switch (parsed.type) {\n case \"root\":\n return statRoot(projectId);\n\n case \"instances\":\n return statInstances(projectId);\n\n case \"instance\":\n return statInstance(client, projectId, zone, parsed.instanceName!);\n\n case \"instance-metadata\":\n return statInstanceMetadata(client, projectId, zone, parsed.instanceName!);\n\n case \"instance-actions\":\n return statInstanceActions(client, projectId, zone, parsed.instanceName!);\n\n case \"instance-action\":\n return statInstanceAction(client, projectId, zone, parsed.instanceName!, parsed.action!);\n\n case \"actions\":\n return statGlobalActions(projectId);\n\n case \"global-action\":\n return statGlobalAction(projectId, parsed.action!);\n\n default:\n throw new Error(`Path not found: ${path}`);\n }\n } catch (error) {\n throw mapGCEError(error);\n }\n}\n\n/**\n * Stat root directory\n */\nfunction statRoot(projectId: string): AFSEntry {\n return {\n id: `gce://${projectId}/`,\n path: \"/\",\n metadata: {\n kind: KINDS.NODE,\n kinds: [KINDS.NODE],\n childrenCount: 2,\n description: \"GCE Root\",\n },\n };\n}\n\n/**\n * Stat instances directory\n */\nfunction statInstances(projectId: string): AFSEntry {\n return {\n id: `gce://${projectId}/instances`,\n path: \"/instances\",\n metadata: {\n kind: KINDS.NODE,\n kinds: [KINDS.NODE],\n childrenCount: 0, // Dynamic\n description: \"GCE Instances\",\n platformRef: generateInstancesListPlatformRef(projectId),\n },\n };\n}\n\n/**\n * Stat a specific instance\n */\nasync function statInstance(\n client: InstancesClient,\n projectId: string,\n zone: string,\n instanceName: string,\n): Promise<AFSEntry> {\n const [instance] = await client.get({\n project: projectId,\n zone,\n instance: instanceName,\n });\n\n const machineType = instance.machineType?.split(\"/\").pop() || \"unknown\";\n\n return {\n id: `gce://${projectId}/${zone}/${instanceName}`,\n path: buildPath(\"instances\", instanceName),\n metadata: {\n kind: KINDS.INSTANCE,\n kinds: [KINDS.INSTANCE, KINDS.GCP_RESOURCE, KINDS.NODE],\n childrenCount: 2, // metadata.json and actions\n status: instance.status as GCEInstanceState,\n machineType,\n privateIp: instance.networkInterfaces?.[0]?.networkIP,\n publicIp: instance.networkInterfaces?.[0]?.accessConfigs?.[0]?.natIP,\n createdAt: instance.creationTimestamp,\n labels: instance.labels,\n platformRef: generateInstancePlatformRef(projectId, zone, instanceName),\n },\n };\n}\n\n/**\n * Stat instance metadata.json file\n */\nasync function statInstanceMetadata(\n client: InstancesClient,\n projectId: string,\n zone: string,\n instanceName: string,\n): Promise<AFSEntry> {\n // Verify instance exists\n await client.get({\n project: projectId,\n zone,\n instance: instanceName,\n });\n\n return {\n id: `gce://${projectId}/${zone}/${instanceName}/metadata.json`,\n path: buildPath(\"instances\", instanceName, \"metadata.json\"),\n metadata: {\n kind: KINDS.NODE,\n kinds: [KINDS.NODE],\n description: \"Instance metadata\",\n },\n };\n}\n\n/**\n * Stat instance actions directory\n */\nasync function statInstanceActions(\n client: InstancesClient,\n projectId: string,\n zone: string,\n instanceName: string,\n): Promise<AFSEntry> {\n // Verify instance exists\n await client.get({\n project: projectId,\n zone,\n instance: instanceName,\n });\n\n return {\n id: `gce://${projectId}/${zone}/${instanceName}/actions`,\n path: buildPath(\"instances\", instanceName, \"actions\"),\n metadata: {\n kind: KINDS.NODE,\n kinds: [KINDS.NODE],\n childrenCount: 0, // Dynamic based on state\n description: \"Instance actions\",\n },\n };\n}\n\n/**\n * Stat a specific instance action\n */\nasync function statInstanceAction(\n client: InstancesClient,\n projectId: string,\n zone: string,\n instanceName: string,\n action: string,\n): Promise<AFSEntry> {\n // Verify instance exists\n await client.get({\n project: projectId,\n zone,\n instance: instanceName,\n });\n\n return {\n id: `gce://${projectId}/${zone}/${instanceName}/actions/${action}`,\n path: buildPath(\"instances\", instanceName, \"actions\", action),\n metadata: {\n kind: KINDS.ACTION,\n kinds: [KINDS.ACTION, KINDS.EXECUTABLE, KINDS.NODE],\n description: `${action.charAt(0).toUpperCase() + action.slice(1)} the instance`,\n },\n };\n}\n\n/**\n * Stat global actions directory\n */\nfunction statGlobalActions(projectId: string): AFSEntry {\n return {\n id: `gce://${projectId}/actions`,\n path: \"/actions\",\n metadata: {\n kind: KINDS.NODE,\n kinds: [KINDS.NODE],\n childrenCount: 1,\n description: \"Global Actions\",\n },\n };\n}\n\n/**\n * Stat a specific global action\n */\nfunction statGlobalAction(projectId: string, action: string): AFSEntry {\n return {\n id: `gce://${projectId}/actions/${action}`,\n path: buildPath(\"actions\", action),\n metadata: {\n kind: KINDS.ACTION,\n kinds: [KINDS.ACTION, KINDS.EXECUTABLE, KINDS.NODE],\n description: `${action.charAt(0).toUpperCase() + action.slice(1)} action`,\n },\n };\n}\n","/**\n * AFS GCE Provider\n *\n * Provides AFS access to Google Compute Engine instances.\n */\n\nimport type {\n AFSListOptions,\n AFSListResult,\n AFSModule,\n AFSReadOptions,\n AFSReadResult,\n AFSStatResult,\n AFSWriteEntryPayload,\n AFSWriteOptions,\n AFSWriteResult,\n} from \"@aigne/afs\";\nimport { InstancesClient } from \"@google-cloud/compute\";\nimport { mapGCEError } from \"./errors.js\";\nimport { executeAction } from \"./operations/actions.js\";\nimport { list } from \"./operations/list.js\";\nimport { read } from \"./operations/read.js\";\nimport { stat } from \"./operations/stat.js\";\nimport { parsePath } from \"./path-resolver.js\";\nimport { type AFSGCEOptions, afsgceOptionsSchema, KINDS } from \"./types.js\";\n\n/**\n * AFS GCE Provider\n *\n * Provides a file-system-like interface to GCE instances.\n *\n * @example\n * ```typescript\n * const provider = new AFSGCE({\n * projectId: 'my-project',\n * zone: 'us-central1-a',\n * });\n *\n * // List instances\n * const instances = await provider.list('/instances');\n *\n * // Get instance metadata\n * const metadata = await provider.read('/instances/my-vm/metadata.json');\n *\n * // Start an instance (requires readwrite mode)\n * await provider.write('/instances/my-vm/actions/start', {});\n * ```\n */\nexport class AFSGCE implements AFSModule {\n readonly name: string;\n readonly description?: string;\n readonly accessMode: \"readonly\" | \"readwrite\";\n\n private readonly client: InstancesClient;\n private readonly projectId: string;\n private readonly zone: string;\n\n constructor(options: AFSGCEOptions) {\n // Validate options\n const validated = afsgceOptionsSchema.parse(options);\n\n this.name = validated.name || \"gce\";\n this.description = validated.description;\n this.accessMode = validated.accessMode || \"readonly\";\n this.projectId = validated.projectId;\n this.zone = validated.zone;\n\n // Create compute client\n this.client = new InstancesClient({\n keyFilename: validated.keyFilename,\n credentials: validated.credentials\n ? {\n client_email: validated.credentials.clientEmail,\n private_key: validated.credentials.privateKey,\n }\n : undefined,\n });\n }\n\n /**\n * List GCE resources\n */\n async list(path: string, options?: AFSListOptions): Promise<AFSListResult> {\n return list(this.client, this.projectId, this.zone, path, options);\n }\n\n /**\n * Get metadata for a GCE resource\n */\n async stat(path: string): Promise<AFSStatResult> {\n const entry = await stat(this.client, this.projectId, this.zone, path);\n return {\n data: {\n path: entry.path,\n childrenCount: entry.metadata?.childrenCount as number | undefined,\n meta: entry.metadata as Record<string, unknown>,\n },\n };\n }\n\n /**\n * Read GCE resource data\n */\n async read(path: string, options?: AFSReadOptions): Promise<AFSReadResult> {\n return read(this.client, this.projectId, this.zone, path, options);\n }\n\n /**\n * Write/execute action on GCE resource\n *\n * In GCE, write is used to execute actions (start, stop, reset)\n */\n async write(\n path: string,\n _content: AFSWriteEntryPayload,\n _options?: AFSWriteOptions,\n ): Promise<AFSWriteResult> {\n if (this.accessMode !== \"readwrite\") {\n throw mapGCEError(new Error(\"Write operations require readwrite access mode\"));\n }\n\n const parsed = parsePath(path);\n\n if (parsed.type === \"instance-action\" || parsed.type === \"global-action\") {\n const result = await executeAction(this.client, this.projectId, this.zone, path);\n\n // Convert ActionResult to AFSWriteResult\n return {\n data: {\n id: `gce://${this.projectId}/${this.zone}/${path}`,\n path,\n metadata: {\n kind: KINDS.ACTION,\n kinds: [KINDS.ACTION, KINDS.EXECUTABLE, KINDS.NODE],\n success: result.success,\n operationName: result.operationName,\n error: result.error,\n },\n },\n message: result.success\n ? `Action ${result.action} executed successfully`\n : `Action ${result.action} failed: ${result.error}`,\n };\n }\n\n throw mapGCEError(new Error(`Cannot write to path: ${path}`));\n }\n}\n\n// Re-export types\nexport type { AFSGCEOptions } from \"./types.js\";\nexport { afsgceOptionsSchema } from \"./types.js\";\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@aigne/afs-gce",
3
+ "version": "1.11.0-beta.6",
4
+ "description": "AIGNE AFS module for Google Compute Engine resources",
5
+ "license": "UNLICENSED",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "author": "Arcblock <blocklet@arcblock.io> https://github.com/arcblock",
10
+ "homepage": "https://github.com/arcblock/afs",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/arcblock/afs"
14
+ },
15
+ "bugs": {
16
+ "url": "https://github.com/arcblock/afs/issues"
17
+ },
18
+ "type": "module",
19
+ "main": "./dist/index.cjs",
20
+ "module": "./dist/index.mjs",
21
+ "types": "./dist/index.d.cts",
22
+ "exports": {
23
+ ".": {
24
+ "require": "./dist/index.cjs",
25
+ "import": "./dist/index.mjs"
26
+ },
27
+ "./*": "./*"
28
+ },
29
+ "files": [
30
+ "dist",
31
+ "LICENSE",
32
+ "README.md",
33
+ "CHANGELOG.md"
34
+ ],
35
+ "dependencies": {
36
+ "@google-cloud/compute": "^4.10.0",
37
+ "zod": "^3.25.67",
38
+ "@aigne/afs": "^1.11.0-beta.6"
39
+ },
40
+ "devDependencies": {
41
+ "@types/bun": "^1.3.6",
42
+ "npm-run-all": "^4.1.5",
43
+ "rimraf": "^6.1.2",
44
+ "tsdown": "0.20.0-beta.3",
45
+ "typescript": "5.9.2",
46
+ "@aigne/scripts": "0.0.0",
47
+ "@aigne/typescript-config": "0.0.0"
48
+ },
49
+ "scripts": {
50
+ "build": "tsdown",
51
+ "check-types": "tsc --noEmit",
52
+ "clean": "rimraf dist coverage",
53
+ "test": "SKIP_E2E=1 bun test",
54
+ "test:e2e": "GOOGLE_APPLICATION_CREDENTIALS=${GOOGLE_APPLICATION_CREDENTIALS:-} bun test test/e2e.test.ts",
55
+ "test:all": "bun test",
56
+ "test:coverage": "bun test --coverage --coverage-reporter=lcov --coverage-reporter=text"
57
+ }
58
+ }