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 commit 2e72e05793.

* Revert "Revert "Rename file""

This reverts commit e2d93fa027.

* Revert "Remove list Record Ids"

This reverts commit 6653fb6ccd.

* 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:
martmull 2024-01-16 15:31:09 +01:00 committed by GitHub
parent fb93bb69fb
commit bb91917ff8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 637 additions and 835 deletions

View File

@ -152,7 +152,6 @@
"uuid": "^9.0.0",
"vite-tsconfig-paths": "^4.2.1",
"xlsx-ugnis": "^0.19.3",
"zapier-platform-core": "15.5.1",
"zod": "^3.22.2"
},
"devDependencies": {
@ -259,8 +258,7 @@
"typescript": "^5.3.3",
"vite": "^5.0.0",
"vite-plugin-checker": "^0.6.2",
"vite-plugin-svgr": "^4.2.0",
"zapier-platform-cli": "^15.4.1"
"vite-plugin-svgr": "^4.2.0"
},
"engines": {
"node": "^18.17.1",

View File

@ -22,7 +22,7 @@ export enum CallWebhookJobsJobOperation {
export type CallWebhookJobsJobData = {
workspaceId: string;
objectMetadataItem: ObjectMetadataInterface;
recordData: any;
record: any;
operation: CallWebhookJobsJobOperation;
};
@ -41,11 +41,6 @@ export class CallWebhookJobsJob
) {}
async handle(data: CallWebhookJobsJobData): Promise<void> {
const objectMetadataItem =
await this.objectMetadataService.findOneOrFailWithinWorkspace(
data.workspaceId,
{ where: { nameSingular: data.objectMetadataItem.nameSingular } },
);
const dataSourceMetadata =
await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceIdOrFail(
data.workspaceId,
@ -54,27 +49,45 @@ export class CallWebhookJobsJob
await this.workspaceDataSourceService.connectToWorkspaceDataSource(
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 }[] =
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) => {
this.messageQueueService.add<CallWebhookJobData>(
CallWebhookJob.name,
{
recordData: data.recordData,
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 },
);
});
this.logger.log(
`CallWebhookJobsJob on operation '${operationName}' called on webhooks ids [\n"${webhooks
.map((webhook) => webhook.id)
.join('",\n"')}"\n]`,
);
if (webhooks.length) {
this.logger.log(
`CallWebhookJobsJob on eventType '${eventType}' called on webhooks ids [\n"${webhooks
.map((webhook) => webhook.id)
.join('",\n"')}"\n]`,
);
}
}
}

View File

@ -5,7 +5,12 @@ import { MessageQueueJob } from 'src/integrations/message-queue/interfaces/messa
export type CallWebhookJobData = {
targetUrl: string;
recordData: any;
eventType: string;
objectMetadata: { id: string; nameSingular: string };
workspaceId: string;
webhookId: string;
eventDate: Date;
record: any;
};
@Injectable()
@ -16,11 +21,9 @@ export class CallWebhookJob implements MessageQueueJob<CallWebhookJobData> {
async handle(data: CallWebhookJobData): Promise<void> {
try {
await this.httpService.axiosRef.post(data.targetUrl, data.recordData);
await this.httpService.axiosRef.post(data.targetUrl, data);
this.logger.log(
`CallWebhookJob successfully called on targetUrl '${
data.targetUrl
}' with data: ${JSON.stringify(data.recordData)}`,
`CallWebhookJob successfully called on targetUrl '${data.targetUrl}'`,
);
} catch (err) {
throw new Error(

View File

@ -388,7 +388,7 @@ export class WorkspaceQueryRunnerService {
this.messageQueueService.add<CallWebhookJobsJobData>(
CallWebhookJobsJob.name,
{
recordData: jobData,
record: jobData,
workspaceId: options.workspaceId,
operation,
objectMetadataItem: options.objectMetadataItem,

View File

@ -22,5 +22,14 @@
"private": true,
"zapier": {
"convertedByCLIVersion": "15.4.1"
},
"dependencies": {
"zapier-platform-core": "15.5.1"
},
"devDependencies": {
"zapier-platform-cli": "^15.4.1"
},
"installConfig": {
"hoistingLimits": "dependencies"
}
}

View File

@ -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,
},
};

View 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,
},
};

View File

@ -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,
},
};

