Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PDE-3732 feat(cli): Implement individual field flags for register command #618

Merged
merged 21 commits into from
Feb 16, 2023
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
f9151f1
Add optional required option and validation to prompt in `ZapierBaseC…
gregilo Jan 24, 2023
3a4aed6
Move nock from devDependencies to dependencies in CLI package.json
gregilo Feb 6, 2023
3aad044
Add fixture for register field choices API response
gregilo Feb 6, 2023
af927cd
Mock API call for register field choices when testing
gregilo Feb 6, 2023
eebe168
Add error handling for API call for register field choices
gregilo Feb 6, 2023
5fc33aa
Implement interactive prompts and individual field flags for register…
gregilo Feb 6, 2023
3e8ad70
Update packages/cli/src/oclif/commands/register.js
gregilo Feb 8, 2023
fae6431
Update audience flag description in packages/cli/src/oclif/commands/r…
gregilo Feb 10, 2023
4fa06df
Update homepage URL flag description in packages/cli/src/oclif/comman…
gregilo Feb 10, 2023
cb985fe
Include caught error object in error message in packages/cli/src/ocli…
gregilo Feb 10, 2023
abcadd3
Set flag options for register command dynamically
gregilo Feb 10, 2023
5825c47
Move register command tests out of smoke-tests and into separate unit
gregilo Feb 13, 2023
4610f36
Enforce character limit on description field/flag
gregilo Feb 14, 2023
3b57747
Use constant for max description length for register command
gregilo Feb 14, 2023
c536cb8
Add ?formId=create to API call for zapier register command
gregilo Feb 14, 2023
08e8ca4
Simplify logic for determining if provided flag has a field mapping w…
gregilo Feb 14, 2023
286afb7
Add more examples for zapier register command
gregilo Feb 14, 2023
093aef9
Utilize object.entries in register.js
gregilo Feb 14, 2023
c9ebfe4
Add test to ensure flags work properly for zapier register command
gregilo Feb 14, 2023
8b34c45
Suppress stdout and stderr when running tests
eliangcs Feb 15, 2023
568c066
Replace fs.statSync with fs.existsSync
eliangcs Feb 15, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/cli.html
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,12 @@ <h2 id="register">register</h2>
</blockquote><p><strong>Usage</strong>: <code>zapier register [TITLE]</code></p><p>After running this, you can run <code>zapier push</code> to build and upload your integration for use in the Zapier editor.</p><p>This will change the <code>./.zapierapprc</code> (which identifies this directory as holding code for a specific integration).</p><p><strong>Arguments</strong></p><ul>
<li><code>title</code> | Your integrations&apos;s public title. Asked interactively if not present.</li>
</ul><p><strong>Flags</strong></p><ul>
<li><code>-D, --desc</code> | A sentence describing your app in 140 characters or less, e.g. &quot;Trello is a team collaboration tool to organize tasks and keep projects on track.&quot;</li>
<li><code>-u, --url</code> | The homepage URL of your app, e.g., <a href="https://example.com">https://example.com</a>.</li>
<li><code>-a, --audience</code> | Are you building a public or private integration?</li>
<li><code>-r, --role</code> | What is your relationship with the app you&apos;re integrating with Zapier?</li>
<li><code>-c, --category</code> | How would you categorize your app? Choose the most appropriate option for your app&apos;s core features.</li>
<li><code>-s, --subscribe</code> | Get tips and recommendations about this integration along with our monthly newsletter that details the performance of your integration and the latest Zapier news.</li>
<li><code>-d, --debug</code> | Show extra debugging output.</li>
</ul><p><strong>Examples</strong></p><ul>
<li><code>zapier register</code></li>
Expand Down
6 changes: 6 additions & 0 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,12 @@ This will change the `./.zapierapprc` (which identifies this directory as holdi
* `title` | Your integrations's public title. Asked interactively if not present.

**Flags**
* `-D, --desc` | A sentence describing your app in 140 characters or less, e.g. "Trello is a team collaboration tool to organize tasks and keep projects on track."
* `-u, --url` | The homepage URL of your app, e.g., https://example.com.
* `-a, --audience` | Are you building a public or private integration?
* `-r, --role` | What is your relationship with the app you're integrating with Zapier?
* `-c, --category` | How would you categorize your app? Choose the most appropriate option for your app's core features.
* `-s, --subscribe` | Get tips and recommendations about this integration along with our monthly newsletter that details the performance of your integration and the latest Zapier news.
* `-d, --debug` | Show extra debugging output.

**Examples**
Expand Down
6 changes: 6 additions & 0 deletions packages/cli/docs/cli.html
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,12 @@ <h2 id="register">register</h2>
</blockquote><p><strong>Usage</strong>: <code>zapier register [TITLE]</code></p><p>After running this, you can run <code>zapier push</code> to build and upload your integration for use in the Zapier editor.</p><p>This will change the <code>./.zapierapprc</code> (which identifies this directory as holding code for a specific integration).</p><p><strong>Arguments</strong></p><ul>
<li><code>title</code> | Your integrations&apos;s public title. Asked interactively if not present.</li>
</ul><p><strong>Flags</strong></p><ul>
<li><code>-D, --desc</code> | A sentence describing your app in 140 characters or less, e.g. &quot;Trello is a team collaboration tool to organize tasks and keep projects on track.&quot;</li>
<li><code>-u, --url</code> | The homepage URL of your app, e.g., <a href="https://example.com">https://example.com</a>.</li>
<li><code>-a, --audience</code> | Are you building a public or private integration?</li>
<li><code>-r, --role</code> | What is your relationship with the app you&apos;re integrating with Zapier?</li>
<li><code>-c, --category</code> | How would you categorize your app? Choose the most appropriate option for your app&apos;s core features.</li>
<li><code>-s, --subscribe</code> | Get tips and recommendations about this integration along with our monthly newsletter that details the performance of your integration and the latest Zapier news.</li>
<li><code>-d, --debug</code> | Show extra debugging output.</li>
</ul><p><strong>Examples</strong></p><ul>
<li><code>zapier register</code></li>
Expand Down
6 changes: 6 additions & 0 deletions packages/cli/docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,12 @@ This will change the `./.zapierapprc` (which identifies this directory as holdi
* `title` | Your integrations's public title. Asked interactively if not present.

**Flags**
* `-D, --desc` | A sentence describing your app in 140 characters or less, e.g. "Trello is a team collaboration tool to organize tasks and keep projects on track."
* `-u, --url` | The homepage URL of your app, e.g., https://example.com.
* `-a, --audience` | Are you building a public or private integration?
* `-r, --role` | What is your relationship with the app you're integrating with Zapier?
* `-c, --category` | How would you categorize your app? Choose the most appropriate option for your app's core features.
* `-s, --subscribe` | Get tips and recommendations about this integration along with our monthly newsletter that details the performance of your integration and the latest Zapier news.
* `-d, --debug` | Show extra debugging output.

**Examples**
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"lodash": "4.17.21",
"marked": "4.2.12",
"marked-terminal": "5.1.1",
"nock": "^13.3.0",
"node-fetch": "2.6.7",
"ora": "5.4.0",
"parse-gitignore": "0.5.1",
Expand All @@ -78,7 +79,6 @@
"litdoc": "1.5.6",
"markdown-toc": "^1",
"mock-fs": "^5.2.0",
"nock": "^13.3.0",
"stdout-stderr": "0.1.13",
"yamljs": "0.3.0"
},
Expand Down
4 changes: 4 additions & 0 deletions packages/cli/src/oclif/ZapierBaseCommand.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ class ZapierBaseCommand extends Command {
* @param {object} opts `inquierer.js` opts ([read more](https://github.com/SBoudrias/Inquirer.js/#question))
*/
async prompt(question, opts = {}) {
if (typeof opts.required !== 'undefined' && opts.required) {
gregilo marked this conversation as resolved.
Show resolved Hide resolved
opts.validate = (input) =>
input.trim() === '' ? 'This field is required.' : true;
}
const { ans } = await inquirer.prompt({
type: 'string',
...opts,
Expand Down
155 changes: 148 additions & 7 deletions packages/cli/src/oclif/commands/register.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ const { CURRENT_APP_FILE } = require('../../constants');
const { buildFlags } = require('../buildFlags');
const { callAPI, writeLinkedAppConfig } = require('../../utils/api');

const { flags } = require('@oclif/command');

class RegisterCommand extends ZapierBaseCommand {
async perform() {
let title = this.args.title;
if (!title) {
title = await this.prompt('What is the title of your integration?');
}
this._validateEnumFlags();
const appMeta = await this._promptForAppMeta();

this.startSpinner(`Registering your new integration "${title}"`);
const app = await callAPI('/apps', { method: 'POST', body: { title } });
this.startSpinner(`Registering your new integration "${appMeta.title}"`);
const app = await callAPI('/apps', { method: 'POST', body: appMeta });
this.stopSpinner();
this.startSpinner(
`Linking app to current directory with \`${CURRENT_APP_FILE}\``
Expand All @@ -22,6 +22,112 @@ class RegisterCommand extends ZapierBaseCommand {
'\nFinished! Now that your integration is registered with Zapier, you can `zapier push`!'
);
}

