Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
48e658df57 | ||
|
|
5874fb5f39 | ||
|
|
37dbd94596 | ||
|
|
238018dc7b | ||
|
|
2267c56f15 | ||
|
|
7aed9291cd | ||
|
|
5c867303e0 | ||
|
|
fda3eabb5f | ||
|
|
7d6111b0a5 | ||
|
|
4df3539ba1 | ||
|
|
8905d860c7 | ||
|
|
bc7b5aee58 | ||
|
|
31b6dbc583 | ||
|
|
3306d66f5b | ||
|
|
6cd3f2db2b | ||
|
|
0e0fb246e6 | ||
|
|
83917f0dca | ||
|
|
ac4819758d | ||
|
|
d07c27a907 | ||
|
|
265d859c6e | ||
|
|
1ae88f4e4f | ||
|
|
85be463487 | ||
|
|
8a84e32cf6 | ||
|
|
8aa208fc93 | ||
|
|
9a58f3d459 | ||
|
|
9d96e529c8 | ||
|
|
e9310555fb | ||
|
|
8090fa4364 | ||
|
|
90de1d4a34 | ||
|
|
8026451220 | ||
|
|
b3d46b0fa3 | ||
|
|
a8085db5fd | ||
|
|
b540ae9735 | ||
|
|
20adb86917 | ||
|
|
c91d642f29 | ||
|
|
15eb3e7edc | ||
|
|
af3423dc6f | ||
|
|
a0484f686a | ||
|
|
5c8b6e395b | ||
|
|
9bdef449e6 | ||
|
|
e2bd3e8ef4 | ||
|
|
c0eacedfec | ||
|
|
24a5273a79 | ||
|
|
607e708670 | ||
|
|
61abfd103d | ||
|
|
54be3b7e87 | ||
|
|
137e068ced | ||
|
|
91f8f7329a | ||
|
|
d341d0d624 | ||
|
|
5e9792009f | ||
|
|
38802bd0b8 | ||
|
|
e692e97428 | ||
|
|
1f3965e5f8 | ||
|
|
e048d03872 | ||
|
|
653180d10f | ||
|
|
8702300b07 | ||
|
|
6e23ca35e6 | ||
|
|
96a242eb7d | ||
|
|
d97a1cfc27 | ||
|
|
c844109ffc | ||
|
|
dd2a09576b | ||
|
|
fe07de63b0 | ||
|
|
1c9fc94c1f | ||
|
|
d10ef156c1 | ||
|
|
d3ec64072b | ||
|
|
1b14e7e1f1 | ||
|
|
6ad9566043 | ||
|
|
f39fccc3c4 | ||
|
|
ac1ec91f25 | ||
|
|
d324bbfc25 | ||
|
|
7c2a9abed4 | ||
|
|
c0c0cbb896 | ||
|
|
a2188cb0eb | ||
|
|
23874848a4 | ||
|
|
b23d2b4e73 | ||
|
|
601dc02ed7 | ||
|
|
2d552fc9fd | ||
|
|
f33ad53e72 | ||
|
|
7053e1bbc5 | ||
|
|
955aa9191f | ||
|
|
3f87d27d5d | ||
|
|
68cd2f6d61 | ||
|
|
8c9228cb2b | ||
|
|
35b76539cc | ||
|
|
ea4ef99565 | ||
|
|
c7d1cd11e0 | ||
|
|
83d30f8b76 |
@@ -85,7 +85,6 @@ npx nx run twenty-server:test:integration:with-db-reset # Run integration tests
|
||||
npx nx run twenty-server:typeorm migration:generate src/database/typeorm/core/migrations/[name] -d src/database/typeorm/core/core.datasource.ts
|
||||
|
||||
# Workspace
|
||||
npx nx run twenty-server:command workspace:sync-metadata -f # Sync metadata
|
||||
```
|
||||
|
||||
## Usage Guidelines
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
name: Deploy Twenty App
|
||||
description: Build and deploy a Twenty app to a remote instance
|
||||
|
||||
inputs:
|
||||
api-url:
|
||||
description: Base URL of the target Twenty instance (e.g. https://my.twenty.instance)
|
||||
required: true
|
||||
api-key:
|
||||
description: API key or access token for the target instance
|
||||
required: true
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Enable Corepack
|
||||
shell: bash
|
||||
run: corepack enable
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: yarn
|
||||
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
run: yarn install --immutable
|
||||
|
||||
- name: Configure remote
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p ~/.twenty
|
||||
node -e "
|
||||
const fs = require('fs'), path = require('path'), os = require('os');
|
||||
fs.writeFileSync(path.join(os.homedir(), '.twenty', 'config.json'), JSON.stringify({
|
||||
version: 1,
|
||||
remotes: { target: { apiUrl: process.env.API_URL, apiKey: process.env.API_KEY } }
|
||||
}, null, 2));
|
||||
"
|
||||
env:
|
||||
API_URL: ${{ inputs.api-url }}
|
||||
API_KEY: ${{ inputs.api-key }}
|
||||
|
||||
- name: Deploy
|
||||
shell: bash
|
||||
run: yarn twenty deploy --remote target
|
||||
@@ -0,0 +1,46 @@
|
||||
name: Install Twenty App
|
||||
description: Install (or upgrade) a Twenty app on a specific workspace
|
||||
|
||||
inputs:
|
||||
api-url:
|
||||
description: Base URL of the target Twenty instance (e.g. https://my.twenty.instance)
|
||||
required: true
|
||||
api-key:
|
||||
description: API key or access token for the target workspace
|
||||
required: true
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Enable Corepack
|
||||
shell: bash
|
||||
run: corepack enable
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: yarn
|
||||
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
run: yarn install --immutable
|
||||
|
||||
- name: Configure remote
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p ~/.twenty
|
||||
node -e "
|
||||
const fs = require('fs'), path = require('path'), os = require('os');
|
||||
fs.writeFileSync(path.join(os.homedir(), '.twenty', 'config.json'), JSON.stringify({
|
||||
version: 1,
|
||||
remotes: { target: { apiUrl: process.env.API_URL, apiKey: process.env.API_KEY } }
|
||||
}, null, 2));
|
||||
"
|
||||
env:
|
||||
API_URL: ${{ inputs.api-url }}
|
||||
API_KEY: ${{ inputs.api-key }}
|
||||
|
||||
- name: Install
|
||||
shell: bash
|
||||
run: yarn twenty install --remote target
|
||||
@@ -0,0 +1,47 @@
|
||||
name: Spawn Twenty App Dev Test
|
||||
description: >
|
||||
Starts a Twenty all-in-one test instance (server, worker, database, redis)
|
||||
using the twentycrm/twenty-app-dev Docker image on port 2021.
|
||||
The server is available at http://localhost:2021 with seeded demo data.
|
||||
|
||||
inputs:
|
||||
twenty-version:
|
||||
description: 'Twenty Docker Hub image tag for twenty-app-dev (e.g., "latest" or "v1.20.0").'
|
||||
required: false
|
||||
default: 'latest'
|
||||
|
||||
outputs:
|
||||
server-url:
|
||||
description: 'URL where the Twenty test server can be reached'
|
||||
value: http://localhost:2021
|
||||
api-key:
|
||||
description: 'API key for the Twenty test instance'
|
||||
value: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyMDIwMjAyMC05ZTNiLTQ2ZDQtYTU1Ni04OGI5ZGRjMmIwMzQiLCJ1c2VySWQiOiIyMDIwMjAyMC05ZTNiLTQ2ZDQtYTU1Ni04OGI5ZGRjMmIwMzQiLCJ3b3Jrc3BhY2VJZCI6IjIwMjAyMDIwLTFjMjUtNGQwMi1iZjI1LTZhZWNjZjdlYTQxOSIsIndvcmtzcGFjZU1lbWJlcklkIjoiMjAyMDIwMjAtMDY4Ny00YzQxLWI3MDctZWQxYmZjYTk3MmE3IiwidXNlcldvcmtzcGFjZUlkIjoiMjAyMDIwMjAtOWUzYi00NmQ0LWE1NTYtODhiOWRkYzJiMDM1IiwidHlwZSI6IkFDQ0VTUyIsImF1dGhQcm92aWRlciI6InBhc3N3b3JkIiwiaWF0IjoxNzUxMjgxNzA0LCJleHAiOjQ5MDQ4ODE3MDR9.9S4wc0MOr5iczsomlFxZdOHD1IRDS4dnRSwNVNpctF4
|
||||
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Start twenty-app-dev-test container
|
||||
shell: bash
|
||||
run: |
|
||||
docker run -d \
|
||||
--name twenty-app-dev-test \
|
||||
-p 2021:2021 \
|
||||
-e NODE_PORT=2021 \
|
||||
-e SERVER_URL=http://localhost:2021 \
|
||||
twentycrm/twenty-app-dev:${{ inputs.twenty-version }}
|
||||
|
||||
echo "Waiting for Twenty test instance to become healthy…"
|
||||
TIMEOUT=180
|
||||
ELAPSED=0
|
||||
until curl -sf http://localhost:2021/healthz > /dev/null 2>&1; do
|
||||
if [ "$ELAPSED" -ge "$TIMEOUT" ]; then
|
||||
echo "::error::Twenty did not become healthy within ${TIMEOUT}s"
|
||||
docker logs twenty-app-dev-test 2>&1 | tail -80
|
||||
exit 1
|
||||
fi
|
||||
sleep 3
|
||||
ELAPSED=$((ELAPSED + 3))
|
||||
echo " … waited ${ELAPSED}s"
|
||||
done
|
||||
echo "Twenty test instance is ready at http://localhost:2021 (took ~${ELAPSED}s)"
|
||||
@@ -25,12 +25,10 @@ jobs:
|
||||
packages/twenty-sdk/**
|
||||
packages/twenty-client-sdk/**
|
||||
packages/twenty-shared/**
|
||||
packages/twenty-server/**
|
||||
!packages/create-twenty-app/package.json
|
||||
!packages/twenty-sdk/package.json
|
||||
!packages/twenty-client-sdk/package.json
|
||||
!packages/twenty-shared/package.json
|
||||
!packages/twenty-server/package.json
|
||||
create-app-e2e-hello-world:
|
||||
needs: changed-files-check
|
||||
if: needs.changed-files-check.outputs.any_changed == 'true'
|
||||
@@ -55,6 +53,8 @@ jobs:
|
||||
- 6379:6379
|
||||
env:
|
||||
PUBLISHABLE_PACKAGES: twenty-client-sdk twenty-sdk create-twenty-app
|
||||
TWENTY_API_URL: http://localhost:3000
|
||||
TWENTY_API_KEY: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ1c2VySWQiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ3b3Jrc3BhY2VJZCI6IjIwMjAyMDIwLTFjMjUtNGQwMi1iZjI1LTZhZWNjZjdlYTQxOSIsIndvcmtzcGFjZU1lbWJlcklkIjoiMjAyMDIwMjAtNDYzZi00MzViLTgyOGMtMTA3ZTAwN2EyNzExIiwidXNlcldvcmtzcGFjZUlkIjoiMjAyMDIwMjAtMWU3Yy00M2Q5LWE1ZGItNjg1YjUwNjlkODE2IiwidHlwZSI6IkFDQ0VTUyIsImF1dGhQcm92aWRlciI6InBhc3N3b3JkIiwiaWF0IjoxNzUxMjgxNzA0LCJleHAiOjIwNjY4NTc3MDR9.HMGqCsVlOAPVUBhKSGlD1X86VoHKt4LIUtET3CGIdik
|
||||
steps:
|
||||
- name: Fetch custom Github Actions and base branch history
|
||||
uses: actions/checkout@v4
|
||||
@@ -139,30 +139,19 @@ jobs:
|
||||
cd /tmp/e2e-test-workspace/test-app
|
||||
npx --no-install twenty --version
|
||||
|
||||
- name: Setup server environment
|
||||
run: npx nx reset:env:e2e-testing-server twenty-server
|
||||
- name: Create test database
|
||||
run: PGPASSWORD=postgres psql -h localhost -p 5432 -U postgres -d postgres -c 'CREATE DATABASE "test";'
|
||||
|
||||
- name: Build server
|
||||
run: npx nx build twenty-server
|
||||
- name: Setup database and start server
|
||||
run: npx nx run twenty-server:database:reset && nohup npx nx start:ci twenty-server &
|
||||
|
||||
- name: Create and setup database
|
||||
run: |
|
||||
PGPASSWORD=postgres psql -h localhost -p 5432 -U postgres -d postgres -c 'CREATE DATABASE "default";'
|
||||
PGPASSWORD=postgres psql -h localhost -p 5432 -U postgres -d postgres -c 'CREATE DATABASE "test";'
|
||||
npx nx run twenty-server:database:reset
|
||||
|
||||
- name: Start server
|
||||
run: |
|
||||
npx nx start twenty-server &
|
||||
echo "Waiting for server to be ready..."
|
||||
timeout 60 bash -c 'until curl -s http://localhost:3000/health; do sleep 2; done'
|
||||
- name: Wait for server to be ready
|
||||
run: npx wait-on http://localhost:3000/healthz --timeout 120000 --interval 1000
|
||||
|
||||
- name: Authenticate with twenty-server
|
||||
env:
|
||||
SEED_API_KEY: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ1c2VySWQiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ3b3Jrc3BhY2VJZCI6IjIwMjAyMDIwLTFjMjUtNGQwMi1iZjI1LTZhZWNjZjdlYTQxOSIsIndvcmtzcGFjZU1lbWJlcklkIjoiMjAyMDIwMjAtNDYzZi00MzViLTgyOGMtMTA3ZTAwN2EyNzExIiwidXNlcldvcmtzcGFjZUlkIjoiMjAyMDIwMjAtMWU3Yy00M2Q5LWE1ZGItNjg1YjUwNjlkODE2IiwidHlwZSI6IkFDQ0VTUyIsImF1dGhQcm92aWRlciI6InBhc3N3b3JkIiwiaWF0IjoxNzUxMjgxNzA0LCJleHAiOjIwNjY4NTc3MDR9.HMGqCsVlOAPVUBhKSGlD1X86VoHKt4LIUtET3CGIdik'
|
||||
run: |
|
||||
cd /tmp/e2e-test-workspace/test-app
|
||||
npx --no-install twenty remote add --api-key $SEED_API_KEY --api-url http://localhost:3000
|
||||
npx --no-install twenty remote add --api-key ${{ env.TWENTY_API_KEY }} --api-url ${{ env.TWENTY_API_URL }}
|
||||
|
||||
- name: Deploy scaffolded app
|
||||
run: |
|
||||
@@ -189,8 +178,6 @@ jobs:
|
||||
echo "$EXEC_OUTPUT" | grep -q 'Created company.*Hello World.*with id'
|
||||
|
||||
- name: Run scaffolded app integration test
|
||||
env:
|
||||
TWENTY_API_URL: http://localhost:3000
|
||||
run: |
|
||||
cd /tmp/e2e-test-workspace/test-app
|
||||
yarn test
|
||||
|
||||
@@ -23,12 +23,10 @@ jobs:
|
||||
packages/twenty-sdk/**
|
||||
packages/twenty-client-sdk/**
|
||||
packages/twenty-shared/**
|
||||
packages/twenty-server/**
|
||||
!packages/create-twenty-app/package.json
|
||||
!packages/twenty-sdk/package.json
|
||||
!packages/twenty-client-sdk/package.json
|
||||
!packages/twenty-shared/package.json
|
||||
!packages/twenty-server/package.json
|
||||
create-app-e2e-minimal:
|
||||
needs: changed-files-check
|
||||
if: needs.changed-files-check.outputs.any_changed == 'true'
|
||||
@@ -53,6 +51,8 @@ jobs:
|
||||
- 6379:6379
|
||||
env:
|
||||
PUBLISHABLE_PACKAGES: twenty-client-sdk twenty-sdk create-twenty-app
|
||||
TWENTY_API_URL: http://localhost:3000
|
||||
TWENTY_API_KEY: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ1c2VySWQiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ3b3Jrc3BhY2VJZCI6IjIwMjAyMDIwLTFjMjUtNGQwMi1iZjI1LTZhZWNjZjdlYTQxOSIsIndvcmtzcGFjZU1lbWJlcklkIjoiMjAyMDIwMjAtNDYzZi00MzViLTgyOGMtMTA3ZTAwN2EyNzExIiwidXNlcldvcmtzcGFjZUlkIjoiMjAyMDIwMjAtMWU3Yy00M2Q5LWE1ZGItNjg1YjUwNjlkODE2IiwidHlwZSI6IkFDQ0VTUyIsImF1dGhQcm92aWRlciI6InBhc3N3b3JkIiwiaWF0IjoxNzUxMjgxNzA0LCJleHAiOjIwNjY4NTc3MDR9.HMGqCsVlOAPVUBhKSGlD1X86VoHKt4LIUtET3CGIdik
|
||||
steps:
|
||||
- name: Fetch custom Github Actions and base branch history
|
||||
uses: actions/checkout@v4
|
||||
@@ -133,30 +133,19 @@ jobs:
|
||||
cd /tmp/e2e-test-workspace/test-app
|
||||
npx --no-install twenty --version
|
||||
|
||||
- name: Setup server environment
|
||||
run: npx nx reset:env:e2e-testing-server twenty-server
|
||||
- name: Create test database
|
||||
run: PGPASSWORD=postgres psql -h localhost -p 5432 -U postgres -d postgres -c 'CREATE DATABASE "test";'
|
||||
|
||||
- name: Build server
|
||||
run: npx nx build twenty-server
|
||||
- name: Setup database and start server
|
||||
run: npx nx run twenty-server:database:reset && nohup npx nx start:ci twenty-server &
|
||||
|
||||
- name: Create and setup database
|
||||
run: |
|
||||
PGPASSWORD=postgres psql -h localhost -p 5432 -U postgres -d postgres -c 'CREATE DATABASE "default";'
|
||||
PGPASSWORD=postgres psql -h localhost -p 5432 -U postgres -d postgres -c 'CREATE DATABASE "test";'
|
||||
npx nx run twenty-server:database:reset
|
||||
|
||||
- name: Start server
|
||||
run: |
|
||||
npx nx start twenty-server &
|
||||
echo "Waiting for server to be ready..."
|
||||
timeout 60 bash -c 'until curl -s http://localhost:3000/health; do sleep 2; done'
|
||||
- name: Wait for server to be ready
|
||||
run: npx wait-on http://localhost:3000/healthz --timeout 120000 --interval 1000
|
||||
|
||||
- name: Authenticate with twenty-server
|
||||
env:
|
||||
SEED_API_KEY: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ1c2VySWQiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ3b3Jrc3BhY2VJZCI6IjIwMjAyMDIwLTFjMjUtNGQwMi1iZjI1LTZhZWNjZjdlYTQxOSIsIndvcmtzcGFjZU1lbWJlcklkIjoiMjAyMDIwMjAtNDYzZi00MzViLTgyOGMtMTA3ZTAwN2EyNzExIiwidXNlcldvcmtzcGFjZUlkIjoiMjAyMDIwMjAtMWU3Yy00M2Q5LWE1ZGItNjg1YjUwNjlkODE2IiwidHlwZSI6IkFDQ0VTUyIsImF1dGhQcm92aWRlciI6InBhc3N3b3JkIiwiaWF0IjoxNzUxMjgxNzA0LCJleHAiOjIwNjY4NTc3MDR9.HMGqCsVlOAPVUBhKSGlD1X86VoHKt4LIUtET3CGIdik'
|
||||
run: |
|
||||
cd /tmp/e2e-test-workspace/test-app
|
||||
npx --no-install twenty remote add --api-key $SEED_API_KEY --api-url http://localhost:3000
|
||||
npx --no-install twenty remote add --api-key ${{ env.TWENTY_API_KEY }} --api-url ${{ env.TWENTY_API_URL }}
|
||||
|
||||
- name: Deploy scaffolded app
|
||||
run: |
|
||||
@@ -169,8 +158,6 @@ jobs:
|
||||
npx --no-install twenty install
|
||||
|
||||
- name: Run scaffolded app integration test
|
||||
env:
|
||||
TWENTY_API_URL: http://localhost:3000
|
||||
run: |
|
||||
cd /tmp/e2e-test-workspace/test-app
|
||||
yarn test
|
||||
|
||||
@@ -25,12 +25,10 @@ jobs:
|
||||
packages/twenty-sdk/**
|
||||
packages/twenty-client-sdk/**
|
||||
packages/twenty-shared/**
|
||||
packages/twenty-server/**
|
||||
!packages/create-twenty-app/package.json
|
||||
!packages/twenty-sdk/package.json
|
||||
!packages/twenty-client-sdk/package.json
|
||||
!packages/twenty-shared/package.json
|
||||
!packages/twenty-server/package.json
|
||||
create-app-e2e-postcard:
|
||||
needs: changed-files-check
|
||||
if: needs.changed-files-check.outputs.any_changed == 'true'
|
||||
@@ -55,6 +53,8 @@ jobs:
|
||||
- 6379:6379
|
||||
env:
|
||||
PUBLISHABLE_PACKAGES: twenty-client-sdk twenty-sdk create-twenty-app
|
||||
TWENTY_API_URL: http://localhost:3000
|
||||
TWENTY_API_KEY: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ1c2VySWQiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ3b3Jrc3BhY2VJZCI6IjIwMjAyMDIwLTFjMjUtNGQwMi1iZjI1LTZhZWNjZjdlYTQxOSIsIndvcmtzcGFjZU1lbWJlcklkIjoiMjAyMDIwMjAtNDYzZi00MzViLTgyOGMtMTA3ZTAwN2EyNzExIiwidXNlcldvcmtzcGFjZUlkIjoiMjAyMDIwMjAtMWU3Yy00M2Q5LWE1ZGItNjg1YjUwNjlkODE2IiwidHlwZSI6IkFDQ0VTUyIsImF1dGhQcm92aWRlciI6InBhc3N3b3JkIiwiaWF0IjoxNzUxMjgxNzA0LCJleHAiOjIwNjY4NTc3MDR9.HMGqCsVlOAPVUBhKSGlD1X86VoHKt4LIUtET3CGIdik
|
||||
steps:
|
||||
- name: Fetch custom Github Actions and base branch history
|
||||
uses: actions/checkout@v4
|
||||
@@ -137,30 +137,19 @@ jobs:
|
||||
cd /tmp/e2e-test-workspace/test-app
|
||||
npx --no-install twenty --version
|
||||
|
||||
- name: Setup server environment
|
||||
run: npx nx reset:env:e2e-testing-server twenty-server
|
||||
- name: Create test database
|
||||
run: PGPASSWORD=postgres psql -h localhost -p 5432 -U postgres -d postgres -c 'CREATE DATABASE "test";'
|
||||
|
||||
- name: Build server
|
||||
run: npx nx build twenty-server
|
||||
- name: Setup database and start server
|
||||
run: npx nx run twenty-server:database:reset && nohup npx nx start:ci twenty-server &
|
||||
|
||||
- name: Create and setup database
|
||||
run: |
|
||||
PGPASSWORD=postgres psql -h localhost -p 5432 -U postgres -d postgres -c 'CREATE DATABASE "default";'
|
||||
PGPASSWORD=postgres psql -h localhost -p 5432 -U postgres -d postgres -c 'CREATE DATABASE "test";'
|
||||
npx nx run twenty-server:database:reset
|
||||
|
||||
- name: Start server
|
||||
run: |
|
||||
npx nx start twenty-server &
|
||||
echo "Waiting for server to be ready..."
|
||||
timeout 60 bash -c 'until curl -s http://localhost:3000/health; do sleep 2; done'
|
||||
- name: Wait for server to be ready
|
||||
run: npx wait-on http://localhost:3000/healthz --timeout 120000 --interval 1000
|
||||
|
||||
- name: Authenticate with twenty-server
|
||||
env:
|
||||
SEED_API_KEY: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ1c2VySWQiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ3b3Jrc3BhY2VJZCI6IjIwMjAyMDIwLTFjMjUtNGQwMi1iZjI1LTZhZWNjZjdlYTQxOSIsIndvcmtzcGFjZU1lbWJlcklkIjoiMjAyMDIwMjAtNDYzZi00MzViLTgyOGMtMTA3ZTAwN2EyNzExIiwidXNlcldvcmtzcGFjZUlkIjoiMjAyMDIwMjAtMWU3Yy00M2Q5LWE1ZGItNjg1YjUwNjlkODE2IiwidHlwZSI6IkFDQ0VTUyIsImF1dGhQcm92aWRlciI6InBhc3N3b3JkIiwiaWF0IjoxNzUxMjgxNzA0LCJleHAiOjIwNjY4NTc3MDR9.HMGqCsVlOAPVUBhKSGlD1X86VoHKt4LIUtET3CGIdik'
|
||||
run: |
|
||||
cd /tmp/e2e-test-workspace/test-app
|
||||
npx --no-install twenty remote add --api-key $SEED_API_KEY --api-url http://localhost:3000
|
||||
npx --no-install twenty remote add --api-key ${{ env.TWENTY_API_KEY }} --api-url ${{ env.TWENTY_API_URL }}
|
||||
|
||||
- name: Deploy scaffolded app
|
||||
run: |
|
||||
@@ -187,8 +176,6 @@ jobs:
|
||||
echo "$EXEC_OUTPUT" | grep -q 'Created company.*Hello World.*with id'
|
||||
|
||||
- name: Run scaffolded app integration test
|
||||
env:
|
||||
TWENTY_API_URL: http://localhost:3000
|
||||
run: |
|
||||
cd /tmp/e2e-test-workspace/test-app
|
||||
yarn test
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
name: CI Example App Hello World
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
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-apps/examples/hello-world/**
|
||||
packages/twenty-sdk/**
|
||||
packages/twenty-client-sdk/**
|
||||
packages/twenty-shared/**
|
||||
!packages/twenty-sdk/package.json
|
||||
!packages/twenty-client-sdk/package.json
|
||||
!packages/twenty-shared/package.json
|
||||
|
||||
example-app-hello-world:
|
||||
needs: changed-files-check
|
||||
if: needs.changed-files-check.outputs.any_changed == 'true'
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:18
|
||||
env:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
ports:
|
||||
- 5432:5432
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
redis:
|
||||
image: redis
|
||||
ports:
|
||||
- 6379:6379
|
||||
env:
|
||||
TWENTY_API_URL: http://localhost:3000
|
||||
TWENTY_API_KEY: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ1c2VySWQiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ3b3Jrc3BhY2VJZCI6IjIwMjAyMDIwLTFjMjUtNGQwMi1iZjI1LTZhZWNjZjdlYTQxOSIsIndvcmtzcGFjZU1lbWJlcklkIjoiMjAyMDIwMjAtNDYzZi00MzViLTgyOGMtMTA3ZTAwN2EyNzExIiwidXNlcldvcmtzcGFjZUlkIjoiMjAyMDIwMjAtMWU3Yy00M2Q5LWE1ZGItNjg1YjUwNjlkODE2IiwidHlwZSI6IkFDQ0VTUyIsImF1dGhQcm92aWRlciI6InBhc3N3b3JkIiwiaWF0IjoxNzUxMjgxNzA0LCJleHAiOjIwNjY4NTc3MDR9.HMGqCsVlOAPVUBhKSGlD1X86VoHKt4LIUtET3CGIdik
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies
|
||||
uses: ./.github/actions/yarn-install
|
||||
|
||||
- name: Build SDK packages
|
||||
run: npx nx build twenty-sdk
|
||||
|
||||
- name: Create test database
|
||||
run: PGPASSWORD=postgres psql -h localhost -p 5432 -U postgres -d postgres -c 'CREATE DATABASE "test";'
|
||||
|
||||
- name: Setup database and start server
|
||||
run: npx nx run twenty-server:database:reset && nohup npx nx start:ci twenty-server &
|
||||
|
||||
- name: Wait for server to be ready
|
||||
run: npx wait-on http://localhost:3000/healthz --timeout 120000 --interval 1000
|
||||
|
||||
- name: Run integration tests
|
||||
working-directory: packages/twenty-apps/examples/hello-world
|
||||
run: npx vitest run
|
||||
|
||||
ci-example-app-hello-world-status-check:
|
||||
if: always() && !cancelled()
|
||||
timeout-minutes: 5
|
||||
runs-on: ubuntu-latest
|
||||
needs: [changed-files-check, example-app-hello-world]
|
||||
steps:
|
||||
- name: Fail job if any needs failed
|
||||
if: contains(needs.*.result, 'failure')
|
||||
run: exit 1
|
||||
@@ -0,0 +1,86 @@
|
||||
name: CI Example App Postcard
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
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-apps/examples/postcard/**
|
||||
packages/twenty-sdk/**
|
||||
packages/twenty-client-sdk/**
|
||||
packages/twenty-shared/**
|
||||
!packages/twenty-sdk/package.json
|
||||
!packages/twenty-client-sdk/package.json
|
||||
!packages/twenty-shared/package.json
|
||||
|
||||
example-app-postcard:
|
||||
needs: changed-files-check
|
||||
if: needs.changed-files-check.outputs.any_changed == 'true'
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:18
|
||||
env:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
ports:
|
||||
- 5432:5432
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
redis:
|
||||
image: redis
|
||||
ports:
|
||||
- 6379:6379
|
||||
env:
|
||||
TWENTY_API_URL: http://localhost:3000
|
||||
TWENTY_API_KEY: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ1c2VySWQiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ3b3Jrc3BhY2VJZCI6IjIwMjAyMDIwLTFjMjUtNGQwMi1iZjI1LTZhZWNjZjdlYTQxOSIsIndvcmtzcGFjZU1lbWJlcklkIjoiMjAyMDIwMjAtNDYzZi00MzViLTgyOGMtMTA3ZTAwN2EyNzExIiwidXNlcldvcmtzcGFjZUlkIjoiMjAyMDIwMjAtMWU3Yy00M2Q5LWE1ZGItNjg1YjUwNjlkODE2IiwidHlwZSI6IkFDQ0VTUyIsImF1dGhQcm92aWRlciI6InBhc3N3b3JkIiwiaWF0IjoxNzUxMjgxNzA0LCJleHAiOjIwNjY4NTc3MDR9.HMGqCsVlOAPVUBhKSGlD1X86VoHKt4LIUtET3CGIdik
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies
|
||||
uses: ./.github/actions/yarn-install
|
||||
|
||||
- name: Build SDK packages
|
||||
run: npx nx build twenty-sdk
|
||||
|
||||
- name: Create test database
|
||||
run: PGPASSWORD=postgres psql -h localhost -p 5432 -U postgres -d postgres -c 'CREATE DATABASE "test";'
|
||||
|
||||
- name: Setup database and start server
|
||||
run: npx nx run twenty-server:database:reset && nohup npx nx start:ci twenty-server &
|
||||
|
||||
- name: Wait for server to be ready
|
||||
run: npx wait-on http://localhost:3000/healthz --timeout 120000 --interval 1000
|
||||
|
||||
- name: Run integration tests
|
||||
working-directory: packages/twenty-apps/examples/postcard
|
||||
run: npx vitest run
|
||||
|
||||
ci-example-app-postcard-status-check:
|
||||
if: always() && !cancelled()
|
||||
timeout-minutes: 5
|
||||
runs-on: ubuntu-latest
|
||||
needs: [changed-files-check, example-app-postcard]
|
||||
steps:
|
||||
- name: Fail job if any needs failed
|
||||
if: contains(needs.*.result, 'failure')
|
||||
run: exit 1
|
||||
@@ -158,7 +158,7 @@ jobs:
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
NODE_OPTIONS: '--max-old-space-size=4096'
|
||||
NODE_OPTIONS: '--max-old-space-size=6144'
|
||||
TASK_CACHE_KEY: front-task-${{ matrix.task }}
|
||||
strategy:
|
||||
matrix:
|
||||
|
||||
@@ -70,6 +70,8 @@ jobs:
|
||||
- 6379:6379
|
||||
env:
|
||||
NODE_ENV: test
|
||||
TWENTY_API_URL: http://localhost:3000
|
||||
TWENTY_API_KEY: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ1c2VySWQiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ3b3Jrc3BhY2VJZCI6IjIwMjAyMDIwLTFjMjUtNGQwMi1iZjI1LTZhZWNjZjdlYTQxOSIsIndvcmtzcGFjZU1lbWJlcklkIjoiMjAyMDIwMjAtNDYzZi00MzViLTgyOGMtMTA3ZTAwN2EyNzExIiwidXNlcldvcmtzcGFjZUlkIjoiMjAyMDIwMjAtMWU3Yy00M2Q5LWE1ZGItNjg1YjUwNjlkODE2IiwidHlwZSI6IkFDQ0VTUyIsImF1dGhQcm92aWRlciI6InBhc3N3b3JkIiwiaWF0IjoxNzUxMjgxNzA0LCJleHAiOjIwNjY4NTc3MDR9.HMGqCsVlOAPVUBhKSGlD1X86VoHKt4LIUtET3CGIdik
|
||||
steps:
|
||||
- name: Fetch custom Github Actions and base branch history
|
||||
uses: actions/checkout@v4
|
||||
|
||||
@@ -75,9 +75,6 @@ npx nx run twenty-server:database:migrate:prod # Run migrations
|
||||
|
||||
# Generate migration (replace [name] with kebab-case descriptive name)
|
||||
npx nx run twenty-server:typeorm migration:generate src/database/typeorm/core/migrations/common/[name] -d src/database/typeorm/core/core.datasource.ts
|
||||
|
||||
# Sync metadata
|
||||
npx nx run twenty-server:command workspace:sync-metadata
|
||||
```
|
||||
|
||||
### Database Inspection (Postgres MCP)
|
||||
@@ -87,7 +84,7 @@ A read-only Postgres MCP server is configured in `.mcp.json`. Use it to:
|
||||
- Verify migration results (columns, types, constraints) after running migrations
|
||||
- Explore the multi-tenant schema structure (core, metadata, workspace-specific schemas)
|
||||
- Debug issues by querying raw data to confirm whether a bug is frontend, backend, or data-level
|
||||
- Inspect metadata tables to debug GraphQL schema generation or `workspace:sync-metadata` issues
|
||||
- Inspect metadata tables to debug GraphQL schema generation issues
|
||||
|
||||
This server is read-only — for write operations (reset, migrations, sync), use the CLI commands above.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "create-twenty-app",
|
||||
"version": "0.8.0",
|
||||
"version": "0.9.0-canary.0",
|
||||
"description": "Command-line interface to create Twenty application",
|
||||
"main": "dist/cli.cjs",
|
||||
"bin": "dist/cli.cjs",
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
name: CD
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
types: [labeled]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
TWENTY_DEPLOY_URL: http://localhost:3000
|
||||
|
||||
concurrency:
|
||||
group: cd-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
deploy-and-install:
|
||||
if: >-
|
||||
github.event_name == 'push' ||
|
||||
(github.event_name == 'pull_request' && github.event.label.name == 'deploy')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
- name: Deploy
|
||||
uses: twentyhq/twenty/.github/actions/deploy-twenty-app@main
|
||||
with:
|
||||
api-url: ${{ env.TWENTY_DEPLOY_URL }}
|
||||
api-key: ${{ secrets.TWENTY_DEPLOY_API_KEY }}
|
||||
|
||||
- name: Install
|
||||
uses: twentyhq/twenty/.github/actions/install-twenty-app@main
|
||||
with:
|
||||
api-url: ${{ env.TWENTY_DEPLOY_URL }}
|
||||
api-key: ${{ secrets.TWENTY_DEPLOY_API_KEY }}
|
||||
+11
-5
@@ -6,9 +6,16 @@ on:
|
||||
- main
|
||||
pull_request: {}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
TWENTY_VERSION: latest
|
||||
|
||||
concurrency:
|
||||
group: ci-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -16,12 +23,11 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Spawn Twenty instance
|
||||
- name: Spawn Twenty test instance
|
||||
id: twenty
|
||||
uses: twentyhq/twenty/.github/actions/spawn-twenty-docker-image@main
|
||||
uses: twentyhq/twenty/.github/actions/spawn-twenty-app-dev-test@main
|
||||
with:
|
||||
twenty-version: ${{ env.TWENTY_VERSION }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Enable Corepack
|
||||
run: corepack enable
|
||||
@@ -30,7 +36,7 @@ jobs:
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'yarn'
|
||||
cache: yarn
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn install --immutable
|
||||
@@ -39,4 +45,4 @@ jobs:
|
||||
run: yarn test
|
||||
env:
|
||||
TWENTY_API_URL: ${{ steps.twenty.outputs.server-url }}
|
||||
TWENTY_API_KEY: ${{ steps.twenty.outputs.access-token }}
|
||||
TWENTY_API_KEY: ${{ steps.twenty.outputs.api-key }}
|
||||
@@ -3,43 +3,51 @@ import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import { beforeAll } from 'vitest';
|
||||
|
||||
const TWENTY_API_URL = process.env.TWENTY_API_URL ?? 'http://localhost:2020';
|
||||
const TEST_CONFIG_DIR = path.join(os.tmpdir(), '.twenty-sdk-test');
|
||||
const CONFIG_DIR = path.join(os.homedir(), '.twenty');
|
||||
const CONFIG_PATH = path.join(CONFIG_DIR, 'config.test.json');
|
||||
|
||||
beforeAll(async () => {
|
||||
const apiUrl = process.env.TWENTY_API_URL!;
|
||||
const token = process.env.TWENTY_API_KEY!;
|
||||
|
||||
if (!apiUrl || !token) {
|
||||
throw new Error(
|
||||
'TWENTY_API_URL and TWENTY_API_KEY must be set.\n' +
|
||||
'Start a local server: yarn twenty server start\n' +
|
||||
'Or set them in vitest env config.',
|
||||
);
|
||||
}
|
||||
|
||||
const assertServerIsReachable = async () => {
|
||||
let response: Response;
|
||||
|
||||
try {
|
||||
response = await fetch(`${TWENTY_API_URL}/healthz`);
|
||||
response = await fetch(`${apiUrl}/healthz`);
|
||||
} catch {
|
||||
throw new Error(
|
||||
`Twenty server is not reachable at ${TWENTY_API_URL}. ` +
|
||||
`Twenty server is not reachable at ${apiUrl}. ` +
|
||||
'Make sure the server is running before executing integration tests.',
|
||||
);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Server at ${TWENTY_API_URL} returned ${response.status}`);
|
||||
throw new Error(`Server at ${apiUrl} returned ${response.status}`);
|
||||
}
|
||||
};
|
||||
|
||||
beforeAll(async () => {
|
||||
await assertServerIsReachable();
|
||||
|
||||
fs.mkdirSync(TEST_CONFIG_DIR, { recursive: true });
|
||||
|
||||
const configFile = {
|
||||
remotes: {
|
||||
local: {
|
||||
apiUrl: process.env.TWENTY_API_URL,
|
||||
apiKey: process.env.TWENTY_API_KEY,
|
||||
},
|
||||
},
|
||||
defaultRemote: 'local',
|
||||
};
|
||||
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(TEST_CONFIG_DIR, 'config.json'),
|
||||
JSON.stringify(configFile, null, 2),
|
||||
CONFIG_PATH,
|
||||
JSON.stringify(
|
||||
{
|
||||
remotes: {
|
||||
local: { apiUrl, apiKey: token },
|
||||
},
|
||||
defaultRemote: 'local',
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
);
|
||||
|
||||
process.env.TWENTY_APP_ACCESS_TOKEN ??= token;
|
||||
});
|
||||
|
||||
@@ -14,8 +14,11 @@ export default defineConfig({
|
||||
include: ['src/**/*.integration-test.ts'],
|
||||
setupFiles: ['src/__tests__/setup-test.ts'],
|
||||
env: {
|
||||
TWENTY_API_URL: process.env.TWENTY_API_URL ?? 'http://localhost:2020',
|
||||
TWENTY_API_KEY:
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ1c2VySWQiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ3b3Jrc3BhY2VJZCI6IjIwMjAyMDIwLTFjMjUtNGQwMi1iZjI1LTZhZWNjZjdlYTQxOSIsIndvcmtzcGFjZU1lbWJlcklkIjoiMjAyMDIwMjAtNDYzZi00MzViLTgyOGMtMTA3ZTAwN2EyNzExIiwidXNlcldvcmtzcGFjZUlkIjoiMjAyMDIwMjAtMWU3Yy00M2Q5LWE1ZGItNjg1YjUwNjlkODE2IiwidHlwZSI6IkFDQ0VTUyIsImF1dGhQcm92aWRlciI6InBhc3N3b3JkIiwiaWF0IjoxNzUxMjgxNzA0LCJleHAiOjIwNjY4NTc3MDR9.HMGqCsVlOAPVUBhKSGlD1X86VoHKt4LIUtET3CGIdik',
|
||||
process.env.TWENTY_API_KEY ??
|
||||
// Tim Apple (admin) access token for twenty-app-dev
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyMDIwMjAyMC05ZTNiLTQ2ZDQtYTU1Ni04OGI5ZGRjMmIwMzQiLCJ1c2VySWQiOiIyMDIwMjAyMC05ZTNiLTQ2ZDQtYTU1Ni04OGI5ZGRjMmIwMzQiLCJ3b3Jrc3BhY2VJZCI6IjIwMjAyMDIwLTFjMjUtNGQwMi1iZjI1LTZhZWNjZjdlYTQxOSIsIndvcmtzcGFjZU1lbWJlcklkIjoiMjAyMDIwMjAtMDY4Ny00YzQxLWI3MDctZWQxYmZjYTk3MmE3IiwidXNlcldvcmtzcGFjZUlkIjoiMjAyMDIwMjAtOWUzYi00NmQ0LWE1NTYtODhiOWRkYzJiMDM1IiwidHlwZSI6IkFDQ0VTUyIsImF1dGhQcm92aWRlciI6InBhc3N3b3JkIiwiaWF0IjoxNzUxMjgxNzA0LCJleHAiOjQ5MDQ4ODE3MDR9.9S4wc0MOr5iczsomlFxZdOHD1IRDS4dnRSwNVNpctF4',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -21,7 +21,7 @@ export const copyBaseApplicationProject = async ({
|
||||
console.log(chalk.gray('Generating application project...'));
|
||||
await fs.copy(join(__dirname, './constants/template'), appDirectory);
|
||||
|
||||
await renameGitignore({ appDirectory });
|
||||
await renameDotfiles({ appDirectory });
|
||||
|
||||
await generateUniversalIdentifiers({
|
||||
appDisplayName,
|
||||
@@ -32,11 +32,20 @@ export const copyBaseApplicationProject = async ({
|
||||
await updatePackageJson({ appName, appDirectory });
|
||||
};
|
||||
|
||||
const renameGitignore = async ({ appDirectory }: { appDirectory: string }) => {
|
||||
const gitignorePath = join(appDirectory, 'gitignore');
|
||||
// npm strips dotfiles/dotdirs (.gitignore, .github/) from published packages,
|
||||
// so we store them without the leading dot and rename after copying.
|
||||
const renameDotfiles = async ({ appDirectory }: { appDirectory: string }) => {
|
||||
const renames = [
|
||||
{ from: 'gitignore', to: '.gitignore' },
|
||||
{ from: 'github', to: '.github' },
|
||||
];
|
||||
|
||||
if (await fs.pathExists(gitignorePath)) {
|
||||
await fs.rename(gitignorePath, join(appDirectory, '.gitignore'));
|
||||
for (const { from, to } of renames) {
|
||||
const sourcePath = join(appDirectory, from);
|
||||
|
||||
if (await fs.pathExists(sourcePath)) {
|
||||
await fs.rename(sourcePath, join(appDirectory, to));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
name: CD
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
types: [labeled]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
TWENTY_DEPLOY_URL: http://localhost:3000
|
||||
|
||||
concurrency:
|
||||
group: cd-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
deploy-and-install:
|
||||
if: >-
|
||||
github.event_name == 'push' ||
|
||||
(github.event_name == 'pull_request' && github.event.label.name == 'deploy')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
- name: Deploy
|
||||
uses: twentyhq/twenty/.github/actions/deploy-twenty-app@main
|
||||
with:
|
||||
api-url: ${{ env.TWENTY_DEPLOY_URL }}
|
||||
api-key: ${{ secrets.TWENTY_DEPLOY_API_KEY }}
|
||||
|
||||
- name: Install
|
||||
uses: twentyhq/twenty/.github/actions/install-twenty-app@main
|
||||
with:
|
||||
api-url: ${{ env.TWENTY_DEPLOY_URL }}
|
||||
api-key: ${{ secrets.TWENTY_DEPLOY_API_KEY }}
|
||||
@@ -6,9 +6,16 @@ on:
|
||||
- main
|
||||
pull_request: {}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
TWENTY_VERSION: latest
|
||||
|
||||
concurrency:
|
||||
group: ci-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -16,12 +23,11 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Spawn Twenty instance
|
||||
- name: Spawn Twenty test instance
|
||||
id: twenty
|
||||
uses: twentyhq/twenty/.github/actions/spawn-twenty-docker-image@main
|
||||
uses: twentyhq/twenty/.github/actions/spawn-twenty-app-dev-test@main
|
||||
with:
|
||||
twenty-version: ${{ env.TWENTY_VERSION }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Enable Corepack
|
||||
run: corepack enable
|
||||
@@ -30,7 +36,7 @@ jobs:
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'yarn'
|
||||
cache: yarn
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn install --immutable
|
||||
@@ -39,4 +45,4 @@ jobs:
|
||||
run: yarn test
|
||||
env:
|
||||
TWENTY_API_URL: ${{ steps.twenty.outputs.server-url }}
|
||||
TWENTY_API_KEY: ${{ steps.twenty.outputs.access-token }}
|
||||
TWENTY_API_KEY: ${{ steps.twenty.outputs.api-key }}
|
||||
|
||||
@@ -3,43 +3,51 @@ import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import { beforeAll } from 'vitest';
|
||||
|
||||
const TWENTY_API_URL = process.env.TWENTY_API_URL ?? 'http://localhost:3000';
|
||||
const TEST_CONFIG_DIR = path.join(os.tmpdir(), '.twenty-sdk-test');
|
||||
const CONFIG_DIR = path.join(os.homedir(), '.twenty');
|
||||
const CONFIG_PATH = path.join(CONFIG_DIR, 'config.test.json');
|
||||
|
||||
beforeAll(async () => {
|
||||
const apiUrl = process.env.TWENTY_API_URL!;
|
||||
const token = process.env.TWENTY_API_KEY!;
|
||||
|
||||
if (!apiUrl || !token) {
|
||||
throw new Error(
|
||||
'TWENTY_API_URL and TWENTY_API_KEY must be set.\n' +
|
||||
'Start a local server: yarn twenty server start\n' +
|
||||
'Or set them in vitest env config.',
|
||||
);
|
||||
}
|
||||
|
||||
const assertServerIsReachable = async () => {
|
||||
let response: Response;
|
||||
|
||||
try {
|
||||
response = await fetch(`${TWENTY_API_URL}/healthz`);
|
||||
response = await fetch(`${apiUrl}/healthz`);
|
||||
} catch {
|
||||
throw new Error(
|
||||
`Twenty server is not reachable at ${TWENTY_API_URL}. ` +
|
||||
`Twenty server is not reachable at ${apiUrl}. ` +
|
||||
'Make sure the server is running before executing integration tests.',
|
||||
);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Server at ${TWENTY_API_URL} returned ${response.status}`);
|
||||
throw new Error(`Server at ${apiUrl} returned ${response.status}`);
|
||||
}
|
||||
};
|
||||
|
||||
beforeAll(async () => {
|
||||
await assertServerIsReachable();
|
||||
|
||||
fs.mkdirSync(TEST_CONFIG_DIR, { recursive: true });
|
||||
|
||||
const configFile = {
|
||||
remotes: {
|
||||
local: {
|
||||
apiUrl: process.env.TWENTY_API_URL,
|
||||
apiKey: process.env.TWENTY_API_KEY,
|
||||
},
|
||||
},
|
||||
defaultRemote: 'local',
|
||||
};
|
||||
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(TEST_CONFIG_DIR, 'config.json'),
|
||||
JSON.stringify(configFile, null, 2),
|
||||
CONFIG_PATH,
|
||||
JSON.stringify(
|
||||
{
|
||||
remotes: {
|
||||
local: { apiUrl, apiKey: token },
|
||||
},
|
||||
defaultRemote: 'local',
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
);
|
||||
|
||||
process.env.TWENTY_APP_ACCESS_TOKEN ??= token;
|
||||
});
|
||||
|
||||
@@ -14,9 +14,11 @@ export default defineConfig({
|
||||
include: ['src/**/*.integration-test.ts'],
|
||||
setupFiles: ['src/__tests__/setup-test.ts'],
|
||||
env: {
|
||||
TWENTY_API_URL: 'http://localhost:3000',
|
||||
TWENTY_API_URL: process.env.TWENTY_API_URL ?? 'http://localhost:2020',
|
||||
TWENTY_API_KEY:
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ1c2VySWQiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ3b3Jrc3BhY2VJZCI6IjIwMjAyMDIwLTFjMjUtNGQwMi1iZjI1LTZhZWNjZjdlYTQxOSIsIndvcmtzcGFjZU1lbWJlcklkIjoiMjAyMDIwMjAtNDYzZi00MzViLTgyOGMtMTA3ZTAwN2EyNzExIiwidXNlcldvcmtzcGFjZUlkIjoiMjAyMDIwMjAtMWU3Yy00M2Q5LWE1ZGItNjg1YjUwNjlkODE2IiwidHlwZSI6IkFDQ0VTUyIsImF1dGhQcm92aWRlciI6InBhc3N3b3JkIiwiaWF0IjoxNzUxMjgxNzA0LCJleHAiOjIwNjY4NTc3MDR9.HMGqCsVlOAPVUBhKSGlD1X86VoHKt4LIUtET3CGIdik',
|
||||
process.env.TWENTY_API_KEY ??
|
||||
// Tim Apple (admin) access token for twenty-app-dev
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyMDIwMjAyMC05ZTNiLTQ2ZDQtYTU1Ni04OGI5ZGRjMmIwMzQiLCJ1c2VySWQiOiIyMDIwMjAyMC05ZTNiLTQ2ZDQtYTU1Ni04OGI5ZGRjMmIwMzQiLCJ3b3Jrc3BhY2VJZCI6IjIwMjAyMDIwLTFjMjUtNGQwMi1iZjI1LTZhZWNjZjdlYTQxOSIsIndvcmtzcGFjZU1lbWJlcklkIjoiMjAyMDIwMjAtMDY4Ny00YzQxLWI3MDctZWQxYmZjYTk3MmE3IiwidXNlcldvcmtzcGFjZUlkIjoiMjAyMDIwMjAtOWUzYi00NmQ0LWE1NTYtODhiOWRkYzJiMDM1IiwidHlwZSI6IkFDQ0VTUyIsImF1dGhQcm92aWRlciI6InBhc3N3b3JkIiwiaWF0IjoxNzUxMjgxNzA0LCJleHAiOjQ5MDQ4ODE3MDR9.9S4wc0MOr5iczsomlFxZdOHD1IRDS4dnRSwNVNpctF4',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
name: CD
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
types: [labeled]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
TWENTY_DEPLOY_URL: http://localhost:3000
|
||||
|
||||
concurrency:
|
||||
group: cd-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
deploy-and-install:
|
||||
if: >-
|
||||
github.event_name == 'push' ||
|
||||
(github.event_name == 'pull_request' && github.event.label.name == 'deploy')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
- name: Deploy
|
||||
uses: twentyhq/twenty/.github/actions/deploy-twenty-app@main
|
||||
with:
|
||||
api-url: ${{ env.TWENTY_DEPLOY_URL }}
|
||||
api-key: ${{ secrets.TWENTY_DEPLOY_API_KEY }}
|
||||
|
||||
- name: Install
|
||||
uses: twentyhq/twenty/.github/actions/install-twenty-app@main
|
||||
with:
|
||||
api-url: ${{ env.TWENTY_DEPLOY_URL }}
|
||||
api-key: ${{ secrets.TWENTY_DEPLOY_API_KEY }}
|
||||
@@ -6,9 +6,16 @@ on:
|
||||
- main
|
||||
pull_request: {}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
TWENTY_VERSION: latest
|
||||
|
||||
concurrency:
|
||||
group: ci-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -16,12 +23,11 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Spawn Twenty instance
|
||||
- name: Spawn Twenty test instance
|
||||
id: twenty
|
||||
uses: twentyhq/twenty/.github/actions/spawn-twenty-docker-image@main
|
||||
uses: twentyhq/twenty/.github/actions/spawn-twenty-app-dev-test@main
|
||||
with:
|
||||
twenty-version: ${{ env.TWENTY_VERSION }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Enable Corepack
|
||||
run: corepack enable
|
||||
@@ -30,7 +36,7 @@ jobs:
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'yarn'
|
||||
cache: yarn
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn install --immutable
|
||||
@@ -39,4 +45,4 @@ jobs:
|
||||
run: yarn test
|
||||
env:
|
||||
TWENTY_API_URL: ${{ steps.twenty.outputs.server-url }}
|
||||
TWENTY_API_KEY: ${{ steps.twenty.outputs.access-token }}
|
||||
TWENTY_API_KEY: ${{ steps.twenty.outputs.api-key }}
|
||||
|
||||
@@ -3,43 +3,51 @@ import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import { beforeAll } from 'vitest';
|
||||
|
||||
const TWENTY_API_URL = process.env.TWENTY_API_URL ?? 'http://localhost:2020';
|
||||
const TEST_CONFIG_DIR = path.join(os.tmpdir(), '.twenty-sdk-test');
|
||||
const CONFIG_DIR = path.join(os.homedir(), '.twenty');
|
||||
const CONFIG_PATH = path.join(CONFIG_DIR, 'config.test.json');
|
||||
|
||||
beforeAll(async () => {
|
||||
const apiUrl = process.env.TWENTY_API_URL!;
|
||||
const token = process.env.TWENTY_API_KEY!;
|
||||
|
||||
if (!apiUrl || !token) {
|
||||
throw new Error(
|
||||
'TWENTY_API_URL and TWENTY_API_KEY must be set.\n' +
|
||||
'Start a local server: yarn twenty server start\n' +
|
||||
'Or set them in vitest env config.',
|
||||
);
|
||||
}
|
||||
|
||||
const assertServerIsReachable = async () => {
|
||||
let response: Response;
|
||||
|
||||
try {
|
||||
response = await fetch(`${TWENTY_API_URL}/healthz`);
|
||||
response = await fetch(`${apiUrl}/healthz`);
|
||||
} catch {
|
||||
throw new Error(
|
||||
`Twenty server is not reachable at ${TWENTY_API_URL}. ` +
|
||||
`Twenty server is not reachable at ${apiUrl}. ` +
|
||||
'Make sure the server is running before executing integration tests.',
|
||||
);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Server at ${TWENTY_API_URL} returned ${response.status}`);
|
||||
throw new Error(`Server at ${apiUrl} returned ${response.status}`);
|
||||
}
|
||||
};
|
||||
|
||||
beforeAll(async () => {
|
||||
await assertServerIsReachable();
|
||||
|
||||
fs.mkdirSync(TEST_CONFIG_DIR, { recursive: true });
|
||||
|
||||
const configFile = {
|
||||
remotes: {
|
||||
local: {
|
||||
apiUrl: process.env.TWENTY_API_URL,
|
||||
apiKey: process.env.TWENTY_API_KEY,
|
||||
},
|
||||
},
|
||||
defaultRemote: 'local',
|
||||
};
|
||||
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(TEST_CONFIG_DIR, 'config.json'),
|
||||
JSON.stringify(configFile, null, 2),
|
||||
CONFIG_PATH,
|
||||
JSON.stringify(
|
||||
{
|
||||
remotes: {
|
||||
local: { apiUrl, apiKey: token },
|
||||
},
|
||||
defaultRemote: 'local',
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
);
|
||||
|
||||
process.env.TWENTY_APP_ACCESS_TOKEN ??= token;
|
||||
});
|
||||
|
||||
@@ -51,28 +51,28 @@ export default defineObject({
|
||||
defaultValue: `'${PostCardStatus.DRAFT}'`,
|
||||
options: [
|
||||
{
|
||||
id: 'a1b2c3d4-0001-4000-8000-000000000001',
|
||||
id: '8ab3abad-02e7-4670-9283-983d7fac7fe4',
|
||||
value: PostCardStatus.DRAFT,
|
||||
label: 'Draft',
|
||||
position: 0,
|
||||
color: 'gray',
|
||||
},
|
||||
{
|
||||
id: 'a1b2c3d4-0002-4000-8000-000000000002',
|
||||
id: '2bcdd195-6c99-4d69-84b2-e2838ee54467',
|
||||
value: PostCardStatus.SENT,
|
||||
label: 'Sent',
|
||||
position: 1,
|
||||
color: 'orange',
|
||||
},
|
||||
{
|
||||
id: 'a1b2c3d4-0003-4000-8000-000000000003',
|
||||
id: '918ff60c-c26e-4fae-8eba-3fbce04dc48b',
|
||||
value: PostCardStatus.DELIVERED,
|
||||
label: 'Delivered',
|
||||
position: 2,
|
||||
color: 'green',
|
||||
},
|
||||
{
|
||||
id: 'a1b2c3d4-0004-4000-8000-000000000004',
|
||||
id: '3c91a653-5d31-4023-be6c-a69c68d21233',
|
||||
value: PostCardStatus.RETURNED,
|
||||
label: 'Returned',
|
||||
position: 3,
|
||||
|
||||
@@ -14,8 +14,11 @@ export default defineConfig({
|
||||
include: ['src/**/*.integration-test.ts'],
|
||||
setupFiles: ['src/__tests__/setup-test.ts'],
|
||||
env: {
|
||||
TWENTY_API_URL: process.env.TWENTY_API_URL ?? 'http://localhost:2020',
|
||||
TWENTY_API_KEY:
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ1c2VySWQiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ3b3Jrc3BhY2VJZCI6IjIwMjAyMDIwLTFjMjUtNGQwMi1iZjI1LTZhZWNjZjdlYTQxOSIsIndvcmtzcGFjZU1lbWJlcklkIjoiMjAyMDIwMjAtNDYzZi00MzViLTgyOGMtMTA3ZTAwN2EyNzExIiwidXNlcldvcmtzcGFjZUlkIjoiMjAyMDIwMjAtMWU3Yy00M2Q5LWE1ZGItNjg1YjUwNjlkODE2IiwidHlwZSI6IkFDQ0VTUyIsImF1dGhQcm92aWRlciI6InBhc3N3b3JkIiwiaWF0IjoxNzUxMjgxNzA0LCJleHAiOjIwNjY4NTc3MDR9.HMGqCsVlOAPVUBhKSGlD1X86VoHKt4LIUtET3CGIdik',
|
||||
process.env.TWENTY_API_KEY ??
|
||||
// Tim Apple (admin) access token for twenty-app-dev
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyMDIwMjAyMC05ZTNiLTQ2ZDQtYTU1Ni04OGI5ZGRjMmIwMzQiLCJ1c2VySWQiOiIyMDIwMjAyMC05ZTNiLTQ2ZDQtYTU1Ni04OGI5ZGRjMmIwMzQiLCJ3b3Jrc3BhY2VJZCI6IjIwMjAyMDIwLTFjMjUtNGQwMi1iZjI1LTZhZWNjZjdlYTQxOSIsIndvcmtzcGFjZU1lbWJlcklkIjoiMjAyMDIwMjAtMDY4Ny00YzQxLWI3MDctZWQxYmZjYTk3MmE3IiwidXNlcldvcmtzcGFjZUlkIjoiMjAyMDIwMjAtOWUzYi00NmQ0LWE1NTYtODhiOWRkYzJiMDM1IiwidHlwZSI6IkFDQ0VTUyIsImF1dGhQcm92aWRlciI6InBhc3N3b3JkIiwiaWF0IjoxNzUxMjgxNzA0LCJleHAiOjQ5MDQ4ODE3MDR9.9S4wc0MOr5iczsomlFxZdOHD1IRDS4dnRSwNVNpctF4',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -10,25 +10,31 @@ export default defineField({
|
||||
description: 'Post card category',
|
||||
options: [
|
||||
{
|
||||
id: 'c1d2e3f4-0001-4000-8000-000000000001',
|
||||
id: 'cd751c81-787d-4581-bc51-efe43f0050a7',
|
||||
value: 'PERSONAL',
|
||||
label: 'Personal',
|
||||
color: 'blue',
|
||||
position: 0,
|
||||
},
|
||||
{
|
||||
id: 'c1d2e3f4-0002-4000-8000-000000000002',
|
||||
id: 'eec437ca-5beb-41a9-a826-c9a5eca2eef4',
|
||||
value: 'BUSINESS',
|
||||
label: 'Business',
|
||||
color: 'green',
|
||||
position: 1,
|
||||
},
|
||||
{
|
||||
id: 'c1d2e3f4-0003-4000-8000-000000000003',
|
||||
id: 'a5baa37d-1047-4972-b6b8-7faae0e3eac1',
|
||||
value: 'PROMOTIONAL',
|
||||
label: 'Promotional',
|
||||
color: 'orange',
|
||||
position: 2,
|
||||
},
|
||||
{
|
||||
value: 'OTHER',
|
||||
label: 'Other',
|
||||
color: 'gray',
|
||||
position: 3,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
@@ -5,6 +5,7 @@ enum PostCardStatus {
|
||||
SENT = 'SENT',
|
||||
DELIVERED = 'DELIVERED',
|
||||
RETURNED = 'RETURNED',
|
||||
LOST = 'LOST',
|
||||
}
|
||||
|
||||
export const POST_CARD_UNIVERSAL_IDENTIFIER =
|
||||
@@ -53,33 +54,40 @@ export default defineObject({
|
||||
defaultValue: `'${PostCardStatus.DRAFT}'`,
|
||||
options: [
|
||||
{
|
||||
id: 'a1b2c3d4-0001-4000-8000-000000000001',
|
||||
id: '1b008e19-1e59-4a07-b187-65a20e547c4e',
|
||||
value: PostCardStatus.DRAFT,
|
||||
label: 'Draft',
|
||||
position: 0,
|
||||
color: 'gray',
|
||||
},
|
||||
{
|
||||
id: 'a1b2c3d4-0002-4000-8000-000000000002',
|
||||
id: '452b9d40-889c-4342-9697-98319394db04',
|
||||
value: PostCardStatus.SENT,
|
||||
label: 'Sent',
|
||||
position: 1,
|
||||
color: 'orange',
|
||||
},
|
||||
{
|
||||
id: 'a1b2c3d4-0003-4000-8000-000000000003',
|
||||
id: 'c2ed0b8c-a3ed-4383-aef9-e0441267bcfe',
|
||||
value: PostCardStatus.DELIVERED,
|
||||
label: 'Delivered',
|
||||
position: 2,
|
||||
color: 'green',
|
||||
},
|
||||
{
|
||||
id: 'a1b2c3d4-0004-4000-8000-000000000004',
|
||||
id: 'c57a5e08-7ef7-49b8-87e6-32d720d22802',
|
||||
value: PostCardStatus.RETURNED,
|
||||
label: 'Returned',
|
||||
position: 3,
|
||||
color: 'orange',
|
||||
},
|
||||
{
|
||||
// No id — exercises addMissingFieldOptionIds in the object branch
|
||||
value: PostCardStatus.LOST,
|
||||
label: 'Lost',
|
||||
position: 4,
|
||||
color: 'red',
|
||||
},
|
||||
],
|
||||
name: 'status',
|
||||
},
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request: {}
|
||||
|
||||
env:
|
||||
TWENTY_VERSION: latest
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Spawn Twenty instance
|
||||
id: twenty
|
||||
uses: twentyhq/twenty/.github/actions/spawn-twenty-docker-image@main
|
||||
with:
|
||||
twenty-version: ${{ env.TWENTY_VERSION }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Enable Corepack
|
||||
run: corepack enable
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'yarn'
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn install --immutable
|
||||
|
||||
- name: Run integration tests
|
||||
run: yarn test
|
||||
env:
|
||||
TWENTY_API_URL: ${{ steps.twenty.outputs.server-url }}
|
||||
TWENTY_API_KEY: ${{ steps.twenty.outputs.access-token }}
|
||||
@@ -1,38 +0,0 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.*
|
||||
.yarn
|
||||
|
||||
# codegen
|
||||
generated
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# dev
|
||||
/dist/
|
||||
|
||||
.twenty
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# env files (can opt-in for committing if needed)
|
||||
.env*
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
*.d.ts
|
||||
@@ -1 +0,0 @@
|
||||
24.5.0
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
||||
"plugins": ["typescript"],
|
||||
"categories": {
|
||||
"correctness": "off"
|
||||
},
|
||||
"ignorePatterns": ["node_modules", "dist"],
|
||||
"rules": {
|
||||
"no-unused-vars": "off",
|
||||
|
||||
"typescript/no-unused-vars": [
|
||||
"warn",
|
||||
{
|
||||
"argsIgnorePattern": "^_"
|
||||
}
|
||||
],
|
||||
"typescript/no-explicit-any": "off"
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
nodeLinker: node-modules
|
||||
@@ -1,14 +0,0 @@
|
||||
## Base documentation
|
||||
|
||||
- Documentation: https://docs.twenty.com/developers/extend/apps/getting-started
|
||||
- Rich app example: https://github.com/twentyhq/twenty/tree/main/packages/twenty-apps/examples/postcard
|
||||
|
||||
## UUID requirement
|
||||
|
||||
- All generated UUIDs must be valid UUID v4.
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
- Creating an object without an index view associated. Unless this is a technical object, user will need to visualize it.
|
||||
- Creating a view without a navigationMenuItem associated. This will make the view available on the left sidebar.
|
||||
- Creating a front-end component that has a scroll instead of being responsive to its fixed widget height and width, unless it is specifically meant to be used in a canvas tab.
|
||||
@@ -1,14 +0,0 @@
|
||||
## Base documentation
|
||||
|
||||
- Documentation: https://docs.twenty.com/developers/extend/apps/getting-started
|
||||
- Rich app example: https://github.com/twentyhq/twenty/tree/main/packages/twenty-apps/examples/postcard
|
||||
|
||||
## UUID requirement
|
||||
|
||||
- All generated UUIDs must be valid UUID v4.
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
- Creating an object without an index view associated. Unless this is a technical object, user will need to visualize it.
|
||||
- Creating a view without a navigationMenuItem associated. This will make the view available on the left sidebar.
|
||||
- Creating a front-end component that has a scroll instead of being responsive to its fixed widget height and width, unless it is specifically meant to be used in a canvas tab.
|
||||
@@ -1,14 +0,0 @@
|
||||
## Base documentation
|
||||
|
||||
- Documentation: https://docs.twenty.com/developers/extend/apps/getting-started
|
||||
- Rich app example: https://github.com/twentyhq/twenty/tree/main/packages/twenty-apps/examples/postcard
|
||||
|
||||
## UUID requirement
|
||||
|
||||
- All generated UUIDs must be valid UUID v4.
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
- Creating an object without an index view associated. Unless this is a technical object, user will need to visualize it.
|
||||
- Creating a view without a navigationMenuItem associated. This will make the view available on the left sidebar.
|
||||
- Creating a front-end component that has a scroll instead of being responsive to its fixed widget height and width, unless it is specifically meant to be used in a canvas tab.
|
||||
@@ -1,11 +0,0 @@
|
||||
This is a [Twenty](https://twenty.com) application bootstrapped with [`create-twenty-app`](https://www.npmjs.com/package/create-twenty-app).
|
||||
|
||||
## Getting Started
|
||||
|
||||
Run `yarn twenty help` to list all available commands.
|
||||
|
||||
## Learn More
|
||||
|
||||
- [Twenty Apps documentation](https://docs.twenty.com/developers/extend/apps/getting-started)
|
||||
- [twenty-sdk CLI reference](https://www.npmjs.com/package/twenty-sdk)
|
||||
- [Discord](https://discord.gg/cx5n4Jzs57)
|
||||
@@ -1,35 +0,0 @@
|
||||
{
|
||||
"name": "my-twenty-app",
|
||||
"version": "0.1.0",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^24.5.0",
|
||||
"npm": "please-use-yarn",
|
||||
"yarn": ">=4.0.2"
|
||||
},
|
||||
"keywords": [
|
||||
"twenty-app"
|
||||
],
|
||||
"packageManager": "yarn@4.9.2",
|
||||
"scripts": {
|
||||
"twenty": "twenty",
|
||||
"lint": "oxlint -c .oxlintrc.json .",
|
||||
"lint:fix": "oxlint --fix -c .oxlintrc.json .",
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest"
|
||||
},
|
||||
"dependencies": {
|
||||
"twenty-client-sdk": "0.8.0-canary.8",
|
||||
"twenty-sdk": "0.8.0-canary.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^24.7.2",
|
||||
"@types/react": "^19.0.0",
|
||||
"oxlint": "^0.16.0",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"typescript": "^5.9.3",
|
||||
"vite-tsconfig-paths": "^4.2.1",
|
||||
"vitest": "^3.1.1"
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
import { APPLICATION_UNIVERSAL_IDENTIFIER } from 'src/constants/universal-identifiers';
|
||||
import { appBuild, appDeploy, appInstall, appUninstall } from 'twenty-sdk/cli';
|
||||
import { MetadataApiClient } from 'twenty-client-sdk/metadata';
|
||||
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
||||
|
||||
const APP_PATH = process.cwd();
|
||||
|
||||
describe('App installation', () => {
|
||||
beforeAll(async () => {
|
||||
const buildResult = await appBuild({
|
||||
appPath: APP_PATH,
|
||||
tarball: true,
|
||||
onProgress: (message: string) => console.log(`[build] ${message}`),
|
||||
});
|
||||
|
||||
if (!buildResult.success) {
|
||||
throw new Error(
|
||||
`Build failed: ${buildResult.error?.message ?? 'Unknown error'}`,
|
||||
);
|
||||
}
|
||||
|
||||
const deployResult = await appDeploy({
|
||||
tarballPath: buildResult.data.tarballPath!,
|
||||
onProgress: (message: string) => console.log(`[deploy] ${message}`),
|
||||
});
|
||||
|
||||
if (!deployResult.success) {
|
||||
throw new Error(
|
||||
`Deploy failed: ${deployResult.error?.message ?? 'Unknown error'}`,
|
||||
);
|
||||
}
|
||||
|
||||
const installResult = await appInstall({ appPath: APP_PATH });
|
||||
|
||||
if (!installResult.success) {
|
||||
throw new Error(
|
||||
`Install failed: ${installResult.error?.message ?? 'Unknown error'}`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
const uninstallResult = await appUninstall({ appPath: APP_PATH });
|
||||
|
||||
if (!uninstallResult.success) {
|
||||
console.warn(
|
||||
`App uninstall failed: ${uninstallResult.error?.message ?? 'Unknown error'}`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should find the installed app in the applications list', async () => {
|
||||
const metadataClient = new MetadataApiClient();
|
||||
|
||||
const result = await metadataClient.query({
|
||||
findManyApplications: {
|
||||
id: true,
|
||||
name: true,
|
||||
universalIdentifier: true,
|
||||
},
|
||||
});
|
||||
|
||||
const installedApp = result.findManyApplications.find(
|
||||
(application: { universalIdentifier: string }) =>
|
||||
application.universalIdentifier === APPLICATION_UNIVERSAL_IDENTIFIER,
|
||||
);
|
||||
|
||||
expect(installedApp).toBeDefined();
|
||||
});
|
||||
});
|
||||
@@ -1,45 +0,0 @@
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import { beforeAll } from 'vitest';
|
||||
|
||||
const TWENTY_API_URL = process.env.TWENTY_API_URL ?? 'http://localhost:2020';
|
||||
const TEST_CONFIG_DIR = path.join(os.tmpdir(), '.twenty-sdk-test');
|
||||
|
||||
const assertServerIsReachable = async () => {
|
||||
let response: Response;
|
||||
|
||||
try {
|
||||
response = await fetch(`${TWENTY_API_URL}/healthz`);
|
||||
} catch {
|
||||
throw new Error(
|
||||
`Twenty server is not reachable at ${TWENTY_API_URL}. ` +
|
||||
'Make sure the server is running before executing integration tests.',
|
||||
);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Server at ${TWENTY_API_URL} returned ${response.status}`);
|
||||
}
|
||||
};
|
||||
|
||||
beforeAll(async () => {
|
||||
await assertServerIsReachable();
|
||||
|
||||
fs.mkdirSync(TEST_CONFIG_DIR, { recursive: true });
|
||||
|
||||
const configFile = {
|
||||
remotes: {
|
||||
local: {
|
||||
apiUrl: process.env.TWENTY_API_URL,
|
||||
apiKey: process.env.TWENTY_API_KEY,
|
||||
},
|
||||
},
|
||||
defaultRemote: 'local',
|
||||
};
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(TEST_CONFIG_DIR, 'config.json'),
|
||||
JSON.stringify(configFile, null, 2),
|
||||
);
|
||||
});
|
||||
@@ -1,15 +0,0 @@
|
||||
import { defineApplication } from 'twenty-sdk';
|
||||
|
||||
import {
|
||||
APP_DESCRIPTION,
|
||||
APP_DISPLAY_NAME,
|
||||
APPLICATION_UNIVERSAL_IDENTIFIER,
|
||||
DEFAULT_ROLE_UNIVERSAL_IDENTIFIER,
|
||||
} from 'src/constants/universal-identifiers';
|
||||
|
||||
export default defineApplication({
|
||||
universalIdentifier: APPLICATION_UNIVERSAL_IDENTIFIER,
|
||||
displayName: APP_DISPLAY_NAME,
|
||||
description: APP_DESCRIPTION,
|
||||
defaultRoleUniversalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER,
|
||||
});
|
||||
@@ -1,4 +0,0 @@
|
||||
export const APP_DISPLAY_NAME = 'My twenty app';
|
||||
export const APP_DESCRIPTION = '';
|
||||
export const APPLICATION_UNIVERSAL_IDENTIFIER = '83a4b244-c80d-4923-b0d5-ae2406e83072';
|
||||
export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER = 'a1a28134-04d1-43ac-b8cc-b547e8cf97ba';
|
||||
@@ -1,16 +0,0 @@
|
||||
import { defineRole } from 'twenty-sdk';
|
||||
|
||||
import {
|
||||
APP_DISPLAY_NAME,
|
||||
DEFAULT_ROLE_UNIVERSAL_IDENTIFIER,
|
||||
} from 'src/constants/universal-identifiers';
|
||||
|
||||
export default defineRole({
|
||||
universalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER,
|
||||
label: `${APP_DISPLAY_NAME} default function role`,
|
||||
description: `${APP_DISPLAY_NAME} default function role`,
|
||||
canReadAllObjectRecords: true,
|
||||
canUpdateAllObjectRecords: true,
|
||||
canSoftDeleteAllObjectRecords: true,
|
||||
canDestroyAllObjectRecords: false,
|
||||
});
|
||||
@@ -1,42 +0,0 @@
|
||||
{
|
||||
"compileOnSave": false,
|
||||
"compilerOptions": {
|
||||
"sourceMap": true,
|
||||
"declaration": true,
|
||||
"outDir": "./dist",
|
||||
"rootDir": ".",
|
||||
"jsx": "react-jsx",
|
||||
"moduleResolution": "node",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"importHelpers": true,
|
||||
"allowUnreachableCode": false,
|
||||
"strict": true,
|
||||
"alwaysStrict": true,
|
||||
"noImplicitAny": true,
|
||||
"strictBindCallApply": false,
|
||||
"target": "es2018",
|
||||
"module": "esnext",
|
||||
"lib": ["es2020", "dom"],
|
||||
"skipLibCheck": true,
|
||||
"skipDefaultLibCheck": true,
|
||||
"resolveJsonModule": true,
|
||||
"paths": {
|
||||
"src/*": ["./src/*"],
|
||||
"~/*": ["./*"]
|
||||
}
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist",
|
||||
"**/*.test.ts",
|
||||
"**/*.spec.ts",
|
||||
"**/*.integration-test.ts"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"types": ["vitest/globals", "node"]
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.tsx"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import tsconfigPaths from 'vite-tsconfig-paths';
|
||||
import { defineConfig } from 'vitest/config';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
tsconfigPaths({
|
||||
projects: ['tsconfig.spec.json'],
|
||||
ignoreConfigErrors: true,
|
||||
}),
|
||||
],
|
||||
test: {
|
||||
testTimeout: 120_000,
|
||||
hookTimeout: 120_000,
|
||||
include: ['src/**/*.integration-test.ts'],
|
||||
setupFiles: ['src/__tests__/setup-test.ts'],
|
||||
env: {
|
||||
TWENTY_API_KEY:
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ1c2VySWQiOiIyMDIwMjAyMC1lNmI1LTQ2ODAtOGEzMi1iODIwOTczNzE1NmIiLCJ3b3Jrc3BhY2VJZCI6IjIwMjAyMDIwLTFjMjUtNGQwMi1iZjI1LTZhZWNjZjdlYTQxOSIsIndvcmtzcGFjZU1lbWJlcklkIjoiMjAyMDIwMjAtNDYzZi00MzViLTgyOGMtMTA3ZTAwN2EyNzExIiwidXNlcldvcmtzcGFjZUlkIjoiMjAyMDIwMjAtMWU3Yy00M2Q5LWE1ZGItNjg1YjUwNjlkODE2IiwidHlwZSI6IkFDQ0VTUyIsImF1dGhQcm92aWRlciI6InBhc3N3b3JkIiwiaWF0IjoxNzUxMjgxNzA0LCJleHAiOjIwNjY4NTc3MDR9.HMGqCsVlOAPVUBhKSGlD1X86VoHKt4LIUtET3CGIdik',
|
||||
},
|
||||
},
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "twenty-client-sdk",
|
||||
"version": "0.8.0",
|
||||
"version": "0.9.0-canary.0",
|
||||
"sideEffects": false,
|
||||
"license": "AGPL-3.0",
|
||||
"scripts": {
|
||||
|
||||
@@ -584,7 +584,7 @@ type ViewField {
|
||||
createdAt: DateTime!
|
||||
updatedAt: DateTime!
|
||||
deletedAt: DateTime
|
||||
isOverridden: Boolean!
|
||||
isOverridden: Boolean @deprecated(reason: "isOverridden is deprecated")
|
||||
}
|
||||
|
||||
enum AggregateOperations {
|
||||
@@ -693,7 +693,7 @@ type ViewFieldGroup {
|
||||
updatedAt: DateTime!
|
||||
deletedAt: DateTime
|
||||
viewFields: [ViewField!]!
|
||||
isOverridden: Boolean!
|
||||
isOverridden: Boolean! @deprecated(reason: "isOverridden is deprecated")
|
||||
}
|
||||
|
||||
type View {
|
||||
@@ -899,7 +899,7 @@ type PageLayoutWidget {
|
||||
createdAt: DateTime!
|
||||
updatedAt: DateTime!
|
||||
deletedAt: DateTime
|
||||
isOverridden: Boolean!
|
||||
isOverridden: Boolean @deprecated(reason: "isOverridden is deprecated")
|
||||
}
|
||||
|
||||
enum WidgetType {
|
||||
@@ -1233,7 +1233,7 @@ type PageLayoutTab {
|
||||
createdAt: DateTime!
|
||||
updatedAt: DateTime!
|
||||
deletedAt: DateTime
|
||||
isOverridden: Boolean!
|
||||
isOverridden: Boolean @deprecated(reason: "isOverridden is deprecated")
|
||||
}
|
||||
|
||||
type PageLayout {
|
||||
@@ -1729,13 +1729,13 @@ enum FeatureFlagKey {
|
||||
IS_JSON_FILTER_ENABLED
|
||||
IS_AI_ENABLED
|
||||
IS_COMMAND_MENU_ITEM_ENABLED
|
||||
IS_MARKETPLACE_ENABLED
|
||||
IS_MARKETPLACE_SETTING_TAB_VISIBLE
|
||||
IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED
|
||||
IS_PUBLIC_DOMAIN_ENABLED
|
||||
IS_EMAILING_DOMAIN_ENABLED
|
||||
IS_JUNCTION_RELATIONS_ENABLED
|
||||
IS_DRAFT_EMAIL_ENABLED
|
||||
IS_CONNECTED_ACCOUNT_MIGRATED
|
||||
IS_USAGE_ANALYTICS_ENABLED
|
||||
IS_RICH_TEXT_V1_MIGRATED
|
||||
IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED
|
||||
@@ -2575,6 +2575,7 @@ type CommandMenuItem {
|
||||
position: Float!
|
||||
isPinned: Boolean!
|
||||
availabilityType: CommandMenuItemAvailabilityType!
|
||||
payload: CommandMenuItemPayload
|
||||
hotKeys: [String!]
|
||||
conditionalAvailabilityExpression: String
|
||||
availabilityObjectMetadataId: UUID
|
||||
@@ -2601,19 +2602,11 @@ enum EngineComponentKey {
|
||||
SEE_DELETED_RECORDS
|
||||
CREATE_NEW_VIEW
|
||||
HIDE_DELETED_RECORDS
|
||||
GO_TO_PEOPLE
|
||||
GO_TO_COMPANIES
|
||||
GO_TO_DASHBOARDS
|
||||
GO_TO_OPPORTUNITIES
|
||||
GO_TO_SETTINGS
|
||||
GO_TO_TASKS
|
||||
GO_TO_NOTES
|
||||
EDIT_RECORD_PAGE_LAYOUT
|
||||
EDIT_DASHBOARD_LAYOUT
|
||||
SAVE_DASHBOARD_LAYOUT
|
||||
CANCEL_DASHBOARD_LAYOUT
|
||||
DUPLICATE_DASHBOARD
|
||||
GO_TO_WORKFLOWS
|
||||
ACTIVATE_WORKFLOW
|
||||
DEACTIVATE_WORKFLOW
|
||||
DISCARD_DRAFT_WORKFLOW
|
||||
@@ -2624,7 +2617,6 @@ enum EngineComponentKey {
|
||||
ADD_NODE_WORKFLOW
|
||||
TIDY_UP_WORKFLOW
|
||||
DUPLICATE_WORKFLOW
|
||||
GO_TO_RUNS
|
||||
SEE_VERSION_WORKFLOW_RUN
|
||||
SEE_WORKFLOW_WORKFLOW_RUN
|
||||
STOP_WORKFLOW_RUN
|
||||
@@ -2636,9 +2628,20 @@ enum EngineComponentKey {
|
||||
SEARCH_RECORDS_FALLBACK
|
||||
ASK_AI
|
||||
VIEW_PREVIOUS_AI_CHATS
|
||||
NAVIGATION
|
||||
TRIGGER_WORKFLOW_VERSION
|
||||
FRONT_COMPONENT_RENDERER
|
||||
REPLY_TO_EMAIL_THREAD
|
||||
COMPOSE_EMAIL
|
||||
GO_TO_PEOPLE
|
||||
GO_TO_COMPANIES
|
||||
GO_TO_DASHBOARDS
|
||||
GO_TO_OPPORTUNITIES
|
||||
GO_TO_SETTINGS
|
||||
GO_TO_TASKS
|
||||
GO_TO_NOTES
|
||||
GO_TO_WORKFLOWS
|
||||
GO_TO_RUNS
|
||||
DELETE_SINGLE_RECORD
|
||||
DELETE_MULTIPLE_RECORDS
|
||||
RESTORE_SINGLE_RECORD
|
||||
@@ -2656,6 +2659,16 @@ enum CommandMenuItemAvailabilityType {
|
||||
FALLBACK
|
||||
}
|
||||
|
||||
union CommandMenuItemPayload = PathCommandMenuItemPayload | ObjectMetadataCommandMenuItemPayload
|
||||
|
||||
type PathCommandMenuItemPayload {
|
||||
path: String!
|
||||
}
|
||||
|
||||
type ObjectMetadataCommandMenuItemPayload {
|
||||
objectMetadataItemId: UUID!
|
||||
}
|
||||
|
||||
type ToolIndexEntry {
|
||||
name: String!
|
||||
description: String!
|
||||
@@ -2762,6 +2775,26 @@ type DuplicatedDashboard {
|
||||
updatedAt: String!
|
||||
}
|
||||
|
||||
type ConnectedAccountDTO {
|
||||
id: UUID!
|
||||
handle: String!
|
||||
provider: String!
|
||||
lastCredentialsRefreshedAt: DateTime
|
||||
authFailedAt: DateTime
|
||||
handleAliases: [String!]
|
||||
scopes: [String!]
|
||||
connectionParameters: ImapSmtpCaldavConnectionParameters
|
||||
lastSignedInAt: DateTime
|
||||
userWorkspaceId: UUID!
|
||||
createdAt: DateTime!
|
||||
updatedAt: DateTime!
|
||||
}
|
||||
|
||||
type SendEmailOutput {
|
||||
success: Boolean!
|
||||
error: String
|
||||
}
|
||||
|
||||
type EventLogRecord {
|
||||
event: String!
|
||||
timestamp: DateTime!
|
||||
@@ -2930,20 +2963,6 @@ enum CalendarChannelContactAutoCreationPolicy {
|
||||
NONE
|
||||
}
|
||||
|
||||
type ConnectedAccountDTO {
|
||||
id: UUID!
|
||||
handle: String!
|
||||
provider: String!
|
||||
lastCredentialsRefreshedAt: DateTime
|
||||
authFailedAt: DateTime
|
||||
handleAliases: [String!]
|
||||
scopes: [String!]
|
||||
lastSignedInAt: DateTime
|
||||
userWorkspaceId: UUID!
|
||||
createdAt: DateTime!
|
||||
updatedAt: DateTime!
|
||||
}
|
||||
|
||||
type MessageChannel {
|
||||
id: UUID!
|
||||
visibility: MessageChannelVisibility!
|
||||
@@ -3226,7 +3245,6 @@ type Query {
|
||||
findApplicationRegistrationStats(id: String!): ApplicationRegistrationStats!
|
||||
findApplicationRegistrationVariables(applicationRegistrationId: String!): [ApplicationRegistrationVariable!]!
|
||||
applicationRegistrationTarballUrl(id: String!): String
|
||||
getApplicationShareLink(id: String!): String!
|
||||
currentUser: User!
|
||||
currentWorkspace: Workspace!
|
||||
getPublicWorkspaceDataByDomain(origin: String): PublicWorkspaceData!
|
||||
@@ -3452,6 +3470,8 @@ type Mutation {
|
||||
updatePageLayout(id: String!, input: UpdatePageLayoutInput!): PageLayout!
|
||||
destroyPageLayout(id: String!): Boolean!
|
||||
updatePageLayoutWithTabsAndWidgets(id: String!, input: UpdatePageLayoutWithTabsInput!): PageLayout!
|
||||
resetPageLayoutWidgetToDefault(id: String!): PageLayoutWidget!
|
||||
resetPageLayoutTabToDefault(id: String!): PageLayoutTab!
|
||||
createPageLayoutWidget(input: CreatePageLayoutWidgetInput!): PageLayoutWidget!
|
||||
updatePageLayoutWidget(id: String!, input: UpdatePageLayoutWidgetInput!): PageLayoutWidget!
|
||||
destroyPageLayoutWidget(id: String!): Boolean!
|
||||
@@ -3552,6 +3572,7 @@ type Mutation {
|
||||
deleteSSOIdentityProvider(input: DeleteSsoInput!): DeleteSso!
|
||||
editSSOIdentityProvider(input: EditSsoInput!): EditSso!
|
||||
impersonate(userId: UUID!, workspaceId: UUID!): Impersonate!
|
||||
sendEmail(input: SendEmailInput!): SendEmailOutput!
|
||||
startChannelSync(connectedAccountId: UUID!): ChannelSyncSuccess!
|
||||
saveImapSmtpCaldavAccount(accountOwnerId: UUID!, handle: String!, connectionParameters: EmailAccountConnectionParameters!, id: UUID): ImapSmtpCaldavConnectionSuccess!
|
||||
updateLabPublicFeatureFlag(input: UpdateLabPublicFeatureFlagInput!): FeatureFlag!
|
||||
@@ -4041,6 +4062,7 @@ input CreateCommandMenuItemInput {
|
||||
hotKeys: [String!]
|
||||
conditionalAvailabilityExpression: String
|
||||
availabilityObjectMetadataId: UUID
|
||||
payload: JSON
|
||||
}
|
||||
|
||||
input UpdateCommandMenuItemInput {
|
||||
@@ -4522,6 +4544,16 @@ input EditSsoInput {
|
||||
status: SSOIdentityProviderStatus!
|
||||
}
|
||||
|
||||
input SendEmailInput {
|
||||
connectedAccountId: String!
|
||||
to: String!
|
||||
cc: String
|
||||
bcc: String
|
||||
subject: String!
|
||||
body: String!
|
||||
inReplyTo: String
|
||||
}
|
||||
|
||||
input EmailAccountConnectionParameters {
|
||||
IMAP: ConnectionParameters
|
||||
SMTP: ConnectionParameters
|
||||
|
||||
@@ -416,7 +416,8 @@ export interface ViewField {
|
||||
createdAt: Scalars['DateTime']
|
||||
updatedAt: Scalars['DateTime']
|
||||
deletedAt?: Scalars['DateTime']
|
||||
isOverridden: Scalars['Boolean']
|
||||
/** @deprecated isOverridden is deprecated */
|
||||
isOverridden?: Scalars['Boolean']
|
||||
__typename: 'ViewField'
|
||||
}
|
||||
|
||||
@@ -493,6 +494,7 @@ export interface ViewFieldGroup {
|
||||
updatedAt: Scalars['DateTime']
|
||||
deletedAt?: Scalars['DateTime']
|
||||
viewFields: ViewField[]
|
||||
/** @deprecated isOverridden is deprecated */
|
||||
isOverridden: Scalars['Boolean']
|
||||
__typename: 'ViewFieldGroup'
|
||||
}
|
||||
@@ -672,7 +674,8 @@ export interface PageLayoutWidget {
|
||||
createdAt: Scalars['DateTime']
|
||||
updatedAt: Scalars['DateTime']
|
||||
deletedAt?: Scalars['DateTime']
|
||||
isOverridden: Scalars['Boolean']
|
||||
/** @deprecated isOverridden is deprecated */
|
||||
isOverridden?: Scalars['Boolean']
|
||||
__typename: 'PageLayoutWidget'
|
||||
}
|
||||
|
||||
@@ -956,7 +959,8 @@ export interface PageLayoutTab {
|
||||
createdAt: Scalars['DateTime']
|
||||
updatedAt: Scalars['DateTime']
|
||||
deletedAt?: Scalars['DateTime']
|
||||
isOverridden: Scalars['Boolean']
|
||||
/** @deprecated isOverridden is deprecated */
|
||||
isOverridden?: Scalars['Boolean']
|
||||
__typename: 'PageLayoutTab'
|
||||
}
|
||||
|
||||
@@ -1429,7 +1433,7 @@ export interface PublicFeatureFlag {
|
||||
__typename: 'PublicFeatureFlag'
|
||||
}
|
||||
|
||||
export type FeatureFlagKey = 'IS_UNIQUE_INDEXES_ENABLED' | 'IS_JSON_FILTER_ENABLED' | 'IS_AI_ENABLED' | 'IS_COMMAND_MENU_ITEM_ENABLED' | 'IS_MARKETPLACE_ENABLED' | 'IS_MARKETPLACE_SETTING_TAB_VISIBLE' | 'IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED' | 'IS_PUBLIC_DOMAIN_ENABLED' | 'IS_EMAILING_DOMAIN_ENABLED' | 'IS_JUNCTION_RELATIONS_ENABLED' | 'IS_DRAFT_EMAIL_ENABLED' | 'IS_USAGE_ANALYTICS_ENABLED' | 'IS_RICH_TEXT_V1_MIGRATED' | 'IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED' | 'IS_RECORD_TABLE_WIDGET_ENABLED' | 'IS_DATASOURCE_MIGRATED'
|
||||
export type FeatureFlagKey = 'IS_UNIQUE_INDEXES_ENABLED' | 'IS_JSON_FILTER_ENABLED' | 'IS_AI_ENABLED' | 'IS_COMMAND_MENU_ITEM_ENABLED' | 'IS_MARKETPLACE_SETTING_TAB_VISIBLE' | 'IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED' | 'IS_PUBLIC_DOMAIN_ENABLED' | 'IS_EMAILING_DOMAIN_ENABLED' | 'IS_JUNCTION_RELATIONS_ENABLED' | 'IS_DRAFT_EMAIL_ENABLED' | 'IS_CONNECTED_ACCOUNT_MIGRATED' | 'IS_USAGE_ANALYTICS_ENABLED' | 'IS_RICH_TEXT_V1_MIGRATED' | 'IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED' | 'IS_RECORD_TABLE_WIDGET_ENABLED' | 'IS_DATASOURCE_MIGRATED'
|
||||
|
||||
export interface ClientConfigMaintenanceMode {
|
||||
startAt: Scalars['DateTime']
|
||||
@@ -2286,6 +2290,7 @@ export interface CommandMenuItem {
|
||||
position: Scalars['Float']
|
||||
isPinned: Scalars['Boolean']
|
||||
availabilityType: CommandMenuItemAvailabilityType
|
||||
payload?: CommandMenuItemPayload
|
||||
hotKeys?: Scalars['String'][]
|
||||
conditionalAvailabilityExpression?: Scalars['String']
|
||||
availabilityObjectMetadataId?: Scalars['UUID']
|
||||
@@ -2295,10 +2300,22 @@ export interface CommandMenuItem {
|
||||
__typename: 'CommandMenuItem'
|
||||
}
|
||||
|
||||
export type EngineComponentKey = 'NAVIGATE_TO_NEXT_RECORD' | 'NAVIGATE_TO_PREVIOUS_RECORD' | 'CREATE_NEW_RECORD' | 'DELETE_RECORDS' | 'RESTORE_RECORDS' | 'DESTROY_RECORDS' | 'ADD_TO_FAVORITES' | 'REMOVE_FROM_FAVORITES' | 'EXPORT_NOTE_TO_PDF' | 'EXPORT_RECORDS' | 'UPDATE_MULTIPLE_RECORDS' | 'MERGE_MULTIPLE_RECORDS' | 'IMPORT_RECORDS' | 'EXPORT_VIEW' | 'SEE_DELETED_RECORDS' | 'CREATE_NEW_VIEW' | 'HIDE_DELETED_RECORDS' | 'GO_TO_PEOPLE' | 'GO_TO_COMPANIES' | 'GO_TO_DASHBOARDS' | 'GO_TO_OPPORTUNITIES' | 'GO_TO_SETTINGS' | 'GO_TO_TASKS' | 'GO_TO_NOTES' | 'EDIT_RECORD_PAGE_LAYOUT' | 'EDIT_DASHBOARD_LAYOUT' | 'SAVE_DASHBOARD_LAYOUT' | 'CANCEL_DASHBOARD_LAYOUT' | 'DUPLICATE_DASHBOARD' | 'GO_TO_WORKFLOWS' | 'ACTIVATE_WORKFLOW' | 'DEACTIVATE_WORKFLOW' | 'DISCARD_DRAFT_WORKFLOW' | 'TEST_WORKFLOW' | 'SEE_ACTIVE_VERSION_WORKFLOW' | 'SEE_RUNS_WORKFLOW' | 'SEE_VERSIONS_WORKFLOW' | 'ADD_NODE_WORKFLOW' | 'TIDY_UP_WORKFLOW' | 'DUPLICATE_WORKFLOW' | 'GO_TO_RUNS' | 'SEE_VERSION_WORKFLOW_RUN' | 'SEE_WORKFLOW_WORKFLOW_RUN' | 'STOP_WORKFLOW_RUN' | 'SEE_RUNS_WORKFLOW_VERSION' | 'SEE_WORKFLOW_WORKFLOW_VERSION' | 'USE_AS_DRAFT_WORKFLOW_VERSION' | 'SEE_VERSIONS_WORKFLOW_VERSION' | 'SEARCH_RECORDS' | 'SEARCH_RECORDS_FALLBACK' | 'ASK_AI' | 'VIEW_PREVIOUS_AI_CHATS' | 'TRIGGER_WORKFLOW_VERSION' | 'FRONT_COMPONENT_RENDERER' | 'REPLY_TO_EMAIL_THREAD' | 'DELETE_SINGLE_RECORD' | 'DELETE_MULTIPLE_RECORDS' | 'RESTORE_SINGLE_RECORD' | 'RESTORE_MULTIPLE_RECORDS' | 'DESTROY_SINGLE_RECORD' | 'DESTROY_MULTIPLE_RECORDS' | 'EXPORT_FROM_RECORD_INDEX' | 'EXPORT_FROM_RECORD_SHOW' | 'EXPORT_MULTIPLE_RECORDS'
|
||||
export type EngineComponentKey = 'NAVIGATE_TO_NEXT_RECORD' | 'NAVIGATE_TO_PREVIOUS_RECORD' | 'CREATE_NEW_RECORD' | 'DELETE_RECORDS' | 'RESTORE_RECORDS' | 'DESTROY_RECORDS' | 'ADD_TO_FAVORITES' | 'REMOVE_FROM_FAVORITES' | 'EXPORT_NOTE_TO_PDF' | 'EXPORT_RECORDS' | 'UPDATE_MULTIPLE_RECORDS' | 'MERGE_MULTIPLE_RECORDS' | 'IMPORT_RECORDS' | 'EXPORT_VIEW' | 'SEE_DELETED_RECORDS' | 'CREATE_NEW_VIEW' | 'HIDE_DELETED_RECORDS' | 'EDIT_RECORD_PAGE_LAYOUT' | 'EDIT_DASHBOARD_LAYOUT' | 'SAVE_DASHBOARD_LAYOUT' | 'CANCEL_DASHBOARD_LAYOUT' | 'DUPLICATE_DASHBOARD' | 'ACTIVATE_WORKFLOW' | 'DEACTIVATE_WORKFLOW' | 'DISCARD_DRAFT_WORKFLOW' | 'TEST_WORKFLOW' | 'SEE_ACTIVE_VERSION_WORKFLOW' | 'SEE_RUNS_WORKFLOW' | 'SEE_VERSIONS_WORKFLOW' | 'ADD_NODE_WORKFLOW' | 'TIDY_UP_WORKFLOW' | 'DUPLICATE_WORKFLOW' | 'SEE_VERSION_WORKFLOW_RUN' | 'SEE_WORKFLOW_WORKFLOW_RUN' | 'STOP_WORKFLOW_RUN' | 'SEE_RUNS_WORKFLOW_VERSION' | 'SEE_WORKFLOW_WORKFLOW_VERSION' | 'USE_AS_DRAFT_WORKFLOW_VERSION' | 'SEE_VERSIONS_WORKFLOW_VERSION' | 'SEARCH_RECORDS' | 'SEARCH_RECORDS_FALLBACK' | 'ASK_AI' | 'VIEW_PREVIOUS_AI_CHATS' | 'NAVIGATION' | 'TRIGGER_WORKFLOW_VERSION' | 'FRONT_COMPONENT_RENDERER' | 'REPLY_TO_EMAIL_THREAD' | 'COMPOSE_EMAIL' | 'GO_TO_PEOPLE' | 'GO_TO_COMPANIES' | 'GO_TO_DASHBOARDS' | 'GO_TO_OPPORTUNITIES' | 'GO_TO_SETTINGS' | 'GO_TO_TASKS' | 'GO_TO_NOTES' | 'GO_TO_WORKFLOWS' | 'GO_TO_RUNS' | 'DELETE_SINGLE_RECORD' | 'DELETE_MULTIPLE_RECORDS' | 'RESTORE_SINGLE_RECORD' | 'RESTORE_MULTIPLE_RECORDS' | 'DESTROY_SINGLE_RECORD' | 'DESTROY_MULTIPLE_RECORDS' | 'EXPORT_FROM_RECORD_INDEX' | 'EXPORT_FROM_RECORD_SHOW' | 'EXPORT_MULTIPLE_RECORDS'
|
||||
|
||||
export type CommandMenuItemAvailabilityType = 'GLOBAL' | 'RECORD_SELECTION' | 'FALLBACK'
|
||||
|
||||
export type CommandMenuItemPayload = (PathCommandMenuItemPayload | ObjectMetadataCommandMenuItemPayload) & { __isUnion?: true }
|
||||
|
||||
export interface PathCommandMenuItemPayload {
|
||||
path: Scalars['String']
|
||||
__typename: 'PathCommandMenuItemPayload'
|
||||
}
|
||||
|
||||
export interface ObjectMetadataCommandMenuItemPayload {
|
||||
objectMetadataItemId: Scalars['UUID']
|
||||
__typename: 'ObjectMetadataCommandMenuItemPayload'
|
||||
}
|
||||
|
||||
export interface ToolIndexEntry {
|
||||
name: Scalars['String']
|
||||
description: Scalars['String']
|
||||
@@ -2416,6 +2433,28 @@ export interface DuplicatedDashboard {
|
||||
__typename: 'DuplicatedDashboard'
|
||||
}
|
||||
|
||||
export interface ConnectedAccountDTO {
|
||||
id: Scalars['UUID']
|
||||
handle: Scalars['String']
|
||||
provider: Scalars['String']
|
||||
lastCredentialsRefreshedAt?: Scalars['DateTime']
|
||||
authFailedAt?: Scalars['DateTime']
|
||||
handleAliases?: Scalars['String'][]
|
||||
scopes?: Scalars['String'][]
|
||||
connectionParameters?: ImapSmtpCaldavConnectionParameters
|
||||
lastSignedInAt?: Scalars['DateTime']
|
||||
userWorkspaceId: Scalars['UUID']
|
||||
createdAt: Scalars['DateTime']
|
||||
updatedAt: Scalars['DateTime']
|
||||
__typename: 'ConnectedAccountDTO'
|
||||
}
|
||||
|
||||
export interface SendEmailOutput {
|
||||
success: Scalars['Boolean']
|
||||
error?: Scalars['String']
|
||||
__typename: 'SendEmailOutput'
|
||||
}
|
||||
|
||||
export interface EventLogRecord {
|
||||
event: Scalars['String']
|
||||
timestamp: Scalars['DateTime']
|
||||
@@ -2575,21 +2614,6 @@ export type CalendarChannelVisibility = 'METADATA' | 'SHARE_EVERYTHING'
|
||||
|
||||
export type CalendarChannelContactAutoCreationPolicy = 'AS_PARTICIPANT_AND_ORGANIZER' | 'AS_PARTICIPANT' | 'AS_ORGANIZER' | 'NONE'
|
||||
|
||||
export interface ConnectedAccountDTO {
|
||||
id: Scalars['UUID']
|
||||
handle: Scalars['String']
|
||||
provider: Scalars['String']
|
||||
lastCredentialsRefreshedAt?: Scalars['DateTime']
|
||||
authFailedAt?: Scalars['DateTime']
|
||||
handleAliases?: Scalars['String'][]
|
||||
scopes?: Scalars['String'][]
|
||||
lastSignedInAt?: Scalars['DateTime']
|
||||
userWorkspaceId: Scalars['UUID']
|
||||
createdAt: Scalars['DateTime']
|
||||
updatedAt: Scalars['DateTime']
|
||||
__typename: 'ConnectedAccountDTO'
|
||||
}
|
||||
|
||||
export interface MessageChannel {
|
||||
id: Scalars['UUID']
|
||||
visibility: MessageChannelVisibility
|
||||
@@ -2779,7 +2803,6 @@ export interface Query {
|
||||
findApplicationRegistrationStats: ApplicationRegistrationStats
|
||||
findApplicationRegistrationVariables: ApplicationRegistrationVariable[]
|
||||
applicationRegistrationTarballUrl?: Scalars['String']
|
||||
getApplicationShareLink: Scalars['String']
|
||||
currentUser: User
|
||||
currentWorkspace: Workspace
|
||||
getPublicWorkspaceDataByDomain: PublicWorkspaceData
|
||||
@@ -2899,6 +2922,8 @@ export interface Mutation {
|
||||
updatePageLayout: PageLayout
|
||||
destroyPageLayout: Scalars['Boolean']
|
||||
updatePageLayoutWithTabsAndWidgets: PageLayout
|
||||
resetPageLayoutWidgetToDefault: PageLayoutWidget
|
||||
resetPageLayoutTabToDefault: PageLayoutTab
|
||||
createPageLayoutWidget: PageLayoutWidget
|
||||
updatePageLayoutWidget: PageLayoutWidget
|
||||
destroyPageLayoutWidget: Scalars['Boolean']
|
||||
@@ -2999,6 +3024,7 @@ export interface Mutation {
|
||||
deleteSSOIdentityProvider: DeleteSso
|
||||
editSSOIdentityProvider: EditSso
|
||||
impersonate: Impersonate
|
||||
sendEmail: SendEmailOutput
|
||||
startChannelSync: ChannelSyncSuccess
|
||||
saveImapSmtpCaldavAccount: ImapSmtpCaldavConnectionSuccess
|
||||
updateLabPublicFeatureFlag: FeatureFlag
|
||||
@@ -3504,6 +3530,7 @@ export interface ViewFieldGenqlSelection{
|
||||
createdAt?: boolean | number
|
||||
updatedAt?: boolean | number
|
||||
deletedAt?: boolean | number
|
||||
/** @deprecated isOverridden is deprecated */
|
||||
isOverridden?: boolean | number
|
||||
__typename?: boolean | number
|
||||
__scalar?: boolean | number
|
||||
@@ -3578,6 +3605,7 @@ export interface ViewFieldGroupGenqlSelection{
|
||||
updatedAt?: boolean | number
|
||||
deletedAt?: boolean | number
|
||||
viewFields?: ViewFieldGenqlSelection
|
||||
/** @deprecated isOverridden is deprecated */
|
||||
isOverridden?: boolean | number
|
||||
__typename?: boolean | number
|
||||
__scalar?: boolean | number
|
||||
@@ -3749,6 +3777,7 @@ export interface PageLayoutWidgetGenqlSelection{
|
||||
createdAt?: boolean | number
|
||||
updatedAt?: boolean | number
|
||||
deletedAt?: boolean | number
|
||||
/** @deprecated isOverridden is deprecated */
|
||||
isOverridden?: boolean | number
|
||||
__typename?: boolean | number
|
||||
__scalar?: boolean | number
|
||||
@@ -4060,6 +4089,7 @@ export interface PageLayoutTabGenqlSelection{
|
||||
createdAt?: boolean | number
|
||||
updatedAt?: boolean | number
|
||||
deletedAt?: boolean | number
|
||||
/** @deprecated isOverridden is deprecated */
|
||||
isOverridden?: boolean | number
|
||||
__typename?: boolean | number
|
||||
__scalar?: boolean | number
|
||||
@@ -5477,6 +5507,7 @@ export interface CommandMenuItemGenqlSelection{
|
||||
position?: boolean | number
|
||||
isPinned?: boolean | number
|
||||
availabilityType?: boolean | number
|
||||
payload?: CommandMenuItemPayloadGenqlSelection
|
||||
hotKeys?: boolean | number
|
||||
conditionalAvailabilityExpression?: boolean | number
|
||||
availabilityObjectMetadataId?: boolean | number
|
||||
@@ -5487,6 +5518,24 @@ export interface CommandMenuItemGenqlSelection{
|
||||
__scalar?: boolean | number
|
||||
}
|
||||
|
||||
export interface CommandMenuItemPayloadGenqlSelection{
|
||||
on_PathCommandMenuItemPayload?:PathCommandMenuItemPayloadGenqlSelection,
|
||||
on_ObjectMetadataCommandMenuItemPayload?:ObjectMetadataCommandMenuItemPayloadGenqlSelection,
|
||||
__typename?: boolean | number
|
||||
}
|
||||
|
||||
export interface PathCommandMenuItemPayloadGenqlSelection{
|
||||
path?: boolean | number
|
||||
__typename?: boolean | number
|
||||
__scalar?: boolean | number
|
||||
}
|
||||
|
||||
export interface ObjectMetadataCommandMenuItemPayloadGenqlSelection{
|
||||
objectMetadataItemId?: boolean | number
|
||||
__typename?: boolean | number
|
||||
__scalar?: boolean | number
|
||||
}
|
||||
|
||||
export interface ToolIndexEntryGenqlSelection{
|
||||
name?: boolean | number
|
||||
description?: boolean | number
|
||||
@@ -5615,6 +5664,30 @@ export interface DuplicatedDashboardGenqlSelection{
|
||||
__scalar?: boolean | number
|
||||
}
|
||||
|
||||
export interface ConnectedAccountDTOGenqlSelection{
|
||||
id?: boolean | number
|
||||
handle?: boolean | number
|
||||
provider?: boolean | number
|
||||
lastCredentialsRefreshedAt?: boolean | number
|
||||
authFailedAt?: boolean | number
|
||||
handleAliases?: boolean | number
|
||||
scopes?: boolean | number
|
||||
connectionParameters?: ImapSmtpCaldavConnectionParametersGenqlSelection
|
||||
lastSignedInAt?: boolean | number
|
||||
userWorkspaceId?: boolean | number
|
||||
createdAt?: boolean | number
|
||||
updatedAt?: boolean | number
|
||||
__typename?: boolean | number
|
||||
__scalar?: boolean | number
|
||||
}
|
||||
|
||||
export interface SendEmailOutputGenqlSelection{
|
||||
success?: boolean | number
|
||||
error?: boolean | number
|
||||
__typename?: boolean | number
|
||||
__scalar?: boolean | number
|
||||
}
|
||||
|
||||
export interface EventLogRecordGenqlSelection{
|
||||
event?: boolean | number
|
||||
timestamp?: boolean | number
|
||||
@@ -5782,22 +5855,6 @@ export interface CalendarChannelGenqlSelection{
|
||||
__scalar?: boolean | number
|
||||
}
|
||||
|
||||
export interface ConnectedAccountDTOGenqlSelection{
|
||||
id?: boolean | number
|
||||
handle?: boolean | number
|
||||
provider?: boolean | number
|
||||
lastCredentialsRefreshedAt?: boolean | number
|
||||
authFailedAt?: boolean | number
|
||||
handleAliases?: boolean | number
|
||||
scopes?: boolean | number
|
||||
lastSignedInAt?: boolean | number
|
||||
userWorkspaceId?: boolean | number
|
||||
createdAt?: boolean | number
|
||||
updatedAt?: boolean | number
|
||||
__typename?: boolean | number
|
||||
__scalar?: boolean | number
|
||||
}
|
||||
|
||||
export interface MessageChannelGenqlSelection{
|
||||
id?: boolean | number
|
||||
visibility?: boolean | number
|
||||
@@ -6000,7 +6057,6 @@ export interface QueryGenqlSelection{
|
||||
findApplicationRegistrationStats?: (ApplicationRegistrationStatsGenqlSelection & { __args: {id: Scalars['String']} })
|
||||
findApplicationRegistrationVariables?: (ApplicationRegistrationVariableGenqlSelection & { __args: {applicationRegistrationId: Scalars['String']} })
|
||||
applicationRegistrationTarballUrl?: { __args: {id: Scalars['String']} }
|
||||
getApplicationShareLink?: { __args: {id: Scalars['String']} }
|
||||
currentUser?: UserGenqlSelection
|
||||
currentWorkspace?: WorkspaceGenqlSelection
|
||||
getPublicWorkspaceDataByDomain?: (PublicWorkspaceDataGenqlSelection & { __args?: {origin?: (Scalars['String'] | null)} })
|
||||
@@ -6139,6 +6195,8 @@ export interface MutationGenqlSelection{
|
||||
updatePageLayout?: (PageLayoutGenqlSelection & { __args: {id: Scalars['String'], input: UpdatePageLayoutInput} })
|
||||
destroyPageLayout?: { __args: {id: Scalars['String']} }
|
||||
updatePageLayoutWithTabsAndWidgets?: (PageLayoutGenqlSelection & { __args: {id: Scalars['String'], input: UpdatePageLayoutWithTabsInput} })
|
||||
resetPageLayoutWidgetToDefault?: (PageLayoutWidgetGenqlSelection & { __args: {id: Scalars['String']} })
|
||||
resetPageLayoutTabToDefault?: (PageLayoutTabGenqlSelection & { __args: {id: Scalars['String']} })
|
||||
createPageLayoutWidget?: (PageLayoutWidgetGenqlSelection & { __args: {input: CreatePageLayoutWidgetInput} })
|
||||
updatePageLayoutWidget?: (PageLayoutWidgetGenqlSelection & { __args: {id: Scalars['String'], input: UpdatePageLayoutWidgetInput} })
|
||||
destroyPageLayoutWidget?: { __args: {id: Scalars['String']} }
|
||||
@@ -6239,6 +6297,7 @@ export interface MutationGenqlSelection{
|
||||
deleteSSOIdentityProvider?: (DeleteSsoGenqlSelection & { __args: {input: DeleteSsoInput} })
|
||||
editSSOIdentityProvider?: (EditSsoGenqlSelection & { __args: {input: EditSsoInput} })
|
||||
impersonate?: (ImpersonateGenqlSelection & { __args: {userId: Scalars['UUID'], workspaceId: Scalars['UUID']} })
|
||||
sendEmail?: (SendEmailOutputGenqlSelection & { __args: {input: SendEmailInput} })
|
||||
startChannelSync?: (ChannelSyncSuccessGenqlSelection & { __args: {connectedAccountId: Scalars['UUID']} })
|
||||
saveImapSmtpCaldavAccount?: (ImapSmtpCaldavConnectionSuccessGenqlSelection & { __args: {accountOwnerId: Scalars['UUID'], handle: Scalars['String'], connectionParameters: EmailAccountConnectionParameters, id?: (Scalars['UUID'] | null)} })
|
||||
updateLabPublicFeatureFlag?: (FeatureFlagGenqlSelection & { __args: {input: UpdateLabPublicFeatureFlagInput} })
|
||||
@@ -6441,7 +6500,7 @@ update: UpdateLogicFunctionFromSourceInputUpdates}
|
||||
|
||||
export interface UpdateLogicFunctionFromSourceInputUpdates {name?: (Scalars['String'] | null),description?: (Scalars['String'] | null),timeoutSeconds?: (Scalars['Float'] | null),sourceHandlerCode?: (Scalars['String'] | null),toolInputSchema?: (Scalars['JSON'] | null),handlerName?: (Scalars['String'] | null),sourceHandlerPath?: (Scalars['String'] | null),isTool?: (Scalars['Boolean'] | null),cronTriggerSettings?: (Scalars['JSON'] | null),databaseEventTriggerSettings?: (Scalars['JSON'] | null),httpRouteTriggerSettings?: (Scalars['JSON'] | null)}
|
||||
|
||||
export interface CreateCommandMenuItemInput {workflowVersionId?: (Scalars['UUID'] | null),frontComponentId?: (Scalars['UUID'] | null),engineComponentKey: EngineComponentKey,label: Scalars['String'],icon?: (Scalars['String'] | null),shortLabel?: (Scalars['String'] | null),position?: (Scalars['Float'] | null),isPinned?: (Scalars['Boolean'] | null),availabilityType?: (CommandMenuItemAvailabilityType | null),hotKeys?: (Scalars['String'][] | null),conditionalAvailabilityExpression?: (Scalars['String'] | null),availabilityObjectMetadataId?: (Scalars['UUID'] | null)}
|
||||
export interface CreateCommandMenuItemInput {workflowVersionId?: (Scalars['UUID'] | null),frontComponentId?: (Scalars['UUID'] | null),engineComponentKey: EngineComponentKey,label: Scalars['String'],icon?: (Scalars['String'] | null),shortLabel?: (Scalars['String'] | null),position?: (Scalars['Float'] | null),isPinned?: (Scalars['Boolean'] | null),availabilityType?: (CommandMenuItemAvailabilityType | null),hotKeys?: (Scalars['String'][] | null),conditionalAvailabilityExpression?: (Scalars['String'] | null),availabilityObjectMetadataId?: (Scalars['UUID'] | null),payload?: (Scalars['JSON'] | null)}
|
||||
|
||||
export interface UpdateCommandMenuItemInput {id: Scalars['UUID'],label?: (Scalars['String'] | null),icon?: (Scalars['String'] | null),shortLabel?: (Scalars['String'] | null),position?: (Scalars['Float'] | null),isPinned?: (Scalars['Boolean'] | null),availabilityType?: (CommandMenuItemAvailabilityType | null),availabilityObjectMetadataId?: (Scalars['UUID'] | null),engineComponentKey?: (EngineComponentKey | null),hotKeys?: (Scalars['String'][] | null)}
|
||||
|
||||
@@ -6589,6 +6648,8 @@ export interface DeleteSsoInput {identityProviderId: Scalars['UUID']}
|
||||
|
||||
export interface EditSsoInput {id: Scalars['UUID'],status: SSOIdentityProviderStatus}
|
||||
|
||||
export interface SendEmailInput {connectedAccountId: Scalars['String'],to: Scalars['String'],cc?: (Scalars['String'] | null),bcc?: (Scalars['String'] | null),subject: Scalars['String'],body: Scalars['String'],inReplyTo?: (Scalars['String'] | null)}
|
||||
|
||||
export interface EmailAccountConnectionParameters {IMAP?: (ConnectionParameters | null),SMTP?: (ConnectionParameters | null),CALDAV?: (ConnectionParameters | null)}
|
||||
|
||||
export interface ConnectionParameters {host: Scalars['String'],port: Scalars['Float'],username?: (Scalars['String'] | null),password: Scalars['String'],secure?: (Scalars['Boolean'] | null)}
|
||||
@@ -8408,6 +8469,30 @@ export interface LogicFunctionLogsInput {applicationId?: (Scalars['UUID'] | null
|
||||
|
||||
|
||||
|
||||
const CommandMenuItemPayload_possibleTypes: string[] = ['PathCommandMenuItemPayload','ObjectMetadataCommandMenuItemPayload']
|
||||
export const isCommandMenuItemPayload = (obj?: { __typename?: any } | null): obj is CommandMenuItemPayload => {
|
||||
if (!obj?.__typename) throw new Error('__typename is missing in "isCommandMenuItemPayload"')
|
||||
return CommandMenuItemPayload_possibleTypes.includes(obj.__typename)
|
||||
}
|
||||
|
||||
|
||||
|
||||
const PathCommandMenuItemPayload_possibleTypes: string[] = ['PathCommandMenuItemPayload']
|
||||
export const isPathCommandMenuItemPayload = (obj?: { __typename?: any } | null): obj is PathCommandMenuItemPayload => {
|
||||
if (!obj?.__typename) throw new Error('__typename is missing in "isPathCommandMenuItemPayload"')
|
||||
return PathCommandMenuItemPayload_possibleTypes.includes(obj.__typename)
|
||||
}
|
||||
|
||||
|
||||
|
||||
const ObjectMetadataCommandMenuItemPayload_possibleTypes: string[] = ['ObjectMetadataCommandMenuItemPayload']
|
||||
export const isObjectMetadataCommandMenuItemPayload = (obj?: { __typename?: any } | null): obj is ObjectMetadataCommandMenuItemPayload => {
|
||||
if (!obj?.__typename) throw new Error('__typename is missing in "isObjectMetadataCommandMenuItemPayload"')
|
||||
return ObjectMetadataCommandMenuItemPayload_possibleTypes.includes(obj.__typename)
|
||||
}
|
||||
|
||||
|
||||
|
||||
const ToolIndexEntry_possibleTypes: string[] = ['ToolIndexEntry']
|
||||
export const isToolIndexEntry = (obj?: { __typename?: any } | null): obj is ToolIndexEntry => {
|
||||
if (!obj?.__typename) throw new Error('__typename is missing in "isToolIndexEntry"')
|
||||
@@ -8496,6 +8581,22 @@ export interface LogicFunctionLogsInput {applicationId?: (Scalars['UUID'] | null
|
||||
|
||||
|
||||
|
||||
const ConnectedAccountDTO_possibleTypes: string[] = ['ConnectedAccountDTO']
|
||||
export const isConnectedAccountDTO = (obj?: { __typename?: any } | null): obj is ConnectedAccountDTO => {
|
||||
if (!obj?.__typename) throw new Error('__typename is missing in "isConnectedAccountDTO"')
|
||||
return ConnectedAccountDTO_possibleTypes.includes(obj.__typename)
|
||||
}
|
||||
|
||||
|
||||
|
||||
const SendEmailOutput_possibleTypes: string[] = ['SendEmailOutput']
|
||||
export const isSendEmailOutput = (obj?: { __typename?: any } | null): obj is SendEmailOutput => {
|
||||
if (!obj?.__typename) throw new Error('__typename is missing in "isSendEmailOutput"')
|
||||
return SendEmailOutput_possibleTypes.includes(obj.__typename)
|
||||
}
|
||||
|
||||
|
||||
|
||||
const EventLogRecord_possibleTypes: string[] = ['EventLogRecord']
|
||||
export const isEventLogRecord = (obj?: { __typename?: any } | null): obj is EventLogRecord => {
|
||||
if (!obj?.__typename) throw new Error('__typename is missing in "isEventLogRecord"')
|
||||
@@ -8624,14 +8725,6 @@ export interface LogicFunctionLogsInput {applicationId?: (Scalars['UUID'] | null
|
||||
|
||||
|
||||
|
||||
const ConnectedAccountDTO_possibleTypes: string[] = ['ConnectedAccountDTO']
|
||||
export const isConnectedAccountDTO = (obj?: { __typename?: any } | null): obj is ConnectedAccountDTO => {
|
||||
if (!obj?.__typename) throw new Error('__typename is missing in "isConnectedAccountDTO"')
|
||||
return ConnectedAccountDTO_possibleTypes.includes(obj.__typename)
|
||||
}
|
||||
|
||||
|
||||
|
||||
const MessageChannel_possibleTypes: string[] = ['MessageChannel']
|
||||
export const isMessageChannel = (obj?: { __typename?: any } | null): obj is MessageChannel => {
|
||||
if (!obj?.__typename) throw new Error('__typename is missing in "isMessageChannel"')
|
||||
@@ -9113,13 +9206,13 @@ export const enumFeatureFlagKey = {
|
||||
IS_JSON_FILTER_ENABLED: 'IS_JSON_FILTER_ENABLED' as const,
|
||||
IS_AI_ENABLED: 'IS_AI_ENABLED' as const,
|
||||
IS_COMMAND_MENU_ITEM_ENABLED: 'IS_COMMAND_MENU_ITEM_ENABLED' as const,
|
||||
IS_MARKETPLACE_ENABLED: 'IS_MARKETPLACE_ENABLED' as const,
|
||||
IS_MARKETPLACE_SETTING_TAB_VISIBLE: 'IS_MARKETPLACE_SETTING_TAB_VISIBLE' as const,
|
||||
IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED: 'IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED' as const,
|
||||
IS_PUBLIC_DOMAIN_ENABLED: 'IS_PUBLIC_DOMAIN_ENABLED' as const,
|
||||
IS_EMAILING_DOMAIN_ENABLED: 'IS_EMAILING_DOMAIN_ENABLED' as const,
|
||||
IS_JUNCTION_RELATIONS_ENABLED: 'IS_JUNCTION_RELATIONS_ENABLED' as const,
|
||||
IS_DRAFT_EMAIL_ENABLED: 'IS_DRAFT_EMAIL_ENABLED' as const,
|
||||
IS_CONNECTED_ACCOUNT_MIGRATED: 'IS_CONNECTED_ACCOUNT_MIGRATED' as const,
|
||||
IS_USAGE_ANALYTICS_ENABLED: 'IS_USAGE_ANALYTICS_ENABLED' as const,
|
||||
IS_RICH_TEXT_V1_MIGRATED: 'IS_RICH_TEXT_V1_MIGRATED' as const,
|
||||
IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED: 'IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED' as const,
|
||||
@@ -9236,19 +9329,11 @@ export const enumEngineComponentKey = {
|
||||
SEE_DELETED_RECORDS: 'SEE_DELETED_RECORDS' as const,
|
||||
CREATE_NEW_VIEW: 'CREATE_NEW_VIEW' as const,
|
||||
HIDE_DELETED_RECORDS: 'HIDE_DELETED_RECORDS' as const,
|
||||
GO_TO_PEOPLE: 'GO_TO_PEOPLE' as const,
|
||||
GO_TO_COMPANIES: 'GO_TO_COMPANIES' as const,
|
||||
GO_TO_DASHBOARDS: 'GO_TO_DASHBOARDS' as const,
|
||||
GO_TO_OPPORTUNITIES: 'GO_TO_OPPORTUNITIES' as const,
|
||||
GO_TO_SETTINGS: 'GO_TO_SETTINGS' as const,
|
||||
GO_TO_TASKS: 'GO_TO_TASKS' as const,
|
||||
GO_TO_NOTES: 'GO_TO_NOTES' as const,
|
||||
EDIT_RECORD_PAGE_LAYOUT: 'EDIT_RECORD_PAGE_LAYOUT' as const,
|
||||
EDIT_DASHBOARD_LAYOUT: 'EDIT_DASHBOARD_LAYOUT' as const,
|
||||
SAVE_DASHBOARD_LAYOUT: 'SAVE_DASHBOARD_LAYOUT' as const,
|
||||
CANCEL_DASHBOARD_LAYOUT: 'CANCEL_DASHBOARD_LAYOUT' as const,
|
||||
DUPLICATE_DASHBOARD: 'DUPLICATE_DASHBOARD' as const,
|
||||
GO_TO_WORKFLOWS: 'GO_TO_WORKFLOWS' as const,
|
||||
ACTIVATE_WORKFLOW: 'ACTIVATE_WORKFLOW' as const,
|
||||
DEACTIVATE_WORKFLOW: 'DEACTIVATE_WORKFLOW' as const,
|
||||
DISCARD_DRAFT_WORKFLOW: 'DISCARD_DRAFT_WORKFLOW' as const,
|
||||
@@ -9259,7 +9344,6 @@ export const enumEngineComponentKey = {
|
||||
ADD_NODE_WORKFLOW: 'ADD_NODE_WORKFLOW' as const,
|
||||
TIDY_UP_WORKFLOW: 'TIDY_UP_WORKFLOW' as const,
|
||||
DUPLICATE_WORKFLOW: 'DUPLICATE_WORKFLOW' as const,
|
||||
GO_TO_RUNS: 'GO_TO_RUNS' as const,
|
||||
SEE_VERSION_WORKFLOW_RUN: 'SEE_VERSION_WORKFLOW_RUN' as const,
|
||||
SEE_WORKFLOW_WORKFLOW_RUN: 'SEE_WORKFLOW_WORKFLOW_RUN' as const,
|
||||
STOP_WORKFLOW_RUN: 'STOP_WORKFLOW_RUN' as const,
|
||||
@@ -9271,9 +9355,20 @@ export const enumEngineComponentKey = {
|
||||
SEARCH_RECORDS_FALLBACK: 'SEARCH_RECORDS_FALLBACK' as const,
|
||||
ASK_AI: 'ASK_AI' as const,
|
||||
VIEW_PREVIOUS_AI_CHATS: 'VIEW_PREVIOUS_AI_CHATS' as const,
|
||||
NAVIGATION: 'NAVIGATION' as const,
|
||||
TRIGGER_WORKFLOW_VERSION: 'TRIGGER_WORKFLOW_VERSION' as const,
|
||||
FRONT_COMPONENT_RENDERER: 'FRONT_COMPONENT_RENDERER' as const,
|
||||
REPLY_TO_EMAIL_THREAD: 'REPLY_TO_EMAIL_THREAD' as const,
|
||||
COMPOSE_EMAIL: 'COMPOSE_EMAIL' as const,
|
||||
GO_TO_PEOPLE: 'GO_TO_PEOPLE' as const,
|
||||
GO_TO_COMPANIES: 'GO_TO_COMPANIES' as const,
|
||||
GO_TO_DASHBOARDS: 'GO_TO_DASHBOARDS' as const,
|
||||
GO_TO_OPPORTUNITIES: 'GO_TO_OPPORTUNITIES' as const,
|
||||
GO_TO_SETTINGS: 'GO_TO_SETTINGS' as const,
|
||||
GO_TO_TASKS: 'GO_TO_TASKS' as const,
|
||||
GO_TO_NOTES: 'GO_TO_NOTES' as const,
|
||||
GO_TO_WORKFLOWS: 'GO_TO_WORKFLOWS' as const,
|
||||
GO_TO_RUNS: 'GO_TO_RUNS' as const,
|
||||
DELETE_SINGLE_RECORD: 'DELETE_SINGLE_RECORD' as const,
|
||||
DELETE_MULTIPLE_RECORDS: 'DELETE_MULTIPLE_RECORDS' as const,
|
||||
RESTORE_SINGLE_RECORD: 'RESTORE_SINGLE_RECORD' as const,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
-17
@@ -50,23 +50,6 @@ npx nx run twenty-server:database:reset
|
||||
npx nx run twenty-server:typeorm migration:generate src/database/typeorm/core/migrations/nameOfYourMigration -d src/database/typeorm/core/core.datasource.ts
|
||||
```
|
||||
|
||||
#### For Workspace objects
|
||||
|
||||
There are no migrations files, migration are generated automatically for each workspace,
|
||||
stored in the database, and applied with this command
|
||||
|
||||
```bash
|
||||
npx nx run twenty-server:command workspace:sync-metadata -f
|
||||
```
|
||||
|
||||
<Warning>
|
||||
|
||||
This will drop the database and re-run the migrations and seed.
|
||||
|
||||
Make sure to back up any data you want to keep before running this command.
|
||||
|
||||
</Warning>
|
||||
|
||||
## Tech Stack
|
||||
|
||||
Twenty primarily uses NestJS for the backend.
|
||||
|
||||
@@ -756,7 +756,7 @@ export default defineFrontComponent({
|
||||
});
|
||||
```
|
||||
|
||||
After syncing with `yarn twenty dev`, the quick action appears in the top-right corner of the page:
|
||||
After syncing with `yarn twenty dev` (or running a one-shot `yarn twenty dev --once`), the quick action appears in the top-right corner of the page:
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/quick-action.png" alt="Quick action button in the top-right corner" />
|
||||
@@ -1402,7 +1402,7 @@ export default defineFrontComponent({
|
||||
|
||||
### How bundling works
|
||||
|
||||
The build step (`yarn twenty dev` or `yarn twenty build`) uses esbuild to produce a single self-contained file per logic function and per front component. All imported packages are inlined into the bundle.
|
||||
The build step uses esbuild to produce a single self-contained file per logic function and per front component. All imported packages are inlined into the bundle.
|
||||
|
||||
**Logic functions** run in a Node.js environment. Node built-in modules (`fs`, `path`, `crypto`, `http`, etc.) are available and do not need to be installed.
|
||||
|
||||
|
||||
@@ -98,6 +98,21 @@ Dev mode is only available on Twenty instances running in development (`NODE_ENV
|
||||
<img src="/images/docs/developers/extends/apps/dev.jpg" alt="Dev mode terminal output" />
|
||||
</div>
|
||||
|
||||
#### One-shot sync with `yarn twenty dev --once`
|
||||
|
||||
If you do not want a watcher running in the background (for example in a CI pipeline, a git hook, or a scripted workflow), pass the `--once` flag. It runs the same pipeline as `yarn twenty dev` — build manifest, bundle files, upload, sync, regenerate the typed API client — but **exits as soon as the sync completes**:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty dev --once
|
||||
```
|
||||
|
||||
| Command | Behavior | When to use |
|
||||
|---------|----------|-------------|
|
||||
| `yarn twenty dev` | Watches your source files and re-syncs on every change. Keeps running until you stop it. | Interactive local development — you want the live status panel and instant feedback loop. |
|
||||
| `yarn twenty dev --once` | Performs a single build + sync, then exits with code `0` on success or `1` on failure. | Scripts, CI, pre-commit hooks, AI agents, and any non-interactive workflow. |
|
||||
|
||||
Both modes require a Twenty server running in development mode and an authenticated remote — the same prerequisites apply.
|
||||
|
||||
### See your app in Twenty
|
||||
|
||||
Open [http://localhost:2020/settings/applications#developer](http://localhost:2020/settings/applications#developer) in your browser. Navigate to **Settings > Apps** and select the **Developer** tab. You should see your app listed under **Your Apps**:
|
||||
|
||||
@@ -52,7 +52,11 @@ yarn twenty deploy
|
||||
|
||||
### Sharing a deployed app
|
||||
|
||||
Tarball apps are not listed in the public marketplace, so other workspaces on the same server won't discover them by browsing. To share a deployed app:
|
||||
<Warning>
|
||||
Sharing private (tarball) apps across workspaces is an **Enterprise** feature. The **Distribution** tab will show an upgrade prompt instead of the share controls until your workspace has a valid Enterprise key. See [Settings > Admin Panel > Enterprise](/settings/admin-panel#enterprise) to activate it.
|
||||
</Warning>
|
||||
|
||||
Tarball apps are not listed in the public marketplace, so other workspaces on the same server won't discover them by browsing. Once your workspace is on the Enterprise plan, you can share a deployed app like this:
|
||||
|
||||
1. Go to **Settings > Applications > Registrations** and open your app
|
||||
2. In the **Distribution** tab, click **Copy share link**
|
||||
@@ -60,10 +64,6 @@ Tarball apps are not listed in the public marketplace, so other workspaces on th
|
||||
|
||||
The share link uses the server's base URL (without any workspace subdomain) so it works for any workspace on the server.
|
||||
|
||||
<Warning>
|
||||
Sharing private apps is an Enterprise feature. Go to [Settings > Admin Panel > Enterprise](/settings/admin-panel#enterprise) to enable it.
|
||||
</Warning>
|
||||
|
||||
### Version management
|
||||
|
||||
To release an update:
|
||||
|
||||
-17
@@ -50,23 +50,6 @@ npx nx run twenty-server:database:reset
|
||||
npx nx run twenty-server:typeorm migration:generate src/database/typeorm/core/migrations/nameOfYourMigration -d src/database/typeorm/core/core.datasource.ts
|
||||
```
|
||||
|
||||
#### لكائنات مساحة العمل
|
||||
|
||||
لا توجد ملفات هجيرات، يتم إنشاء الهجيرات تلقائيًا لكل مساحة عمل،
|
||||
مخزنة في قاعدة البيانات، ويتم تطبيقها مع هذا الأمر
|
||||
|
||||
```bash
|
||||
npx nx run twenty-server:command workspace:sync-metadata -f
|
||||
```
|
||||
|
||||
<Warning>
|
||||
|
||||
سيؤدي هذا إلى إسقاط قاعدة البيانات وإعادة تشغيل الهجرات والبذور.
|
||||
|
||||
تأكد من عمل نسخة احتياطية لأي بيانات تريد الاحتفاظ بها قبل تشغيل هذا الأمر.
|
||||
|
||||
</Warning>
|
||||
|
||||
## "التقنية المستخدمة"
|
||||
|
||||
تستخدم Twenty بشكل أساسي NestJS للواجهة الخلفية.
|
||||
|
||||
@@ -755,7 +755,7 @@ export default defineFrontComponent({
|
||||
});
|
||||
```
|
||||
|
||||
بعد المزامنة باستخدام `yarn twenty dev`، يظهر الإجراء السريع في الزاوية العلوية اليمنى من الصفحة:
|
||||
بعد المزامنة باستخدام `yarn twenty dev` (أو تشغيل الأمر لمرة واحدة `yarn twenty dev --once`)، يظهر الإجراء السريع في الزاوية العلوية اليمنى من الصفحة:
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/quick-action.png" alt="زر إجراء سريع في الزاوية العلوية اليمنى" />
|
||||
@@ -1401,7 +1401,7 @@ export default defineFrontComponent({
|
||||
|
||||
### كيف يعمل التجميع
|
||||
|
||||
تستخدم خطوة البناء (`yarn twenty dev` أو `yarn twenty build`) أداة esbuild لإنتاج ملف واحد مستقل لكل دالة منطقية وكل مكوّن أمامي. تُضمَّن جميع الحزم المستوردة داخل الحزمة.
|
||||
تستخدم خطوة البناء أداة esbuild لإنتاج ملف واحد مستقل لكل دالة منطقية ولكل مكوّن أمامي. تُضمَّن جميع الحزم المستوردة داخل الحزمة.
|
||||
|
||||
**الدوال المنطقية** تعمل في بيئة Node.js. الوحدات المدمجة في Node (`fs` و`path` و`crypto` و`http` وغيرها) متاحة ولا تحتاج إلى تثبيت.
|
||||
|
||||
|
||||
@@ -98,6 +98,21 @@ yarn twenty dev --verbose
|
||||
<img src="/images/docs/developers/extends/apps/dev.jpg" alt="مخرجات الطرفية في وضع التطوير" />
|
||||
</div>
|
||||
|
||||
#### مزامنة لمرة واحدة باستخدام `yarn twenty dev --once`
|
||||
|
||||
إذا كنت لا تريد تشغيل مراقب في الخلفية (مثلًا في خط أنابيب CI، أو خطاف Git، أو سير عمل مُؤتمت عبر سكربت)، فمرِّر الخيار `--once`. يُشغِّل خط الأنابيب نفسه مثل `yarn twenty dev` — إنشاء بيان البناء، تجميع الملفات، الرفع، المزامنة، إعادة توليد عميل API مضبوط الأنواع — ولكنه **ينهي التنفيذ فور اكتمال المزامنة**:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty dev --once
|
||||
```
|
||||
|
||||
| أمر | السلوك | متى يُستخدم |
|
||||
| ------------------------ | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
|
||||
| `yarn twenty dev` | يراقب ملفات المصدر ويعيد المزامنة عند كل تغيير. يستمر بالتشغيل حتى توقفه. | تطوير محلي تفاعلي — تريد لوحة حالة مباشرة وحلقة تغذية راجعة فورية. |
|
||||
| `yarn twenty dev --once` | يجري عملية بناء واحدة + مزامنة واحدة، ثم ينهي التنفيذ برمز `0` عند النجاح أو `1` عند الفشل. | البرامج النصية، وCI، وخطافات ما قبل الالتزام، ووكلاء الذكاء الاصطناعي، وأي سير عمل غير تفاعلي. |
|
||||
|
||||
كلا الوضعين يتطلبان خادم Twenty يعمل في وضع التطوير وجهة بعيدة موثَّقة — تنطبق المتطلبات المسبقة نفسها.
|
||||
|
||||
### اعرض تطبيقك في Twenty
|
||||
|
||||
افتح [http://localhost:2020/settings/applications#developer](http://localhost:2020/settings/applications#developer) في متصفحك. انتقل إلى **Settings > Apps** واختر علامة التبويب **Developer**. يُفترض أن ترى تطبيقك مُدرجًا تحت **Your Apps**:
|
||||
|
||||
@@ -52,7 +52,11 @@ yarn twenty deploy
|
||||
|
||||
### مشاركة تطبيق منشور
|
||||
|
||||
تطبيقات tarball لا تُدرَج في السوق العامة، لذا لن تكتشفها مساحات العمل الأخرى على الخادم نفسه عبر الاستعراض. لمشاركة تطبيق منشور:
|
||||
<Warning>
|
||||
تُعد مشاركة التطبيقات الخاصة (tarball) عبر مساحات العمل ميزة ضمن **Enterprise**. ستعرض علامة التبويب **Distribution** مطالبة بالترقية بدلًا من عناصر التحكم في المشاركة حتى تحتوي مساحة العمل لديك على مفتاح Enterprise صالح. اطلع على [الإعدادات > لوحة الإدارة > Enterprise](/settings/admin-panel#enterprise) لتنشيطه.
|
||||
</Warning>
|
||||
|
||||
تطبيقات tarball لا تُدرَج في السوق العامة، لذا لن تكتشفها مساحات العمل الأخرى على الخادم نفسه عبر الاستعراض. بمجرد أن تصبح مساحة العمل لديك ضمن خطة Enterprise، يمكنك مشاركة تطبيق تم نشره كما يلي:
|
||||
|
||||
1. اذهب إلى **الإعدادات > التطبيقات > التسجيلات** وافتح تطبيقك
|
||||
2. في علامة التبويب **التوزيع**، انقر **نسخ رابط المشاركة**
|
||||
@@ -60,10 +64,6 @@ yarn twenty deploy
|
||||
|
||||
يستخدم رابط المشاركة عنوان URL الأساسي للخادم (من دون أي نطاق فرعي لمساحة عمل)، لذا يعمل مع أي مساحة عمل على الخادم.
|
||||
|
||||
<Warning>
|
||||
مشاركة التطبيقات الخاصة هي ميزة ضمن باقة Enterprise. اذهب إلى [الإعدادات > لوحة الإدارة > Enterprise](/settings/admin-panel#enterprise) لتمكينها.
|
||||
</Warning>
|
||||
|
||||
### إدارة الإصدارات
|
||||
|
||||
لطرح تحديث:
|
||||
|
||||
@@ -140,12 +140,12 @@ description: دليل شامل لاستكشاف أخطاء استيراد CSV و
|
||||
#### تاريخ
|
||||
|
||||
**المشكلة:** تنسيق تاريخ غير معروف
|
||||
**الحل:** استخدم تنسيقًا متّسقًا في جميع أنحاء الملف
|
||||
**الحل:** استخدم تنسيق `YYYY-MM-DD` بشكل متّسق في جميع أنحاء الملف
|
||||
|
||||
```
|
||||
✓ 2024-03-15 (YYYY-MM-DD - recommended)
|
||||
✓ 03/15/2024 (MM/DD/YYYY)
|
||||
✓ 15/03/2024 (DD/MM/YYYY)
|
||||
✓ 2024-03-15 (YYYY-MM-DD)
|
||||
❌ 03/15/2024 (MM/DD/YYYY)
|
||||
❌ 15/03/2024 (DD/MM/YYYY)
|
||||
```
|
||||
|
||||
#### هاتف
|
||||
|
||||
@@ -103,8 +103,6 @@ description: دليل كامل خطوة بخطوة لتنسيق بياناتك
|
||||
استخدم تنسيقًا موحدًا في كامل ملفك:
|
||||
|
||||
* `YYYY-MM-DD` (مُوصى به): `2024-03-15`
|
||||
* `MM/DD/YYYY`: `03/15/2024`
|
||||
* `DD/MM/YYYY`: `15/03/2024`
|
||||
* ISO 8601: `2024-03-15T10:30:00Z`
|
||||
|
||||
### حقول الأرقام
|
||||
|
||||
-16
@@ -50,22 +50,6 @@ npx nx run twenty-server:database:reset
|
||||
npx nx run twenty-server:typeorm migration:generate src/database/typeorm/core/migrations/nameOfYourMigration -d src/database/typeorm/core/core.datasource.ts
|
||||
```
|
||||
|
||||
#### Pro objekty Pracovní plochy
|
||||
|
||||
Nejsou žádné soubory migrací, migrace jsou generovány automaticky pro každou pracovní plochu, uloženy v databázi a aplikovány tímto příkazem
|
||||
|
||||
```bash
|
||||
npx nx run twenty-server:command workspace:sync-metadata -f
|
||||
```
|
||||
|
||||
<Warning>
|
||||
|
||||
Tímto se databáze smaže a znovu se spustí migrace a seedování.
|
||||
|
||||
Před spuštěním tohoto příkazu si nezapomeňte zálohovat všechna data, která chcete zachovat.
|
||||
|
||||
</Warning>
|
||||
|
||||
## Technologický stack
|
||||
|
||||
Twenty primárně používá NestJS pro backend.
|
||||
|
||||
@@ -756,7 +756,7 @@ export default defineFrontComponent({
|
||||
});
|
||||
```
|
||||
|
||||
Po synchronizaci pomocí `yarn twenty dev` se rychlá akce zobrazí v pravém horním rohu stránky:
|
||||
Po synchronizaci pomocí `yarn twenty dev` (nebo po jednorázovém spuštění `yarn twenty dev --once`) se rychlá akce zobrazí v pravém horním rohu stránky:
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/quick-action.png" alt="Tlačítko rychlé akce v pravém horním rohu" />
|
||||
@@ -1402,7 +1402,7 @@ export default defineFrontComponent({
|
||||
|
||||
### Jak funguje bundlování
|
||||
|
||||
Krok sestavení (`yarn twenty dev` nebo `yarn twenty build`) používá esbuild k vytvoření jediného samostatného souboru pro každou logickou funkci a každou frontendovou komponentu. Všechny importované balíčky jsou vloženy přímo do bundlu.
|
||||
Krok sestavení používá esbuild k vytvoření jediného samostatného souboru pro každou logickou funkci a každou frontendovou komponentu. Všechny importované balíčky jsou vloženy přímo do bundlu.
|
||||
|
||||
**Logické funkce** běží v prostředí Node.js. Vestavěné moduly Node (`fs`, `path`, `crypto`, `http` atd.) jsou k dispozici a není je třeba instalovat.
|
||||
|
||||
|
||||
@@ -98,6 +98,21 @@ Vývojový režim je k dispozici pouze na instancích Twenty běžících v rež
|
||||
<img src="/images/docs/developers/extends/apps/dev.jpg" alt="Výstup terminálu ve vývojovém režimu" />
|
||||
</div>
|
||||
|
||||
#### Jednorázová synchronizace pomocí `yarn twenty dev --once`
|
||||
|
||||
Pokud nechcete, aby na pozadí běžel watcher (například v CI pipeline, git hooku nebo skriptovaném workflow), použijte příznak `--once`. Spouští stejnou pipeline jako `yarn twenty dev` — sestaví manifest, zabalí soubory, nahraje, synchronizuje, znovu vygeneruje typovaného klienta API — ale **ukončí se, jakmile se synchronizace dokončí**:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty dev --once
|
||||
```
|
||||
|
||||
| Příkaz | Chování | Kdy použít |
|
||||
| ------------------------ | -------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
|
||||
| `yarn twenty dev` | Sleduje vaše zdrojové soubory a při každé změně znovu spustí synchronizaci. Zůstává spuštěný, dokud jej nezastavíte. | Interaktivní lokální vývoj — chcete živý panel stavu a okamžitou zpětnovazebnou smyčku. |
|
||||
| `yarn twenty dev --once` | Provede jedno sestavení + synchronizaci, poté ukončí běh s kódem `0` při úspěchu nebo `1` při neúspěchu. | Skripty, CI, pre-commit hooky, AI agenti a jakýkoli neinteraktivní pracovní postup. |
|
||||
|
||||
Oba režimy vyžadují server Twenty běžící v režimu vývoje a autentizovaný remote — platí stejné požadavky.
|
||||
|
||||
### Zobrazte svou aplikaci v Twenty
|
||||
|
||||
Otevřete ve svém prohlížeči [http://localhost:2020/settings/applications#developer](http://localhost:2020/settings/applications#developer). Přejděte do **Settings > Apps** a vyberte kartu **Developer**. Vaše aplikace by měla být uvedena v části **Your Apps**:
|
||||
|
||||
@@ -52,7 +52,11 @@ yarn twenty deploy
|
||||
|
||||
### Sdílení nasazené aplikace
|
||||
|
||||
Aplikace ve formě tarball nejsou uvedeny ve veřejném tržišti, takže je ostatní pracovní prostory na tomtéž serveru procházením neobjeví. Chcete-li sdílet nasazenou aplikaci:
|
||||
<Warning>
|
||||
Sdílení soukromých (tarball) aplikací napříč pracovními prostory je funkcí **Enterprise**. Karta **Distribution** bude místo ovládacích prvků sdílení zobrazovat výzvu k upgradu, dokud váš pracovní prostor nebude mít platný klíč Enterprise. Přejděte do [Nastavení > Admin Panel > Enterprise](/settings/admin-panel#enterprise) a aktivujte ji.
|
||||
</Warning>
|
||||
|
||||
Aplikace ve formě tarball nejsou uvedeny ve veřejném tržišti, takže je ostatní pracovní prostory na tomtéž serveru procházením neobjeví. Jakmile je váš pracovní prostor na tarifu Enterprise, můžete sdílet nasazenou aplikaci takto:
|
||||
|
||||
1. Přejděte do **Nastavení > Aplikace > Registrace** a otevřete svou aplikaci
|
||||
2. Na kartě **Distribuce** klikněte na **Zkopírovat odkaz ke sdílení**
|
||||
@@ -60,10 +64,6 @@ Aplikace ve formě tarball nejsou uvedeny ve veřejném tržišti, takže je ost
|
||||
|
||||
Odkaz ke sdílení používá základní adresu URL serveru (bez jakékoli subdomény pracovního prostoru), takže funguje pro libovolný pracovní prostor na serveru.
|
||||
|
||||
<Warning>
|
||||
Sdílení soukromých aplikací je funkce Enterprise. Přejděte do [Nastavení > Admin Panel > Enterprise](/settings/admin-panel#enterprise) a povolte ji.
|
||||
</Warning>
|
||||
|
||||
### Správa verzí
|
||||
|
||||
Chcete-li vydat aktualizaci:
|
||||
|
||||
@@ -140,12 +140,12 @@ Data neodpovídají očekávanému formátu pro tento typ pole.
|
||||
#### Datum
|
||||
|
||||
**Problém:** Nerozpoznaný formát data
|
||||
**Řešení:** Používejte jednotný formát v celém souboru
|
||||
**Řešení:** Používejte formát `YYYY-MM-DD` jednotně v celém souboru
|
||||
|
||||
```
|
||||
✓ 2024-03-15 (YYYY-MM-DD - recommended)
|
||||
✓ 03/15/2024 (MM/DD/YYYY)
|
||||
✓ 15/03/2024 (DD/MM/YYYY)
|
||||
✓ 2024-03-15 (YYYY-MM-DD)
|
||||
❌ 03/15/2024 (MM/DD/YYYY)
|
||||
❌ 15/03/2024 (DD/MM/YYYY)
|
||||
```
|
||||
|
||||
#### Telefon
|
||||
|
||||
@@ -103,8 +103,6 @@ Adresa je **vnořené pole** s více sloupci (některé mohou zůstat prázdné)
|
||||
Používejte jednotný formát v celém souboru:
|
||||
|
||||
* `YYYY-MM-DD` (doporučeno): `2024-03-15`
|
||||
* `MM/DD/YYYY`: `03/15/2024`
|
||||
* `DD/MM/YYYY`: `15/03/2024`
|
||||
* ISO 8601: `2024-03-15T10:30:00Z`
|
||||
|
||||
### Číselná pole
|
||||
|
||||
-17
@@ -50,23 +50,6 @@ npx nx run twenty-server:database:reset
|
||||
npx nx run twenty-server:typeorm migration:generate src/database/typeorm/core/migrations/nameOfYourMigration -d src/database/typeorm/core/core.datasource.ts
|
||||
```
|
||||
|
||||
#### Für Arbeitsbereichsobjekte
|
||||
|
||||
Es gibt keine Migrationsdateien, Migrationen werden automatisch für jeden Arbeitsbereich generiert,
|
||||
in der Datenbank gespeichert und mit diesem Befehl angewendet
|
||||
|
||||
```bash
|
||||
npx nx run twenty-server:command workspace:sync-metadata -f
|
||||
```
|
||||
|
||||
<Warning>
|
||||
|
||||
Dadurch wird die Datenbank gelöscht und die Migrationen sowie das Seeding erneut ausgeführt.
|
||||
|
||||
Stellen Sie sicher, dass Sie alle Daten sichern, die Sie aufbewahren möchten, bevor Sie diesen Befehl ausführen.
|
||||
|
||||
</Warning>
|
||||
|
||||
## Technologie-Stack
|
||||
|
||||
Twenty verwendet in erster Linie NestJS für das Backend.
|
||||
|
||||
@@ -755,7 +755,7 @@ export default defineFrontComponent({
|
||||
});
|
||||
```
|
||||
|
||||
Nach dem Synchronisieren mit `yarn twenty dev` erscheint die Schnellaktion oben rechts auf der Seite:
|
||||
Nach dem Synchronisieren mit `yarn twenty dev` (oder durch einmaliges Ausführen von `yarn twenty dev --once`) erscheint die Schnellaktion oben rechts auf der Seite:
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/quick-action.png" alt="Schnellaktionsschaltfläche oben rechts" />
|
||||
@@ -1401,7 +1401,7 @@ export default defineFrontComponent({
|
||||
|
||||
### Wie das Bundling funktioniert
|
||||
|
||||
Der Build-Schritt (`yarn twenty dev` oder `yarn twenty build`) verwendet esbuild, um pro Logikfunktion und pro Frontend-Komponente eine einzelne, in sich geschlossene Datei zu erzeugen. Alle importierten Pakete werden in das Bundle eingebettet.
|
||||
Der Build-Schritt verwendet esbuild, um pro Logikfunktion und pro Frontend-Komponente eine einzelne, in sich geschlossene Datei zu erzeugen. Alle importierten Pakete werden in das Bundle eingebettet.
|
||||
|
||||
**Logikfunktionen** laufen in einer Node.js-Umgebung. Eingebaute Node.js-Module (`fs`, `path`, `crypto`, `http` usw.) stehen zur Verfügung und müssen nicht installiert werden.
|
||||
|
||||
|
||||
@@ -98,6 +98,21 @@ Der Dev-Modus ist nur auf Twenty-Instanzen verfügbar, die im Entwicklungsmodus
|
||||
<img src="/images/docs/developers/extends/apps/dev.jpg" alt="Terminalausgabe im Dev-Modus" />
|
||||
</div>
|
||||
|
||||
#### Einmalige Synchronisierung mit `yarn twenty dev --once`
|
||||
|
||||
Wenn Sie keinen Watcher im Hintergrund ausführen lassen möchten (zum Beispiel in einer CI-Pipeline, einem Git-Hook oder einem skriptgesteuerten Workflow), geben Sie das Flag `--once` an. Es führt dieselbe Pipeline aus wie `yarn twenty dev` — Build-Manifest erstellen, Dateien bündeln, hochladen, synchronisieren, den typisierten API-Client neu generieren — beendet sich jedoch, **sobald die Synchronisierung abgeschlossen ist**:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty dev --once
|
||||
```
|
||||
|
||||
| Befehl | Verhalten | Wann verwenden |
|
||||
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
|
||||
| `yarn twenty dev` | Überwacht Ihre Quelldateien und synchronisiert bei jeder Änderung erneut. Läuft weiter, bis Sie es stoppen. | Interaktive lokale Entwicklung — Sie möchten das Live-Status-Panel und eine sofortige Feedback-Schleife. |
|
||||
| `yarn twenty dev --once` | Führt einen einzelnen Build + Sync aus und beendet sich anschließend mit Code `0` bei Erfolg oder `1` bei einem Fehler. | Skripte, CI, Pre-Commit-Hooks, KI-Agenten und jeder nicht-interaktive Workflow. |
|
||||
|
||||
Beide Modi erfordern einen Twenty-Server, der im Entwicklungsmodus läuft, und ein authentifiziertes Remote — es gelten dieselben Voraussetzungen.
|
||||
|
||||
### Sehen Sie sich Ihre App in Twenty an
|
||||
|
||||
Öffnen Sie [http://localhost:2020/settings/applications#developer](http://localhost:2020/settings/applications#developer) in Ihrem Browser. Navigieren Sie zu **Settings > Apps** und wählen Sie die Registerkarte **Developer**. Unter **Your Apps** sollte Ihre App aufgeführt sein:
|
||||
|
||||
@@ -52,7 +52,11 @@ yarn twenty deploy
|
||||
|
||||
### Eine bereitgestellte App freigeben
|
||||
|
||||
Tarball-Apps werden nicht im öffentlichen Marktplatz gelistet, daher entdecken andere Arbeitsbereiche auf demselben Server sie nicht durch Stöbern. So geben Sie eine bereitgestellte App frei:
|
||||
<Warning>
|
||||
Das Teilen privater (Tarball-)Apps über Arbeitsbereiche hinweg ist eine **Enterprise**-Funktion. Die Registerkarte **Distribution** zeigt anstelle der Freigabeoptionen eine Aufforderung zum Upgrade an, bis Ihr Arbeitsbereich über einen gültigen Enterprise-Schlüssel verfügt. Gehen Sie zu [Einstellungen > Admin-Panel > Enterprise](/settings/admin-panel#enterprise), um es zu aktivieren.
|
||||
</Warning>
|
||||
|
||||
Tarball-Apps werden nicht im öffentlichen Marktplatz gelistet, daher entdecken andere Arbeitsbereiche auf demselben Server sie nicht durch Stöbern. Sobald sich Ihr Arbeitsbereich im Enterprise-Plan befindet, können Sie eine bereitgestellte App wie folgt freigeben:
|
||||
|
||||
1. Gehen Sie zu **Einstellungen > Anwendungen > Registrierungen** und öffnen Sie Ihre App
|
||||
2. Klicken Sie im Tab **Distribution** auf **Freigabelink kopieren**
|
||||
@@ -60,10 +64,6 @@ Tarball-Apps werden nicht im öffentlichen Marktplatz gelistet, daher entdecken
|
||||
|
||||
Der Freigabelink verwendet die Basis-URL des Servers (ohne Workspace-Subdomain), sodass er für jeden Arbeitsbereich auf dem Server funktioniert.
|
||||
|
||||
<Warning>
|
||||
Das Teilen privater Apps ist eine Enterprise-Funktion. Gehen Sie zu [Einstellungen > Admin-Panel > Enterprise](/settings/admin-panel#enterprise), um es zu aktivieren.
|
||||
</Warning>
|
||||
|
||||
### Versionsverwaltung
|
||||
|
||||
So veröffentlichen Sie ein Update:
|
||||
|
||||
@@ -140,12 +140,12 @@ Die Daten entsprechen nicht dem erwarteten Format für diesen Feldtyp.
|
||||
#### Datum
|
||||
|
||||
**Problem:** Nicht erkanntes Datumsformat
|
||||
**Lösung:** Verwenden Sie in der gesamten Datei ein einheitliches Format
|
||||
**Lösung:** Verwenden Sie in der gesamten Datei durchgängig das Format `YYYY-MM-DD`
|
||||
|
||||
```
|
||||
✓ 2024-03-15 (YYYY-MM-DD - empfohlen)
|
||||
✓ 03/15/2024 (MM/DD/YYYY)
|
||||
✓ 15/03/2024 (DD/MM/YYYY)
|
||||
✓ 2024-03-15 (YYYY-MM-DD)
|
||||
❌ 03/15/2024 (MM/DD/YYYY)
|
||||
❌ 15/03/2024 (DD/MM/YYYY)
|
||||
```
|
||||
|
||||
#### Telefon
|
||||
|
||||
@@ -103,8 +103,6 @@ Adresse ist ein **verschachteltes Feld** mit mehreren Spalten (einige können le
|
||||
Verwenden Sie in Ihrer Datei ein einheitliches Format:
|
||||
|
||||
* `YYYY-MM-DD` (empfohlen): `2024-03-15`
|
||||
* `MM/DD/YYYY`: `03/15/2024`
|
||||
* `DD/MM/YYYY`: `15/03/2024`
|
||||
* ISO 8601: `2024-03-15T10:30:00Z`
|
||||
|
||||
### Zahlenfelder
|
||||
|
||||
-14
@@ -50,20 +50,6 @@ npx nx run twenty-server:database:reset
|
||||
npx nx run twenty-server:typeorm migration:generate src/database/typeorm/core/migrations/nameOfYourMigration -d src/database/typeorm/core/core.datasource.ts
|
||||
```
|
||||
|
||||
#### Para objetos de Workspace
|
||||
|
||||
No hay archivos de migraciones, las migraciones se generan automáticamente para cada espacio de trabajo, se almacenan en la base de datos y se aplican con este comando
|
||||
|
||||
```bash
|
||||
npx nx run twenty-server:command workspace:sync-metadata -f
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Esto eliminará la base de datos y volverá a ejecutar las migraciones y semillas.
|
||||
|
||||
Asegúrate de respaldar cualquier dato que desees conservar antes de ejecutar este comando.
|
||||
</Warning>
|
||||
|
||||
## Stack Tecnológico
|
||||
|
||||
Twenty utiliza principalmente NestJS para el backend.
|
||||
|
||||
@@ -372,10 +372,8 @@ Ejecución de los siguientes comandos:
|
||||
|
||||
```
|
||||
yarn database:migrate:prod
|
||||
yarn command:prod workspace:sync-metadata -f
|
||||
yarn command:prod upgrade-0.22
|
||||
```
|
||||
|
||||
El comando `yarn database:migrate:prod` aplicará las migraciones a la base de datos.
|
||||
El comando `yarn command:prod workspace:sync-metadata -f` sincronizará la definición de objetos estándar a las tablas de metadatos y aplicará las migraciones requeridas a los espacios de trabajo existentes.
|
||||
El comando `yarn command:prod upgrade-0.22` aplicará transformaciones de datos específicas para adaptarse a las nuevas opciones predeterminadas de instrumentación de solicitud de objetos.
|
||||
|
||||
-21
@@ -43,27 +43,6 @@ npx nx run twenty-server:database:reset
|
||||
```
|
||||
|
||||
### Migrations
|
||||
|
||||
#### Pour les objets dans les schémas Core/Metadata (TypeORM)
|
||||
|
||||
```bash
|
||||
npx nx run twenty-server:typeorm migration:generate src/database/typeorm/core/migrations/nameOfYourMigration -d src/database/typeorm/core/core.datasource.ts
|
||||
```
|
||||
|
||||
#### Pour les objets de l'Espace de travail
|
||||
|
||||
Il n'y a pas de fichiers de migrations, les migrations sont générées automatiquement pour chaque espace de travail, stockées dans la base de données et appliquées avec cette commande
|
||||
|
||||
```bash
|
||||
npx nx run twenty-server:command workspace:sync-metadata -f
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Cela supprimera la base de données et réexécutera les migrations et l'initialisation des données.
|
||||
|
||||
Assurez-vous de sauvegarder toutes les données que vous souhaitez conserver avant d'exécuter cette commande.
|
||||
</Warning>
|
||||
|
||||
## Écosystème Tech
|
||||
|
||||
Twenty utilise principalement NestJS pour le backend.
|
||||
|
||||
@@ -372,10 +372,8 @@ Exécutez les commandes suivantes :
|
||||
|
||||
```
|
||||
yarn database:migrate:prod
|
||||
yarn command:prod workspace:sync-metadata -f
|
||||
yarn command:prod upgrade-0.22
|
||||
```
|
||||
|
||||
La commande `yarn database:migrate:prod` appliquera les migrations à la base de données.
|
||||
La commande `yarn command:prod workspace:sync-metadata -f` synchronisera la définition des objets standard avec les tables de métadonnées et appliquera les migrations nécessaires aux espaces de travail existants.
|
||||
La commande `yarn command:prod upgrade-0.22` appliquera des transformations de données spécifiques pour s’adapter aux nouvelles `defaultRequestInstrumentationOptions` d’objet.
|
||||
|
||||
-16
@@ -50,22 +50,6 @@ npx nx run twenty-server:database:reset
|
||||
npx nx run twenty-server:typeorm migration:generate src/database/typeorm/core/migrations/nameOfYourMigration -d src/database/typeorm/core/core.datasource.ts
|
||||
```
|
||||
|
||||
#### Per gli oggetti del Workspace
|
||||
|
||||
Non ci sono file di migrazioni; le migrazioni sono generate automaticamente per ogni workspace, memorizzate nel database e applicate con questo comando
|
||||
|
||||
```bash
|
||||
npx nx run twenty-server:command workspace:sync-metadata -f
|
||||
```
|
||||
|
||||
<Warning>
|
||||
|
||||
Questo eliminerà il database e rieseguirà le migrazioni e il popolamento dei dati.
|
||||
|
||||
Assicurati di eseguire il backup dei dati che vuoi mantenere prima di eseguire questo comando.
|
||||
|
||||
</Warning>
|
||||
|
||||
## Tech Stack
|
||||
|
||||
Twenty utilizza principalmente NestJS per il backend.
|
||||
|
||||
@@ -755,7 +755,7 @@ export default defineFrontComponent({
|
||||
});
|
||||
```
|
||||
|
||||
Dopo la sincronizzazione con `yarn twenty dev`, l'azione rapida appare nell'angolo in alto a destra della pagina:
|
||||
Dopo la sincronizzazione con `yarn twenty dev` (o eseguendo una volta sola `yarn twenty dev --once`), l'azione rapida appare nell'angolo in alto a destra della pagina:
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/quick-action.png" alt="Pulsante di azione rapida nell'angolo in alto a destra" />
|
||||
@@ -1401,7 +1401,7 @@ export default defineFrontComponent({
|
||||
|
||||
### Come funziona il bundling
|
||||
|
||||
La fase di build (`yarn twenty dev` o `yarn twenty build`) usa esbuild per produrre un singolo file autonomo per ogni funzione logica e per ogni componente front-end. Tutti i pacchetti importati sono incorporati nel bundle.
|
||||
La fase di build usa esbuild per produrre un singolo file autonomo per ogni funzione logica e per ogni componente front-end. Tutti i pacchetti importati sono incorporati nel bundle.
|
||||
|
||||
**Le funzioni logiche** vengono eseguite in un ambiente Node.js. I moduli integrati di Node (`fs`, `path`, `crypto`, `http`, ecc.) sono disponibili e non necessitano di essere installati.
|
||||
|
||||
|
||||
@@ -98,6 +98,21 @@ La modalità di sviluppo è disponibile solo sulle istanze di Twenty in esecuzio
|
||||
<img src="/images/docs/developers/extends/apps/dev.jpg" alt="Output del terminale in modalità sviluppo" />
|
||||
</div>
|
||||
|
||||
#### Sincronizzazione una tantum con `yarn twenty dev --once`
|
||||
|
||||
Se non vuoi un watcher in esecuzione in background (ad esempio in una pipeline CI, un hook di Git o un flusso di lavoro scriptato), passa il flag `--once`. Esegue la stessa pipeline di `yarn twenty dev` — genera il manifest, effettua il bundling dei file, carica, sincronizza, rigenera il client API tipizzato — ma **termina non appena la sincronizzazione è completata**:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty dev --once
|
||||
```
|
||||
|
||||
| Comando | Comportamento | Quando usarlo |
|
||||
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
|
||||
| `yarn twenty dev` | Monitora i file sorgente e risincronizza a ogni modifica. Rimane in esecuzione finché non lo interrompi. | Sviluppo locale interattivo — vuoi il pannello di stato in tempo reale e un ciclo di feedback immediato. |
|
||||
| `yarn twenty dev --once` | Esegue una singola build + sincronizzazione, quindi termina con codice `0` in caso di successo o `1` in caso di errore. | Script, CI, hook pre-commit, agenti IA e qualsiasi flusso di lavoro non interattivo. |
|
||||
|
||||
Entrambe le modalità richiedono un server Twenty in esecuzione in modalità di sviluppo e un remote autenticato — si applicano gli stessi prerequisiti.
|
||||
|
||||
### Visualizza la tua app in Twenty
|
||||
|
||||
Apri [http://localhost:2020/settings/applications#developer](http://localhost:2020/settings/applications#developer) nel browser. Vai su **Settings > Apps** e seleziona la scheda **Developer**. Dovresti vedere la tua app elencata in **Your Apps**:
|
||||
|
||||
@@ -52,7 +52,11 @@ yarn twenty deploy
|
||||
|
||||
### Condivisione di un'app distribuita
|
||||
|
||||
Le app in formato tarball non sono elencate nel marketplace pubblico, quindi altri spazi di lavoro sullo stesso server non le troveranno navigando. Per condividere un'app distribuita:
|
||||
<Warning>
|
||||
La condivisione di app private (tarball) tra spazi di lavoro è una funzionalità **Enterprise**. La scheda **Distribution** mostrerà un invito all'aggiornamento al posto dei controlli di condivisione finché il tuo spazio di lavoro non dispone di una chiave Enterprise valida. Vedi [Impostazioni > Pannello di amministrazione > Enterprise](/settings/admin-panel#enterprise) per attivarla.
|
||||
</Warning>
|
||||
|
||||
Le app in formato tarball non sono elencate nel marketplace pubblico, quindi altri spazi di lavoro sullo stesso server non le troveranno navigando. Una volta che il tuo spazio di lavoro è sul piano Enterprise, puoi condividere un'app distribuita in questo modo:
|
||||
|
||||
1. Vai su **Impostazioni > Applicazioni > Registrazioni** e apri la tua app
|
||||
2. Nella scheda **Distribuzione**, fai clic su **Copia link di condivisione**
|
||||
@@ -60,10 +64,6 @@ Le app in formato tarball non sono elencate nel marketplace pubblico, quindi alt
|
||||
|
||||
Il link di condivisione utilizza l'URL di base del server (senza alcun sottodominio dello spazio di lavoro) così funziona per qualsiasi spazio di lavoro sul server.
|
||||
|
||||
<Warning>
|
||||
La condivisione delle app private è una funzionalità Enterprise. Vai a [Impostazioni > Pannello di amministrazione > Enterprise](/settings/admin-panel#enterprise) per abilitarla.
|
||||
</Warning>
|
||||
|
||||
### Gestione delle versioni
|
||||
|
||||
Per rilasciare un aggiornamento:
|
||||
|
||||
@@ -140,12 +140,12 @@ I dati non corrispondono al formato previsto per quel tipo di campo.
|
||||
#### Data
|
||||
|
||||
**Problema:** formato data non riconosciuto
|
||||
**Soluzione:** usa un formato coerente in tutto il file
|
||||
**Soluzione:** Usa il formato `YYYY-MM-DD` in modo coerente in tutto il file
|
||||
|
||||
```
|
||||
✓ 2024-03-15 (YYYY-MM-DD - recommended)
|
||||
✓ 03/15/2024 (MM/DD/YYYY)
|
||||
✓ 15/03/2024 (DD/MM/YYYY)
|
||||
✓ 2024-03-15 (YYYY-MM-DD)
|
||||
❌ 03/15/2024 (MM/DD/YYYY)
|
||||
❌ 15/03/2024 (DD/MM/YYYY)
|
||||
```
|
||||
|
||||
#### Telefono
|
||||
|
||||
@@ -103,8 +103,6 @@ Indirizzo è un **campo annidato** con più colonne (alcune possono essere lasci
|
||||
Usa un formato coerente in tutto il file:
|
||||
|
||||
* `YYYY-MM-DD` (consigliato): `2024-03-15`
|
||||
* `MM/DD/YYYY`: `03/15/2024`
|
||||
* `DD/MM/YYYY`: `15/03/2024`
|
||||
* ISO 8601: `2024-03-15T10:30:00Z`
|
||||
|
||||
### Campi numerici
|
||||
|
||||
-22
@@ -48,28 +48,6 @@ npx nx run twenty-server:database:reset
|
||||
```
|
||||
|
||||
### マイグレーション
|
||||
|
||||
#### Core/Metadata スキーマ (TypeORM) のオブジェクトに対して
|
||||
|
||||
```bash
|
||||
npx nx run twenty-server:typeorm migration:generate src/database/typeorm/core/migrations/nameOfYourMigration -d src/database/typeorm/core/core.datasource.ts
|
||||
```
|
||||
|
||||
#### ワークスペースオブジェクトに対して
|
||||
|
||||
マイグレーションファイルはなく、それぞれのワークスペースに対して自動的に生成され、
|
||||
データベースに保存され、このコマンドで適用されます。
|
||||
|
||||
```bash
|
||||
npx nx run twenty-server:command workspace:sync-metadata -f
|
||||
```
|
||||
|
||||
<Warning>
|
||||
これによりデータベースが削除され、マイグレーションとシードが再実行されます。
|
||||
|
||||
このコマンドを実行する前に、保持したいデータをバックアップしてください。
|
||||
</Warning>
|
||||
|
||||
## 技術スタック
|
||||
|
||||
Twenty は主にバックエンドに NestJS を使用しています。
|
||||
|
||||
@@ -270,7 +270,6 @@ yarn command:prod upgrade-0.33
|
||||
`yarn database:migrate:prod` コマンドはデータベース構造(コアおよびメタデータスキーマ)の移行を適用します
|
||||
`yarn command:prod upgrade-0.33` はすべてのワークスペースのデータ移行を行います。
|
||||
`yarn database:migrate:prod` コマンドはデータベースへの移行を適用します。
|
||||
"`yarn command:prod workspace:sync-metadata -f` コマンドは、標準オブジェクトの定義をメタデータテーブルに同期し、既存のワークスペースに必要な移行を適用します。"
|
||||
The `yarn command:prod upgrade-0.22` command will apply specific data transformations to adapt to the new object defaultRequestInstrumentationOptions.
|
||||
|
||||
このバージョンから、DB用のtwenty-postgresイメージは廃止され、twenty-postgres-spiloが代わりに使用されるようになりました。
|
||||
@@ -389,11 +388,9 @@ Twentyインスタンスをv0.22.0イメージにアップグレードします
|
||||
|
||||
```
|
||||
yarn database:migrate:prod
|
||||
yarn command:prod workspace:sync-metadata -f
|
||||
yarn command:prod upgrade-0.22
|
||||
```
|
||||
|
||||
`yarn database:migrate:prod` コマンドはデータベースへの移行を適用します。
|
||||
`yarn command:prod upgrade-0.23` は、アクティビティをタスク/ノートに移行するなど、データ移行を担当します。
|
||||
"`yarn command:prod workspace:sync-metadata -f` コマンドは、標準オブジェクトの定義をメタデータテーブルに同期し、既存のワークスペースに必要な移行を適用します。"
|
||||
`yarn command:prod upgrade-0.22` コマンドは、新しいオブジェクトの defaultRequestInstrumentationOptions に適合させるため、特定のデータ変換を適用します。
|
||||
|
||||
-21
@@ -43,27 +43,6 @@ npx nx run twenty-server:database:reset
|
||||
```
|
||||
|
||||
### 마이그레이션
|
||||
|
||||
#### Core/Metadata 스키마의 객체용 (TypeORM)
|
||||
|
||||
```bash
|
||||
npx nx run twenty-server:typeorm migration:generate src/database/typeorm/core/migrations/nameOfYourMigration -d src/database/typeorm/core/core.datasource.ts
|
||||
```
|
||||
|
||||
#### 워크스페이스 객체용
|
||||
|
||||
마이그레이션 파일이 없으며, 각 작업 공간에 대해 자동 생성되고 데이터베이스에 저장되어 이 명령으로 적용됩니다.
|
||||
|
||||
```bash
|
||||
npx nx run twenty-server:command workspace:sync-metadata -f
|
||||
```
|
||||
|
||||
<Warning>
|
||||
이 작업은 데이터베이스를 삭제하고 마이그레이션과 시드를 다시 실행합니다.
|
||||
|
||||
이 명령을 실행하기 전에 유지하고 싶은 데이터를 백업하십시오.
|
||||
</Warning>
|
||||
|
||||
## 기술 스택
|
||||
|
||||
Twenty는 주로 NestJS를 백엔드에 사용합니다.
|
||||
|
||||
@@ -365,10 +365,8 @@ Twenty 인스턴스를 v0.22.0 이미지로 업그레이드하십시오.
|
||||
|
||||
```
|
||||
yarn database:migrate:prod
|
||||
yarn command:prod workspace:sync-metadata -f
|
||||
yarn command:prod upgrade-0.22
|
||||
```
|
||||
|
||||
`yarn database:migrate:prod` 명령은 데이터베이스에 마이그레이션을 적용합니다.
|
||||
`yarn command:prod workspace:sync-metadata -f` 명령은 표준 객체의 정의를 메타데이터 테이블에 동기화하고 기존 워크스페이스에 필요한 마이그레이션을 적용합니다.
|
||||
`yarn command:prod upgrade-0.22` 명령은 새 객체 defaultRequestInstrumentationOptions에 적응하기 위한 특정 데이터 변환을 적용합니다.
|
||||
|
||||
-16
@@ -50,22 +50,6 @@ npx nx run twenty-server:database:reset
|
||||
npx nx run twenty-server:typeorm migration:generate src/database/typeorm/core/migrations/nameOfYourMigration -d src/database/typeorm/core/core.datasource.ts
|
||||
```
|
||||
|
||||
#### For Workspace objects
|
||||
|
||||
Não há arquivos de migração, as migrações são geradas automaticamente para cada espaço de trabalho, armazenadas no banco de dados e aplicadas com este comando
|
||||
|
||||
```bash
|
||||
npx nx run twenty-server:command workspace:sync-metadata -f
|
||||
```
|
||||
|
||||
<Warning>
|
||||
|
||||
Isso excluirá o banco de dados e reexecutará as migrações e seeds.
|
||||
|
||||
Certifique-se de fazer backup de todos os dados que deseja manter antes de executar este comando.
|
||||
|
||||
</Warning>
|
||||
|
||||
## Pilha de Tecnologias
|
||||
|
||||
O Twenty usa principalmente NestJS para o backend.
|
||||
|
||||
@@ -755,7 +755,7 @@ export default defineFrontComponent({
|
||||
});
|
||||
```
|
||||
|
||||
Após sincronizar com `yarn twenty dev`, a ação rápida aparece no canto superior direito da página:
|
||||
Após sincronizar com `yarn twenty dev` (ou executando uma única vez o `yarn twenty dev --once`), a ação rápida aparece no canto superior direito da página:
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/quick-action.png" alt="Botão de ação rápida no canto superior direito" />
|
||||
@@ -1401,7 +1401,7 @@ export default defineFrontComponent({
|
||||
|
||||
### Como o empacotamento funciona
|
||||
|
||||
A etapa de build (`yarn twenty dev` ou `yarn twenty build`) usa o esbuild para produzir um único arquivo independente por função lógica e por componente de front-end. Todos os pacotes importados são incorporados ao bundle.
|
||||
A etapa de build usa o esbuild para produzir um único arquivo independente por função lógica e por componente de front-end. Todos os pacotes importados são incorporados ao bundle.
|
||||
|
||||
**Funções lógicas** são executadas em um ambiente Node.js. Módulos nativos do Node (`fs`, `path`, `crypto`, `http`, etc.) estão disponíveis e não precisam ser instalados.
|
||||
|
||||
|
||||
@@ -98,6 +98,21 @@ O modo de desenvolvimento só está disponível em instâncias do Twenty em modo
|
||||
<img src="/images/docs/developers/extends/apps/dev.jpg" alt="Saída do terminal no modo de desenvolvimento" />
|
||||
</div>
|
||||
|
||||
#### Sincronização única com `yarn twenty dev --once`
|
||||
|
||||
Se você não quiser um monitor em execução em segundo plano (por exemplo, em um pipeline de CI, um hook do git ou um fluxo de trabalho com script), passe a flag `--once`. Ele executa o mesmo pipeline que `yarn twenty dev` — gerar o manifesto, empacotar arquivos, fazer upload, sincronizar, regenerar o cliente de API tipado — mas **encerra assim que a sincronização for concluída**:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty dev --once
|
||||
```
|
||||
|
||||
| Comando | Comportamento | Quando usar |
|
||||
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| `yarn twenty dev` | Monitora seus arquivos-fonte e ressincroniza a cada alteração. Continua em execução até você interrompê-lo. | Desenvolvimento local interativo — você quer o painel de status em tempo real e um ciclo de feedback instantâneo. |
|
||||
| `yarn twenty dev --once` | Executa uma única compilação + sincronização e, em seguida, encerra com o código `0` em caso de sucesso ou `1` em caso de falha. | Scripts, CI, hooks de pre-commit, agentes de IA e qualquer fluxo de trabalho não interativo. |
|
||||
|
||||
Ambos os modos exigem um servidor Twenty em execução no modo de desenvolvimento e um remoto autenticado — aplicam-se os mesmos pré-requisitos.
|
||||
|
||||
### Veja seu aplicativo no Twenty
|
||||
|
||||
Abra [http://localhost:2020/settings/applications#developer](http://localhost:2020/settings/applications#developer) no seu navegador. Navegue até **Settings > Apps** e selecione a aba **Developer**. Você deverá ver seu aplicativo listado em **Your Apps**:
|
||||
|
||||
@@ -52,7 +52,11 @@ yarn twenty deploy
|
||||
|
||||
### Compartilhando um aplicativo implantado
|
||||
|
||||
Aplicativos em tarball não são listados no marketplace público, então outros espaços de trabalho no mesmo servidor não os descobrirão ao navegar. Para compartilhar um aplicativo implantado:
|
||||
<Warning>
|
||||
Compartilhar aplicativos privados (tarball) entre espaços de trabalho é um recurso do plano **Enterprise**. A guia **Distribution** exibirá um aviso de atualização em vez dos controles de compartilhamento até que seu espaço de trabalho tenha uma chave Enterprise válida. Vá para [Configurações > Painel de Administração > Enterprise](/settings/admin-panel#enterprise) para ativá-lo.
|
||||
</Warning>
|
||||
|
||||
Aplicativos em tarball não são listados no marketplace público, então outros espaços de trabalho no mesmo servidor não os descobrirão ao navegar. Assim que o seu espaço de trabalho estiver no plano Enterprise, você pode compartilhar um app implantado desta forma:
|
||||
|
||||
1. Vá para **Configurações > Aplicações > Registros** e abra seu aplicativo
|
||||
2. Na guia **Distribuição**, clique em **Copiar link de compartilhamento**
|
||||
@@ -60,10 +64,6 @@ Aplicativos em tarball não são listados no marketplace público, então outros
|
||||
|
||||
O link de compartilhamento usa a URL base do servidor (sem qualquer subdomínio de espaço de trabalho), para funcionar em qualquer espaço de trabalho no servidor.
|
||||
|
||||
<Warning>
|
||||
Compartilhar apps privados é um recurso do plano Enterprise. Vá para [Configurações > Painel de Administração > Enterprise](/settings/admin-panel#enterprise) para ativá-lo.
|
||||
</Warning>
|
||||
|
||||
### Gerenciamento de versões
|
||||
|
||||
Para lançar uma atualização:
|
||||
|
||||
@@ -140,12 +140,12 @@ Os dados não correspondem ao formato esperado para esse tipo de campo.
|
||||
#### Data
|
||||
|
||||
**Problema:** Formato de data não reconhecido
|
||||
**Solução:** Use um formato consistente em todo o ficheiro
|
||||
**Solução:** Use o formato `YYYY-MM-DD` de forma consistente em todo o ficheiro
|
||||
|
||||
```
|
||||
✓ 2024-03-15 (YYYY-MM-DD - recomendado)
|
||||
✓ 03/15/2024 (MM/DD/YYYY)
|
||||
✓ 15/03/2024 (DD/MM/YYYY)
|
||||
✓ 2024-03-15 (YYYY-MM-DD)
|
||||
❌ 03/15/2024 (MM/DD/YYYY)
|
||||
❌ 15/03/2024 (DD/MM/YYYY)
|
||||
```
|
||||
|
||||
#### Telefone
|
||||
|
||||
@@ -103,8 +103,6 @@ Endereço é um **campo aninhado** com várias colunas (algumas podem ficar em b
|
||||
Use formatação consistente em todo o seu arquivo:
|
||||
|
||||
* `YYYY-MM-DD` (recomendado): `2024-03-15`
|
||||
* `MM/DD/YYYY`: `03/15/2024`
|
||||
* `DD/MM/YYYY`: `15/03/2024`
|
||||
* ISO 8601: `2024-03-15T10:30:00Z`
|
||||
|
||||
### Campos Numéricos
|
||||
|
||||
-17
@@ -50,23 +50,6 @@ npx nx run twenty-server:database:reset
|
||||
npx nx run twenty-server:typeorm migration:generate src/database/typeorm/core/migrations/nameOfYourMigration -d src/database/typeorm/core/core.datasource.ts
|
||||
```
|
||||
|
||||
#### Pentru obiectele din Workspace
|
||||
|
||||
Nu există fișiere de migrație, migrația este generată automat pentru fiecare spațiu de lucru,
|
||||
este stocată în baza de date și aplicată cu această comandă
|
||||
|
||||
```bash
|
||||
npx nx run twenty-server:command workspace:sync-metadata -f
|
||||
```
|
||||
|
||||
<Warning>
|
||||
|
||||
Acest lucru va elimina baza de date și va relansa migrațiile și seed-urile.
|
||||
|
||||
Asigură-te că faci un backup pentru orice date pe care dorești să le păstrezi înainte de a rula această comandă.
|
||||
|
||||
</Warning>
|
||||
|
||||
## Tehnologii Utilizate
|
||||
|
||||
Twenty folosește în principal NestJS pentru backend.
|
||||
|
||||
@@ -756,7 +756,7 @@ export default defineFrontComponent({
|
||||
});
|
||||
```
|
||||
|
||||
După sincronizarea cu `yarn twenty dev`, acțiunea rapidă apare în colțul din dreapta sus al paginii:
|
||||
După sincronizarea cu `yarn twenty dev` (sau prin rularea o singură dată a comenzii `yarn twenty dev --once`), acțiunea rapidă apare în colțul din dreapta sus al paginii:
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/quick-action.png" alt="Buton de acțiune rapidă în colțul din dreapta sus" />
|
||||
@@ -1402,7 +1402,7 @@ export default defineFrontComponent({
|
||||
|
||||
### Cum funcționează împachetarea
|
||||
|
||||
Pasul de build (`yarn twenty dev` sau `yarn twenty build`) folosește esbuild pentru a produce un singur fișier autonom per funcție logică și per componentă frontend. Toate pachetele importate sunt integrate în bundle.
|
||||
Pasul de build folosește esbuild pentru a produce un singur fișier autonom pentru fiecare funcție logică și pentru fiecare componentă frontend. Toate pachetele importate sunt integrate în bundle.
|
||||
|
||||
**Funcțiile logice** rulează într-un mediu Node.js. Modulele built-in Node (`fs`, `path`, `crypto`, `http` etc.) sunt disponibile și nu trebuie instalate.
|
||||
|
||||
|
||||
@@ -98,6 +98,21 @@ Modul de dezvoltare este disponibil doar pe instanțele Twenty care rulează în
|
||||
<img src="/images/docs/developers/extends/apps/dev.jpg" alt="Ieșirea terminalului în modul de dezvoltare" />
|
||||
</div>
|
||||
|
||||
#### One-shot sync with `yarn twenty dev --once`
|
||||
|
||||
If you do not want a watcher running in the background (for example in a CI pipeline, a git hook, or a scripted workflow), pass the `--once` flag. It runs the same pipeline as `yarn twenty dev` — build manifest, bundle files, upload, sync, regenerate the typed API client — but **exits as soon as the sync completes**:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty dev --once
|
||||
```
|
||||
|
||||
| Comandă | Comportament | When to use |
|
||||
| ------------------------ | ---------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
|
||||
| `yarn twenty dev` | Watches your source files and re-syncs on every change. Keeps running until you stop it. | Interactive local development — you want the live status panel and instant feedback loop. |
|
||||
| `yarn twenty dev --once` | Performs a single build + sync, then exits with code `0` on success or `1` on failure. | Scripts, CI, pre-commit hooks, AI agents, and any non-interactive workflow. |
|
||||
|
||||
Both modes require a Twenty server running in development mode and an authenticated remote — the same prerequisites apply.
|
||||
|
||||
### Vedeți aplicația în Twenty
|
||||
|
||||
Deschideți [http://localhost:2020/settings/applications#developer](http://localhost:2020/settings/applications#developer) în browser. Navigați la **Settings > Apps** și selectați fila **Developer**. Ar trebui să vedeți aplicația listată la **Your Apps**:
|
||||
|
||||
@@ -52,7 +52,11 @@ yarn twenty deploy
|
||||
|
||||
### Partajarea unei aplicații implementate
|
||||
|
||||
Aplicațiile tarball nu sunt listate în marketplace-ul public, astfel încât alte spații de lucru de pe același server nu le vor descoperi prin navigare. Pentru a partaja o aplicație implementată:
|
||||
<Warning>
|
||||
Partajarea aplicațiilor private (tarball) între spații de lucru este o funcționalitate **Enterprise**. Fila **Distribution** va afișa un mesaj de actualizare în locul controalelor de partajare până când spațiul tău de lucru are o cheie Enterprise validă. Mergi la [Setări > Panou de administrare > Enterprise](/settings/admin-panel#enterprise) pentru a o activa.
|
||||
</Warning>
|
||||
|
||||
Aplicațiile tarball nu sunt listate în marketplace-ul public, astfel încât alte spații de lucru de pe același server nu le vor descoperi prin navigare. După ce spațiul tău de lucru este pe planul Enterprise, poți partaja o aplicație implementată astfel:
|
||||
|
||||
1. Mergi la **Setări > Aplicații > Înregistrări** și deschide aplicația ta
|
||||
2. În fila **Distribuție**, fă clic pe **Copiază linkul de partajare**
|
||||
@@ -60,10 +64,6 @@ Aplicațiile tarball nu sunt listate în marketplace-ul public, astfel încât a
|
||||
|
||||
Linkul de partajare folosește URL-ul de bază al serverului (fără niciun subdomeniu de spațiu de lucru), astfel încât funcționează pentru orice spațiu de lucru de pe server.
|
||||
|
||||
<Warning>
|
||||
Partajarea aplicațiilor private este o funcționalitate Enterprise. Mergi la [Setări > Panou de administrare > Enterprise](/settings/admin-panel#enterprise) pentru a o activa.
|
||||
</Warning>
|
||||
|
||||
### Gestionarea versiunilor
|
||||
|
||||
Pentru a lansa o actualizare:
|
||||
|
||||
-17
@@ -50,23 +50,6 @@ npx nx run twenty-server:database:reset
|
||||
npx nx run twenty-server:typeorm migration:generate src/database/typeorm/core/migrations/nameOfYourMigration -d src/database/typeorm/core/core.datasource.ts
|
||||
```
|
||||
|
||||
#### Для объектов Рабочего пространства
|
||||
|
||||
Файлов миграций нет, миграции создаются автоматически для каждого рабочего пространства,
|
||||
хранятся в базе данных и применяются этой командой
|
||||
|
||||
```bash
|
||||
npx nx run twenty-server:command workspace:sync-metadata -f
|
||||
```
|
||||
|
||||
<Warning>
|
||||
|
||||
Это удалит базу данных, переустановит миграции и семена.
|
||||
|
||||
Убедитесь, что создали резервную копию данных, которые хотите сохранить, прежде чем выполнять эту команду.
|
||||
|
||||
</Warning>
|
||||
|
||||
## Технологический стек
|
||||
|
||||
Для работы с серверной частью Twenty в основном использует NestJS.
|
||||
|
||||
@@ -755,7 +755,7 @@ export default defineFrontComponent({
|
||||
});
|
||||
```
|
||||
|
||||
После синхронизации с помощью `yarn twenty dev` быстрое действие появится в правом верхнем углу страницы:
|
||||
После синхронизации с помощью `yarn twenty dev` (или однократного запуска `yarn twenty dev --once`) быстрое действие появится в правом верхнем углу страницы:
|
||||
|
||||
<div style={{textAlign: 'center'}}>
|
||||
<img src="/images/docs/developers/extends/apps/quick-action.png" alt="Кнопка быстрого действия в правом верхнем углу" />
|
||||
@@ -1401,7 +1401,7 @@ export default defineFrontComponent({
|
||||
|
||||
### Как работает бандлинг
|
||||
|
||||
Этап сборки (`yarn twenty dev` или `yarn twenty build`) использует esbuild для создания одного самодостаточного файла на каждую логическую функцию и на каждый компонент фронтенда. Все импортированные пакеты встроены в бандл.
|
||||
Этап сборки использует esbuild для создания одного самодостаточного файла на каждую логическую функцию и на каждый компонент фронтенда. Все импортированные пакеты встроены в бандл.
|
||||
|
||||
**Логические функции** выполняются в среде Node.js. Встроенные модули Node (`fs`, `path`, `crypto`, `http` и т. д.) доступны и не требуют установки.
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user