From d424d9feef8bcb55f4a2a25fca19d25ad7b7e697 Mon Sep 17 00:00:00 2001 From: Kanad Gupta <8854718+kanadgupta@users.noreply.github.com> Date: Fri, 15 Sep 2023 12:05:08 -0500 Subject: [PATCH] feat(versions): flag parity with API, copy fixes (#906) BREAKING CHANGE: this flips the `isPublic` flag to `hidden`. --- README.md | 2 +- __tests__/cmds/versions/create.test.ts | 15 +++++------ __tests__/cmds/versions/update.test.ts | 35 +++++++++++--------------- __tests__/lib/prompts.test.ts | 2 +- src/cmds/versions/create.ts | 13 ++++------ src/cmds/versions/update.ts | 9 +++---- src/lib/baseCommand.ts | 13 +++++----- src/lib/prompts.ts | 20 +++++++-------- 8 files changed, 50 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index 76f2a869d..b4c3a9672 100644 --- a/README.md +++ b/README.md @@ -395,7 +395,7 @@ If you wish to automate the process of creating a new project version, and not h For example, the following command contains all the flags to bypass the CLI prompts: ```sh -rdme versions:create --fork={version-fork} --main={true|false} --beta={true|false} --deprecated={true|false} --isPublic={true|false} +rdme versions:create --fork={version-fork} --main={true|false} --beta={true|false} --deprecated={true|false} --hidden={true|false} ``` See `rdme versions:create --help` for a full list of flags. diff --git a/__tests__/cmds/versions/create.test.ts b/__tests__/cmds/versions/create.test.ts index 4e0d5a374..7c858a75d 100644 --- a/__tests__/cmds/versions/create.test.ts +++ b/__tests__/cmds/versions/create.test.ts @@ -48,7 +48,7 @@ describe('rdme versions:create', () => { }); it('should create a specific version', async () => { - prompts.inject([version, false, true, true]); + prompts.inject([version, false, true, true, false]); const newVersion = '1.0.1'; const mockRequest = getAPIMock() @@ -60,7 +60,8 @@ describe('rdme versions:create', () => { is_stable: false, is_beta: true, from: '1.0.0', - is_hidden: false, + is_hidden: true, + is_deprecated: false, }) .basicAuth({ user: key }) .reply(201, { version: newVersion }); @@ -96,7 +97,7 @@ describe('rdme versions:create', () => { deprecated: 'false', main: 'false', codename: 'test', - isPublic: 'true', + hidden: 'false', }), ).resolves.toBe(`Version ${newVersion} created successfully.`); @@ -123,7 +124,7 @@ describe('rdme versions:create', () => { fork: version, beta: 'false', main: 'true', - isPublic: 'false', + hidden: 'true', deprecated: 'true', }), ).resolves.toBe(`Version ${newVersion} created successfully.`); @@ -174,7 +175,7 @@ describe('rdme versions:create', () => { ).rejects.toStrictEqual(new Error("Invalid option passed for 'deprecated'. Must be 'true' or 'false'.")); }); - it('should throw if non-boolean `isPublic` flag is passed', () => { + it('should throw if non-boolean `hidden` flag is passed', () => { const newVersion = '1.0.1'; return expect( @@ -183,9 +184,9 @@ describe('rdme versions:create', () => { version: newVersion, fork: version, // @ts-expect-error deliberately passing a bad value here - isPublic: 'test', + hidden: 'test', }), - ).rejects.toStrictEqual(new Error("Invalid option passed for 'isPublic'. Must be 'true' or 'false'.")); + ).rejects.toStrictEqual(new Error("Invalid option passed for 'hidden'. Must be 'true' or 'false'.")); }); it('should throw if non-boolean `main` flag is passed', () => { diff --git a/__tests__/cmds/versions/update.test.ts b/__tests__/cmds/versions/update.test.ts index 77b227c21..e24174df0 100644 --- a/__tests__/cmds/versions/update.test.ts +++ b/__tests__/cmds/versions/update.test.ts @@ -38,7 +38,7 @@ describe('rdme versions:update', () => { it('should update a specific version object', async () => { const versionToChange = '1.1.0'; const renamedVersion = '1.1.0-update'; - prompts.inject([versionToChange, renamedVersion, false, true, true, false]); + prompts.inject([versionToChange, renamedVersion, false, true, false, false]); const updatedVersionObject = { version: renamedVersion, @@ -96,7 +96,7 @@ describe('rdme versions:update', () => { beta: 'true', main: 'false', codename: 'updated-test', - isPublic: 'true', + hidden: 'false', }), ).resolves.toBe(`Version ${versionToChange} updated successfully.`); mockRequest.done(); @@ -111,7 +111,7 @@ describe('rdme versions:update', () => { version: renamedVersion, is_beta: false, is_deprecated: false, - is_hidden: false, + is_hidden: true, is_stable: false, }; @@ -135,7 +135,7 @@ describe('rdme versions:update', () => { deprecated: 'false', main: 'false', codename: 'updated-test', - isPublic: 'true', + hidden: 'true', }), ).resolves.toBe(`Version ${versionToChange} updated successfully.`); mockRequest.done(); @@ -173,7 +173,7 @@ describe('rdme versions:update', () => { newVersion: renamedVersion, main: 'false', codename: 'updated-test', - isPublic: 'true', + hidden: 'false', }), ).resolves.toBe(`Version ${versionToChange} updated successfully.`); mockRequest.done(); @@ -210,7 +210,7 @@ describe('rdme versions:update', () => { beta: 'false', main: 'false', codename: 'updated-test', - isPublic: 'true', + hidden: 'false', }), ).resolves.toBe(`Version ${versionToChange} updated successfully.`); mockRequest.done(); @@ -245,17 +245,12 @@ describe('rdme versions:update', () => { deprecated: 'true', beta: 'false', main: 'true', - isPublic: 'false', + hidden: 'true', }), ).resolves.toBe(`Version ${versionToChange} updated successfully.`); mockRequest.done(); }); - // Note: this test is a bit bizarre since the flag management - // in our version commands is really confusing to follow. - // I'm not sure if it's technically possible to demote a stable version - // with our current prompt/flag management flow, but that's not - // really the purpose of this test so I think it's fine as is. it('should catch any put request errors', async () => { const renamedVersion = '1.0.0-update'; @@ -263,15 +258,15 @@ describe('rdme versions:update', () => { version: renamedVersion, is_beta: true, is_deprecated: true, - is_hidden: true, + is_hidden: false, is_stable: false, }; - prompts.inject([renamedVersion, true, false, true]); + prompts.inject([renamedVersion, false, true, false, true]); const errorResponse = { - error: 'VERSION_CANT_DEMOTE_STABLE', - message: "You can't make a stable version non-stable", + error: 'VERSION_DUPLICATE', + message: 'The version already exists.', suggestion: '...a suggestion to resolve the issue...', help: 'If you need help, email support@readme.io and mention log "fake-metrics-uuid".', }; @@ -287,7 +282,7 @@ describe('rdme versions:update', () => { .basicAuth({ user: key }) .reply(400, errorResponse); - await expect(updateVersion.run({ key, version, main: 'false' })).rejects.toStrictEqual(new APIError(errorResponse)); + await expect(updateVersion.run({ key, version })).rejects.toStrictEqual(new APIError(errorResponse)); mockRequest.done(); }); @@ -336,7 +331,7 @@ describe('rdme versions:update', () => { mockRequest.done(); }); - it('should throw if non-boolean `isPublic` flag is passed', async () => { + it('should throw if non-boolean `hidden` flag is passed', async () => { const versionToChange = '1.1.0'; const mockRequest = getAPIMock() @@ -352,9 +347,9 @@ describe('rdme versions:update', () => { key, version: versionToChange, // @ts-expect-error deliberately passing a bad value here - isPublic: 'hi', + hidden: 'hi', }), - ).rejects.toStrictEqual(new Error("Invalid option passed for 'isPublic'. Must be 'true' or 'false'.")); + ).rejects.toStrictEqual(new Error("Invalid option passed for 'hidden'. Must be 'true' or 'false'.")); mockRequest.done(); }); diff --git a/__tests__/lib/prompts.test.ts b/__tests__/lib/prompts.test.ts index 06be844ce..05a951472 100644 --- a/__tests__/lib/prompts.test.ts +++ b/__tests__/lib/prompts.test.ts @@ -97,7 +97,7 @@ describe('prompt test bed', () => { newVersion: '1.2.1', is_stable: false, is_beta: true, - is_public: true, + is_hidden: true, is_deprecated: false, }); }); diff --git a/src/cmds/versions/create.ts b/src/cmds/versions/create.ts index 4e4a8649a..ce65ea187 100644 --- a/src/cmds/versions/create.ts +++ b/src/cmds/versions/create.ts @@ -20,7 +20,7 @@ export interface CommonOptions { beta?: 'true' | 'false'; codename?: string; deprecated?: 'true' | 'false'; - isPublic?: 'true' | 'false'; + hidden?: 'true' | 'false'; main?: 'true' | 'false'; } @@ -49,7 +49,7 @@ export default class CreateVersionCommand extends Command { await super.run(opts); let versionList; - const { key, version, fork, codename, main, beta, deprecated, isPublic } = opts; + const { key, version, fork, codename, main, beta, deprecated, hidden } = opts; if (!version || !semver.valid(semver.coerce(version))) { return Promise.reject( @@ -64,17 +64,15 @@ export default class CreateVersionCommand extends Command { }).then(handleRes); } - const versionPrompt = promptHandler.versionPrompt(versionList || []); - prompts.override({ from: fork, is_beta: castStringOptToBool(beta, 'beta'), is_deprecated: castStringOptToBool(deprecated, 'deprecated'), - is_public: castStringOptToBool(isPublic, 'isPublic'), + is_hidden: castStringOptToBool(hidden, 'hidden'), is_stable: castStringOptToBool(main, 'main'), }); - const promptResponse = await promptTerminal(versionPrompt); + const promptResponse = await promptTerminal(promptHandler.versionPrompt(versionList || [])); const body: Version = { codename, @@ -82,8 +80,7 @@ export default class CreateVersionCommand extends Command { from: promptResponse.from, is_beta: promptResponse.is_beta, is_deprecated: promptResponse.is_deprecated, - // if the "is public" question was never asked, we should omit that from the payload - is_hidden: typeof promptResponse.is_public === 'undefined' ? undefined : !promptResponse.is_public, + is_hidden: promptResponse.is_hidden, is_stable: promptResponse.is_stable, }; diff --git a/src/cmds/versions/update.ts b/src/cmds/versions/update.ts index 67ea2e37b..8203579d9 100644 --- a/src/cmds/versions/update.ts +++ b/src/cmds/versions/update.ts @@ -40,7 +40,7 @@ export default class UpdateVersionCommand extends Command { async run(opts: AuthenticatedCommandOptions) { await super.run(opts); - const { key, version, newVersion, codename, main, beta, isPublic, deprecated } = opts; + const { key, version, newVersion, codename, main, beta, hidden, deprecated } = opts; const selectedVersion = await getProjectVersion(version, key); @@ -56,7 +56,7 @@ export default class UpdateVersionCommand extends Command { prompts.override({ is_beta: castStringOptToBool(beta, 'beta'), is_deprecated: castStringOptToBool(deprecated, 'deprecated'), - is_public: castStringOptToBool(isPublic, 'isPublic'), + is_hidden: castStringOptToBool(hidden, 'hidden'), is_stable: castStringOptToBool(main, 'main'), newVersion, }); @@ -65,12 +65,11 @@ export default class UpdateVersionCommand extends Command { const body: Version = { codename, - // fall back to current version if user didn't enter one + // fallback to existing version if user was prompted to rename the version but didn't enter anything version: promptResponse.newVersion || version, is_beta: promptResponse.is_beta, is_deprecated: promptResponse.is_deprecated, - // if the "is public" question was never asked, we should omit that from the payload - is_hidden: typeof promptResponse.is_public === 'undefined' ? undefined : !promptResponse.is_public, + is_hidden: promptResponse.is_hidden, is_stable: promptResponse.is_stable, }; diff --git a/src/lib/baseCommand.ts b/src/lib/baseCommand.ts index 75bbb6f85..bb20224af 100644 --- a/src/lib/baseCommand.ts +++ b/src/lib/baseCommand.ts @@ -189,24 +189,23 @@ export default class Command { { name: 'main', type: String, - description: - "Should this version be the primary (default) version for your project? (Must be 'true' or 'false')", + description: "Should this be the main version for your project? (Must be 'true' or 'false')", }, { name: 'beta', type: String, - description: "Is this version in beta? (Must be 'true' or 'false')", + description: "Should this version be in beta? (Must be 'true' or 'false')", }, { name: 'deprecated', type: String, - description: "Would you like to deprecate this version? (Must be 'true' or 'false')", + description: + "Should this version be deprecated? The main version cannot be deprecated. (Must be 'true' or 'false')", }, { - name: 'isPublic', + name: 'hidden', type: String, - description: - "Would you like to make this version public? Any primary version must be public. (Must be 'true' or 'false')", + description: "Should this version be hidden? The main version cannot be hidden. (Must be 'true' or 'false')", }, ]; } diff --git a/src/lib/prompts.ts b/src/lib/prompts.ts index c20ec3b94..ee55ec84f 100644 --- a/src/lib/prompts.ts +++ b/src/lib/prompts.ts @@ -139,14 +139,14 @@ export function versionPrompt( /** list of versions, used for prompt about which version to fork */ versionList: Version[], /** existing version if we're performing an update */ - isUpdate?: { + existingVersion?: { is_stable: boolean; }, ): PromptObject[] { return [ { // only runs for versions:create command - type: isUpdate ? null : 'select', + type: existingVersion ? null : 'select', name: 'from', message: 'Which version would you like to fork from?', choices: versionList.map(v => { @@ -158,7 +158,7 @@ export function versionPrompt( }, { // only runs for versions:update command - type: !isUpdate ? null : 'text', + type: !existingVersion ? null : 'text', name: 'newVersion', message: 'What should the version be renamed to?', hint: '1.0.0', @@ -169,11 +169,11 @@ export function versionPrompt( }, }, { - // if the existing version being updated is already the main version, - // we can't switch that so we skip this question - type: isUpdate?.is_stable ? null : 'confirm', + // if the user is already updating the main version + // we skip this question since it must remain the main version + type: existingVersion?.is_stable ? null : 'confirm', name: 'is_stable', - message: 'Would you like to make this version the main version for this project?', + message: 'Should this be the main version for your project?', }, { type: 'confirm', @@ -186,8 +186,8 @@ export function versionPrompt( // it can't also be hidden. return values.is_stable ? null : 'confirm'; }, - name: 'is_public', - message: 'Would you like to make this version public?', + name: 'is_hidden', + message: 'Should this version be hidden?', }, { type: (prev, values) => { @@ -196,7 +196,7 @@ export function versionPrompt( return values.is_stable ? null : 'confirm'; }, name: 'is_deprecated', - message: 'Would you like to deprecate this version?', + message: 'Should this version be deprecated?', }, ]; }