Skip to content

Commit 5ca537b

Browse files
committed
Simplified roomName, channelName and spaceName validation
1 parent 41a3fb2 commit 5ca537b

59 files changed

Lines changed: 152 additions & 76 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/base-command.ts

Lines changed: 19 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { InteractiveBaseCommand } from "./interactive-base-command.js";
2-
import { Interfaces } from "@oclif/core";
32
import * as Ably from "ably";
43
import chalk from "chalk";
54
import colorJson from "color-json";
@@ -128,63 +127,31 @@ export abstract class AblyBaseCommand extends InteractiveBaseCommand {
128127
this.isWebCliMode = isWebCliMode();
129128
}
130129

131-
/**
132-
* Mapping of common arg names to their human-readable labels.
133-
* The parse() override validates these are non-empty automatically.
134-
*/
135-
private static readonly RESOURCE_ARG_LABELS: Record<string, string> = {
136-
channel: "Channel",
137-
channels: "Channel", // channels:subscribe uses plural arg name (strict: false, variadic via argv)
138-
room: "Room",
139-
rooms: "Room", // rooms:messages:subscribe uses plural arg name (strict: false, variadic via argv)
140-
space_name: "Space",
141-
};
142-
143-
/**
144-
* Override parse() to automatically validate that common resource name
145-
* args (channel, room, space_name) are non-empty after oclif parsing.
146-
*/
147-
protected override async parse<
148-
F extends Record<string, unknown>,
149-
B extends Record<string, unknown>,
150-
A extends Record<string, unknown>,
151-
>(
152-
options?: Interfaces.Input<F, B, A>,
130+
protected validateChannelName(
131+
args: Record<string, unknown>,
132+
flags: BaseFlags,
153133
argv?: string[],
154-
): Promise<Interfaces.ParserOutput<F, B, A>> {
155-
const result = await super.parse(options, argv);
156-
157-
const parsedArgs = result.args as Record<string, unknown>;
158-
const flags = result.flags as BaseFlags;
159-
for (const [argName, label] of Object.entries(
160-
AblyBaseCommand.RESOURCE_ARG_LABELS,
161-
)) {
162-
if (
163-
argName in parsedArgs &&
164-
typeof parsedArgs[argName] === "string" &&
165-
!(parsedArgs[argName] as string).trim()
166-
) {
167-
this.fail(`${label} name cannot be empty`, flags, "parse");
168-
}
134+
): void {
135+
const name = (args.channel ?? args.channels ?? "") as string;
136+
if (!name.trim()) {
137+
this.fail("Channel name cannot be empty", flags, "parse");
169138
}
170139

171-
// Also validate argv entries for variadic commands (strict: false)
172-
// where extra values bypass the named arg
173-
const hasResourceArg = Object.keys(
174-
AblyBaseCommand.RESOURCE_ARG_LABELS,
175-
).some((name) => name in parsedArgs);
176-
if (hasResourceArg && Array.isArray(result.argv)) {
177-
const label = Object.entries(AblyBaseCommand.RESOURCE_ARG_LABELS).find(
178-
([name]) => name in parsedArgs,
179-
)?.[1];
180-
for (const value of result.argv as string[]) {
181-
if (typeof value === "string" && !value.trim()) {
182-
this.fail(`${label} name cannot be empty`, flags, "parse");
140+
if (argv) {
141+
if (argv.length === 0) {
142+
this.fail(
143+
"At least one channel name is required",
144+
flags,
145+
"channelSubscribe",
146+
);
147+
}
148+
149+
for (const n of argv) {
150+
if (!n.trim()) {
151+
this.fail("Channel name cannot be empty", flags, "parse");
183152
}
184153
}
185154
}
186-
187-
return result;
188155
}
189156

190157
protected isAnonymousWebMode(): boolean {

src/chat-base-command.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,33 @@ export abstract class ChatBaseCommand extends AblyBaseCommand {
1717
private _chatClient: ChatClient | null = null;
1818
private _cleanupTimeout: NodeJS.Timeout | undefined;
1919

20+
protected validateRoomName(
21+
args: Record<string, unknown>,
22+
flags: BaseFlags,
23+
argv?: string[],
24+
): void {
25+
const name = (args.room ?? args.rooms ?? "") as string;
26+
if (!name.trim()) {
27+
this.fail("Room name cannot be empty", flags, "parse");
28+
}
29+
30+
if (argv) {
31+
if (argv.length === 0) {
32+
this.fail(
33+
"At least one room name is required",
34+
flags,
35+
"roomMessageSubscribe",
36+
);
37+
}
38+
39+
for (const n of argv) {
40+
if (!n.trim()) {
41+
this.fail("Room name cannot be empty", flags, "parse");
42+
}
43+
}
44+
}
45+
}
46+
2047
/**
2148
* Override getClientOptions to disable binary protocol for Chat commands.
2249
* The Chat API uses realtime.request() for REST calls, and binary (MsgPack)

src/commands/apps/create.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ export default class AppsCreateCommand extends ControlBaseCommand {
3232

3333
async run(): Promise<void> {
3434
const { flags } = await this.parse(AppsCreateCommand);
35+
if (!flags.name?.trim()) {
36+
this.fail("App name cannot be empty", flags, "parse");
37+
}
3538

3639
try {
3740
const controlApi = this.createControlApi(flags);

src/commands/apps/rules/create.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ export default class RulesCreateCommand extends ControlBaseCommand {
100100

101101
async run(): Promise<void> {
102102
const { flags } = await this.parse(RulesCreateCommand);
103+
if (!flags.name?.trim()) {
104+
this.fail("Rule name cannot be empty", flags, "parse");
105+
}
103106

104107
const appId = await this.requireAppId(flags);
105108

src/commands/auth/keys/create.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ export default class KeysCreateCommand extends ControlBaseCommand {
4242

4343
async run(): Promise<void> {
4444
const { flags } = await this.parse(KeysCreateCommand);
45+
if (!flags.name?.trim()) {
46+
this.fail("Key name cannot be empty", flags, "parse");
47+
}
4548

4649
const appId = await this.requireAppId(flags);
4750

src/commands/channels/annotations/delete.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export default class ChannelsAnnotationsDelete extends AblyBaseCommand {
5151

5252
async run(): Promise<void> {
5353
const { args, flags } = await this.parse(ChannelsAnnotationsDelete);
54+
this.validateChannelName(args, flags);
5455
const channelName = args.channel;
5556
const serial = args.serial;
5657
const type = args.type;

src/commands/channels/annotations/get.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export default class ChannelsAnnotationsGet extends AblyBaseCommand {
4747

4848
async run(): Promise<void> {
4949
const { args, flags } = await this.parse(ChannelsAnnotationsGet);
50+
this.validateChannelName(args, flags);
5051
const channelName = args.channel;
5152
const serial = args.serial;
5253

src/commands/channels/annotations/publish.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export default class ChannelsAnnotationsPublish extends AblyBaseCommand {
6262

6363
async run(): Promise<void> {
6464
const { args, flags } = await this.parse(ChannelsAnnotationsPublish);
65+
this.validateChannelName(args, flags);
6566
const channelName = args.channel;
6667
const serial = args.serial;
6768
const type = args.type;

src/commands/channels/annotations/subscribe.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export default class ChannelsAnnotationsSubscribe extends AblyBaseCommand {
5050

5151
async run(): Promise<void> {
5252
const { args, flags } = await this.parse(ChannelsAnnotationsSubscribe);
53+
this.validateChannelName(args, flags);
5354
const channelName = args.channel;
5455

5556
try {

src/commands/channels/append.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export default class ChannelsAppend extends AblyBaseCommand {
5656

5757
async run(): Promise<void> {
5858
const { args, flags } = await this.parse(ChannelsAppend);
59+
this.validateChannelName(args, flags);
5960
const channelName = args.channel;
6061
const serial = args.serial;
6162

0 commit comments

Comments
 (0)