airfoil 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/index.js +1181 -104238
  2. package/package.json +19 -24
  3. package/src/commands/cluster/data-lake/create-iceberg.ts +8 -10
  4. package/src/commands/cluster/data-lake/create-parquet.ts +8 -10
  5. package/src/commands/cluster/data-lake/create.ts +4 -10
  6. package/src/commands/cluster/data-lake/delete.ts +6 -10
  7. package/src/commands/cluster/data-lake/get.ts +7 -13
  8. package/src/commands/cluster/data-lake/list.ts +8 -18
  9. package/src/commands/cluster/index.ts +3 -6
  10. package/src/commands/cluster/namespace/create.ts +18 -28
  11. package/src/commands/cluster/namespace/delete.ts +6 -10
  12. package/src/commands/cluster/namespace/get.ts +6 -10
  13. package/src/commands/cluster/namespace/list.ts +7 -16
  14. package/src/commands/cluster/object-store/create-aws.ts +20 -24
  15. package/src/commands/cluster/object-store/create-azure.ts +17 -21
  16. package/src/commands/cluster/object-store/create-google.ts +19 -34
  17. package/src/commands/cluster/object-store/create-s3.ts +22 -34
  18. package/src/commands/cluster/object-store/create.ts +2 -1
  19. package/src/commands/cluster/object-store/delete.ts +6 -8
  20. package/src/commands/cluster/object-store/get.ts +6 -8
  21. package/src/commands/cluster/object-store/list.ts +8 -18
  22. package/src/commands/cluster/tenant/create.ts +6 -10
  23. package/src/commands/cluster/tenant/delete.ts +10 -16
  24. package/src/commands/cluster/tenant/get.ts +6 -10
  25. package/src/commands/cluster/tenant/list.ts +5 -12
  26. package/src/commands/cluster/topic/create.ts +43 -66
  27. package/src/commands/cluster/topic/delete.ts +9 -11
  28. package/src/commands/cluster/topic/get.ts +5 -5
  29. package/src/commands/cluster/topic/list.ts +7 -16
  30. package/src/commands/dev.ts +89 -192
  31. package/src/commands/sql.ts +38 -59
  32. package/src/index.ts +18 -9
  33. package/src/utils/docker.ts +43 -0
  34. package/src/utils/options.ts +16 -17
  35. package/src/utils/wings.ts +68 -64
  36. package/src/scripts/compile-all.ts +0 -21
  37. package/src/utils/effect.ts +0 -11
@@ -1,35 +1,35 @@
1
1
  import * as p from "@clack/prompts";
2
- import { Command, Options } from "@effect/cli";
3
2
  import { WingsClusterMetadata } from "@useairfoil/wings";
4
3
  import { printTable } from "console-table-printer";
5
4
  import { Effect, Option } from "effect";
5
+ import { Command, Flag } from "effect/unstable/cli";
6
+
6
7
  import { makeClusterMetadataLayer } from "../../../utils/client.js";
7
- import { handleCliError } from "../../../utils/effect.js";
8
8
  import { hostOption, portOption } from "../../../utils/options.js";
9
9
 
