Skip to content

Commit

Permalink
Merge branch 'main' into zapier-platform-major-release-16.0.0-dev
Browse files Browse the repository at this point in the history
  • Loading branch information
rnegron committed Nov 22, 2024
2 parents 9461d67 + 787317f commit ff4d9c0
Show file tree
Hide file tree
Showing 22 changed files with 2,587 additions and 1,403 deletions.
4 changes: 2 additions & 2 deletions packages/cli/docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -637,8 +637,8 @@ You can mix and match several options to customize the created scaffold for your
**Flags**
* `-d, --dest` | Specify the new file's directory. Use this flag when you want to create a different folder structure such as `src/triggers` instead of the default `triggers`. Defaults to `[triggers|searches|creates]/{noun}`.
* `--test-dest` | Specify the new test file's directory. Use this flag when you want to create a different folder structure such as `src/triggers` instead of the default `triggers`. Defaults to `test/[triggers|searches|creates]/{noun}`.
* `-e, --entry` | Supply the path to your integration's root (`index.js`). Only needed if your `index.js` is in a subfolder, like `src`. Defaults to `index.js`.
* `-f, --force` | Should we overwrite an exisiting trigger/search/create file?
* `-e, --entry` | Supply the path to your integration's entry point (`index.js` or `src/index.ts`). This will try to automatically detect the correct file if not provided.
* `-f, --force` | Should we overwrite an existing trigger/search/create file?
* `--no-help` | When scaffolding, should we skip adding helpful intro comments? Useful if this isn't your first rodeo.
* `-d, --debug` | Show extra debugging output.

