mirror of
https://github.com/twentyhq/twenty.git
synced 2024-10-26 19:24:49 +03:00
2114 timebox make sure the zapier integrations supports custom objects (#3091)
* Fix build command * Add hidden trigger to fetch object names * Remove useless actions * Rename createObject to createRecord
This commit is contained in:
parent
984fc76b94
commit
b1841d0e2f
@ -20,7 +20,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dotenv-cli": "^7.2.1",
|
"dotenv-cli": "^7.2.1",
|
||||||
"prettier": "^3.0.3",
|
"prettier": "^3.0.3",
|
||||||
"zapier-platform-core": "15.4.1"
|
"zapier-platform-core": "15.5.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "^29.5.5",
|
"@types/jest": "^29.5.5",
|
||||||
|
@ -1,129 +0,0 @@
|
|||||||
import { Bundle, ZObject } from 'zapier-platform-core';
|
|
||||||
import handleQueryParams from '../utils/handleQueryParams';
|
|
||||||
import requestDb from '../utils/requestDb';
|
|
||||||
|
|
||||||
const perform = async (z: ZObject, bundle: Bundle) => {
|
|
||||||
const query = `
|
|
||||||
mutation createCompany {
|
|
||||||
createCompany(
|
|
||||||
data:{${handleQueryParams(bundle.inputData)}}
|
|
||||||
)
|
|
||||||
{id}
|
|
||||||
}`;
|
|
||||||
return await requestDb(z, bundle, query);
|
|
||||||
};
|
|
||||||
export default {
|
|
||||||
display: {
|
|
||||||
description: 'Creates a new Company in Twenty',
|
|
||||||
hidden: false,
|
|
||||||
label: 'Create New Company',
|
|
||||||
},
|
|
||||||
key: 'create_company',
|
|
||||||
noun: 'Company',
|
|
||||||
operation: {
|
|
||||||
inputFields: [
|
|
||||||
{
|
|
||||||
key: 'name',
|
|
||||||
label: 'Company Name',
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
list: false,
|
|
||||||
altersDynamicFields: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'address',
|
|
||||||
label: 'Address',
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
list: false,
|
|
||||||
altersDynamicFields: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'domainName',
|
|
||||||
label: 'Url',
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
list: false,
|
|
||||||
altersDynamicFields: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'linkedinLink__url',
|
|
||||||
label: 'Linkedin Link Url',
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
list: false,
|
|
||||||
altersDynamicFields: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'linkedinLink__label',
|
|
||||||
label: 'Linkedin Link Label',
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
list: false,
|
|
||||||
altersDynamicFields: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'xLink__url',
|
|
||||||
label: 'Twitter Link Url',
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
list: false,
|
|
||||||
altersDynamicFields: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'xLink__label',
|
|
||||||
label: 'Twitter Link Label',
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
list: false,
|
|
||||||
altersDynamicFields: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'annualRecurringRevenue__amountMicros',
|
|
||||||
label: 'ARR (Annual Recurring Revenue) amount micros',
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
list: false,
|
|
||||||
altersDynamicFields: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'annualRecurringRevenue__currencyCode',
|
|
||||||
label: 'ARR (Annual Recurring Revenue) currency Code',
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
list: false,
|
|
||||||
altersDynamicFields: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'idealCustomerProfile',
|
|
||||||
label: 'ICP (Ideal Customer Profile)',
|
|
||||||
type: 'boolean',
|
|
||||||
required: false,
|
|
||||||
list: false,
|
|
||||||
altersDynamicFields: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'employees',
|
|
||||||
label: 'Number of Employees',
|
|
||||||
type: 'number',
|
|
||||||
required: false,
|
|
||||||
list: false,
|
|
||||||
altersDynamicFields: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
sample: {
|
|
||||||
name: 'Apple',
|
|
||||||
address: 'apple.com',
|
|
||||||
domainName: 'Cupertino',
|
|
||||||
linkedinUrl__url: '/apple',
|
|
||||||
linkedinUrl__label: 'Apple',
|
|
||||||
xUrl__url: '/apple',
|
|
||||||
xUrl__label: 'Apple',
|
|
||||||
annualRecurringRevenue__amountMicros: 1000000000,
|
|
||||||
annualRecurringRevenue__currencyCode: 'USD',
|
|
||||||
idealCustomerProfile: true,
|
|
||||||
employees: 10000,
|
|
||||||
},
|
|
||||||
perform,
|
|
||||||
},
|
|
||||||
};
|
|
@ -1,75 +0,0 @@
|
|||||||
import { Bundle, ZObject } from 'zapier-platform-core';
|
|
||||||
import handleQueryParams from '../utils/handleQueryParams';
|
|
||||||
import requestDb from '../utils/requestDb';
|
|
||||||
|
|
||||||
const perform = async (z: ZObject, bundle: Bundle) => {
|
|
||||||
const query = `
|
|
||||||
mutation createPerson {
|
|
||||||
createPerson(
|
|
||||||
data:{${handleQueryParams(bundle.inputData)}}
|
|
||||||
)
|
|
||||||
{id}
|
|
||||||
}`;
|
|
||||||
return await requestDb(z, bundle, query);
|
|
||||||
};
|
|
||||||
export default {
|
|
||||||
display: {
|
|
||||||
description: 'Creates a new Person in Twenty',
|
|
||||||
hidden: false,
|
|
||||||
label: 'Create New Person',
|
|
||||||
},
|
|
||||||
key: 'create_person',
|
|
||||||
noun: 'Person',
|
|
||||||
operation: {
|
|
||||||
inputFields: [
|
|
||||||
{
|
|
||||||
key: 'name__firstName',
|
|
||||||
label: 'First Name',
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
list: false,
|
|
||||||
altersDynamicFields: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'name__lastName',
|
|
||||||
label: 'Last Name',
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
list: false,
|
|
||||||
altersDynamicFields: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'email',
|
|
||||||
label: 'Email',
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
list: false,
|
|
||||||
altersDynamicFields: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'phone',
|
|
||||||
label: 'Phone',
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
list: false,
|
|
||||||
altersDynamicFields: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'city',
|
|
||||||
label: 'City',
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
list: false,
|
|
||||||
altersDynamicFields: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
sample: {
|
|
||||||
name__firstName: 'John',
|
|
||||||
name__lastName: 'Doe',
|
|
||||||
email: 'johndoe@gmail.com',
|
|
||||||
phone: '0390900909',
|
|
||||||
city: 'Paris',
|
|
||||||
},
|
|
||||||
perform,
|
|
||||||
},
|
|
||||||
};
|
|
52
packages/twenty-zapier/src/creates/create_record.ts
Normal file
52
packages/twenty-zapier/src/creates/create_record.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import { Bundle, ZObject } from "zapier-platform-core";
|
||||||
|
import requestDb, { requestSchema } from "../utils/requestDb";
|
||||||
|
import handleQueryParams from "../utils/handleQueryParams";
|
||||||
|
import { capitalize } from "../utils/capitalize";
|
||||||
|
import { computeInputFields } from "../utils/computeInputFields";
|
||||||
|
|
||||||
|
const recordInputFields = async (z: ZObject, bundle: Bundle) => {
|
||||||
|
const schema = await requestSchema(z, bundle)
|
||||||
|
const infos = schema.components.schemas[bundle.inputData.nameSingular]
|
||||||
|
|
||||||
|
return computeInputFields(infos);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 default {
|
||||||
|
display: {
|
||||||
|
description: 'Creates a new Record in Twenty',
|
||||||
|
hidden: false,
|
||||||
|
label: 'Create New Record',
|
||||||
|
},
|
||||||
|
key: 'create_record',
|
||||||
|
noun: 'Record',
|
||||||
|
operation: {
|
||||||
|
inputFields: [
|
||||||
|
{
|
||||||
|
key: 'nameSingular',
|
||||||
|
required: true,
|
||||||
|
label: 'Name of the Record to create',
|
||||||
|
dynamic: 'find_objects.nameSingular',
|
||||||
|
altersDynamicFields: true,
|
||||||
|
},
|
||||||
|
recordInputFields
|
||||||
|
],
|
||||||
|
sample: {
|
||||||
|
id: '179ed459-79cf-41d9-ab85-96397fa8e936',
|
||||||
|
},
|
||||||
|
perform
|
||||||
|
},
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
const { version } = require('../package.json');
|
const { version } = require('../package.json');
|
||||||
import { version as platformVersion } from 'zapier-platform-core';
|
import { version as platformVersion } from 'zapier-platform-core';
|
||||||
import createPerson from './creates/create_person';
|
import createRecord from './creates/create_record';
|
||||||
import createCompany from './creates/create_company';
|
import findObjects from './triggers/find_objects'
|
||||||
import authentication from './authentication';
|
import authentication from './authentication';
|
||||||
import 'dotenv/config';
|
import 'dotenv/config';
|
||||||
|
|
||||||
@ -9,8 +9,10 @@ export default {
|
|||||||
version,
|
version,
|
||||||
platformVersion,
|
platformVersion,
|
||||||
authentication: authentication,
|
authentication: authentication,
|
||||||
|
triggers: {
|
||||||
|
[findObjects.key]: findObjects,
|
||||||
|
},
|
||||||
creates: {
|
creates: {
|
||||||
[createPerson.key]: createPerson,
|
[createRecord.key]: createRecord,
|
||||||
[createCompany.key]: createCompany,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
import App from '../../index';
|
|
||||||
import { Bundle, createAppTester, tools, ZObject } from 'zapier-platform-core';
|
|
||||||
import getBundle from '../../utils/getBundle';
|
|
||||||
import requestDb from '../../utils/requestDb';
|
|
||||||
const appTester = createAppTester(App);
|
|
||||||
tools.env.inject();
|
|
||||||
|
|
||||||
describe('creates.create_person', () => {
|
|
||||||
test('should run', async () => {
|
|
||||||
const bundle = getBundle({
|
|
||||||
name: {firstName: 'John', lastName: 'Doe'},
|
|
||||||
email: 'johndoe@gmail.com',
|
|
||||||
phone: '+33610203040',
|
|
||||||
city: 'Paris',
|
|
||||||
});
|
|
||||||
const results = await appTester(
|
|
||||||
App.creates.create_person.operation.perform,
|
|
||||||
bundle,
|
|
||||||
);
|
|
||||||
expect(results).toBeDefined();
|
|
||||||
expect(results.data?.createPerson?.id).toBeDefined();
|
|
||||||
const checkDbResult = await appTester(
|
|
||||||
(z: ZObject, bundle: Bundle) =>
|
|
||||||
requestDb(
|
|
||||||
z,
|
|
||||||
bundle,
|
|
||||||
`query findPerson {person(filter: {id: {eq: "${results.data.createPerson.id}"}}){phone}}`,
|
|
||||||
),
|
|
||||||
bundle,
|
|
||||||
);
|
|
||||||
expect(checkDbResult.data.person.phone).toEqual('+33610203040');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should run with not required params', async () => {
|
|
||||||
const bundle = getBundle({});
|
|
||||||
const results = await appTester(
|
|
||||||
App.creates.create_person.operation.perform,
|
|
||||||
bundle,
|
|
||||||
);
|
|
||||||
expect(results).toBeDefined();
|
|
||||||
expect(results.data?.createPerson?.id).toBeDefined();
|
|
||||||
const checkDbResult = await appTester(
|
|
||||||
(z: ZObject, bundle: Bundle) =>
|
|
||||||
requestDb(
|
|
||||||
z,
|
|
||||||
bundle,
|
|
||||||
`query findPerson {person(filter: {id: {eq: "${results.data.createPerson.id}"}}){phone}}`,
|
|
||||||
),
|
|
||||||
bundle,
|
|
||||||
);
|
|
||||||
expect(checkDbResult.data.person.phone).toEqual("");
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,13 +1,14 @@
|
|||||||
import App from '../../index';
|
import App from '../../index';
|
||||||
import { Bundle, createAppTester, tools, ZObject } from 'zapier-platform-core';
|
import getBundle from "../../utils/getBundle";
|
||||||
import getBundle from '../../utils/getBundle';
|
import { Bundle, createAppTester, tools, ZObject } from "zapier-platform-core";
|
||||||
import requestDb from '../../utils/requestDb';
|
import requestDb from "../../utils/requestDb";
|
||||||
const appTester = createAppTester(App);
|
const appTester = createAppTester(App);
|
||||||
tools.env.inject;
|
tools.env.inject;
|
||||||
|
|
||||||
describe('creates.create_company', () => {
|
describe('creates.create_record', () => {
|
||||||
test('should run', async () => {
|
test('should run to create a Company Record', async () => {
|
||||||
const bundle = getBundle({
|
const bundle = getBundle({
|
||||||
|
nameSingular: 'Company',
|
||||||
name: 'Company Name',
|
name: 'Company Name',
|
||||||
address: 'Company Address',
|
address: 'Company Address',
|
||||||
domainName: 'Company Domain Name',
|
domainName: 'Company Domain Name',
|
||||||
@ -18,7 +19,7 @@ describe('creates.create_company', () => {
|
|||||||
employees: 25,
|
employees: 25,
|
||||||
});
|
});
|
||||||
const result = await appTester(
|
const result = await appTester(
|
||||||
App.creates.create_company.operation.perform,
|
App.creates.create_record.operation.perform,
|
||||||
bundle,
|
bundle,
|
||||||
);
|
);
|
||||||
expect(result).toBeDefined();
|
expect(result).toBeDefined();
|
||||||
@ -35,26 +36,30 @@ describe('creates.create_company', () => {
|
|||||||
expect(checkDbResult.data.company.annualRecurringRevenue.amountMicros).toEqual(
|
expect(checkDbResult.data.company.annualRecurringRevenue.amountMicros).toEqual(
|
||||||
100000000000,
|
100000000000,
|
||||||
);
|
);
|
||||||
});
|
})
|
||||||
test('should run with not required params', async () => {
|
test('should run to create a Person Record', async () => {
|
||||||
const bundle = getBundle({});
|
const bundle = getBundle({
|
||||||
|
nameSingular: 'Person',
|
||||||
|
name: {firstName: 'John', lastName: 'Doe'},
|
||||||
|
email: 'johndoe@gmail.com',
|
||||||
|
phone: '+33610203040',
|
||||||
|
city: 'Paris',
|
||||||
|
});
|
||||||
const result = await appTester(
|
const result = await appTester(
|
||||||
App.creates.create_company.operation.perform,
|
App.creates.create_record.operation.perform,
|
||||||
bundle,
|
bundle,
|
||||||
);
|
);
|
||||||
expect(result).toBeDefined();
|
expect(result).toBeDefined();
|
||||||
expect(result.data?.createCompany?.id).toBeDefined();
|
expect(result.data?.createPerson?.id).toBeDefined();
|
||||||
const checkDbResult = await appTester(
|
const checkDbResult = await appTester(
|
||||||
(z: ZObject, bundle: Bundle) =>
|
(z: ZObject, bundle: Bundle) =>
|
||||||
requestDb(
|
requestDb(
|
||||||
z,
|
z,
|
||||||
bundle,
|
bundle,
|
||||||
`query findCompany {company(filter: {id: {eq: "${result.data.createCompany.id}"}}){id annualRecurringRevenue{amountMicros currencyCode}}}`,
|
`query findPerson {person(filter: {id: {eq: "${result.data.createPerson.id}"}}){phone}}`,
|
||||||
),
|
),
|
||||||
bundle,
|
bundle,
|
||||||
);
|
);
|
||||||
expect(checkDbResult.data.company.annualRecurringRevenue.amountMicros).toEqual(
|
expect(checkDbResult.data.person.phone).toEqual('+33610203040');
|
||||||
null,
|
})
|
||||||
);
|
})
|
||||||
});
|
|
||||||
});
|
|
@ -0,0 +1,17 @@
|
|||||||
|
import { createAppTester } from "zapier-platform-core";
|
||||||
|
import getBundle from '../../utils/getBundle';
|
||||||
|
import App from '../../index';
|
||||||
|
|
||||||
|
const appTester = createAppTester(App);
|
||||||
|
describe('triggers.find_objects', () => {
|
||||||
|
test('should run', async () => {
|
||||||
|
const bundle = getBundle({});
|
||||||
|
const result = await appTester(
|
||||||
|
App.triggers.find_objects.operation.perform,
|
||||||
|
bundle,
|
||||||
|
);
|
||||||
|
expect(result).toBeDefined();
|
||||||
|
expect(result.length).toBeGreaterThan(1)
|
||||||
|
expect(result[0].nameSingular).toBeDefined()
|
||||||
|
})
|
||||||
|
})
|
8
packages/twenty-zapier/src/test/utils/capitalize.spec.ts
Normal file
8
packages/twenty-zapier/src/test/utils/capitalize.spec.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { capitalize } from "../../utils/capitalize";
|
||||||
|
|
||||||
|
describe('capitalize', ()=> {
|
||||||
|
test('should capitalize properly', ()=> {
|
||||||
|
expect(capitalize('word')).toEqual('Word')
|
||||||
|
expect(capitalize('word word')).toEqual('Word word')
|
||||||
|
})
|
||||||
|
})
|
@ -0,0 +1,42 @@
|
|||||||
|
import { computeInputFields } from "../../utils/computeInputFields";
|
||||||
|
|
||||||
|
describe('computeInputFields', ()=> {
|
||||||
|
test('should create Person input fields properly', ()=> {
|
||||||
|
const personInfos = {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
email: {
|
||||||
|
type: "string"
|
||||||
|
},
|
||||||
|
xLink: {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
url: {
|
||||||
|
type: "string"
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
type: "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
avatarUrl: {
|
||||||
|
type: "string"
|
||||||
|
},
|
||||||
|
favorites: {
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
$ref: "#/components/schemas/Favorite"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
example: {},
|
||||||
|
required: ['avatarUrl']
|
||||||
|
}
|
||||||
|
expect(computeInputFields(personInfos)).toEqual([
|
||||||
|
{ key: "email", label: "Email", required: false, type: "string" },
|
||||||
|
{ key: "xLink__url", label: "X Link: Url", required: false, type: "string" },
|
||||||
|
{ key: "xLink__label", label: "X Link: Label", required: false, type: "string" },
|
||||||
|
{ key: "avatarUrl", label: "Avatar Url", required: true, type: "string" },
|
||||||
|
])
|
||||||
|
})
|
||||||
|
})
|
7
packages/twenty-zapier/src/test/utils/labelize.spec.ts
Normal file
7
packages/twenty-zapier/src/test/utils/labelize.spec.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { labelling } from "../../utils/labelling";
|
||||||
|
|
||||||
|
describe('labelling', ()=> {
|
||||||
|
test('should label properly', ()=> {
|
||||||
|
expect(labelling('createdAt')).toEqual('Created At')
|
||||||
|
})
|
||||||
|
})
|
22
packages/twenty-zapier/src/triggers/find_objects.ts
Normal file
22
packages/twenty-zapier/src/triggers/find_objects.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
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}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
display: {
|
||||||
|
description: 'Find objects',
|
||||||
|
label: 'Find objects',
|
||||||
|
hidden: true,
|
||||||
|
},
|
||||||
|
key: 'find_objects',
|
||||||
|
noun: 'Object',
|
||||||
|
operation: {
|
||||||
|
perform: objectListRequest,
|
||||||
|
},
|
||||||
|
}
|
3
packages/twenty-zapier/src/utils/capitalize.ts
Normal file
3
packages/twenty-zapier/src/utils/capitalize.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export const capitalize = (word: string): string => {
|
||||||
|
return word.charAt(0).toUpperCase() + word.slice(1)
|
||||||
|
}
|
54
packages/twenty-zapier/src/utils/computeInputFields.ts
Normal file
54
packages/twenty-zapier/src/utils/computeInputFields.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { labelling } from "../utils/labelling";
|
||||||
|
|
||||||
|
type Infos = {
|
||||||
|
properties: {
|
||||||
|
[field: string]: {
|
||||||
|
type: string;
|
||||||
|
properties?: { [field: string]: { type: string } }
|
||||||
|
items?: { [$ref: string]: string }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
example: object,
|
||||||
|
required: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const computeInputFields = (infos: Infos): object[] => {
|
||||||
|
const result = []
|
||||||
|
|
||||||
|
for (const fieldName of Object.keys(infos.properties)) {
|
||||||
|
switch (infos.properties[fieldName].type) {
|
||||||
|
case 'array':
|
||||||
|
break;
|
||||||
|
case 'object':
|
||||||
|
if (!infos.properties[fieldName].properties) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (const subFieldName of Object.keys(infos.properties[fieldName].properties || {})) {
|
||||||
|
const field = {
|
||||||
|
key: `${fieldName}__${subFieldName}`,
|
||||||
|
label: `${labelling(fieldName)}: ${labelling(subFieldName)}`,
|
||||||
|
type: infos.properties[fieldName].properties?.[subFieldName].type,
|
||||||
|
required: false,
|
||||||
|
}
|
||||||
|
if (infos.required?.includes(fieldName)) {
|
||||||
|
field.required = true
|
||||||
|
}
|
||||||
|
result.push(field)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
const field = {
|
||||||
|
key: fieldName,
|
||||||
|
label: labelling(fieldName),
|
||||||
|
type: infos.properties[fieldName].type,
|
||||||
|
required: false,
|
||||||
|
}
|
||||||
|
if (infos.required?.includes(fieldName)) {
|
||||||
|
field.required = true
|
||||||
|
}
|
||||||
|
result.push(field)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
9
packages/twenty-zapier/src/utils/labelling.ts
Normal file
9
packages/twenty-zapier/src/utils/labelling.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { capitalize } from "../utils/capitalize";
|
||||||
|
|
||||||
|
export const labelling = (str: string): string => {
|
||||||
|
return str
|
||||||
|
.replace(/[A-Z]/g, letter => ` ${letter.toLowerCase()}`)
|
||||||
|
.split(' ')
|
||||||
|
.map((word)=> capitalize(word))
|
||||||
|
.join(' ');
|
||||||
|
}
|
@ -1,5 +1,20 @@
|
|||||||
import { Bundle, HttpRequestOptions, ZObject } from 'zapier-platform-core';
|
import { Bundle, HttpRequestOptions, ZObject } from 'zapier-platform-core';
|
||||||
|
|
||||||
|
export const requestSchema = async (z: ZObject, bundle: Bundle) => {
|
||||||
|
const options = {
|
||||||
|
url: `${process.env.SERVER_BASE_URL}/open-api`,
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Accept: 'application/json',
|
||||||
|
Authorization: `Bearer ${bundle.authData.apiKey}`,
|
||||||
|
},
|
||||||
|
} satisfies HttpRequestOptions;
|
||||||
|
|
||||||
|
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) => {
|
||||||
const options = {
|
const options = {
|
||||||
url: `${process.env.SERVER_BASE_URL}/graphql`,
|
url: `${process.env.SERVER_BASE_URL}/graphql`,
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
"lib": ["esnext"],
|
"lib": ["esnext"],
|
||||||
"outDir": "./lib",
|
"outDir": "./lib",
|
||||||
"rootDir": "./src",
|
"rootDir": "./src",
|
||||||
"strict": true
|
"strict": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"skipLibCheck": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
24
yarn.lock
24
yarn.lock
@ -15190,7 +15190,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@zapier/secret-scrubber@npm:^1.0.7":
|
"@zapier/secret-scrubber@npm:^1.0.8":
|
||||||
version: 1.0.8
|
version: 1.0.8
|
||||||
resolution: "@zapier/secret-scrubber@npm:1.0.8"
|
resolution: "@zapier/secret-scrubber@npm:1.0.8"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -41285,7 +41285,7 @@ __metadata:
|
|||||||
rimraf: "npm:^5.0.5"
|
rimraf: "npm:^5.0.5"
|
||||||
typescript: "npm:^5.2.2"
|
typescript: "npm:^5.2.2"
|
||||||
zapier-platform-cli: "npm:^15.4.1"
|
zapier-platform-cli: "npm:^15.4.1"
|
||||||
zapier-platform-core: "npm:15.4.1"
|
zapier-platform-core: "npm:15.5.1"
|
||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
@ -44005,12 +44005,12 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"zapier-platform-core@npm:15.4.1":
|
"zapier-platform-core@npm:15.5.1":
|
||||||
version: 15.4.1
|
version: 15.5.1
|
||||||
resolution: "zapier-platform-core@npm:15.4.1"
|
resolution: "zapier-platform-core@npm:15.5.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/node": "npm:^20.3.1"
|
"@types/node": "npm:^20.3.1"
|
||||||
"@zapier/secret-scrubber": "npm:^1.0.7"
|
"@zapier/secret-scrubber": "npm:^1.0.8"
|
||||||
bluebird: "npm:3.7.2"
|
bluebird: "npm:3.7.2"
|
||||||
content-disposition: "npm:0.5.4"
|
content-disposition: "npm:0.5.4"
|
||||||
dotenv: "npm:12.0.4 "
|
dotenv: "npm:12.0.4 "
|
||||||
@ -44021,21 +44021,21 @@ __metadata:
|
|||||||
node-fetch: "npm:2.6.7"
|
node-fetch: "npm:2.6.7"
|
||||||
oauth-sign: "npm:0.9.0"
|
oauth-sign: "npm:0.9.0"
|
||||||
semver: "npm:7.5.2"
|
semver: "npm:7.5.2"
|
||||||
zapier-platform-schema: "npm:15.4.1"
|
zapier-platform-schema: "npm:15.5.1"
|
||||||
dependenciesMeta:
|
dependenciesMeta:
|
||||||
"@types/node":
|
"@types/node":
|
||||||
optional: true
|
optional: true
|
||||||
checksum: 84ab2e0c65a436c9617f386219b82aac33d534f1af8104684f7037025cb916dd9e035ef18d82fe4c63039b9af95ea976b6d4561a123dea79dd20011252996ba8
|
checksum: af61f412fa8b4ce58a701d9bacd1600d2af59cb7eb80bc7206c7077cd5aa2cc69c4837e98b26872a3e43848d68ea2356521316ef74aadc35fb56f009352bc9b4
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"zapier-platform-schema@npm:15.4.1":
|
"zapier-platform-schema@npm:15.5.1":
|
||||||
version: 15.4.1
|
version: 15.5.1
|
||||||
resolution: "zapier-platform-schema@npm:15.4.1"
|
resolution: "zapier-platform-schema@npm:15.5.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
jsonschema: "npm:1.2.2"
|
jsonschema: "npm:1.2.2"
|
||||||
lodash: "npm:4.17.21"
|
lodash: "npm:4.17.21"
|
||||||
checksum: a7b9de082aceeac345e4d03b740dd66f5131b7ab10a289e3db4e2548764c90495818fd6af366a6092c3c8d379533509482a6fcd88283381d424bfbda236e58b8
|
checksum: d08435d8221f7d6dbcb02a7a507bd63dbb9f2b9ee1d868da8d53e71e7fdc91426932957c2ff2afd8fc471749c17cf10a8d651e25f682af4c3fd0f11f5d76b5fd
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user