@aigne/afs-gce 1.11.0-beta.6 → 1.11.0-beta.7

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.mjs CHANGED
@@ -1,273 +1,9 @@
1
+ import { AFSBaseProvider, AFSNotFoundError, AFSReadonlyError, Actions, Delete, Explain, List, Meta, Read, Stat, Write } from "@aigne/afs";
2
+ import { camelize, optionalize, zodParse } from "@aigne/afs/utils/zod";
1
3
  import { InstancesClient } from "@google-cloud/compute";
2
- import { camelize, optionalize } from "@aigne/afs/utils/zod";
4
+ import { joinURL } from "ufo";
3
5
  import { z } from "zod";
4
6
 
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
7
  //#region src/platform-ref.ts
272
8
  /**
273
9
  * Generate platform reference with GCP Console URL for an instance
@@ -317,6 +53,19 @@ const afsgceOptionsSchema = camelize(z.object({
317
53
  cacheTtl: optionalize(z.number().int().min(0))
318
54
  }).strict());
319
55
  /**
56
+ * GCE instance states
57
+ */
58
+ const GCE_INSTANCE_STATES = [
59
+ "PROVISIONING",
60
+ "STAGING",
61
+ "RUNNING",
62
+ "STOPPING",
63
+ "STOPPED",
64
+ "SUSPENDING",
65
+ "SUSPENDED",
66
+ "TERMINATED"
67
+ ];
68
+ /**
320
69
  * Kind constants for GCE resources
321
70
  */
322
71
  const KINDS = {
@@ -328,433 +77,58 @@ const KINDS = {
328
77
  };
329
78
 
330
79
  //#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
- }] };
80
+ //#region \0@oxc-project+runtime@0.108.0/helpers/decorate.js
81
+ function __decorate(decorators, target, key, desc) {
82
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
83
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
84
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
85
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
500
86
  }
501
87
 
502
88
  //#endregion
503
- //#region src/operations/read.ts
89
+ //#region src/index.ts
504
90
  /**
505
- * Read GCE resource data
91
+ * AFS GCE Provider
506
92
  *
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
93
+ * GCE provider using AFSBaseProvider decorator routing pattern.
94
+ * Provides file-system-like access to Google Compute Engine instances.
527
95
  */
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
96
  /**
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
97
+ * Map GCE SDK errors to appropriate AFS errors
556
98
  */
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);
99
+ function mapGCEError(error, path) {
100
+ if (error instanceof AFSNotFoundError || error instanceof AFSReadonlyError) return error;
101
+ if (typeof error === "object" && error !== null && "code" in error) {
102
+ const err = error;
103
+ if (err.code === 404) return new AFSNotFoundError(path ?? "/", err.message);
573
104
  }
105
+ if (error instanceof Error) return error;
106
+ return new Error(String(error));
574
107
  }
575
108
  /**
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
109
+ * AFSGCE Provider using AFSBaseProvider pattern
737
110
  *
738
- * Provides a file-system-like interface to GCE instances.
111
+ * Provides file-system-like access to GCE instances.
112
+ * Uses decorator routing (@List, @Read, @Write, @Delete, @Meta, @Actions, @Explain).
739
113
  *
740
114
  * @example
741
115
  * ```typescript
742
- * const provider = new AFSGCE({
743
- * projectId: 'my-project',
744
- * zone: 'us-central1-a',
116
+ * const gce = new AFSGCE({
117
+ * projectId: "my-project",
118
+ * zone: "us-central1-a",
745
119
  * });
746
120
  *
747
- * // List instances
748
- * const instances = await provider.list('/instances');
121
+ * // Mount to AFS
122
+ * afs.mount(gce);
749
123
  *
750
- * // Get instance metadata
751
- * const metadata = await provider.read('/instances/my-vm/metadata.json');
124
+ * // List instances
125
+ * const result = await afs.list("/modules/gce/instances");
752
126
  *
753
- * // Start an instance (requires readwrite mode)
754
- * await provider.write('/instances/my-vm/actions/start', {});
127
+ * // Read instance metadata
128
+ * const meta = await afs.read("/modules/gce/instances/my-vm/metadata.json");
755
129
  * ```
756
130
  */
757
- var AFSGCE = class {
131
+ var AFSGCE = class AFSGCE extends AFSBaseProvider {
758
132
  name;
759
133
  description;
760
134
  accessMode;
@@ -762,6 +136,7 @@ var AFSGCE = class {
762
136
  projectId;
763
137
  zone;
764
138
  constructor(options) {
139
+ super();
765
140
  const validated = afsgceOptionsSchema.parse(options);
766
141
  this.name = validated.name || "gce";
767
142
  this.description = validated.description;
@@ -776,61 +151,577 @@ var AFSGCE = class {
776
151
  } : void 0
777
152
  });
778
153
  }
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);
154
+ static schema() {
155
+ return afsgceOptionsSchema;
156
+ }
157
+ static async load({ basePath, config } = {}) {
158
+ return new AFSGCE(zodParse(afsgceOptionsSchema, config, { prefix: basePath }));
159
+ }
160
+ async getInstance(instanceName) {
161
+ try {
162
+ const [instance] = await this.client.get({
163
+ project: this.projectId,
164
+ zone: this.zone,
165
+ instance: instanceName
166
+ });
167
+ return instance;
168
+ } catch (error) {
169
+ throw mapGCEError(error, joinURL("/instances", instanceName));
170
+ }
171
+ }
172
+ async listAllInstances(maxResults) {
173
+ const [instances] = await this.client.list({
174
+ project: this.projectId,
175
+ zone: this.zone,
176
+ maxResults: maxResults ?? 1e3
177
+ });
178
+ return instances || [];
179
+ }
180
+ buildInstanceEntry(instance, basePath) {
181
+ const name = instance.name;
182
+ const machineType = instance.machineType?.split("/").pop() || "unknown";
183
+ return {
184
+ id: `gce://${this.projectId}/${this.zone}/${name}`,
185
+ path: joinURL(basePath, name),
186
+ meta: {
187
+ kind: KINDS.INSTANCE,
188
+ kinds: [
189
+ KINDS.INSTANCE,
190
+ KINDS.GCP_RESOURCE,
191
+ KINDS.NODE
192
+ ],
193
+ childrenCount: -1,
194
+ status: instance.status,
195
+ machineType,
196
+ privateIp: instance.networkInterfaces?.[0]?.networkIP,
197
+ publicIp: instance.networkInterfaces?.[0]?.accessConfigs?.[0]?.natIP,
198
+ createdAt: instance.creationTimestamp,
199
+ labels: instance.labels,
200
+ platformRef: generateInstancePlatformRef(this.projectId, this.zone, name)
201
+ }
202
+ };
203
+ }
204
+ async listRoot(_ctx) {
205
+ return { data: [{
206
+ id: `gce://${this.projectId}/instances`,
207
+ path: "/instances",
208
+ meta: {
209
+ kind: KINDS.NODE,
210
+ kinds: [KINDS.NODE],
211
+ childrenCount: -1,
212
+ description: "GCE Instances",
213
+ platformRef: generateInstancesListPlatformRef(this.projectId)
214
+ }
215
+ }, {
216
+ id: `gce://${this.projectId}/by-status`,
217
+ path: "/by-status",
218
+ meta: {
219
+ kind: KINDS.NODE,
220
+ kinds: [KINDS.NODE],
221
+ childrenCount: GCE_INSTANCE_STATES.length,
222
+ description: "Instances grouped by status"
223
+ }
224
+ }] };
225
+ }
226
+ async listInstances(_ctx) {
227
+ try {
228
+ return { data: (await this.listAllInstances()).map((instance) => this.buildInstanceEntry(instance, "/instances")) };
229
+ } catch (error) {
230
+ throw mapGCEError(error, "/instances");
231
+ }
232
+ }
233
+ async listInstanceChildren(ctx) {
234
+ await this.getInstance(ctx.params.instanceId);
235
+ return { data: [{
236
+ id: `gce://${this.projectId}/${this.zone}/${ctx.params.instanceId}/metadata.json`,
237
+ path: joinURL(ctx.path, "metadata.json"),
238
+ meta: {
239
+ kind: KINDS.NODE,
240
+ kinds: [KINDS.NODE],
241
+ description: "Instance metadata"
242
+ }
243
+ }, {
244
+ id: `gce://${this.projectId}/${this.zone}/${ctx.params.instanceId}/labels`,
245
+ path: joinURL(ctx.path, "labels"),
246
+ meta: {
247
+ kind: KINDS.NODE,
248
+ kinds: [KINDS.NODE],
249
+ childrenCount: -1,
250
+ description: "Instance labels"
251
+ }
252
+ }] };
253
+ }
254
+ async listInstanceLabels(ctx) {
255
+ const labels = (await this.getInstance(ctx.params.instanceId)).labels || {};
256
+ return { data: Object.entries(labels).map(([key, value]) => ({
257
+ id: `gce://${this.projectId}/${this.zone}/${ctx.params.instanceId}/labels/${key}`,
258
+ path: joinURL(ctx.path, encodeURIComponent(key)),
259
+ content: value,
260
+ meta: { kind: "gce:label" }
261
+ })) };
262
+ }
263
+ async listByStatus(_ctx) {
264
+ return { data: GCE_INSTANCE_STATES.map((status) => ({
265
+ id: `gce://${this.projectId}/by-status/${status.toLowerCase()}`,
266
+ path: joinURL("/by-status", status.toLowerCase()),
267
+ meta: {
268
+ kind: KINDS.NODE,
269
+ kinds: [KINDS.NODE],
270
+ childrenCount: -1,
271
+ description: `Instances in ${status} state`
272
+ }
273
+ })) };
274
+ }
275
+ async listByStatusFilter(ctx) {
276
+ try {
277
+ const statusUpper = ctx.params.status.toUpperCase();
278
+ return { data: (await this.listAllInstances()).filter((inst) => inst.status?.toUpperCase() === statusUpper).map((instance) => this.buildInstanceEntry(instance, ctx.path)) };
279
+ } catch (error) {
280
+ throw mapGCEError(error, ctx.path);
281
+ }
282
+ }
283
+ async readCapabilities(_ctx) {
284
+ const actionCatalogs = [];
285
+ actionCatalogs.push({
286
+ kind: "gce:instance",
287
+ description: "Instance lifecycle operations",
288
+ catalog: [
289
+ {
290
+ name: "start",
291
+ description: "Start a stopped or terminated instance",
292
+ inputSchema: {
293
+ type: "object",
294
+ properties: {}
295
+ }
296
+ },
297
+ {
298
+ name: "stop",
299
+ description: "Stop a running instance",
300
+ inputSchema: {
301
+ type: "object",
302
+ properties: {}
303
+ }
304
+ },
305
+ {
306
+ name: "reset",
307
+ description: "Reset (hard reboot) a running instance",
308
+ inputSchema: {
309
+ type: "object",
310
+ properties: {}
311
+ }
312
+ }
313
+ ],
314
+ discovery: {
315
+ pathTemplate: "/instances/:instanceName/.actions",
316
+ note: "Replace :instanceName with actual instance name"
317
+ }
318
+ });
319
+ if (this.accessMode === "readwrite") actionCatalogs.push({
320
+ kind: "gce:global",
321
+ description: "Global GCE operations",
322
+ catalog: [{
323
+ name: "refresh",
324
+ description: "Refresh cached instance data",
325
+ inputSchema: {
326
+ type: "object",
327
+ properties: {}
328
+ }
329
+ }],
330
+ discovery: {
331
+ pathTemplate: "/.actions",
332
+ note: "Available at provider root"
333
+ }
334
+ });
335
+ return {
336
+ id: "/.meta/.capabilities",
337
+ path: "/.meta/.capabilities",
338
+ content: {
339
+ schemaVersion: 1,
340
+ provider: this.name,
341
+ version: "1.0.0",
342
+ description: this.description,
343
+ tools: [],
344
+ actions: actionCatalogs,
345
+ operations: this.getOperationsDeclaration()
346
+ },
347
+ meta: { kind: "afs:capabilities" }
348
+ };
349
+ }
350
+ async readInstanceMetadata(ctx) {
351
+ try {
352
+ const instance = await this.getInstance(ctx.params.instanceId);
353
+ return {
354
+ id: `gce://${this.projectId}/${this.zone}/${ctx.params.instanceId}/metadata.json`,
355
+ path: ctx.path,
356
+ meta: {
357
+ kind: KINDS.NODE,
358
+ kinds: [KINDS.NODE],
359
+ description: "Instance metadata"
360
+ },
361
+ content: JSON.stringify(instance, null, 2)
362
+ };
363
+ } catch (error) {
364
+ throw mapGCEError(error, ctx.path);
365
+ }
366
+ }
367
+ async readInstanceLabel(ctx) {
368
+ const value = ((await this.getInstance(ctx.params.instanceId)).labels || {})[ctx.params.labelKey];
369
+ if (value === void 0) throw new AFSNotFoundError(ctx.path);
370
+ return {
371
+ id: `gce://${this.projectId}/${this.zone}/${ctx.params.instanceId}/labels/${ctx.params.labelKey}`,
372
+ path: ctx.path,
373
+ content: value,
374
+ meta: { kind: "gce:label" }
375
+ };
376
+ }
377
+ async metaRoot(ctx) {
378
+ return {
379
+ id: `gce://${this.projectId}/`,
380
+ path: ctx.path,
381
+ meta: {
382
+ kind: KINDS.NODE,
383
+ kinds: [KINDS.NODE],
384
+ childrenCount: 2,
385
+ description: "GCE Root"
386
+ }
387
+ };
388
+ }
389
+ async metaInstances(ctx) {
390
+ return {
391
+ id: `gce://${this.projectId}/instances`,
392
+ path: ctx.path,
393
+ meta: {
394
+ kind: KINDS.NODE,
395
+ kinds: [KINDS.NODE],
396
+ childrenCount: -1,
397
+ description: "GCE Instances",
398
+ platformRef: generateInstancesListPlatformRef(this.projectId)
399
+ }
400
+ };
401
+ }
402
+ async metaInstance(ctx) {
403
+ try {
404
+ const instance = await this.getInstance(ctx.params.instanceId);
405
+ const machineType = instance.machineType?.split("/").pop() || "unknown";
406
+ return {
407
+ id: `gce://${this.projectId}/${this.zone}/${ctx.params.instanceId}`,
408
+ path: ctx.path,
409
+ meta: {
410
+ kind: KINDS.INSTANCE,
411
+ kinds: [
412
+ KINDS.INSTANCE,
413
+ KINDS.GCP_RESOURCE,
414
+ KINDS.NODE
415
+ ],
416
+ childrenCount: -1,
417
+ status: instance.status,
418
+ machineType,
419
+ privateIp: instance.networkInterfaces?.[0]?.networkIP,
420
+ publicIp: instance.networkInterfaces?.[0]?.accessConfigs?.[0]?.natIP,
421
+ createdAt: instance.creationTimestamp,
422
+ labels: instance.labels,
423
+ platformRef: generateInstancePlatformRef(this.projectId, this.zone, ctx.params.instanceId)
424
+ }
425
+ };
426
+ } catch (error) {
427
+ throw mapGCEError(error, ctx.path);
428
+ }
429
+ }
430
+ async statRoot(ctx) {
431
+ const meta = await this.metaRoot(ctx);
790
432
  return { data: {
791
- path: entry.path,
792
- childrenCount: entry.metadata?.childrenCount,
793
- meta: entry.metadata
433
+ id: meta.id,
434
+ path: ctx.path,
435
+ meta: meta.meta
794
436
  } };
795
437
  }
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);
438
+ async statInstances(ctx) {
439
+ const meta = await this.metaInstances(ctx);
440
+ return { data: {
441
+ id: meta.id,
442
+ path: ctx.path,
443
+ meta: meta.meta
444
+ } };
445
+ }
446
+ async statInstance(ctx) {
447
+ const meta = await this.metaInstance(ctx);
448
+ return { data: {
449
+ id: meta.id,
450
+ path: ctx.path,
451
+ meta: meta.meta
452
+ } };
453
+ }
454
+ async writeInstanceLabel(ctx, payload) {
455
+ if (this.accessMode !== "readwrite") throw new AFSReadonlyError("Write operations require readwrite access mode");
456
+ try {
457
+ const instance = await this.getInstance(ctx.params.instanceId);
458
+ const labels = { ...instance.labels || {} };
459
+ labels[ctx.params.labelKey] = String(payload.content ?? "");
460
+ await this.client.setLabels({
461
+ project: this.projectId,
462
+ zone: this.zone,
463
+ instance: ctx.params.instanceId,
464
+ instancesSetLabelsRequestResource: {
465
+ labels,
466
+ labelFingerprint: instance.labelFingerprint
467
+ }
468
+ });
812
469
  return {
813
470
  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
- }
471
+ id: `gce://${this.projectId}/${this.zone}/${ctx.params.instanceId}/labels/${ctx.params.labelKey}`,
472
+ path: ctx.path,
473
+ content: payload.content,
474
+ meta: { kind: "gce:label" }
827
475
  },
828
- message: result.success ? `Action ${result.action} executed successfully` : `Action ${result.action} failed: ${result.error}`
476
+ message: `Label '${ctx.params.labelKey}' set on instance '${ctx.params.instanceId}'`
477
+ };
478
+ } catch (error) {
479
+ throw mapGCEError(error, ctx.path);
480
+ }
481
+ }
482
+ async deleteInstanceLabel(ctx) {
483
+ if (this.accessMode !== "readwrite") throw new AFSReadonlyError("Delete operations require readwrite access mode");
484
+ try {
485
+ const instance = await this.getInstance(ctx.params.instanceId);
486
+ const labels = { ...instance.labels || {} };
487
+ if (!(ctx.params.labelKey in labels)) throw new AFSNotFoundError(ctx.path, `Label '${ctx.params.labelKey}' not found on instance '${ctx.params.instanceId}'`);
488
+ delete labels[ctx.params.labelKey];
489
+ await this.client.setLabels({
490
+ project: this.projectId,
491
+ zone: this.zone,
492
+ instance: ctx.params.instanceId,
493
+ instancesSetLabelsRequestResource: {
494
+ labels,
495
+ labelFingerprint: instance.labelFingerprint
496
+ }
497
+ });
498
+ return { message: `Label '${ctx.params.labelKey}' removed from instance '${ctx.params.instanceId}'` };
499
+ } catch (error) {
500
+ if (error instanceof AFSNotFoundError) throw error;
501
+ throw mapGCEError(error, ctx.path);
502
+ }
503
+ }
504
+ async listGlobalActions(ctx) {
505
+ return { data: [{
506
+ id: "refresh",
507
+ path: joinURL(ctx.path, "refresh"),
508
+ summary: "Refresh instance cache",
509
+ meta: {
510
+ kind: "afs:executable",
511
+ kinds: ["afs:executable", "afs:node"],
512
+ inputSchema: {
513
+ type: "object",
514
+ properties: {}
515
+ }
516
+ }
517
+ }] };
518
+ }
519
+ async refreshAction(_ctx, _args) {
520
+ return {
521
+ success: true,
522
+ data: { message: "Cache refreshed" }
523
+ };
524
+ }
525
+ async listInstanceActions(ctx) {
526
+ const status = (await this.getInstance(ctx.params.instanceId)).status;
527
+ const actions = [];
528
+ switch (status) {
529
+ case "RUNNING":
530
+ actions.push({
531
+ name: "stop",
532
+ summary: "Stop the instance"
533
+ }, {
534
+ name: "reset",
535
+ summary: "Reset (hard reboot) the instance"
536
+ });
537
+ break;
538
+ case "STOPPED":
539
+ case "TERMINATED":
540
+ actions.push({
541
+ name: "start",
542
+ summary: "Start the instance"
543
+ });
544
+ break;
545
+ case "SUSPENDED":
546
+ actions.push({
547
+ name: "start",
548
+ summary: "Resume the instance"
549
+ });
550
+ break;
551
+ }
552
+ return { data: actions.map((action) => ({
553
+ id: action.name,
554
+ path: joinURL(ctx.path, action.name),
555
+ summary: action.summary,
556
+ meta: {
557
+ kind: "afs:executable",
558
+ kinds: ["afs:executable", "afs:node"],
559
+ inputSchema: {
560
+ type: "object",
561
+ properties: {}
562
+ }
563
+ }
564
+ })) };
565
+ }
566
+ async startInstanceAction(ctx, _args) {
567
+ try {
568
+ const status = (await this.getInstance(ctx.params.instanceId)).status;
569
+ if (status !== "STOPPED" && status !== "TERMINATED") return {
570
+ success: false,
571
+ error: {
572
+ code: "INVALID_STATE",
573
+ message: `Cannot start instance in ${status} state. Instance must be STOPPED or TERMINATED.`
574
+ }
575
+ };
576
+ const [operation] = await this.client.start({
577
+ project: this.projectId,
578
+ zone: this.zone,
579
+ instance: ctx.params.instanceId
580
+ });
581
+ return {
582
+ success: true,
583
+ data: { operationName: operation.latestResponse?.name || "unknown" }
584
+ };
585
+ } catch (error) {
586
+ throw mapGCEError(error, ctx.path);
587
+ }
588
+ }
589
+ async stopInstanceAction(ctx, _args) {
590
+ try {
591
+ const status = (await this.getInstance(ctx.params.instanceId)).status;
592
+ if (status !== "RUNNING") return {
593
+ success: false,
594
+ error: {
595
+ code: "INVALID_STATE",
596
+ message: `Cannot stop instance in ${status} state. Instance must be RUNNING.`
597
+ }
598
+ };
599
+ const [operation] = await this.client.stop({
600
+ project: this.projectId,
601
+ zone: this.zone,
602
+ instance: ctx.params.instanceId
603
+ });
604
+ return {
605
+ success: true,
606
+ data: { operationName: operation.latestResponse?.name || "unknown" }
607
+ };
608
+ } catch (error) {
609
+ throw mapGCEError(error, ctx.path);
610
+ }
611
+ }
612
+ async resetInstanceAction(ctx, _args) {
613
+ try {
614
+ const status = (await this.getInstance(ctx.params.instanceId)).status;
615
+ if (status !== "RUNNING") return {
616
+ success: false,
617
+ error: {
618
+ code: "INVALID_STATE",
619
+ message: `Cannot reset instance in ${status} state. Instance must be RUNNING.`
620
+ }
621
+ };
622
+ const [operation] = await this.client.reset({
623
+ project: this.projectId,
624
+ zone: this.zone,
625
+ instance: ctx.params.instanceId
626
+ });
627
+ return {
628
+ success: true,
629
+ data: { operationName: operation.latestResponse?.name || "unknown" }
630
+ };
631
+ } catch (error) {
632
+ throw mapGCEError(error, ctx.path);
633
+ }
634
+ }
635
+ async explainRoot(_ctx) {
636
+ try {
637
+ const instances = await this.listAllInstances();
638
+ const byStatus = {};
639
+ for (const inst of instances) {
640
+ const status = inst.status || "UNKNOWN";
641
+ byStatus[status] = (byStatus[status] || 0) + 1;
642
+ }
643
+ const statusLines = Object.entries(byStatus).map(([status, count]) => `- **${status}**: ${count}`).join("\n");
644
+ return {
645
+ format: "markdown",
646
+ content: `# GCE Provider
647
+
648
+ - **Project**: ${this.projectId}
649
+ - **Zone**: ${this.zone}
650
+ - **Access Mode**: ${this.accessMode}
651
+ - **Total Instances**: ${instances.length}
652
+
653
+ ## Instances by Status
654
+
655
+ ${statusLines || "- No instances found"}
656
+
657
+ ## Navigation
658
+
659
+ - \`/instances/\` — list all instances
660
+ - \`/by-status/\` — instances grouped by status
661
+ - \`/.actions/\` — global actions
662
+ `
663
+ };
664
+ } catch (error) {
665
+ throw mapGCEError(error);
666
+ }
667
+ }
668
+ async explainInstance(ctx) {
669
+ try {
670
+ const instance = await this.getInstance(ctx.params.instanceId);
671
+ const machineType = instance.machineType?.split("/").pop() || "unknown";
672
+ const privateIp = instance.networkInterfaces?.[0]?.networkIP || "none";
673
+ const publicIp = instance.networkInterfaces?.[0]?.accessConfigs?.[0]?.natIP || "none";
674
+ const labels = instance.labels || {};
675
+ const labelLines = Object.entries(labels).map(([k, v]) => `- \`${k}\`: ${v}`).join("\n");
676
+ return {
677
+ format: "markdown",
678
+ content: `# Instance: ${ctx.params.instanceId}
679
+
680
+ - **Status**: ${instance.status}
681
+ - **Machine Type**: ${machineType}
682
+ - **Zone**: ${this.zone}
683
+ - **Created**: ${instance.creationTimestamp || "unknown"}
684
+
685
+ ## Network
686
+
687
+ - **Private IP**: ${privateIp}
688
+ - **Public IP**: ${publicIp}
689
+
690
+ ## Labels
691
+
692
+ ${labelLines || "- No labels"}
693
+ `
829
694
  };
695
+ } catch (error) {
696
+ throw mapGCEError(error, ctx.path);
830
697
  }
831
- throw mapGCEError(/* @__PURE__ */ new Error(`Cannot write to path: ${path}`));
832
698
  }