Expand Down
5 changes: 4 additions & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
"gulp-prettier": "4.0.0",
"ignore": "5.2.4",
"inquirer": "8.2.5",
"jscodeshift": "0.15.0",
"jscodeshift": "^17.0.0",
"klaw": "4.1.0",
"lodash": "4.17.21",
"luxon": "3.5.0",
Expand All @@ -82,11 +82,14 @@
},
"devDependencies": {
"@oclif/test": "^4.0.9",
"@types/jscodeshift": "^0.12.0",
"@types/mocha": "^10.0.9",
"chai": "^4.3.7",
"decompress": "4.2.1",
"mock-fs": "^5.2.0",
"nock": "^13.3.1",
"oclif": "^4.15.1",
"typescript": "^5.6.3",
"yamljs": "0.3.0"
},
"bin": {
Expand Down
64 changes: 64 additions & 0 deletions packages/cli/scaffold/create.template.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import type { Create, PerformFunction } from 'zapier-platform-core';

// create a particular <%= LOWER_NOUN %> by name
const perform: PerformFunction = async (z, bundle) => {
const response = await z.request({
method: 'POST',
url: 'https://jsonplaceholder.typicode.com/posts',
// if `body` is an object, it'll automatically get run through JSON.stringify
// if you don't want to send JSON, pass a string in your chosen format here instead
body: {
name: bundle.inputData.name
}
});
// this should return a single object
return response.data;
};

export default {
// see here for a full list of available properties:
// https://github.com/zapier/zapier-platform/blob/main/packages/schema/docs/build/schema.md#createschema
key: '<%= KEY %>',
noun: '<%= NOUN %>',

display: {
label: 'Create <%= NOUN %>',
description: 'Creates a new <%= LOWER_NOUN %>, probably with input from previous steps.'
},

operation: {
perform,

<%= INCLUDE_INTRO_COMMENTS ? [
'// `inputFields` defines the fields a user could provide',
'// Zapier will pass them in as `bundle.inputData` later. They\'re optional.',
'// End-users will map data into these fields. In general, they should have any fields that the API can accept. Be sure to accurately mark which fields are required!'
].join('\n ') : '' %>
inputFields: [
{key: 'name', required: true},
{key: 'fave_meal', label: 'Favorite Meal', required: false}
],
<%= INCLUDE_INTRO_COMMENTS ? [
'// In cases where Zapier needs to show an example record to the user, but we are unable to get a live example',
'// from the API, Zapier will fallback to this hard-coded sample. It should reflect the data structure of',
'// returned records, and have obvious placeholder values that we can show to any user.'
].join('\n ') : '' %>
sample: {
id: 1,
name: 'Test'
},
<%= INCLUDE_INTRO_COMMENTS ? [
'// If fields are custom to each user (like spreadsheet columns), `outputFields` can create human labels',
'// For a more complete example of using dynamic fields see',
'// https://github.com/zapier/zapier-platform/tree/main/packages/cli#customdynamic-fields',
'// Alternatively, a static field definition can be provided, to specify labels for the fields'
].join('\n ') : '' %>
outputFields: [
// these are placeholders to match the example `perform` above
// {key: 'id', label: 'Person ID'},
// {key: 'name', label: 'Person Name'}
]
}
} satisfies Create;
119 changes: 119 additions & 0 deletions packages/cli/scaffold/resource.template.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import type { PerformFunction, Resource } from 'zapier-platform-core';

// get a list of <%= LOWER_NOUN %>s
const performList: PerformFunction = async (z, bundle) => {
const response = await z.request({
url: 'https://jsonplaceholder.typicode.com/posts',
params: {
order_by: 'id desc',
},
});
return response.data;
};

// find a particular <%= LOWER_NOUN %> by name (or other search criteria)
const performSearch: PerformFunction = async (z, bundle) => {
const response = await z.request({
url: 'https://jsonplaceholder.typicode.com/posts',
params: {
name: bundle.inputData.name,
},
});
return response.data;
};

// creates a new <%= LOWER_NOUN %>
const performCreate: PerformFunction = async (z, bundle) => {
const response = await z.request({
method: 'POST',
url: 'https://jsonplaceholder.typicode.com/posts',
body: {
name: bundle.inputData.name, // json by default
},
});
return response.data;
};

export default {
// see here for a full list of available properties:
// https://github.com/zapier/zapier-platform/blob/main/packages/schema/docs/build/schema.md#resourceschema
key: '<%= KEY %>',
noun: '<%= NOUN %>',

<%= INCLUDE_INTRO_COMMENTS ? [
'// If `get` is defined, it will be called after a `search` or `create`'
].join('\n ') : '' %>
// useful if your `searches` and `creates` return sparse objects
// get: {
// display: {
// label: 'Get <%= NOUN %>',
// description: 'Gets a <%= LOWER_NOUN %>.'
// },
// operation: {
// inputFields: [
// {key: 'id', required: true}
// ],
// perform: defineMe
// }
// },

list: {
display: {
label: 'New <%= NOUN %>',
description: 'Lists the <%= LOWER_NOUN %>s.',
},
operation: {
perform: performList,
<%= INCLUDE_INTRO_COMMENTS ? [
'// `inputFields` defines the fields a user could provide',
'// Zapier will pass them in as `bundle.inputData` later. They\'re optional on triggers, but required on searches and creates.'
].join('\n ') : '' %>
inputFields: [],
},
},

search: {
display: {
label: 'Find <%= NOUN %>',
description: 'Finds a <%= LOWER_NOUN %> give.',
},
operation: {
inputFields: [{ key: 'name', required: true }],
perform: performSearch,
},
},

create: {
display: {
label: 'Create <%= NOUN %>',
description: 'Creates a new <%= LOWER_NOUN %>.',
},
operation: {
inputFields: [{ key: 'name', required: true }],
perform: performCreate,
},
},

<%= INCLUDE_INTRO_COMMENTS ? [
'// In cases where Zapier needs to show an example record to the user, but we are unable to get a live example',
'// from the API, Zapier will fallback to this hard-coded sample. It should reflect the data structure of',
'// returned records, and have obvious placeholder values that we can show to any user.',
'// In this resource, the sample is reused across all methods'
].join('\n ') : '' %>
sample: {
id: 1,
name: 'Test',
},

<%= INCLUDE_INTRO_COMMENTS ? [
'// If fields are custom to each user (like spreadsheet columns), `outputFields` can create human labels',
'// For a more complete example of using dynamic fields see',
'// https://github.com/zapier/zapier-platform/tree/main/packages/cli#customdynamic-fields',
'// Alternatively, a static field definition can be provided, to specify labels for the fields',
'// In this resource, these output fields are reused across all resources'
].join('\n ') : '' %>
outputFields: [
{ key: 'id', label: 'ID' },
{ key: 'name', label: 'Name' },
],
} satisfies Resource;
63 changes: 63 additions & 0 deletions packages/cli/scaffold/search.template.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import type { PerformFunction, Search } from 'zapier-platform-core';

// find a particular <%= LOWER_NOUN %> by name
const perform: PerformFunction = async (z, bundle) => {
const response = await z.request({
url: 'https://jsonplaceholder.typicode.com/posts',
params: {
name: bundle.inputData.name,
},
});
// this should return an array of objects (but only the first will be used)
return response.data;
};

export default {
// see here for a full list of available properties:
// https://github.com/zapier/zapier-platform/blob/main/packages/schema/docs/build/schema.md#searchschema
key: '<%= KEY %>',
noun: '<%= NOUN %>',

display: {
label: 'Find <%= NOUN %>',
description: 'Finds a <%= LOWER_NOUN %> based on name.',
},

operation: {
perform,

<%= INCLUDE_INTRO_COMMENTS ? [
'// `inputFields` defines the fields a user could provide',
'// Zapier will pass them in as `bundle.inputData` later. Searches need at least one `inputField`.'
].join('\n ') : '' %>
inputFields: [
{
key: 'name',
required: true,
helpText: 'Find the <%= NOUN %> with this name.',
},
],

<%= INCLUDE_INTRO_COMMENTS ? [
'// In cases where Zapier needs to show an example record to the user, but we are unable to get a live example',
'// from the API, Zapier will fallback to this hard-coded sample. It should reflect the data structure of',
'// returned records, and have obvious placeholder values that we can show to any user.'
].join('\n ') : '' %>
sample: {
id: 1,
name: 'Test',
},
<%= INCLUDE_INTRO_COMMENTS ? [
'// If fields are custom to each user (like spreadsheet columns), `outputFields` can create human labels',
'// For a more complete example of using dynamic fields see',
'// https://github.com/zapier/zapier-platform/tree/main/packages/cli#customdynamic-fields',
'// Alternatively, a static field definition can be provided, to specify labels for the fields'
].join('\n ') : '' %>
outputFields: [
// these are placeholders to match the example `perform` above
// {key: 'id', label: 'Person ID'},
// {key: 'name', label: 'Person Name'}
],
},
} satisfies Search;
18 changes: 18 additions & 0 deletions packages/cli/scaffold/test.template.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { describe, expect, it } from 'vitest';
import zapier from 'zapier-platform-core';

import App from '../../index';

const appTester = zapier.createAppTester(App);
// read the `.env` file into the environment, if available
zapier.tools.env.inject();

describe('<%= ACTION_PLURAL %>.<%= KEY %>', () => {
it('should run', async () => {
const bundle = { inputData: {} };

const results = await appTester(App.<%= ACTION_PLURAL %>['<%= KEY %>'].<%= MAYBE_RESOURCE %>operation.perform, bundle);
expect(results).toBeDefined();
// TODO: add more assertions
});
});
58 changes: 58 additions & 0 deletions packages/cli/scaffold/trigger.template.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import type { PerformFunction, Trigger } from 'zapier-platform-core';

// triggers on a new <%= LOWER_NOUN %> with a certain tag
const perform: PerformFunction = async (z, bundle) => {
const response = await z.request({
url: 'https://jsonplaceholder.typicode.com/posts',
params: {
tag: bundle.inputData.tagName,
},
});
// this should return an array of objects
return response.data;
};

export default {
// see here for a full list of available properties:
// https://github.com/zapier/zapier-platform/blob/main/packages/schema/docs/build/schema.md#triggerschema
key: '<%= KEY %>' as const,
noun: '<%= NOUN %>',

display: {
label: 'New <%= NOUN %>',
description: 'Triggers when a new <%= LOWER_NOUN %> is created.',
},

operation: {
type: 'polling',
perform,

<%= INCLUDE_INTRO_COMMENTS ? [
'// `inputFields` defines the fields a user could provide',
'// Zapier will pass them in as `bundle.inputData` later. They\'re optional.'
].join('\n ') : '' %>
inputFields: [],

<%= INCLUDE_INTRO_COMMENTS ? [
'// In cases where Zapier needs to show an example record to the user, but we are unable to get a live example',
'// from the API, Zapier will fallback to this hard-coded sample. It should reflect the data structure of',
'// returned records, and have obvious placeholder values that we can show to any user.'
].join('\n ') : '' %>
sample: {
id: 1,
name: 'Test',
},

<%= INCLUDE_INTRO_COMMENTS ? [
'// If fields are custom to each user (like spreadsheet columns), `outputFields` can create human labels',
'// For a more complete example of using dynamic fields see',
'// https://github.com/zapier/zapier-platform/tree/main/packages/cli#customdynamic-fields',
'// Alternatively, a static field definition can be provided, to specify labels for the fields'
].join('\n ') : '' %>
outputFields: [
// these are placeholders to match the example `perform` above
// {key: 'id', label: 'Person ID'},
// {key: 'name', label: 'Person Name'}
],
},
} satisfies Trigger;
Loading

0 comments on commit ff4d9c0

Please sign in to comment.