From e6a415b438fc8e23cfc382efa057d4399f1c0ce9 Mon Sep 17 00:00:00 2001 From: martmull Date: Wed, 25 Feb 2026 10:35:46 +0100 Subject: [PATCH] Fix twenty zapier (#18191) as title --- .github/workflows/ci-zapier.yaml | 60 ++++++++++++++++ eslint.config.mjs | 4 ++ packages/create-twenty-app/jest.config.mjs | 2 +- packages/twenty-zapier/CHANGELOG.md | 3 + packages/twenty-zapier/eslint.config.mjs | 48 +++++++++++++ packages/twenty-zapier/index.js | 2 +- packages/twenty-zapier/jest.config.mjs | 13 ++-- packages/twenty-zapier/package.json | 11 +-- packages/twenty-zapier/project.json | 38 ++++++---- .../authentication.test.ts | 4 +- packages/twenty-zapier/src/authentication.ts | 9 +-- .../__tests__}/crud_record.test.ts | 34 ++++----- .../twenty-zapier/src/creates/crud_record.ts | 16 ++--- packages/twenty-zapier/src/index.ts | 12 ++-- .../find_object_names_singular.test.ts | 6 +- .../__tests__}/list_record_ids.test.ts | 6 +- .../__tests__}/trigger_record.test.ts | 52 +++++++++----- .../triggers/find_object_names_singular.ts | 2 +- .../src/triggers/list_record_ids.ts | 2 +- .../src/triggers/trigger_record.ts | 2 +- .../src/types/FieldMetadataType.ts | 27 ------- .../__tests__}/computeInputFields.test.ts | 6 +- .../__tests__}/handleQueryParams.test.ts | 2 +- .../src/utils/computeInputFields.ts | 4 +- .../twenty-zapier/src/utils/data.types.ts | 2 +- packages/twenty-zapier/src/utils/getBundle.ts | 5 +- .../src/utils/handleQueryParams.ts | 2 +- packages/twenty-zapier/src/utils/requestDb.ts | 20 +++--- .../src/utils/triggers/triggers.utils.ts | 20 +++--- packages/twenty-zapier/tsconfig.json | 12 ++-- packages/twenty-zapier/vite.config.ts | 72 +++++++++++++++++++ yarn.lock | 4 ++ 32 files changed, 351 insertions(+), 151 deletions(-) create mode 100644 .github/workflows/ci-zapier.yaml create mode 100644 packages/twenty-zapier/eslint.config.mjs rename packages/twenty-zapier/src/{test => __tests__}/authentication.test.ts (95%) rename packages/twenty-zapier/src/{test/creates => creates/__tests__}/crud_record.test.ts (84%) rename packages/twenty-zapier/src/{test/triggers => triggers/__tests__}/find_object_names_singular.test.ts (75%) rename packages/twenty-zapier/src/{test/triggers => triggers/__tests__}/list_record_ids.test.ts (77%) rename packages/twenty-zapier/src/{test/triggers => triggers/__tests__}/trigger_record.test.ts (86%) delete mode 100644 packages/twenty-zapier/src/types/FieldMetadataType.ts rename packages/twenty-zapier/src/{test/utils => utils/__tests__}/computeInputFields.test.ts (97%) rename packages/twenty-zapier/src/{test/utils => utils/__tests__}/handleQueryParams.test.ts (97%) create mode 100644 packages/twenty-zapier/vite.config.ts diff --git a/.github/workflows/ci-zapier.yaml b/.github/workflows/ci-zapier.yaml new file mode 100644 index 0000000000..86505de501 --- /dev/null +++ b/.github/workflows/ci-zapier.yaml @@ -0,0 +1,60 @@ +name: CI Zapier + +on: + push: + branches: + - main + + pull_request: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + +jobs: + changed-files-check: + uses: ./.github/workflows/changed-files.yaml + with: + files: | + packages/twenty-zapier/** + packages/twenty-server/** + !packages/twenty-zapier/package.json + !packages/twenty-zapier/CHANGELOG.md + zapier-test: + needs: changed-files-check + if: needs.changed-files-check.outputs.any_changed == 'true' + timeout-minutes: 30 + runs-on: ubuntu-latest + strategy: + matrix: + task: [lint, typecheck, test, validate] + steps: + - name: Cancel Previous Runs + uses: styfle/cancel-workflow-action@0.11.0 + with: + access_token: ${{ github.token }} + - name: Fetch custom Github Actions and base branch history + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Install dependencies + uses: ./.github/actions/yarn-install + - name: Build + run: npx nx build twenty-zapier + - name: Run ${{ matrix.task }} task + uses: ./.github/actions/nx-affected + with: + tag: scope:zapier + tasks: ${{ matrix.task }} + ci-zapier-status-check: + if: always() && !cancelled() + timeout-minutes: 5 + runs-on: ubuntu-latest + needs: [changed-files-check, zapier-test] + steps: + - name: Fail job if any needs failed + if: contains(needs.*.result, 'failure') + run: exit 1 diff --git a/eslint.config.mjs b/eslint.config.mjs index 8f8685622e..28a917b803 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -83,6 +83,10 @@ export default [ sourceTag: 'scope:frontend', onlyDependOnLibsWithTags: ['scope:shared', 'scope:frontend'], }, + { + sourceTag: 'scope:zapier', + onlyDependOnLibsWithTags: ['scope:shared', 'scope:zapier'], + }, ], }, ], diff --git a/packages/create-twenty-app/jest.config.mjs b/packages/create-twenty-app/jest.config.mjs index 91035c812a..58fd12ed0a 100644 --- a/packages/create-twenty-app/jest.config.mjs +++ b/packages/create-twenty-app/jest.config.mjs @@ -1,5 +1,5 @@ const jestConfig = { - displayName: 'twenty-cli', + displayName: 'create-twenty-app', preset: '../../jest.preset.js', testEnvironment: 'node', transformIgnorePatterns: ['../../node_modules/'], diff --git a/packages/twenty-zapier/CHANGELOG.md b/packages/twenty-zapier/CHANGELOG.md index da45e65e14..7a953398de 100644 --- a/packages/twenty-zapier/CHANGELOG.md +++ b/packages/twenty-zapier/CHANGELOG.md @@ -1,3 +1,6 @@ +## 2.2.0 +* Fix authentication issue + ## 2.1.1 * Add changelog diff --git a/packages/twenty-zapier/eslint.config.mjs b/packages/twenty-zapier/eslint.config.mjs new file mode 100644 index 0000000000..7750764cd9 --- /dev/null +++ b/packages/twenty-zapier/eslint.config.mjs @@ -0,0 +1,48 @@ +import reactPlugin from 'eslint-plugin-react'; +import reactHooksPlugin from 'eslint-plugin-react-hooks'; +import reactRefreshPlugin from 'eslint-plugin-react-refresh'; +import baseConfig from '../../eslint.config.mjs'; + +export default [ + ...baseConfig, + { + ignores: ['**/dist/**'], + }, + { + files: ['**/*.{js,jsx,ts,tsx}'], + plugins: { + react: reactPlugin, + 'react-hooks': reactHooksPlugin, + 'react-refresh': reactRefreshPlugin, + }, + settings: { + react: { + version: 'detect', + }, + }, + rules: { + 'prettier/prettier': 'error', + 'react/no-unescaped-entities': 'off', + 'react/prop-types': 'off', + 'react/jsx-key': 'off', + 'react/display-name': 'off', + 'react/jsx-uses-react': 'off', + 'react/react-in-jsx-scope': 'off', + 'react/jsx-no-useless-fragment': 'off', + 'react/jsx-props-no-spreading': [ + 'error', + { + explicitSpread: 'ignore', + }, + ], + 'react-hooks/rules-of-hooks': 'error', + 'react-hooks/exhaustive-deps': 'warn', + }, + }, + { + rules: { + 'no-console': 'off', + }, + ignores: ['src/**/*.ts', '!src/cli/**/*.ts'], + }, +]; diff --git a/packages/twenty-zapier/index.js b/packages/twenty-zapier/index.js index 4d5e21a46f..f99edb95d5 100644 --- a/packages/twenty-zapier/index.js +++ b/packages/twenty-zapier/index.js @@ -1 +1 @@ -module.exports = require('./lib').default; +module.exports = require('./lib/index.cjs').default; diff --git a/packages/twenty-zapier/jest.config.mjs b/packages/twenty-zapier/jest.config.mjs index 7f05b6b846..b8806818ca 100644 --- a/packages/twenty-zapier/jest.config.mjs +++ b/packages/twenty-zapier/jest.config.mjs @@ -1,9 +1,12 @@ +import { pathsToModuleNameMapper } from 'ts-jest'; + export default { preset: 'ts-jest', testEnvironment: 'node', - transform: { - '^.+\\.ts?$': 'ts-jest', - }, - moduleFileExtensions: ['ts', 'js'], - transformIgnorePatterns: ['/node_modules/'], + rootDir: './src', + testMatch: ['**/__tests__/**/*.test.ts'], + moduleNameMapper: pathsToModuleNameMapper( + { 'src/*': ['./src/*'] }, + { prefix: '/../' }, + ), }; diff --git a/packages/twenty-zapier/package.json b/packages/twenty-zapier/package.json index c9e3f11c7e..3f7d3b6bbf 100644 --- a/packages/twenty-zapier/package.json +++ b/packages/twenty-zapier/package.json @@ -1,8 +1,8 @@ { "name": "twenty-zapier", - "version": "2.1.1", + "version": "2.2.0", "description": "Effortlessly sync Twenty with 3000+ apps. Automate tasks, boost productivity, and supercharge your customer relationships!", - "main": "src/index.ts", + "main": "lib/index.cjs", "engines": { "node": "^24.5.0", "npm": "please-use-yarn", @@ -22,9 +22,10 @@ "devDependencies": { "jest": "29.7.0", "rimraf": "^3.0.2", + "twenty-shared": "workspace:*", + "vite": "^7.0.0", + "vite-plugin-dts": "^4.5.4", + "vite-tsconfig-paths": "^4.2.1", "zapier-platform-cli": "^15.4.1" - }, - "installConfig": { - "hoistingLimits": "dependencies" } } diff --git a/packages/twenty-zapier/project.json b/packages/twenty-zapier/project.json index f016527de2..46a5412d92 100644 --- a/packages/twenty-zapier/project.json +++ b/packages/twenty-zapier/project.json @@ -8,9 +8,9 @@ "executor": "nx:run-commands", "options": { "cwd": "{projectRoot}", - "commands": ["tsc"] + "commands": ["npx vite build"] }, - "dependsOn": ["clean","^build"] + "dependsOn": ["clean", "^build"] }, "format": { "executor": "nx:run-commands", @@ -23,16 +23,27 @@ "executor": "nx:run-commands", "options": { "cwd": "{projectRoot}", - "commands": ["NODE_ENV=test && nx run twenty-zapier:build && jest --testTimeout 10000 --rootDir ./lib/test"] + "commands": [ + "NODE_ENV=test jest --testTimeout 10000" + ] + } + }, + "lint": { + "options": { + "lintFilePatterns": ["{projectRoot}/src/**/*.{ts,json}"], + "maxWarnings": 0 }, - "dependsOn": ["build"] + "configurations": { + "ci": { "lintFilePatterns": ["{projectRoot}/**/*.{ts,json}"] }, + "fix": {} + } }, "typecheck": {}, "validate": { "executor": "nx:run-commands", "options": { "cwd": "{projectRoot}", - "commands": ["nx run twenty-zapier:build && zapier validate"] + "commands": ["zapier validate"] }, "dependsOn": ["build"] }, @@ -40,10 +51,11 @@ "executor": "nx:run-commands", "options": { "cwd": "{projectRoot}", - "commands": ["nx run twenty-zapier:build && zapier versions"] - } + "commands": ["zapier versions"] + }, + "dependsOn": ["build"] }, - "watch":{ + "watch": { "executor": "nx:run-commands", "options": { "cwd": "{projectRoot}", @@ -55,16 +67,14 @@ "executor": "nx:run-commands", "options": { "cwd": "{projectRoot}", - "commands": ["rimraf ./lib ./build"] + "commands": ["rimraf ./lib"] } }, "deploy": { "executor": "nx:run-commands", "options": { "cwd": "{projectRoot}", - "commands": [ - "nx run twenty-zapier:build && zapier push --disable-dependency-detection" - ] + "commands": ["zapier push --disable-dependency-detection"] }, "dependsOn": ["build"] }, @@ -72,9 +82,7 @@ "executor": "nx:run-commands", "options": { "cwd": "{projectRoot}", - "commands": [ - "zapier promote" - ] + "commands": ["zapier promote"] }, "dependsOn": ["build"] } diff --git a/packages/twenty-zapier/src/test/authentication.test.ts b/packages/twenty-zapier/src/__tests__/authentication.test.ts similarity index 95% rename from packages/twenty-zapier/src/test/authentication.test.ts rename to packages/twenty-zapier/src/__tests__/authentication.test.ts index fa8fe0a631..e32051e987 100644 --- a/packages/twenty-zapier/src/test/authentication.test.ts +++ b/packages/twenty-zapier/src/__tests__/authentication.test.ts @@ -1,7 +1,7 @@ import { createAppTester, tools } from 'zapier-platform-core'; -import App from '../index'; -import getBundle from '../utils/getBundle'; +import App from 'src/index'; +import { getBundle } from 'src/utils/getBundle'; const appTester = createAppTester(App); tools.env.inject(); diff --git a/packages/twenty-zapier/src/authentication.ts b/packages/twenty-zapier/src/authentication.ts index 486c5aedb6..84b3d2e92f 100644 --- a/packages/twenty-zapier/src/authentication.ts +++ b/packages/twenty-zapier/src/authentication.ts @@ -1,13 +1,14 @@ import type { Bundle, ZObject } from 'zapier-platform-core'; -import requestDb from './utils/requestDb'; +import requestDb from 'src/utils/requestDb'; const testAuthentication = async (z: ZObject, bundle: Bundle) => { - return await requestDb( + return await requestDb({ z, bundle, - 'query currentWorkspace {currentWorkspace {id displayName}}', - ); + query: 'query currentWorkspace {currentWorkspace {id displayName}}', + endpoint: 'metadata', + }); }; export default { diff --git a/packages/twenty-zapier/src/test/creates/crud_record.test.ts b/packages/twenty-zapier/src/creates/__tests__/crud_record.test.ts similarity index 84% rename from packages/twenty-zapier/src/test/creates/crud_record.test.ts rename to packages/twenty-zapier/src/creates/__tests__/crud_record.test.ts index d6707137c3..12084222e5 100644 --- a/packages/twenty-zapier/src/test/creates/crud_record.test.ts +++ b/packages/twenty-zapier/src/creates/__tests__/crud_record.test.ts @@ -5,11 +5,11 @@ import { type 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 { DatabaseEventAction } from '../../utils/triggers/triggers.utils'; +import { crudRecordKey } from 'src/creates/crud_record'; +import App from 'src/index'; +import { getBundle } from 'src/utils/getBundle'; +import requestDb from 'src/utils/requestDb'; +import { DatabaseEventAction } from 'src/utils/triggers/triggers.utils'; const appTester = createAppTester(App); tools.env.inject(); @@ -49,11 +49,11 @@ describe('creates.create_company', () => { expect(result.data?.createCompany?.id).toBeDefined(); const checkDbResult = await appTester( (z: ZObject, bundle: Bundle) => - requestDb( + requestDb({ z, bundle, - `query findCompany {company(filter: {id: {eq: "${result.data.createCompany.id}"}}){id annualRecurringRevenue{amountMicros currencyCode}}}`, - ), + query: `query findCompany {company(filter: {id: {eq: "${result.data.createCompany.id}"}}){id annualRecurringRevenue{amountMicros currencyCode}}}`, + }), bundle, ); expect( @@ -83,11 +83,11 @@ describe('creates.create_company', () => { expect(result.data?.createPerson?.id).toBeDefined(); const checkDbResult = await appTester( (z: ZObject, bundle: Bundle) => - requestDb( + requestDb({ z, bundle, - `query findPerson {person(filter: {id: {eq: "${result.data.createPerson.id}"}}){phones{primaryPhoneNumber}}}`, - ), + query: `query findPerson {person(filter: {id: {eq: "${result.data.createPerson.id}"}}){phones{primaryPhoneNumber}}}`, + }), bundle, ); expect(checkDbResult.data.person.phones.primaryPhoneNumber).toEqual( @@ -128,11 +128,11 @@ describe('creates.update_company', () => { expect(updateResult.data?.updateCompany?.id).toBeDefined(); const checkDbResult = await appTester( (z: ZObject, bundle: Bundle) => - requestDb( + requestDb({ z, bundle, - `query findCompany {company(filter: {id: {eq: "${companyId}"}}){id name}}`, - ), + query: `query findCompany {company(filter: {id: {eq: "${companyId}"}}){id name}}`, + }), updateBundle, ); expect(checkDbResult.data.company.name).toEqual('Updated Company Name'); @@ -170,11 +170,11 @@ describe('creates.delete_company', () => { expect(deleteResult.data?.deleteCompany?.id).toBeDefined(); const checkDbResult = await appTester( (z: ZObject, bundle: Bundle) => - requestDb( + requestDb({ z, bundle, - `query findCompanies {companies(filter: {id: {eq: "${companyId}"}}){edges{node{id}}}}`, - ), + query: `query findCompanies {companies(filter: {id: {eq: "${companyId}"}}){edges{node{id}}}}`, + }), deleteBundle, ); expect(checkDbResult.data.companies.edges.length).toEqual(0); diff --git a/packages/twenty-zapier/src/creates/crud_record.ts b/packages/twenty-zapier/src/creates/crud_record.ts index 900f3a4e13..dc0b30c89b 100644 --- a/packages/twenty-zapier/src/creates/crud_record.ts +++ b/packages/twenty-zapier/src/creates/crud_record.ts @@ -1,11 +1,11 @@ import type { Bundle, ZObject } from 'zapier-platform-core'; -import { findObjectNamesSingularKey } from '../triggers/find_object_names_singular'; -import { listRecordIdsKey } from '../triggers/list_record_ids'; -import { computeInputFields } from '../utils/computeInputFields'; -import { type InputData } from '../utils/data.types'; -import handleQueryParams from '../utils/handleQueryParams'; -import requestDb, { requestSchema } from '../utils/requestDb'; -import { DatabaseEventAction } from '../utils/triggers/triggers.utils'; +import { findObjectNamesSingularKey } from 'src/triggers/find_object_names_singular'; +import { listRecordIdsKey } from 'src/triggers/list_record_ids'; +import { computeInputFields } from 'src/utils/computeInputFields'; +import { type InputData } from 'src/utils/data.types'; +import handleQueryParams from 'src/utils/handleQueryParams'; +import requestDb, { requestSchema } from 'src/utils/requestDb'; +import { DatabaseEventAction } from 'src/utils/triggers/triggers.utils'; import { isNonEmptyString } from '@sniptt/guards'; const capitalize = (stringToCapitalize: string) => { @@ -103,7 +103,7 @@ const perform = async (z: ZObject, bundle: Bundle) => { ) {id} }`; - return await requestDb(z, bundle, query); + return await requestDb({ z, bundle, query }); }; export const crudRecordKey = 'crud_record'; diff --git a/packages/twenty-zapier/src/index.ts b/packages/twenty-zapier/src/index.ts index fd458353ce..5901100fdb 100644 --- a/packages/twenty-zapier/src/index.ts +++ b/packages/twenty-zapier/src/index.ts @@ -2,15 +2,15 @@ import { version as platformVersion } from 'zapier-platform-core'; import 'dotenv/config'; -const { version } = require('../package.json'); +import { version } from '../package.json'; -import crudRecord, { crudRecordKey } from './creates/crud_record'; +import crudRecord, { crudRecordKey } from 'src/creates/crud_record'; import findObjectNamesSingular, { findObjectNamesSingularKey, -} from './triggers/find_object_names_singular'; -import listRecordIds, { listRecordIdsKey } from './triggers/list_record_ids'; -import triggerRecord, { triggerRecordKey } from './triggers/trigger_record'; -import authentication from './authentication'; +} from 'src/triggers/find_object_names_singular'; +import listRecordIds, { listRecordIdsKey } from 'src/triggers/list_record_ids'; +import triggerRecord, { triggerRecordKey } from 'src/triggers/trigger_record'; +import authentication from 'src/authentication'; export default { version, diff --git a/packages/twenty-zapier/src/test/triggers/find_object_names_singular.test.ts b/packages/twenty-zapier/src/triggers/__tests__/find_object_names_singular.test.ts similarity index 75% rename from packages/twenty-zapier/src/test/triggers/find_object_names_singular.test.ts rename to packages/twenty-zapier/src/triggers/__tests__/find_object_names_singular.test.ts index d775708aeb..4fe960bbe9 100644 --- a/packages/twenty-zapier/src/test/triggers/find_object_names_singular.test.ts +++ b/packages/twenty-zapier/src/triggers/__tests__/find_object_names_singular.test.ts @@ -1,7 +1,7 @@ import { createAppTester, tools } from 'zapier-platform-core'; -import getBundle from '../../utils/getBundle'; -import App from '../../index'; -import { findObjectNamesSingularKey } from '../../triggers/find_object_names_singular'; +import { getBundle } from 'src/utils/getBundle'; +import App from 'src/index'; +import { findObjectNamesSingularKey } from 'src/triggers/find_object_names_singular'; tools.env.inject(); const appTester = createAppTester(App); diff --git a/packages/twenty-zapier/src/test/triggers/list_record_ids.test.ts b/packages/twenty-zapier/src/triggers/__tests__/list_record_ids.test.ts similarity index 77% rename from packages/twenty-zapier/src/test/triggers/list_record_ids.test.ts rename to packages/twenty-zapier/src/triggers/__tests__/list_record_ids.test.ts index 578b2f02a0..ead59ae623 100644 --- a/packages/twenty-zapier/src/test/triggers/list_record_ids.test.ts +++ b/packages/twenty-zapier/src/triggers/__tests__/list_record_ids.test.ts @@ -1,8 +1,8 @@ import { createAppTester, tools } from 'zapier-platform-core'; -import App from '../../index'; -import { listRecordIdsKey } from '../../triggers/list_record_ids'; -import getBundle from '../../utils/getBundle'; +import App from 'src/index'; +import { listRecordIdsKey } from 'src/triggers/list_record_ids'; +import { getBundle } from 'src/utils/getBundle'; tools.env.inject(); const appTester = createAppTester(App); diff --git a/packages/twenty-zapier/src/test/triggers/trigger_record.test.ts b/packages/twenty-zapier/src/triggers/__tests__/trigger_record.test.ts similarity index 86% rename from packages/twenty-zapier/src/test/triggers/trigger_record.test.ts rename to packages/twenty-zapier/src/triggers/__tests__/trigger_record.test.ts index 2f5fbf4710..5212e1974b 100644 --- a/packages/twenty-zapier/src/test/triggers/trigger_record.test.ts +++ b/packages/twenty-zapier/src/triggers/__tests__/trigger_record.test.ts @@ -4,11 +4,11 @@ import { type 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'; -import { DatabaseEventAction } from '../../utils/triggers/triggers.utils'; +import App from 'src/index'; +import { triggerRecordKey } from 'src/triggers/trigger_record'; +import { getBundle } from 'src/utils/getBundle'; +import requestDb from 'src/utils/requestDb'; +import { DatabaseEventAction } from 'src/utils/triggers/triggers.utils'; const appTester = createAppTester(App); describe('triggers.trigger_record.created', () => { @@ -29,11 +29,12 @@ describe('triggers.trigger_record.created', () => { const checkDbResult = await appTester( (z: ZObject, bundle: Bundle) => - requestDb( + requestDb({ z, bundle, - `query webhook {webhook(input: {id: "${result.id}"}){id operations}}`, - ), + query: `query webhook {webhook(id: "${result.id}"){id operations}}`, + endpoint: 'metadata', + }), bundle, ); @@ -65,7 +66,12 @@ describe('triggers.trigger_record.created', () => { const checkDbResult = await appTester( (z: ZObject, bundle: Bundle) => - requestDb(z, bundle, `query webhook {webhooks {id}}`), + requestDb({ + z, + bundle, + query: `query webhook {webhooks {id}}`, + endpoint: 'metadata', + }), bundle, ); expect( @@ -141,11 +147,12 @@ describe('triggers.trigger_record.update', () => { const checkDbResult = await appTester( (z: ZObject, bundle: Bundle) => - requestDb( + requestDb({ z, bundle, - `query webhook {webhook(input: {id: "${result.id}"}){id operations}}`, - ), + query: `query webhook {webhook(id: "${result.id}"){id operations }}`, + endpoint: 'metadata', + }), bundle, ); @@ -176,7 +183,12 @@ describe('triggers.trigger_record.update', () => { const checkDbResult = await appTester( (z: ZObject, bundle: Bundle) => - requestDb(z, bundle, `query webhook {webhooks {id}}`), + requestDb({ + z, + bundle, + query: `query webhook {webhooks {id}}`, + endpoint: 'metadata', + }), bundle, ); expect( @@ -223,11 +235,12 @@ describe('triggers.trigger_record.delete', () => { const checkDbResult = await appTester( (z: ZObject, bundle: Bundle) => - requestDb( + requestDb({ z, bundle, - `query webhook {webhook(input: {id: "${result.id}"}){id operations}}`, - ), + query: `query webhook {webhook(id: "${result.id}"){id operations }}`, + endpoint: 'metadata', + }), bundle, ); @@ -258,7 +271,12 @@ describe('triggers.trigger_record.delete', () => { const checkDbResult = await appTester( (z: ZObject, bundle: Bundle) => - requestDb(z, bundle, `query webhook {webhooks {id}}`), + requestDb({ + z, + bundle, + query: `query webhook {webhooks {id}}`, + endpoint: 'metadata', + }), bundle, ); expect( diff --git a/packages/twenty-zapier/src/triggers/find_object_names_singular.ts b/packages/twenty-zapier/src/triggers/find_object_names_singular.ts index 77c9107695..0a271e9ffc 100644 --- a/packages/twenty-zapier/src/triggers/find_object_names_singular.ts +++ b/packages/twenty-zapier/src/triggers/find_object_names_singular.ts @@ -1,6 +1,6 @@ import type { Bundle, ZObject } from 'zapier-platform-core'; -import { requestSchema } from '../utils/requestDb'; +import { requestSchema } from 'src/utils/requestDb'; const objectListRequest = async (z: ZObject, bundle: Bundle) => { const schema = await requestSchema(z, bundle); diff --git a/packages/twenty-zapier/src/triggers/list_record_ids.ts b/packages/twenty-zapier/src/triggers/list_record_ids.ts index 9c91ebc7ac..e5003eec69 100644 --- a/packages/twenty-zapier/src/triggers/list_record_ids.ts +++ b/packages/twenty-zapier/src/triggers/list_record_ids.ts @@ -1,4 +1,4 @@ -import { performList } from '../utils/triggers/triggers.utils'; +import { performList } from 'src/utils/triggers/triggers.utils'; export const listRecordIdsKey = 'list_record_ids'; diff --git a/packages/twenty-zapier/src/triggers/trigger_record.ts b/packages/twenty-zapier/src/triggers/trigger_record.ts index c61259dc90..6b48c79804 100644 --- a/packages/twenty-zapier/src/triggers/trigger_record.ts +++ b/packages/twenty-zapier/src/triggers/trigger_record.ts @@ -1,4 +1,4 @@ -import { findObjectNamesSingularKey } from '../triggers/find_object_names_singular'; +import { findObjectNamesSingularKey } from 'src/triggers/find_object_names_singular'; import { performSubscribe, performUnsubscribe, diff --git a/packages/twenty-zapier/src/types/FieldMetadataType.ts b/packages/twenty-zapier/src/types/FieldMetadataType.ts deleted file mode 100644 index 287d2c59d6..0000000000 --- a/packages/twenty-zapier/src/types/FieldMetadataType.ts +++ /dev/null @@ -1,27 +0,0 @@ -export enum FieldMetadataType { - UUID = 'UUID', - TEXT = 'TEXT', - PHONES = 'PHONES', - EMAILS = 'EMAILS', - DATE_TIME = 'DATE_TIME', - DATE = 'DATE', - BOOLEAN = 'BOOLEAN', - NUMBER = 'NUMBER', - NUMERIC = 'NUMERIC', - LINKS = 'LINKS', - CURRENCY = 'CURRENCY', - FULL_NAME = 'FULL_NAME', - RATING = 'RATING', - SELECT = 'SELECT', - MULTI_SELECT = 'MULTI_SELECT', - RELATION = 'RELATION', - MORPH_RELATION = 'MORPH_RELATION', - POSITION = 'POSITION', - ADDRESS = 'ADDRESS', - RAW_JSON = 'RAW_JSON', - RICH_TEXT = 'RICH_TEXT', - RICH_TEXT_V2 = 'RICH_TEXT_V2', - ACTOR = 'ACTOR', - ARRAY = 'ARRAY', - TS_VECTOR = 'TS_VECTOR', -} diff --git a/packages/twenty-zapier/src/test/utils/computeInputFields.test.ts b/packages/twenty-zapier/src/utils/__tests__/computeInputFields.test.ts similarity index 97% rename from packages/twenty-zapier/src/test/utils/computeInputFields.test.ts rename to packages/twenty-zapier/src/utils/__tests__/computeInputFields.test.ts index 7239d03cda..3fd044d8e1 100644 --- a/packages/twenty-zapier/src/test/utils/computeInputFields.test.ts +++ b/packages/twenty-zapier/src/utils/__tests__/computeInputFields.test.ts @@ -1,6 +1,6 @@ -import { FieldMetadataType } from '../../types/FieldMetadataType'; -import { computeInputFields } from '../../utils/computeInputFields'; -import { type InputField } from '../../utils/data.types'; +import { FieldMetadataType } from 'twenty-shared/types'; +import { computeInputFields } from 'src/utils/computeInputFields'; +import { type InputField } from 'src/utils/data.types'; describe('computeInputFields', () => { test('should create Person input fields properly', () => { diff --git a/packages/twenty-zapier/src/test/utils/handleQueryParams.test.ts b/packages/twenty-zapier/src/utils/__tests__/handleQueryParams.test.ts similarity index 97% rename from packages/twenty-zapier/src/test/utils/handleQueryParams.test.ts rename to packages/twenty-zapier/src/utils/__tests__/handleQueryParams.test.ts index ac5f319ce8..17476b57d7 100644 --- a/packages/twenty-zapier/src/test/utils/handleQueryParams.test.ts +++ b/packages/twenty-zapier/src/utils/__tests__/handleQueryParams.test.ts @@ -1,4 +1,4 @@ -import handleQueryParams from '../../utils/handleQueryParams'; +import handleQueryParams from 'src/utils/handleQueryParams'; describe('utils.handleQueryParams', () => { test('should handle empty values', () => { diff --git a/packages/twenty-zapier/src/utils/computeInputFields.ts b/packages/twenty-zapier/src/utils/computeInputFields.ts index 186f7c85f6..e06ccf80b3 100644 --- a/packages/twenty-zapier/src/utils/computeInputFields.ts +++ b/packages/twenty-zapier/src/utils/computeInputFields.ts @@ -1,9 +1,9 @@ -import { FieldMetadataType } from '../types/FieldMetadataType'; +import { FieldMetadataType } from 'twenty-shared/types'; import { type InputField, type Node, type NodeField, -} from '../utils/data.types'; +} from 'src/utils/data.types'; const getListFromFieldMetadataType = (fieldMetadataType: FieldMetadataType) => { return fieldMetadataType === FieldMetadataType.ARRAY; diff --git a/packages/twenty-zapier/src/utils/data.types.ts b/packages/twenty-zapier/src/utils/data.types.ts index ac9ff0c52e..c70ccafb02 100644 --- a/packages/twenty-zapier/src/utils/data.types.ts +++ b/packages/twenty-zapier/src/utils/data.types.ts @@ -1,4 +1,4 @@ -import { type FieldMetadataType } from '../types/FieldMetadataType'; +import { type FieldMetadataType } from 'twenty-shared/types'; export type InputData = { [x: string]: any }; diff --git a/packages/twenty-zapier/src/utils/getBundle.ts b/packages/twenty-zapier/src/utils/getBundle.ts index ed31f7aff3..8095437ee5 100644 --- a/packages/twenty-zapier/src/utils/getBundle.ts +++ b/packages/twenty-zapier/src/utils/getBundle.ts @@ -1,8 +1,8 @@ import { type Bundle } from 'zapier-platform-core'; -import { type InputData } from '../utils/data.types'; +import { type InputData } from 'src/utils/data.types'; -const getBundle = (inputData?: InputData): Bundle => { +export const getBundle = (inputData?: InputData): Bundle => { return { authData: { apiKey: String(process.env.API_KEY) }, inputData: inputData || {}, @@ -19,4 +19,3 @@ const getBundle = (inputData?: InputData): Bundle => { }, }; }; -export default getBundle; diff --git a/packages/twenty-zapier/src/utils/handleQueryParams.ts b/packages/twenty-zapier/src/utils/handleQueryParams.ts index e94c835371..6a10214c8e 100644 --- a/packages/twenty-zapier/src/utils/handleQueryParams.ts +++ b/packages/twenty-zapier/src/utils/handleQueryParams.ts @@ -1,4 +1,4 @@ -import { type InputData } from '../utils/data.types'; +import { type InputData } from 'src/utils/data.types'; const OBJECT_SUBFIELD_NAMES = ['secondaryLinks', 'additionalPhones']; diff --git a/packages/twenty-zapier/src/utils/requestDb.ts b/packages/twenty-zapier/src/utils/requestDb.ts index e5e4a9374a..1f6dbe8172 100644 --- a/packages/twenty-zapier/src/utils/requestDb.ts +++ b/packages/twenty-zapier/src/utils/requestDb.ts @@ -1,6 +1,6 @@ import type { Bundle, HttpRequestOptions, ZObject } from 'zapier-platform-core'; -import { type Schema } from '../utils/data.types'; +import { type Schema } from 'src/utils/data.types'; export const requestSchema = async ( z: ZObject, @@ -29,16 +29,20 @@ export const requestSchema = async ( } } }`; - const endpoint = 'metadata'; - return await requestDb(z, bundle, query, endpoint); + return await requestDb({ z, bundle, query, endpoint: 'metadata' }); }; -const requestDb = async ( - z: ZObject, - bundle: Bundle, - query: string, +const requestDb = async ({ + z, + bundle, + query, endpoint = 'graphql', -) => { +}: { + z: ZObject; + bundle: Bundle; + query: string; + endpoint?: string; +}) => { const options = { url: `${bundle.authData.apiUrl || process.env.SERVER_BASE_URL}/${endpoint}`, method: 'POST', diff --git a/packages/twenty-zapier/src/utils/triggers/triggers.utils.ts b/packages/twenty-zapier/src/utils/triggers/triggers.utils.ts index e428de3f5c..d4845625f0 100644 --- a/packages/twenty-zapier/src/utils/triggers/triggers.utils.ts +++ b/packages/twenty-zapier/src/utils/triggers/triggers.utils.ts @@ -1,10 +1,10 @@ import { type Bundle, type ZObject } from 'zapier-platform-core'; -import handleQueryParams from '../../utils/handleQueryParams'; import requestDb, { requestDbViaRestApi, requestSchema, -} from '../../utils/requestDb'; +} from 'src/utils/requestDb'; +import handleQueryParams from 'src/utils/handleQueryParams'; export enum DatabaseEventAction { CREATED = 'created', @@ -20,14 +20,14 @@ export const performSubscribe = async (z: ZObject, bundle: Bundle) => { ], secret: '', }; - const result = await requestDb( + const result = await requestDb({ z, bundle, - `mutation createWebhook {createWebhook(input:{${handleQueryParams( + query: `mutation createWebhook {createWebhook(input:{${handleQueryParams( data, )}}) {id}}`, - 'metadata', - ); + endpoint: 'metadata', + }); return result.data.createWebhook; }; @@ -36,12 +36,12 @@ export const performUnsubscribe = async ( bundle: Bundle, ): Promise => { const data = { id: bundle.subscribeData?.id }; - const result = await requestDb( + const result = await requestDb({ z, bundle, - `mutation deleteWebhook {deleteWebhook(input: {${handleQueryParams(data)}})}`, - 'metadata', - ); + query: `mutation deleteWebhook {deleteWebhook(${handleQueryParams(data)}) {id}}`, + endpoint: 'metadata', + }); return result.data.deleteWebhook; }; diff --git a/packages/twenty-zapier/tsconfig.json b/packages/twenty-zapier/tsconfig.json index f572dc731f..e21946126b 100644 --- a/packages/twenty-zapier/tsconfig.json +++ b/packages/twenty-zapier/tsconfig.json @@ -1,16 +1,18 @@ { + "extends": "../../tsconfig.base.json", "compilerOptions": { "target": "es2019", "module": "commonjs", "moduleResolution": "node", "lib": ["esnext"], - "outDir": "./lib", - "rootDir": "./src", + "outDir": "lib", + "rootDir": ".", "strict": true, "esModuleInterop": true, "skipLibCheck": true, + "paths": { + "src/*": ["./src/*"] + } }, - "exclude": [ - "jest.config.mjs" - ] + "exclude": ["node_modules", "lib"] } diff --git a/packages/twenty-zapier/vite.config.ts b/packages/twenty-zapier/vite.config.ts new file mode 100644 index 0000000000..045d15641d --- /dev/null +++ b/packages/twenty-zapier/vite.config.ts @@ -0,0 +1,72 @@ +import { defineConfig } from 'vite'; + +import tsconfigPaths from 'vite-tsconfig-paths'; +import packageJson from './package.json'; +import type { PackageJson } from 'type-fest'; + +const entryFileNames = (chunk: any, extension: 'cjs') => { + if (!chunk.isEntry) { + throw new Error( + `Should never occurs, encountered a non entry chunk ${chunk.facadeModuleId}`, + ); + } + + const splitFaceModuleId = chunk.facadeModuleId?.split('/'); + if (splitFaceModuleId === undefined) { + throw new Error( + `Should never occurs splitFaceModuleId is undefined ${chunk.facadeModuleId}`, + ); + } + + const moduleDirectory = splitFaceModuleId[splitFaceModuleId?.length - 2]; + if (moduleDirectory === 'src') { + return `${chunk.name}.${extension}`; + } + return `${moduleDirectory}.${extension}`; +}; + +export default defineConfig(() => { + return { + root: __dirname, + cacheDir: '../../node_modules/.vite/packages/twenty-zapier', + plugins: [ + tsconfigPaths({ + root: __dirname, + }), + ], + build: { + emptyOutDir: false, + outDir: 'lib', + lib: { entry: 'src/index.ts', name: 'twenty-zapier' }, + rollupOptions: { + external: (id: string) => { + if (/^node:/.test(id)) { + return true; + } + + const builtins = ['path', 'fs', 'child_process', 'util']; + + if (builtins.includes(id)) { + return true; + } + + const deps = Object.keys( + (packageJson as PackageJson).dependencies || {}, + ); + + return deps.some((dep) => id === dep || id.startsWith(dep + '/')); + }, + output: [ + { + format: 'cjs', + interop: 'auto', + esModule: true, + exports: 'named', + entryFileNames: (chunk) => entryFileNames(chunk, 'cjs'), + }, + ], + }, + }, + logLevel: 'warn', + }; +}); diff --git a/yarn.lock b/yarn.lock index e0d054673f..3483e773cc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -59113,6 +59113,10 @@ __metadata: jest: "npm:29.7.0" libphonenumber-js: "npm:^1.10.26" rimraf: "npm:^3.0.2" + twenty-shared: "workspace:*" + vite: "npm:^7.0.0" + vite-plugin-dts: "npm:^4.5.4" + vite-tsconfig-paths: "npm:^4.2.1" zapier-platform-cli: "npm:^15.4.1" zapier-platform-core: "npm:15.5.1" zod: "npm:^4.1.11"