10
- const parentOption = Options.text("parent").pipe(
11
- Options.withDescription("Parent tenant in format: tenants/{tenant}"),
10
+ const parentOption = Flag.string("parent").pipe(
11
+ Flag.withDescription("Parent tenant in format: tenants/{tenant}"),
12
12
  );
13
13
 
14
- const objectStoreIdOption = Options.text("object-store-id").pipe(
15
- Options.withDescription("Unique identifier for the object store"),
14
+ const objectStoreIdOption = Flag.string("object-store-id").pipe(
15
+ Flag.withDescription("Unique identifier for the object store"),
16
16
  );
17
17
 
18
- const containerNameOption = Options.text("container-name").pipe(
19
- Options.withDescription("Azure container name"),
18
+ const containerNameOption = Flag.string("container-name").pipe(
19
+ Flag.withDescription("Azure container name"),
20
20
  );
21
21
 
22
- const prefixOption = Options.text("prefix").pipe(
23
- Options.withDescription("Container prefix (optional)"),
24
- Options.optional,
22
+ const prefixOption = Flag.string("prefix").pipe(
23
+ Flag.withDescription("Container prefix (optional)"),
24
+ Flag.optional,
25
25
  );
26
26
 
27
- const storageAccountNameOption = Options.text("storage-account-name").pipe(
28
- Options.withDescription("AZURE_STORAGE_ACCOUNT_NAME"),
27
+ const storageAccountNameOption = Flag.string("storage-account-name").pipe(
28
+ Flag.withDescription("AZURE_STORAGE_ACCOUNT_NAME"),
29
29
  );
30
30
 
31
- const storageAccountKeyOption = Options.text("storage-account-key").pipe(
32
- Options.withDescription("AZURE_STORAGE_ACCOUNT_KEY"),
31
+ const storageAccountKeyOption = Flag.string("storage-account-key").pipe(
32
+ Flag.withDescription("AZURE_STORAGE_ACCOUNT_KEY"),
33
33
  );
34
34
 
35
35
  export const createObjectStoreAzureCommand = Command.make(
@@ -76,9 +76,7 @@ export const createObjectStoreAzureCommand = Command.make(
76
76
  },
77
77
  }).pipe(
78
78
  Effect.provide(layer),
79
- Effect.tapError(() =>
80
- Effect.sync(() => s.stop("Failed to create Azure object store")),
81
- ),
79
+ Effect.tapError(() => Effect.sync(() => s.stop("Failed to create Azure object store"))),
82
80
  );
83
81
 
84
82
  s.stop("Azure object store created successfully");
@@ -94,7 +92,5 @@ export const createObjectStoreAzureCommand = Command.make(
94
92
  ]);
95
93
  p.outro("✓ Done");
96
94
  });
97
- }).pipe(
98
- Effect.catchAll(handleCliError("Failed to create Azure object store")),
99
- ),
95
+ }),
100
96
  ).pipe(Command.withDescription("Create a new Azure Blob Storage object store"));
@@ -1,35 +1,35 @@
1
1
  import * as p from "@clack/prompts";
2
- import { Command, Options } from "@effect/cli";
3
2
  import { WingsClusterMetadata } from "@useairfoil/wings";
4
3
  import { printTable } from "console-table-printer";
5
4
  import { Effect, Option } from "effect";
5
+ import { Command, Flag } from "effect/unstable/cli";
6
+
6
7
  import { makeClusterMetadataLayer } from "../../../utils/client.js";
7
- import { handleCliError } from "../../../utils/effect.js";
8
8
  import { hostOption, portOption } from "../../../utils/options.js";
9
9
 