_validateEnumFlags() {
const flagFieldMappings = {
audience: 'intention',
role: 'role',
category: 'app_category',
};

for (const flag of Object.keys(this.flags)) {
gregilo marked this conversation as resolved.
Show resolved Hide resolved
// Only validate user input for enum flags (in flagFieldMappings)
if (!Object.prototype.hasOwnProperty.call(flagFieldMappings, flag)) {
gregilo marked this conversation as resolved.
Show resolved Hide resolved
continue;
}

// Check user input against this.config.enumFieldChoices (retrieved in getAppRegistrationFieldChoices hook)
const enumFieldChoices = this.config.enumFieldChoices[
flagFieldMappings[flag]
];
if (
!enumFieldChoices.find((option) => option.value === this.flags[flag])
) {
throw new Error(
`${
this.flags[flag]
} is not a valid value for ${flag}. Must be one of the following: ${enumFieldChoices
.map((option) => option.value)
.join(', ')}`
);
}
}
}

async _promptForAppMeta() {
const appMeta = {};

appMeta.title = this.args.title?.trim();
if (!appMeta.title) {
appMeta.title = await this.prompt(
'What is the title of your integration?',
{ required: true }
);
}

appMeta.description = this.flags.desc?.trim();
if (!appMeta.description) {
appMeta.description = await this.prompt(
'Please provide a sentence describing your app in 140 characters or less.',
gregilo marked this conversation as resolved.
Show resolved Hide resolved
{ required: true }
);
}

appMeta.homepage_url = this.flags.url;
if (!appMeta.homepage_url) {
appMeta.homepage_url = await this.prompt(
'What is the homepage URL of your app? (optional)'
);
}

appMeta.intention = this.flags.audience;
if (!appMeta.intention) {
appMeta.intention = await this.promptWithList(
'Are you building a public or private integration?',
this.config.enumFieldChoices.intention
);
}

appMeta.role = this.flags.role;
if (!appMeta.role) {
appMeta.role = await this.promptWithList(
"What is your relationship with the app you're integrating with Zapier?",
this._getRoleChoicesWithAppTitle(
appMeta.title,
this.config.enumFieldChoices.role
)
);
}

appMeta.app_category = this.flags.category;
if (!appMeta.app_category) {
appMeta.app_category = await this.promptWithList(
'How would you categorize your app?',
this.config.enumFieldChoices.app_category
);
}

appMeta.subscription = this.flags.subscribe;
// boolean field, so using `typeof` === `undefined`
if (typeof appMeta.subscription === 'undefined') {
appMeta.subscription = await this.promptWithList(
'Subscribe to Updates about your Integration',
[
{ name: 'Yes', value: true },
{ name: 'No', value: false },
]
);
}

return appMeta;
}