View File

@ -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,
},
};

View File

@ -4,25 +4,12 @@ import 'dotenv/config';
const { version } = require('../package.json');
import createRecord, { createRecordKey } from './creates/create_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 crudRecord, { crudRecordKey } from './creates/crud_record';
import findObjectNamesSingular, {
findObjectNamesSingularKey,
} from './triggers/find_object_names_singular';
import listRecordIds, { listRecordIdsKey } from './triggers/list_record_ids';
import triggerRecordCreated, {
triggerRecordCreatedKey,
} from './triggers/trigger_record_created';
import triggerRecordDeleted, {
triggerRecordDeletedKey,
} from './triggers/trigger_record_deleted';
import triggerRecordUpdated, {
triggerRecordUpdatedKey,
} from './triggers/trigger_record_updated';
import triggerRecord, { triggerRecordKey } from './triggers/trigger_record';
import authentication from './authentication';
export default {
@ -31,15 +18,10 @@ export default {
authentication: authentication,
triggers: {
[findObjectNamesSingularKey]: findObjectNamesSingular,
[findObjectNamesPluralKey]: findObjectNamesPlural,
[listRecordIdsKey]: listRecordIds,
[triggerRecordCreatedKey]: triggerRecordCreated,
[triggerRecordUpdatedKey]: triggerRecordUpdated,
[triggerRecordDeletedKey]: triggerRecordDeleted,
[triggerRecordKey]: triggerRecord,
},
creates: {
[createRecordKey]: createRecord,
[updateRecordKey]: updateRecord,
[deleteRecordKey]: deleteRecord,
[crudRecordKey]: crudRecord,
},
};

View File

@ -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');
});
});

View 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);
});
});

View File

@ -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);
});
});

View File

@ -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');
});
});

View File

@ -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();
});
});

View File

@ -8,7 +8,7 @@ tools.env.inject();
const appTester = createAppTester(App);
describe('triggers.list_record_ids', () => {
test('should run', async () => {
const bundle = getBundle({ namePlural: 'companies' });
const bundle = getBundle({ nameSingular: 'company' });
const result = await appTester(
App.triggers[listRecordIdsKey].operation.perform,
bundle,

View 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);
});
});

View File

@ -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();
});
});

View File

@ -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);
});
});

View File

@ -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();
});
});

View File

@ -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,
},
};

View File

@ -1,10 +1,11 @@
import { Bundle, ZObject } from 'zapier-platform-core';
import { requestSchema } from '../utils/requestDb';
const objectListRequest = async (z: ZObject, bundle: Bundle) => {
const schema = await requestSchema(z, bundle);
return Object.keys(schema.components.schemas).map((schema) => {
return { id: schema, nameSingular: schema };
return { id: schema, nameSingular: schema.toLowerCase() };
});
};

View File

@ -1,24 +1,13 @@
import { Bundle, ZObject } from 'zapier-platform-core';
import { capitalize } from '../utils/capitalize';
import requestDb from '../utils/requestDb';
import { ObjectData } from '../utils/data.types';
import { listSample } from '../utils/triggers/triggers.utils';
const listRecordIdsRequest = async (
z: ZObject,
bundle: Bundle,
): Promise<{ id: string }[]> => {
const data = bundle.inputData;
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,
};
});
): Promise<ObjectData[]> => {
return listSample(z, bundle, true);
};
export const listRecordIdsKey = 'list_record_ids';

View File