10
- const parentOption = Options.text("parent").pipe(
11
- Options.withDescription("Parent tenant in format: tenants/{tenant}"),
10
+ const parentOption = Flag.string("parent").pipe(
11
+ Flag.withDescription("Parent tenant in format: tenants/{tenant}"),
12
12
  );
13
13
 
14
- const objectStoreIdOption = Options.text("object-store-id").pipe(
15
- Options.withDescription("Unique identifier for the object store"),
14
+ const objectStoreIdOption = Flag.string("object-store-id").pipe(
15
+ Flag.withDescription("Unique identifier for the object store"),
16
16
  );
17
17
 
18
- const bucketNameOption = Options.text("bucket-name").pipe(
19
- Options.withDescription("Google Cloud Storage bucket name"),
18
+ const bucketNameOption = Flag.string("bucket-name").pipe(
19
+ Flag.withDescription("Google Cloud Storage bucket name"),
20
20
  );
21
21
 
22
- const prefixOption = Options.text("prefix").pipe(
23
- Options.withDescription("Bucket prefix (optional)"),
24
- Options.optional,
22
+ const prefixOption = Flag.string("prefix").pipe(
23
+ Flag.withDescription("Bucket prefix (optional)"),
24
+ Flag.optional,
25
25
  );
26
26
 
27
- const serviceAccountOption = Options.text("service-account").pipe(
28
- Options.withDescription("GOOGLE_SERVICE_ACCOUNT"),
27
+ const serviceAccountOption = Flag.string("service-account").pipe(
28
+ Flag.withDescription("GOOGLE_SERVICE_ACCOUNT"),
29
29
  );
30
30
 
31
- const serviceAccountKeyOption = Options.text("service-account-key").pipe(
32
- Options.withDescription("GOOGLE_SERVICE_ACCOUNT_KEY"),
31
+ const serviceAccountKeyOption = Flag.string("service-account-key").pipe(
32
+ Flag.withDescription("GOOGLE_SERVICE_ACCOUNT_KEY"),
33
33
  );
34
34
 
35
35
  export const createObjectStoreGoogleCommand = Command.make(
@@ -44,16 +44,7 @@ export const createObjectStoreGoogleCommand = Command.make(
44
44
  host: hostOption,
45
45
  port: portOption,
46
46
  },
47
- ({
48
- parent,
49
- objectStoreId,
50
- bucketName,
51
- prefix,
52
- serviceAccount,
53
- serviceAccountKey,
54
- host,
55
- port,
56
- }) =>
47
+ ({ parent, objectStoreId, bucketName, prefix, serviceAccount, serviceAccountKey, host, port }) =>
57
48
  Effect.gen(function* () {
58
49
  p.intro("🗄️ Create Google Cloud Storage Object Store");
59
50
 
@@ -76,9 +67,7 @@ export const createObjectStoreGoogleCommand = Command.make(
76
67
  },
77
68
  }).pipe(
78
69
  Effect.provide(layer),
79
- Effect.tapError(() =>
80
- Effect.sync(() => s.stop("Failed to create Google object store")),
81
- ),
70
+ Effect.tapError(() => Effect.sync(() => s.stop("Failed to create Google object store"))),
82
71
  );
83
72
 
84
73
  s.stop("Google Cloud Storage object store created successfully");
@@ -94,9 +83,5 @@ export const createObjectStoreGoogleCommand = Command.make(
94
83
  ]);
95
84
  p.outro("✓ Done");
96
85
  });
97
- }).pipe(
98
- Effect.catchAll(handleCliError("Failed to create Google object store")),
99
- ),
100
- ).pipe(
101
- Command.withDescription("Create a new Google Cloud Storage object store"),
102
- );
86
+ }),
87
+ ).pipe(Command.withDescription("Create a new Google Cloud Storage object store"));
@@ -1,46 +1,42 @@
1
1
  import * as p from "@clack/prompts";
2
- import { Command, Options } from "@effect/cli";
3
2
  import { WingsClusterMetadata } from "@useairfoil/wings";
4
3
  import { printTable } from "console-table-printer";
5
4
  import { Effect, Option } from "effect";
5
+ import { Command, Flag } from "effect/unstable/cli";
6
+
6
7
  import { makeClusterMetadataLayer } from "../../../utils/client.js";
7
- import { handleCliError } from "../../../utils/effect.js";
8
8
  import { hostOption, portOption } from "../../../utils/options.js";
9
9
 
10
- const parentOption = Options.text("parent").pipe(
11
- Options.withDescription("Parent tenant in format: tenants/{tenant}"),
10
+ const parentOption = Flag.string("parent").pipe(
11
+ Flag.withDescription("Parent tenant in format: tenants/{tenant}"),
12
12
  );
13
13
 
14
- const objectStoreIdOption = Options.text("object-store-id").pipe(
15
- Options.withDescription("Unique identifier for the object store"),
14
+ const objectStoreIdOption = Flag.string("object-store-id").pipe(
15
+ Flag.withDescription("Unique identifier for the object store"),
16
16
  );
17
17
 
18
- const bucketNameOption = Options.text("bucket-name").pipe(
19
- Options.withDescription("S3 bucket name"),
20
- );
18
+ const bucketNameOption = Flag.string("bucket-name").pipe(Flag.withDescription("S3 bucket name"));
21
19
 
22
- const prefixOption = Options.text("prefix").pipe(
23
- Options.withDescription("Bucket prefix (optional)"),
24
- Options.optional,
20
+ const prefixOption = Flag.string("prefix").pipe(
21
+ Flag.withDescription("Bucket prefix (optional)"),
22
+ Flag.optional,
25
23
  );
26
24
 
27
- const accessKeyIdOption = Options.text("access-key-id").pipe(
28
- Options.withDescription("AWS_ACCESS_KEY_ID"),
25
+ const accessKeyIdOption = Flag.string("access-key-id").pipe(
26
+ Flag.withDescription("AWS_ACCESS_KEY_ID"),
29
27
  );
30
28
 
31
- const secretAccessKeyOption = Options.text("secret-access-key").pipe(
32
- Options.withDescription("AWS_SECRET_ACCESS_KEY"),
29
+ const secretAccessKeyOption = Flag.string("secret-access-key").pipe(
30
+ Flag.withDescription("AWS_SECRET_ACCESS_KEY"),
33
31
  );
34
32
 
35
- const regionOption = Options.text("region").pipe(
36
- Options.withDescription("AWS_DEFAULT_REGION"),
37
- Options.optional,
33
+ const regionOption = Flag.string("region").pipe(
34
+ Flag.withDescription("AWS_DEFAULT_REGION"),
35
+ Flag.optional,
38
36
  );
39
37
 
40
- const endpointOption = Options.text("endpoint").pipe(
41
- Options.withDescription(
42
- "AWS_ENDPOINT (e.g., https://nyc3.digitaloceanspaces.com)",
43
- ),
38
+ const endpointOption = Flag.string("endpoint").pipe(
39
+ Flag.withDescription("AWS_ENDPOINT (e.g., https://nyc3.digitaloceanspaces.com)"),
44
40
  );
45
41
 
46
42
  export const createObjectStoreS3Command = Command.make(
@@ -95,9 +91,7 @@ export const createObjectStoreS3Command = Command.make(
95
91
  }).pipe(
96
92
  Effect.provide(layer),
97
93
  Effect.tapError(() =>
98
- Effect.sync(() =>
99
- s.stop("Failed to create S3-compatible object store"),
100
- ),
94
+ Effect.sync(() => s.stop("Failed to create S3-compatible object store")),
101
95
  ),
102
96
  );
103
97
 
@@ -114,13 +108,7 @@ export const createObjectStoreS3Command = Command.make(
114
108
  ]);
115
109
  p.outro("✓ Done");
116
110
  });
117
- }).pipe(
118
- Effect.catchAll(
119
- handleCliError("Failed to create S3-compatible object store"),
120
- ),
121
- ),
111
+ }),
122
112
  ).pipe(
123
- Command.withDescription(
124
- "Create a new S3-compatible object store (MinIO, DigitalOcean, etc.)",
125
- ),
113
+ Command.withDescription("Create a new S3-compatible object store (MinIO, DigitalOcean, etc.)"),
126
114
  );
@@ -1,5 +1,6 @@
1
- import { Command } from "@effect/cli";
2
1
  import { Effect } from "effect";
2
+ import { Command } from "effect/unstable/cli";
3
+
3
4
  import { createObjectStoreAwsCommand } from "./create-aws.js";
4
5
  import { createObjectStoreAzureCommand } from "./create-azure.js";
5
6
  import { createObjectStoreGoogleCommand } from "./create-google.js";
@@ -1,13 +1,13 @@
1
1
  import * as p from "@clack/prompts";
2
- import { Command, Options } from "@effect/cli";
3
2
  import { WingsClusterMetadata } from "@useairfoil/wings";
4
3
  import { Effect } from "effect";
4
+ import { Command, Flag } from "effect/unstable/cli";
5
+
5
6
  import { makeClusterMetadataLayer } from "../../../utils/client.js";
6
- import { handleCliError } from "../../../utils/effect.js";
7
7
  import { forceOption, hostOption, portOption } from "../../../utils/options.js";
8
8
 
9
- const nameOption = Options.text("name").pipe(
10
- Options.withDescription(
9
+ const nameOption = Flag.string("name").pipe(
10
+ Flag.withDescription(
11
11
  "Object store name in format: tenants/{tenant}/object-stores/{object-store}",
12
12
  ),
13
13
  );
@@ -47,12 +47,10 @@ export const deleteObjectStoreCommand = Command.make(
47
47
 
48
48
  yield* WingsClusterMetadata.deleteObjectStore({ name }).pipe(
49
49
  Effect.provide(layer),
50
- Effect.tapError(() =>
51
- Effect.sync(() => s.stop("Failed to delete object store")),
52
- ),
50
+ Effect.tapError(() => Effect.sync(() => s.stop("Failed to delete object store"))),
53
51
  );
54
52
 
55
53
  s.stop("Object store deleted successfully");
56
54
  p.outro("✓ Done");
57
- }).pipe(Effect.catchAll(handleCliError("Failed to delete object store"))),
55
+ }),
58
56
  ).pipe(Command.withDescription("Delete an object store from the cluster"));
