airfoil 0.3.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.
- package/dist/index.js +1182 -99651
- package/package.json +19 -23
- package/src/commands/cluster/data-lake/create-iceberg.ts +3 -5
- package/src/commands/cluster/data-lake/create-parquet.ts +3 -5
- package/src/commands/cluster/data-lake/create.ts +3 -9
- package/src/commands/cluster/data-lake/delete.ts +4 -8
- package/src/commands/cluster/data-lake/get.ts +5 -11
- package/src/commands/cluster/data-lake/list.ts +5 -15
- package/src/commands/cluster/index.ts +2 -5
- package/src/commands/cluster/namespace/create.ts +7 -17
- package/src/commands/cluster/namespace/delete.ts +4 -8
- package/src/commands/cluster/namespace/get.ts +4 -8
- package/src/commands/cluster/namespace/list.ts +5 -14
- package/src/commands/cluster/object-store/create-aws.ts +3 -5
- package/src/commands/cluster/object-store/create-azure.ts +3 -7
- package/src/commands/cluster/object-store/create-google.ts +5 -20
- package/src/commands/cluster/object-store/create-s3.ts +6 -18
- package/src/commands/cluster/object-store/create.ts +1 -0
- package/src/commands/cluster/object-store/delete.ts +3 -5
- package/src/commands/cluster/object-store/get.ts +3 -5
- package/src/commands/cluster/object-store/list.ts +5 -15
- package/src/commands/cluster/tenant/create.ts +3 -5
- package/src/commands/cluster/tenant/delete.ts +7 -13
- package/src/commands/cluster/tenant/get.ts +4 -8
- package/src/commands/cluster/tenant/list.ts +4 -11
- package/src/commands/cluster/topic/create.ts +19 -40
- package/src/commands/cluster/topic/delete.ts +3 -5
- package/src/commands/cluster/topic/get.ts +2 -2
- package/src/commands/cluster/topic/list.ts +5 -14
- package/src/commands/dev.ts +70 -173
- package/src/commands/sql.ts +23 -44
- package/src/index.ts +12 -5
- package/src/utils/docker.ts +43 -0
- package/src/utils/options.ts +1 -3
- package/src/utils/wings.ts +68 -64
- package/src/scripts/compile-all.ts +0 -21
- package/src/utils/effect.ts +0 -11
|
@@ -3,8 +3,8 @@ import { WingsClusterMetadata } from "@useairfoil/wings";
|
|
|
3
3
|
import { printTable } from "console-table-printer";
|
|
4
4
|
import { Effect } from "effect";
|
|
5
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
10
|
const nameOption = Flag.string("name").pipe(
|
|
@@ -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
|
-
})
|
|
48
|
+
}),
|
|
51
49
|
).pipe(Command.withDescription("Get details of a specific object store"));
|
|
@@ -3,14 +3,9 @@ import { WingsClusterMetadata } from "@useairfoil/wings";
|
|
|
3
3
|
import { printTable } from "console-table-printer";
|
|
4
4
|
import { Effect, Option } from "effect";
|
|
5
5
|
import { Command, Flag } from "effect/unstable/cli";
|
|
6
|
+
|
|
6
7
|
import { makeClusterMetadataLayer } from "../../../utils/client.js";
|
|
7
|
-
import {
|
|
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
|
const parentOption = Flag.string("parent").pipe(
|
|
16
11
|
Flag.withDescription("Parent tenant in format: tenants/{tenant}"),
|
|
@@ -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
|
-
})
|
|
61
|
+
}),
|
|
72
62
|
).pipe(Command.withDescription("List all object stores belonging to a tenant"));
|
|
@@ -3,8 +3,8 @@ import { WingsClusterMetadata } from "@useairfoil/wings";
|
|
|
3
3
|
import { printTable } from "console-table-printer";
|
|
4
4
|
import { Effect } from "effect";
|
|
5
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
10
|
const tenantIdOption = Flag.string("tenant-id").pipe(
|
|
@@ -31,9 +31,7 @@ export const createTenantCommand = Command.make(
|
|
|
31
31
|
tenantId,
|
|
32
32
|
}).pipe(
|
|
33
33
|
Effect.provide(layer),
|
|
34
|
-
Effect.tapError(() =>
|
|
35
|
-
Effect.sync(() => s.stop("Failed to create tenant")),
|
|
36
|
-
),
|
|
34
|
+
Effect.tapError(() => Effect.sync(() => s.stop("Failed to create tenant"))),
|
|
37
35
|
);
|
|
38
36
|
|
|
39
37
|
s.stop("Tenant created successfully");
|
|
@@ -42,5 +40,5 @@ export const createTenantCommand = Command.make(
|
|
|
42
40
|
printTable([{ name: tenant.name }]);
|
|
43
41
|
p.outro("✓ Done");
|
|
44
42
|
});
|
|
45
|
-
})
|
|
43
|
+
}),
|
|
46
44
|
).pipe(Command.withDescription("Create a new tenant in the cluster"));
|
|
@@ -2,14 +2,12 @@ import * as p from "@clack/prompts";
|
|
|
2
2
|
import { WingsClusterMetadata } from "@useairfoil/wings";
|
|
3
3
|
import { Effect } from "effect";
|
|
4
4
|
import { Command, Flag } from "effect/unstable/cli";
|
|
5
|
-
|
|
6
|
-
import {
|
|
7
|
-
import { forceOption, hostOption, portOption } from "../../../utils/options
|
|
5
|
+
|
|
6
|
+
import { makeClusterMetadataLayer } from "../../../utils/client";
|
|
7
|
+
import { forceOption, hostOption, portOption } from "../../../utils/options";
|
|
8
8
|
|
|
9
9
|
const nameOption = Flag.string("name").pipe(
|
|
10
|
-
Flag.withDescription(
|
|
11
|
-
"Tenant name in format: tenants/{tenant} (e.g., 'tenants/acme-corp')",
|
|
12
|
-
),
|
|
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
|
-
})
|
|
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
|
);
|
|
@@ -3,14 +3,12 @@ import { WingsClusterMetadata } from "@useairfoil/wings";
|
|
|
3
3
|
import { printTable } from "console-table-printer";
|
|
4
4
|
import { Effect } from "effect";
|
|
5
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
10
|
const nameOption = Flag.string("name").pipe(
|
|
11
|
-
Flag.withDescription(
|
|
12
|
-
"Tenant name in format: tenants/{tenant} (e.g., 'tenants/acme-corp')",
|
|
13
|
-
),
|
|
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
|
-
})
|
|
39
|
+
}),
|
|
44
40
|
).pipe(Command.withDescription("Get details of a specific tenant"));
|
|
@@ -3,14 +3,9 @@ import { WingsClusterMetadata } from "@useairfoil/wings";
|
|
|
3
3
|
import { printTable } from "console-table-printer";
|
|
4
4
|
import { Effect, Option } from "effect";
|
|
5
5
|
import { Command } from "effect/unstable/cli";
|
|
6
|
+
|
|
6
7
|
import { makeClusterMetadataLayer } from "../../../utils/client.js";
|
|
7
|
-
import {
|
|
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
|
-
})
|
|
52
|
+
}),
|
|
60
53
|
).pipe(Command.withDescription("List all tenants in the cluster"));
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import * as fs from "node:fs";
|
|
2
|
-
import * as p from "@clack/prompts";
|
|
3
1
|
import type { FieldConfig } from "@useairfoil/wings";
|
|
2
|
+
|
|
3
|
+
import * as p from "@clack/prompts";
|
|
4
4
|
import { WingsClusterMetadata } from "@useairfoil/wings";
|
|
5
5
|
import { printTable } from "console-table-printer";
|
|
6
6
|
import { Effect, Option } from "effect";
|
|
7
7
|
import { Command, Flag } from "effect/unstable/cli";
|
|
8
|
+
import * as fs from "node:fs";
|
|
9
|
+
|
|
8
10
|
import { makeClusterMetadataLayer } from "../../../utils/client.js";
|
|
9
|
-
import { handleCliError } from "../../../utils/effect.js";
|
|
10
11
|
import { hostOption, portOption } from "../../../utils/options.js";
|
|
11
12
|
|
|
12
13
|
// Supported simple types (no config required)
|
|
@@ -41,9 +42,7 @@ const SUPPORTED_INLINE_TYPES = [
|
|
|
41
42
|
type SupportedInlineType = (typeof SUPPORTED_INLINE_TYPES)[number];
|
|
42
43
|
|
|
43
44
|
const parentOption = Flag.string("parent").pipe(
|
|
44
|
-
Flag.withDescription(
|
|
45
|
-
"Parent namespace in format: tenants/{tenant}/namespaces/{namespace}",
|
|
46
|
-
),
|
|
45
|
+
Flag.withDescription("Parent namespace in format: tenants/{tenant}/namespaces/{namespace}"),
|
|
47
46
|
);
|
|
48
47
|
|
|
49
48
|
const topicIdOption = Flag.string("topic-id").pipe(
|
|
@@ -56,16 +55,12 @@ const descriptionOption = Flag.string("description").pipe(
|
|
|
56
55
|
);
|
|
57
56
|
|
|
58
57
|
const fieldsOption = Flag.string("fields").pipe(
|
|
59
|
-
Flag.withDescription(
|
|
60
|
-
'Field definitions in format "name:Type" or "name:Type?" for nullable',
|
|
61
|
-
),
|
|
58
|
+
Flag.withDescription('Field definitions in format "name:Type" or "name:Type?" for nullable'),
|
|
62
59
|
Flag.atLeast(0),
|
|
63
60
|
);
|
|
64
61
|
|
|
65
62
|
const schemaFileOption = Flag.string("schema-file").pipe(
|
|
66
|
-
Flag.withDescription(
|
|
67
|
-
"Path to JSON file containing FieldConfig[] (for complex types)",
|
|
68
|
-
),
|
|
63
|
+
Flag.withDescription("Path to JSON file containing FieldConfig[] (for complex types)"),
|
|
69
64
|
Flag.optional,
|
|
70
65
|
);
|
|
71
66
|
|
|
@@ -151,15 +146,11 @@ function loadFieldsFromFile(filePath: string): FieldConfig[] {
|
|
|
151
146
|
}
|
|
152
147
|
|
|
153
148
|
if (!Array.isArray(parsed)) {
|
|
154
|
-
throw new Error(
|
|
155
|
-
`Schema file must contain an array of fields. Got: ${typeof parsed}`,
|
|
156
|
-
);
|
|
149
|
+
throw new Error(`Schema file must contain an array of fields. Got: ${typeof parsed}`);
|
|
157
150
|
}
|
|
158
151
|
|
|
159
152
|
if (parsed.length === 0) {
|
|
160
|
-
throw new Error(
|
|
161
|
-
"Schema file contains an empty array. At least one field is required.",
|
|
162
|
-
);
|
|
153
|
+
throw new Error("Schema file contains an empty array. At least one field is required.");
|
|
163
154
|
}
|
|
164
155
|
|
|
165
156
|
return (parsed as FieldConfig[]).map((field, index) => {
|
|
@@ -206,9 +197,7 @@ export const createTopicCommand = Command.make(
|
|
|
206
197
|
const hasFields = fields.length > 0;
|
|
207
198
|
|
|
208
199
|
if (!hasFields && !schemaFilePath) {
|
|
209
|
-
return yield* Effect.fail(
|
|
210
|
-
new Error("Either --fields or --schema-file must be provided"),
|
|
211
|
-
);
|
|
200
|
+
return yield* Effect.fail(new Error("Either --fields or --schema-file must be provided"));
|
|
212
201
|
}
|
|
213
202
|
|
|
214
203
|
if (hasFields && schemaFilePath) {
|
|
@@ -219,11 +208,8 @@ export const createTopicCommand = Command.make(
|
|
|
219
208
|
|
|
220
209
|
const topicFields = yield* Effect.try({
|
|
221
210
|
try: () =>
|
|
222
|
-
schemaFilePath
|
|
223
|
-
|
|
224
|
-
: parseFieldsFromArgs(fields),
|
|
225
|
-
catch: (error) =>
|
|
226
|
-
error instanceof Error ? error : new Error("Failed to parse fields"),
|
|
211
|
+
schemaFilePath ? loadFieldsFromFile(schemaFilePath) : parseFieldsFromArgs(fields),
|
|
212
|
+
catch: (error) => (error instanceof Error ? error : new Error("Failed to parse fields")),
|
|
227
213
|
});
|
|
228
214
|
|
|
229
215
|
if (topicFields.length === 0) {
|
|
@@ -233,9 +219,7 @@ export const createTopicCommand = Command.make(
|
|
|
233
219
|
const partitionKeyName = Option.getOrUndefined(partitionKey);
|
|
234
220
|
let partitionKeyId: bigint | undefined;
|
|
235
221
|
if (partitionKeyName) {
|
|
236
|
-
const index = topicFields.findIndex(
|
|
237
|
-
(field) => field.name === partitionKeyName,
|
|
238
|
-
);
|
|
222
|
+
const index = topicFields.findIndex((field) => field.name === partitionKeyName);
|
|
239
223
|
if (index === -1) {
|
|
240
224
|
return yield* Effect.fail(
|
|
241
225
|
new Error(
|
|
@@ -267,16 +251,12 @@ export const createTopicCommand = Command.make(
|
|
|
267
251
|
partitionKey: partitionKeyId,
|
|
268
252
|
compaction: {
|
|
269
253
|
freshnessSeconds: BigInt(freshnessSeconds),
|
|
270
|
-
ttlSeconds: Option.getOrUndefined(
|
|
271
|
-
Option.map(ttlSeconds, (ttl) => BigInt(ttl)),
|
|
272
|
-
),
|
|
254
|
+
ttlSeconds: Option.getOrUndefined(Option.map(ttlSeconds, (ttl) => BigInt(ttl))),
|
|
273
255
|
targetFileSizeBytes: BigInt(targetFileSizeBytes),
|
|
274
256
|
},
|
|
275
257
|
}).pipe(
|
|
276
258
|
Effect.provide(layer),
|
|
277
|
-
Effect.tapError(() =>
|
|
278
|
-
Effect.sync(() => s.stop("Failed to create topic")),
|
|
279
|
-
),
|
|
259
|
+
Effect.tapError(() => Effect.sync(() => s.stop("Failed to create topic"))),
|
|
280
260
|
);
|
|
281
261
|
|
|
282
262
|
s.stop("Topic created successfully");
|
|
@@ -288,13 +268,12 @@ export const createTopicCommand = Command.make(
|
|
|
288
268
|
description: topic.description || "-",
|
|
289
269
|
partition_key:
|
|
290
270
|
topic.partitionKey !== undefined
|
|
291
|
-
? topicFields.find((field) => field.id === topic.partitionKey)
|
|
292
|
-
|
|
271
|
+
? topicFields.find((field) => field.id === topic.partitionKey)?.name ||
|
|
272
|
+
topic.partitionKey.toString()
|
|
293
273
|
: "-",
|
|
294
274
|
freshness_seconds: topic.compaction.freshnessSeconds.toString(),
|
|
295
275
|
ttl_seconds: topic.compaction.ttlSeconds?.toString() || "-",
|
|
296
|
-
target_file_size_bytes:
|
|
297
|
-
topic.compaction.targetFileSizeBytes.toString(),
|
|
276
|
+
target_file_size_bytes: topic.compaction.targetFileSizeBytes.toString(),
|
|
298
277
|
fields_count: topic.schema.fields.length.toString(),
|
|
299
278
|
},
|
|
300
279
|
]);
|
|
@@ -313,5 +292,5 @@ export const createTopicCommand = Command.make(
|
|
|
313
292
|
|
|
314
293
|
p.outro("✓ Done");
|
|
315
294
|
});
|
|
316
|
-
})
|
|
295
|
+
}),
|
|
317
296
|
).pipe(Command.withDescription("Create a new topic belonging to a namespace"));
|
|
@@ -2,8 +2,8 @@ import * as p from "@clack/prompts";
|
|
|
2
2
|
import { WingsClusterMetadata } from "@useairfoil/wings";
|
|
3
3
|
import { Effect } from "effect";
|
|
4
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
9
|
const nameOption = Flag.string("name").pipe(
|
|
@@ -56,12 +56,10 @@ export const deleteTopicCommand = Command.make(
|
|
|
56
56
|
force: forceDelete,
|
|
57
57
|
}).pipe(
|
|
58
58
|
Effect.provide(layer),
|
|
59
|
-
Effect.tapError(() =>
|
|
60
|
-
Effect.sync(() => s.stop("Failed to delete topic")),
|
|
61
|
-
),
|
|
59
|
+
Effect.tapError(() => Effect.sync(() => s.stop("Failed to delete topic"))),
|
|
62
60
|
);
|
|
63
61
|
|
|
64
62
|
s.stop("Topic deleted successfully");
|
|
65
63
|
p.outro("✓ Done");
|
|
66
|
-
})
|
|
64
|
+
}),
|
|
67
65
|
).pipe(Command.withDescription("Delete a topic from the cluster"));
|
|
@@ -3,8 +3,8 @@ import { WingsClusterMetadata } from "@useairfoil/wings";
|
|
|
3
3
|
import { printTable } from "console-table-printer";
|
|
4
4
|
import { Effect } from "effect";
|
|
5
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
10
|
const nameOption = Flag.string("name").pipe(
|
|
@@ -47,5 +47,5 @@ export const getTopicCommand = Command.make(
|
|
|
47
47
|
|
|
48
48
|
p.outro("✓ Done");
|
|
49
49
|
});
|
|
50
|
-
})
|
|
50
|
+
}),
|
|
51
51
|
).pipe(Command.withDescription("Get details of a specific topic"));
|
|
@@ -3,19 +3,12 @@ import { WingsClusterMetadata } from "@useairfoil/wings";
|
|
|
3
3
|
import { printTable } from "console-table-printer";
|
|
4
4
|
import { Effect, Option } from "effect";
|
|
5
5
|
import { Command, Flag } from "effect/unstable/cli";
|
|
6
|
+
|
|
6
7
|
import { makeClusterMetadataLayer } from "../../../utils/client.js";
|
|
7
|
-
import {
|
|
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
|
const parentOption = Flag.string("parent").pipe(
|
|
16
|
-
Flag.withDescription(
|
|
17
|
-
"Parent namespace in format: tenants/{tenant}/namespaces/{namespace}",
|
|
18
|
-
),
|
|
11
|
+
Flag.withDescription("Parent namespace in format: tenants/{tenant}/namespaces/{namespace}"),
|
|
19
12
|
);
|
|
20
13
|
|
|
21
14
|
export const listTopicsCommand = Command.make(
|
|
@@ -40,9 +33,7 @@ export const listTopicsCommand = Command.make(
|
|
|
40
33
|
pageToken: Option.getOrUndefined(pageToken),
|
|
41
34
|
}).pipe(
|
|
42
35
|
Effect.provide(layer),
|
|
43
|
-
Effect.tapError(() =>
|
|
44
|
-
Effect.sync(() => s.stop("Failed to list topics")),
|
|
45
|
-
),
|
|
36
|
+
Effect.tapError(() => Effect.sync(() => s.stop("Failed to list topics"))),
|
|
46
37
|
);
|
|
47
38
|
|
|
48
39
|
s.stop(`Found ${response.topics.length} topic(s)`);
|
|
@@ -66,5 +57,5 @@ export const listTopicsCommand = Command.make(
|
|
|
66
57
|
|
|
67
58
|
p.outro("✓ Done");
|
|
68
59
|
});
|
|
69
|
-
})
|
|
60
|
+
}),
|
|
70
61
|
).pipe(Command.withDescription("List all topics belonging to a namespace"));
|