@ -1,6 +1,6 @@
import { Bundle, ZObject } from 'zapier-platform-core';
import { findObjectNamesPluralKey } from '../triggers/find_object_names_plural';
import { findObjectNamesSingularKey } from '../triggers/find_object_names_singular';
import {
listSample,
Operation,
@ -9,26 +9,38 @@ import {
subscribe,
} from '../utils/triggers/triggers.utils';
export const triggerRecordUpdatedKey = 'trigger_record_updated';
export const triggerRecordKey = 'trigger_record';
const performSubscribe = (z: ZObject, bundle: Bundle) =>
subscribe(z, bundle, Operation.update);
const performList = (z: ZObject, bundle: Bundle) => listSample(z, bundle);
subscribe(z, bundle, bundle.inputData.operation);
const performList = (z: ZObject, bundle: Bundle) =>
listSample(z, bundle, bundle.inputData.operation === Operation.delete);
export default {
key: triggerRecordUpdatedKey,
key: triggerRecordKey,
noun: 'Record',
display: {
label: 'Record Trigger Updated',
description: 'Triggers when a Record is updated.',
label: 'Record Trigger',
description: 'Triggers when a Record is created, updated or deleted.',
},
operation: {
inputFields: [
{
key: 'namePlural',
key: 'nameSingular',
required: true,
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,
},
],

View File

@ -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' },
],
},
};

View File

@ -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' }],
},
};

View File

@ -0,0 +1,2 @@
export type InputData = { [x: string]: any };
export type ObjectData = { id: string } | { [x: string]: any };

View File

@ -1,6 +1,8 @@
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 {
authData: { apiKey: String(process.env.API_KEY) },
inputData: inputData || {},

View File

@ -1,5 +1,7 @@
const handleQueryParams = (inputData: { [x: string]: any }): string => {
const formattedInputData: { [x: string]: any } = {};
import { InputData } from '../utils/data.types';
const handleQueryParams = (inputData: InputData): string => {
const formattedInputData: InputData = {};
Object.keys(inputData).forEach((key) => {
if (key.includes('__')) {
const [objectKey, nestedObjectKey] = key.split('__');

View File

@ -14,9 +14,14 @@ export const requestSchema = async (z: ZObject, bundle: Bundle) => {
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 = {
url: `${process.env.SERVER_BASE_URL}/graphql`,
url: `${process.env.SERVER_BASE_URL}/${endpoint}`,
method: 'POST',
headers: {
'Content-Type': 'application/json',

View File

@ -1,5 +1,6 @@
import { Bundle, ZObject } from 'zapier-platform-core';
import { ObjectData } from '../../utils/data.types';
import handleQueryParams from '../../utils/handleQueryParams';
import requestDb, { requestDbViaRestApi } from '../../utils/requestDb';
@ -16,7 +17,7 @@ export const subscribe = async (
) => {
const data = {
targetUrl: bundle.targetUrl,
operation: `${operation}.${bundle.inputData.namePlural}`,
operation: `${operation}.${bundle.inputData.nameSingular}`,
};
const result = await requestDb(
z,
@ -39,18 +40,52 @@ export const performUnsubscribe = async (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 (
z: ZObject,
bundle: Bundle,
onlyIds = false,
) => {
): Promise<ObjectData[]> => {
const nameSingular = bundle.inputData.nameSingular;
const namePlural = await getNamePluralFromNameSingular(
z,
bundle,
nameSingular,
);
const result: { [key: string]: string }[] = await requestDbViaRestApi(
z,
bundle,
bundle.inputData.namePlural,
namePlural,
);
if (onlyIds) {

View File

@ -42347,6 +42347,9 @@ __metadata:
"twenty-zapier@workspace:packages/twenty-zapier":
version: 0.0.0-use.local
resolution: "twenty-zapier@workspace:packages/twenty-zapier"
dependencies:
zapier-platform-cli: "npm:^15.4.1"
zapier-platform-core: "npm:15.5.1"
languageName: unknown
linkType: soft
@ -42605,8 +42608,6 @@ __metadata:
vite-plugin-svgr: "npm:^4.2.0"
vite-tsconfig-paths: "npm:^4.2.1"
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"
languageName: unknown
linkType: soft