@@ -1,14 +1,14 @@
1
1
  import * as p from "@clack/prompts";
2
- import { Command, Options } from "@effect/cli";
3
2
  import { WingsClusterMetadata } from "@useairfoil/wings";
4
3
  import { printTable } from "console-table-printer";
5
4
  import { Effect } from "effect";
5
+ import { Command, Flag } from "effect/unstable/cli";
6
+
6
7
  import { makeClusterMetadataLayer } from "../../../utils/client.js";
7
- import { handleCliError } from "../../../utils/effect.js";
8
8
  import { hostOption, portOption } from "../../../utils/options.js";
9
9
 
10
- const nameOption = Options.text("name").pipe(
11
- Options.withDescription(
10
+ const nameOption = Flag.string("name").pipe(
11
+ Flag.withDescription(
12
12
  "Object store name in format: tenants/{tenant}/object-stores/{object-store}",
13
13
  ),
14
14
  );
@@ -31,9 +31,7 @@ export const getObjectStoreCommand = Command.make(
31
31
  name,
32
32
  }).pipe(
33
33
  Effect.provide(layer),
34
- Effect.tapError(() =>
35
- Effect.sync(() => s.stop("Failed to get object store")),
36
- ),
34
+ Effect.tapError(() => Effect.sync(() => s.stop("Failed to get object store"))),
37
35
  );
38
36
 
39
37
  s.stop("Object store retrieved");
@@ -47,5 +45,5 @@ export const getObjectStoreCommand = Command.make(
47
45
  ]);
48
46
  p.outro("✓ Done");
49
47
  });
50
- }).pipe(Effect.catchAll(handleCliError("Failed to get object store"))),
48
+ }),
51
49
  ).pipe(Command.withDescription("Get details of a specific object store"));
@@ -1,19 +1,14 @@
1
1
  import * as p from "@clack/prompts";
2
- import { Command, Options } from "@effect/cli";
3
2
  import { WingsClusterMetadata } from "@useairfoil/wings";
4
3
  import { printTable } from "console-table-printer";
5
4
  import { Effect, Option } from "effect";
5
+ import { Command, Flag } from "effect/unstable/cli";
6
+
6
7
  import { makeClusterMetadataLayer } from "../../../utils/client.js";
7
- import { handleCliError } from "../../../utils/effect.js";
8
- import {
9
- hostOption,
10
- pageSizeOption,
11
- pageTokenOption,
12
- portOption,
13
- } from "../../../utils/options.js";
8
+ import { hostOption, pageSizeOption, pageTokenOption, portOption } from "../../../utils/options.js";
14
9
 
15
- const parentOption = Options.text("parent").pipe(
16
- Options.withDescription("Parent tenant in format: tenants/{tenant}"),
10
+ const parentOption = Flag.string("parent").pipe(
11
+ Flag.withDescription("Parent tenant in format: tenants/{tenant}"),
17
12
  );
18
13
 
19
14
  export const listObjectStoresCommand = Command.make(
@@ -38,9 +33,7 @@ export const listObjectStoresCommand = Command.make(
38
33
  pageToken: Option.getOrUndefined(pageToken),
39
34
  }).pipe(
40
35
  Effect.provide(layer),
41
- Effect.tapError(() =>
42
- Effect.sync(() => s.stop("Failed to list object stores")),
43
- ),
36
+ Effect.tapError(() => Effect.sync(() => s.stop("Failed to list object stores"))),
44
37
  );
45
38
 
46
39
  s.stop(`Found ${response.objectStores.length} object store(s)`);
@@ -51,10 +44,7 @@ export const listObjectStoresCommand = Command.make(
51
44
  } else {
52
45
  printTable(
53
46
  response.objectStores.map(
54
- (objectStore: {
55
- name: string;
56
- objectStoreConfig: { _tag?: string | null };
57
- }) => ({
47
+ (objectStore: { name: string; objectStoreConfig: { _tag?: string | null } }) => ({
58
48
  name: objectStore.name,
59
49
  type: objectStore.objectStoreConfig._tag || "-",
60
50
  }),
@@ -68,5 +58,5 @@ export const listObjectStoresCommand = Command.make(
68
58
 
69
59
  p.outro("✓ Done");
70
60
  });
71
- }).pipe(Effect.catchAll(handleCliError("Failed to list object stores"))),
61
+ }),
72
62
  ).pipe(Command.withDescription("List all object stores belonging to a tenant"));
@@ -1,16 +1,14 @@
1
1
  import * as p from "@clack/prompts";
2
- import { Command, Options } from "@effect/cli";
3
2
  import { WingsClusterMetadata } from "@useairfoil/wings";
4
3
  import { printTable } from "console-table-printer";
5
4
  import { Effect } from "effect";
5
+ import { Command, Flag } from "effect/unstable/cli";
6
+
6
7
  import { makeClusterMetadataLayer } from "../../../utils/client.js";
7
- import { handleCliError } from "../../../utils/effect.js";
8
8
  import { hostOption, portOption } from "../../../utils/options.js";
9
9
 
10
- const tenantIdOption = Options.text("tenant-id").pipe(
11
- Options.withDescription(
12
- "Unique identifier for the tenant (e.g., 'acme-corp')",
13
- ),
10
+ const tenantIdOption = Flag.string("tenant-id").pipe(
11
+ Flag.withDescription("Unique identifier for the tenant (e.g., 'acme-corp')"),
14
12
  );
15
13
 
16
14
  export const createTenantCommand = Command.make(
@@ -33,9 +31,7 @@ export const createTenantCommand = Command.make(
33
31
  tenantId,
34
32
  }).pipe(
35
33
  Effect.provide(layer),
36
- Effect.tapError(() =>
37
- Effect.sync(() => s.stop("Failed to create tenant")),
38
- ),
34
+ Effect.tapError(() => Effect.sync(() => s.stop("Failed to create tenant"))),
39
35
  );
40
36
 
41
37
  s.stop("Tenant created successfully");
@@ -44,5 +40,5 @@ export const createTenantCommand = Command.make(
44
40
  printTable([{ name: tenant.name }]);
45
41
  p.outro("✓ Done");
46
42
  });
47
- }).pipe(Effect.catchAll(handleCliError("Failed to create tenant"))),
43
+ }),
48
44
  ).pipe(Command.withDescription("Create a new tenant in the cluster"));
@@ -1,15 +1,13 @@
1
1
  import * as p from "@clack/prompts";
2
- import { Command, Options } from "@effect/cli";
3
2
  import { WingsClusterMetadata } from "@useairfoil/wings";
4
3
  import { Effect } from "effect";
5
- import { makeClusterMetadataLayer } from "../../../utils/client.js";
6
- import { handleCliError } from "../../../utils/effect.js";
7
- import { forceOption, hostOption, portOption } from "../../../utils/options.js";
8
-
9
- const nameOption = Options.text("name").pipe(
10
- Options.withDescription(
11
- "Tenant name in format: tenants/{tenant} (e.g., 'tenants/acme-corp')",
12
- ),
4
+ import { Command, Flag } from "effect/unstable/cli";
5
+
6
+ import { makeClusterMetadataLayer } from "../../../utils/client";
7
+ import { forceOption, hostOption, portOption } from "../../../utils/options";
8
+
9
+ const nameOption = Flag.string("name").pipe(
10
+ Flag.withDescription("Tenant name in format: tenants/{tenant} (e.g., 'tenants/acme-corp')"),
13
11
  );
14
12
 
15
13
  export const deleteTenantCommand = Command.make(
@@ -47,16 +45,12 @@ export const deleteTenantCommand = Command.make(
47
45
 
48
46
  yield* WingsClusterMetadata.deleteTenant({ name }).pipe(
49
47
  Effect.provide(layer),
50
- Effect.tapError(() =>
51
- Effect.sync(() => s.stop("Failed to delete tenant")),
52
- ),
48
+ Effect.tapError(() => Effect.sync(() => s.stop("Failed to delete tenant"))),
53
49
  );
54
50
 
55
51
  s.stop("Tenant deleted successfully");
56
52
  p.outro("✓ Done");
57
- }).pipe(Effect.catchAll(handleCliError("Failed to delete tenant"))),
53
+ }),
58
54
  ).pipe(
59
- Command.withDescription(
60
- "Delete a tenant from the cluster (fails if tenant has any namespaces)",
61
- ),
55
+ Command.withDescription("Delete a tenant from the cluster (fails if tenant has any namespaces)"),
62
56
  );
