From 2f71b038ce2b6d48e840d7b53813634369aa2a1e Mon Sep 17 00:00:00 2001 From: Shazron Abdullah <36107+shazron@users.noreply.github.com> Date: Wed, 25 Mar 2026 21:04:32 +0800 Subject: [PATCH 1/9] chore: update @oclif/core to v4 - Bump @oclif/core from ^2.0.0 to ^4.0.0 and oclif devDep to ^4.0.0 - Replace removed ux.prompt() with a readline-based prompt utility (src/prompt.js) - Fix tests: pass mock config with runHook to Command constructor (required by v4) - Convert set.js tests from instance-based to static Command.run() approach - Add allowModules for @oclif/core in eslint settings (v4 uses exports-only, no main field) Closes #182 Co-Authored-By: Claude Sonnet 4.6 --- .eslintrc.json | 5 +++ .gitignore | 1 + package.json | 4 +- src/commands/config/clear.js | 5 ++- src/commands/config/set.js | 5 ++- src/prompt.js | 31 ++++++++++++++++ test/commands/base-command.js | 8 ++-- test/commands/config/clear.js | 17 +++------ test/commands/config/set.js | 69 +++++++++++------------------------ test/commands/prompt.js | 32 ++++++++++++++++ 10 files changed, 110 insertions(+), 67 deletions(-) create mode 100644 src/prompt.js create mode 100644 test/commands/prompt.js diff --git a/.eslintrc.json b/.eslintrc.json index d86882e..0d06011 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,5 +1,10 @@ { "extends": "@adobe/eslint-config-aio-lib-config", + "settings": { + "node": { + "allowModules": ["@oclif/core"] + } + }, "rules": { "jsdoc/tag-lines": [ // The Error level should be `error`, `warn`, or `off` (or 2, 1, or 0) diff --git a/.gitignore b/.gitignore index ac02c8e..fac8f55 100755 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ junit.xml /coverage oclif.manifest.json +.claude diff --git a/package.json b/package.json index cf81a80..c727080 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "bugs": "https://github.com/adobe/aio-cli-plugin-config/issues", "dependencies": { "@adobe/aio-lib-core-config": "^5", - "@oclif/core": "^2.0.0", + "@oclif/core": "^4.0.0", "hjson": "^3.2.2", "js-yaml": "^4.1.0" }, @@ -30,7 +30,7 @@ "jest-haste-map": "^29.5.0", "jest-junit": "^16.0.0", "jest-resolve": "^29.5.0", - "oclif": "^3.2.0", + "oclif": "^4.0.0", "stdout-stderr": "^0.1.13" }, "engines": { diff --git a/src/commands/config/clear.js b/src/commands/config/clear.js index da59c8a..93f308c 100755 --- a/src/commands/config/clear.js +++ b/src/commands/config/clear.js @@ -10,15 +10,16 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -const { Flags, ux } = require('@oclif/core') +const { Flags } = require('@oclif/core') const BaseCommand = require('../../base-command') +const { prompt } = require('../../prompt') class ClearCommand extends BaseCommand { async run () { const { flags } = await this.parse(ClearCommand) if (!flags.force) { - const confirm = await ux.prompt('are you sure? [yN]', { type: 'normal' }) + const confirm = await prompt('are you sure? [yN]') if (!confirm[0] || confirm[0].toLowerCase() !== 'y') { return } diff --git a/src/commands/config/set.js b/src/commands/config/set.js index 68308f9..b3a61c0 100644 --- a/src/commands/config/set.js +++ b/src/commands/config/set.js @@ -10,13 +10,14 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -const { Flags, Args, ux } = require('@oclif/core') +const { Flags, Args } = require('@oclif/core') const BaseCommand = require('../../base-command') const fs = require('fs') const yaml = require('js-yaml') const hjson = require('hjson') const { getPipedData } = require('@adobe/aio-lib-core-config') const path = require('path') +const { prompt } = require('../../prompt') class SetCommand extends BaseCommand { async run () { @@ -39,7 +40,7 @@ class SetCommand extends BaseCommand { this.error(`Cannot read file: ${value}`) } } else if (flags.interactive) { - value = await ux.prompt('value', { type: 'normal' }) + value = await prompt('value') } else if (value == null) { if (args.key.indexOf('=') > 0) { const parts = args.key.split('=') diff --git a/src/prompt.js b/src/prompt.js new file mode 100644 index 0000000..7df4094 --- /dev/null +++ b/src/prompt.js @@ -0,0 +1,31 @@ +/* +Copyright 2024 Adobe. 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 readline = require('readline') + +/** + * Prompts the user for input. + * + * @param {string} message - the prompt message to display + * @returns {Promise} the user's input + */ +async function prompt (message) { + const rl = readline.createInterface({ input: process.stdin, output: process.stdout }) + return new Promise((resolve) => { + rl.question(`${message}: `, (answer) => { + rl.close() + resolve(answer) + }) + }) +} + +module.exports = { prompt } diff --git a/test/commands/base-command.js b/test/commands/base-command.js index bfe7805..46b3ab1 100644 --- a/test/commands/base-command.js +++ b/test/commands/base-command.js @@ -15,6 +15,8 @@ const TheCommand = require('../../src/base-command') const { stdout } = require('stdout-stderr') const hjson = require('hjson') +const mockConfig = { runHook: async () => ({ successes: [], failures: [] }) } + describe('base-command', () => { test('exports', () => { expect(typeof TheCommand).toEqual('function') @@ -29,7 +31,7 @@ describe('base-command', () => { let command beforeEach(() => { - command = new TheCommand([], { }) + command = new TheCommand([], mockConfig) }) describe('printObject', () => { @@ -43,13 +45,13 @@ describe('base-command', () => { }) test('yaml', async () => { - command = new TheCommand(['--yaml'], { }) + command = new TheCommand(['--yaml'], mockConfig) await command.printObject({ foo: { bar: true } }) expect(stdout.output).toEqual('foo:\n bar: true\n\n') }) test('json', async () => { - command = new TheCommand(['--json'], { }) + command = new TheCommand(['--json'], mockConfig) await command.printObject({ foo: { bar: true } }) expect(stdout.output).toEqual('{"foo":{"bar":true}}\n') }) diff --git a/test/commands/config/clear.js b/test/commands/config/clear.js index d0e8de7..9d2a655 100755 --- a/test/commands/config/clear.js +++ b/test/commands/config/clear.js @@ -13,15 +13,10 @@ governing permissions and limitations under the License. const TheCommand = require('../../../src/commands/config/clear.js') const { mockSet } = require('@adobe/aio-lib-core-config/src/Config') -jest.mock('@oclif/core', () => { - return { - ...jest.requireActual('@oclif/core'), - ux: { - prompt: jest.fn() - } - } -}) -const { ux } = require('@oclif/core') +jest.mock('../../../src/prompt', () => ({ + prompt: jest.fn() +})) +const { prompt } = require('../../../src/prompt') describe('clear', () => { afterEach(() => { @@ -51,14 +46,14 @@ describe('clear', () => { }) test('prompt with yes', () => { - ux.prompt = jest.fn(() => 'y') + prompt.mockResolvedValue('y') return TheCommand.run([]).then(() => { expect(mockSet).toHaveBeenCalledWith(null, null, false) }) }) test('prompt with no', () => { - ux.prompt = jest.fn(() => 'n') + prompt.mockResolvedValue('n') return TheCommand.run([]).then(() => { expect(mockSet).not.toHaveBeenCalled() }) diff --git a/test/commands/config/set.js b/test/commands/config/set.js index 8713a83..0b40260 100644 --- a/test/commands/config/set.js +++ b/test/commands/config/set.js @@ -10,26 +10,18 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -const { ux } = require('@oclif/core') const TheCommand = require('../../../src/commands/config/set.js') const config = require('@adobe/aio-lib-core-config') const path = require('path') const { mockSet } = require('@adobe/aio-lib-core-config/src/Config') -jest.mock('@oclif/core', () => { - return { - ...jest.requireActual('@oclif/core'), - ux: { - prompt: jest.fn() - } - } -}) +jest.mock('../../../src/prompt', () => ({ + prompt: jest.fn() +})) +const { prompt } = require('../../../src/prompt') describe('set', () => { - let command - beforeEach(() => { - command = new TheCommand([]) mockSet.mockImplementation(() => { return { a: 12 } }) }) @@ -42,106 +34,89 @@ describe('set', () => { }) test('default', async () => { - command.argv = ['a-key', 'value'] - await expect(command.run()).resolves.not.toThrow() + await expect(TheCommand.run(['a-key', 'value'])).resolves.not.toThrow() expect(mockSet).toHaveBeenCalledWith('a-key', 'value', false) }) test('local', async () => { - command.argv = ['-l', 'a-key', 'value'] - await expect(command.run()).resolves.not.toThrow() + await expect(TheCommand.run(['-l', 'a-key', 'value'])).resolves.not.toThrow() expect(mockSet).toHaveBeenCalledWith('a-key', 'value', true) }) test('global', async () => { - command.argv = ['-g', 'a-key', 'value'] - await expect(command.run()).resolves.not.toThrow() + await expect(TheCommand.run(['-g', 'a-key', 'value'])).resolves.not.toThrow() expect(mockSet).toHaveBeenCalledWith('a-key', 'value', false) }) test('no value', async () => { - command.argv = ['a-key'] - await expect(command.run()).rejects.toEqual(new Error('Missing value')) + await expect(TheCommand.run(['a-key'])).rejects.toEqual(new Error('Missing value')) }) test('get piped data', async () => { config.getPipedData.mockResolvedValue('a file') - command.argv = ['-g', 'a-key'] - await expect(command.run()).resolves.not.toThrow() + await expect(TheCommand.run(['-g', 'a-key'])).resolves.not.toThrow() expect(config.getPipedData).toHaveBeenCalledWith() expect(mockSet).toHaveBeenCalledWith('a-key', 'a file', false) }) test('parse key=value', async () => { - command.argv = ['a-key=value'] - await expect(command.run()).resolves.not.toThrow() + await expect(TheCommand.run(['a-key=value'])).resolves.not.toThrow() expect(mockSet).toHaveBeenCalledWith('a-key', 'value', false) }) test('parse json', async () => { - command.argv = ['a-key', '-j', '{a:1}'] - await expect(command.run()).resolves.not.toThrow() + await expect(TheCommand.run(['a-key', '-j', '{a:1}'])).resolves.not.toThrow() expect(mockSet).toHaveBeenCalledWith('a-key', { a: 1 }, false) }) test('throw error on bad yaml parsing', async () => { - command.argv = ['a-key', '-y', 'a:\nhy '] - await expect(command.run()).rejects.toEqual(new Error('Cannot parse yaml')) + await expect(TheCommand.run(['a-key', '-y', 'a:\nhy '])).rejects.toEqual(new Error('Cannot parse yaml')) }) test('throw error on bad json parsing', async () => { - command.argv = ['a-key', '-j', '{a:1\n'] - await expect(command.run()).rejects.toEqual(new Error('Cannot parse json')) + await expect(TheCommand.run(['a-key', '-j', '{a:1\n'])).rejects.toEqual(new Error('Cannot parse json')) }) test('parse yaml', async () => { - command.argv = ['a-key', '-y', 'a:\n b: true'] - await expect(command.run()).resolves.not.toThrow() + await expect(TheCommand.run(['a-key', '-y', 'a:\n b: true'])).resolves.not.toThrow() expect(mockSet).toHaveBeenCalledWith('a-key', { a: { b: true } }, false) }) test('json file', async () => { - command.argv = ['a-key', '-f', './test/__fixtures__/a.json'] - await expect(command.run()).resolves.not.toThrow() + await expect(TheCommand.run(['a-key', '-f', './test/__fixtures__/a.json'])).resolves.not.toThrow() expect(mockSet).toHaveBeenCalledWith('a-key', { a: 12 }, false) }) test('yaml file', async () => { - command.argv = ['a-key', '-f', './test/__fixtures__/a.yaml'] - await expect(command.run()).resolves.not.toThrow() + await expect(TheCommand.run(['a-key', '-f', './test/__fixtures__/a.yaml'])).resolves.not.toThrow() expect(mockSet).toHaveBeenCalledWith('a-key', { a: { b: 12 } }, false) }) test('yml file', async () => { - command.argv = ['a-key', '-f', './test/__fixtures__/a.yml'] - await expect(command.run()).resolves.not.toThrow() + await expect(TheCommand.run(['a-key', '-f', './test/__fixtures__/a.yml'])).resolves.not.toThrow() expect(mockSet).toHaveBeenCalledWith('a-key', { a: { b: 12 } }, false) }) test('other file', async () => { - command.argv = ['a-key', '-f', './test/__fixtures__/a.txt'] - await expect(command.run()).resolves.not.toThrow() + await expect(TheCommand.run(['a-key', '-f', './test/__fixtures__/a.txt'])).resolves.not.toThrow() expect(mockSet).toHaveBeenCalledWith('a-key', 'raw data', false) }) test('file but no value', async () => { - command.argv = ['a-key', '-f'] - await expect(command.run()).rejects.toEqual(new Error('Missing filename')) + await expect(TheCommand.run(['a-key', '-f'])).rejects.toEqual(new Error('Missing filename')) }) test('file but not exists', async () => { - command.argv = ['a-key', '-f', '/doesnotexist'] - await expect(command.run()).rejects.toEqual(new Error(`Cannot read file: ${path.resolve('/doesnotexist')}`)) + await expect(TheCommand.run(['a-key', '-f', '/doesnotexist'])).rejects.toEqual(new Error(`Cannot read file: ${path.resolve('/doesnotexist')}`)) }) test('prompt for value', async () => { config.getPipedData.mockResolvedValue(null) - ux.prompt = jest.fn(() => 'a value') + prompt.mockResolvedValue('a value') - command.argv = ['a-key', '-i'] - await expect(command.run()).resolves.not.toThrow() + await expect(TheCommand.run(['a-key', '-i'])).resolves.not.toThrow() expect(mockSet).toHaveBeenCalledWith('a-key', 'a value', false) }) }) diff --git a/test/commands/prompt.js b/test/commands/prompt.js new file mode 100644 index 0000000..675a241 --- /dev/null +++ b/test/commands/prompt.js @@ -0,0 +1,32 @@ +/* +Copyright 2024 Adobe. 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 readline = require('readline') +const { prompt } = require('../../src/prompt') + +jest.mock('readline') + +describe('prompt', () => { + test('returns user input', async () => { + const mockClose = jest.fn() + const userAnswer = 'user answer' + const mockQuestion = jest.fn((msg, cb) => cb(userAnswer)) + readline.createInterface.mockReturnValue({ question: mockQuestion, close: mockClose }) + + const result = await prompt('enter value') + + expect(readline.createInterface).toHaveBeenCalledWith({ input: process.stdin, output: process.stdout }) + expect(mockQuestion).toHaveBeenCalledWith('enter value: ', expect.any(Function)) + expect(mockClose).toHaveBeenCalled() + expect(result).toEqual('user answer') + }) +}) From 8275faa22f3b781d87de76107bf4e8d72b6394a6 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah <36107+shazron@users.noreply.github.com> Date: Wed, 25 Mar 2026 22:57:07 +0800 Subject: [PATCH 2/9] chore: replace readline with @inquirer/prompts in prompt utility Co-Authored-By: Claude Sonnet 4.6 --- package.json | 1 + src/prompt.js | 10 ++-------- test/commands/prompt.js | 15 ++++++--------- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index c727080..928cef1 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "bugs": "https://github.com/adobe/aio-cli-plugin-config/issues", "dependencies": { "@adobe/aio-lib-core-config": "^5", + "@inquirer/prompts": "^7.0.0", "@oclif/core": "^4.0.0", "hjson": "^3.2.2", "js-yaml": "^4.1.0" diff --git a/src/prompt.js b/src/prompt.js index 7df4094..e60806d 100644 --- a/src/prompt.js +++ b/src/prompt.js @@ -10,7 +10,7 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -const readline = require('readline') +const { input } = require('@inquirer/prompts') /** * Prompts the user for input. @@ -19,13 +19,7 @@ const readline = require('readline') * @returns {Promise} the user's input */ async function prompt (message) { - const rl = readline.createInterface({ input: process.stdin, output: process.stdout }) - return new Promise((resolve) => { - rl.question(`${message}: `, (answer) => { - rl.close() - resolve(answer) - }) - }) + return input({ message }) } module.exports = { prompt } diff --git a/test/commands/prompt.js b/test/commands/prompt.js index 675a241..88350a9 100644 --- a/test/commands/prompt.js +++ b/test/commands/prompt.js @@ -10,23 +10,20 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -const readline = require('readline') const { prompt } = require('../../src/prompt') -jest.mock('readline') +jest.mock('@inquirer/prompts', () => ({ + input: jest.fn() +})) +const { input } = require('@inquirer/prompts') describe('prompt', () => { test('returns user input', async () => { - const mockClose = jest.fn() - const userAnswer = 'user answer' - const mockQuestion = jest.fn((msg, cb) => cb(userAnswer)) - readline.createInterface.mockReturnValue({ question: mockQuestion, close: mockClose }) + input.mockResolvedValue('user answer') const result = await prompt('enter value') - expect(readline.createInterface).toHaveBeenCalledWith({ input: process.stdin, output: process.stdout }) - expect(mockQuestion).toHaveBeenCalledWith('enter value: ', expect.any(Function)) - expect(mockClose).toHaveBeenCalled() + expect(input).toHaveBeenCalledWith({ message: 'enter value' }) expect(result).toEqual('user answer') }) }) From c8f6c2f3a1a07873eec4e07a58cfde33126289d0 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah <36107+shazron@users.noreply.github.com> Date: Wed, 25 Mar 2026 23:21:58 +0800 Subject: [PATCH 3/9] chore: update @adobe/eslint-config-aio-lib-config to v5 - Bump @adobe/eslint-config-aio-lib-config from ^4.0.0 to ^5.0.0 - Update eslint from ^8 to ^9 - Migrate from .eslintrc.json to eslint.config.js (ESLint v9 flat config) - Migrate .eslintignore to ignores in eslint.config.js - Remove eslint plugins now provided by neostandard (via the shared config): eslint-config-oclif, eslint-config-standard, eslint-plugin-import, eslint-plugin-node, eslint-plugin-promise, eslint-plugin-standard, eslint-plugin-n Co-Authored-By: Claude Sonnet 4.6 --- .eslintignore | 1 - .eslintrc.json | 18 ------------------ eslint.config.js | 27 +++++++++++++++++++++++++++ package.json | 11 ++--------- 4 files changed, 29 insertions(+), 28 deletions(-) delete mode 100644 .eslintignore delete mode 100644 .eslintrc.json create mode 100644 eslint.config.js diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 1c2f433..0000000 --- a/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -tmp \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 0d06011..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "extends": "@adobe/eslint-config-aio-lib-config", - "settings": { - "node": { - "allowModules": ["@oclif/core"] - } - }, - "rules": { - "jsdoc/tag-lines": [ - // The Error level should be `error`, `warn`, or `off` (or 2, 1, or 0) - "error", - "never", - { - "startLines": null - } - ] - } -} \ No newline at end of file diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..1c7ec6c --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,27 @@ +/* +Copyright 2024 Adobe. 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 aioLibConfig = require('@adobe/eslint-config-aio-lib-config') +const jest = require('eslint-plugin-jest') + +module.exports = [ + { ignores: ['tmp'] }, + ...aioLibConfig, + jest.configs['flat/recommended'], + { + settings: { + n: { + allowModules: ['@oclif/core'] + } + } + } +] diff --git a/package.json b/package.json index 928cef1..d3f0b54 100644 --- a/package.json +++ b/package.json @@ -12,19 +12,12 @@ "js-yaml": "^4.1.0" }, "devDependencies": { - "@adobe/eslint-config-aio-lib-config": "^4.0.0", + "@adobe/eslint-config-aio-lib-config": "^5.0.0", "acorn": "^8.7.0", "chalk": "^4.0.0", - "eslint": "^8.57.1", - "eslint-config-oclif": "^5.2.2", - "eslint-config-standard": "^17.1.0", - "eslint-plugin-import": "^2.31.0", + "eslint": "^9.0.0", "eslint-plugin-jest": "^27.9.0", "eslint-plugin-jsdoc": "^48.11.0", - "eslint-plugin-n": "^15.7.0", - "eslint-plugin-node": "^11.1.0", - "eslint-plugin-promise": "^6.6.0", - "eslint-plugin-standard": "^5.0.0", "execa": "^4.0.2", "globby": "^11.0.0", "jest": "^29", From f29b6ae933f0a32971b0e896b72c24f9ff6bb5a1 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah <36107+shazron@users.noreply.github.com> Date: Wed, 25 Mar 2026 23:27:43 +0800 Subject: [PATCH 4/9] fix: upgrade eslint-plugin-jest to v29 for ESLint v9 compatibility eslint-plugin-jest@27 only supports eslint@^7||^8; v29 adds ^9 support. Also add neostandard as an explicit devDependency (peer dep of @adobe/eslint-config-aio-lib-config that npm does not auto-install). Co-Authored-By: Claude Sonnet 4.6 --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index d3f0b54..8d4be0e 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,8 @@ "acorn": "^8.7.0", "chalk": "^4.0.0", "eslint": "^9.0.0", - "eslint-plugin-jest": "^27.9.0", + "eslint-plugin-jest": "^29.0.0", + "neostandard": "^0.13.0", "eslint-plugin-jsdoc": "^48.11.0", "execa": "^4.0.2", "globby": "^11.0.0", From 34c36d95ee8462128d262db8c28b79a61efbe634 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah <36107+shazron@users.noreply.github.com> Date: Wed, 25 Mar 2026 23:33:16 +0800 Subject: [PATCH 5/9] fix: rename eslint.config.js to eslint.config.mjs for Node 18 compatibility neostandard uses ESM-only packages (find-up) that cannot be require()'d in Node 18. Using .mjs forces ESLint to load the config as an ES module, avoiding the ERR_REQUIRE_ESM error. Co-Authored-By: Claude Sonnet 4.6 --- eslint.config.js => eslint.config.mjs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename eslint.config.js => eslint.config.mjs (85%) diff --git a/eslint.config.js b/eslint.config.mjs similarity index 85% rename from eslint.config.js rename to eslint.config.mjs index 1c7ec6c..9bd1d49 100644 --- a/eslint.config.js +++ b/eslint.config.mjs @@ -10,10 +10,10 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -const aioLibConfig = require('@adobe/eslint-config-aio-lib-config') -const jest = require('eslint-plugin-jest') +import aioLibConfig from '@adobe/eslint-config-aio-lib-config' +import jest from 'eslint-plugin-jest' -module.exports = [ +export default [ { ignores: ['tmp'] }, ...aioLibConfig, jest.configs['flat/recommended'], From ce871ef4dc93abe23d19b5a6af1c320af7698289 Mon Sep 17 00:00:00 2001 From: Shazron Abdullah <36107+shazron@users.noreply.github.com> Date: Wed, 25 Mar 2026 23:39:31 +0800 Subject: [PATCH 6/9] fix: override find-up to v5 for Node 18 compatibility neostandard bundles find-up@8 (ESM-only), which cannot be require()'d in Node 18. The npm overrides field forces neostandard to use find-up@5 (CJS) which exports the same findUpSync API that neostandard uses. Co-Authored-By: Claude Sonnet 4.6 --- package.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/package.json b/package.json index 8d4be0e..b316cb8 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,11 @@ "engines": { "node": ">=18" }, + "overrides": { + "neostandard": { + "find-up": "^5.0.0" + } + }, "files": [ "/oclif.manifest.json", "/src" From 98dee7b9d6ff65afd64b3e9f9cd943a06d96755f Mon Sep 17 00:00:00 2001 From: Shazron Abdullah <36107+shazron@users.noreply.github.com> Date: Thu, 26 Mar 2026 22:32:23 +0800 Subject: [PATCH 7/9] Revert "fix: override find-up to v5 for Node 18 compatibility" This reverts commit ce871ef4dc93abe23d19b5a6af1c320af7698289. --- package.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/package.json b/package.json index b316cb8..8d4be0e 100644 --- a/package.json +++ b/package.json @@ -31,11 +31,6 @@ "engines": { "node": ">=18" }, - "overrides": { - "neostandard": { - "find-up": "^5.0.0" - } - }, "files": [ "/oclif.manifest.json", "/src" From dc32cafe63a7bbd3dd27c8d2df02bbafcecc518a Mon Sep 17 00:00:00 2001 From: Shazron Abdullah <36107+shazron@users.noreply.github.com> Date: Thu, 26 Mar 2026 22:33:22 +0800 Subject: [PATCH 8/9] Revert "fix: rename eslint.config.js to eslint.config.mjs for Node 18 compatibility" This reverts commit 34c36d95ee8462128d262db8c28b79a61efbe634. --- eslint.config.mjs => eslint.config.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename eslint.config.mjs => eslint.config.js (85%) diff --git a/eslint.config.mjs b/eslint.config.js similarity index 85% rename from eslint.config.mjs rename to eslint.config.js index 9bd1d49..1c7ec6c 100644 --- a/eslint.config.mjs +++ b/eslint.config.js @@ -10,10 +10,10 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -import aioLibConfig from '@adobe/eslint-config-aio-lib-config' -import jest from 'eslint-plugin-jest' +const aioLibConfig = require('@adobe/eslint-config-aio-lib-config') +const jest = require('eslint-plugin-jest') -export default [ +module.exports = [ { ignores: ['tmp'] }, ...aioLibConfig, jest.configs['flat/recommended'], From 6b96040751865cfa5c0c2bbb8feaf9be25eeb1ee Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 7 Apr 2026 11:34:22 +0000 Subject: [PATCH 9/9] chore: update copyright year to 2026 in new files Agent-Logs-Url: https://github.com/adobe/aio-cli-plugin-config/sessions/8ff9a4c5-d281-4fcc-bcce-e9e9c698b99b Co-authored-by: shazron <36107+shazron@users.noreply.github.com> --- eslint.config.js | 2 +- src/prompt.js | 2 +- test/commands/prompt.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 1c7ec6c..89b44d6 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,5 +1,5 @@ /* -Copyright 2024 Adobe. All rights reserved. +Copyright 2026 Adobe. 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 diff --git a/src/prompt.js b/src/prompt.js index e60806d..3ecbe7f 100644 --- a/src/prompt.js +++ b/src/prompt.js @@ -1,5 +1,5 @@ /* -Copyright 2024 Adobe. All rights reserved. +Copyright 2026 Adobe. 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 diff --git a/test/commands/prompt.js b/test/commands/prompt.js index 88350a9..62056de 100644 --- a/test/commands/prompt.js +++ b/test/commands/prompt.js @@ -1,5 +1,5 @@ /* -Copyright 2024 Adobe. All rights reserved. +Copyright 2026 Adobe. 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