Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat(schema) support hook to poll triggers INT-15776 #432

Merged
merged 9 commits into from
Nov 11, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/schema/docs/build/schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -1904,7 +1904,7 @@ Key | Required | Type | Description
`key` | **yes** | [/KeySchema](#keyschema) | A key to uniquely identify this trigger.
`noun` | **yes** | `string` | A noun for this trigger that completes the sentence "triggers on a new XXX".
`display` | **yes** | [/BasicDisplaySchema](#basicdisplayschema) | Configures the UI for this trigger.
`operation` | **yes** | anyOf([/BasicPollingOperationSchema](#basicpollingoperationschema), [/BasicHookOperationSchema](#basichookoperationschema)) | Powers the functionality for this trigger.
`operation` | **yes** | anyOf([/BasicPollingOperationSchema](#basicpollingoperationschema), [/BasicHookOperationSchema](#basichookoperationschema), [/BasicHookToPollOperationSchema](#basichooktopolloperationschema)) | Powers the functionality for this trigger.

#### Examples

Expand Down
84 changes: 84 additions & 0 deletions packages/schema/exported-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1063,6 +1063,87 @@
},
"additionalProperties": false
},
"BasicHookToPollOperationSchema": {
"id": "/BasicHookToPollOperationSchema",
"description": "Represents the inbound mechanics of hook to poll style triggers. Defers to list for fields.",
"type": "object",
"required": ["performList"],
"properties": {
"type": {
"description": "Must be explicitly set to `\"hook\"` unless this hook is defined as part of a resource, in which case it's optional.",
"type": "string",
"enum": ["hook_to_poll"],
"required": {
"type": "replace",
"value": "**yes** (with exceptions, see description)"
}
},
"resource": {
"description": "Optionally reference and extends a resource. Allows Zapier to automatically tie together samples, lists and hooks, greatly improving the UX. EG: if you had another trigger reusing a resource but filtering the results.",
"$ref": "/KeySchema"
},
casshill marked this conversation as resolved.
Show resolved Hide resolved
"performList": {
"description": "Similar a polling trigger, but checks for new data when a webhook is received, instead of every few minutes",
"oneOf": [
{
"$ref": "/RequestSchema"
},
{
"$ref": "/FunctionSchema"
}
]
},
"canPaginate": {
"description": "Does this endpoint support pagination via temporary cursor storage?",
"type": "boolean"
},
"performSubscribe": {
"description": "Takes a URL and any necessary data from the user and subscribes. ",
"oneOf": [
{
"$ref": "/RequestSchema"
},
{
"$ref": "/FunctionSchema"
}
]
},
"performUnsubscribe": {
"description": "Takes a URL and data from a previous subscribe call and unsubscribes. ",
"oneOf": [
{
"$ref": "/RequestSchema"
},
{
"$ref": "/FunctionSchema"
}
]
},
"inputFields": {
"description": "What should the form a user sees and configures look like?",
"$ref": "/DynamicFieldsSchema"
},
"outputFields": {
"description": "What fields of data will this return? Will use resource outputFields if missing, will also use sample if available.",
"$ref": "/DynamicFieldsSchema"
},
"sample": {
"description": "What does a sample of data look like? Will use resource sample if missing. Requirement waived if `display.hidden` is true or if this belongs to a resource that has a top-level sample",
"type": "object",
"minProperties": 1,
"docAnnotation": {
"required": {
"type": "replace",
"value": "**yes** (with exceptions, see description)"
}
}
}
},
"additionalProperties": false,
"docAnnotation": {
"hide": true
}
},
"TriggerSchema": {
"id": "/TriggerSchema",
"description": "How will Zapier get notified of new objects?",
Expand Down Expand Up @@ -1091,6 +1172,9 @@
},
{
"$ref": "/BasicHookOperationSchema"
},
{
"$ref": "/BasicHookToPollOperationSchema"
}
]
}
Expand Down
89 changes: 89 additions & 0 deletions packages/schema/lib/schemas/BasicHookToPollOperationSchema.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
'use strict';

const makeSchema = require('../utils/makeSchema');
const { SKIP_KEY } = require('../constants');

const BasicOperationSchema = require('./BasicOperationSchema');
const FunctionSchema = require('./FunctionSchema');
const RequestSchema = require('./RequestSchema');

// TODO: would be nice to deep merge these instead
// or maybe use allOf which is built into json-schema
const BasicHookToPollOperationSchema = JSON.parse(
JSON.stringify(BasicOperationSchema.schema)
);

BasicHookToPollOperationSchema.id = '/BasicHookToPollOperationSchema';

BasicHookToPollOperationSchema.description =
'Represents the inbound mechanics of hook to poll style triggers. Defers to list for fields.';

(BasicHookToPollOperationSchema.docAnnotation = {
hide: true,
}),
(BasicHookToPollOperationSchema.required = ['performList']),
(BasicHookToPollOperationSchema.properties = {
type: {
description:
'Must be explicitly set to `"hook"` unless this hook is defined as part of a resource, in which case it\'s optional.',
type: 'string',
enum: ['hook_to_poll'],
required: {
type: 'replace',
value: '**yes** (with exceptions, see description)',
},
},
resource: BasicHookToPollOperationSchema.properties.resource,
performList: {
description:
'Similar a polling trigger, but checks for new data when a webhook is received, instead of every few minutes',
oneOf: [{ $ref: RequestSchema.id }, { $ref: FunctionSchema.id }],
},
canPaginate: {
description:
'Does this endpoint support pagination via temporary cursor storage?',
type: 'boolean',
},
performSubscribe: {
description:
'Takes a URL and any necessary data from the user and subscribes. ',
oneOf: [{ $ref: RequestSchema.id }, { $ref: FunctionSchema.id }],
},
performUnsubscribe: {
description:
'Takes a URL and data from a previous subscribe call and unsubscribes. ',
oneOf: [{ $ref: RequestSchema.id }, { $ref: FunctionSchema.id }],
},
inputFields: BasicHookToPollOperationSchema.properties.inputFields,
outputFields: BasicHookToPollOperationSchema.properties.outputFields,
sample: BasicHookToPollOperationSchema.properties.sample,
});

BasicHookToPollOperationSchema.examples = [
{
type: 'hook_to_poll',
performList: { require: 'some/path/to/file2.js' },
performSubscribe: { require: 'some/path/to/file3.js' },
performUnsubscribe: { require: 'some/path/to/file4.js' },
sample: { id: 42, name: 'Hooli' },
},
];

BasicHookToPollOperationSchema.antiExamples = [
{
[SKIP_KEY]: true, // Cannot validate that sample is only required if display isn't true / top-level resource doesn't have sample
example: {
type: 'hook_to_poll',
performList: { require: 'some/path/to/file2.js' },
performSubscribe: { require: 'some/path/to/file3.js' },
performUnsubscribe: { require: 'some/path/to/file4.js' },
},
reason:
'Missing required key: sample. Note - This is only invalid if `display` is not explicitly set to true and if it does not belong to a resource that has a sample.',
},
];

module.exports = makeSchema(
BasicHookToPollOperationSchema,
BasicOperationSchema.dependencies
);
3 changes: 3 additions & 0 deletions packages/schema/lib/schemas/TriggerSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const makeSchema = require('../utils/makeSchema');

const BasicDisplaySchema = require('./BasicDisplaySchema');
const BasicHookOperationSchema = require('./BasicHookOperationSchema');
const BasicHookToPollOperationSchema = require('./BasicHookToPollOperationSchema');
const BasicPollingOperationSchema = require('./BasicPollingOperationSchema');
const KeySchema = require('./KeySchema');

Expand Down Expand Up @@ -34,6 +35,7 @@ module.exports = makeSchema(
anyOf: [
{ $ref: BasicPollingOperationSchema.id },
{ $ref: BasicHookOperationSchema.id },
{ $ref: BasicHookToPollOperationSchema.id },
casshill marked this conversation as resolved.
Show resolved Hide resolved
],
},
},
Expand Down Expand Up @@ -89,5 +91,6 @@ module.exports = makeSchema(
BasicDisplaySchema,
BasicPollingOperationSchema,
BasicHookOperationSchema,
BasicHookToPollOperationSchema,
]
);
4 changes: 3 additions & 1 deletion packages/schema/lib/utils/buildDocs.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ const walkSchemas = (InitSchema, callback) => {
const collectSchemas = (InitSchema) => {
const schemas = {};
walkSchemas(InitSchema, (Schema) => {
schemas[Schema.id] = Schema;
if (!_.get(Schema, 'schema.docAnnotation.hide')) {
casshill marked this conversation as resolved.
Show resolved Hide resolved
schemas[Schema.id] = Schema;
}
});
return schemas;
};
Expand Down