@@ -1,16 +1,14 @@
1
1
  import * as p from "@clack/prompts";
2
- import { Command, Options } from "@effect/cli";
3
2
  import { WingsClusterMetadata } from "@useairfoil/wings";
4
3
  import { printTable } from "console-table-printer";
5
4
  import { Effect } from "effect";
5
+ import { Command, Flag } from "effect/unstable/cli";
6
+
6
7
  import { makeClusterMetadataLayer } from "../../../utils/client.js";
7
- import { handleCliError } from "../../../utils/effect.js";
8
8
  import { hostOption, portOption } from "../../../utils/options.js";
9
9
 
10
- const nameOption = Options.text("name").pipe(
11
- Options.withDescription(
12
- "Tenant name in format: tenants/{tenant} (e.g., 'tenants/acme-corp')",
13
- ),
10
+ const nameOption = Flag.string("name").pipe(
11
+ Flag.withDescription("Tenant name in format: tenants/{tenant} (e.g., 'tenants/acme-corp')"),
14
12
  );
15
13
 
16
14
  export const getTenantCommand = Command.make(
@@ -29,9 +27,7 @@ export const getTenantCommand = Command.make(
29
27
 
30
28
  const tenant = yield* WingsClusterMetadata.getTenant({ name }).pipe(
31
29
  Effect.provide(layer),
32
- Effect.tapError(() =>
33
- Effect.sync(() => s.stop("Failed to get tenant")),
34
- ),
30
+ Effect.tapError(() => Effect.sync(() => s.stop("Failed to get tenant"))),
35
31
  );
36
32
 
37
33
  s.stop("Tenant retrieved");
@@ -40,5 +36,5 @@ export const getTenantCommand = Command.make(
40
36
  printTable([{ name: tenant.name }]);
41
37
  p.outro("✓ Done");
42
38
  });
43
- }).pipe(Effect.catchAll(handleCliError("Failed to get tenant"))),
39
+ }),
44
40
  ).pipe(Command.withDescription("Get details of a specific tenant"));
@@ -1,16 +1,11 @@
1
1
  import * as p from "@clack/prompts";
2
- import { Command } from "@effect/cli";
3
2
  import { WingsClusterMetadata } from "@useairfoil/wings";
4
3
  import { printTable } from "console-table-printer";
5
4
  import { Effect, Option } from "effect";
5
+ import { Command } from "effect/unstable/cli";
6
+
6
7
  import { makeClusterMetadataLayer } from "../../../utils/client.js";
7
- import { handleCliError } from "../../../utils/effect.js";
8
- import {
9
- hostOption,
10
- pageSizeOption,
11
- pageTokenOption,
12
- portOption,
13
- } from "../../../utils/options.js";
8
+ import { hostOption, pageSizeOption, pageTokenOption, portOption } from "../../../utils/options.js";
14
9
 
15
10
  export const listTenantsCommand = Command.make(
16
11
  "list-tenants",
@@ -32,9 +27,7 @@ export const listTenantsCommand = Command.make(
32
27
  pageToken: Option.getOrUndefined(pageToken),
33
28
  }).pipe(
34
29
  Effect.provide(layer),
35
- Effect.tapError(() =>
36
- Effect.sync(() => s.stop("Failed to list tenants")),
37
- ),
30
+ Effect.tapError(() => Effect.sync(() => s.stop("Failed to list tenants"))),
38
31
  );
39
32
 
40
33
  s.stop(`Found ${response.tenants.length} tenant(s)`);
@@ -56,5 +49,5 @@ export const listTenantsCommand = Command.make(
56
49
 
57
50
  p.outro("✓ Done");
58
51
  });
59
- }).pipe(Effect.catchAll(handleCliError("Failed to list tenants"))),
52
+ }),
60
53
  ).pipe(Command.withDescription("List all tenants in the cluster"));