mirror of
https://github.com/twentyhq/twenty.git
synced 2024-09-11 23:37:21 +03:00
Improve webhook (#3459)
* Add trigger record * Merge triggers * Merge creates * Fix libraries * Fix create merged key * Rename file * Remove list Record Ids * Revert "Rename file" This reverts commit2e72e05793
. * Revert "Revert "Rename file"" This reverts commite2d93fa027
. * Revert "Remove list Record Ids" This reverts commit6653fb6ccd
. * Remove namePlural field * Use name singular for webhooks * Send webhook metadata * Extract resource from zapier webhook * Fix package.json * Fix package.json * Update payload * Fix package.json * Update payload * Update payload * Rename file * Use wildcard in webhook events * Fix nameSingular * Code review returns * Code review returns
This commit is contained in:
parent
fb93bb69fb
commit
bb91917ff8
@ -152,7 +152,6 @@
|
|||||||
"uuid": "^9.0.0",
|
"uuid": "^9.0.0",
|
||||||
"vite-tsconfig-paths": "^4.2.1",
|
"vite-tsconfig-paths": "^4.2.1",
|
||||||
"xlsx-ugnis": "^0.19.3",
|
"xlsx-ugnis": "^0.19.3",
|
||||||
"zapier-platform-core": "15.5.1",
|
|
||||||
"zod": "^3.22.2"
|
"zod": "^3.22.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@ -259,8 +258,7 @@
|
|||||||
"typescript": "^5.3.3",
|
"typescript": "^5.3.3",
|
||||||
"vite": "^5.0.0",
|
"vite": "^5.0.0",
|
||||||
"vite-plugin-checker": "^0.6.2",
|
"vite-plugin-checker": "^0.6.2",
|
||||||
"vite-plugin-svgr": "^4.2.0",
|
"vite-plugin-svgr": "^4.2.0"
|
||||||
"zapier-platform-cli": "^15.4.1"
|
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.17.1",
|
"node": "^18.17.1",
|
||||||
|
@ -22,7 +22,7 @@ export enum CallWebhookJobsJobOperation {
|
|||||||
export type CallWebhookJobsJobData = {
|
export type CallWebhookJobsJobData = {
|
||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
objectMetadataItem: ObjectMetadataInterface;
|
objectMetadataItem: ObjectMetadataInterface;
|
||||||
recordData: any;
|
record: any;
|
||||||
operation: CallWebhookJobsJobOperation;
|
operation: CallWebhookJobsJobOperation;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -41,11 +41,6 @@ export class CallWebhookJobsJob
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
async handle(data: CallWebhookJobsJobData): Promise<void> {
|
async handle(data: CallWebhookJobsJobData): Promise<void> {
|
||||||
const objectMetadataItem =
|
|
||||||
await this.objectMetadataService.findOneOrFailWithinWorkspace(
|
|
||||||
data.workspaceId,
|
|
||||||
{ where: { nameSingular: data.objectMetadataItem.nameSingular } },
|
|
||||||
);
|
|
||||||
const dataSourceMetadata =
|
const dataSourceMetadata =
|
||||||
await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceIdOrFail(
|
await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceIdOrFail(
|
||||||
data.workspaceId,
|
data.workspaceId,
|
||||||
@ -54,27 +49,45 @@ export class CallWebhookJobsJob
|
|||||||
await this.workspaceDataSourceService.connectToWorkspaceDataSource(
|
await this.workspaceDataSourceService.connectToWorkspaceDataSource(
|
||||||
data.workspaceId,
|
data.workspaceId,
|
||||||
);
|
);
|
||||||
const operationName = `${data.operation}.${objectMetadataItem.namePlural}`;
|
const nameSingular = data.objectMetadataItem.nameSingular;
|
||||||
|
const operation = data.operation;
|
||||||
|
const eventType = `${operation}.${nameSingular}`;
|
||||||
const webhooks: { id: string; targetUrl: string }[] =
|
const webhooks: { id: string; targetUrl: string }[] =
|
||||||
await workspaceDataSource?.query(
|
await workspaceDataSource?.query(
|
||||||
`SELECT * FROM ${dataSourceMetadata.schema}."webhook" WHERE operation='${operationName}'`,
|
`
|
||||||
|
SELECT * FROM ${dataSourceMetadata.schema}."webhook"
|
||||||
|
WHERE operation LIKE '%${eventType}%'
|
||||||
|
OR operation LIKE '%*.${nameSingular}%'
|
||||||
|
OR operation LIKE '%${operation}.*%'
|
||||||
|
OR operation LIKE '%*.*%'
|
||||||
|
`,
|
||||||
);
|
);
|
||||||
|
|
||||||
webhooks.forEach((webhook) => {
|
webhooks.forEach((webhook) => {
|
||||||
this.messageQueueService.add<CallWebhookJobData>(
|
this.messageQueueService.add<CallWebhookJobData>(
|
||||||
CallWebhookJob.name,
|
CallWebhookJob.name,
|
||||||
{
|
{
|
||||||
recordData: data.recordData,
|
|
||||||
targetUrl: webhook.targetUrl,
|
targetUrl: webhook.targetUrl,
|
||||||
|
eventType,
|
||||||
|
objectMetadata: {
|
||||||
|
id: data.objectMetadataItem.id,
|
||||||
|
nameSingular: data.objectMetadataItem.nameSingular,
|
||||||
|
},
|
||||||
|
workspaceId: data.workspaceId,
|
||||||
|
webhookId: webhook.id,
|
||||||
|
eventDate: new Date(),
|
||||||
|
record: data.record,
|
||||||
},
|
},
|
||||||
{ retryLimit: 3 },
|
{ retryLimit: 3 },
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.logger.log(
|
if (webhooks.length) {
|
||||||
`CallWebhookJobsJob on operation '${operationName}' called on webhooks ids [\n"${webhooks
|
this.logger.log(
|
||||||
.map((webhook) => webhook.id)
|
`CallWebhookJobsJob on eventType '${eventType}' called on webhooks ids [\n"${webhooks
|
||||||
.join('",\n"')}"\n]`,
|
.map((webhook) => webhook.id)
|
||||||
);
|
.join('",\n"')}"\n]`,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,12 @@ import { MessageQueueJob } from 'src/integrations/message-queue/interfaces/messa
|
|||||||
|
|
||||||
export type CallWebhookJobData = {
|
export type CallWebhookJobData = {
|
||||||
targetUrl: string;
|
targetUrl: string;
|
||||||
recordData: any;
|
eventType: string;
|
||||||
|
objectMetadata: { id: string; nameSingular: string };
|
||||||
|
workspaceId: string;
|
||||||
|
webhookId: string;
|
||||||
|
eventDate: Date;
|
||||||
|
record: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@ -16,11 +21,9 @@ export class CallWebhookJob implements MessageQueueJob<CallWebhookJobData> {
|
|||||||
|
|
||||||
async handle(data: CallWebhookJobData): Promise<void> {
|
async handle(data: CallWebhookJobData): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await this.httpService.axiosRef.post(data.targetUrl, data.recordData);
|
await this.httpService.axiosRef.post(data.targetUrl, data);
|
||||||
this.logger.log(
|
this.logger.log(
|
||||||
`CallWebhookJob successfully called on targetUrl '${
|
`CallWebhookJob successfully called on targetUrl '${data.targetUrl}'`,
|
||||||
data.targetUrl
|
|
||||||
}' with data: ${JSON.stringify(data.recordData)}`,
|
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
@ -388,7 +388,7 @@ export class WorkspaceQueryRunnerService {
|
|||||||
this.messageQueueService.add<CallWebhookJobsJobData>(
|
this.messageQueueService.add<CallWebhookJobsJobData>(
|
||||||
CallWebhookJobsJob.name,
|
CallWebhookJobsJob.name,
|
||||||
{
|
{
|
||||||
recordData: jobData,
|
record: jobData,
|
||||||
workspaceId: options.workspaceId,
|
workspaceId: options.workspaceId,
|
||||||
operation,
|
operation,
|
||||||
objectMetadataItem: options.objectMetadataItem,
|
objectMetadataItem: options.objectMetadataItem,
|
||||||
|
@ -22,5 +22,14 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"zapier": {
|
"zapier": {
|
||||||
"convertedByCLIVersion": "15.4.1"
|
"convertedByCLIVersion": "15.4.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"zapier-platform-core": "15.5.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"zapier-platform-cli": "^15.4.1"
|
||||||
|
},
|
||||||
|
"installConfig": {
|
||||||
|
"hoistingLimits": "dependencies"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
import { Bundle, ZObject } from 'zapier-platform-core';
|
|
||||||
|
|
||||||
import { findObjectNamesSingularKey } from '../triggers/find_object_names_singular';
|
|
||||||
import { capitalize } from '../utils/capitalize';
|
|
||||||
import { recordInputFields } from '../utils/creates/creates.utils';
|
|
||||||
import handleQueryParams from '../utils/handleQueryParams';
|
|
||||||
import requestDb from '../utils/requestDb';
|
|
||||||
|
|
||||||
const perform = async (z: ZObject, bundle: Bundle) => {
|
|
||||||
const data = bundle.inputData;
|
|
||||||
const nameSingular = data.nameSingular;
|
|
||||||
delete data.nameSingular;
|
|
||||||
const query = `
|
|
||||||
mutation create${capitalize(nameSingular)} {
|
|
||||||
create${capitalize(nameSingular)}(
|
|
||||||
data:{${handleQueryParams(data)}}
|
|
||||||
)
|
|
||||||
{id}
|
|
||||||
}`;
|
|
||||||
return await requestDb(z, bundle, query);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const createRecordKey = 'create_record';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
display: {
|
|
||||||
description: 'Create a Record in Twenty.',
|
|
||||||
hidden: false,
|
|
||||||
label: 'Create Record',
|
|
||||||
},
|
|
||||||
key: createRecordKey,
|
|
||||||
noun: 'Record',
|
|
||||||
operation: {
|
|
||||||
inputFields: [
|
|
||||||
{
|
|
||||||
key: 'nameSingular',
|
|
||||||
required: true,
|
|
||||||
label: 'Record Name',
|
|
||||||
dynamic: `${findObjectNamesSingularKey}.nameSingular`,
|
|
||||||
altersDynamicFields: true,
|
|
||||||
},
|
|
||||||
recordInputFields,
|
|
||||||
],
|
|
||||||
sample: {
|
|
||||||
id: '179ed459-79cf-41d9-ab85-96397fa8e936',
|
|
||||||
},
|
|
||||||
perform,
|
|
||||||
},
|
|
||||||
};
|
|
108
packages/twenty-zapier/src/creates/crud_record.ts
Normal file
108
packages/twenty-zapier/src/creates/crud_record.ts
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
import { Bundle, ZObject } from 'zapier-platform-core';
|
||||||
|
|
||||||
|
import { findObjectNamesSingularKey } from '../triggers/find_object_names_singular';
|
||||||
|
import { listRecordIdsKey } from '../triggers/list_record_ids';
|
||||||
|
import { capitalize } from '../utils/capitalize';
|
||||||
|
import { recordInputFields } from '../utils/creates/creates.utils';
|
||||||
|
import { InputData } from '../utils/data.types';
|
||||||
|
import handleQueryParams from '../utils/handleQueryParams';
|
||||||
|
import requestDb from '../utils/requestDb';
|
||||||
|
import { Operation } from '../utils/triggers/triggers.utils';
|
||||||
|
|
||||||
|
const computeFields = async (z: ZObject, bundle: Bundle) => {
|
||||||
|
const operation = bundle.inputData.crudZapierOperation;
|
||||||
|
switch (operation) {
|
||||||
|
case Operation.delete:
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
key: 'id',
|
||||||
|
label: 'Id',
|
||||||
|
type: 'string',
|
||||||
|
dynamic: `${listRecordIdsKey}.id`,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
case Operation.update:
|
||||||
|
return recordInputFields(z, bundle, true);
|
||||||
|
case Operation.create:
|
||||||
|
return recordInputFields(z, bundle, false);
|
||||||
|
default:
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const computeQueryParameters = (
|
||||||
|
operation: Operation,
|
||||||
|
data: InputData,
|
||||||
|
): string => {
|
||||||
|
switch (operation) {
|
||||||
|
case Operation.create:
|
||||||
|
return `data:{${handleQueryParams(data)}}`;
|
||||||
|
case Operation.update:
|
||||||
|
return `
|
||||||
|
data:{${handleQueryParams(data)}},
|
||||||
|
id: "${data.id}"
|
||||||
|
`;
|
||||||
|
case Operation.delete:
|
||||||
|
return `
|
||||||
|
id: "${data.id}"
|
||||||
|
`;
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const perform = async (z: ZObject, bundle: Bundle) => {
|
||||||
|
const data = bundle.inputData;
|
||||||
|
const operation = data.crudZapierOperation;
|
||||||
|
const nameSingular = data.nameSingular;
|
||||||
|
delete data.nameSingular;
|
||||||
|
delete data.crudZapierOperation;
|
||||||
|
const query = `
|
||||||
|
mutation ${operation}${capitalize(nameSingular)} {
|
||||||
|
${operation}${capitalize(nameSingular)}(
|
||||||
|
${computeQueryParameters(operation, data)}
|
||||||
|
)
|
||||||
|
{id}
|
||||||
|
}`;
|
||||||
|
return await requestDb(z, bundle, query);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const crudRecordKey = 'crud_record';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
display: {
|
||||||
|
description: 'Create, Update or Delete a Record in Twenty.',
|
||||||
|
hidden: false,
|
||||||
|
label: 'Create, Update or Delete Record',
|
||||||
|
},
|
||||||
|
key: crudRecordKey,
|
||||||
|
noun: 'Record',
|
||||||
|
operation: {
|
||||||
|
inputFields: [
|
||||||
|
{
|
||||||
|
key: 'nameSingular',
|
||||||
|
required: true,
|
||||||
|
label: 'Record Name',
|
||||||
|
dynamic: `${findObjectNamesSingularKey}.nameSingular`,
|
||||||
|
altersDynamicFields: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'crudZapierOperation',
|
||||||
|
required: true,
|
||||||
|
label: 'Operation',
|
||||||
|
choices: {
|
||||||
|
[Operation.create]: Operation.create,
|
||||||
|
[Operation.update]: Operation.update,
|
||||||
|
[Operation.delete]: Operation.delete,
|
||||||
|
},
|
||||||
|
altersDynamicFields: true,
|
||||||
|
},
|
||||||
|
computeFields,
|
||||||
|
],
|
||||||
|
sample: {
|
||||||
|
id: '179ed459-79cf-41d9-ab85-96397fa8e936',
|
||||||
|
},
|
||||||
|
perform,
|
||||||
|
},
|
||||||
|
};
|
@ -1,56 +0,0 @@
|
|||||||
import { Bundle, ZObject } from 'zapier-platform-core';
|
|
||||||
|
|
||||||
import { findObjectNamesPluralKey } from '../triggers/find_object_names_plural';
|
|
||||||
import { listRecordIdsKey } from '../triggers/list_record_ids';
|
|
||||||
import { capitalize } from '../utils/capitalize';
|
|
||||||
import requestDb from '../utils/requestDb';
|
|
||||||
|
|
||||||
export const deleteRecordKey = 'delete_record';
|
|
||||||
|
|
||||||
const perform = async (z: ZObject, bundle: Bundle) => {
|
|
||||||
const data = bundle.inputData;
|
|
||||||
const nameSingular = data.nameSingular;
|
|
||||||
const id = data.id;
|
|
||||||
delete data.nameSingular;
|
|
||||||
delete data.id;
|
|
||||||
const query = `
|
|
||||||
mutation delete${capitalize(nameSingular)} {
|
|
||||||
delete${capitalize(nameSingular)}(
|
|
||||||
id: "${id}"
|
|
||||||
)
|
|
||||||
{id}
|
|
||||||
}`;
|
|
||||||
return await requestDb(z, bundle, query);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default {
|
|
||||||
display: {
|
|
||||||
description: 'Delete a Record in Twenty.',
|
|
||||||
hidden: false,
|
|
||||||
label: 'Delete Record',
|
|
||||||
},
|
|
||||||
key: deleteRecordKey,
|
|
||||||
noun: 'Record',
|
|
||||||
operation: {
|
|
||||||
inputFields: [
|
|
||||||
{
|
|
||||||
key: 'namePlural',
|
|
||||||
label: 'Record Name',
|
|
||||||
dynamic: `${findObjectNamesPluralKey}.namePlural`,
|
|
||||||
required: true,
|
|
||||||
altersDynamicFields: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'id',
|
|
||||||
label: 'Id',
|
|
||||||
type: 'string',
|
|
||||||
dynamic: `${listRecordIdsKey}.id`,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
sample: {
|
|
||||||
id: '179ed459-79cf-41d9-ab85-96397fa8e936',
|
|
||||||
},
|
|
||||||
perform,
|
|
||||||
},
|
|
||||||
};
|
|
@ -1,56 +0,0 @@
|
|||||||
import { Bundle, ZObject } from 'zapier-platform-core';
|
|
||||||
|
|
||||||
import { findObjectNamesSingularKey } from '../triggers/find_object_names_singular';
|
|
||||||
import { capitalize } from '../utils/capitalize';
|
|
||||||
import { recordInputFields } from '../utils/creates/creates.utils';
|
|
||||||
import handleQueryParams from '../utils/handleQueryParams';
|
|
||||||
import requestDb from '../utils/requestDb';
|
|
||||||
|
|
||||||
export const updateRecordKey = 'update_record';
|
|
||||||
|
|
||||||
const perform = async (z: ZObject, bundle: Bundle) => {
|
|
||||||
const data = bundle.inputData;
|
|
||||||
const nameSingular = data.nameSingular;
|
|
||||||
const id = data.id;
|
|
||||||
delete data.nameSingular;
|
|
||||||
delete data.id;
|
|
||||||
const query = `
|
|
||||||
mutation update${capitalize(nameSingular)} {
|
|
||||||
update${capitalize(nameSingular)}(
|
|
||||||
data:{${handleQueryParams(data)}},
|
|
||||||
id: "${id}"
|
|
||||||
)
|
|
||||||
{id}
|
|
||||||
}`;
|
|
||||||
return await requestDb(z, bundle, query);
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateRecordInputFields = async (z: ZObject, bundle: Bundle) => {
|
|
||||||
return recordInputFields(z, bundle, true);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default {
|
|
||||||
display: {
|
|
||||||
description: 'Update a Record in Twenty.',
|
|
||||||
hidden: false,
|
|
||||||
label: 'Update Record',
|
|
||||||
},
|
|
||||||
key: updateRecordKey,
|
|
||||||
noun: 'Record',
|
|
||||||
operation: {
|
|
||||||
inputFields: [
|
|
||||||
{
|
|
||||||
key: 'nameSingular',
|
|
||||||
required: true,
|
|
||||||
label: 'Record Name',
|
|
||||||
dynamic: `${findObjectNamesSingularKey}.nameSingular`,
|
|
||||||
altersDynamicFields: true,
|
|
||||||
},
|
|
||||||
updateRecordInputFields,
|
|
||||||
],
|
|
||||||
sample: {
|
|
||||||
id: '179ed459-79cf-41d9-ab85-96397fa8e936',
|
|
||||||
},
|
|
||||||
perform,
|
|
||||||
},
|
|
||||||
};
|
|
@ -4,25 +4,12 @@ import 'dotenv/config';
|
|||||||
|
|
||||||
const { version } = require('../package.json');
|
const { version } = require('../package.json');
|
||||||
|
|
||||||
import createRecord, { createRecordKey } from './creates/create_record';
|
import crudRecord, { crudRecordKey } from './creates/crud_record';
|
||||||
import deleteRecord, { deleteRecordKey } from './creates/delete_record';
|
|
||||||
import updateRecord, { updateRecordKey } from './creates/update_record';
|
|
||||||
import findObjectNamesPlural, {
|
|
||||||
findObjectNamesPluralKey,
|
|
||||||
} from './triggers/find_object_names_plural';
|
|
||||||
import findObjectNamesSingular, {
|
import findObjectNamesSingular, {
|
||||||
findObjectNamesSingularKey,
|
findObjectNamesSingularKey,
|
||||||
} from './triggers/find_object_names_singular';
|
} from './triggers/find_object_names_singular';
|
||||||
import listRecordIds, { listRecordIdsKey } from './triggers/list_record_ids';
|
import listRecordIds, { listRecordIdsKey } from './triggers/list_record_ids';
|
||||||
import triggerRecordCreated, {
|
import triggerRecord, { triggerRecordKey } from './triggers/trigger_record';
|
||||||
triggerRecordCreatedKey,
|
|
||||||
} from './triggers/trigger_record_created';
|
|
||||||
import triggerRecordDeleted, {
|
|
||||||
triggerRecordDeletedKey,
|
|
||||||
} from './triggers/trigger_record_deleted';
|
|
||||||
import triggerRecordUpdated, {
|
|
||||||
triggerRecordUpdatedKey,
|
|
||||||
} from './triggers/trigger_record_updated';
|
|
||||||
import authentication from './authentication';
|
import authentication from './authentication';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -31,15 +18,10 @@ export default {
|
|||||||
authentication: authentication,
|
authentication: authentication,
|
||||||
triggers: {
|
triggers: {
|
||||||
[findObjectNamesSingularKey]: findObjectNamesSingular,
|
[findObjectNamesSingularKey]: findObjectNamesSingular,
|
||||||
[findObjectNamesPluralKey]: findObjectNamesPlural,
|
|
||||||
[listRecordIdsKey]: listRecordIds,
|
[listRecordIdsKey]: listRecordIds,
|
||||||
[triggerRecordCreatedKey]: triggerRecordCreated,
|
[triggerRecordKey]: triggerRecord,
|
||||||
[triggerRecordUpdatedKey]: triggerRecordUpdated,
|
|
||||||
[triggerRecordDeletedKey]: triggerRecordDeleted,
|
|
||||||
},
|
},
|
||||||
creates: {
|
creates: {
|
||||||
[createRecordKey]: createRecord,
|
[crudRecordKey]: crudRecord,
|
||||||
[updateRecordKey]: updateRecord,
|
|
||||||
[deleteRecordKey]: deleteRecord,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,70 +0,0 @@
|
|||||||
import { Bundle, createAppTester, tools, ZObject } from 'zapier-platform-core';
|
|
||||||
|
|
||||||
import { createRecordKey } from '../../creates/create_record';
|
|
||||||
import App from '../../index';
|
|
||||||
import getBundle from '../../utils/getBundle';
|
|
||||||
import requestDb from '../../utils/requestDb';
|
|
||||||
const appTester = createAppTester(App);
|
|
||||||
tools.env.inject();
|
|
||||||
|
|
||||||
describe('creates.create_company', () => {
|
|
||||||
test('should run to create a Company Record', async () => {
|
|
||||||
const bundle = getBundle({
|
|
||||||
nameSingular: 'Company',
|
|
||||||
name: 'Company Name',
|
|
||||||
address: 'Company Address',
|
|
||||||
domainName: 'Company Domain Name',
|
|
||||||
linkedinLink: { url: '/linkedin_url', label: 'Test linkedinUrl' },
|
|
||||||
xLink: { url: '/x_url', label: 'Test xUrl' },
|
|
||||||
annualRecurringRevenue: {
|
|
||||||
amountMicros: 100000000000,
|
|
||||||
currencyCode: 'USD',
|
|
||||||
},
|
|
||||||
idealCustomerProfile: true,
|
|
||||||
employees: 25,
|
|
||||||
});
|
|
||||||
const result = await appTester(
|
|
||||||
App.creates[createRecordKey].operation.perform,
|
|
||||||
bundle,
|
|
||||||
);
|
|
||||||
expect(result).toBeDefined();
|
|
||||||
expect(result.data?.createCompany?.id).toBeDefined();
|
|
||||||
const checkDbResult = await appTester(
|
|
||||||
(z: ZObject, bundle: Bundle) =>
|
|
||||||
requestDb(
|
|
||||||
z,
|
|
||||||
bundle,
|
|
||||||
`query findCompany {company(filter: {id: {eq: "${result.data.createCompany.id}"}}){id annualRecurringRevenue{amountMicros currencyCode}}}`,
|
|
||||||
),
|
|
||||||
bundle,
|
|
||||||
);
|
|
||||||
expect(
|
|
||||||
checkDbResult.data.company.annualRecurringRevenue.amountMicros,
|
|
||||||
).toEqual(100000000000);
|
|
||||||
});
|
|
||||||
test('should run to create a Person Record', async () => {
|
|
||||||
const bundle = getBundle({
|
|
||||||
nameSingular: 'Person',
|
|
||||||
name: { firstName: 'John', lastName: 'Doe' },
|
|
||||||
email: 'johndoe@gmail.com',
|
|
||||||
phone: '+33610203040',
|
|
||||||
city: 'Paris',
|
|
||||||
});
|
|
||||||
const result = await appTester(
|
|
||||||
App.creates[createRecordKey].operation.perform,
|
|
||||||
bundle,
|
|
||||||
);
|
|
||||||
expect(result).toBeDefined();
|
|
||||||
expect(result.data?.createPerson?.id).toBeDefined();
|
|
||||||
const checkDbResult = await appTester(
|
|
||||||
(z: ZObject, bundle: Bundle) =>
|
|
||||||
requestDb(
|
|
||||||
z,
|
|
||||||
bundle,
|
|
||||||
`query findPerson {person(filter: {id: {eq: "${result.data.createPerson.id}"}}){phone}}`,
|
|
||||||
),
|
|
||||||
bundle,
|
|
||||||
);
|
|
||||||
expect(checkDbResult.data.person.phone).toEqual('+33610203040');
|
|
||||||
});
|
|
||||||
});
|
|
158
packages/twenty-zapier/src/test/creates/crud_record.test.ts
Normal file
158
packages/twenty-zapier/src/test/creates/crud_record.test.ts
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
import { Bundle, createAppTester, tools, ZObject } from 'zapier-platform-core';
|
||||||
|
|
||||||
|
import { crudRecordKey } from '../../creates/crud_record';
|
||||||
|
import App from '../../index';
|
||||||
|
import getBundle from '../../utils/getBundle';
|
||||||
|
import requestDb from '../../utils/requestDb';
|
||||||
|
import { Operation } from '../../utils/triggers/triggers.utils';
|
||||||
|
const appTester = createAppTester(App);
|
||||||
|
tools.env.inject();
|
||||||
|
|
||||||
|
describe('creates.create_company', () => {
|
||||||
|
test('should run to create a Company Record', async () => {
|
||||||
|
const bundle = getBundle({
|
||||||
|
nameSingular: 'Company',
|
||||||
|
crudZapierOperation: Operation.create,
|
||||||
|
name: 'Company Name',
|
||||||
|
address: 'Company Address',
|
||||||
|
domainName: 'Company Domain Name',
|
||||||
|
linkedinLink: { url: '/linkedin_url', label: 'Test linkedinUrl' },
|
||||||
|
xLink: { url: '/x_url', label: 'Test xUrl' },
|
||||||
|
annualRecurringRevenue: {
|
||||||
|
amountMicros: 100000000000,
|
||||||
|
currencyCode: 'USD',
|
||||||
|
},
|
||||||
|
idealCustomerProfile: true,
|
||||||
|
employees: 25,
|
||||||
|
});
|
||||||
|
const result = await appTester(
|
||||||
|
App.creates[crudRecordKey].operation.perform,
|
||||||
|
bundle,
|
||||||
|
);
|
||||||
|
expect(result).toBeDefined();
|
||||||
|
expect(result.data?.createCompany?.id).toBeDefined();
|
||||||
|
const checkDbResult = await appTester(
|
||||||
|
(z: ZObject, bundle: Bundle) =>
|
||||||
|
requestDb(
|
||||||
|
z,
|
||||||
|
bundle,
|
||||||
|
`query findCompany {company(filter: {id: {eq: "${result.data.createCompany.id}"}}){id annualRecurringRevenue{amountMicros currencyCode}}}`,
|
||||||
|
),
|
||||||
|
bundle,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
checkDbResult.data.company.annualRecurringRevenue.amountMicros,
|
||||||
|
).toEqual(100000000000);
|
||||||
|
});
|
||||||
|
test('should run to create a Person Record', async () => {
|
||||||
|
const bundle = getBundle({
|
||||||
|
nameSingular: 'Person',
|
||||||
|
crudZapierOperation: Operation.create,
|
||||||
|
name: { firstName: 'John', lastName: 'Doe' },
|
||||||
|
email: 'johndoe@gmail.com',
|
||||||
|
phone: '+33610203040',
|
||||||
|
city: 'Paris',
|
||||||
|
});
|
||||||
|
const result = await appTester(
|
||||||
|
App.creates[crudRecordKey].operation.perform,
|
||||||
|
bundle,
|
||||||
|
);
|
||||||
|
expect(result).toBeDefined();
|
||||||
|
expect(result.data?.createPerson?.id).toBeDefined();
|
||||||
|
const checkDbResult = await appTester(
|
||||||
|
(z: ZObject, bundle: Bundle) =>
|
||||||
|
requestDb(
|
||||||
|
z,
|
||||||
|
bundle,
|
||||||
|
`query findPerson {person(filter: {id: {eq: "${result.data.createPerson.id}"}}){phone}}`,
|
||||||
|
),
|
||||||
|
bundle,
|
||||||
|
);
|
||||||
|
expect(checkDbResult.data.person.phone).toEqual('+33610203040');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('creates.update_company', () => {
|
||||||
|
test('should run to update a Company record', async () => {
|
||||||
|
const createBundle = getBundle({
|
||||||
|
nameSingular: 'Company',
|
||||||
|
crudZapierOperation: Operation.create,
|
||||||
|
name: 'Company Name',
|
||||||
|
employees: 25,
|
||||||
|
});
|
||||||
|
|
||||||
|
const createResult = await appTester(
|
||||||
|
App.creates[crudRecordKey].operation.perform,
|
||||||
|
createBundle,
|
||||||
|
);
|
||||||
|
|
||||||
|
const companyId = createResult.data?.createCompany?.id;
|
||||||
|
|
||||||
|
const updateBundle = getBundle({
|
||||||
|
nameSingular: 'Company',
|
||||||
|
crudZapierOperation: Operation.update,
|
||||||
|
id: companyId,
|
||||||
|
name: 'Updated Company Name',
|
||||||
|
});
|
||||||
|
|
||||||
|
const updateResult = await appTester(
|
||||||
|
App.creates[crudRecordKey].operation.perform,
|
||||||
|
updateBundle,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(updateResult).toBeDefined();
|
||||||
|
expect(updateResult.data?.updateCompany?.id).toBeDefined();
|
||||||
|
const checkDbResult = await appTester(
|
||||||
|
(z: ZObject, bundle: Bundle) =>
|
||||||
|
requestDb(
|
||||||
|
z,
|
||||||
|
bundle,
|
||||||
|
`query findCompany {company(filter: {id: {eq: "${companyId}"}}){id name}}`,
|
||||||
|
),
|
||||||
|
updateBundle,
|
||||||
|
);
|
||||||
|
expect(checkDbResult.data.company.name).toEqual('Updated Company Name');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('creates.delete_company', () => {
|
||||||
|
test('should run to delete a Company record', async () => {
|
||||||
|
const createBundle = getBundle({
|
||||||
|
nameSingular: 'Company',
|
||||||
|
crudZapierOperation: Operation.create,
|
||||||
|
name: 'Delete Company Name',
|
||||||
|
employees: 25,
|
||||||
|
});
|
||||||
|
|
||||||
|
const createResult = await appTester(
|
||||||
|
App.creates[crudRecordKey].operation.perform,
|
||||||
|
createBundle,
|
||||||
|
);
|
||||||
|
|
||||||
|
const companyId = createResult.data?.createCompany?.id;
|
||||||
|
|
||||||
|
const deleteBundle = getBundle({
|
||||||
|
nameSingular: 'Company',
|
||||||
|
crudZapierOperation: Operation.delete,
|
||||||
|
id: companyId,
|
||||||
|
});
|
||||||
|
|
||||||
|
const deleteResult = await appTester(
|
||||||
|
App.creates[crudRecordKey].operation.perform,
|
||||||
|
deleteBundle,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(deleteResult).toBeDefined();
|
||||||
|
expect(deleteResult.data?.deleteCompany?.id).toBeDefined();
|
||||||
|
const checkDbResult = await appTester(
|
||||||
|
(z: ZObject, bundle: Bundle) =>
|
||||||
|
requestDb(
|
||||||
|
z,
|
||||||
|
bundle,
|
||||||
|
`query findCompanies {companies(filter: {id: {eq: "${companyId}"}}){edges{node{id}}}}`,
|
||||||
|
),
|
||||||
|
deleteBundle,
|
||||||
|
);
|
||||||
|
expect(checkDbResult.data.companies.edges.length).toEqual(0);
|
||||||
|
});
|
||||||
|
});
|
@ -1,49 +0,0 @@
|
|||||||
import { Bundle, createAppTester, tools, ZObject } from 'zapier-platform-core';
|
|
||||||
|
|
||||||
import { createRecordKey } from '../../creates/create_record';
|
|
||||||
import { deleteRecordKey } from '../../creates/delete_record';
|
|
||||||
import App from '../../index';
|
|
||||||
import getBundle from '../../utils/getBundle';
|
|
||||||
import requestDb from '../../utils/requestDb';
|
|
||||||
const appTester = createAppTester(App);
|
|
||||||
|
|
||||||
tools.env.inject();
|
|
||||||
describe('creates.delete_company', () => {
|
|
||||||
test('should run to delete a Company record', async () => {
|
|
||||||
const createBundle = getBundle({
|
|
||||||
nameSingular: 'Company',
|
|
||||||
name: 'Delete Company Name',
|
|
||||||
employees: 25,
|
|
||||||
});
|
|
||||||
|
|
||||||
const createResult = await appTester(
|
|
||||||
App.creates[createRecordKey].operation.perform,
|
|
||||||
createBundle,
|
|
||||||
);
|
|
||||||
|
|
||||||
const companyId = createResult.data?.createCompany?.id;
|
|
||||||
|
|
||||||
const deleteBundle = getBundle({
|
|
||||||
nameSingular: 'Company',
|
|
||||||
id: companyId,
|
|
||||||
});
|
|
||||||
|
|
||||||
const deleteResult = await appTester(
|
|
||||||
App.creates[deleteRecordKey].operation.perform,
|
|
||||||
deleteBundle,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(deleteResult).toBeDefined();
|
|
||||||
expect(deleteResult.data?.deleteCompany?.id).toBeDefined();
|
|
||||||
const checkDbResult = await appTester(
|
|
||||||
(z: ZObject, bundle: Bundle) =>
|
|
||||||
requestDb(
|
|
||||||
z,
|
|
||||||
bundle,
|
|
||||||
`query findCompanies {companies(filter: {id: {eq: "${companyId}"}}){edges{node{id}}}}`,
|
|
||||||
),
|
|
||||||
deleteBundle,
|
|
||||||
);
|
|
||||||
expect(checkDbResult.data.companies.edges.length).toEqual(0);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,50 +0,0 @@
|
|||||||
import { Bundle, createAppTester, tools, ZObject } from 'zapier-platform-core';
|
|
||||||
|
|
||||||
import { createRecordKey } from '../../creates/create_record';
|
|
||||||
import { updateRecordKey } from '../../creates/update_record';
|
|
||||||
import App from '../../index';
|
|
||||||
import getBundle from '../../utils/getBundle';
|
|
||||||
import requestDb from '../../utils/requestDb';
|
|
||||||
const appTester = createAppTester(App);
|
|
||||||
|
|
||||||
tools.env.inject();
|
|
||||||
describe('creates.update_company', () => {
|
|
||||||
test('should run to update a Company record', async () => {
|
|
||||||
const createBundle = getBundle({
|
|
||||||
nameSingular: 'Company',
|
|
||||||
name: 'Company Name',
|
|
||||||
employees: 25,
|
|
||||||
});
|
|
||||||
|
|
||||||
const createResult = await appTester(
|
|
||||||
App.creates[createRecordKey].operation.perform,
|
|
||||||
createBundle,
|
|
||||||
);
|
|
||||||
|
|
||||||
const companyId = createResult.data?.createCompany?.id;
|
|
||||||
|
|
||||||
const updateBundle = getBundle({
|
|
||||||
nameSingular: 'Company',
|
|
||||||
id: companyId,
|
|
||||||
name: 'Updated Company Name',
|
|
||||||
});
|
|
||||||
|
|
||||||
const updateResult = await appTester(
|
|
||||||
App.creates[updateRecordKey].operation.perform,
|
|
||||||
updateBundle,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(updateResult).toBeDefined();
|
|
||||||
expect(updateResult.data?.updateCompany?.id).toBeDefined();
|
|
||||||
const checkDbResult = await appTester(
|
|
||||||
(z: ZObject, bundle: Bundle) =>
|
|
||||||
requestDb(
|
|
||||||
z,
|
|
||||||
bundle,
|
|
||||||
`query findCompany {company(filter: {id: {eq: "${companyId}"}}){id name}}`,
|
|
||||||
),
|
|
||||||
updateBundle,
|
|
||||||
);
|
|
||||||
expect(checkDbResult.data.company.name).toEqual('Updated Company Name');
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,19 +0,0 @@
|
|||||||
import { createAppTester, tools } from 'zapier-platform-core';
|
|
||||||
import getBundle from '../../utils/getBundle';
|
|
||||||
import App from '../../index';
|
|
||||||
import { findObjectNamesPluralKey } from '../../triggers/find_object_names_plural';
|
|
||||||
tools.env.inject();
|
|
||||||
|
|
||||||
const appTester = createAppTester(App);
|
|
||||||
describe('triggers.find_object_names_plural', () => {
|
|
||||||
test('should run', async () => {
|
|
||||||
const bundle = getBundle({});
|
|
||||||
const result = await appTester(
|
|
||||||
App.triggers[findObjectNamesPluralKey].operation.perform,
|
|
||||||
bundle,
|
|
||||||
);
|
|
||||||
expect(result).toBeDefined();
|
|
||||||
expect(result.length).toBeGreaterThan(1);
|
|
||||||
expect(result[0].namePlural).toBeDefined();
|
|
||||||
});
|
|
||||||
});
|
|
@ -8,7 +8,7 @@ tools.env.inject();
|
|||||||
const appTester = createAppTester(App);
|
const appTester = createAppTester(App);
|
||||||
describe('triggers.list_record_ids', () => {
|
describe('triggers.list_record_ids', () => {
|
||||||
test('should run', async () => {
|
test('should run', async () => {
|
||||||
const bundle = getBundle({ namePlural: 'companies' });
|
const bundle = getBundle({ nameSingular: 'company' });
|
||||||
const result = await appTester(
|
const result = await appTester(
|
||||||
App.triggers[listRecordIdsKey].operation.perform,
|
App.triggers[listRecordIdsKey].operation.perform,
|
||||||
bundle,
|
bundle,
|
||||||
|
235
packages/twenty-zapier/src/test/triggers/trigger_record.test.ts
Normal file
235
packages/twenty-zapier/src/test/triggers/trigger_record.test.ts
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
import { Bundle, createAppTester, ZObject } from 'zapier-platform-core';
|
||||||
|
|
||||||
|
import App from '../../index';
|
||||||
|
import { triggerRecordKey } from '../../triggers/trigger_record';
|
||||||
|
import getBundle from '../../utils/getBundle';
|
||||||
|
import requestDb from '../../utils/requestDb';
|
||||||
|
const appTester = createAppTester(App);
|
||||||
|
|
||||||
|
describe('triggers.trigger_record.created', () => {
|
||||||
|
test('should succeed to subscribe', async () => {
|
||||||
|
const bundle = getBundle({});
|
||||||
|
bundle.inputData.nameSingular = 'company';
|
||||||
|
bundle.inputData.operation = 'create';
|
||||||
|
bundle.targetUrl = 'https://test.com';
|
||||||
|
const result = await appTester(
|
||||||
|
App.triggers[triggerRecordKey].operation.performSubscribe,
|
||||||
|
bundle,
|
||||||
|
);
|
||||||
|
expect(result).toBeDefined();
|
||||||
|
expect(result.id).toBeDefined();
|
||||||
|
const checkDbResult = await appTester(
|
||||||
|
(z: ZObject, bundle: Bundle) =>
|
||||||
|
requestDb(
|
||||||
|
z,
|
||||||
|
bundle,
|
||||||
|
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operation}}}}`,
|
||||||
|
),
|
||||||
|
bundle,
|
||||||
|
);
|
||||||
|
expect(checkDbResult.data.webhooks.edges[0].node.operation).toEqual(
|
||||||
|
'create.company',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
test('should succeed to unsubscribe', async () => {
|
||||||
|
const bundle = getBundle({});
|
||||||
|
bundle.inputData.nameSingular = 'company';
|
||||||
|
bundle.inputData.operation = 'create';
|
||||||
|
bundle.targetUrl = 'https://test.com';
|
||||||
|
const result = await appTester(
|
||||||
|
App.triggers[triggerRecordKey].operation.performSubscribe,
|
||||||
|
bundle,
|
||||||
|
);
|
||||||
|
const unsubscribeBundle = getBundle({});
|
||||||
|
unsubscribeBundle.subscribeData = { id: result.id };
|
||||||
|
const unsubscribeResult = await appTester(
|
||||||
|
App.triggers[triggerRecordKey].operation.performUnsubscribe,
|
||||||
|
unsubscribeBundle,
|
||||||
|
);
|
||||||
|
expect(unsubscribeResult).toBeDefined();
|
||||||
|
expect(unsubscribeResult.id).toEqual(result.id);
|
||||||
|
const checkDbResult = await appTester(
|
||||||
|
(z: ZObject, bundle: Bundle) =>
|
||||||
|
requestDb(
|
||||||
|
z,
|
||||||
|
bundle,
|
||||||
|
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operation}}}}`,
|
||||||
|
),
|
||||||
|
bundle,
|
||||||
|
);
|
||||||
|
expect(checkDbResult.data.webhooks.edges.length).toEqual(0);
|
||||||
|
});
|
||||||
|
test('should load company from webhook', async () => {
|
||||||
|
const bundle = {
|
||||||
|
cleanedRequest: {
|
||||||
|
record: {
|
||||||
|
id: 'd6ccb1d1-a90b-4822-a992-a0dd946592c9',
|
||||||
|
name: '',
|
||||||
|
domainName: '',
|
||||||
|
createdAt: '2023-10-19 10:10:12.490',
|
||||||
|
address: '',
|
||||||
|
employees: null,
|
||||||
|
linkedinUrl: null,
|
||||||
|
xUrl: null,
|
||||||
|
annualRecurringRevenue: null,
|
||||||
|
idealCustomerProfile: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const results = await appTester(
|
||||||
|
App.triggers[triggerRecordKey].operation.perform,
|
||||||
|
bundle,
|
||||||
|
);
|
||||||
|
expect(results.length).toEqual(1);
|
||||||
|
const company = results[0];
|
||||||
|
expect(company.id).toEqual('d6ccb1d1-a90b-4822-a992-a0dd946592c9');
|
||||||
|
});
|
||||||
|
it('should load companies from list', async () => {
|
||||||
|
const bundle = getBundle({});
|
||||||
|
bundle.inputData.nameSingular = 'company';
|
||||||
|
bundle.inputData.operation = 'create';
|
||||||
|
const results = await appTester(
|
||||||
|
App.triggers[triggerRecordKey].operation.performList,
|
||||||
|
bundle,
|
||||||
|
);
|
||||||
|
expect(results.length).toBeGreaterThan(1);
|
||||||
|
const firstCompany = results[0];
|
||||||
|
expect(firstCompany).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('triggers.trigger_record.update', () => {
|
||||||
|
test('should succeed to subscribe', async () => {
|
||||||
|
const bundle = getBundle({});
|
||||||
|
bundle.inputData.nameSingular = 'company';
|
||||||
|
bundle.inputData.operation = 'update';
|
||||||
|
bundle.targetUrl = 'https://test.com';
|
||||||
|
const result = await appTester(
|
||||||
|
App.triggers[triggerRecordKey].operation.performSubscribe,
|
||||||
|
bundle,
|
||||||
|
);
|
||||||
|
expect(result).toBeDefined();
|
||||||
|
expect(result.id).toBeDefined();
|
||||||
|
const checkDbResult = await appTester(
|
||||||
|
(z: ZObject, bundle: Bundle) =>
|
||||||
|
requestDb(
|
||||||
|
z,
|
||||||
|
bundle,
|
||||||
|
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operation}}}}`,
|
||||||
|
),
|
||||||
|
bundle,
|
||||||
|
);
|
||||||
|
expect(checkDbResult.data.webhooks.edges[0].node.operation).toEqual(
|
||||||
|
'update.company',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
test('should succeed to unsubscribe', async () => {
|
||||||
|
const bundle = getBundle({});
|
||||||
|
bundle.inputData.nameSingular = 'company';
|
||||||
|
bundle.inputData.operation = 'update';
|
||||||
|
bundle.targetUrl = 'https://test.com';
|
||||||
|
const result = await appTester(
|
||||||
|
App.triggers[triggerRecordKey].operation.performSubscribe,
|
||||||
|
bundle,
|
||||||
|
);
|
||||||
|
const unsubscribeBundle = getBundle({});
|
||||||
|
unsubscribeBundle.subscribeData = { id: result.id };
|
||||||
|
const unsubscribeResult = await appTester(
|
||||||
|
App.triggers[triggerRecordKey].operation.performUnsubscribe,
|
||||||
|
unsubscribeBundle,
|
||||||
|
);
|
||||||
|
expect(unsubscribeResult).toBeDefined();
|
||||||
|
expect(unsubscribeResult.id).toEqual(result.id);
|
||||||
|
const checkDbResult = await appTester(
|
||||||
|
(z: ZObject, bundle: Bundle) =>
|
||||||
|
requestDb(
|
||||||
|
z,
|
||||||
|
bundle,
|
||||||
|
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operation}}}}`,
|
||||||
|
),
|
||||||
|
bundle,
|
||||||
|
);
|
||||||
|
expect(checkDbResult.data.webhooks.edges.length).toEqual(0);
|
||||||
|
});
|
||||||
|
it('should load companies from list', async () => {
|
||||||
|
const bundle = getBundle({});
|
||||||
|
bundle.inputData.nameSingular = 'company';
|
||||||
|
bundle.inputData.operation = 'update';
|
||||||
|
const results = await appTester(
|
||||||
|
App.triggers[triggerRecordKey].operation.performList,
|
||||||
|
bundle,
|
||||||
|
);
|
||||||
|
expect(results.length).toBeGreaterThan(1);
|
||||||
|
const firstCompany = results[0];
|
||||||
|
expect(firstCompany).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('triggers.trigger_record.delete', () => {
|
||||||
|
test('should succeed to subscribe', async () => {
|
||||||
|
const bundle = getBundle({});
|
||||||
|
bundle.inputData.nameSingular = 'company';
|
||||||
|
bundle.inputData.operation = 'delete';
|
||||||
|
bundle.targetUrl = 'https://test.com';
|
||||||
|
const result = await appTester(
|
||||||
|
App.triggers[triggerRecordKey].operation.performSubscribe,
|
||||||
|
bundle,
|
||||||
|
);
|
||||||
|
expect(result).toBeDefined();
|
||||||
|
expect(result.id).toBeDefined();
|
||||||
|
const checkDbResult = await appTester(
|
||||||
|
(z: ZObject, bundle: Bundle) =>
|
||||||
|
requestDb(
|
||||||
|
z,
|
||||||
|
bundle,
|
||||||
|
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operation}}}}`,
|
||||||
|
),
|
||||||
|
bundle,
|
||||||
|
);
|
||||||
|
expect(checkDbResult.data.webhooks.edges[0].node.operation).toEqual(
|
||||||
|
'delete.company',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
test('should succeed to unsubscribe', async () => {
|
||||||
|
const bundle = getBundle({});
|
||||||
|
bundle.inputData.nameSingular = 'company';
|
||||||
|
bundle.inputData.operation = 'delete';
|
||||||
|
bundle.targetUrl = 'https://test.com';
|
||||||
|
const result = await appTester(
|
||||||
|
App.triggers[triggerRecordKey].operation.performSubscribe,
|
||||||
|
bundle,
|
||||||
|
);
|
||||||
|
const unsubscribeBundle = getBundle({});
|
||||||
|
unsubscribeBundle.subscribeData = { id: result.id };
|
||||||
|
const unsubscribeResult = await appTester(
|
||||||
|
App.triggers[triggerRecordKey].operation.performUnsubscribe,
|
||||||
|
unsubscribeBundle,
|
||||||
|
);
|
||||||
|
expect(unsubscribeResult).toBeDefined();
|
||||||
|
expect(unsubscribeResult.id).toEqual(result.id);
|
||||||
|
const checkDbResult = await appTester(
|
||||||
|
(z: ZObject, bundle: Bundle) =>
|
||||||
|
requestDb(
|
||||||
|
z,
|
||||||
|
bundle,
|
||||||
|
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operation}}}}`,
|
||||||
|
),
|
||||||
|
bundle,
|
||||||
|
);
|
||||||
|
expect(checkDbResult.data.webhooks.edges.length).toEqual(0);
|
||||||
|
});
|
||||||
|
it('should load companies from list', async () => {
|
||||||
|
const bundle = getBundle({});
|
||||||
|
bundle.inputData.nameSingular = 'company';
|
||||||
|
bundle.inputData.operation = 'delete';
|
||||||
|
const results = await appTester(
|
||||||
|
App.triggers[triggerRecordKey].operation.performList,
|
||||||
|
bundle,
|
||||||
|
);
|
||||||
|
expect(results.length).toBeGreaterThan(1);
|
||||||
|
const firstCompany = results[0];
|
||||||
|
expect(firstCompany).toBeDefined();
|
||||||
|
expect(firstCompany.id).toBeDefined();
|
||||||
|
expect(Object.keys(firstCompany).length).toEqual(1);
|
||||||
|
});
|
||||||
|
});
|
@ -1,93 +0,0 @@
|
|||||||
import { Bundle, createAppTester, ZObject } from 'zapier-platform-core';
|
|
||||||
import App from '../../index';
|
|
||||||
import getBundle from '../../utils/getBundle';
|
|
||||||
import requestDb from '../../utils/requestDb';
|
|
||||||
import { triggerRecordCreatedKey } from '../../triggers/trigger_record_created';
|
|
||||||
const appTester = createAppTester(App);
|
|
||||||
|
|
||||||
describe('triggers.trigger_record_created', () => {
|
|
||||||
test('should succeed to subscribe', async () => {
|
|
||||||
const bundle = getBundle({});
|
|
||||||
bundle.inputData.namePlural = 'companies';
|
|
||||||
bundle.targetUrl = 'https://test.com';
|
|
||||||
const result = await appTester(
|
|
||||||
App.triggers[triggerRecordCreatedKey].operation.performSubscribe,
|
|
||||||
bundle,
|
|
||||||
);
|
|
||||||
expect(result).toBeDefined();
|
|
||||||
expect(result.id).toBeDefined();
|
|
||||||
const checkDbResult = await appTester(
|
|
||||||
(z: ZObject, bundle: Bundle) =>
|
|
||||||
requestDb(
|
|
||||||
z,
|
|
||||||
bundle,
|
|
||||||
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operation}}}}`,
|
|
||||||
),
|
|
||||||
bundle,
|
|
||||||
);
|
|
||||||
expect(checkDbResult.data.webhooks.edges[0].node.operation).toEqual(
|
|
||||||
'create.companies',
|
|
||||||
);
|
|
||||||
});
|
|
||||||
test('should succeed to unsubscribe', async () => {
|
|
||||||
const bundle = getBundle({});
|
|
||||||
bundle.inputData.namePlural = 'companies';
|
|
||||||
bundle.targetUrl = 'https://test.com';
|
|
||||||
const result = await appTester(
|
|
||||||
App.triggers[triggerRecordCreatedKey].operation.performSubscribe,
|
|
||||||
bundle,
|
|
||||||
);
|
|
||||||
const unsubscribeBundle = getBundle({});
|
|
||||||
unsubscribeBundle.subscribeData = { id: result.id };
|
|
||||||
const unsubscribeResult = await appTester(
|
|
||||||
App.triggers[triggerRecordCreatedKey].operation.performUnsubscribe,
|
|
||||||
unsubscribeBundle,
|
|
||||||
);
|
|
||||||
expect(unsubscribeResult).toBeDefined();
|
|
||||||
expect(unsubscribeResult.id).toEqual(result.id);
|
|
||||||
const checkDbResult = await appTester(
|
|
||||||
(z: ZObject, bundle: Bundle) =>
|
|
||||||
requestDb(
|
|
||||||
z,
|
|
||||||
bundle,
|
|
||||||
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operation}}}}`,
|
|
||||||
),
|
|
||||||
bundle,
|
|
||||||
);
|
|
||||||
expect(checkDbResult.data.webhooks.edges.length).toEqual(0);
|
|
||||||
});
|
|
||||||
test('should load company from webhook', async () => {
|
|
||||||
const bundle = {
|
|
||||||
cleanedRequest: {
|
|
||||||
id: 'd6ccb1d1-a90b-4822-a992-a0dd946592c9',
|
|
||||||
name: '',
|
|
||||||
domainName: '',
|
|
||||||
createdAt: '2023-10-19 10:10:12.490',
|
|
||||||
address: '',
|
|
||||||
employees: null,
|
|
||||||
linkedinUrl: null,
|
|
||||||
xUrl: null,
|
|
||||||
annualRecurringRevenue: null,
|
|
||||||
idealCustomerProfile: false,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const results = await appTester(
|
|
||||||
App.triggers[triggerRecordCreatedKey].operation.perform,
|
|
||||||
bundle,
|
|
||||||
);
|
|
||||||
expect(results.length).toEqual(1);
|
|
||||||
const company = results[0];
|
|
||||||
expect(company.id).toEqual('d6ccb1d1-a90b-4822-a992-a0dd946592c9');
|
|
||||||
});
|
|
||||||
it('should load companies from list', async () => {
|
|
||||||
const bundle = getBundle({});
|
|
||||||
bundle.inputData.namePlural = 'companies';
|
|
||||||
const results = await appTester(
|
|
||||||
App.triggers[triggerRecordCreatedKey].operation.performList,
|
|
||||||
bundle,
|
|
||||||
);
|
|
||||||
expect(results.length).toBeGreaterThan(1);
|
|
||||||
const firstCompany = results[0];
|
|
||||||
expect(firstCompany).toBeDefined();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,95 +0,0 @@
|
|||||||
import { Bundle, createAppTester, ZObject } from 'zapier-platform-core';
|
|
||||||
import App from '../../index';
|
|
||||||
import getBundle from '../../utils/getBundle';
|
|
||||||
import requestDb from '../../utils/requestDb';
|
|
||||||
import { triggerRecordDeletedKey } from '../../triggers/trigger_record_deleted';
|
|
||||||
const appTester = createAppTester(App);
|
|
||||||
|
|
||||||
describe('triggers.trigger_record_deleted', () => {
|
|
||||||
test('should succeed to subscribe', async () => {
|
|
||||||
const bundle = getBundle({});
|
|
||||||
bundle.inputData.namePlural = 'companies';
|
|
||||||
bundle.targetUrl = 'https://test.com';
|
|
||||||
const result = await appTester(
|
|
||||||
App.triggers[triggerRecordDeletedKey].operation.performSubscribe,
|
|
||||||
bundle,
|
|
||||||
);
|
|
||||||
expect(result).toBeDefined();
|
|
||||||
expect(result.id).toBeDefined();
|
|
||||||
const checkDbResult = await appTester(
|
|
||||||
(z: ZObject, bundle: Bundle) =>
|
|
||||||
requestDb(
|
|
||||||
z,
|
|
||||||
bundle,
|
|
||||||
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operation}}}}`,
|
|
||||||
),
|
|
||||||
bundle,
|
|
||||||
);
|
|
||||||
expect(checkDbResult.data.webhooks.edges[0].node.operation).toEqual(
|
|
||||||
'delete.companies',
|
|
||||||
);
|
|
||||||
});
|
|
||||||
test('should succeed to unsubscribe', async () => {
|
|
||||||
const bundle = getBundle({});
|
|
||||||
bundle.inputData.namePlural = 'companies';
|
|
||||||
bundle.targetUrl = 'https://test.com';
|
|
||||||
const result = await appTester(
|
|
||||||
App.triggers[triggerRecordDeletedKey].operation.performSubscribe,
|
|
||||||
bundle,
|
|
||||||
);
|
|
||||||
const unsubscribeBundle = getBundle({});
|
|
||||||
unsubscribeBundle.subscribeData = { id: result.id };
|
|
||||||
const unsubscribeResult = await appTester(
|
|
||||||
App.triggers[triggerRecordDeletedKey].operation.performUnsubscribe,
|
|
||||||
unsubscribeBundle,
|
|
||||||
);
|
|
||||||
expect(unsubscribeResult).toBeDefined();
|
|
||||||
expect(unsubscribeResult.id).toEqual(result.id);
|
|
||||||
const checkDbResult = await appTester(
|
|
||||||
(z: ZObject, bundle: Bundle) =>
|
|
||||||
requestDb(
|
|
||||||
z,
|
|
||||||
bundle,
|
|
||||||
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operation}}}}`,
|
|
||||||
),
|
|
||||||
bundle,
|
|
||||||
);
|
|
||||||
expect(checkDbResult.data.webhooks.edges.length).toEqual(0);
|
|
||||||
});
|
|
||||||
test('should load company from webhook', async () => {
|
|
||||||
const bundle = {
|
|
||||||
cleanedRequest: {
|
|
||||||
id: 'd6ccb1d1-a90b-4822-a992-a0dd946592c9',
|
|
||||||
name: '',
|
|
||||||
domainName: '',
|
|
||||||
createdAt: '2023-10-19 10:10:12.490',
|
|
||||||
address: '',
|
|
||||||
employees: null,
|
|
||||||
linkedinUrl: null,
|
|
||||||
xUrl: null,
|
|
||||||
annualRecurringRevenue: null,
|
|
||||||
idealCustomerProfile: false,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const results = await appTester(
|
|
||||||
App.triggers[triggerRecordDeletedKey].operation.perform,
|
|
||||||
bundle,
|
|
||||||
);
|
|
||||||
expect(results.length).toEqual(1);
|
|
||||||
const company = results[0];
|
|
||||||
expect(company.id).toEqual('d6ccb1d1-a90b-4822-a992-a0dd946592c9');
|
|
||||||
});
|
|
||||||
it('should load companies from list', async () => {
|
|
||||||
const bundle = getBundle({});
|
|
||||||
bundle.inputData.namePlural = 'companies';
|
|
||||||
const results = await appTester(
|
|
||||||
App.triggers[triggerRecordDeletedKey].operation.performList,
|
|
||||||
bundle,
|
|
||||||
);
|
|
||||||
expect(results.length).toBeGreaterThan(1);
|
|
||||||
const firstCompany = results[0];
|
|
||||||
expect(firstCompany).toBeDefined();
|
|
||||||
expect(firstCompany.id).toBeDefined();
|
|
||||||
expect(Object.keys(firstCompany).length).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,93 +0,0 @@
|
|||||||
import { Bundle, createAppTester, ZObject } from 'zapier-platform-core';
|
|
||||||
import App from '../../index';
|
|
||||||
import getBundle from '../../utils/getBundle';
|
|
||||||
import requestDb from '../../utils/requestDb';
|
|
||||||
import { triggerRecordUpdatedKey } from '../../triggers/trigger_record_updated';
|
|
||||||
const appTester = createAppTester(App);
|
|
||||||
|
|
||||||
describe('triggers.trigger_record_updated', () => {
|
|
||||||
test('should succeed to subscribe', async () => {
|
|
||||||
const bundle = getBundle({});
|
|
||||||
bundle.inputData.namePlural = 'companies';
|
|
||||||
bundle.targetUrl = 'https://test.com';
|
|
||||||
const result = await appTester(
|
|
||||||
App.triggers[triggerRecordUpdatedKey].operation.performSubscribe,
|
|
||||||
bundle,
|
|
||||||
);
|
|
||||||
expect(result).toBeDefined();
|
|
||||||
expect(result.id).toBeDefined();
|
|
||||||
const checkDbResult = await appTester(
|
|
||||||
(z: ZObject, bundle: Bundle) =>
|
|
||||||
requestDb(
|
|
||||||
z,
|
|
||||||
bundle,
|
|
||||||
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operation}}}}`,
|
|
||||||
),
|
|
||||||
bundle,
|
|
||||||
);
|
|
||||||
expect(checkDbResult.data.webhooks.edges[0].node.operation).toEqual(
|
|
||||||
'update.companies',
|
|
||||||
);
|
|
||||||
});
|
|
||||||
test('should succeed to unsubscribe', async () => {
|
|
||||||
const bundle = getBundle({});
|
|
||||||
bundle.inputData.namePlural = 'companies';
|
|
||||||
bundle.targetUrl = 'https://test.com';
|
|
||||||
const result = await appTester(
|
|
||||||
App.triggers[triggerRecordUpdatedKey].operation.performSubscribe,
|
|
||||||
bundle,
|
|
||||||
);
|
|
||||||
const unsubscribeBundle = getBundle({});
|
|
||||||
unsubscribeBundle.subscribeData = { id: result.id };
|
|
||||||
const unsubscribeResult = await appTester(
|
|
||||||
App.triggers[triggerRecordUpdatedKey].operation.performUnsubscribe,
|
|
||||||
unsubscribeBundle,
|
|
||||||
);
|
|
||||||
expect(unsubscribeResult).toBeDefined();
|
|
||||||
expect(unsubscribeResult.id).toEqual(result.id);
|
|
||||||
const checkDbResult = await appTester(
|
|
||||||
(z: ZObject, bundle: Bundle) =>
|
|
||||||
requestDb(
|
|
||||||
z,
|
|
||||||
bundle,
|
|
||||||
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operation}}}}`,
|
|
||||||
),
|
|
||||||
bundle,
|
|
||||||
);
|
|
||||||
expect(checkDbResult.data.webhooks.edges.length).toEqual(0);
|
|
||||||
});
|
|
||||||
test('should load company from webhook', async () => {
|
|
||||||
const bundle = {
|
|
||||||
cleanedRequest: {
|
|
||||||
id: 'd6ccb1d1-a90b-4822-a992-a0dd946592c9',
|
|
||||||
name: '',
|
|
||||||
domainName: '',
|
|
||||||
createdAt: '2023-10-19 10:10:12.490',
|
|
||||||
address: '',
|
|
||||||
employees: null,
|
|
||||||
linkedinUrl: null,
|
|
||||||
xUrl: null,
|
|
||||||
annualRecurringRevenue: null,
|
|
||||||
idealCustomerProfile: false,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const results = await appTester(
|
|
||||||
App.triggers[triggerRecordUpdatedKey].operation.perform,
|
|
||||||
bundle,
|
|
||||||
);
|
|
||||||
expect(results.length).toEqual(1);
|
|
||||||
const company = results[0];
|
|
||||||
expect(company.id).toEqual('d6ccb1d1-a90b-4822-a992-a0dd946592c9');
|
|
||||||
});
|
|
||||||
it('should load companies from list', async () => {
|
|
||||||
const bundle = getBundle({});
|
|
||||||
bundle.inputData.namePlural = 'companies';
|
|
||||||
const results = await appTester(
|
|
||||||
App.triggers[triggerRecordUpdatedKey].operation.performList,
|
|
||||||
bundle,
|
|
||||||
);
|
|
||||||
expect(results.length).toBeGreaterThan(1);
|
|
||||||
const firstCompany = results[0];
|
|
||||||
expect(firstCompany).toBeDefined();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,27 +0,0 @@
|
|||||||
import { Bundle, ZObject } from 'zapier-platform-core';
|
|
||||||
import { requestSchema } from '../utils/requestDb';
|
|
||||||
|
|
||||||
const objectNamesPluralListRequest = async (z: ZObject, bundle: Bundle) => {
|
|
||||||
const schema = await requestSchema(z, bundle);
|
|
||||||
const tags: { name: string }[] = schema.tags;
|
|
||||||
return Object.values(tags)
|
|
||||||
.filter((tag) => tag.name !== 'General')
|
|
||||||
.map((tag) => {
|
|
||||||
return { id: tag.name, namePlural: tag.name };
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const findObjectNamesPluralKey = 'find_object_names_plural';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
display: {
|
|
||||||
description: 'Find objects',
|
|
||||||
label: 'Find objects',
|
|
||||||
hidden: true,
|
|
||||||
},
|
|
||||||
key: findObjectNamesPluralKey,
|
|
||||||
noun: 'Object',
|
|
||||||
operation: {
|
|
||||||
perform: objectNamesPluralListRequest,
|
|
||||||
},
|
|
||||||
};
|
|
@ -1,10 +1,11 @@
|
|||||||
import { Bundle, ZObject } from 'zapier-platform-core';
|
import { Bundle, ZObject } from 'zapier-platform-core';
|
||||||
|
|
||||||
import { requestSchema } from '../utils/requestDb';
|
import { requestSchema } from '../utils/requestDb';
|
||||||
|
|
||||||
const objectListRequest = async (z: ZObject, bundle: Bundle) => {
|
const objectListRequest = async (z: ZObject, bundle: Bundle) => {
|
||||||
const schema = await requestSchema(z, bundle);
|
const schema = await requestSchema(z, bundle);
|
||||||
return Object.keys(schema.components.schemas).map((schema) => {
|
return Object.keys(schema.components.schemas).map((schema) => {
|
||||||
return { id: schema, nameSingular: schema };
|
return { id: schema, nameSingular: schema.toLowerCase() };
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,24 +1,13 @@
|
|||||||
import { Bundle, ZObject } from 'zapier-platform-core';
|
import { Bundle, ZObject } from 'zapier-platform-core';
|
||||||
|
|
||||||
import { capitalize } from '../utils/capitalize';
|
import { ObjectData } from '../utils/data.types';
|
||||||
import requestDb from '../utils/requestDb';
|
import { listSample } from '../utils/triggers/triggers.utils';
|
||||||
|
|
||||||
const listRecordIdsRequest = async (
|
const listRecordIdsRequest = async (
|
||||||
z: ZObject,
|
z: ZObject,
|
||||||
bundle: Bundle,
|
bundle: Bundle,
|
||||||
): Promise<{ id: string }[]> => {
|
): Promise<ObjectData[]> => {
|
||||||
const data = bundle.inputData;
|
return listSample(z, bundle, true);
|
||||||
const namePlural = data.namePlural;
|
|
||||||
const query = `
|
|
||||||
query List${capitalize(namePlural)}Ids {
|
|
||||||
${namePlural}{edges{node{id}}}
|
|
||||||
}`;
|
|
||||||
const result = await requestDb(z, bundle, query);
|
|
||||||
return result.data[namePlural]['edges'].map((edge: any) => {
|
|
||||||
return {
|
|
||||||
id: edge.node.id,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const listRecordIdsKey = 'list_record_ids';
|
export const listRecordIdsKey = 'list_record_ids';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Bundle, ZObject } from 'zapier-platform-core';
|
import { Bundle, ZObject } from 'zapier-platform-core';
|
||||||
|
|
||||||
import { findObjectNamesPluralKey } from '../triggers/find_object_names_plural';
|
import { findObjectNamesSingularKey } from '../triggers/find_object_names_singular';
|
||||||
import {
|
import {
|
||||||
listSample,
|
listSample,
|
||||||
Operation,
|
Operation,
|
||||||
@ -9,26 +9,38 @@ import {
|
|||||||
subscribe,
|
subscribe,
|
||||||
} from '../utils/triggers/triggers.utils';
|
} from '../utils/triggers/triggers.utils';
|
||||||
|
|
||||||
export const triggerRecordUpdatedKey = 'trigger_record_updated';
|
export const triggerRecordKey = 'trigger_record';
|
||||||
|
|
||||||
const performSubscribe = (z: ZObject, bundle: Bundle) =>
|
const performSubscribe = (z: ZObject, bundle: Bundle) =>
|
||||||
subscribe(z, bundle, Operation.update);
|
subscribe(z, bundle, bundle.inputData.operation);
|
||||||
const performList = (z: ZObject, bundle: Bundle) => listSample(z, bundle);
|
const performList = (z: ZObject, bundle: Bundle) =>
|
||||||
|
listSample(z, bundle, bundle.inputData.operation === Operation.delete);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
key: triggerRecordUpdatedKey,
|
key: triggerRecordKey,
|
||||||
noun: 'Record',
|
noun: 'Record',
|
||||||
display: {
|
display: {
|
||||||
label: 'Record Trigger Updated',
|
label: 'Record Trigger',
|
||||||
description: 'Triggers when a Record is updated.',
|
description: 'Triggers when a Record is created, updated or deleted.',
|
||||||
},
|
},
|
||||||
operation: {
|
operation: {
|
||||||
inputFields: [
|
inputFields: [
|
||||||
{
|
{
|
||||||
key: 'namePlural',
|
key: 'nameSingular',
|
||||||
required: true,
|
required: true,
|
||||||
label: 'Record Name',
|
label: 'Record Name',
|
||||||
dynamic: `${findObjectNamesPluralKey}.namePlural`,
|
dynamic: `${findObjectNamesSingularKey}.nameSingular`,
|
||||||
|
altersDynamicFields: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'operation',
|
||||||
|
required: true,
|
||||||
|
label: 'Operation',
|
||||||
|
choices: {
|
||||||
|
[Operation.create]: Operation.create,
|
||||||
|
[Operation.update]: Operation.update,
|
||||||
|
[Operation.delete]: Operation.delete,
|
||||||
|
},
|
||||||
altersDynamicFields: true,
|
altersDynamicFields: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
@ -1,51 +0,0 @@
|
|||||||
import { Bundle, ZObject } from 'zapier-platform-core';
|
|
||||||
|
|
||||||
import { findObjectNamesPluralKey } from '../triggers/find_object_names_plural';
|
|
||||||
import {
|
|
||||||
listSample,
|
|
||||||
Operation,
|
|
||||||
perform,
|
|
||||||
performUnsubscribe,
|
|
||||||
subscribe,
|
|
||||||
} from '../utils/triggers/triggers.utils';
|
|
||||||
|
|
||||||
export const triggerRecordCreatedKey = 'trigger_record_created';
|
|
||||||
|
|
||||||
const performSubscribe = (z: ZObject, bundle: Bundle) =>
|
|
||||||
subscribe(z, bundle, Operation.create);
|
|
||||||
const performList = (z: ZObject, bundle: Bundle) => listSample(z, bundle);
|
|
||||||
|
|
||||||
export default {
|
|
||||||
key: triggerRecordCreatedKey,
|
|
||||||
noun: 'Record',
|
|
||||||
display: {
|
|
||||||
label: 'Record Trigger Created',
|
|
||||||
description: 'Triggers when a Record is created.',
|
|
||||||
},
|
|
||||||
operation: {
|
|
||||||
inputFields: [
|
|
||||||
{
|
|
||||||
key: 'namePlural',
|
|
||||||
required: true,
|
|
||||||
label: 'Record Name',
|
|
||||||
dynamic: `${findObjectNamesPluralKey}.namePlural`,
|
|
||||||
altersDynamicFields: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
type: 'hook',
|
|
||||||
performSubscribe,
|
|
||||||
performUnsubscribe,
|
|
||||||
perform,
|
|
||||||
performList,
|
|
||||||
sample: {
|
|
||||||
id: 'f75f6b2e-9442-4c72-aa95-47d8e5ec8cb3',
|
|
||||||
createdAt: '2023-10-19T07:37:25.306Z',
|
|
||||||
workspaceId: 'c8b070fc-c969-4ca5-837a-e7c3735734d2',
|
|
||||||
},
|
|
||||||
outputFields: [
|
|
||||||
{ key: 'id', label: 'ID' },
|
|
||||||
{ key: 'createdAt', label: 'Created At' },
|
|
||||||
{ key: 'workspaceId', label: 'Workspace ID' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
@ -1,45 +0,0 @@
|
|||||||
import { Bundle, ZObject } from 'zapier-platform-core';
|
|
||||||
|
|
||||||
import { findObjectNamesPluralKey } from '../triggers/find_object_names_plural';
|
|
||||||
import {
|
|
||||||
listSample,
|
|
||||||
Operation,
|
|
||||||
perform,
|
|
||||||
performUnsubscribe,
|
|
||||||
subscribe,
|
|
||||||
} from '../utils/triggers/triggers.utils';
|
|
||||||
|
|
||||||
export const triggerRecordDeletedKey = 'trigger_record_deleted';
|
|
||||||
|
|
||||||
const performSubscribe = (z: ZObject, bundle: Bundle) =>
|
|
||||||
subscribe(z, bundle, Operation.delete);
|
|
||||||
const performList = (z: ZObject, bundle: Bundle) => listSample(z, bundle, true);
|
|
||||||
|
|
||||||
export default {
|
|
||||||
key: triggerRecordDeletedKey,
|
|
||||||
noun: 'Record',
|
|
||||||
display: {
|
|
||||||
label: 'Record Trigger Deleted',
|
|
||||||
description: 'Triggers when a Record is deleted.',
|
|
||||||
},
|
|
||||||
operation: {
|
|
||||||
inputFields: [
|
|
||||||
{
|
|
||||||
key: 'namePlural',
|
|
||||||
required: true,
|
|
||||||
label: 'Record Name',
|
|
||||||
dynamic: `${findObjectNamesPluralKey}.namePlural`,
|
|
||||||
altersDynamicFields: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
type: 'hook',
|
|
||||||
performSubscribe,
|
|
||||||
performUnsubscribe,
|
|
||||||
perform,
|
|
||||||
performList,
|
|
||||||
sample: {
|
|
||||||
id: 'f75f6b2e-9442-4c72-aa95-47d8e5ec8cb3',
|
|
||||||
},
|
|
||||||
outputFields: [{ key: 'id', label: 'ID' }],
|
|
||||||
},
|
|
||||||
};
|
|
2
packages/twenty-zapier/src/utils/data.types.ts
Normal file
2
packages/twenty-zapier/src/utils/data.types.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export type InputData = { [x: string]: any };
|
||||||
|
export type ObjectData = { id: string } | { [x: string]: any };
|
@ -1,6 +1,8 @@
|
|||||||
import { Bundle } from 'zapier-platform-core';
|
import { Bundle } from 'zapier-platform-core';
|
||||||
|
|
||||||
const getBundle = (inputData?: { [x: string]: any }): Bundle => {
|
import { InputData } from '../utils/data.types';
|
||||||
|
|
||||||
|
const getBundle = (inputData?: InputData): Bundle => {
|
||||||
return {
|
return {
|
||||||
authData: { apiKey: String(process.env.API_KEY) },
|
authData: { apiKey: String(process.env.API_KEY) },
|
||||||
inputData: inputData || {},
|
inputData: inputData || {},
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
const handleQueryParams = (inputData: { [x: string]: any }): string => {
|
import { InputData } from '../utils/data.types';
|
||||||
const formattedInputData: { [x: string]: any } = {};
|
|
||||||
|
const handleQueryParams = (inputData: InputData): string => {
|
||||||
|
const formattedInputData: InputData = {};
|
||||||
Object.keys(inputData).forEach((key) => {
|
Object.keys(inputData).forEach((key) => {
|
||||||
if (key.includes('__')) {
|
if (key.includes('__')) {
|
||||||
const [objectKey, nestedObjectKey] = key.split('__');
|
const [objectKey, nestedObjectKey] = key.split('__');
|
||||||
|
@ -14,9 +14,14 @@ export const requestSchema = async (z: ZObject, bundle: Bundle) => {
|
|||||||
return z.request(options).then((response) => response.json);
|
return z.request(options).then((response) => response.json);
|
||||||
};
|
};
|
||||||
|
|
||||||
const requestDb = async (z: ZObject, bundle: Bundle, query: string) => {
|
const requestDb = async (
|
||||||
|
z: ZObject,
|
||||||
|
bundle: Bundle,
|
||||||
|
query: string,
|
||||||
|
endpoint = 'graphql',
|
||||||
|
) => {
|
||||||
const options = {
|
const options = {
|
||||||
url: `${process.env.SERVER_BASE_URL}/graphql`,
|
url: `${process.env.SERVER_BASE_URL}/${endpoint}`,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Bundle, ZObject } from 'zapier-platform-core';
|
import { Bundle, ZObject } from 'zapier-platform-core';
|
||||||
|
|
||||||
|
import { ObjectData } from '../../utils/data.types';
|
||||||
import handleQueryParams from '../../utils/handleQueryParams';
|
import handleQueryParams from '../../utils/handleQueryParams';
|
||||||
import requestDb, { requestDbViaRestApi } from '../../utils/requestDb';
|
import requestDb, { requestDbViaRestApi } from '../../utils/requestDb';
|
||||||
|
|
||||||
@ -16,7 +17,7 @@ export const subscribe = async (
|
|||||||
) => {
|
) => {
|
||||||
const data = {
|
const data = {
|
||||||
targetUrl: bundle.targetUrl,
|
targetUrl: bundle.targetUrl,
|
||||||
operation: `${operation}.${bundle.inputData.namePlural}`,
|
operation: `${operation}.${bundle.inputData.nameSingular}`,
|
||||||
};
|
};
|
||||||
const result = await requestDb(
|
const result = await requestDb(
|
||||||
z,
|
z,
|
||||||
@ -39,18 +40,52 @@ export const performUnsubscribe = async (z: ZObject, bundle: Bundle) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const perform = (z: ZObject, bundle: Bundle) => {
|
export const perform = (z: ZObject, bundle: Bundle) => {
|
||||||
return [bundle.cleanedRequest];
|
return [bundle.cleanedRequest.record];
|
||||||
|
};
|
||||||
|
|
||||||
|
const getNamePluralFromNameSingular = async (
|
||||||
|
z: ZObject,
|
||||||
|
bundle: Bundle,
|
||||||
|
nameSingular: string,
|
||||||
|
): Promise<string> => {
|
||||||
|
const result = await requestDb(
|
||||||
|
z,
|
||||||
|
bundle,
|
||||||
|
`query GetObjects {
|
||||||
|
objects(paging: {first: 1000}) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
nameSingular
|
||||||
|
namePlural
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
'metadata',
|
||||||
|
);
|
||||||
|
for (const object of result.data.objects.edges) {
|
||||||
|
if (object.node.nameSingular === nameSingular) {
|
||||||
|
return object.node.namePlural;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error(`Unknown Object Name Singular ${nameSingular}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const listSample = async (
|
export const listSample = async (
|
||||||
z: ZObject,
|
z: ZObject,
|
||||||
bundle: Bundle,
|
bundle: Bundle,
|
||||||
onlyIds = false,
|
onlyIds = false,
|
||||||
) => {
|
): Promise<ObjectData[]> => {
|
||||||
|
const nameSingular = bundle.inputData.nameSingular;
|
||||||
|
const namePlural = await getNamePluralFromNameSingular(
|
||||||
|
z,
|
||||||
|
bundle,
|
||||||
|
nameSingular,
|
||||||
|
);
|
||||||
const result: { [key: string]: string }[] = await requestDbViaRestApi(
|
const result: { [key: string]: string }[] = await requestDbViaRestApi(
|
||||||
z,
|
z,
|
||||||
bundle,
|
bundle,
|
||||||
bundle.inputData.namePlural,
|
namePlural,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (onlyIds) {
|
if (onlyIds) {
|
||||||
|
@ -42347,6 +42347,9 @@ __metadata:
|
|||||||
"twenty-zapier@workspace:packages/twenty-zapier":
|
"twenty-zapier@workspace:packages/twenty-zapier":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "twenty-zapier@workspace:packages/twenty-zapier"
|
resolution: "twenty-zapier@workspace:packages/twenty-zapier"
|
||||||
|
dependencies:
|
||||||
|
zapier-platform-cli: "npm:^15.4.1"
|
||||||
|
zapier-platform-core: "npm:15.5.1"
|
||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
@ -42605,8 +42608,6 @@ __metadata:
|
|||||||
vite-plugin-svgr: "npm:^4.2.0"
|
vite-plugin-svgr: "npm:^4.2.0"
|
||||||
vite-tsconfig-paths: "npm:^4.2.1"
|
vite-tsconfig-paths: "npm:^4.2.1"
|
||||||
xlsx-ugnis: "npm:^0.19.3"
|
xlsx-ugnis: "npm:^0.19.3"
|
||||||
zapier-platform-cli: "npm:^15.4.1"
|
|
||||||
zapier-platform-core: "npm:15.5.1"
|
|
||||||
zod: "npm:^3.22.2"
|
zod: "npm:^3.22.2"
|
||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
Loading…
Reference in New Issue
Block a user