From 829deb800403cd24d4e780a3701881f808200b9d Mon Sep 17 00:00:00 2001 From: Elanthenral Elangovan Date: Tue, 9 Dec 2025 10:11:14 -0800 Subject: [PATCH] ACNA-4221: Addding custome help class to fix alias rt to display help commands --- package.json | 1 + src/custom-help.js | 59 ++++++++++++++++++++++++++++++++++++++++ test/custom-help.test.js | 54 ++++++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+) create mode 100644 src/custom-help.js create mode 100644 test/custom-help.test.js diff --git a/package.json b/package.json index a0fdeba..6d2bcb0 100644 --- a/package.json +++ b/package.json @@ -78,6 +78,7 @@ "topicSeparator": " ", "commands": "./src/commands", "bin": "aio", + "helpClass": "./src/custom-help", "plugins": [ "@oclif/plugin-help", "@oclif/plugin-plugins", diff --git a/src/custom-help.js b/src/custom-help.js new file mode 100644 index 0000000..781b21b --- /dev/null +++ b/src/custom-help.js @@ -0,0 +1,59 @@ +/* + * Copyright 2025 Adobe Inc. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +const { Help } = require('@oclif/core') + +/** + * Custom Help class to handle alias resolution for command help display. + * + * Issue: When users run "aio rt --help", oclif's help system doesn't recognize + * that "rt" is an alias for "runtime" and should display all subcommands. + * The help system looks for "rt:*" subcommands which don't exist in the manifest + * (they're registered as "runtime:*"). + * + * Solution: Override showHelp to resolve aliases to their canonical command names + * before displaying help, ensuring proper subcommand listing. + * + * @see https://github.com/adobe/aio-cli-plugin-runtime + */ +class CustomHelp extends Help { + /** + * Show help for a command, resolving aliases to canonical names. + * + * @param {string[]} args - Command ID and arguments to show help for + * @returns {Promise} + */ + async showHelp (args) { + // Skip alias resolution if args is invalid or empty + if (!Array.isArray(args) || args.length === 0) { + return super.showHelp(args) + } + + // Map of known aliases to canonical command names + // Add more mappings here as needed for other top-level aliases + const aliasMap = { + rt: 'runtime' + } + + // Resolve alias to canonical name if it exists + const commandId = args[0] + if (aliasMap[commandId]) { + const resolvedArgs = [aliasMap[commandId], ...args.slice(1)] + return super.showHelp(resolvedArgs) + } + + // No alias resolution needed, show help as-is + return super.showHelp(args) + } +} + +module.exports = CustomHelp diff --git a/test/custom-help.test.js b/test/custom-help.test.js new file mode 100644 index 0000000..e0d058e --- /dev/null +++ b/test/custom-help.test.js @@ -0,0 +1,54 @@ +/* + * Copyright 2025 Adobe Inc. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +const { Help } = require('@oclif/core') +const CustomHelp = require('../src/custom-help') + +describe('CustomHelp', () => { + let customHelp + let showHelpSpy + + beforeEach(() => { + const mockConfig = { commands: new Map(), topics: [] } + customHelp = new CustomHelp(mockConfig) + showHelpSpy = jest.spyOn(Help.prototype, 'showHelp').mockResolvedValue() + }) + + afterEach(() => { + showHelpSpy.mockRestore() + }) + + test('resolves "rt" alias to "runtime"', async () => { + await customHelp.showHelp(['rt']) + expect(showHelpSpy).toHaveBeenCalledWith(['runtime']) + }) + + test('resolves "rt" with subcommands', async () => { + await customHelp.showHelp(['rt', 'action']) + expect(showHelpSpy).toHaveBeenCalledWith(['runtime', 'action']) + }) + + test('passes through non-aliased commands unchanged', async () => { + await customHelp.showHelp(['config']) + expect(showHelpSpy).toHaveBeenCalledWith(['config']) + }) + + test('handles empty array', async () => { + await customHelp.showHelp([]) + expect(showHelpSpy).toHaveBeenCalledWith([]) + }) + + test('handles non-array arguments', async () => { + await customHelp.showHelp('runtime') + expect(showHelpSpy).toHaveBeenCalledWith('runtime') + }) +})