forked from loafle/openapi-generator-original
Zapier generator (#15997)
* First version of Zapier Generator * fixed zapier codegen * added zapier templates * added zapier sample * added zapier doc * added zapier generator form data management * added samples generation * updated docs * fixed zapier api template * fixed zapier samples export * added zapier readme template * fixed zapier readme template * added petstore readme * cleaned zapier generator * updated samples * fixed zapier enum label * cleaned code * updated samples * improved zapier search actions * updated samples --------- Co-authored-by: Mauro Valota <maurovalota@fattureincloud.it> Co-authored-by: William Cheng <wing328hk@gmail.com>
This commit is contained in:
parent
f63ef71432
commit
9baf4988f3
7
bin/configs/zapier-petstore-new.yaml
Normal file
7
bin/configs/zapier-petstore-new.yaml
Normal file
@ -0,0 +1,7 @@
|
||||
generatorName: zapier
|
||||
outputDir: samples/client/petstore/zapier
|
||||
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
|
||||
templateDir: modules/openapi-generator/src/main/resources/zapier
|
||||
additionalProperties:
|
||||
npmVersion: 0.0.1
|
||||
npmName: '@openapitools/zapier'
|
@ -74,6 +74,7 @@ The following generators are available:
|
||||
* [typescript-redux-query](generators/typescript-redux-query.md)
|
||||
* [typescript-rxjs](generators/typescript-rxjs.md)
|
||||
* [xojo-client](generators/xojo-client.md)
|
||||
* [zapier](generators/zapier.md)
|
||||
|
||||
|
||||
## SERVER generators
|
||||
|
178
docs/generators/zapier.md
Normal file
178
docs/generators/zapier.md
Normal file
@ -0,0 +1,178 @@
|
||||
---
|
||||
title: Documentation for the zapier Generator
|
||||
---
|
||||
|
||||
## METADATA
|
||||
|
||||
| Property | Value | Notes |
|
||||
| -------- | ----- | ----- |
|
||||
| generator name | zapier | pass this to the generate command after -g |
|
||||
| generator stability | STABLE | |
|
||||
| generator type | CLIENT | |
|
||||
| generator default templating engine | mustache | |
|
||||
| helpTxt | Generates a zapier client. | |
|
||||
|
||||
## CONFIG OPTIONS
|
||||
These options may be applied as additional-properties (cli) or configOptions (plugins). Refer to [configuration docs](https://openapi-generator.tech/docs/configuration) for more details.
|
||||
|
||||
| Option | Description | Values | Default |
|
||||
| ------ | ----------- | ------ | ------- |
|
||||
|allowUnicodeIdentifiers|boolean, toggles whether unicode identifiers are allowed in names or not, default is false| |false|
|
||||
|disallowAdditionalPropertiesIfNotPresent|If false, the 'additionalProperties' implementation (set to true by default) is compliant with the OAS and JSON schema specifications. If true (default), keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.|<dl><dt>**false**</dt><dd>The 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications.</dd><dt>**true**</dt><dd>Keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.</dd></dl>|true|
|
||||
|ensureUniqueParams|Whether to ensure parameter names are unique in an operation (rename parameters that are not).| |true|
|
||||
|enumUnknownDefaultCase|If the server adds new enum cases, that are unknown by an old spec/client, the client will fail to parse the network response.With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the server sends an enum case that is not known by the client/spec, they can safely fallback to this case.|<dl><dt>**false**</dt><dd>No changes to the enum's are made, this is the default option.</dd><dt>**true**</dt><dd>With this option enabled, each enum will have a new case, 'unknown_default_open_api', so that when the enum case sent by the server is not known by the client/spec, can safely be decoded to this case.</dd></dl>|false|
|
||||
|legacyDiscriminatorBehavior|Set to false for generators with better support for discriminators. (Python, Java, Go, PowerShell, C# have this enabled by default).|<dl><dt>**true**</dt><dd>The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document.</dd><dt>**false**</dt><dd>The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing.</dd></dl>|true|
|
||||
|prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false|
|
||||
|sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true|
|
||||
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
|
||||
|
||||
## IMPORT MAPPING
|
||||
|
||||
| Type/Alias | Imports |
|
||||
| ---------- | ------- |
|
||||
|
||||
|
||||
## INSTANTIATION TYPES
|
||||
|
||||
| Type/Alias | Instantiated By |
|
||||
| ---------- | --------------- |
|
||||
|array|array|
|
||||
|list|array|
|
||||
|map|object|
|
||||
|set|array|
|
||||
|
||||
|
||||
## LANGUAGE PRIMITIVES
|
||||
|
||||
<ul class="column-ul">
|
||||
<li>array</li>
|
||||
<li>boolean</li>
|
||||
<li>file</li>
|
||||
<li>integer</li>
|
||||
<li>number</li>
|
||||
<li>object</li>
|
||||
<li>string</li>
|
||||
</ul>
|
||||
|
||||
## RESERVED WORDS
|
||||
|
||||
<ul class="column-ul">
|
||||
</ul>
|
||||
|
||||
## FEATURE SET
|
||||
|
||||
|
||||
### Client Modification Feature
|
||||
| Name | Supported | Defined By |
|
||||
| ---- | --------- | ---------- |
|
||||
|BasePath|✗|ToolingExtension
|
||||
|Authorizations|✗|ToolingExtension
|
||||
|UserAgent|✗|ToolingExtension
|
||||
|MockServer|✗|ToolingExtension
|
||||
|
||||
### Data Type Feature
|
||||
| Name | Supported | Defined By |
|
||||
| ---- | --------- | ---------- |
|
||||
|Custom|✗|OAS2,OAS3
|
||||
|Int32|✓|OAS2,OAS3
|
||||
|Int64|✓|OAS2,OAS3
|
||||
|Float|✓|OAS2,OAS3
|
||||
|Double|✓|OAS2,OAS3
|
||||
|Decimal|✓|ToolingExtension
|
||||
|String|✓|OAS2,OAS3
|
||||
|Byte|✓|OAS2,OAS3
|
||||
|Binary|✓|OAS2,OAS3
|
||||
|Boolean|✓|OAS2,OAS3
|
||||
|Date|✓|OAS2,OAS3
|
||||
|DateTime|✓|OAS2,OAS3
|
||||
|Password|✓|OAS2,OAS3
|
||||
|File|✓|OAS2
|
||||
|Uuid|✗|
|
||||
|Array|✓|OAS2,OAS3
|
||||
|Null|✗|OAS3
|
||||
|AnyType|✗|OAS2,OAS3
|
||||
|Object|✓|OAS2,OAS3
|
||||
|Maps|✓|ToolingExtension
|
||||
|CollectionFormat|✓|OAS2
|
||||
|CollectionFormatMulti|✓|OAS2
|
||||
|Enum|✓|OAS2,OAS3
|
||||
|ArrayOfEnum|✓|ToolingExtension
|
||||
|ArrayOfModel|✓|ToolingExtension
|
||||
|ArrayOfCollectionOfPrimitives|✓|ToolingExtension
|
||||
|ArrayOfCollectionOfModel|✓|ToolingExtension
|
||||
|ArrayOfCollectionOfEnum|✓|ToolingExtension
|
||||
|MapOfEnum|✓|ToolingExtension
|
||||
|MapOfModel|✓|ToolingExtension
|
||||
|MapOfCollectionOfPrimitives|✓|ToolingExtension
|
||||
|MapOfCollectionOfModel|✓|ToolingExtension
|
||||
|MapOfCollectionOfEnum|✓|ToolingExtension
|
||||
|
||||
### Documentation Feature
|
||||
| Name | Supported | Defined By |
|
||||
| ---- | --------- | ---------- |
|
||||
|Readme|✗|ToolingExtension
|
||||
|Model|✓|ToolingExtension
|
||||
|Api|✓|ToolingExtension
|
||||
|
||||
### Global Feature
|
||||
| Name | Supported | Defined By |
|
||||
| ---- | --------- | ---------- |
|
||||
|Host|✓|OAS2,OAS3
|
||||
|BasePath|✓|OAS2,OAS3
|
||||
|Info|✓|OAS2,OAS3
|
||||
|Schemes|✗|OAS2,OAS3
|
||||
|PartialSchemes|✓|OAS2,OAS3
|
||||
|Consumes|✓|OAS2
|
||||
|Produces|✓|OAS2
|
||||
|ExternalDocumentation|✓|OAS2,OAS3
|
||||
|Examples|✓|OAS2,OAS3
|
||||
|XMLStructureDefinitions|✗|OAS2,OAS3
|
||||
|MultiServer|✗|OAS3
|
||||
|ParameterizedServer|✗|OAS3
|
||||
|ParameterStyling|✗|OAS3
|
||||
|Callbacks|✓|OAS3
|
||||
|LinkObjects|✗|OAS3
|
||||
|
||||
### Parameter Feature
|
||||
| Name | Supported | Defined By |
|
||||
| ---- | --------- | ---------- |
|
||||
|Path|✓|OAS2,OAS3
|
||||
|Query|✓|OAS2,OAS3
|
||||
|Header|✓|OAS2,OAS3
|
||||
|Body|✓|OAS2
|
||||
|FormUnencoded|✓|OAS2
|
||||
|FormMultipart|✓|OAS2
|
||||
|Cookie|✓|OAS3
|
||||
|
||||
### Schema Support Feature
|
||||
| Name | Supported | Defined By |
|
||||
| ---- | --------- | ---------- |
|
||||
|Simple|✓|OAS2,OAS3
|
||||
|Composite|✓|OAS2,OAS3
|
||||
|Polymorphism|✓|OAS2,OAS3
|
||||
|Union|✗|OAS3
|
||||
|allOf|✗|OAS2,OAS3
|
||||
|anyOf|✗|OAS3
|
||||
|oneOf|✗|OAS3
|
||||
|not|✗|OAS3
|
||||
|
||||
### Security Feature
|
||||
| Name | Supported | Defined By |
|
||||
| ---- | --------- | ---------- |
|
||||
|BasicAuth|✓|OAS2,OAS3
|
||||
|ApiKey|✓|OAS2,OAS3
|
||||
|OpenIDConnect|✗|OAS3
|
||||
|BearerToken|✓|OAS3
|
||||
|OAuth2_Implicit|✓|OAS2,OAS3
|
||||
|OAuth2_Password|✓|OAS2,OAS3
|
||||
|OAuth2_ClientCredentials|✓|OAS2,OAS3
|
||||
|OAuth2_AuthorizationCode|✓|OAS2,OAS3
|
||||
|SignatureAuth|✗|OAS3
|
||||
|
||||
### Wire Format Feature
|
||||
| Name | Supported | Defined By |
|
||||
| ---- | --------- | ---------- |
|
||||
|JSON|✓|OAS2,OAS3
|
||||
|XML|✓|OAS2,OAS3
|
||||
|PROTOBUF|✗|ToolingExtension
|
||||
|Custom|✗|OAS2,OAS3
|
@ -0,0 +1,199 @@
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import io.swagger.v3.core.util.Json;
|
||||
import io.swagger.v3.oas.models.media.ArraySchema;
|
||||
import io.swagger.v3.oas.models.media.Schema;
|
||||
import io.swagger.v3.oas.models.responses.ApiResponse;
|
||||
import org.openapitools.codegen.*;
|
||||
import org.openapitools.codegen.utils.ModelUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
import static org.openapitools.codegen.utils.CamelizeOption.LOWERCASE_FIRST_LETTER;
|
||||
import static org.openapitools.codegen.utils.StringUtils.camelize;
|
||||
import static org.openapitools.codegen.utils.StringUtils.escape;
|
||||
|
||||
public class ZapierClientCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
public static final String PROJECT_NAME = "projectName";
|
||||
|
||||
private final Logger LOGGER = LoggerFactory.getLogger(ZapierClientCodegen.class);
|
||||
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.CLIENT;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "zapier";
|
||||
}
|
||||
|
||||
public String getHelp() {
|
||||
return "Generates a zapier client.";
|
||||
}
|
||||
|
||||
public ZapierClientCodegen() {
|
||||
super();
|
||||
|
||||
outputFolder = "generated-code" + File.separator + "zapier";
|
||||
modelTemplateFiles.put("model.mustache", ".js");
|
||||
apiTemplateFiles.put("api.mustache", ".js");
|
||||
embeddedTemplateDir = templateDir = "zapier";
|
||||
apiPackage = "apis";
|
||||
testPackage = "samples";
|
||||
modelPackage = "models";
|
||||
apiTestTemplateFiles.put("sample.mustache", ".js");
|
||||
supportingFiles.add(new SupportingFile("actions.mustache", "operations", "actions.js"));
|
||||
supportingFiles.add(new SupportingFile("utils.mustache", "utils", "utils.js"));
|
||||
supportingFiles.add(new SupportingFile("index.mustache", "", "index.js"));
|
||||
supportingFiles.add(new SupportingFile("authentication.mustache", "", "authentication.js"));
|
||||
supportingFiles.add(new SupportingFile("package.mustache", "", "package.json"));
|
||||
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
|
||||
|
||||
languageSpecificPrimitives.clear();
|
||||
languageSpecificPrimitives = new HashSet<>(
|
||||
Arrays.asList("number", "integer", "string", "boolean", "array", "file", "object")
|
||||
);
|
||||
|
||||
instantiationTypes.put("array", "array");
|
||||
instantiationTypes.put("set", "array");
|
||||
instantiationTypes.put("list", "array");
|
||||
instantiationTypes.put("map", "object");
|
||||
typeMapping = new HashMap<>();
|
||||
typeMapping.put("array", "array");
|
||||
typeMapping.put("set", "array");
|
||||
typeMapping.put("map", "object");
|
||||
typeMapping.put("List", "array");
|
||||
typeMapping.put("boolean", "boolean");
|
||||
typeMapping.put("string", "string");
|
||||
typeMapping.put("int", "integer");
|
||||
typeMapping.put("float", "number");
|
||||
typeMapping.put("number", "number");
|
||||
typeMapping.put("decimal", "number");
|
||||
typeMapping.put("DateTime", "string");
|
||||
typeMapping.put("date", "string");
|
||||
typeMapping.put("long", "number");
|
||||
typeMapping.put("short", "number");
|
||||
typeMapping.put("char", "string");
|
||||
typeMapping.put("double", "number");
|
||||
typeMapping.put("object", "object");
|
||||
typeMapping.put("integer", "integer");
|
||||
typeMapping.put("binary", "file");
|
||||
typeMapping.put("file", "file");
|
||||
typeMapping.put("UUID", "string");
|
||||
typeMapping.put("URI", "string");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initializeSpecialCharacterMapping() {
|
||||
super.initializeSpecialCharacterMapping();
|
||||
specialCharReplacements.remove("_");
|
||||
}
|
||||
|
||||
/**
|
||||
* Works identically to {@link DefaultCodegen#toParamName(String)} but doesn't camelize.
|
||||
*
|
||||
* @param name Codegen property object
|
||||
* @return the sanitized parameter name
|
||||
*/
|
||||
@Override
|
||||
public String toParamName(String name) {
|
||||
if (reservedWords.contains(name)) {
|
||||
return escapeReservedWord(name);
|
||||
} else if (((CharSequence) name).chars().anyMatch(character -> specialCharReplacements.keySet().contains(String.valueOf((char) character)))) {
|
||||
return escape(name, specialCharReplacements, null, null);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelName(final String name) {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelImport(String name) {
|
||||
return "const " + name + " = " + "require('../" + modelPackage() + "/" + name + "');";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSchemaType(Schema p) {
|
||||
String openAPIType = super.getSchemaType(p);
|
||||
String type = null;
|
||||
if (typeMapping.containsKey(openAPIType)) {
|
||||
type = typeMapping.get(openAPIType);
|
||||
if (!needToImport(type)) {
|
||||
return type;
|
||||
}
|
||||
} else {
|
||||
type = openAPIType;
|
||||
}
|
||||
if (null == type) {
|
||||
LOGGER.error("No Type defined for Schema {}", p);
|
||||
}
|
||||
return toModelName(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelFilename(String name) {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toApiTestFilename(String name) {
|
||||
return toApiName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeneratorLanguage generatorLanguage() { return null; }
|
||||
|
||||
@Override
|
||||
public String escapeUnsafeCharacters(String input) {
|
||||
return input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeQuotationMark(String input) {
|
||||
return input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CodegenResponse fromResponse(String responseCode, ApiResponse response) {
|
||||
CodegenResponse r = super.fromResponse(responseCode, response);
|
||||
try {
|
||||
Map<String, Map<String, Map<String, Object>>> map = Json.mapper().readerFor(Map.class).readValue(Json.pretty(response.getContent()));
|
||||
Map.Entry<String, Map<String, Map<String, Object>>> entry = map.entrySet().stream().findFirst().get();
|
||||
Map<String, Map<String, Object>> example = entry.getValue();
|
||||
r.examples = toExamples(example.get("examples"));
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(e.toString());
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Map<String, Object>> toExamples(Map<String, Object> examples) {
|
||||
if (examples == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final List<Map<String, Object>> output = new ArrayList<>(examples.size());
|
||||
for (Map.Entry<String, Object> entry : examples.entrySet()) {
|
||||
final Map<String, Object> kv = new HashMap<>();
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> map = (Map<String, Object>) entry.getValue();
|
||||
String example = "";
|
||||
try{
|
||||
example = Json.mapper().writeValueAsString(map.getOrDefault("value", map));
|
||||
} catch(Exception ignored) {}
|
||||
|
||||
kv.put("example", example);
|
||||
output.add(kv);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
@ -140,3 +140,4 @@ org.openapitools.codegen.languages.TypeScriptReduxQueryClientCodegen
|
||||
org.openapitools.codegen.languages.TypeScriptRxjsClientCodegen
|
||||
org.openapitools.codegen.languages.WsdlSchemaCodegen
|
||||
org.openapitools.codegen.languages.XojoClientCodegen
|
||||
org.openapitools.codegen.languages.ZapierClientCodegen
|
||||
|
51
modules/openapi-generator/src/main/resources/zapier/README.mustache
vendored
Normal file
51
modules/openapi-generator/src/main/resources/zapier/README.mustache
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
# Documentation for zapier generator
|
||||
|
||||
This generator generates a partial implementation of a zapier integration from an openapi specification.
|
||||
|
||||
## Why is it partial?
|
||||
|
||||
It's a partial integration because you have to put in some code for it to be 100% complete, code that depends only on how your api is structured.
|
||||
|
||||
Here there are all the parts you need to complete by yourself:
|
||||
|
||||
### 1) **utils/utils.js** isSearchAction method
|
||||
This method has to return either true or false if a method is a [zapier search action](https://platform.zapier.com/docs/search-create).
|
||||
```
|
||||
const isSearchAction = (key) => {
|
||||
// TODO: custom logic
|
||||
return false
|
||||
}
|
||||
```
|
||||
|
||||
### 2) **utils/utils.js** searchMiddleware method
|
||||
This method has to return an array of resources (searches must return an array), if you have pagination or you api returns an array inside nested fields, here you have to extract the array.
|
||||
|
||||
```
|
||||
const searchMiddleware = (action) => {
|
||||
// TODO: custom logic
|
||||
return action
|
||||
}
|
||||
```
|
||||
|
||||
### 3) **authentication.js**
|
||||
This file must be written completely according to your api authentication, you can get it generated automatically by creating the integration on the zapier website and filling the requested data, or you can build it yourself following [this guide](https://platform.zapier.com/cli_tutorials/getting-started#adding-authentication).
|
||||
|
||||
## Samples
|
||||
To get your app made public on zapier you must provide a sample (json example response) for each of your actions, these samples get automatically generated by this generator but you have to have actual response examples in you openapi file.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
CreateUserResponse:
|
||||
description: Example response
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: ./models/responses/CreateUserResponse.yaml
|
||||
examples:
|
||||
example-1:
|
||||
value:
|
||||
data:
|
||||
id: 12345
|
||||
name: user1
|
||||
```
|
23
modules/openapi-generator/src/main/resources/zapier/actions.mustache
vendored
Normal file
23
modules/openapi-generator/src/main/resources/zapier/actions.mustache
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
{{#apiInfo}}
|
||||
{{#apis}}
|
||||
const {{classname}} = require('../{{apiPackage}}/{{classname}}');
|
||||
{{/apis}}
|
||||
{{/apiInfo}}
|
||||
const { searchMiddleware, hasSearchRequisites, isSearchAction } = require('../utils/utils');
|
||||
|
||||
const actions = {
|
||||
{{#apiInfo}}
|
||||
{{#apis}}
|
||||
{{#operations}}
|
||||
{{#operation}}
|
||||
[{{classname}}.{{operationId}}.key]: {{classname}}.{{operationId}},
|
||||
{{/operation}}
|
||||
{{/operations}}
|
||||
{{/apis}}
|
||||
{{/apiInfo}}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
searchActions: () => Object.entries(actions).reduce((actions, [key, value]) => isSearchAction(key) && hasSearchRequisites(value) ? {...actions, [key]: searchMiddleware(value)} : actions, {}),
|
||||
createActions: () => Object.entries(actions).reduce((actions, [key, value]) => !isSearchAction(key) ? {...actions, [key]: value} : actions, {}),
|
||||
}
|
106
modules/openapi-generator/src/main/resources/zapier/api.mustache
vendored
Normal file
106
modules/openapi-generator/src/main/resources/zapier/api.mustache
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
const samples = require('../samples/{{classFilename}}');
|
||||
{{#imports}}{{{import}}}
|
||||
{{/imports}}
|
||||
const utils = require('../utils/utils');
|
||||
{{#operations}}
|
||||
{{#operation}}
|
||||
{{#isMultipart}}
|
||||
const FormData = require('form-data');
|
||||
{{/isMultipart}}
|
||||
{{/operation}}
|
||||
{{/operations}}
|
||||
{{#operations}}
|
||||
|
||||
module.exports = {
|
||||
{{#operation}}
|
||||
{{operationId}}: {
|
||||
key: '{{operationId}}',
|
||||
noun: '{{baseName}}',
|
||||
display: {
|
||||
label: '{{operationId}}',
|
||||
description: '{{#notes}}{{.}}{{/notes}}',
|
||||
hidden: false,
|
||||
},
|
||||
operation: {
|
||||
inputFields: [
|
||||
{{#allParams}}
|
||||
{{#isPrimitiveType}}
|
||||
{
|
||||
key: '{{baseName}}',
|
||||
label: '{{description}}',
|
||||
type: '{{#isInteger}}integer{{/isInteger}}{{^isInteger}}{{#isNumeric}}number{{/isNumeric}}{{/isInteger}}{{#isString}}string{{/isString}}{{#isBoolean}}boolean{{/isBoolean}}{{#isDateTime}}datetime{{/isDateTime}}{{#isDate}}datetime{{/isDate}}{{#isFile}}file{{/isFile}}',
|
||||
{{#required}}
|
||||
required: true,
|
||||
{{/required}}
|
||||
{{#isEnum}}
|
||||
choices: [
|
||||
{{#_enum}}
|
||||
'{{.}}',
|
||||
{{/_enum}}
|
||||
],
|
||||
{{/isEnum}}
|
||||
},
|
||||
{{/isPrimitiveType}}
|
||||
{{^isPrimitiveType}}
|
||||
...{{baseType}}.fields(),
|
||||
{{/isPrimitiveType}}
|
||||
{{/allParams}}
|
||||
],
|
||||
outputFields: [
|
||||
{{#returnType}}
|
||||
{{^returnTypeIsPrimitive}}
|
||||
...{{returnType}}.fields('', false),
|
||||
{{/returnTypeIsPrimitive}}
|
||||
{{/returnType}}
|
||||
],
|
||||
perform: async (z, bundle) => {
|
||||
{{#isMultipart}}
|
||||
const formData = new FormData()
|
||||
{{#allParams}}
|
||||
{{#isFormParam}}
|
||||
{{^isFile}}
|
||||
formData.append('{{baseName}}', bundle.inputData?.['{{baseName}}'])
|
||||
{{/isFile}}
|
||||
{{#isFile}}
|
||||
const filename = bundle.inputData?.['filename'] || bundle.inputData?.['{{baseName}}'].split('/').slice(-1)[0]
|
||||
formData.append('{{baseName}}', (await (await z.request({url: bundle.inputData?.['{{baseName}}'], method: 'GET', raw: true})).buffer()), { filename: filename })
|
||||
{{/isFile}}
|
||||
{{/isFormParam}}
|
||||
{{/allParams}}
|
||||
{{/isMultipart}}
|
||||
const options = {
|
||||
url: utils.replacePathParameters('{{basePath}}{{path}}'),
|
||||
method: '{{httpMethod}}',
|
||||
removeMissingValuesFrom: { params: true, body: true },
|
||||
headers: {
|
||||
'Authorization': 'Bearer {{=<% %>=}}{{bundle.authData.access_token}}<%={{ }}=%>',
|
||||
{{^isMultipart}}'Content-Type': '{{#consumes}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/consumes}}',{{/isMultipart}}
|
||||
'Accept': '{{#produces}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/produces}}',
|
||||
},
|
||||
params: {
|
||||
{{#allParams}}
|
||||
{{#isQueryParam}}
|
||||
'{{baseName}}': bundle.inputData?.['{{baseName}}'],
|
||||
{{/isQueryParam}}
|
||||
{{/allParams}}
|
||||
},
|
||||
body: {{#isMultipart}}formData,{{/isMultipart}}{{^isMultipart}}{
|
||||
{{#allParams}}
|
||||
{{#isBodyParam}}
|
||||
{{#isPrimitiveType}}'{{baseName}}': bundle.inputData?.['{{baseName}}']{{/isPrimitiveType}}{{^isPrimitiveType}}...{{baseName}}.mapping(bundle){{/isPrimitiveType}},
|
||||
{{/isBodyParam}}
|
||||
{{/allParams}}
|
||||
},{{/isMultipart}}
|
||||
}
|
||||
return z.request(options).then((response) => {
|
||||
response.throwForStatus();
|
||||
const results = response.json;
|
||||
return {{#returnType}}{{#returnTypeIsPrimitive}}{ data: results }{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}results{{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}results{{/returnType}};
|
||||
})
|
||||
},
|
||||
sample: {{#returnType}}{{^returnTypeIsPrimitive}}{{#responses}}{{#is2xx}}{{#baseType}}samples['{{baseType}}Sample']{{/baseType}}{{/is2xx}}{{/responses}}{{/returnTypeIsPrimitive}}{{#returnTypeIsPrimitive}}{ data: {} }{{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}{ data: {} }{{/returnType}}
|
||||
}
|
||||
},
|
||||
{{/operation}}
|
||||
}
|
||||
{{/operations}}
|
4
modules/openapi-generator/src/main/resources/zapier/authentication.mustache
vendored
Normal file
4
modules/openapi-generator/src/main/resources/zapier/authentication.mustache
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
// TODO: autentication logic
|
||||
// https://platform.zapier.com/cli_tutorials/getting-started#adding-authentication
|
||||
};
|
10
modules/openapi-generator/src/main/resources/zapier/index.mustache
vendored
Normal file
10
modules/openapi-generator/src/main/resources/zapier/index.mustache
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
const authentication = require('./authentication');
|
||||
const { searchActions, createActions } = require('./operations/actions');
|
||||
|
||||
module.exports = {
|
||||
version: require('./package.json').version,
|
||||
platformVersion: require('zapier-platform-core').version,
|
||||
authentication: authentication,
|
||||
searches: searchActions(),
|
||||
creates: createActions(),
|
||||
};
|
93
modules/openapi-generator/src/main/resources/zapier/model.mustache
vendored
Normal file
93
modules/openapi-generator/src/main/resources/zapier/model.mustache
vendored
Normal file
@ -0,0 +1,93 @@
|
||||
const utils = require('../utils/utils');
|
||||
{{#imports}}{{{import}}}
|
||||
{{/imports}}
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
|
||||
{{#isEnum}}
|
||||
module.exports = {
|
||||
fields: (key) => (
|
||||
{
|
||||
label: `{{#description}}{{{.}}} - {{/description}}[${key.replaceAll('__', '.')}]`,
|
||||
choices: [
|
||||
{{#allowableValues}}
|
||||
{{#values}}
|
||||
'{{.}}',
|
||||
{{/values}}
|
||||
{{/allowableValues}}
|
||||
],
|
||||
}
|
||||
)
|
||||
}
|
||||
{{/isEnum}}
|
||||
{{^isEnum}}
|
||||
module.exports = {
|
||||
fields: (prefix = '', isInput = true, isArrayChild = false) => {
|
||||
const {keyPrefix, labelPrefix} = utils.buildKeyAndLabel(prefix, isInput, isArrayChild)
|
||||
return [
|
||||
{{#vars}}
|
||||
{{#isPrimitiveType}}
|
||||
{
|
||||
key: `${keyPrefix}{{baseName}}`,
|
||||
label: `{{#description}}{{{.}}} - {{/description}}[${labelPrefix}{{baseName}}]`,
|
||||
{{#isArray}}
|
||||
list: true,
|
||||
type: '{{#items}}{{baseType}}{{/items}}',
|
||||
{{/isArray}}
|
||||
{{^isArray}}
|
||||
{{#isFreeFormObject}}
|
||||
dict: true,
|
||||
{{/isFreeFormObject}}
|
||||
{{^isFreeFormObject}}
|
||||
type: '{{baseType}}',
|
||||
{{/isFreeFormObject}}
|
||||
{{/isArray}}
|
||||
{{#isEnum}}
|
||||
choices: [
|
||||
{{#_enum}}
|
||||
'{{.}}',
|
||||
{{/_enum}}
|
||||
],
|
||||
{{/isEnum}}
|
||||
},
|
||||
{{/isPrimitiveType}}
|
||||
{{^isPrimitiveType}}
|
||||
{{#isArray}}
|
||||
{
|
||||
key: `${keyPrefix}{{baseName}}`,{{#items}}{{^isEnumRef}}
|
||||
label: `{{#description}}{{{.}}} - {{/description}}[${labelPrefix}{{baseName}}]`,
|
||||
children: {{complexType}}.fields(`${keyPrefix}{{baseName}}${!isInput ? '[]' : ''}`, isInput, true), {{/isEnumRef}}{{#isEnumRef}}
|
||||
list: true,
|
||||
type: 'string',
|
||||
...{{complexType}}.fields(`${keyPrefix}{{baseName}}`, isInput),{{/isEnumRef}}{{/items}}
|
||||
},
|
||||
{{/isArray}}
|
||||
{{^isArray}}
|
||||
{{^allowableValues}}
|
||||
{{^isFreeFormObject}}
|
||||
...{{complexType}}.fields(`${keyPrefix}{{baseName}}`, isInput),
|
||||
{{/isFreeFormObject}}
|
||||
{{/allowableValues}}
|
||||
{{#allowableValues}}
|
||||
{
|
||||
key: `${keyPrefix}{{baseName}}`,
|
||||
...{{complexType}}.fields(`${keyPrefix}{{baseName}}`, isInput),
|
||||
},
|
||||
{{/allowableValues}}
|
||||
{{/isArray}}
|
||||
{{/isPrimitiveType}}
|
||||
{{/vars}}
|
||||
]
|
||||
},
|
||||
mapping: (bundle, prefix = '') => {
|
||||
const {keyPrefix} = utils.buildKeyAndLabel(prefix)
|
||||
return {
|
||||
{{#vars}}
|
||||
'{{baseName}}': {{#isPrimitiveType}}bundle.inputData?.[`${keyPrefix}{{baseName}}`]{{/isPrimitiveType}}{{^isPrimitiveType}}{{^allowableValues}}{{^isArray}}utils.removeIfEmpty({{complexType}}.mapping(bundle, `${keyPrefix}{{baseName}}`)){{/isArray}}{{#isArray}}utils.removeKeyPrefixes(bundle.inputData?.[`${keyPrefix}{{baseName}}`]){{/isArray}}{{/allowableValues}}{{#allowableValues}}bundle.inputData?.[`${keyPrefix}{{baseName}}`]{{/allowableValues}}{{/isPrimitiveType}},
|
||||
{{/vars}}
|
||||
}
|
||||
},
|
||||
}
|
||||
{{/isEnum}}
|
||||
{{/model}}
|
||||
{{/models}}
|
27
modules/openapi-generator/src/main/resources/zapier/package.mustache
vendored
Normal file
27
modules/openapi-generator/src/main/resources/zapier/package.mustache
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "{{npmName}}",
|
||||
"version": "{{npmVersion}}",
|
||||
"description": "OpenAPI client for {{npmName}}",
|
||||
"author": "OpenAPI-Generator",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "mocha --recursive -t 10000"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=v16",
|
||||
"npm": ">=5.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.21",
|
||||
"zapier-platform-core": "14.1.1",
|
||||
"form-data": "2.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "^10.2.0",
|
||||
"should": "^13.2.0"
|
||||
},
|
||||
"private": true,
|
||||
"zapier": {
|
||||
"convertedByCLIVersion": "14.1.1"
|
||||
}
|
||||
}
|
18
modules/openapi-generator/src/main/resources/zapier/sample.mustache
vendored
Normal file
18
modules/openapi-generator/src/main/resources/zapier/sample.mustache
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
{{#operations}}
|
||||
module.exports = {
|
||||
{{#operation}}
|
||||
{{#returnType}}
|
||||
{{^returnTypeIsPrimitive}}
|
||||
{{#responses}}
|
||||
{{#is2xx}}
|
||||
{{#baseType}}
|
||||
"{{baseType}}Sample":
|
||||
{{#examples}}{{#-last}}{{{example}}}{{/-last}}{{/examples}}{{^examples}}{ data: {} }{{/examples}},
|
||||
{{/baseType}}
|
||||
{{/is2xx}}
|
||||
{{/responses}}
|
||||
{{/returnTypeIsPrimitive}}
|
||||
{{/returnType}}
|
||||
{{/operation}}
|
||||
}
|
||||
{{/operations}}
|
34
modules/openapi-generator/src/main/resources/zapier/utils.mustache
vendored
Normal file
34
modules/openapi-generator/src/main/resources/zapier/utils.mustache
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
const _ = require('lodash')
|
||||
|
||||
const replacePathParameters = (url) => url.replace(/{([^{}]+)}/g, (keyExpr, key) => `{{bundle.inputData.${key}}}`)
|
||||
const removeKeyPrefixes = (objectsArray) => objectsArray == undefined || typeof objectsArray[0] != 'object' ? objectsArray : objectsArray.map((obj) => Object.keys(obj).reduce((res, key) => (res[(key.split('.')).slice(-1)] = obj[key], res), {}))
|
||||
const removeIfEmpty = (obj) => _.isEmpty(JSON.parse(JSON.stringify(obj))) ? undefined : obj
|
||||
const buildKeyAndLabel = (prefix, isInput = true, isArrayChild = false) => {
|
||||
const keyPrefix = !_.isEmpty(prefix) && (!isArrayChild || isInput) ? `${prefix}${isInput ? '.' : '__'}` : prefix
|
||||
const labelPrefix = !_.isEmpty(keyPrefix) ? keyPrefix.replaceAll('__', '.') : ''
|
||||
return {
|
||||
keyPrefix: keyPrefix,
|
||||
labelPrefix:labelPrefix,
|
||||
}
|
||||
}
|
||||
const isSearchAction = (key) => {
|
||||
// TODO: custom logic
|
||||
return false
|
||||
}
|
||||
const hasASearchField = action => action.operation.inputFields.length > 0
|
||||
const returnsObjectsArray = action => !!action.operation.outputFields.find(field => 'children' in field)
|
||||
const hasSearchRequisites = action => hasASearchField(action) && returnsObjectsArray(action)
|
||||
const searchMiddleware = (action) => {
|
||||
// TODO: custom logic
|
||||
return action
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
replacePathParameters: replacePathParameters,
|
||||
removeKeyPrefixes: removeKeyPrefixes,
|
||||
removeIfEmpty: removeIfEmpty,
|
||||
buildKeyAndLabel: buildKeyAndLabel,
|
||||
hasSearchRequisites: hasSearchRequisites,
|
||||
isSearchAction: isSearchAction,
|
||||
searchMiddleware: searchMiddleware,
|
||||
}
|
@ -2023,15 +2023,19 @@ namespace Org.OpenAPITools.Api
|
||||
/// <summary>
|
||||
/// Validates the request parameters
|
||||
/// </summary>
|
||||
/// <param name="enumHeaderString"></param>
|
||||
/// <param name="enumHeaderStringArray"></param>
|
||||
/// <param name="enumQueryStringArray"></param>
|
||||
/// <param name="enumFormStringArray"></param>
|
||||
/// <param name="enumHeaderString"></param>
|
||||
/// <param name="enumQueryString"></param> /// <param name="enumFormString"></param>
|
||||
/// <param name="enumQueryString"></param>
|
||||
/// <param name="enumFormString"></param>
|
||||
/// <returns></returns>
|
||||
private void ValidateTestEnumParameters(Option<List<string>> enumHeaderStringArray, Option<List<string>> enumQueryStringArray, Option<List<string>> enumFormStringArray, Option<string> enumHeaderString, Option<string> enumQueryString, Option<string> enumFormString)
|
||||
{
|
||||
if (enumHeaderString.IsSet && enumHeaderString.Value == null)
|
||||
throw new ArgumentNullException(nameof(enumHeaderString));
|
||||
|
||||
if (enumHeaderStringArray.IsSet && enumHeaderStringArray.Value == null)
|
||||
throw new ArgumentNullException(nameof(enumHeaderStringArray));
|
||||
|
||||
@ -2049,6 +2053,9 @@ namespace Org.OpenAPITools.Api
|
||||
|
||||
if (enumFormString.IsSet && enumFormString.Value == null)
|
||||
throw new ArgumentNullException(nameof(enumFormString));
|
||||
|
||||
if (enumQueryString.IsSet && enumQueryString.Value == null)
|
||||
throw new ArgumentNullException(nameof(enumQueryString));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -2042,11 +2042,15 @@ namespace Org.OpenAPITools.Api
|
||||
if (enumHeaderString.IsSet && enumHeaderString.Value == null)
|
||||
throw new ArgumentNullException(nameof(enumHeaderString));
|
||||
|
||||
|
||||
if (enumQueryString.IsSet && enumQueryString.Value == null)
|
||||
throw new ArgumentNullException(nameof(enumQueryString));
|
||||
|
||||
if (enumFormString.IsSet && enumFormString.Value == null)
|
||||
throw new ArgumentNullException(nameof(enumFormString));
|
||||
|
||||
if (enumQueryString.IsSet && enumQueryString.Value == null)
|
||||
throw new ArgumentNullException(nameof(enumQueryString));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
23
samples/client/petstore/zapier/.openapi-generator-ignore
Normal file
23
samples/client/petstore/zapier/.openapi-generator-ignore
Normal file
@ -0,0 +1,23 @@
|
||||
# OpenAPI Generator Ignore
|
||||
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
|
||||
|
||||
# Use this file to prevent files from being overwritten by the generator.
|
||||
# The patterns follow closely to .gitignore or .dockerignore.
|
||||
|
||||
# As an example, the C# client generator defines ApiClient.cs.
|
||||
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
|
||||
#ApiClient.cs
|
||||
|
||||
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
|
||||
#foo/*/qux
|
||||
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
|
||||
|
||||
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
|
||||
#foo/**/qux
|
||||
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
|
||||
|
||||
# You can also negate patterns with an exclamation (!).
|
||||
# For example, you can ignore all files in a docs folder with the file extension .md:
|
||||
#docs/*.md
|
||||
# Then explicitly reverse the ignore rule for a single file:
|
||||
#!docs/README.md
|
15
samples/client/petstore/zapier/.openapi-generator/FILES
Normal file
15
samples/client/petstore/zapier/.openapi-generator/FILES
Normal file
@ -0,0 +1,15 @@
|
||||
README.md
|
||||
apis/PetApi.js
|
||||
apis/StoreApi.js
|
||||
apis/UserApi.js
|
||||
authentication.js
|
||||
index.js
|
||||
models/ApiResponse.js
|
||||
models/Category.js
|
||||
models/Order.js
|
||||
models/Pet.js
|
||||
models/Tag.js
|
||||
models/User.js
|
||||
operations/actions.js
|
||||
package.json
|
||||
utils/utils.js
|
@ -0,0 +1 @@
|
||||
7.0.0-SNAPSHOT
|
51
samples/client/petstore/zapier/README.md
Normal file
51
samples/client/petstore/zapier/README.md
Normal file
@ -0,0 +1,51 @@
|
||||
# Documentation for zapier generator
|
||||
|
||||
This generator generates a partial implementation of a zapier integration from an openapi specification.
|
||||
|
||||
## Why is it partial?
|
||||
|
||||
It's a partial integration because you have to put in some code for it to be 100% complete, code that depends only on how your api is structured.
|
||||
|
||||
Here there are all the parts you need to complete by yourself:
|
||||
|
||||
### 1) **utils/utils.js** isSearchAction method
|
||||
This method has to return either true or false if a method is a [zapier search action](https://platform.zapier.com/docs/search-create).
|
||||
```
|
||||
const isSearchAction = (key) => {
|
||||
// TODO: custom logic
|
||||
return false
|
||||
}
|
||||
```
|
||||
|
||||
### 2) **utils/utils.js** searchMiddleware method
|
||||
This method has to return an array of resources (searches must return an array), if you have pagination or you api returns an array inside nested fields, here you have to extract the array.
|
||||
|
||||
```
|
||||
const searchMiddleware = (action) => {
|
||||
// TODO: custom logic
|
||||
return action
|
||||
}
|
||||
```
|
||||
|
||||
### 3) **authentication.js**
|
||||
This file must be written completely according to your api authentication, you can get it generated automatically by creating the integration on the zapier website and filling the requested data, or you can build it yourself following [this guide](https://platform.zapier.com/cli_tutorials/getting-started#adding-authentication).
|
||||
|
||||
## Samples
|
||||
To get your app made public on zapier you must provide a sample (json example response) for each of your actions, these samples get automatically generated by this generator but you have to have actual response examples in you openapi file.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
CreateUserResponse:
|
||||
description: Example response
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: ./models/responses/CreateUserResponse.yaml
|
||||
examples:
|
||||
example-1:
|
||||
value:
|
||||
data:
|
||||
id: 12345
|
||||
name: user1
|
||||
```
|
370
samples/client/petstore/zapier/apis/PetApi.js
Normal file
370
samples/client/petstore/zapier/apis/PetApi.js
Normal file
@ -0,0 +1,370 @@
|
||||
const samples = require('../samples/PetApi');
|
||||
const ApiResponse = require('../models/ApiResponse');
|
||||
const Pet = require('../models/Pet');
|
||||
const utils = require('../utils/utils');
|
||||
const FormData = require('form-data');
|
||||
|
||||
module.exports = {
|
||||
addPet: {
|
||||
key: 'addPet',
|
||||
noun: 'Pet',
|
||||
display: {
|
||||
label: 'addPet',
|
||||
description: '',
|
||||
hidden: false,
|
||||
},
|
||||
operation: {
|
||||
inputFields: [
|
||||
...Pet.fields(),
|
||||
],
|
||||
outputFields: [
|
||||
...Pet.fields('', false),
|
||||
],
|
||||
perform: async (z, bundle) => {
|
||||
const options = {
|
||||
url: utils.replacePathParameters('http://petstore.swagger.io/v2/pet'),
|
||||
method: 'POST',
|
||||
removeMissingValuesFrom: { params: true, body: true },
|
||||
headers: {
|
||||
'Authorization': 'Bearer {{bundle.authData.access_token}}',
|
||||
'Content-Type': 'application/json, application/xml',
|
||||
'Accept': 'application/xml, application/json',
|
||||
},
|
||||
params: {
|
||||
},
|
||||
body: {
|
||||
...Pet.mapping(bundle),
|
||||
},
|
||||
}
|
||||
return z.request(options).then((response) => {
|
||||
response.throwForStatus();
|
||||
const results = response.json;
|
||||
return results;
|
||||
})
|
||||
},
|
||||
sample: samples['PetSample']
|
||||
}
|
||||
},
|
||||
deletePet: {
|
||||
key: 'deletePet',
|
||||
noun: 'Pet',
|
||||
display: {
|
||||
label: 'deletePet',
|
||||
description: '',
|
||||
hidden: false,
|
||||
},
|
||||
operation: {
|
||||
inputFields: [
|
||||
{
|
||||
key: 'petId',
|
||||
label: 'Pet id to delete',
|
||||
type: '',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
key: 'api_key',
|
||||
label: '',
|
||||
type: 'string',
|
||||
},
|
||||
],
|
||||
outputFields: [
|
||||
],
|
||||
perform: async (z, bundle) => {
|
||||
const options = {
|
||||
url: utils.replacePathParameters('http://petstore.swagger.io/v2/pet/{petId}'),
|
||||
method: 'DELETE',
|
||||
removeMissingValuesFrom: { params: true, body: true },
|
||||
headers: {
|
||||
'Authorization': 'Bearer {{bundle.authData.access_token}}',
|
||||
'Content-Type': '',
|
||||
'Accept': '',
|
||||
},
|
||||
params: {
|
||||
},
|
||||
body: {
|
||||
},
|
||||
}
|
||||
return z.request(options).then((response) => {
|
||||
response.throwForStatus();
|
||||
const results = response.json;
|
||||
return results;
|
||||
})
|
||||
},
|
||||
sample: { data: {} }
|
||||
}
|
||||
},
|
||||
findPetsByStatus: {
|
||||
key: 'findPetsByStatus',
|
||||
noun: 'Pet',
|
||||
display: {
|
||||
label: 'findPetsByStatus',
|
||||
description: 'Multiple status values can be provided with comma separated strings',
|
||||
hidden: false,
|
||||
},
|
||||
operation: {
|
||||
inputFields: [
|
||||
...string.fields(),
|
||||
],
|
||||
outputFields: [
|
||||
...array.fields('', false),
|
||||
],
|
||||
perform: async (z, bundle) => {
|
||||
const options = {
|
||||
url: utils.replacePathParameters('http://petstore.swagger.io/v2/pet/findByStatus'),
|
||||
method: 'GET',
|
||||
removeMissingValuesFrom: { params: true, body: true },
|
||||
headers: {
|
||||
'Authorization': 'Bearer {{bundle.authData.access_token}}',
|
||||
'Content-Type': '',
|
||||
'Accept': 'application/xml, application/json',
|
||||
},
|
||||
params: {
|
||||
'status': bundle.inputData?.['status'],
|
||||
},
|
||||
body: {
|
||||
},
|
||||
}
|
||||
return z.request(options).then((response) => {
|
||||
response.throwForStatus();
|
||||
const results = response.json;
|
||||
return results;
|
||||
})
|
||||
},
|
||||
sample: samples['PetSample']
|
||||
}
|
||||
},
|
||||
findPetsByTags: {
|
||||
key: 'findPetsByTags',
|
||||
noun: 'Pet',
|
||||
display: {
|
||||
label: 'findPetsByTags',
|
||||
description: 'Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.',
|
||||
hidden: false,
|
||||
},
|
||||
operation: {
|
||||
inputFields: [
|
||||
...string.fields(),
|
||||
],
|
||||
outputFields: [
|
||||
...array.fields('', false),
|
||||
],
|
||||
perform: async (z, bundle) => {
|
||||
const options = {
|
||||
url: utils.replacePathParameters('http://petstore.swagger.io/v2/pet/findByTags'),
|
||||
method: 'GET',
|
||||
removeMissingValuesFrom: { params: true, body: true },
|
||||
headers: {
|
||||
'Authorization': 'Bearer {{bundle.authData.access_token}}',
|
||||
'Content-Type': '',
|
||||
'Accept': 'application/xml, application/json',
|
||||
},
|
||||
params: {
|
||||
'tags': bundle.inputData?.['tags'],
|
||||
},
|
||||
body: {
|
||||
},
|
||||
}
|
||||
return z.request(options).then((response) => {
|
||||
response.throwForStatus();
|
||||
const results = response.json;
|
||||
return results;
|
||||
})
|
||||
},
|
||||
sample: samples['PetSample']
|
||||
}
|
||||
},
|
||||
getPetById: {
|
||||
key: 'getPetById',
|
||||
noun: 'Pet',
|
||||
display: {
|
||||
label: 'getPetById',
|
||||
description: 'Returns a single pet',
|
||||
hidden: false,
|
||||
},
|
||||
operation: {
|
||||
inputFields: [
|
||||
{
|
||||
key: 'petId',
|
||||
label: 'ID of pet to return',
|
||||
type: '',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
outputFields: [
|
||||
...Pet.fields('', false),
|
||||
],
|
||||
perform: async (z, bundle) => {
|
||||
const options = {
|
||||
url: utils.replacePathParameters('http://petstore.swagger.io/v2/pet/{petId}'),
|
||||
method: 'GET',
|
||||
removeMissingValuesFrom: { params: true, body: true },
|
||||
headers: {
|
||||
'Authorization': 'Bearer {{bundle.authData.access_token}}',
|
||||
'Content-Type': '',
|
||||
'Accept': 'application/xml, application/json',
|
||||
},
|
||||
params: {
|
||||
},
|
||||
body: {
|
||||
},
|
||||
}
|
||||
return z.request(options).then((response) => {
|
||||
response.throwForStatus();
|
||||
const results = response.json;
|
||||
return results;
|
||||
})
|
||||
},
|
||||
sample: samples['PetSample']
|
||||
}
|
||||
},
|
||||
updatePet: {
|
||||
key: 'updatePet',
|
||||
noun: 'Pet',
|
||||
display: {
|
||||
label: 'updatePet',
|
||||
description: '',
|
||||
hidden: false,
|
||||
},
|
||||
operation: {
|
||||
inputFields: [
|
||||
...Pet.fields(),
|
||||
],
|
||||
outputFields: [
|
||||
...Pet.fields('', false),
|
||||
],
|
||||
perform: async (z, bundle) => {
|
||||
const options = {
|
||||
url: utils.replacePathParameters('http://petstore.swagger.io/v2/pet'),
|
||||
method: 'PUT',
|
||||
removeMissingValuesFrom: { params: true, body: true },
|
||||
headers: {
|
||||
'Authorization': 'Bearer {{bundle.authData.access_token}}',
|
||||
'Content-Type': 'application/json, application/xml',
|
||||
'Accept': 'application/xml, application/json',
|
||||
},
|
||||
params: {
|
||||
},
|
||||
body: {
|
||||
...Pet.mapping(bundle),
|
||||
},
|
||||
}
|
||||
return z.request(options).then((response) => {
|
||||
response.throwForStatus();
|
||||
const results = response.json;
|
||||
return results;
|
||||
})
|
||||
},
|
||||
sample: samples['PetSample']
|
||||
}
|
||||
},
|
||||
updatePetWithForm: {
|
||||
key: 'updatePetWithForm',
|
||||
noun: 'Pet',
|
||||
display: {
|
||||
label: 'updatePetWithForm',
|
||||
description: '',
|
||||
hidden: false,
|
||||
},
|
||||
operation: {
|
||||
inputFields: [
|
||||
{
|
||||
key: 'petId',
|
||||
label: 'ID of pet that needs to be updated',
|
||||
type: '',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
key: 'name',
|
||||
label: 'Updated name of the pet',
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
key: 'status',
|
||||
label: 'Updated status of the pet',
|
||||
type: 'string',
|
||||
},
|
||||
],
|
||||
outputFields: [
|
||||
],
|
||||
perform: async (z, bundle) => {
|
||||
const options = {
|
||||
url: utils.replacePathParameters('http://petstore.swagger.io/v2/pet/{petId}'),
|
||||
method: 'POST',
|
||||
removeMissingValuesFrom: { params: true, body: true },
|
||||
headers: {
|
||||
'Authorization': 'Bearer {{bundle.authData.access_token}}',
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'Accept': '',
|
||||
},
|
||||
params: {
|
||||
},
|
||||
body: {
|
||||
},
|
||||
}
|
||||
return z.request(options).then((response) => {
|
||||
response.throwForStatus();
|
||||
const results = response.json;
|
||||
return results;
|
||||
})
|
||||
},
|
||||
sample: { data: {} }
|
||||
}
|
||||
},
|
||||
uploadFile: {
|
||||
key: 'uploadFile',
|
||||
noun: 'Pet',
|
||||
display: {
|
||||
label: 'uploadFile',
|
||||
description: '',
|
||||
hidden: false,
|
||||
},
|
||||
operation: {
|
||||
inputFields: [
|
||||
{
|
||||
key: 'petId',
|
||||
label: 'ID of pet to update',
|
||||
type: '',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
key: 'additionalMetadata',
|
||||
label: 'Additional data to pass to server',
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
key: 'file',
|
||||
label: 'file to upload',
|
||||
type: 'file',
|
||||
},
|
||||
],
|
||||
outputFields: [
|
||||
...ApiResponse.fields('', false),
|
||||
],
|
||||
perform: async (z, bundle) => {
|
||||
const formData = new FormData()
|
||||
formData.append('additionalMetadata', bundle.inputData?.['additionalMetadata'])
|
||||
const filename = bundle.inputData?.['filename'] || bundle.inputData?.['file'].split('/').slice(-1)[0]
|
||||
formData.append('file', (await (await z.request({url: bundle.inputData?.['file'], method: 'GET', raw: true})).buffer()), { filename: filename })
|
||||
const options = {
|
||||
url: utils.replacePathParameters('http://petstore.swagger.io/v2/pet/{petId}/uploadImage'),
|
||||
method: 'POST',
|
||||
removeMissingValuesFrom: { params: true, body: true },
|
||||
headers: {
|
||||
'Authorization': 'Bearer {{bundle.authData.access_token}}',
|
||||
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
params: {
|
||||
},
|
||||
body: formData,
|
||||
}
|
||||
return z.request(options).then((response) => {
|
||||
response.throwForStatus();
|
||||
const results = response.json;
|
||||
return results;
|
||||
})
|
||||
},
|
||||
sample: samples['ApiResponseSample']
|
||||
}
|
||||
},
|
||||
}
|
170
samples/client/petstore/zapier/apis/StoreApi.js
Normal file
170
samples/client/petstore/zapier/apis/StoreApi.js
Normal file
@ -0,0 +1,170 @@
|
||||
const samples = require('../samples/StoreApi');
|
||||
const Order = require('../models/Order');
|
||||
const utils = require('../utils/utils');
|
||||
|
||||
module.exports = {
|
||||
deleteOrder: {
|
||||
key: 'deleteOrder',
|
||||
noun: 'Store',
|
||||
display: {
|
||||
label: 'deleteOrder',
|
||||
description: 'For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors',
|
||||
hidden: false,
|
||||
},
|
||||
operation: {
|
||||
inputFields: [
|
||||
{
|
||||
key: 'orderId',
|
||||
label: 'ID of the order that needs to be deleted',
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
outputFields: [
|
||||
],
|
||||
perform: async (z, bundle) => {
|
||||
const options = {
|
||||
url: utils.replacePathParameters('http://petstore.swagger.io/v2/store/order/{orderId}'),
|
||||
method: 'DELETE',
|
||||
removeMissingValuesFrom: { params: true, body: true },
|
||||
headers: {
|
||||
'Authorization': 'Bearer {{bundle.authData.access_token}}',
|
||||
'Content-Type': '',
|
||||
'Accept': '',
|
||||
},
|
||||
params: {
|
||||
},
|
||||
body: {
|
||||
},
|
||||
}
|
||||
return z.request(options).then((response) => {
|
||||
response.throwForStatus();
|
||||
const results = response.json;
|
||||
return results;
|
||||
})
|
||||
},
|
||||
sample: { data: {} }
|
||||
}
|
||||
},
|
||||
getInventory: {
|
||||
key: 'getInventory',
|
||||
noun: 'Store',
|
||||
display: {
|
||||
label: 'getInventory',
|
||||
description: 'Returns a map of status codes to quantities',
|
||||
hidden: false,
|
||||
},
|
||||
operation: {
|
||||
inputFields: [
|
||||
],
|
||||
outputFields: [
|
||||
],
|
||||
perform: async (z, bundle) => {
|
||||
const options = {
|
||||
url: utils.replacePathParameters('http://petstore.swagger.io/v2/store/inventory'),
|
||||
method: 'GET',
|
||||
removeMissingValuesFrom: { params: true, body: true },
|
||||
headers: {
|
||||
'Authorization': 'Bearer {{bundle.authData.access_token}}',
|
||||
'Content-Type': '',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
params: {
|
||||
},
|
||||
body: {
|
||||
},
|
||||
}
|
||||
return z.request(options).then((response) => {
|
||||
response.throwForStatus();
|
||||
const results = response.json;
|
||||
return { data: results };
|
||||
})
|
||||
},
|
||||
sample: { data: {} }
|
||||
}
|
||||
},
|
||||
getOrderById: {
|
||||
key: 'getOrderById',
|
||||
noun: 'Store',
|
||||
display: {
|
||||
label: 'getOrderById',
|
||||
description: 'For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions',
|
||||
hidden: false,
|
||||
},
|
||||
operation: {
|
||||
inputFields: [
|
||||
{
|
||||
key: 'orderId',
|
||||
label: 'ID of pet that needs to be fetched',
|
||||
type: '',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
outputFields: [
|
||||
...Order.fields('', false),
|
||||
],
|
||||
perform: async (z, bundle) => {
|
||||
const options = {
|
||||
url: utils.replacePathParameters('http://petstore.swagger.io/v2/store/order/{orderId}'),
|
||||
method: 'GET',
|
||||
removeMissingValuesFrom: { params: true, body: true },
|
||||
headers: {
|
||||
'Authorization': 'Bearer {{bundle.authData.access_token}}',
|
||||
'Content-Type': '',
|
||||
'Accept': 'application/xml, application/json',
|
||||
},
|
||||
params: {
|
||||
},
|
||||
body: {
|
||||
},
|
||||
}
|
||||
return z.request(options).then((response) => {
|
||||
response.throwForStatus();
|
||||
const results = response.json;
|
||||
return results;
|
||||
})
|
||||
},
|
||||
sample: samples['OrderSample']
|
||||
}
|
||||
},
|
||||
placeOrder: {
|
||||
key: 'placeOrder',
|
||||
noun: 'Store',
|
||||
display: {
|
||||
label: 'placeOrder',
|
||||
description: '',
|
||||
hidden: false,
|
||||
},
|
||||
operation: {
|
||||
inputFields: [
|
||||
...Order.fields(),
|
||||
],
|
||||
outputFields: [
|
||||
...Order.fields('', false),
|
||||
],
|
||||
perform: async (z, bundle) => {
|
||||
const options = {
|
||||
url: utils.replacePathParameters('http://petstore.swagger.io/v2/store/order'),
|
||||
method: 'POST',
|
||||
removeMissingValuesFrom: { params: true, body: true },
|
||||
headers: {
|
||||
'Authorization': 'Bearer {{bundle.authData.access_token}}',
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/xml, application/json',
|
||||
},
|
||||
params: {
|
||||
},
|
||||
body: {
|
||||
...Order.mapping(bundle),
|
||||
},
|
||||
}
|
||||
return z.request(options).then((response) => {
|
||||
response.throwForStatus();
|
||||
const results = response.json;
|
||||
return results;
|
||||
})
|
||||
},
|
||||
sample: samples['OrderSample']
|
||||
}
|
||||
},
|
||||
}
|
343
samples/client/petstore/zapier/apis/UserApi.js
Normal file
343
samples/client/petstore/zapier/apis/UserApi.js
Normal file
@ -0,0 +1,343 @@
|
||||
const samples = require('../samples/UserApi');
|
||||
const User = require('../models/User');
|
||||
const utils = require('../utils/utils');
|
||||
|
||||
module.exports = {
|
||||
createUser: {
|
||||
key: 'createUser',
|
||||
noun: 'User',
|
||||
display: {
|
||||
label: 'createUser',
|
||||
description: 'This can only be done by the logged in user.',
|
||||
hidden: false,
|
||||
},
|
||||
operation: {
|
||||
inputFields: [
|
||||
...User.fields(),
|
||||
],
|
||||
outputFields: [
|
||||
],
|
||||
perform: async (z, bundle) => {
|
||||
const options = {
|
||||
url: utils.replacePathParameters('http://petstore.swagger.io/v2/user'),
|
||||
method: 'POST',
|
||||
removeMissingValuesFrom: { params: true, body: true },
|
||||
headers: {
|
||||
'Authorization': 'Bearer {{bundle.authData.access_token}}',
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': '',
|
||||
},
|
||||
params: {
|
||||
},
|
||||
body: {
|
||||
...User.mapping(bundle),
|
||||
},
|
||||
}
|
||||
return z.request(options).then((response) => {
|
||||
response.throwForStatus();
|
||||
const results = response.json;
|
||||
return results;
|
||||
})
|
||||
},
|
||||
sample: { data: {} }
|
||||
}
|
||||
},
|
||||
createUsersWithArrayInput: {
|
||||
key: 'createUsersWithArrayInput',
|
||||
noun: 'User',
|
||||
display: {
|
||||
label: 'createUsersWithArrayInput',
|
||||
description: '',
|
||||
hidden: false,
|
||||
},
|
||||
operation: {
|
||||
inputFields: [
|
||||
...User.fields(),
|
||||
],
|
||||
outputFields: [
|
||||
],
|
||||
perform: async (z, bundle) => {
|
||||
const options = {
|
||||
url: utils.replacePathParameters('http://petstore.swagger.io/v2/user/createWithArray'),
|
||||
method: 'POST',
|
||||
removeMissingValuesFrom: { params: true, body: true },
|
||||
headers: {
|
||||
'Authorization': 'Bearer {{bundle.authData.access_token}}',
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': '',
|
||||
},
|
||||
params: {
|
||||
},
|
||||
body: {
|
||||
...User.mapping(bundle),
|
||||
},
|
||||
}
|
||||
return z.request(options).then((response) => {
|
||||
response.throwForStatus();
|
||||
const results = response.json;
|
||||
return results;
|
||||
})
|
||||
},
|
||||
sample: { data: {} }
|
||||
}
|
||||
},
|
||||
createUsersWithListInput: {
|
||||
key: 'createUsersWithListInput',
|
||||
noun: 'User',
|
||||
display: {
|
||||
label: 'createUsersWithListInput',
|
||||
description: '',
|
||||
hidden: false,
|
||||
},
|
||||
operation: {
|
||||
inputFields: [
|
||||
...User.fields(),
|
||||
],
|
||||
outputFields: [
|
||||
],
|
||||
perform: async (z, bundle) => {
|
||||
const options = {
|
||||
url: utils.replacePathParameters('http://petstore.swagger.io/v2/user/createWithList'),
|
||||
method: 'POST',
|
||||
removeMissingValuesFrom: { params: true, body: true },
|
||||
headers: {
|
||||
'Authorization': 'Bearer {{bundle.authData.access_token}}',
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': '',
|
||||
},
|
||||
params: {
|
||||
},
|
||||
body: {
|
||||
...User.mapping(bundle),
|
||||
},
|
||||
}
|
||||
return z.request(options).then((response) => {
|
||||
response.throwForStatus();
|
||||
const results = response.json;
|
||||
return results;
|
||||
})
|
||||
},
|
||||
sample: { data: {} }
|
||||
}
|
||||
},
|
||||
deleteUser: {
|
||||
key: 'deleteUser',
|
||||
noun: 'User',
|
||||
display: {
|
||||
label: 'deleteUser',
|
||||
description: 'This can only be done by the logged in user.',
|
||||
hidden: false,
|
||||
},
|
||||
operation: {
|
||||
inputFields: [
|
||||
{
|
||||
key: 'username',
|
||||
label: 'The name that needs to be deleted',
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
outputFields: [
|
||||
],
|
||||
perform: async (z, bundle) => {
|
||||
const options = {
|
||||
url: utils.replacePathParameters('http://petstore.swagger.io/v2/user/{username}'),
|
||||
method: 'DELETE',
|
||||
removeMissingValuesFrom: { params: true, body: true },
|
||||
headers: {
|
||||
'Authorization': 'Bearer {{bundle.authData.access_token}}',
|
||||
'Content-Type': '',
|
||||
'Accept': '',
|
||||
},
|
||||
params: {
|
||||
},
|
||||
body: {
|
||||
},
|
||||
}
|
||||
return z.request(options).then((response) => {
|
||||
response.throwForStatus();
|
||||
const results = response.json;
|
||||
return results;
|
||||
})
|
||||
},
|
||||
sample: { data: {} }
|
||||
}
|
||||
},
|
||||
getUserByName: {
|
||||
key: 'getUserByName',
|
||||
noun: 'User',
|
||||
display: {
|
||||
label: 'getUserByName',
|
||||
description: '',
|
||||
hidden: false,
|
||||
},
|
||||
operation: {
|
||||
inputFields: [
|
||||
{
|
||||
key: 'username',
|
||||
label: 'The name that needs to be fetched. Use user1 for testing.',
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
outputFields: [
|
||||
...User.fields('', false),
|
||||
],
|
||||
perform: async (z, bundle) => {
|
||||
const options = {
|
||||
url: utils.replacePathParameters('http://petstore.swagger.io/v2/user/{username}'),
|
||||
method: 'GET',
|
||||
removeMissingValuesFrom: { params: true, body: true },
|
||||
headers: {
|
||||
'Authorization': 'Bearer {{bundle.authData.access_token}}',
|
||||
'Content-Type': '',
|
||||
'Accept': 'application/xml, application/json',
|
||||
},
|
||||
params: {
|
||||
},
|
||||
body: {
|
||||
},
|
||||
}
|
||||
return z.request(options).then((response) => {
|
||||
response.throwForStatus();
|
||||
const results = response.json;
|
||||
return results;
|
||||
})
|
||||
},
|
||||
sample: samples['UserSample']
|
||||
}
|
||||
},
|
||||
loginUser: {
|
||||
key: 'loginUser',
|
||||
noun: 'User',
|
||||
display: {
|
||||
label: 'loginUser',
|
||||
description: '',
|
||||
hidden: false,
|
||||
},
|
||||
operation: {
|
||||
inputFields: [
|
||||
{
|
||||
key: 'username',
|
||||
label: 'The user name for login',
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
key: 'password',
|
||||
label: 'The password for login in clear text',
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
outputFields: [
|
||||
],
|
||||
perform: async (z, bundle) => {
|
||||
const options = {
|
||||
url: utils.replacePathParameters('http://petstore.swagger.io/v2/user/login'),
|
||||
method: 'GET',
|
||||
removeMissingValuesFrom: { params: true, body: true },
|
||||
headers: {
|
||||
'Authorization': 'Bearer {{bundle.authData.access_token}}',
|
||||
'Content-Type': '',
|
||||
'Accept': 'application/xml, application/json',
|
||||
},
|
||||
params: {
|
||||
'username': bundle.inputData?.['username'],
|
||||
'password': bundle.inputData?.['password'],
|
||||
},
|
||||
body: {
|
||||
},
|
||||
}
|
||||
return z.request(options).then((response) => {
|
||||
response.throwForStatus();
|
||||
const results = response.json;
|
||||
return { data: results };
|
||||
})
|
||||
},
|
||||
sample: { data: {} }
|
||||
}
|
||||
},
|
||||
logoutUser: {
|
||||
key: 'logoutUser',
|
||||
noun: 'User',
|
||||
display: {
|
||||
label: 'logoutUser',
|
||||
description: '',
|
||||
hidden: false,
|
||||
},
|
||||
operation: {
|
||||
inputFields: [
|
||||
],
|
||||
outputFields: [
|
||||
],
|
||||
perform: async (z, bundle) => {
|
||||
const options = {
|
||||
url: utils.replacePathParameters('http://petstore.swagger.io/v2/user/logout'),
|
||||
method: 'GET',
|
||||
removeMissingValuesFrom: { params: true, body: true },
|
||||
headers: {
|
||||
'Authorization': 'Bearer {{bundle.authData.access_token}}',
|
||||
'Content-Type': '',
|
||||
'Accept': '',
|
||||
},
|
||||
params: {
|
||||
},
|
||||
body: {
|
||||
},
|
||||
}
|
||||
return z.request(options).then((response) => {
|
||||
response.throwForStatus();
|
||||
const results = response.json;
|
||||
return results;
|
||||
})
|
||||
},
|
||||
sample: { data: {} }
|
||||
}
|
||||
},
|
||||
updateUser: {
|
||||
key: 'updateUser',
|
||||
noun: 'User',
|
||||
display: {
|
||||
label: 'updateUser',
|
||||
description: 'This can only be done by the logged in user.',
|
||||
hidden: false,
|
||||
},
|
||||
operation: {
|
||||
inputFields: [
|
||||
{
|
||||
key: 'username',
|
||||
label: 'name that need to be deleted',
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
...User.fields(),
|
||||
],
|
||||
outputFields: [
|
||||
],
|
||||
perform: async (z, bundle) => {
|
||||
const options = {
|
||||
url: utils.replacePathParameters('http://petstore.swagger.io/v2/user/{username}'),
|
||||
method: 'PUT',
|
||||
removeMissingValuesFrom: { params: true, body: true },
|
||||
headers: {
|
||||
'Authorization': 'Bearer {{bundle.authData.access_token}}',
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': '',
|
||||
},
|
||||
params: {
|
||||
},
|
||||
body: {
|
||||
...User.mapping(bundle),
|
||||
},
|
||||
}
|
||||
return z.request(options).then((response) => {
|
||||
response.throwForStatus();
|
||||
const results = response.json;
|
||||
return results;
|
||||
})
|
||||
},
|
||||
sample: { data: {} }
|
||||
}
|
||||
},
|
||||
}
|
4
samples/client/petstore/zapier/authentication.js
Normal file
4
samples/client/petstore/zapier/authentication.js
Normal file
@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
// TODO: autentication logic
|
||||
// https://platform.zapier.com/cli_tutorials/getting-started#adding-authentication
|
||||
};
|
10
samples/client/petstore/zapier/index.js
Normal file
10
samples/client/petstore/zapier/index.js
Normal file
@ -0,0 +1,10 @@
|
||||
const authentication = require('./authentication');
|
||||
const { searchActions, createActions } = require('./operations/actions');
|
||||
|
||||
module.exports = {
|
||||
version: require('./package.json').version,
|
||||
platformVersion: require('zapier-platform-core').version,
|
||||
authentication: authentication,
|
||||
searches: searchActions(),
|
||||
creates: createActions(),
|
||||
};
|
32
samples/client/petstore/zapier/models/ApiResponse.js
Normal file
32
samples/client/petstore/zapier/models/ApiResponse.js
Normal file
@ -0,0 +1,32 @@
|
||||
const utils = require('../utils/utils');
|
||||
|
||||
module.exports = {
|
||||
fields: (prefix = '', isInput = true, isArrayChild = false) => {
|
||||
const {keyPrefix, labelPrefix} = utils.buildKeyAndLabel(prefix, isInput, isArrayChild)
|
||||
return [
|
||||
{
|
||||
key: `${keyPrefix}code`,
|
||||
label: `[${labelPrefix}code]`,
|
||||
type: 'integer',
|
||||
},
|
||||
{
|
||||
key: `${keyPrefix}type`,
|
||||
label: `[${labelPrefix}type]`,
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
key: `${keyPrefix}message`,
|
||||
label: `[${labelPrefix}message]`,
|
||||
type: 'string',
|
||||
},
|
||||
]
|
||||
},
|
||||
mapping: (bundle, prefix = '') => {
|
||||
const {keyPrefix} = utils.buildKeyAndLabel(prefix)
|
||||
return {
|
||||
'code': bundle.inputData?.[`${keyPrefix}code`],
|
||||
'type': bundle.inputData?.[`${keyPrefix}type`],
|
||||
'message': bundle.inputData?.[`${keyPrefix}message`],
|
||||
}
|
||||
},
|
||||
}
|
26
samples/client/petstore/zapier/models/Category.js
Normal file
26
samples/client/petstore/zapier/models/Category.js
Normal file
@ -0,0 +1,26 @@
|
||||
const utils = require('../utils/utils');
|
||||
|
||||
module.exports = {
|
||||
fields: (prefix = '', isInput = true, isArrayChild = false) => {
|
||||
const {keyPrefix, labelPrefix} = utils.buildKeyAndLabel(prefix, isInput, isArrayChild)
|
||||
return [
|
||||
{
|
||||
key: `${keyPrefix}id`,
|
||||
label: `[${labelPrefix}id]`,
|
||||
type: 'number',
|
||||
},
|
||||
{
|
||||
key: `${keyPrefix}name`,
|
||||
label: `[${labelPrefix}name]`,
|
||||
type: 'string',
|
||||
},
|
||||
]
|
||||
},
|
||||
mapping: (bundle, prefix = '') => {
|
||||
const {keyPrefix} = utils.buildKeyAndLabel(prefix)
|
||||
return {
|
||||
'id': bundle.inputData?.[`${keyPrefix}id`],
|
||||
'name': bundle.inputData?.[`${keyPrefix}name`],
|
||||
}
|
||||
},
|
||||
}
|
55
samples/client/petstore/zapier/models/Order.js
Normal file
55
samples/client/petstore/zapier/models/Order.js
Normal file
@ -0,0 +1,55 @@
|
||||
const utils = require('../utils/utils');
|
||||
|
||||
module.exports = {
|
||||
fields: (prefix = '', isInput = true, isArrayChild = false) => {
|
||||
const {keyPrefix, labelPrefix} = utils.buildKeyAndLabel(prefix, isInput, isArrayChild)
|
||||
return [
|
||||
{
|
||||
key: `${keyPrefix}id`,
|
||||
label: `[${labelPrefix}id]`,
|
||||
type: 'number',
|
||||
},
|
||||
{
|
||||
key: `${keyPrefix}petId`,
|
||||
label: `[${labelPrefix}petId]`,
|
||||
type: 'number',
|
||||
},
|
||||
{
|
||||
key: `${keyPrefix}quantity`,
|
||||
label: `[${labelPrefix}quantity]`,
|
||||
type: 'integer',
|
||||
},
|
||||
{
|
||||
key: `${keyPrefix}shipDate`,
|
||||
label: `[${labelPrefix}shipDate]`,
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
key: `${keyPrefix}status`,
|
||||
label: `Order Status - [${labelPrefix}status]`,
|
||||
type: 'string',
|
||||
choices: [
|
||||
'placed',
|
||||
'approved',
|
||||
'delivered',
|
||||
],
|
||||
},
|
||||
{
|
||||
key: `${keyPrefix}complete`,
|
||||
label: `[${labelPrefix}complete]`,
|
||||
type: 'boolean',
|
||||
},
|
||||
]
|
||||
},
|
||||
mapping: (bundle, prefix = '') => {
|
||||
const {keyPrefix} = utils.buildKeyAndLabel(prefix)
|
||||
return {
|
||||
'id': bundle.inputData?.[`${keyPrefix}id`],
|
||||
'petId': bundle.inputData?.[`${keyPrefix}petId`],
|
||||
'quantity': bundle.inputData?.[`${keyPrefix}quantity`],
|
||||
'shipDate': bundle.inputData?.[`${keyPrefix}shipDate`],
|
||||
'status': bundle.inputData?.[`${keyPrefix}status`],
|
||||
'complete': bundle.inputData?.[`${keyPrefix}complete`],
|
||||
}
|
||||
},
|
||||
}
|
54
samples/client/petstore/zapier/models/Pet.js
Normal file
54
samples/client/petstore/zapier/models/Pet.js
Normal file
@ -0,0 +1,54 @@
|
||||
const utils = require('../utils/utils');
|
||||
const Category = require('../models/Category');
|
||||
const Tag = require('../models/Tag');
|
||||
|
||||
module.exports = {
|
||||
fields: (prefix = '', isInput = true, isArrayChild = false) => {
|
||||
const {keyPrefix, labelPrefix} = utils.buildKeyAndLabel(prefix, isInput, isArrayChild)
|
||||
return [
|
||||
{
|
||||
key: `${keyPrefix}id`,
|
||||
label: `[${labelPrefix}id]`,
|
||||
type: 'number',
|
||||
},
|
||||
...Category.fields(`${keyPrefix}category`, isInput),
|
||||
{
|
||||
key: `${keyPrefix}name`,
|
||||
label: `[${labelPrefix}name]`,
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
key: `${keyPrefix}photoUrls`,
|
||||
label: `[${labelPrefix}photoUrls]`,
|
||||
list: true,
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
key: `${keyPrefix}tags`,
|
||||
label: `[${labelPrefix}tags]`,
|
||||
children: Tag.fields(`${keyPrefix}tags${!isInput ? '[]' : ''}`, isInput, true),
|
||||
},
|
||||
{
|
||||
key: `${keyPrefix}status`,
|
||||
label: `pet status in the store - [${labelPrefix}status]`,
|
||||
type: 'string',
|
||||
choices: [
|
||||
'available',
|
||||
'pending',
|
||||
'sold',
|
||||
],
|
||||
},
|
||||
]
|
||||
},
|
||||
mapping: (bundle, prefix = '') => {
|
||||
const {keyPrefix} = utils.buildKeyAndLabel(prefix)
|
||||
return {
|
||||
'id': bundle.inputData?.[`${keyPrefix}id`],
|
||||
'category': utils.removeIfEmpty(Category.mapping(bundle, `${keyPrefix}category`)),
|
||||
'name': bundle.inputData?.[`${keyPrefix}name`],
|
||||
'photoUrls': bundle.inputData?.[`${keyPrefix}photoUrls`],
|
||||
'tags': utils.removeKeyPrefixes(bundle.inputData?.[`${keyPrefix}tags`]),
|
||||
'status': bundle.inputData?.[`${keyPrefix}status`],
|
||||
}
|
||||
},
|
||||
}
|
26
samples/client/petstore/zapier/models/Tag.js
Normal file
26
samples/client/petstore/zapier/models/Tag.js
Normal file
@ -0,0 +1,26 @@
|
||||
const utils = require('../utils/utils');
|
||||
|
||||
module.exports = {
|
||||
fields: (prefix = '', isInput = true, isArrayChild = false) => {
|
||||
const {keyPrefix, labelPrefix} = utils.buildKeyAndLabel(prefix, isInput, isArrayChild)
|
||||
return [
|
||||
{
|
||||
key: `${keyPrefix}id`,
|
||||
label: `[${labelPrefix}id]`,
|
||||
type: 'number',
|
||||
},
|
||||
{
|
||||
key: `${keyPrefix}name`,
|
||||
label: `[${labelPrefix}name]`,
|
||||
type: 'string',
|
||||
},
|
||||
]
|
||||
},
|
||||
mapping: (bundle, prefix = '') => {
|
||||
const {keyPrefix} = utils.buildKeyAndLabel(prefix)
|
||||
return {
|
||||
'id': bundle.inputData?.[`${keyPrefix}id`],
|
||||
'name': bundle.inputData?.[`${keyPrefix}name`],
|
||||
}
|
||||
},
|
||||
}
|
62
samples/client/petstore/zapier/models/User.js
Normal file
62
samples/client/petstore/zapier/models/User.js
Normal file
@ -0,0 +1,62 @@
|
||||
const utils = require('../utils/utils');
|
||||
|
||||
module.exports = {
|
||||
fields: (prefix = '', isInput = true, isArrayChild = false) => {
|
||||
const {keyPrefix, labelPrefix} = utils.buildKeyAndLabel(prefix, isInput, isArrayChild)
|
||||
return [
|
||||
{
|
||||
key: `${keyPrefix}id`,
|
||||
label: `[${labelPrefix}id]`,
|
||||
type: 'number',
|
||||
},
|
||||
{
|
||||
key: `${keyPrefix}username`,
|
||||
label: `[${labelPrefix}username]`,
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
key: `${keyPrefix}firstName`,
|
||||
label: `[${labelPrefix}firstName]`,
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
key: `${keyPrefix}lastName`,
|
||||
label: `[${labelPrefix}lastName]`,
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
key: `${keyPrefix}email`,
|
||||
label: `[${labelPrefix}email]`,
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
key: `${keyPrefix}password`,
|
||||
label: `[${labelPrefix}password]`,
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
key: `${keyPrefix}phone`,
|
||||
label: `[${labelPrefix}phone]`,
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
key: `${keyPrefix}userStatus`,
|
||||
label: `User Status - [${labelPrefix}userStatus]`,
|
||||
type: 'integer',
|
||||
},
|
||||
]
|
||||
},
|
||||
mapping: (bundle, prefix = '') => {
|
||||
const {keyPrefix} = utils.buildKeyAndLabel(prefix)
|
||||
return {
|
||||
'id': bundle.inputData?.[`${keyPrefix}id`],
|
||||
'username': bundle.inputData?.[`${keyPrefix}username`],
|
||||
'firstName': bundle.inputData?.[`${keyPrefix}firstName`],
|
||||
'lastName': bundle.inputData?.[`${keyPrefix}lastName`],
|
||||
'email': bundle.inputData?.[`${keyPrefix}email`],
|
||||
'password': bundle.inputData?.[`${keyPrefix}password`],
|
||||
'phone': bundle.inputData?.[`${keyPrefix}phone`],
|
||||
'userStatus': bundle.inputData?.[`${keyPrefix}userStatus`],
|
||||
}
|
||||
},
|
||||
}
|
32
samples/client/petstore/zapier/operations/actions.js
Normal file
32
samples/client/petstore/zapier/operations/actions.js
Normal file
@ -0,0 +1,32 @@
|
||||
const PetApi = require('../apis/PetApi');
|
||||
const StoreApi = require('../apis/StoreApi');
|
||||
const UserApi = require('../apis/UserApi');
|
||||
const { searchMiddleware, hasSearchRequisites, isSearchAction } = require('../utils/utils');
|
||||
|
||||
const actions = {
|
||||
[PetApi.addPet.key]: PetApi.addPet,
|
||||
[PetApi.deletePet.key]: PetApi.deletePet,
|
||||
[PetApi.findPetsByStatus.key]: PetApi.findPetsByStatus,
|
||||
[PetApi.findPetsByTags.key]: PetApi.findPetsByTags,
|
||||
[PetApi.getPetById.key]: PetApi.getPetById,
|
||||
[PetApi.updatePet.key]: PetApi.updatePet,
|
||||
[PetApi.updatePetWithForm.key]: PetApi.updatePetWithForm,
|
||||
[PetApi.uploadFile.key]: PetApi.uploadFile,
|
||||
[StoreApi.deleteOrder.key]: StoreApi.deleteOrder,
|
||||
[StoreApi.getInventory.key]: StoreApi.getInventory,
|
||||
[StoreApi.getOrderById.key]: StoreApi.getOrderById,
|
||||
[StoreApi.placeOrder.key]: StoreApi.placeOrder,
|
||||
[UserApi.createUser.key]: UserApi.createUser,
|
||||
[UserApi.createUsersWithArrayInput.key]: UserApi.createUsersWithArrayInput,
|
||||
[UserApi.createUsersWithListInput.key]: UserApi.createUsersWithListInput,
|
||||
[UserApi.deleteUser.key]: UserApi.deleteUser,
|
||||
[UserApi.getUserByName.key]: UserApi.getUserByName,
|
||||
[UserApi.loginUser.key]: UserApi.loginUser,
|
||||
[UserApi.logoutUser.key]: UserApi.logoutUser,
|
||||
[UserApi.updateUser.key]: UserApi.updateUser,
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
searchActions: () => Object.entries(actions).reduce((actions, [key, value]) => isSearchAction(key) && hasSearchRequisites(value) ? {...actions, [key]: searchMiddleware(value)} : actions, {}),
|
||||
createActions: () => Object.entries(actions).reduce((actions, [key, value]) => !isSearchAction(key) ? {...actions, [key]: value} : actions, {}),
|
||||
}
|
27
samples/client/petstore/zapier/package.json
Normal file
27
samples/client/petstore/zapier/package.json
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "@openapitools/zapier",
|
||||
"version": "0.0.1",
|
||||
"description": "OpenAPI client for @openapitools/zapier",
|
||||
"author": "OpenAPI-Generator",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "mocha --recursive -t 10000"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=v16",
|
||||
"npm": ">=5.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.21",
|
||||
"zapier-platform-core": "14.1.1",
|
||||
"form-data": "2.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "^10.2.0",
|
||||
"should": "^13.2.0"
|
||||
},
|
||||
"private": true,
|
||||
"zapier": {
|
||||
"convertedByCLIVersion": "14.1.1"
|
||||
}
|
||||
}
|
14
samples/client/petstore/zapier/samples/PetApi.js
Normal file
14
samples/client/petstore/zapier/samples/PetApi.js
Normal file
@ -0,0 +1,14 @@
|
||||
module.export = {
|
||||
"PetSample":
|
||||
{ data: {} },
|
||||
"PetSample":
|
||||
{ data: {} },
|
||||
"PetSample":
|
||||
{ data: {} },
|
||||
"PetSample":
|
||||
{ data: {} },
|
||||
"PetSample":
|
||||
{ data: {} },
|
||||
"ApiResponseSample":
|
||||
{ data: {} },
|
||||
}
|
6
samples/client/petstore/zapier/samples/StoreApi.js
Normal file
6
samples/client/petstore/zapier/samples/StoreApi.js
Normal file
@ -0,0 +1,6 @@
|
||||
module.export = {
|
||||
"OrderSample":
|
||||
{ data: {} },
|
||||
"OrderSample":
|
||||
{ data: {} },
|
||||
}
|
4
samples/client/petstore/zapier/samples/UserApi.js
Normal file
4
samples/client/petstore/zapier/samples/UserApi.js
Normal file
@ -0,0 +1,4 @@
|
||||
module.export = {
|
||||
"UserSample":
|
||||
{ data: {} },
|
||||
}
|
34
samples/client/petstore/zapier/utils/utils.js
Normal file
34
samples/client/petstore/zapier/utils/utils.js
Normal file
@ -0,0 +1,34 @@
|
||||
const _ = require('lodash')
|
||||
|
||||
const replacePathParameters = (url) => url.replace(/{([^{}]+)}/g, (keyExpr, key) => `{{bundle.inputData.${key}}}`)
|
||||
const removeKeyPrefixes = (objectsArray) => objectsArray == undefined || typeof objectsArray[0] != 'object' ? objectsArray : objectsArray.map((obj) => Object.keys(obj).reduce((res, key) => (res[(key.split('.')).slice(-1)] = obj[key], res), {}))
|
||||
const removeIfEmpty = (obj) => _.isEmpty(JSON.parse(JSON.stringify(obj))) ? undefined : obj
|
||||
const buildKeyAndLabel = (prefix, isInput = true, isArrayChild = false) => {
|
||||
const keyPrefix = !_.isEmpty(prefix) && (!isArrayChild || isInput) ? `${prefix}${isInput ? '.' : '__'}` : prefix
|
||||
const labelPrefix = !_.isEmpty(keyPrefix) ? keyPrefix.replaceAll('__', '.') : ''
|
||||
return {
|
||||
keyPrefix: keyPrefix,
|
||||
labelPrefix:labelPrefix,
|
||||
}
|
||||
}
|
||||
const isSearchAction = (key) => {
|
||||
// TODO: custom logic
|
||||
return false
|
||||
}
|
||||
const hasASearchField = action => action.operation.inputFields.length > 0
|
||||
const returnsObjectsArray = action => !!action.operation.outputFields.find(field => 'children' in field)
|
||||
const hasSearchRequisites = action => hasASearchField(action) && returnsObjectsArray(action)
|
||||
const searchMiddleware = (action) => {
|
||||
// TODO: custom logic
|
||||
return action
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
replacePathParameters: replacePathParameters,
|
||||
removeKeyPrefixes: removeKeyPrefixes,
|
||||
removeIfEmpty: removeIfEmpty,
|
||||
buildKeyAndLabel: buildKeyAndLabel,
|
||||
hasSearchRequisites: hasSearchRequisites,
|
||||
isSearchAction: isSearchAction,
|
||||
searchMiddleware: searchMiddleware,
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user