833
699
  };
700
+ __decorate([List("/")], AFSGCE.prototype, "listRoot", null);
701
+ __decorate([List("/instances")], AFSGCE.prototype, "listInstances", null);
702
+ __decorate([List("/instances/:instanceId"), List("/by-status/:status/:instanceId")], AFSGCE.prototype, "listInstanceChildren", null);
703
+ __decorate([List("/instances/:instanceId/labels"), List("/by-status/:status/:instanceId/labels")], AFSGCE.prototype, "listInstanceLabels", null);
704
+ __decorate([List("/by-status")], AFSGCE.prototype, "listByStatus", null);
705
+ __decorate([List("/by-status/:status")], AFSGCE.prototype, "listByStatusFilter", null);
706
+ __decorate([Read("/.meta/.capabilities")], AFSGCE.prototype, "readCapabilities", null);
707
+ __decorate([Read("/instances/:instanceId/metadata.json"), Read("/by-status/:status/:instanceId/metadata.json")], AFSGCE.prototype, "readInstanceMetadata", null);
708
+ __decorate([Read("/instances/:instanceId/labels/:labelKey"), Read("/by-status/:status/:instanceId/labels/:labelKey")], AFSGCE.prototype, "readInstanceLabel", null);
709
+ __decorate([Meta("/")], AFSGCE.prototype, "metaRoot", null);
710
+ __decorate([Meta("/instances")], AFSGCE.prototype, "metaInstances", null);
711
+ __decorate([Meta("/instances/:instanceId"), Meta("/by-status/:status/:instanceId")], AFSGCE.prototype, "metaInstance", null);
712
+ __decorate([Stat("/")], AFSGCE.prototype, "statRoot", null);
713
+ __decorate([Stat("/instances")], AFSGCE.prototype, "statInstances", null);
714
+ __decorate([Stat("/instances/:instanceId"), Stat("/by-status/:status/:instanceId")], AFSGCE.prototype, "statInstance", null);
715
+ __decorate([Write("/instances/:instanceId/labels/:labelKey"), Write("/by-status/:status/:instanceId/labels/:labelKey")], AFSGCE.prototype, "writeInstanceLabel", null);
716
+ __decorate([Delete("/instances/:instanceId/labels/:labelKey"), Delete("/by-status/:status/:instanceId/labels/:labelKey")], AFSGCE.prototype, "deleteInstanceLabel", null);
717
+ __decorate([Actions("/")], AFSGCE.prototype, "listGlobalActions", null);
718
+ __decorate([Actions.Exec("/", "refresh")], AFSGCE.prototype, "refreshAction", null);
719
+ __decorate([Actions("/instances/:instanceId"), Actions("/by-status/:status/:instanceId")], AFSGCE.prototype, "listInstanceActions", null);
720
+ __decorate([Actions.Exec("/instances/:instanceId", "start"), Actions.Exec("/by-status/:status/:instanceId", "start")], AFSGCE.prototype, "startInstanceAction", null);
721
+ __decorate([Actions.Exec("/instances/:instanceId", "stop"), Actions.Exec("/by-status/:status/:instanceId", "stop")], AFSGCE.prototype, "stopInstanceAction", null);
722
+ __decorate([Actions.Exec("/instances/:instanceId", "reset"), Actions.Exec("/by-status/:status/:instanceId", "reset")], AFSGCE.prototype, "resetInstanceAction", null);
723
+ __decorate([Explain("/")], AFSGCE.prototype, "explainRoot", null);
724
+ __decorate([Explain("/instances/:instanceId"), Explain("/by-status/:status/:instanceId")], AFSGCE.prototype, "explainInstance", null);
834
725
 
835
726
  //#endregion
836
727
  export { AFSGCE, afsgceOptionsSchema };