_getRoleChoicesWithAppTitle(title, choices) {
return choices.map((choice) => ({
value: choice.value,
name: choice.name.replace('[app_title]', title),
}));
}
}

RegisterCommand.skipValidInstallCheck = true;
Expand All @@ -32,7 +138,42 @@ RegisterCommand.args = [
"Your integrations's public title. Asked interactively if not present.",
},
];
RegisterCommand.flags = buildFlags();

RegisterCommand.flags = buildFlags({
commandFlags: {
desc: flags.string({
char: 'D',
description:
'A sentence describing your app in 140 characters or less, e.g. "Trello is a team collaboration tool to organize tasks and keep projects on track."',
gregilo marked this conversation as resolved.
Show resolved Hide resolved
}),
url: flags.string({
char: 'u',
description:
'The homepage URL of your app, e.g., https://example.com.',
}),
audience: flags.string({
char: 'a',
gregilo marked this conversation as resolved.
Show resolved Hide resolved
description:
'Are you building a public or private integration?',
}),
role: flags.string({
char: 'r',
description:
"What is your relationship with the app you're integrating with Zapier?",
}),
category: flags.string({
char: 'c',
description:
"How would you categorize your app? Choose the most appropriate option for your app's core features.",
}),
subscribe: flags.boolean({
char: 's',
description:
'Get tips and recommendations about this integration along with our monthly newsletter that details the performance of your integration and the latest Zapier news.',
allowNo: true,
}),
},
});
RegisterCommand.examples = [
'zapier register',
'zapier register "My Cool Integration"',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add some more examples here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eliangcs I added more here - 286afb7. Do you think these are thorough enough?

Expand Down
Loading