diff --git a/README.md b/README.md index ffa07571..3e381f5d 100644 --- a/README.md +++ b/README.md @@ -539,8 +539,8 @@ Create a new Adobe I/O App ``` USAGE $ aio app init [PATH] [-v] [--version] [--install] [-y] [--login] [-e ... | -t ... | --repo - ] [--standalone-app | | ] [-w | -i ] [--confirm-new-workspace] [--use-jwt] [--github-pat - ] [--linter none|basic|adobe-recommended] + ] [--standalone-app | | ] [--template-options ] [-o | -i | ] [-p | | ] [-w + | | ] [--confirm-new-workspace] [--use-jwt] [--github-pat ] [--linter none|basic|adobe-recommended] ARGUMENTS PATH [default: .] Path to the app directory @@ -548,6 +548,8 @@ ARGUMENTS FLAGS -e, --extension=... Extension point(s) to implement -i, --import= Import an Adobe I/O Developer Console configuration file + -o, --org= Specify the Adobe Developer Console Org to init from (orgId, or orgCode) + -p, --project= Specify the Adobe Developer Console Project to init from (projectId, or projectName) -t, --template=... Specify a link to a template that will be installed -v, --verbose Verbose output -w, --workspace= [default: Stage] Specify the Adobe Developer Console Workspace to init from, @@ -561,6 +563,7 @@ FLAGS --[no-]login Login using your Adobe ID for interacting with Adobe I/O Developer Console --repo= Init from gh quick-start repo. Expected to be of the form // --standalone-app Create a stand-alone application + --template-options= Optional template options, as a base64-encoded json string --use-jwt if the config has both jwt and OAuth Server to Server Credentials (while migrating), prefer the JWT credentials --version Show version diff --git a/src/commands/app/init.js b/src/commands/app/init.js index 91519e46..5969fc22 100644 --- a/src/commands/app/init.js +++ b/src/commands/app/init.js @@ -122,6 +122,7 @@ class InitCommand extends TemplatesCommand { useDefaultValues: flags.yes, installNpm: flags.install, installConfig: flags.login, + templateOptions: flags['template-options'], templates }) } @@ -174,6 +175,7 @@ class InitCommand extends TemplatesCommand { await this.installTemplates({ useDefaultValues: flags.yes, installNpm: flags.install, + templateOptions: flags['template-options'], templates }) } @@ -456,21 +458,33 @@ InitCommand.flags = { char: 't', multiple: true }), + 'template-options': Flags.string({ + description: 'Optional template options, as a base64-encoded json string', + parse: input => { + try { + const decoded = Buffer.from(input, 'base64').toString('utf8') + aioLogger.debug(`--template-options: ${input} decoded as ${decoded}`) + return JSON.parse(decoded) + } catch (e) { + throw new Error(`--template-options: ${input} is not a base64 encoded JSON object.`) + } + } + }), org: Flags.string({ - description: 'Specify the Adobe Developer Console Org to init from', - hidden: true, - exclusive: ['import'] // also no-login + description: 'Specify the Adobe Developer Console Org to init from (orgId, or orgCode)', + char: 'o', + exclusive: ['import', 'no-login'] }), project: Flags.string({ - description: 'Specify the Adobe Developer Console Project to init from', - hidden: true, - exclusive: ['import'] // also no-login + description: 'Specify the Adobe Developer Console Project to init from (projectId, or projectName)', + char: 'p', + exclusive: ['import', 'no-login'] }), workspace: Flags.string({ description: 'Specify the Adobe Developer Console Workspace to init from, defaults to Stage', default: DEFAULT_WORKSPACE, char: 'w', - exclusive: ['import'] // also no-login + exclusive: ['import', 'no-login'] }), 'confirm-new-workspace': Flags.boolean({ description: 'Prompt to confirm before creating a new workspace', diff --git a/test/commands/app/init.test.js b/test/commands/app/init.test.js index 74f7446a..aa9abd98 100644 --- a/test/commands/app/init.test.js +++ b/test/commands/app/init.test.js @@ -223,7 +223,20 @@ describe('Command Prototype', () => { expect(TheCommand.flags.workspace.default).toBe('Stage') expect(TheCommand.flags.workspace.char).toBe('w') - expect(TheCommand.flags.workspace.exclusive).toEqual(['import']) + expect(TheCommand.flags.workspace.exclusive).toEqual(['import', 'no-login']) + + expect(TheCommand.flags.org).toBeDefined() + expect(TheCommand.flags.org.hidden).toBeFalsy() + expect(TheCommand.flags.org.char).toBe('o') + expect(TheCommand.flags.org.exclusive).toEqual(['import', 'no-login']) + + expect(TheCommand.flags.project).toBeDefined() + expect(TheCommand.flags.project.hidden).toBeFalsy() + expect(TheCommand.flags.project.char).toBe('p') + expect(TheCommand.flags.project.exclusive).toEqual(['import', 'no-login']) + + expect(TheCommand.flags['template-options']).toBeDefined() + expect(TheCommand.flags['template-options'].type).toBe('option') expect(TheCommand.flags['confirm-new-workspace'].type).toBe('boolean') expect(TheCommand.flags['confirm-new-workspace'].default).toBe(true) @@ -801,3 +814,70 @@ describe('dev terms', () => { await expect(command.run()).rejects.toThrow('The Developer Terms of Service could not be accepted') }) }) + +describe('template-options', () => { + test('no flag', async () => { + command.argv = ['--template', 'some-template'] + + const installOptions = { + installNpm: true, + templates: ['some-template'], + useDefaultValues: false + } + + await command.run() + expect(command.installTemplates).toHaveBeenCalledWith(installOptions) + }) + + test('valid base64', async () => { + const templateOptions = { + text: 'base-text' + } + const base64 = Buffer.from(JSON.stringify(templateOptions)).toString('base64') + command.argv = ['--template', 'some-template', '--template-options', `${base64}`] + + const installOptions = { + installNpm: true, + templates: ['some-template'], + useDefaultValues: false, + templateOptions + } + + await command.run() + expect(command.installTemplates).toHaveBeenCalledWith(installOptions) + }) + + test('valid base64 --no-login', async () => { + const templateOptions = { + text: 'base-text' + } + const base64 = Buffer.from(JSON.stringify(templateOptions)).toString('base64') + command.argv = ['--no-login', '--template', 'some-template', '--template-options', `${base64}`] + + const installOptions = { + installConfig: false, + installNpm: true, + templates: ['some-template'], + useDefaultValues: false, + templateOptions + } + + await command.run() + expect(command.installTemplates).toHaveBeenCalledWith(installOptions) + }) + + test('invalid base64', async () => { + command.argv = ['--template', 'some-template', '--template-options=%'] // % is an invalid base64 character + + expect.assertions(1) + await expect(command.run()).rejects.toThrow('--template-options: % is not a base64 encoded JSON object.') + }) + + test('malformed json', async () => { + const options = '{' // ew== in base64 + command.argv = ['--template', 'some-template', `--template-options=${Buffer.from(options).toString('base64')}`] + + expect.assertions(1) + await expect(command.run()).rejects.toThrow('--template-options: ew== is not a base64 encoded JSON object.') + }) +})