Skip to content
This repository has been archived by the owner on Jun 27, 2019. It is now read-only.

Server-side zapier convert #380

Merged
merged 9 commits into from
Dec 19, 2018
Merged

Server-side zapier convert #380

merged 9 commits into from
Dec 19, 2018

Conversation

eliangcs
Copy link
Member

@eliangcs eliangcs commented Dec 13, 2018

Reworks the zapier convert command so that it uses the up-to-date converter implementation on the backend. Requires https://github.com/zapier/zapier/pull/22060.

This PR is quite big and can be unstraightforward to review, but the big ideas are:

  • The server now has a cli-dump endpoint (see https://github.com/zapier/zapier/pull/22060) that dumps a legacy WB app to a JSON app definition compatible with the CLI platform.
  • zapier convert pulls the app definition from the cli-dump endpoint.
  • zapier convert splits the app definition, a big JSON blob, into separate js files.
  • Most of the conversion logic is moved out of the CLI client to the server.

@eliangcs eliangcs changed the title (WIP) Server-side zapier convert 🚧 Server-side zapier convert Dec 13, 2018
@eliangcs eliangcs changed the title 🚧 Server-side zapier convert (WIP) Server-side zapier convert Dec 13, 2018
@eliangcs eliangcs changed the title (WIP) Server-side zapier convert Server-side zapier convert Dec 18, 2018
@eliangcs eliangcs requested a review from xavdid December 18, 2018 09:20
@eliangcs
Copy link
Member Author

@FokkeZB this is something we talked about, so you might be interested in having a look, but please don't feel obligated to review. :)

Copy link
Contributor

@xavdid xavdid left a comment

Choose a reason for hiding this comment

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

Cool! Looks awesome.

I didn't read anything that was 100% removal, but I feel like I covered and understood everything else well enough. A couple of minor things, but no hard blockers if you feel like it's a non/issue has been resolved.

Thanks for grabbing this stuff!

@@ -17,24 +17,27 @@ const convert = (context, appid, location) => {
return Promise.reject(new Error(message));
}

const createApp = tempAppDir => {
const url = `${
const createApp = async tempAppDir => {
Copy link
Contributor

Choose a reason for hiding this comment

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

+1 to eventually getting all of cli to async // await!

context.line(
"Looks like this is your first push. Let's register your app on Zapier."
);
return getInput('Enter app title (Ctrl-C to cancel):\n\n ').then(title =>
register(context, title, { printWhenDone: false })
return await getInput('Enter app title (Ctrl-C to cancel):\n\n ').then(
Copy link
Contributor

Choose a reason for hiding this comment

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

minor, seems weird to return the promise chain here. Why not

const input = await getInput('Enter' // ...
await register(context, // ...
return null

Also, i'm not sure we need the return statement at all.

Copy link
Member Author

Choose a reason for hiding this comment

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

I totally missed it! Cleaned up in 4830272.

templateContext,
prettify = true
) => {
const templateBuf = await readFile(templateFile);
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe this can be const template = await readFile(templateFile, 'utf-8'), since passing encoding gives you a string instead of a buffer.

Copy link
Member Author

Choose a reason for hiding this comment

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

This readFile is a function we wrote in src/utils/files.js and doesn't accept an encoding option. It is used in other places, so I rather not change its interface for now.

const renderIndex = async appDefinition => {
let exportBlock = _.cloneDeep(appDefinition),
functionBlock = '',
importBlock = '';
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd probably do importBlock as an array and then .join('\n') at the end instead of needing to use a newline whenever you add to it.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good call! Changed in 3447bd7.

includeInBuild: ['scripting.js']
});
await createFile(content, '.zapierapprc', newAppDir);
startSpinner('Writing .zapierapprc');
Copy link
Contributor

Choose a reason for hiding this comment

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

presumably we'd want to start the spinner before beginning the async action?

Copy link
Member Author

@eliangcs eliangcs Dec 19, 2018

Choose a reason for hiding this comment

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

We're only using it to print messages and not really taking advantage of spinner here. Each output file is generated concurrently with Promise.all. To properly use spinner to show progress, we need to create a spinner instance for each promise, whereas we only have a global spinner instance in src/utils/display.js. Since conversion is very fast, spinner doesn't help that much, I wouldn't bother to create multiple spinner instances just to properly show progress.

const destFile = path.join(dir, filename);
await ensureDir(path.dirname(destFile));
await writeFile(destFile, content);
startSpinner(`Writing ${filename}`);
Copy link
Contributor

Choose a reason for hiding this comment

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

order here is weird too

Copy link
Member Author

Choose a reason for hiding this comment

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

See my previous comment.

silent = false
) => {
if (silent) {
startSpinner = endSpinner = () => null;
Copy link
Contributor

Choose a reason for hiding this comment

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

I did some googling and i don't think this has any chance of messing up the import for other files (it's just redefining a local variable).

That said, I think i'd rather build this functionality into the spinner itself rather than do this each place we may need to maybe not have the spinner actually go. Maybe in utils, instead of exporting the object itself we export a wrapper class?

// wrapper pseudocode
class SpinnerWrapperClass {
  constructor(silent=false)

  startSpinner() {
    if (this.silent) {return}
    spinner.spin()
}

// usage
const {spinner} = require('./utils/display')

const s = new Spinner(silent)
s.startSpinner()

slightly more verbose, but then we keep all functionality in the same spot. Not a blocker, just a thought.

Copy link
Member Author

Choose a reason for hiding this comment

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

Currently, the silent option is there only for this test to avoid printing stuff in the console while running tests. It's true that the spinner utils could use some improvement but it's probably not worth doing only for a test.

@eliangcs eliangcs merged commit 25e5681 into master Dec 19, 2018
@eliangcs eliangcs deleted the server-side-convert branch December 19, 2018 07:44
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants