Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f1c2ac33b3 | ||
|
|
6fe3d586cd | ||
|
|
3d95d6ca00 | ||
|
|
9c334b5f03 | ||
|
|
35319ee13f | ||
|
|
2e7dbe6b90 | ||
|
|
6c9abedc96 | ||
|
|
267bfcadf8 | ||
|
|
a829ae62e2 | ||
|
|
c62bd396f7 | ||
|
|
3e75e39650 | ||
|
|
578aa9d5ca | ||
|
|
735855d7b1 | ||
|
|
ea79425fc0 | ||
|
|
e79046618b | ||
|
|
21a433dd93 | ||
|
|
9b0e8d3232 | ||
|
|
2378a91d8f | ||
|
|
59672e3e34 | ||
|
|
a7c5969ede | ||
|
|
a892462c05 | ||
|
|
e18262cfa6 | ||
|
|
a0f196e871 | ||
|
|
288db78abd | ||
|
|
f248b3f7f4 | ||
|
|
05b30554c3 | ||
|
|
3274c18a90 | ||
|
|
900401c101 | ||
|
|
5edb5e2d53 | ||
|
|
21c023c6d6 | ||
|
|
bf818b7d8d | ||
|
|
77409b6eb2 | ||
|
|
aa729a2a0a | ||
|
|
0158c6fb3c | ||
|
|
eecc7aaed3 | ||
|
|
12babba6f6 | ||
|
|
13e283fc3a | ||
|
|
9cfcc114de | ||
|
|
1038efa3dd | ||
|
|
00e970bdf4 | ||
|
|
f880ab086c | ||
|
|
4ed8c8ed32 | ||
|
|
6ea817dd6c | ||
|
|
5d4170d4c3 | ||
|
|
eedb163131 | ||
|
|
59f0f6f9db | ||
|
|
2922a1ee5a | ||
|
|
269135e8c5 | ||
|
|
5abab1feb2 | ||
|
|
2691222d5f | ||
|
|
68c429a54a | ||
|
|
da7536124e | ||
|
|
670d6ce3ec | ||
|
|
2cdf5ae75b | ||
|
|
a8e7d4dfc3 | ||
|
|
32f387a966 | ||
|
|
c51a4a188d | ||
|
|
d39a7e809b | ||
|
|
5e00893c37 | ||
|
|
1eb2e44058 | ||
|
|
4e0545ebc5 | ||
|
|
425a3814e9 | ||
|
|
79e2602790 | ||
|
|
af23fddfa2 | ||
|
|
ee08060798 | ||
|
|
1fcb8b464c | ||
|
|
638d4015a1 | ||
|
|
19fc20173b | ||
|
|
b5ec6df62f | ||
|
|
f489bbdbab | ||
|
|
e498367e2f | ||
|
|
3f08a0c901 | ||
|
|
dedb191cae | ||
|
|
63afed6400 | ||
|
|
9f62188ba6 | ||
|
|
ea3c5d2d45 | ||
|
|
23a7611aac | ||
|
|
cd699cbda1 | ||
|
|
4d7965c058 | ||
|
|
f2cdf8a6e1 | ||
|
|
df20c52293 | ||
|
|
5016c25daa | ||
|
|
7bf68e5f31 | ||
|
|
9387680020 | ||
|
|
7620e1b0a6 | ||
|
|
f2f1204af6 | ||
|
|
fc6b136c2f | ||
|
|
470888a23a | ||
|
|
5cea3d4358 | ||
|
|
e712eb01fb | ||
|
|
f2d9400e22 | ||
|
|
4d223e3ad3 | ||
|
|
9bc58a4ef9 | ||
|
|
eb362c6d5f | ||
|
|
9620a4b0ba | ||
|
|
fd9ea2f5ee | ||
|
|
1e98e4da4d | ||
|
|
04b01170ed | ||
|
|
e53e0d266d | ||
|
|
b1ef395627 | ||
|
|
a77b9d4a95 | ||
|
|
a343bc1aee | ||
|
|
41a07006ef | ||
|
|
f3dc81217e | ||
|
|
fa87603fd8 | ||
|
|
f23aa632a7 | ||
|
|
d09cb7c66b | ||
|
|
eaac569812 | ||
|
|
2f25922f4c | ||
|
|
32a876bbd4 | ||
|
|
d4b3a8978d | ||
|
|
3b8db734a5 | ||
|
|
4fed51b7d8 | ||
|
|
accd55d7cb | ||
|
|
65480eb492 | ||
|
|
ec53302ba8 | ||
|
|
d217767600 | ||
|
|
3590bf1e83 | ||
|
|
26ec6729c0 | ||
|
|
da626f70b7 | ||
|
|
27547fd445 | ||
|
|
57ae12ff7c | ||
|
|
76ed82b598 | ||
|
|
ca5bd76c6a | ||
|
|
97a8beb3f9 | ||
|
|
46ce9eca3f | ||
|
|
1607aebcc6 | ||
|
|
978c0acb90 | ||
|
|
afd5ccc775 | ||
|
|
f3a796e17e | ||
|
|
44f4203d58 | ||
|
|
20e6f130d1 | ||
|
|
db6456b1af | ||
|
|
d7f8c2d338 | ||
|
|
1a45576990 | ||
|
|
7001c91a7d | ||
|
|
9c9a01d55a | ||
|
|
7e90dd888c | ||
|
|
9f939eb4c3 | ||
|
|
4f20fd35c5 | ||
|
|
35f81805b8 | ||
|
|
b1d1bcb712 | ||
|
|
5d1c2a3348 | ||
|
|
ee6ac6bb4c | ||
|
|
3c658b209d | ||
|
|
70f48ba445 | ||
|
|
5202e2b2db | ||
|
|
fc4dbb80de | ||
|
|
7f441d741b | ||
|
|
60e69f92d9 | ||
|
|
c82c4a4507 | ||
|
|
4120c191f8 | ||
|
|
8dc182d659 | ||
|
|
c34f798a9c | ||
|
|
6fcb05d9b3 | ||
|
|
dc2c2c413c | ||
|
|
996ccd8353 | ||
|
|
74eab77539 | ||
|
|
0d34651d5e | ||
|
|
4d0c469157 | ||
|
|
6c1c78ea3d | ||
|
|
b1c03b533f | ||
|
|
f3416d435c | ||
|
|
1740a2217a | ||
|
|
0bf2d13832 | ||
|
|
21543b6803 | ||
|
|
71724de7dd | ||
|
|
42bba3de52 | ||
|
|
8455ecc3e8 | ||
|
|
825728b1c4 | ||
|
|
6d141c2439 | ||
|
|
88fbe6c51d | ||
|
|
3be3c4e965 | ||
|
|
2028a8f9be | ||
|
|
ab3d48383b | ||
|
|
53509360ff | ||
|
|
26169a2136 | ||
|
|
e7ebf51e50 | ||
|
|
3c0ae49a23 | ||
|
|
3e584c3d5f | ||
|
|
a47b7dfed0 | ||
|
|
46d1ea6505 | ||
|
|
316aec3c40 | ||
|
|
7109abc311 | ||
|
|
04562b11fb | ||
|
|
26e2fe349f | ||
|
|
b2472b30c4 | ||
|
|
30b6907c44 | ||
|
|
208c0857ee |
@@ -12,6 +12,7 @@ This directory contains Twenty's development guidelines and best practices in th
|
||||
### Core Guidelines
|
||||
- **architecture.mdc** - Project overview, technology stack, and infrastructure setup (Always Applied)
|
||||
- **nx-rules.mdc** - Nx workspace guidelines and best practices (Auto-attached to Nx files)
|
||||
- **server-migrations.mdc** - Backend migration and TypeORM guidelines for `twenty-server` (Auto-attached to server entities and migration files)
|
||||
|
||||
### Code Quality
|
||||
- **typescript-guidelines.mdc** - TypeScript best practices and conventions (Auto-attached to .ts/.tsx files)
|
||||
@@ -40,7 +41,7 @@ You can manually reference any rule using the `@ruleName` syntax:
|
||||
- `@testing-guidelines` - Get testing recommendations
|
||||
|
||||
### Rule Types Used
|
||||
- **Always Applied** - Loaded in every context (architecture.mdc, README.mdc)
|
||||
- **Always Applied** - Loaded in every context (architecture.mdc, README.mdc)
|
||||
- **Auto Attached** - Loaded when matching file patterns are referenced
|
||||
- **Agent Requested** - Available for AI to include when relevant
|
||||
- **Manual** - Only included when explicitly mentioned
|
||||
|
||||
@@ -89,6 +89,8 @@ Use the AI codebase search to find:
|
||||
|
||||
### 1. Setup Git Branch
|
||||
|
||||
**IMPORTANT**: Always start from an up-to-date main branch to avoid merge conflicts and ensure the changelog is based on the latest code.
|
||||
|
||||
```bash
|
||||
cd /Users/thomascolasdesfrancs/code/twenty
|
||||
git checkout main
|
||||
@@ -98,6 +100,8 @@ git checkout -b {VERSION}
|
||||
|
||||
Replace `{VERSION}` with the actual version number (e.g., `1.9.0`)
|
||||
|
||||
⚠️ **Do this first** before making any file changes. This ensures your branch is based on the latest main.
|
||||
|
||||
### 2. Create File Structure
|
||||
|
||||
**Create changelog file:**
|
||||
@@ -174,6 +178,7 @@ Description of the third feature.
|
||||
- Focus on user benefits, not technical implementation
|
||||
- Use active voice
|
||||
- Start with what the user can now do
|
||||
- **NEVER mention the brand name "Twenty"** in changelog text - use "your workspace", "the platform", or similar neutral references instead
|
||||
|
||||
**Reference Previous Changelogs:**
|
||||
- Check `packages/twenty-website/src/content/releases/` for examples
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
---
|
||||
description: Guidelines for generating and managing TypeORM migrations in twenty-server
|
||||
globs: [
|
||||
"packages/twenty-server/src/**/*.entity.ts",
|
||||
"packages/twenty-server/src/database/typeorm/**/*.ts"
|
||||
]
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
## Server Migrations (twenty-server)
|
||||
|
||||
- **When changing an entity, always generate a migration**
|
||||
- If you modify a `*.entity.ts` file in `packages/twenty-server/src`, you **must** generate a corresponding TypeORM migration instead of manually editing the database schema.
|
||||
- Use the Nx + TypeORM command from the project root:
|
||||
|
||||
```bash
|
||||
npx nx run twenty-server:typeorm migration:generate src/database/typeorm/core/migrations/common/[name] -d src/database/typeorm/core/core.datasource.ts
|
||||
```
|
||||
|
||||
- Replace `[name]` with a descriptive, kebab-case migration name that reflects the change (for example, `add-agent-turn-evaluation`).
|
||||
|
||||
- **Prefer generated migrations over manual edits**
|
||||
- Let TypeORM infer schema changes from the updated entities; only adjust the generated migration file manually if absolutely necessary (for example, for data backfills or complex constraints).
|
||||
- Keep schema changes (DDL) in these generated migrations and avoid mixing in heavy data migrations unless there is a strong reason and clear comments.
|
||||
|
||||
- **Keep migrations consistent and reversible**
|
||||
- Ensure the generated migration includes both `up` and `down` logic that correctly applies and reverts the entity change when possible.
|
||||
- Do not delete or rewrite existing, committed migrations unless you are explicitly working on a pre-release branch where history rewrites are allowed by team conventions.
|
||||
|
||||
@@ -63,4 +63,4 @@ git push origin your-branch-name
|
||||
|
||||
## Reporting Issues
|
||||
|
||||
If you face any issues or have suggestions, please feel free to (create an issue on Twenty's GitHub repository)[https://github.com/twentyhq/twenty/issues/new]. Please provide as much detail as possible.
|
||||
If you face any issues or have suggestions, please feel free to [create an issue on Twenty's GitHub repository](https://github.com/twentyhq/twenty/issues/new). Please provide as much detail as possible.
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
name: CI Create App
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
|
||||
|
||||
jobs:
|
||||
changed-files-check:
|
||||
uses: ./.github/workflows/changed-files.yaml
|
||||
with:
|
||||
files: |
|
||||
packages/create-twenty-app/**
|
||||
create-app-test:
|
||||
needs: changed-files-check
|
||||
if: needs.changed-files-check.outputs.any_changed == 'true'
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
task: [lint, typecheck, test, build]
|
||||
steps:
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.11.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
- name: Fetch custom Github Actions and base branch history
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Install dependencies
|
||||
uses: ./.github/workflows/actions/yarn-install
|
||||
- name: Run ${{ matrix.task }} task
|
||||
uses: ./.github/workflows/actions/nx-affected
|
||||
with:
|
||||
tag: scope:create-app
|
||||
tasks: ${{ matrix.task }}
|
||||
ci-create-app-status-check:
|
||||
if: always() && !cancelled()
|
||||
timeout-minutes: 5
|
||||
runs-on: ubuntu-latest
|
||||
needs: [changed-files-check, create-app-test]
|
||||
steps:
|
||||
- name: Fail job if any needs failed
|
||||
if: contains(needs.*.result, 'failure')
|
||||
run: exit 1
|
||||
@@ -1,4 +1,4 @@
|
||||
name: CI CLI
|
||||
name: CI SDK
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -19,9 +19,8 @@ jobs:
|
||||
uses: ./.github/workflows/changed-files.yaml
|
||||
with:
|
||||
files: |
|
||||
packages/twenty-cli/**
|
||||
packages/twenty-server/**
|
||||
cli-test:
|
||||
packages/twenty-sdk/**
|
||||
sdk-test:
|
||||
needs: changed-files-check
|
||||
if: needs.changed-files-check.outputs.any_changed == 'true'
|
||||
timeout-minutes: 30
|
||||
@@ -43,12 +42,12 @@ jobs:
|
||||
- name: Run ${{ matrix.task }} task
|
||||
uses: ./.github/workflows/actions/nx-affected
|
||||
with:
|
||||
tag: scope:cli
|
||||
tag: scope:sdk
|
||||
tasks: ${{ matrix.task }}
|
||||
cli-e2e-test:
|
||||
sdk-e2e-test:
|
||||
timeout-minutes: 30
|
||||
runs-on: depot-ubuntu-24.04-8
|
||||
needs: [changed-files-check, cli-test]
|
||||
needs: [changed-files-check, sdk-test]
|
||||
if: needs.changed-files-check.outputs.any_changed == 'true'
|
||||
services:
|
||||
postgres:
|
||||
@@ -90,13 +89,13 @@ jobs:
|
||||
- name: Server / Create Test DB
|
||||
run: |
|
||||
PGPASSWORD=postgres psql -h localhost -p 5432 -U postgres -d postgres -c 'CREATE DATABASE "test";'
|
||||
- name: CLI / Run E2E Tests
|
||||
run: npx nx test:e2e twenty-cli
|
||||
ci-cli-status-check:
|
||||
- name: SDK / Run E2E Tests
|
||||
run: npx nx test:e2e twenty-sdk
|
||||
ci-sdk-status-check:
|
||||
if: always() && !cancelled()
|
||||
timeout-minutes: 5
|
||||
runs-on: ubuntu-latest
|
||||
needs: [changed-files-check, cli-test, cli-e2e-test]
|
||||
needs: [changed-files-check, sdk-test, sdk-e2e-test]
|
||||
steps:
|
||||
- name: Fail job if any needs failed
|
||||
if: contains(needs.*.result, 'failure')
|
||||
@@ -1,4 +1,8 @@
|
||||
name: 'Test Docker Compose'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
|
||||
@@ -124,7 +124,9 @@ jobs:
|
||||
exit 0
|
||||
fi
|
||||
git commit -m "chore: sync docs artifacts"
|
||||
git push origin HEAD:${{ github.head_ref }}
|
||||
git push origin "HEAD:$HEAD_REF"
|
||||
env:
|
||||
HEAD_REF: ${{ github.head_ref }}
|
||||
|
||||
- name: Check for changes and commit
|
||||
if: github.event_name != 'pull_request'
|
||||
|
||||
+2
-7
@@ -9,8 +9,6 @@
|
||||
"@linaria/core": "^6.2.0",
|
||||
"@linaria/react": "^6.2.1",
|
||||
"@radix-ui/colors": "^3.0.0",
|
||||
"@sentry/profiling-node": "^9.26.0",
|
||||
"@sentry/react": "^9.26.0",
|
||||
"@sniptt/guards": "^0.2.0",
|
||||
"@tabler/icons-react": "^3.31.0",
|
||||
"@wyw-in-js/vite": "^0.7.0",
|
||||
@@ -189,11 +187,7 @@
|
||||
"ts-node": "10.9.1",
|
||||
"tsconfig-paths": "^4.2.0",
|
||||
"tsx": "^4.17.0",
|
||||
"vite": "^7.0.0",
|
||||
"vite-plugin-checker": "^0.10.2",
|
||||
"vite-plugin-cjs-interop": "^2.2.0",
|
||||
"vite-plugin-dts": "3.8.1",
|
||||
"vite-plugin-svgr": "^4.2.0"
|
||||
"vite": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^24.5.0",
|
||||
@@ -233,6 +227,7 @@
|
||||
"packages/twenty-sdk",
|
||||
"packages/twenty-apps",
|
||||
"packages/twenty-cli",
|
||||
"packages/create-twenty-app",
|
||||
"tools/eslint-rules"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
<div align="center">
|
||||
<a href="https://twenty.com">
|
||||
<picture>
|
||||
<img alt="Twenty logo" src="https://raw.githubusercontent.com/twentyhq/twenty/2f25922f4cd5bd61e1427c57c4f8ea224e1d552c/packages/twenty-website/public/images/core/logo.svg" height="128">
|
||||
</picture>
|
||||
</a>
|
||||
<h1>Create Twenty App</h1>
|
||||
|
||||
<a href="https://www.npmjs.com/package/create-twenty-app"><img alt="NPM version" src="https://img.shields.io/npm/v/create-twenty-app.svg?style=for-the-badge&labelColor=000000"></a>
|
||||
<a href="https://github.com/twentyhq/twenty/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/npm/l/next.svg?style=for-the-badge&labelColor=000000"></a>
|
||||
<a href="https://discord.gg/cx5n4Jzs57"><img alt="Join the community on Discord" src="https://img.shields.io/badge/Join%20the%20community-blueviolet.svg?style=for-the-badge&logo=Twenty&labelColor=000000&logoWidth=20"></a>
|
||||
|
||||
</div>
|
||||
|
||||
Create Twenty App is the official scaffolding CLI for building apps on top of [Twenty CRM](https://twenty.com). It sets up a ready‑to‑run project that works seamlessly with the [twenty-sdk](https://www.npmjs.com/package/twenty-sdk).
|
||||
|
||||
- Zero‑config project bootstrap
|
||||
- Preconfigured scripts for auth, generate, dev sync, one‑off sync, uninstall
|
||||
- Strong TypeScript support and typed client generation
|
||||
|
||||
## Prerequisites
|
||||
- Node.js 24+ (recommended) and Yarn 4
|
||||
- A Twenty workspace and an API key (create one at https://app.twenty.com/settings/api-webhooks)
|
||||
|
||||
## Quick start
|
||||
```bash
|
||||
npx create-twenty-app@latest my-twenty-app
|
||||
cd my-twenty-app
|
||||
|
||||
# Authenticate using your API key (you'll be prompted)
|
||||
yarn auth
|
||||
|
||||
# Add a new entity to your application (guided)
|
||||
yarn create-entity
|
||||
|
||||
# Generate a typed Twenty client and workspace entity types
|
||||
yarn generate
|
||||
|
||||
# Start dev mode: automatically syncs local changes to your workspace
|
||||
yarn dev
|
||||
|
||||
# Or run a one‑time sync
|
||||
yarn sync
|
||||
|
||||
# Uninstall the application from the current workspace
|
||||
yarn uninstall
|
||||
```
|
||||
|
||||
## What gets scaffolded
|
||||
- A minimal app structure ready for Twenty
|
||||
- TypeScript configuration
|
||||
- Prewired scripts that wrap the `twenty` CLI from twenty-sdk
|
||||
- Example placeholders to help you add entities, actions, and sync logic
|
||||
|
||||
## Next steps
|
||||
- Explore the generated project and add your first entity with `yarn create-entity`.
|
||||
- Keep your types up‑to‑date using `yarn generate`.
|
||||
- Use `yarn dev` while you iterate to see changes instantly in your workspace.
|
||||
|
||||
|
||||
## Publish your application
|
||||
Applications are currently stored in `twenty/packages/twenty-apps`.
|
||||
|
||||
You can share your application with all Twenty users:
|
||||
|
||||
```bash
|
||||
# pull the Twenty project
|
||||
git clone https://github.com/twentyhq/twenty.git
|
||||
cd twenty
|
||||
|
||||
# create a new branch
|
||||
git checkout -b feature/my-awesome-app
|
||||
```
|
||||
|
||||
- Copy your app folder into `twenty/packages/twenty-apps`.
|
||||
- Commit your changes and open a pull request on https://github.com/twentyhq/twenty
|
||||
|
||||
```bash
|
||||
git commit -m "Add new application"
|
||||
git push
|
||||
```
|
||||
|
||||
Our team reviews contributions for quality, security, and reusability before merging.
|
||||
|
||||
## Troubleshooting
|
||||
- Auth prompts not appearing: run `yarn auth` again and verify the API key permissions.
|
||||
- Types not generated: ensure `yarn generate` runs without errors, then re‑start `yarn dev`.
|
||||
|
||||
## Contributing
|
||||
- See our [GitHub](https://github.com/twentyhq/twenty)
|
||||
- Join our [Discord](https://discord.gg/cx5n4Jzs57)
|
||||
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"name": "create-twenty-app",
|
||||
"version": "0.1.0",
|
||||
"description": "Command-line interface to create Twenty application",
|
||||
"main": "dist/cli.cjs",
|
||||
"bin": "dist/cli.cjs",
|
||||
"files": [
|
||||
"dist/**/*"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "npx rimraf dist && npx vite build"
|
||||
},
|
||||
"keywords": [
|
||||
"twenty",
|
||||
"cli",
|
||||
"crm",
|
||||
"application",
|
||||
"development"
|
||||
],
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/cli.d.ts",
|
||||
"import": "./dist/cli.mjs",
|
||||
"require": "./dist/cli.cjs"
|
||||
}
|
||||
},
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
"@genql/cli": "^3.0.3",
|
||||
"chalk": "^5.3.0",
|
||||
"commander": "^12.0.0",
|
||||
"fs-extra": "^11.2.0",
|
||||
"inquirer": "^10.0.0",
|
||||
"lodash.camelcase": "^4.3.0",
|
||||
"lodash.kebabcase": "^4.1.1",
|
||||
"lodash.startcase": "^4.4.0",
|
||||
"uuid": "^13.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "^11.0.0",
|
||||
"@types/inquirer": "^9.0.0",
|
||||
"@types/lodash.camelcase": "^4.3.7",
|
||||
"@types/lodash.kebabcase": "^4.1.7",
|
||||
"@types/lodash.startcase": "^4",
|
||||
"@types/node": "^20.0.0",
|
||||
"vite": "^7.0.0",
|
||||
"vite-plugin-dts": "^4.5.4",
|
||||
"vite-tsconfig-paths": "^4.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^24.5.0",
|
||||
"yarn": "^4.0.2"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"name": "create-twenty-app",
|
||||
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||
"projectType": "library",
|
||||
"tags": ["scope:create-app"],
|
||||
"targets": {
|
||||
"build": {
|
||||
"dependsOn": ["^build"],
|
||||
"outputs": ["{projectRoot}/dist"]
|
||||
},
|
||||
"dev": {
|
||||
"executor": "nx:run-commands",
|
||||
"dependsOn": ["build"],
|
||||
"options": {
|
||||
"cwd": "packages/create-twenty-app",
|
||||
"command": "tsx src/cli.ts"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"executor": "nx:run-commands",
|
||||
"dependsOn": ["build"],
|
||||
"options": {
|
||||
"cwd": "packages/create-twenty-app",
|
||||
"command": "node dist/cli.cjs"
|
||||
}
|
||||
},
|
||||
"typecheck": {},
|
||||
"lint": {
|
||||
"options": {
|
||||
"lintFilePatterns": ["{projectRoot}/src/**/*.{ts,json}"],
|
||||
"maxWarnings": 0
|
||||
},
|
||||
"configurations": {
|
||||
"ci": {
|
||||
"lintFilePatterns": ["{projectRoot}/src/**/*.{ts,json}"],
|
||||
"maxWarnings": 0
|
||||
},
|
||||
"fix": {}
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"executor": "@nx/jest:jest",
|
||||
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
|
||||
"options": {
|
||||
"jestConfig": "{projectRoot}/jest.config.mjs"
|
||||
},
|
||||
"configurations": {
|
||||
"ci": {
|
||||
"ci": true,
|
||||
"coverage": true,
|
||||
"watchAll": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env node
|
||||
import chalk from 'chalk';
|
||||
import { Command, CommanderError } from 'commander';
|
||||
import { CreateAppCommand } from './create-app.command';
|
||||
import packageJson from '../package.json';
|
||||
|
||||
const program = new Command(packageJson.name)
|
||||
.description('CLI tool to initialize a new Twenty application')
|
||||
.version(
|
||||
packageJson.version,
|
||||
'-v, --version',
|
||||
'Output the current version of create-twenty-app.',
|
||||
)
|
||||
.argument('[directory]')
|
||||
.helpOption('-h, --help', 'Display this help message.')
|
||||
.action(async (directory?: string) => {
|
||||
if (directory && !/^[a-z0-9-]+$/.test(directory)) {
|
||||
console.error(
|
||||
chalk.red(
|
||||
`Invalid directory "${directory}". Must contain only lowercase letters, numbers, and hyphens`,
|
||||
),
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
await new CreateAppCommand().execute(directory);
|
||||
});
|
||||
|
||||
program.exitOverride();
|
||||
|
||||
try {
|
||||
program.parse();
|
||||
} catch (error) {
|
||||
if (error instanceof CommanderError) {
|
||||
process.exit(error.exitCode);
|
||||
}
|
||||
if (error instanceof Error) {
|
||||
console.error(chalk.red('Error:'), error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
24.5.0
|
||||
Binary file not shown.
@@ -0,0 +1,35 @@
|
||||
This is a [Twenty](https://twenty.com) application project bootstrapped with [`create-twenty-app`](https://www.npmjs.com/package/create-twenty-app).
|
||||
|
||||
## Getting Started
|
||||
|
||||
First, authenticate to your workspace:
|
||||
|
||||
```bash
|
||||
yarn auth
|
||||
```
|
||||
|
||||
Then, run the development server:
|
||||
|
||||
```bash
|
||||
yarn dev
|
||||
```
|
||||
|
||||
Open your Twenty instance and go to `/settings/applications` section to see the result.
|
||||
|
||||
You can start adding twenty entities by running
|
||||
|
||||
```bash
|
||||
yarn create-entity
|
||||
```
|
||||
|
||||
The application auto-updates as you edit the file.
|
||||
|
||||
## Learn More
|
||||
|
||||
To learn more about Twenty applications, take a look at the following resources:
|
||||
|
||||
- [twenty-sdk](https://www.npmjs.com/package/twenty-sdk) - learn about `twenty-sdk` tool.
|
||||
- [Twenty doc](https://docs.twenty.com/) - Twenty's documentation.
|
||||
- Join our [Discord](https://discord.gg/cx5n4Jzs57)
|
||||
|
||||
You can check out [the Twenty GitHub repository](https://github.com/twentyhq/twenty) - your feedback and contributions are welcome!
|
||||
@@ -0,0 +1,137 @@
|
||||
import js from '@eslint/js';
|
||||
import typescriptEslint from '@typescript-eslint/eslint-plugin';
|
||||
import typescriptParser from '@typescript-eslint/parser';
|
||||
import importPlugin from 'eslint-plugin-import';
|
||||
import preferArrowPlugin from 'eslint-plugin-prefer-arrow';
|
||||
import prettierPlugin from 'eslint-plugin-prettier';
|
||||
import unusedImportsPlugin from 'eslint-plugin-unused-imports';
|
||||
|
||||
export default [
|
||||
// Base JS rules
|
||||
js.configs.recommended,
|
||||
|
||||
// Global ignores
|
||||
{
|
||||
ignores: ['**/node_modules/**', '**/dist/**', '**/coverage/**'],
|
||||
},
|
||||
|
||||
// Base config for TS/JS files
|
||||
{
|
||||
files: ['**/*.{js,jsx,ts,tsx}'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module',
|
||||
},
|
||||
plugins: {
|
||||
prettier: prettierPlugin,
|
||||
import: importPlugin,
|
||||
'prefer-arrow': preferArrowPlugin,
|
||||
'unused-imports': unusedImportsPlugin,
|
||||
},
|
||||
rules: {
|
||||
// General rules (aligned with main project)
|
||||
'func-style': ['error', 'declaration', { allowArrowFunctions: true }],
|
||||
'no-console': [
|
||||
'warn',
|
||||
{ allow: ['group', 'groupCollapsed', 'groupEnd'] },
|
||||
],
|
||||
'no-control-regex': 0,
|
||||
'no-debugger': 'error',
|
||||
'no-duplicate-imports': 'error',
|
||||
'no-undef': 'off',
|
||||
'no-unused-vars': 'off',
|
||||
|
||||
// Import rules
|
||||
'import/no-relative-packages': 'error',
|
||||
'import/no-useless-path-segments': 'error',
|
||||
'import/no-duplicates': ['error', { considerQueryString: true }],
|
||||
|
||||
// Prefer arrow functions
|
||||
'prefer-arrow/prefer-arrow-functions': [
|
||||
'error',
|
||||
{
|
||||
disallowPrototype: true,
|
||||
singleReturnOnly: false,
|
||||
classPropertiesAllowed: false,
|
||||
},
|
||||
],
|
||||
|
||||
// Unused imports
|
||||
'unused-imports/no-unused-imports': 'warn',
|
||||
'unused-imports/no-unused-vars': [
|
||||
'warn',
|
||||
{
|
||||
vars: 'all',
|
||||
varsIgnorePattern: '^_',
|
||||
args: 'after-used',
|
||||
argsIgnorePattern: '^_',
|
||||
},
|
||||
],
|
||||
|
||||
// Prettier (formatting as lint errors if you want)
|
||||
'prettier/prettier': 'error',
|
||||
},
|
||||
},
|
||||
|
||||
// TypeScript-specific configuration
|
||||
{
|
||||
files: ['**/*.{ts,tsx}'],
|
||||
languageOptions: {
|
||||
parser: typescriptParser,
|
||||
parserOptions: {
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
'@typescript-eslint': typescriptEslint,
|
||||
},
|
||||
rules: {
|
||||
// Turn off base rule and use TS-aware versions
|
||||
'no-redeclare': 'off',
|
||||
'@typescript-eslint/no-redeclare': 'error',
|
||||
|
||||
'@typescript-eslint/ban-ts-comment': 'error',
|
||||
'@typescript-eslint/consistent-type-imports': [
|
||||
'error',
|
||||
{
|
||||
prefer: 'type-imports',
|
||||
fixStyle: 'inline-type-imports',
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
'@typescript-eslint/interface-name-prefix': 'off',
|
||||
'@typescript-eslint/no-empty-interface': [
|
||||
'error',
|
||||
{
|
||||
allowSingleExtends: true,
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
'@typescript-eslint/no-unused-vars': 'off',
|
||||
},
|
||||
},
|
||||
|
||||
// Test files (Jest)
|
||||
{
|
||||
files: ['**/*.spec.@(ts|tsx|js|jsx)', '**/*.test.@(ts|tsx|js|jsx)'],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
jest: true,
|
||||
describe: true,
|
||||
it: true,
|
||||
expect: true,
|
||||
beforeEach: true,
|
||||
afterEach: true,
|
||||
beforeAll: true,
|
||||
afterAll: true,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||
},
|
||||
},
|
||||
];
|
||||
+1
-2
@@ -11,7 +11,7 @@
|
||||
"experimentalDecorators": true,
|
||||
"importHelpers": true,
|
||||
"allowUnreachableCode": false,
|
||||
"strictNullChecks": true,
|
||||
"strict": true,
|
||||
"alwaysStrict": true,
|
||||
"noImplicitAny": true,
|
||||
"strictBindCallApply": false,
|
||||
@@ -22,6 +22,5 @@
|
||||
"skipDefaultLibCheck": true,
|
||||
"resolveJsonModule": true,
|
||||
},
|
||||
|
||||
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
|
||||
}
|
||||
+16
-8
@@ -2,11 +2,15 @@ import chalk from 'chalk';
|
||||
import * as fs from 'fs-extra';
|
||||
import inquirer from 'inquirer';
|
||||
import * as path from 'path';
|
||||
import { copyBaseApplicationProject } from '../utils/app-template';
|
||||
import { copyBaseApplicationProject } from './utils/app-template';
|
||||
import kebabCase from 'lodash.kebabcase';
|
||||
import { convertToLabel } from '../utils/convert-to-label';
|
||||
import { convertToLabel } from './utils/convert-to-label';
|
||||
import { tryGitInit } from './utils/try-git-init';
|
||||
import { install } from './utils/install';
|
||||
|
||||
export class AppInitCommand {
|
||||
const CURRENT_EXECUTION_DIRECTORY = process.env.INIT_CWD || process.cwd();
|
||||
|
||||
export class CreateAppCommand {
|
||||
async execute(directory?: string): Promise<void> {
|
||||
try {
|
||||
const { appName, appDisplayName, appDirectory, appDescription } =
|
||||
@@ -25,6 +29,10 @@ export class AppInitCommand {
|
||||
appDirectory,
|
||||
});
|
||||
|
||||
await install(appDirectory);
|
||||
|
||||
await tryGitInit(appDirectory);
|
||||
|
||||
this.logSuccess(appDirectory);
|
||||
} catch (error) {
|
||||
console.error(
|
||||
@@ -78,8 +86,8 @@ export class AppInitCommand {
|
||||
const appDescription = description.trim();
|
||||
|
||||
const appDirectory = directory
|
||||
? path.join(process.cwd(), kebabCase(directory))
|
||||
: path.join(process.cwd(), kebabCase(appName));
|
||||
? path.join(CURRENT_EXECUTION_DIRECTORY, directory)
|
||||
: path.join(CURRENT_EXECUTION_DIRECTORY, kebabCase(appName));
|
||||
|
||||
return { appName, appDisplayName, appDirectory, appDescription };
|
||||
}
|
||||
@@ -111,10 +119,10 @@ export class AppInitCommand {
|
||||
}
|
||||
|
||||
private logSuccess(appDirectory: string): void {
|
||||
console.log(chalk.green('✅ Application created successfully!'));
|
||||
console.log(chalk.green('✅ Application created!'));
|
||||
console.log('');
|
||||
console.log(chalk.blue('Next steps:'));
|
||||
console.log(` cd ${appDirectory}`);
|
||||
console.log(' twenty app dev');
|
||||
console.log(`cd ${appDirectory.split('/').reverse()[0] ?? ''}`);
|
||||
console.log('yarn auth');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
import * as fs from 'fs-extra';
|
||||
import { join } from 'path';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
export const copyBaseApplicationProject = async ({
|
||||
appName,
|
||||
appDisplayName,
|
||||
appDescription,
|
||||
appDirectory,
|
||||
}: {
|
||||
appName: string;
|
||||
appDisplayName: string;
|
||||
appDescription: string;
|
||||
appDirectory: string;
|
||||
}) => {
|
||||
await fs.copy(join(__dirname, './constants/base-application'), appDirectory);
|
||||
|
||||
await createPackageJson({ appName, appDirectory });
|
||||
|
||||
await createGitignore(appDirectory);
|
||||
|
||||
await createYarnLock(appDirectory);
|
||||
|
||||
await createApplicationConfig({
|
||||
displayName: appDisplayName,
|
||||
description: appDescription,
|
||||
appDirectory,
|
||||
});
|
||||
};
|
||||
|
||||
const createYarnLock = async (appDirectory: string) => {
|
||||
const yarnLockContent = `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
`;
|
||||
|
||||
await fs.writeFile(join(appDirectory, 'yarn.lock'), yarnLockContent);
|
||||
};
|
||||
const createGitignore = async (appDirectory: string) => {
|
||||
const gitignoreContent = `# 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/
|
||||
|
||||
# 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
|
||||
`;
|
||||
|
||||
await fs.writeFile(join(appDirectory, '.gitignore'), gitignoreContent);
|
||||
};
|
||||
|
||||
const createApplicationConfig = async ({
|
||||
displayName,
|
||||
description,
|
||||
appDirectory,
|
||||
}: {
|
||||
displayName: string;
|
||||
description?: string;
|
||||
appDirectory: string;
|
||||
}) => {
|
||||
const content = `import { type ApplicationConfig } from 'twenty-sdk';
|
||||
|
||||
const config: ApplicationConfig = {
|
||||
universalIdentifier: '${v4()}',
|
||||
displayName: '${displayName}',
|
||||
description: '${description ?? ''}',
|
||||
};
|
||||
|
||||
export default config;
|
||||
`;
|
||||
|
||||
await fs.writeFile(join(appDirectory, 'application.config.ts'), content);
|
||||
};
|
||||
|
||||
const createPackageJson = async ({
|
||||
appName,
|
||||
appDirectory,
|
||||
}: {
|
||||
appName: string;
|
||||
appDirectory: string;
|
||||
}) => {
|
||||
const packageJson = {
|
||||
name: appName,
|
||||
version: '0.1.0',
|
||||
license: 'MIT',
|
||||
engines: {
|
||||
node: '^24.5.0',
|
||||
npm: 'please-use-yarn',
|
||||
yarn: '>=4.0.2',
|
||||
},
|
||||
packageManager: 'yarn@4.9.2',
|
||||
scripts: {
|
||||
'create-entity': 'twenty app add',
|
||||
dev: 'twenty app dev',
|
||||
generate: 'twenty app generate',
|
||||
sync: 'twenty app sync',
|
||||
uninstall: 'twenty app uninstall',
|
||||
auth: 'twenty auth login',
|
||||
},
|
||||
dependencies: {
|
||||
'twenty-sdk': '0.1.2',
|
||||
},
|
||||
devDependencies: {
|
||||
'@types/node': '^24.7.2',
|
||||
typescript: '^5.9.3',
|
||||
},
|
||||
};
|
||||
|
||||
await fs.writeFile(
|
||||
join(appDirectory, 'package.json'),
|
||||
JSON.stringify(packageJson, null, 2),
|
||||
'utf8',
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
import chalk from 'chalk';
|
||||
import { promisify } from 'util';
|
||||
import { exec } from 'child_process';
|
||||
|
||||
const execPromise = promisify(exec);
|
||||
|
||||
export const install = async (root: string) => {
|
||||
try {
|
||||
await execPromise('yarn', { cwd: root });
|
||||
} catch (error: any) {
|
||||
console.error(chalk.red('yarn install failed:'), error.stdout);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,70 @@
|
||||
import * as fs from 'fs-extra';
|
||||
import { join } from 'path';
|
||||
import { promisify } from 'util';
|
||||
import { exec } from 'child_process';
|
||||
|
||||
const execPromise = promisify(exec);
|
||||
|
||||
const isInGitRepository = async (root: string): Promise<boolean> => {
|
||||
try {
|
||||
await execPromise('git rev-parse --is-inside-work-tree', { cwd: root });
|
||||
return true;
|
||||
} catch {
|
||||
// Empty catch block
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const isInMercurialRepository = async (root: string): Promise<boolean> => {
|
||||
try {
|
||||
await execPromise('hg --cwd . root', { cwd: root });
|
||||
return true;
|
||||
} catch {
|
||||
// Empty catch block
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const isDefaultBranchSet = async (root: string): Promise<boolean> => {
|
||||
try {
|
||||
await execPromise('git config init.defaultBranch', { cwd: root });
|
||||
return true;
|
||||
} catch {
|
||||
// Empty catch block
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
export const tryGitInit = async (root: string): Promise<boolean> => {
|
||||
try {
|
||||
await execPromise('git --version', { cwd: root });
|
||||
|
||||
if (
|
||||
(await isInGitRepository(root)) ||
|
||||
(await isInMercurialRepository(root))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
await execPromise('git init', { cwd: root });
|
||||
|
||||
try {
|
||||
if (!(await isDefaultBranchSet(root))) {
|
||||
await execPromise('git checkout -b main', { cwd: root });
|
||||
}
|
||||
|
||||
await execPromise('git add -A', { cwd: root });
|
||||
await execPromise(
|
||||
'git commit -m "Initial commit from Create Twenty App"',
|
||||
{
|
||||
cwd: root,
|
||||
},
|
||||
);
|
||||
return true;
|
||||
} catch {
|
||||
fs.rm(join(root, '.git'), { recursive: true, force: true });
|
||||
return false;
|
||||
}
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"allowJs": false,
|
||||
"esModuleInterop": false,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strictNullChecks": true,
|
||||
"alwaysStrict": true,
|
||||
"noImplicitAny": true,
|
||||
"strictBindCallApply": false,
|
||||
"noEmit": true,
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
}
|
||||
],
|
||||
"extends": "../../tsconfig.base.json"
|
||||
}
|
||||
+11
-9
@@ -1,21 +1,23 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"module": "commonjs",
|
||||
"target": "ES2022",
|
||||
"moduleResolution": "node",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"skipLibCheck": true,
|
||||
"resolveJsonModule": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"declaration": false,
|
||||
"sourceMap": true
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts", "**/*.e2e-spec.ts", "**/__tests__/**"]
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist",
|
||||
"**/*.test.ts",
|
||||
"**/*.spec.ts",
|
||||
"**/__tests__/**"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"types": ["jest", "node"]
|
||||
},
|
||||
"include": [
|
||||
"**/__mocks__/**/*",
|
||||
"vite.config.ts",
|
||||
"jest.config.mjs",
|
||||
"src/**/*.d.ts",
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.spec.tsx",
|
||||
"src/**/*.test.ts",
|
||||
"src/**/*.test.tsx"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
import { defineConfig } from 'vite';
|
||||
import dts from 'vite-plugin-dts';
|
||||
import tsconfigPaths from 'vite-tsconfig-paths';
|
||||
import packageJson from './package.json';
|
||||
|
||||
const moduleEntries = Object.keys((packageJson as any).exports || {})
|
||||
.filter(
|
||||
(key) => key !== './style.css' && key !== '.' && !key.startsWith('./src/'),
|
||||
)
|
||||
.map((module) => `src/${module.replace(/^\.\//, '')}/index.ts`);
|
||||
|
||||
const entries = ['src/cli.ts', ...moduleEntries];
|
||||
|
||||
const entryFileNames = (chunk: any, extension: 'cjs' | 'mjs') => {
|
||||
if (!chunk.isEntry) {
|
||||
throw new Error(
|
||||
`Should never occurs, encountered a non entry chunk ${chunk.facadeModuleId}`,
|
||||
);
|
||||
}
|
||||
|
||||
const splitFaceModuleId = chunk.facadeModuleId?.split('/');
|
||||
if (splitFaceModuleId === undefined) {
|
||||
throw new Error(
|
||||
`Should never occurs splitFaceModuleId is undefined ${chunk.facadeModuleId}`,
|
||||
);
|
||||
}
|
||||
|
||||
const moduleDirectory = splitFaceModuleId[splitFaceModuleId?.length - 2];
|
||||
if (moduleDirectory === 'src') {
|
||||
return `${chunk.name}.${extension}`;
|
||||
}
|
||||
return `${moduleDirectory}.${extension}`;
|
||||
};
|
||||
|
||||
const copyAssetPlugin = (targets: { src: string; dest: string }[]) => {
|
||||
return {
|
||||
name: 'copy-assets',
|
||||
closeBundle: async () => {
|
||||
for (const target of targets) {
|
||||
await fs.copy(
|
||||
path.resolve(__dirname, target.src),
|
||||
path.resolve(__dirname, target.dest),
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default defineConfig(() => {
|
||||
const tsConfigPath = path.resolve(__dirname, './tsconfig.lib.json');
|
||||
|
||||
return {
|
||||
root: __dirname,
|
||||
cacheDir: '../../node_modules/.vite/packages/create-twenty-app',
|
||||
plugins: [
|
||||
tsconfigPaths({
|
||||
root: __dirname,
|
||||
}),
|
||||
dts({ entryRoot: './src', tsconfigPath: tsConfigPath }),
|
||||
copyAssetPlugin([
|
||||
{
|
||||
src: 'src/constants/base-application',
|
||||
dest: 'dist/constants/base-application',
|
||||
},
|
||||
]),
|
||||
],
|
||||
build: {
|
||||
outDir: 'dist',
|
||||
lib: { entry: entries, name: 'create-twenty-app' },
|
||||
rollupOptions: {
|
||||
external: [
|
||||
...Object.keys((packageJson as any).dependencies || {}),
|
||||
'path',
|
||||
'fs',
|
||||
'child_process',
|
||||
],
|
||||
output: [
|
||||
{
|
||||
format: 'es',
|
||||
entryFileNames: (chunk) => entryFileNames(chunk, 'mjs'),
|
||||
},
|
||||
{
|
||||
format: 'cjs',
|
||||
interop: 'auto',
|
||||
esModule: true,
|
||||
exports: 'named',
|
||||
entryFileNames: (chunk) => entryFileNames(chunk, 'cjs'),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
logLevel: 'warn',
|
||||
};
|
||||
});
|
||||
@@ -2056,8 +2056,8 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"glob@npm:^10.2.2":
|
||||
version: 10.4.5
|
||||
resolution: "glob@npm:10.4.5"
|
||||
version: 10.5.0
|
||||
resolution: "glob@npm:10.5.0"
|
||||
dependencies:
|
||||
foreground-child: "npm:^3.1.0"
|
||||
jackspeak: "npm:^3.1.2"
|
||||
@@ -2067,7 +2067,7 @@ __metadata:
|
||||
path-scurry: "npm:^1.11.1"
|
||||
bin:
|
||||
glob: dist/esm/bin.mjs
|
||||
checksum: 10c0/19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e
|
||||
checksum: 10c0/100705eddbde6323e7b35e1d1ac28bcb58322095bd8e63a7d0bef1a2cdafe0d0f7922a981b2b48369a4f8c1b077be5c171804534c3509dfe950dde15fbe6d828
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
@@ -239,6 +239,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/node@npm:^24.7.2":
|
||||
version: 24.10.1
|
||||
resolution: "@types/node@npm:24.10.1"
|
||||
dependencies:
|
||||
undici-types: "npm:~7.16.0"
|
||||
checksum: 10c0/d6bca7a78f550fbb376f236f92b405d676003a8a09a1b411f55920ef34286ee3ee51f566203920e835478784df52662b5b2af89159d9d319352e9ea21801c002
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"abbrev@npm:^3.0.0":
|
||||
version: 3.0.1
|
||||
resolution: "abbrev@npm:3.0.1"
|
||||
@@ -572,8 +581,8 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"glob@npm:^10.2.2":
|
||||
version: 10.4.5
|
||||
resolution: "glob@npm:10.4.5"
|
||||
version: 10.5.0
|
||||
resolution: "glob@npm:10.5.0"
|
||||
dependencies:
|
||||
foreground-child: "npm:^3.1.0"
|
||||
jackspeak: "npm:^3.1.2"
|
||||
@@ -583,7 +592,7 @@ __metadata:
|
||||
path-scurry: "npm:^1.11.1"
|
||||
bin:
|
||||
glob: dist/esm/bin.mjs
|
||||
checksum: 10c0/19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e
|
||||
checksum: 10c0/100705eddbde6323e7b35e1d1ac28bcb58322095bd8e63a7d0bef1a2cdafe0d0f7922a981b2b48369a4f8c1b077be5c171804534c3509dfe950dde15fbe6d828
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -907,8 +916,10 @@ __metadata:
|
||||
version: 0.0.0-use.local
|
||||
resolution: "rollup-engine@workspace:."
|
||||
dependencies:
|
||||
"@types/node": "npm:^24.7.2"
|
||||
dotenv: "npm:^16.4.5"
|
||||
tsx: "npm:^4.20.6"
|
||||
twenty-sdk: "npm:0.0.3"
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
@@ -1067,6 +1078,20 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"twenty-sdk@npm:0.0.3":
|
||||
version: 0.0.3
|
||||
resolution: "twenty-sdk@npm:0.0.3"
|
||||
checksum: 10c0/0a3c85c27edb22fb50f7eb0da4f9770e85729fce05e9e0118ad0cdfc36e42425c93340a6cd1c276daf30aeeaa612db0cd905831c0a8287a31bff3da5be9b0562
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"undici-types@npm:~7.16.0":
|
||||
version: 7.16.0
|
||||
resolution: "undici-types@npm:7.16.0"
|
||||
checksum: 10c0/3033e2f2b5c9f1504bdc5934646cb54e37ecaca0f9249c983f7b1fc2e87c6d18399ebb05dc7fd5419e02b2e915f734d872a65da2e3eeed1813951c427d33cc9a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"unique-filename@npm:^4.0.0":
|
||||
version: 4.0.0
|
||||
resolution: "unique-filename@npm:4.0.0"
|
||||
|
||||
@@ -50,7 +50,7 @@ const returnWorkspaceMemberObjectId = async (): Promise<string> => {
|
||||
).id;
|
||||
};
|
||||
|
||||
const createUpdatedByField = async (
|
||||
const createUpdatedByFieldMetadata = async (
|
||||
sourceObjectId: string,
|
||||
workspaceMemberObjectId: string,
|
||||
objectName: string,
|
||||
@@ -124,7 +124,7 @@ const createUpdatedByField = async (
|
||||
}
|
||||
};
|
||||
|
||||
const updateUpdatedByField = async (
|
||||
const updateUpdatedByFieldValue = async (
|
||||
objectName: string,
|
||||
workspaceMemberId: string,
|
||||
recordId: string,
|
||||
@@ -184,7 +184,7 @@ export const main = async (params: {
|
||||
const workspaceMemberObjectId: string =
|
||||
await returnWorkspaceMemberObjectId();
|
||||
|
||||
const isFieldCreated: boolean | undefined = await createUpdatedByField(
|
||||
const isFieldCreated: boolean | undefined = await createUpdatedByFieldMetadata(
|
||||
objectMetadata.id,
|
||||
workspaceMemberObjectId,
|
||||
objectMetadata.namePlural,
|
||||
@@ -198,7 +198,7 @@ export const main = async (params: {
|
||||
}
|
||||
}
|
||||
|
||||
const isObjectUpdated: boolean | undefined = await updateUpdatedByField(
|
||||
const isObjectUpdated: boolean | undefined = await updateUpdatedByFieldValue(
|
||||
objectMetadata.namePlural,
|
||||
workspaceMemberId,
|
||||
recordId,
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
# Why Twenty CLI?
|
||||
# Deprecated: twenty-cli
|
||||
|
||||
A command-line interface to easily scaffold, develop, and publish applications that extend Twenty CRM
|
||||
|
||||
## Installation
|
||||
This package is deprecated. Please install and use twenty-sdk instead:
|
||||
|
||||
```bash
|
||||
npm install -g twenty-cli
|
||||
npm uninstall twenty-cli
|
||||
npm install -g twenty-sdk
|
||||
```
|
||||
|
||||
The command name remains the same: twenty.
|
||||
|
||||
A command-line interface to easily scaffold, develop, and publish applications that extend Twenty CRM (now provided by twenty-sdk).
|
||||
|
||||
## Requirements
|
||||
- yarn >= 4.9.2
|
||||
- an `apiKey`. Go to `https://twenty.com/settings/api-webhooks` to generate one
|
||||
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env node
|
||||
const message = `\nTwenty CLI (twenty-cli) is deprecated.\n\nPlease install and use the new package instead:\n npm install -g twenty-sdk\n\nThe command name remains the same: \"twenty\".\nMore info: https://www.npmjs.com/package/twenty-sdk\n`;
|
||||
|
||||
console.error(message);
|
||||
process.exitCode = 1;
|
||||
@@ -1,64 +1,10 @@
|
||||
{
|
||||
"name": "twenty-cli",
|
||||
"version": "0.2.4",
|
||||
"description": "Command-line interface for Twenty application development",
|
||||
"main": "dist/cli.js",
|
||||
"bin": {
|
||||
"twenty": "dist/cli.js"
|
||||
},
|
||||
"files": [
|
||||
"dist/**/*",
|
||||
"!dist/**/*.e2e-spec.*",
|
||||
"!dist/**/__tests__/**"
|
||||
],
|
||||
"version": "0.3.0",
|
||||
"description": "[DEPRECATED] Use twenty-sdk instead: https://www.npmjs.com/package/twenty-sdk",
|
||||
"scripts": {
|
||||
"build": "echo 'use npx nx build'",
|
||||
"dev": "tsx src/cli.ts",
|
||||
"start": "node dist/cli.js"
|
||||
"start": "echo 'deprecated'"
|
||||
},
|
||||
"keywords": [
|
||||
"twenty",
|
||||
"cli",
|
||||
"crm",
|
||||
"application",
|
||||
"development"
|
||||
],
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
"@genql/cli": "^3.0.3",
|
||||
"ajv": "^8.12.0",
|
||||
"ajv-formats": "^2.1.1",
|
||||
"axios": "^1.6.0",
|
||||
"chalk": "^5.3.0",
|
||||
"chokidar": "^4.0.0",
|
||||
"commander": "^12.0.0",
|
||||
"dotenv": "^16.4.0",
|
||||
"fs-extra": "^11.2.0",
|
||||
"graphql": "^16.8.1",
|
||||
"inquirer": "^10.0.0",
|
||||
"jsonc-parser": "^3.2.0",
|
||||
"lodash.camelcase": "^4.3.0",
|
||||
"lodash.capitalize": "^4.2.1",
|
||||
"lodash.kebabcase": "^4.1.1",
|
||||
"lodash.startcase": "^4.4.0",
|
||||
"typescript": "^5.9.2",
|
||||
"uuid": "^13.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "^11.0.0",
|
||||
"@types/inquirer": "^9.0.0",
|
||||
"@types/jest": "^29.5.0",
|
||||
"@types/lodash.camelcase": "^4.3.7",
|
||||
"@types/lodash.capitalize": "^4",
|
||||
"@types/lodash.kebabcase": "^4.1.7",
|
||||
"@types/lodash.startcase": "^4",
|
||||
"@types/node": "^20.0.0",
|
||||
"jest": "^29.5.0",
|
||||
"tsx": "^4.7.0",
|
||||
"wait-on": "^7.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^24.5.0",
|
||||
"yarn": "^4.0.2"
|
||||
}
|
||||
"license": "AGPL-3.0"
|
||||
}
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
{
|
||||
"name": "twenty-cli",
|
||||
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||
"projectType": "application",
|
||||
"tags": ["scope:cli"],
|
||||
"targets": {
|
||||
"before-build": {
|
||||
"executor": "nx:run-commands",
|
||||
"cache": true,
|
||||
"options": {
|
||||
"cwd": "packages/twenty-cli",
|
||||
"commands": ["rimraf dist", "tsc --project tsconfig.lib.json"]
|
||||
},
|
||||
"dependsOn": ["^build", "typecheck"]
|
||||
},
|
||||
"build": {
|
||||
"executor": "nx:run-commands",
|
||||
"cache": true,
|
||||
"options": {
|
||||
"cwd": "packages/twenty-cli",
|
||||
"commands": [
|
||||
"cp -R src/constants/base-application-project dist/constants"
|
||||
]
|
||||
},
|
||||
"dependsOn": ["before-build"]
|
||||
},
|
||||
"dev": {
|
||||
"executor": "nx:run-commands",
|
||||
"dependsOn": ["build"],
|
||||
"options": {
|
||||
"cwd": "packages/twenty-cli",
|
||||
"command": "tsx src/cli.ts"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"executor": "nx:run-commands",
|
||||
"dependsOn": ["build"],
|
||||
"options": {
|
||||
"cwd": "packages/twenty-cli",
|
||||
"command": "node dist/cli.js"
|
||||
}
|
||||
},
|
||||
"typecheck": {},
|
||||
"lint": {
|
||||
"options": {
|
||||
"lintFilePatterns": ["{projectRoot}/src/**/*.{ts,json}"],
|
||||
"maxWarnings": 0
|
||||
},
|
||||
"configurations": {
|
||||
"ci": {
|
||||
"lintFilePatterns": ["{projectRoot}/src/**/*.{ts,json}"],
|
||||
"maxWarnings": 0
|
||||
},
|
||||
"fix": {}
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"executor": "@nx/jest:jest",
|
||||
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
|
||||
"options": {
|
||||
"jestConfig": "{projectRoot}/jest.config.mjs"
|
||||
},
|
||||
"configurations": {
|
||||
"ci": {
|
||||
"ci": true,
|
||||
"coverage": true,
|
||||
"watchAll": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"test:e2e": {
|
||||
"executor": "nx:run-commands",
|
||||
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
|
||||
"options": {
|
||||
"cwd": "packages/twenty-cli",
|
||||
"commands": [
|
||||
"npx wait-on http://localhost:3000/healthz --timeout 600000 --interval 1000 --log && NODE_ENV=test npx jest --config ./jest.e2e.config.ts"
|
||||
]
|
||||
},
|
||||
"parallel": false,
|
||||
"dependsOn": [
|
||||
"build",
|
||||
{
|
||||
"target": "database:reset",
|
||||
"projects": "twenty-server"
|
||||
},
|
||||
{
|
||||
"target": "start:ci-if-needed",
|
||||
"projects": "twenty-server"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
# Set environment values for your application here.
|
||||
# Use the format: KEY=value
|
||||
#
|
||||
# These variables are automatically loaded when running your serverless functions.
|
||||
# You can access them directly in your code using:
|
||||
# const myValue = process.env.KEY;
|
||||
#
|
||||
# To make these variables available to your application, add them in application.config.ts file
|
||||
#
|
||||
# const config: ApplicationConfig = {
|
||||
# ...
|
||||
# applicationVariables: {
|
||||
# KEY: {
|
||||
# universalIdentifier: 'dedc53eb-9c12-4fe2-ba86-4a2add19d305',
|
||||
# description: 'Description',
|
||||
# isSecret: true,
|
||||
# },
|
||||
# },
|
||||
# };
|
||||
#
|
||||
# Those environment variables will be provided to your serverless
|
||||
# functions at runtime.
|
||||
#
|
||||
# Example:
|
||||
# API_TOKEN=your-api-token
|
||||
# TIMEOUT_MS=3000
|
||||
@@ -1,5 +0,0 @@
|
||||
# Duplicated with ./gitignore because npm publish does not include .gitignore
|
||||
# https://github.com/npm/npm/issues/3763
|
||||
|
||||
.yarn/install-state.gz
|
||||
.env
|
||||
Binary file not shown.
@@ -1,15 +0,0 @@
|
||||
# {title}
|
||||
|
||||
{description}
|
||||
|
||||
## Requirements
|
||||
- twenty-cli `npm install -g twenty-cli`
|
||||
- an `apiKey`. Go to `https://twenty.com/settings/api-webhooks` to generate one
|
||||
|
||||
|
||||
## Install to your Twenty workspace
|
||||
|
||||
```bash
|
||||
twenty auth login
|
||||
twenty app sync
|
||||
```
|
||||
@@ -1,2 +0,0 @@
|
||||
.yarn/install-state.gz
|
||||
.env
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"name": "my-application",
|
||||
"version": "0.0.1",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^24.5.0",
|
||||
"npm": "please-use-yarn",
|
||||
"yarn": ">=4.0.2"
|
||||
},
|
||||
"packageManager": "yarn@4.9.2",
|
||||
"dependencies": {
|
||||
"twenty-sdk": "0.0.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^24.7.2"
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
# This file is generated by running "yarn install" inside your project.
|
||||
# Manual changes might be lost - proceed with caution!
|
||||
|
||||
__metadata:
|
||||
version: 8
|
||||
cacheKey: 10c0
|
||||
|
||||
"@types/node@npm:^24.7.2":
|
||||
version: 24.9.1
|
||||
resolution: "@types/node@npm:24.9.1"
|
||||
dependencies:
|
||||
undici-types: "npm:~7.16.0"
|
||||
checksum: 10c0/c52f8168080ef9a7c3dc23d8ac6061fab5371aad89231a0f6f4c075869bc3de7e89b075b1f3e3171d9e5143d0dda1807c3dab8e32eac6d68f02e7480e7e78576
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"root-workspace-0b6124@workspace:.":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "root-workspace-0b6124@workspace:."
|
||||
dependencies:
|
||||
"@types/node": "npm:^24.7.2"
|
||||
twenty-sdk: "npm:^0.0.2"
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"twenty-sdk@npm:^0.0.2":
|
||||
version: 0.0.2
|
||||
resolution: "twenty-sdk@npm:0.0.2"
|
||||
checksum: 10c0/99e6fe86059d847b548c1f03e0f0c59a4d540caf1d28dd4500f1f5f0094196985ded955801274de9e72ff03e3d1f41e9a509b4c2c5a02ffc8a027277b1e35d8e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"undici-types@npm:~7.16.0":
|
||||
version: 7.16.0
|
||||
resolution: "undici-types@npm:7.16.0"
|
||||
checksum: 10c0/3033e2f2b5c9f1504bdc5934646cb54e37ecaca0f9249c983f7b1fc2e87c6d18399ebb05dc7fd5419e02b2e915f734d872a65da2e3eeed1813951c427d33cc9a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
@@ -1,8 +0,0 @@
|
||||
import { join } from 'path';
|
||||
|
||||
const BASE_PATH = join(__dirname, '../constants');
|
||||
|
||||
export const BASE_APPLICATION_PROJECT_PATH = join(
|
||||
BASE_PATH,
|
||||
'base-application-project',
|
||||
);
|
||||
@@ -1,107 +0,0 @@
|
||||
import * as fs from 'fs-extra';
|
||||
import { BASE_APPLICATION_PROJECT_PATH } from '../constants/constants-path';
|
||||
import { writeJsoncFile } from '../utils/jsonc-parser';
|
||||
import { join } from 'path';
|
||||
import path from 'path';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
export const copyBaseApplicationProject = async ({
|
||||
appName,
|
||||
appDisplayName,
|
||||
appDescription,
|
||||
appDirectory,
|
||||
}: {
|
||||
appName: string;
|
||||
appDisplayName: string;
|
||||
appDescription: string;
|
||||
appDirectory: string;
|
||||
}) => {
|
||||
await fs.copy(BASE_APPLICATION_PROJECT_PATH, appDirectory);
|
||||
|
||||
await fs.rename(
|
||||
join(appDirectory, 'gitignore'),
|
||||
join(appDirectory, '.gitignore'),
|
||||
);
|
||||
|
||||
await fs.copy(join(appDirectory, '.env.example'), join(appDirectory, '.env'));
|
||||
|
||||
await createBasePackageJson({
|
||||
appName,
|
||||
appDirectory,
|
||||
});
|
||||
|
||||
await createApplicationConfig({
|
||||
displayName: appDisplayName,
|
||||
description: appDescription,
|
||||
appDirectory,
|
||||
});
|
||||
|
||||
await createReadmeContent({
|
||||
displayName: appDisplayName,
|
||||
appDescription,
|
||||
appDirectory,
|
||||
});
|
||||
};
|
||||
|
||||
const createApplicationConfig = async ({
|
||||
displayName,
|
||||
description,
|
||||
appDirectory,
|
||||
}: {
|
||||
displayName: string;
|
||||
description?: string;
|
||||
appDirectory: string;
|
||||
}) => {
|
||||
const content = `import { type ApplicationConfig } from 'twenty-sdk/application';
|
||||
|
||||
const config: ApplicationConfig = {
|
||||
universalIdentifier: '${v4()}',
|
||||
displayName: '${displayName}',
|
||||
description: '${description ?? ''}',
|
||||
};
|
||||
|
||||
export default config;
|
||||
`;
|
||||
|
||||
await fs.writeFile(path.join(appDirectory, 'application.config.ts'), content);
|
||||
};
|
||||
|
||||
const createBasePackageJson = async ({
|
||||
appName,
|
||||
appDirectory,
|
||||
}: {
|
||||
appName: string;
|
||||
appDirectory: string;
|
||||
}) => {
|
||||
const base = JSON.parse(await readBaseApplicationProjectFile('package.json'));
|
||||
|
||||
base['universalIdentifier'] = v4();
|
||||
base['name'] = appName;
|
||||
|
||||
await writeJsoncFile(join(appDirectory, 'package.json'), base);
|
||||
};
|
||||
|
||||
const createReadmeContent = async ({
|
||||
displayName,
|
||||
appDescription,
|
||||
appDirectory,
|
||||
}: {
|
||||
displayName: string;
|
||||
appDescription: string;
|
||||
appDirectory: string;
|
||||
}) => {
|
||||
let readmeContent = await readBaseApplicationProjectFile('README.md');
|
||||
|
||||
readmeContent = readmeContent.replace(/\{title}/g, displayName);
|
||||
|
||||
readmeContent = readmeContent.replace(/\{description}/g, appDescription);
|
||||
|
||||
await fs.writeFile(path.join(appDirectory, 'README.md'), readmeContent);
|
||||
};
|
||||
|
||||
const readBaseApplicationProjectFile = async (fileName: string) => {
|
||||
return await fs.readFile(
|
||||
join(BASE_APPLICATION_PROJECT_PATH, fileName),
|
||||
'utf-8',
|
||||
);
|
||||
};
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"extends": "./tsconfig.lib.json",
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts", "**/*.e2e-spec.ts", "**/__tests__/**"]
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"types": ["jest", "node"]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*",
|
||||
"src/**/__tests__/**/*.spec.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist",
|
||||
]
|
||||
}
|
||||
@@ -39,6 +39,12 @@ Deploy Twenty on Railway with the community maintained template below.
|
||||
|
||||
[](https://railway.com/deploy/nAL3hA)
|
||||
|
||||
### Twenty on Sealos
|
||||
|
||||
Deploy Twenty on Sealos with the community maintained template below.
|
||||
|
||||
[](https://sealos.io/products/app-store/twenty)
|
||||
|
||||
## Others
|
||||
|
||||
Please feel free to Open a PR to add more Cloud Provider options.
|
||||
|
||||
@@ -39,6 +39,12 @@ crwdns60692:0crwdne60692:0
|
||||
|
||||
crwdns60694:0https://railway.com/button.svgcrwdnd60694:0https://railway.com/deploy/nAL3hAcrwdne60694:0
|
||||
|
||||
### crwdns64878:0crwdne64878:0
|
||||
|
||||
crwdns64880:0crwdne64880:0
|
||||
|
||||
crwdns64882:0https://sealos.io/Deploy-on-Sealos.svgcrwdnd64882:0https://sealos.io/products/app-store/twentycrwdne64882:0
|
||||
|
||||
## crwdns60696:0crwdne60696:0
|
||||
|
||||
crwdns60698:0crwdne60698:0
|
||||
|
||||
@@ -39,6 +39,12 @@ Stel Twenty op Railway in met die gemeenskap-onderhoudene sjabloon hieronder.
|
||||
|
||||
[](https://railway.com/deploy/nAL3hA)
|
||||
|
||||
### Ander
|
||||
|
||||
Stel Twenty op Sealos in met die deur die gemeenskap onderhoue sjabloon hieronder.
|
||||
|
||||
[](https://sealos.io/products/app-store/twenty)
|
||||
|
||||
## Ander
|
||||
|
||||
Voel vry om 'n PR te open om meer Wolkverskaffer opsies by te voeg.
|
||||
|
||||
@@ -57,7 +57,7 @@ sectionInfo: أتمتة العمليات والاندماج مع الأدوات
|
||||
|
||||
**المشكلة**: الوصول إلى حد 100 سير عمل متزامن لكل مساحة عمل.
|
||||
|
||||
<Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning>لا يمكنك تشغيل أكثر من 100 سير عمل بالتوازي في أي وقت لكل مساحة عمل.</Warning></Warning>
|
||||
<Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning>لا يمكنك تشغيل أكثر من 100 سير عمل بالتوازي في أي وقت لكل مساحة عمل.</Warning></Warning>
|
||||
|
||||
**حلول**:
|
||||
|
||||
|
||||
@@ -39,6 +39,12 @@ Nasazení Twenty na Railway s komunitně udržovanou šablonou níže.
|
||||
|
||||
[](https://railway.com/deploy/nAL3hA)
|
||||
|
||||
### Ostatní
|
||||
|
||||
Nasazení Twenty na Sealos s komunitně udržovanou šablonou níže.
|
||||
|
||||
[](https://sealos.io/products/app-store/twenty)
|
||||
|
||||
## Ostatní
|
||||
|
||||
Neváhejte otevřít PR pro přidání dalších možností poskytovatele cloudových služeb.
|
||||
|
||||
@@ -39,6 +39,12 @@ Implementer Twenty på Railway med den fællesskabsvedligeholdte skabelon nedenf
|
||||
|
||||
[](https://railway.com/deploy/nAL3hA)
|
||||
|
||||
### Twenty på Sealos
|
||||
|
||||
Implementer Twenty på Sealos med den fællesskabsvedligeholdte skabelon nedenfor.
|
||||
|
||||
[](https://sealos.io/products/app-store/twenty)
|
||||
|
||||
## Andre
|
||||
|
||||
Du er velkommen til at åbne en PR for at tilføje flere Cloud Provider-muligheder.
|
||||
|
||||
@@ -39,6 +39,12 @@ image: /images/user-guide/notes/notes_header.png
|
||||
|
||||
[](https://railway.com/deploy/nAL3hA)
|
||||
|
||||
### Twenty στο Sealos
|
||||
|
||||
Αναπτύξτε το Twenty στο Sealos με το υποστηριζόμενο από την κοινότητα πρότυπο παρακάτω.
|
||||
|
||||
[](https://sealos.io/products/app-store/twenty)
|
||||
|
||||
## Άλλες επιλογές
|
||||
|
||||
Παρακαλώ μη διστάσετε να ανοίξετε ένα PR για να προσθέσετε περισσότερες επιλογές Παρόχου Cloud.
|
||||
|
||||
@@ -18,7 +18,7 @@ Absolutamente. Puedes crear un nuevo espacio de trabajo haciendo clic en el men
|
||||
|
||||
<Accordion title="I accidentally created multiple workspaces but only need one. What should I do?"><Accordion title="How do I change my workspace appearance and regional settings?">Ve a `Configuración → Experiencia` para personalizar:
|
||||
|
||||
<Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning>No elimines tu cuenta (accesible en Configuración → Configuración de perfil): tu cuenta se comparte entre los diferentes espacios de trabajo.</Warning></Warning>
|
||||
<Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning>No elimines tu cuenta (accesible en Configuración → Configuración de perfil): tu cuenta se comparte entre los diferentes espacios de trabajo.</Warning></Warning>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="How can I disable my workspace?"><Accordion title="How can I disable my workspace?"><Accordion title="How can I disable my workspace?"><Accordion title="How can I disable my workspace?"><Accordion title="How can I disable my workspace?">Si solo deseas desactivar tu espacio de trabajo (no eliminarlo), ve a `Configuración → Facturación` y haz clic en `Cancelar plan`.</Accordion></Accordion>
|
||||
|
||||
@@ -57,7 +57,7 @@ Los formularios están diseñados actualmente solo para disparadores manuales. P
|
||||
|
||||
**Problema**: Se alcanza el límite de 100 flujos de trabajo concurrentes por espacio de trabajo.
|
||||
|
||||
<Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning>No puedes ejecutar más de 100 flujos de trabajo en paralelo en cualquier momento por espacio de trabajo.</Warning></Warning>
|
||||
<Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning>No puedes ejecutar más de 100 flujos de trabajo en paralelo en cualquier momento por espacio de trabajo.</Warning></Warning>
|
||||
|
||||
**Soluciones**:
|
||||
|
||||
|
||||
@@ -39,6 +39,12 @@ Déployez Twenty sur Railway avec le modèle maintenu par la communauté ci-dess
|
||||
|
||||
[](https://railway.com/deploy/nAL3hA)
|
||||
|
||||
### Twenty sur Sealos
|
||||
|
||||
Déployez Twenty sur Sealos avec le modèle maintenu par la communauté ci-dessous.
|
||||
|
||||
[](https://sealos.io/products/app-store/twenty)
|
||||
|
||||
## Autres
|
||||
|
||||
N'hésitez pas à ouvrir une PR pour ajouter d'autres options de fournisseur cloud.
|
||||
|
||||
@@ -25,7 +25,7 @@ Vous pouvez **voir, modifier, supprimer des enregistrements** à partir de là a
|
||||
- Utilisez la **barre de recherche** (appuyez sur `/` pour y accéder instantanément)
|
||||
- Ouvrir la section **Paramètres**
|
||||
|
||||
<Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning>Veuillez noter que notre documentation API est accessible sous la section Paramètres et non dans le guide de l'utilisateur.</Warning></Warning>
|
||||
<Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning><Warning>Veuillez noter que notre documentation API est accessible sous la section Paramètres et non dans le guide de l'utilisateur.</Warning></Warning>
|
||||
|
||||
- </Warning>
|
||||
Ayez un accès direct à vos **vues favorites**. Les favoris sont uniques pour chaque utilisateur.
|
||||
|
||||
@@ -39,6 +39,12 @@ image: /images/user-guide/notes/notes_header.png
|
||||
|
||||
[](https://railway.com/deploy/nAL3hA)
|
||||
|
||||
### Twenty על Sealos
|
||||
|
||||
פרסו את Twenty ב-Sealos עם התבנית המנוהלת על ידי הקהילה למטה.
|
||||
|
||||
[](https://sealos.io/products/app-store/twenty)
|
||||
|
||||
## אחרים
|
||||
|
||||
אל תהססו לפתוח PR כדי להוסיף עוד אפשרויות ספקי ענן.
|
||||
|
||||
@@ -39,6 +39,12 @@ Telepítse a Twenty-t a Railwayre az alábbi közösségi karbantartású sablon
|
||||
|
||||
[](https://railway.com/deploy/nAL3hA)
|
||||
|
||||
### Twenty a Sealoson
|
||||
|
||||
Nyugodtan nyisson PR-t további felhőszolgáltatók hozzáadásához.
|
||||
|
||||
[](https://sealos.io/products/app-store/twenty)
|
||||
|
||||
## Egyéb
|
||||
|
||||
Nyugodtan nyisson PR-t további felhőszolgáltatók hozzáadásához.
|
||||
|
||||
@@ -23,6 +23,14 @@ Figma は、デザイナーと開発者の間のコミュニケーションの
|
||||
このガイドは、Figma を使って共同作業する方法を説明します。
|
||||
このガイドは、Figma を使って共同作業する方法を説明します。
|
||||
このガイドは、Figma を使って共同作業する方法を説明します。
|
||||
このガイドは、Figma を使って共同作業する方法を説明します。
|
||||
このガイドは、Figma を使って共同作業する方法を説明します。
|
||||
このガイドは、Figma を使って共同作業する方法を説明します。
|
||||
このガイドは、Figma を使って共同作業する方法を説明します。
|
||||
このガイドは、Figma を使って共同作業する方法を説明します。
|
||||
このガイドは、Figma を使って共同作業する方法を説明します。
|
||||
このガイドは、Figma を使って共同作業する方法を説明します。
|
||||
このガイドは、Figma を使って共同作業する方法を説明します。
|
||||
|
||||
## アクセス
|
||||
|
||||
@@ -84,6 +92,28 @@ Figma プラットフォームの学習に関するより包括的な詳細と
|
||||
これは推奨拡張機能の一部です。
|
||||
これは推奨拡張機能の一部です。
|
||||
これは推奨拡張機能の一部です。
|
||||
これは推奨拡張機能の一部です。
|
||||
これは推奨拡張機能の一部です。
|
||||
これは推奨拡張機能の一部です。
|
||||
これは推奨拡張機能の一部です。
|
||||
これは推奨拡張機能の一部です。
|
||||
これは推奨拡張機能の一部です。
|
||||
これは推奨拡張機能の一部です。
|
||||
これは推奨拡張機能の一部です。
|
||||
これは推奨拡張機能の一部です。
|
||||
これは推奨拡張機能の一部です。
|
||||
これは推奨拡張機能の一部です。
|
||||
これは推奨拡張機能の一部です。
|
||||
これは推奨拡張機能の一部です。
|
||||
これは推奨拡張機能の一部です。
|
||||
これは推奨拡張機能の一部です。
|
||||
これは推奨拡張機能の一部です。
|
||||
これは推奨拡張機能の一部です。
|
||||
これは推奨拡張機能の一部です。
|
||||
これは推奨拡張機能の一部です。
|
||||
これは推奨拡張機能の一部です。
|
||||
これは推奨拡張機能の一部です。
|
||||
これは推奨拡張機能の一部です。
|
||||
|
||||
## コラボレーション
|
||||
|
||||
|
||||
@@ -41,6 +41,12 @@ Coolifyを使用してサーバーにTwentyをデプロイします。 (Coolify
|
||||
|
||||
[](https://railway.com/deploy/nAL3hA)
|
||||
|
||||
### Sealos上のTwenty
|
||||
|
||||
以下のコミュニティがメンテナンスしているテンプレートを使用して、SealosにTwentyをデプロイします。
|
||||
|
||||
[](https://sealos.io/products/app-store/twenty)
|
||||
|
||||
## その他
|
||||
|
||||
もっと多くのクラウドプロバイダーオプションを追加するために、PRを自由に作成してください。
|
||||
|
||||
@@ -158,7 +158,7 @@ SSL(HTTPS)は、特定のブラウザ機能が正しく動作するために
|
||||
|
||||
2. **.env ファイルを更新**
|
||||
|
||||
.env`ファイルを開き、`SERVER_URL\\\\\\\\\\\\\\`を更新します:
|
||||
.env`ファイルを開き、`SERVER_URL\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\`を更新します:
|
||||
|
||||
```ini
|
||||
SERVER_URL=http(s)://your-domain-or-ip:your-port
|
||||
|
||||
@@ -27,10 +27,10 @@ Twentyは、日常をサポートする最適なデータモデルを形成す
|
||||
例:Stripeではオブジェクト`サブスクリプション`が、Airbnbではオブジェクト`旅行`が、スタートアップアクセラレーターではオブジェクト`バッチ`が必要でしょう。
|
||||
|
||||
**2. バリエーションにはフィールドを使い、新しいオブジェクトは使わないでください。**
|
||||
既存のオブジェクトの特性に過ぎないもの(例:会社の「業種」や機会の「ステータス」)はフィールドにします。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。
|
||||
既存のオブジェクトの特性に過ぎないもの(例:会社の「業種」や機会の「ステータス」)はフィールドにします。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。 カテゴリ、ラベル、属性にはフィールドが最適です。
|
||||
|
||||
**3. 単独で存在する場合には新しいオブジェクトを作成してください。**
|
||||
概念が独自のライフサイクル、プロパティ、または関係を持つ場合、それは通常オブジェクトに値します。 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば:
|
||||
概念が独自のライフサイクル、プロパティ、または関係を持つ場合、それは通常オブジェクトに値します。 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば: 例えば:
|
||||
|
||||
- **プロジェクト**:独自の期限、所有者、タスクを持つもの
|
||||
- **サブスクリプション**:会社、製品、請求書を結ぶもの
|
||||
|
||||
@@ -50,7 +50,7 @@ CRMには基本的な2つの種類のレコードがあります:
|
||||
|
||||
## オブジェクト
|
||||
|
||||
オブジェクトは、CRMにおける特定のエンティティを表すデータ構造です(例:人々、会社、機会)。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。
|
||||
オブジェクトは、CRMにおける特定のエンティティを表すデータ構造です(例:人々、会社、機会)。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。 オブジェクトは標準(ビルトイン)またはカスタム(あなたによって作成)することができます。
|
||||
|
||||
## 商談
|
||||
|
||||
|
||||
@@ -39,6 +39,12 @@ Implementeer Twenty op Railway met de hieronder vermelde, door de gemeenschap on
|
||||
|
||||
[](https://railway.com/deploy/nAL3hA)
|
||||
|
||||
### Twenty op Sealos
|
||||
|
||||
Implementeer Twenty op Sealos met de hieronder vermelde, door de gemeenschap onderhouden sjabloon.
|
||||
|
||||
[](https://sealos.io/products/app-store/twenty)
|
||||
|
||||
## Andere
|
||||
|
||||
Voel je vrij om een PR in te dienen om meer Cloud Provider-opties toe te voegen.
|
||||
|
||||
@@ -39,6 +39,12 @@ Implante Twenty no Railway com o template mantido pela comunidade abaixo.
|
||||
|
||||
[](https://railway.com/deploy/nAL3hA)
|
||||
|
||||
### Twenty no Sealos
|
||||
|
||||
Implante Twenty no Sealos com o template mantido pela comunidade abaixo.
|
||||
|
||||
[](https://sealos.io/products/app-store/twenty)
|
||||
|
||||
## Outros
|
||||
|
||||
Sinta-se à vontade para abrir um PR para adicionar mais opções de Provedor de Nuvem.
|
||||
|
||||
@@ -39,6 +39,12 @@ Triển khai Twenty trên Railway với mẫu do cộng đồng duy trì dưới
|
||||
|
||||
[](https://railway.com/deploy/nAL3hA)
|
||||
|
||||
### Khác
|
||||
|
||||
Hãy tự do mở một PR để thêm nhiều tùy chọn Nhà cung cấp Đám mây hơn.
|
||||
|
||||
[](https://sealos.io/products/app-store/twenty)
|
||||
|
||||
## Khác
|
||||
|
||||
Hãy tự do mở một PR để thêm nhiều tùy chọn Nhà cung cấp Đám mây hơn.
|
||||
|
||||
@@ -17,7 +17,7 @@ image: /images/user-guide/notes/notes_header.png
|
||||
|
||||
### Coolify
|
||||
|
||||
使用 Coolify 部署 Twenty 到伺服器。 (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出)
|
||||
使用 Coolify 部署 Twenty 到伺服器。 (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出) (官方 Coolify 映像即將推出)
|
||||
|
||||
[Coolify 文件](https://coolify.io/docs/get-started/introduction)
|
||||
|
||||
@@ -39,6 +39,12 @@ image: /images/user-guide/notes/notes_header.png
|
||||
|
||||
[](https://railway.com/deploy/nAL3hA)
|
||||
|
||||
### Sealos 上的 Twenty
|
||||
|
||||
使用下面社群維護的範本在 Sealos 部署 Twenty。
|
||||
|
||||
[](https://sealos.io/products/app-store/twenty)
|
||||
|
||||
## 其他
|
||||
|
||||
歡迎自由提交 PR 以增加更多的雲供應商選項。
|
||||
|
||||
@@ -45,8 +45,9 @@ sectionInfo: 配置您的Twenty工作空间设置和偏好
|
||||
刪除您的帳號將永久移除您對所有工作空間的訪問。
|
||||
刪除您的帳號將永久移除您對所有工作空間的訪問。 此操作無法撤銷,您將失去所有工作空間權限,如您只想退出特定的團隊,應考慮退出個別的工作空間。 刪除您的帳號將永久移除您對所有工作空間的訪問。
|
||||
刪除您的帳號將永久移除您對所有工作空間的訪問。 此操作無法撤銷,您將失去所有工作空間權限,如您只想退出特定的團隊,應考慮退出個別的工作空間。
|
||||
</Warning> 刪除您的帳號將永久移除您對所有工作空間的訪問。
|
||||
</Warning> 刪除您的帳號將永久移除您對所有工作空間的訪問。
|
||||
刪除您的帳號將永久移除您對所有工作空間的訪問。 此操作無法撤銷,您將失去所有工作空間權限,如您只想退出特定的團隊,應考慮退出個別的工作空間。
|
||||
|
||||
</Warning>
|
||||
|
||||
要删除您的帐户:
|
||||
|
||||
@@ -24,7 +24,8 @@
|
||||
"@tiptap/core": "^3.4.2",
|
||||
"@types/react": "^19",
|
||||
"@types/react-dom": "^19",
|
||||
"react-email": "4.0.6"
|
||||
"react-email": "4.0.6",
|
||||
"vite-plugin-dts": "3.8.1"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
"@react-email/components": "^0.5.3",
|
||||
"@react-pdf/renderer": "^4.1.6",
|
||||
"@scalar/api-reference-react": "^0.4.36",
|
||||
"@sentry/react": "^10.27.0",
|
||||
"@tiptap/core": "^3.4.2",
|
||||
"@tiptap/extension-bold": "^3.4.2",
|
||||
"@tiptap/extension-document": "^3.4.2",
|
||||
@@ -146,6 +147,8 @@
|
||||
"optionator": "^0.9.1",
|
||||
"playwright": "^1.56.1",
|
||||
"rollup-plugin-visualizer": "^5.14.0",
|
||||
"vite-plugin-checker": "^0.10.2",
|
||||
"vite-plugin-svgr": "^4.3.0",
|
||||
"vite-tsconfig-paths": "^4.2.1"
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -53,6 +53,7 @@ export type Agent = {
|
||||
applicationId?: Maybe<Scalars['UUID']>;
|
||||
createdAt: Scalars['DateTime'];
|
||||
description?: Maybe<Scalars['String']>;
|
||||
evaluationInputs: Array<Scalars['String']>;
|
||||
icon?: Maybe<Scalars['String']>;
|
||||
id: Scalars['UUID'];
|
||||
isCustom: Scalars['Boolean'];
|
||||
@@ -67,17 +68,32 @@ export type Agent = {
|
||||
updatedAt: Scalars['DateTime'];
|
||||
};
|
||||
|
||||
export type AgentChatMessage = {
|
||||
__typename?: 'AgentChatMessage';
|
||||
export type AgentChatThread = {
|
||||
__typename?: 'AgentChatThread';
|
||||
createdAt: Scalars['DateTime'];
|
||||
id: Scalars['UUID'];
|
||||
parts: Array<AgentChatMessagePart>;
|
||||
role: Scalars['String'];
|
||||
threadId: Scalars['UUID'];
|
||||
title?: Maybe<Scalars['String']>;
|
||||
updatedAt: Scalars['DateTime'];
|
||||
};
|
||||
|
||||
export type AgentChatMessagePart = {
|
||||
__typename?: 'AgentChatMessagePart';
|
||||
export type AgentIdInput = {
|
||||
/** The id of the agent. */
|
||||
id: Scalars['UUID'];
|
||||
};
|
||||
|
||||
export type AgentMessage = {
|
||||
__typename?: 'AgentMessage';
|
||||
agentId?: Maybe<Scalars['UUID']>;
|
||||
createdAt: Scalars['DateTime'];
|
||||
id: Scalars['UUID'];
|
||||
parts: Array<AgentMessagePart>;
|
||||
role: Scalars['String'];
|
||||
threadId: Scalars['UUID'];
|
||||
turnId: Scalars['UUID'];
|
||||
};
|
||||
|
||||
export type AgentMessagePart = {
|
||||
__typename?: 'AgentMessagePart';
|
||||
createdAt: Scalars['DateTime'];
|
||||
errorDetails?: Maybe<Scalars['JSON']>;
|
||||
errorMessage?: Maybe<Scalars['String']>;
|
||||
@@ -105,24 +121,23 @@ export type AgentChatMessagePart = {
|
||||
type: Scalars['String'];
|
||||
};
|
||||
|
||||
export type AgentChatThread = {
|
||||
__typename?: 'AgentChatThread';
|
||||
export type AgentTurn = {
|
||||
__typename?: 'AgentTurn';
|
||||
agentId?: Maybe<Scalars['UUID']>;
|
||||
createdAt: Scalars['DateTime'];
|
||||
evaluations: Array<AgentTurnEvaluation>;
|
||||
id: Scalars['UUID'];
|
||||
messages: Array<AgentMessage>;
|
||||
threadId: Scalars['UUID'];
|
||||
};
|
||||
|
||||
export type AgentTurnEvaluation = {
|
||||
__typename?: 'AgentTurnEvaluation';
|
||||
comment?: Maybe<Scalars['String']>;
|
||||
createdAt: Scalars['DateTime'];
|
||||
id: Scalars['UUID'];
|
||||
title?: Maybe<Scalars['String']>;
|
||||
updatedAt: Scalars['DateTime'];
|
||||
};
|
||||
|
||||
export type AgentHandoff = {
|
||||
__typename?: 'AgentHandoff';
|
||||
description?: Maybe<Scalars['String']>;
|
||||
id: Scalars['UUID'];
|
||||
toAgent: Agent;
|
||||
};
|
||||
|
||||
export type AgentIdInput = {
|
||||
/** The id of the agent. */
|
||||
id: Scalars['UUID'];
|
||||
score: Scalars['Int'];
|
||||
turnId: Scalars['UUID'];
|
||||
};
|
||||
|
||||
export type AggregateChartConfiguration = {
|
||||
@@ -136,6 +151,8 @@ export type AggregateChartConfiguration = {
|
||||
format?: Maybe<Scalars['String']>;
|
||||
graphType: GraphType;
|
||||
label?: Maybe<Scalars['String']>;
|
||||
prefix?: Maybe<Scalars['String']>;
|
||||
suffix?: Maybe<Scalars['String']>;
|
||||
timezone?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
@@ -328,10 +345,12 @@ export type BarChartConfiguration = {
|
||||
color?: Maybe<Scalars['String']>;
|
||||
description?: Maybe<Scalars['String']>;
|
||||
displayDataLabel?: Maybe<Scalars['Boolean']>;
|
||||
displayLegend?: Maybe<Scalars['Boolean']>;
|
||||
filter?: Maybe<Scalars['JSON']>;
|
||||
firstDayOfTheWeek?: Maybe<Scalars['Int']>;
|
||||
graphType: GraphType;
|
||||
groupMode?: Maybe<BarChartGroupMode>;
|
||||
isCumulative?: Maybe<Scalars['Boolean']>;
|
||||
omitNullValues?: Maybe<Scalars['Boolean']>;
|
||||
primaryAxisDateGranularity?: Maybe<ObjectRecordGroupByDateGranularity>;
|
||||
primaryAxisGroupByFieldMetadataId: Scalars['UUID'];
|
||||
@@ -670,6 +689,7 @@ export type CoreView = {
|
||||
kanbanAggregateOperation?: Maybe<AggregateOperations>;
|
||||
kanbanAggregateOperationFieldMetadataId?: Maybe<Scalars['UUID']>;
|
||||
key?: Maybe<ViewKey>;
|
||||
mainGroupByFieldMetadataId?: Maybe<Scalars['UUID']>;
|
||||
name: Scalars['String'];
|
||||
objectMetadataId: Scalars['UUID'];
|
||||
openRecordIn: ViewOpenRecordIn;
|
||||
@@ -755,14 +775,9 @@ export type CoreViewSort = {
|
||||
workspaceId: Scalars['UUID'];
|
||||
};
|
||||
|
||||
export type CreateAgentHandoffInput = {
|
||||
description?: InputMaybe<Scalars['String']>;
|
||||
fromAgentId: Scalars['UUID'];
|
||||
toAgentId: Scalars['UUID'];
|
||||
};
|
||||
|
||||
export type CreateAgentInput = {
|
||||
description?: InputMaybe<Scalars['String']>;
|
||||
evaluationInputs?: InputMaybe<Array<Scalars['String']>>;
|
||||
icon?: InputMaybe<Scalars['String']>;
|
||||
label: Scalars['String'];
|
||||
modelConfiguration?: InputMaybe<Scalars['JSON']>;
|
||||
@@ -949,6 +964,7 @@ export type CreateViewInput = {
|
||||
kanbanAggregateOperation?: InputMaybe<AggregateOperations>;
|
||||
kanbanAggregateOperationFieldMetadataId?: InputMaybe<Scalars['UUID']>;
|
||||
key?: InputMaybe<ViewKey>;
|
||||
mainGroupByFieldMetadataId?: InputMaybe<Scalars['UUID']>;
|
||||
name: Scalars['String'];
|
||||
objectMetadataId: Scalars['UUID'];
|
||||
openRecordIn?: InputMaybe<ViewOpenRecordIn>;
|
||||
@@ -1257,15 +1273,13 @@ export enum FeatureFlagKey {
|
||||
IS_GLOBAL_WORKSPACE_DATASOURCE_ENABLED = 'IS_GLOBAL_WORKSPACE_DATASOURCE_ENABLED',
|
||||
IS_IMAP_SMTP_CALDAV_ENABLED = 'IS_IMAP_SMTP_CALDAV_ENABLED',
|
||||
IS_JSON_FILTER_ENABLED = 'IS_JSON_FILTER_ENABLED',
|
||||
IS_MESSAGE_FOLDER_CONTROL_ENABLED = 'IS_MESSAGE_FOLDER_CONTROL_ENABLED',
|
||||
IS_PAGE_LAYOUT_ENABLED = 'IS_PAGE_LAYOUT_ENABLED',
|
||||
IS_POSTGRESQL_INTEGRATION_ENABLED = 'IS_POSTGRESQL_INTEGRATION_ENABLED',
|
||||
IS_PUBLIC_DOMAIN_ENABLED = 'IS_PUBLIC_DOMAIN_ENABLED',
|
||||
IS_RECORD_PAGE_LAYOUT_ENABLED = 'IS_RECORD_PAGE_LAYOUT_ENABLED',
|
||||
IS_STRIPE_INTEGRATION_ENABLED = 'IS_STRIPE_INTEGRATION_ENABLED',
|
||||
IS_UNIQUE_INDEXES_ENABLED = 'IS_UNIQUE_INDEXES_ENABLED',
|
||||
IS_WORKFLOW_RUN_STOPPAGE_ENABLED = 'IS_WORKFLOW_RUN_STOPPAGE_ENABLED',
|
||||
IS_WORKSPACE_MIGRATION_V2_ENABLED = 'IS_WORKSPACE_MIGRATION_V2_ENABLED'
|
||||
IS_WORKFLOW_RUN_STOPPAGE_ENABLED = 'IS_WORKFLOW_RUN_STOPPAGE_ENABLED'
|
||||
}
|
||||
|
||||
export type Field = {
|
||||
@@ -1659,9 +1673,11 @@ export type LineChartConfiguration = {
|
||||
color?: Maybe<Scalars['String']>;
|
||||
description?: Maybe<Scalars['String']>;
|
||||
displayDataLabel?: Maybe<Scalars['Boolean']>;
|
||||
displayLegend?: Maybe<Scalars['Boolean']>;
|
||||
filter?: Maybe<Scalars['JSON']>;
|
||||
firstDayOfTheWeek?: Maybe<Scalars['Int']>;
|
||||
graphType: GraphType;
|
||||
isCumulative?: Maybe<Scalars['Boolean']>;
|
||||
isStacked?: Maybe<Scalars['Boolean']>;
|
||||
omitNullValues?: Maybe<Scalars['Boolean']>;
|
||||
primaryAxisDateGranularity?: Maybe<ObjectRecordGroupByDateGranularity>;
|
||||
@@ -1729,10 +1745,8 @@ export type Mutation = {
|
||||
checkPublicDomainValidRecords?: Maybe<DomainValidRecords>;
|
||||
checkoutSession: BillingSessionOutput;
|
||||
computeStepOutputSchema: Scalars['JSON'];
|
||||
createAgentHandoff: Scalars['Boolean'];
|
||||
createApiKey: ApiKey;
|
||||
createApprovedAccessDomain: ApprovedAccessDomain;
|
||||
createChatThread: AgentChatThread;
|
||||
createCoreView: CoreView;
|
||||
createCoreViewField: CoreViewField;
|
||||
createCoreViewFilter: CoreViewFilter;
|
||||
@@ -1826,7 +1840,6 @@ export type Mutation = {
|
||||
initiateOTPProvisioning: InitiateTwoFactorAuthenticationProvisioningOutput;
|
||||
initiateOTPProvisioningForAuthenticatedUser: InitiateTwoFactorAuthenticationProvisioningOutput;
|
||||
publishServerlessFunction: ServerlessFunction;
|
||||
removeAgentHandoff: Scalars['Boolean'];
|
||||
removeRoleFromAgent: Scalars['Boolean'];
|
||||
renewToken: AuthTokens;
|
||||
resendEmailVerificationToken: ResendEmailVerificationTokenOutput;
|
||||
@@ -1890,6 +1903,7 @@ export type Mutation = {
|
||||
uploadImage: SignedFile;
|
||||
uploadProfilePicture: SignedFile;
|
||||
uploadWorkspaceLogo: SignedFile;
|
||||
uploadWorkspaceMemberProfilePicture: SignedFile;
|
||||
upsertFieldPermissions: Array<FieldPermission>;
|
||||
upsertObjectPermissions: Array<ObjectPermission>;
|
||||
upsertPermissionFlags: Array<PermissionFlag>;
|
||||
@@ -1949,11 +1963,6 @@ export type MutationComputeStepOutputSchemaArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type MutationCreateAgentHandoffArgs = {
|
||||
input: CreateAgentHandoffInput;
|
||||
};
|
||||
|
||||
|
||||
export type MutationCreateApiKeyArgs = {
|
||||
input: CreateApiKeyInput;
|
||||
};
|
||||
@@ -2409,11 +2418,6 @@ export type MutationPublishServerlessFunctionArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type MutationRemoveAgentHandoffArgs = {
|
||||
input: RemoveAgentHandoffInput;
|
||||
};
|
||||
|
||||
|
||||
export type MutationRemoveRoleFromAgentArgs = {
|
||||
agentId: Scalars['UUID'];
|
||||
};
|
||||
@@ -2746,6 +2750,11 @@ export type MutationUploadWorkspaceLogoArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type MutationUploadWorkspaceMemberProfilePictureArgs = {
|
||||
file: Scalars['Upload'];
|
||||
};
|
||||
|
||||
|
||||
export type MutationUpsertFieldPermissionsArgs = {
|
||||
upsertFieldPermissionsInput: UpsertFieldPermissionsInput;
|
||||
};
|
||||
@@ -2915,7 +2924,7 @@ export type ObjectRecordFilterInput = {
|
||||
updatedAt?: InputMaybe<DateTimeFilter>;
|
||||
};
|
||||
|
||||
/** Date granularity options (e.g. DAY, MONTH, QUARTER, YEAR, DAY_OF_THE_WEEK, MONTH_OF_THE_YEAR, QUARTER_OF_THE_YEAR) */
|
||||
/** Date granularity options (e.g. DAY, MONTH, QUARTER, YEAR, WEEK, DAY_OF_THE_WEEK, MONTH_OF_THE_YEAR, QUARTER_OF_THE_YEAR) */
|
||||
export enum ObjectRecordGroupByDateGranularity {
|
||||
DAY = 'DAY',
|
||||
DAY_OF_THE_WEEK = 'DAY_OF_THE_WEEK',
|
||||
@@ -2924,6 +2933,7 @@ export enum ObjectRecordGroupByDateGranularity {
|
||||
NONE = 'NONE',
|
||||
QUARTER = 'QUARTER',
|
||||
QUARTER_OF_THE_YEAR = 'QUARTER_OF_THE_YEAR',
|
||||
WEEK = 'WEEK',
|
||||
YEAR = 'YEAR'
|
||||
}
|
||||
|
||||
@@ -3041,6 +3051,7 @@ export enum PermissionFlagType {
|
||||
DATA_MODEL = 'DATA_MODEL',
|
||||
DOWNLOAD_FILE = 'DOWNLOAD_FILE',
|
||||
EXPORT_CSV = 'EXPORT_CSV',
|
||||
HTTP_REQUEST_TOOL = 'HTTP_REQUEST_TOOL',
|
||||
IMPERSONATE = 'IMPERSONATE',
|
||||
IMPORT_CSV = 'IMPORT_CSV',
|
||||
LAYOUTS = 'LAYOUTS',
|
||||
@@ -3064,12 +3075,14 @@ export type PieChartConfiguration = {
|
||||
dateGranularity?: Maybe<ObjectRecordGroupByDateGranularity>;
|
||||
description?: Maybe<Scalars['String']>;
|
||||
displayDataLabel?: Maybe<Scalars['Boolean']>;
|
||||
displayLegend?: Maybe<Scalars['Boolean']>;
|
||||
filter?: Maybe<Scalars['JSON']>;
|
||||
firstDayOfTheWeek?: Maybe<Scalars['Int']>;
|
||||
graphType: GraphType;
|
||||
groupByFieldMetadataId: Scalars['UUID'];
|
||||
groupBySubFieldName?: Maybe<Scalars['String']>;
|
||||
orderBy?: Maybe<GraphOrderBy>;
|
||||
showCenterMetric?: Maybe<Scalars['Boolean']>;
|
||||
timezone?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
@@ -3131,17 +3144,12 @@ export type Query = {
|
||||
apiKey?: Maybe<ApiKey>;
|
||||
apiKeys: Array<ApiKey>;
|
||||
billingPortalSession: BillingSessionOutput;
|
||||
chatMessages: Array<AgentChatMessage>;
|
||||
chatThread: AgentChatThread;
|
||||
chatThreads: Array<AgentChatThread>;
|
||||
checkUserExists: CheckUserExistOutput;
|
||||
checkWorkspaceInviteHashIsValid: WorkspaceInviteHashValidOutput;
|
||||
currentUser: User;
|
||||
currentWorkspace: Workspace;
|
||||
field: Field;
|
||||
fields: FieldConnection;
|
||||
findAgentHandoffTargets: Array<Agent>;
|
||||
findAgentHandoffs: Array<AgentHandoff>;
|
||||
findManyAgents: Array<Agent>;
|
||||
findManyApplications: Array<Application>;
|
||||
findManyCronTriggers: Array<CronTrigger>;
|
||||
@@ -3222,16 +3230,6 @@ export type QueryBillingPortalSessionArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type QueryChatMessagesArgs = {
|
||||
threadId: Scalars['UUID'];
|
||||
};
|
||||
|
||||
|
||||
export type QueryChatThreadArgs = {
|
||||
id: Scalars['UUID'];
|
||||
};
|
||||
|
||||
|
||||
export type QueryCheckUserExistsArgs = {
|
||||
captchaToken?: InputMaybe<Scalars['String']>;
|
||||
email: Scalars['String'];
|
||||
@@ -3243,16 +3241,6 @@ export type QueryCheckWorkspaceInviteHashIsValidArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type QueryFindAgentHandoffTargetsArgs = {
|
||||
input: AgentIdInput;
|
||||
};
|
||||
|
||||
|
||||
export type QueryFindAgentHandoffsArgs = {
|
||||
input: AgentIdInput;
|
||||
};
|
||||
|
||||
|
||||
export type QueryFindOneAgentArgs = {
|
||||
input: AgentIdInput;
|
||||
};
|
||||
@@ -3602,11 +3590,6 @@ export enum RemoteTableStatus {
|
||||
SYNCED = 'SYNCED'
|
||||
}
|
||||
|
||||
export type RemoveAgentHandoffInput = {
|
||||
fromAgentId: Scalars['UUID'];
|
||||
toAgentId: Scalars['UUID'];
|
||||
};
|
||||
|
||||
export type ResendEmailVerificationTokenOutput = {
|
||||
__typename?: 'ResendEmailVerificationTokenOutput';
|
||||
success: Scalars['Boolean'];
|
||||
@@ -4032,6 +4015,7 @@ export type UuidFilterComparison = {
|
||||
|
||||
export type UpdateAgentInput = {
|
||||
description?: InputMaybe<Scalars['String']>;
|
||||
evaluationInputs?: InputMaybe<Array<Scalars['String']>>;
|
||||
icon?: InputMaybe<Scalars['String']>;
|
||||
id: Scalars['UUID'];
|
||||
label?: InputMaybe<Scalars['String']>;
|
||||
@@ -4083,6 +4067,7 @@ export type UpdateFieldInput = {
|
||||
isUIReadOnly?: InputMaybe<Scalars['Boolean']>;
|
||||
isUnique?: InputMaybe<Scalars['Boolean']>;
|
||||
label?: InputMaybe<Scalars['String']>;
|
||||
morphRelationsUpdatePayload?: InputMaybe<Array<Scalars['JSON']>>;
|
||||
name?: InputMaybe<Scalars['String']>;
|
||||
options?: InputMaybe<Scalars['JSON']>;
|
||||
settings?: InputMaybe<Scalars['JSON']>;
|
||||
@@ -4274,6 +4259,7 @@ export type UpdateViewInput = {
|
||||
isCompact?: InputMaybe<Scalars['Boolean']>;
|
||||
kanbanAggregateOperation?: InputMaybe<AggregateOperations>;
|
||||
kanbanAggregateOperationFieldMetadataId?: InputMaybe<Scalars['UUID']>;
|
||||
mainGroupByFieldMetadataId?: InputMaybe<Scalars['UUID']>;
|
||||
name?: InputMaybe<Scalars['String']>;
|
||||
openRecordIn?: InputMaybe<ViewOpenRecordIn>;
|
||||
position?: InputMaybe<Scalars['Float']>;
|
||||
@@ -4323,6 +4309,7 @@ export type UpdateWorkspaceInput = {
|
||||
defaultRoleId?: InputMaybe<Scalars['UUID']>;
|
||||
displayName?: InputMaybe<Scalars['String']>;
|
||||
editableProfileFields?: InputMaybe<Array<Scalars['String']>>;
|
||||
fastModel?: InputMaybe<Scalars['String']>;
|
||||
inviteHash?: InputMaybe<Scalars['String']>;
|
||||
isGoogleAuthBypassEnabled?: InputMaybe<Scalars['Boolean']>;
|
||||
isGoogleAuthEnabled?: InputMaybe<Scalars['Boolean']>;
|
||||
@@ -4333,7 +4320,7 @@ export type UpdateWorkspaceInput = {
|
||||
isPublicInviteLinkEnabled?: InputMaybe<Scalars['Boolean']>;
|
||||
isTwoFactorAuthenticationEnforced?: InputMaybe<Scalars['Boolean']>;
|
||||
logo?: InputMaybe<Scalars['String']>;
|
||||
routerModel?: InputMaybe<Scalars['String']>;
|
||||
smartModel?: InputMaybe<Scalars['String']>;
|
||||
subdomain?: InputMaybe<Scalars['String']>;
|
||||
trashRetentionDays?: InputMaybe<Scalars['Float']>;
|
||||
};
|
||||
@@ -4660,6 +4647,7 @@ export type Workspace = {
|
||||
deletedAt?: Maybe<Scalars['DateTime']>;
|
||||
displayName?: Maybe<Scalars['String']>;
|
||||
editableProfileFields?: Maybe<Array<Scalars['String']>>;
|
||||
fastModel: Scalars['String'];
|
||||
featureFlags?: Maybe<Array<FeatureFlagDto>>;
|
||||
hasValidEnterpriseKey: Scalars['Boolean'];
|
||||
id: Scalars['UUID'];
|
||||
@@ -4676,6 +4664,7 @@ export type Workspace = {
|
||||
logo?: Maybe<Scalars['String']>;
|
||||
metadataVersion: Scalars['Float'];
|
||||
routerModel: Scalars['String'];
|
||||
smartModel: Scalars['String'];
|
||||
subdomain: Scalars['String'];
|
||||
trashRetentionDays: Scalars['Float'];
|
||||
updatedAt: Scalars['DateTime'];
|
||||
@@ -4803,7 +4792,7 @@ export type SearchQueryVariables = Exact<{
|
||||
|
||||
export type SearchQuery = { __typename?: 'Query', search: { __typename?: 'SearchResultConnection', edges: Array<{ __typename?: 'SearchResultEdge', cursor: string, node: { __typename?: 'SearchRecord', recordId: any, objectNameSingular: string, label: string, imageUrl?: string | null, tsRankCD: number, tsRank: number } }>, pageInfo: { __typename?: 'SearchResultPageInfo', hasNextPage: boolean, endCursor?: string | null } } };
|
||||
|
||||
export type PageLayoutWidgetFragmentFragment = { __typename?: 'PageLayoutWidget', id: any, title: string, type: WidgetType, objectMetadataId?: any | null, createdAt: string, updatedAt: string, deletedAt?: string | null, pageLayoutTabId: any, gridPosition: { __typename?: 'GridPosition', column: number, columnSpan: number, row: number, rowSpan: number }, configuration?: { __typename?: 'AggregateChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, label?: string | null, displayDataLabel?: boolean | null, format?: string | null, description?: string | null, filter?: any | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'BarChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, primaryAxisGroupByFieldMetadataId: any, primaryAxisGroupBySubFieldName?: string | null, primaryAxisDateGranularity?: ObjectRecordGroupByDateGranularity | null, primaryAxisOrderBy?: GraphOrderBy | null, secondaryAxisGroupByFieldMetadataId?: any | null, secondaryAxisGroupBySubFieldName?: string | null, secondaryAxisGroupByDateGranularity?: ObjectRecordGroupByDateGranularity | null, secondaryAxisOrderBy?: GraphOrderBy | null, omitNullValues?: boolean | null, axisNameDisplay?: AxisNameDisplay | null, displayDataLabel?: boolean | null, rangeMin?: number | null, rangeMax?: number | null, color?: string | null, description?: string | null, filter?: any | null, groupMode?: BarChartGroupMode | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'GaugeChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, displayDataLabel?: boolean | null, color?: string | null, description?: string | null, filter?: any | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'IframeConfiguration', url?: string | null } | { __typename?: 'LineChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, primaryAxisGroupByFieldMetadataId: any, primaryAxisGroupBySubFieldName?: string | null, primaryAxisDateGranularity?: ObjectRecordGroupByDateGranularity | null, primaryAxisOrderBy?: GraphOrderBy | null, secondaryAxisGroupByFieldMetadataId?: any | null, secondaryAxisGroupBySubFieldName?: string | null, secondaryAxisGroupByDateGranularity?: ObjectRecordGroupByDateGranularity | null, secondaryAxisOrderBy?: GraphOrderBy | null, omitNullValues?: boolean | null, axisNameDisplay?: AxisNameDisplay | null, displayDataLabel?: boolean | null, rangeMin?: number | null, rangeMax?: number | null, color?: string | null, description?: string | null, filter?: any | null, isStacked?: boolean | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'PieChartConfiguration', graphType: GraphType, groupByFieldMetadataId: any, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, groupBySubFieldName?: string | null, dateGranularity?: ObjectRecordGroupByDateGranularity | null, orderBy?: GraphOrderBy | null, displayDataLabel?: boolean | null, color?: string | null, description?: string | null, filter?: any | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | null };
|
||||
export type PageLayoutWidgetFragmentFragment = { __typename?: 'PageLayoutWidget', id: any, title: string, type: WidgetType, objectMetadataId?: any | null, createdAt: string, updatedAt: string, deletedAt?: string | null, pageLayoutTabId: any, gridPosition: { __typename?: 'GridPosition', column: number, columnSpan: number, row: number, rowSpan: number }, configuration?: { __typename?: 'AggregateChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, label?: string | null, displayDataLabel?: boolean | null, format?: string | null, description?: string | null, filter?: any | null, prefix?: string | null, suffix?: string | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'BarChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, primaryAxisGroupByFieldMetadataId: any, primaryAxisGroupBySubFieldName?: string | null, primaryAxisDateGranularity?: ObjectRecordGroupByDateGranularity | null, primaryAxisOrderBy?: GraphOrderBy | null, secondaryAxisGroupByFieldMetadataId?: any | null, secondaryAxisGroupBySubFieldName?: string | null, secondaryAxisGroupByDateGranularity?: ObjectRecordGroupByDateGranularity | null, secondaryAxisOrderBy?: GraphOrderBy | null, omitNullValues?: boolean | null, axisNameDisplay?: AxisNameDisplay | null, displayDataLabel?: boolean | null, displayLegend?: boolean | null, rangeMin?: number | null, rangeMax?: number | null, color?: string | null, description?: string | null, filter?: any | null, groupMode?: BarChartGroupMode | null, isCumulative?: boolean | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'GaugeChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, displayDataLabel?: boolean | null, color?: string | null, description?: string | null, filter?: any | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'IframeConfiguration', url?: string | null } | { __typename?: 'LineChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, primaryAxisGroupByFieldMetadataId: any, primaryAxisGroupBySubFieldName?: string | null, primaryAxisDateGranularity?: ObjectRecordGroupByDateGranularity | null, primaryAxisOrderBy?: GraphOrderBy | null, secondaryAxisGroupByFieldMetadataId?: any | null, secondaryAxisGroupBySubFieldName?: string | null, secondaryAxisGroupByDateGranularity?: ObjectRecordGroupByDateGranularity | null, secondaryAxisOrderBy?: GraphOrderBy | null, omitNullValues?: boolean | null, axisNameDisplay?: AxisNameDisplay | null, displayDataLabel?: boolean | null, displayLegend?: boolean | null, rangeMin?: number | null, rangeMax?: number | null, color?: string | null, description?: string | null, filter?: any | null, isStacked?: boolean | null, isCumulative?: boolean | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'PieChartConfiguration', graphType: GraphType, groupByFieldMetadataId: any, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, groupBySubFieldName?: string | null, dateGranularity?: ObjectRecordGroupByDateGranularity | null, orderBy?: GraphOrderBy | null, displayDataLabel?: boolean | null, showCenterMetric?: boolean | null, displayLegend?: boolean | null, color?: string | null, description?: string | null, filter?: any | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | null };
|
||||
|
||||
export type UpdatePageLayoutWithTabsAndWidgetsMutationVariables = Exact<{
|
||||
id: Scalars['String'];
|
||||
@@ -4811,7 +4800,7 @@ export type UpdatePageLayoutWithTabsAndWidgetsMutationVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type UpdatePageLayoutWithTabsAndWidgetsMutation = { __typename?: 'Mutation', updatePageLayoutWithTabsAndWidgets: { __typename?: 'PageLayout', id: any, name: string, type: PageLayoutType, objectMetadataId?: any | null, createdAt: string, updatedAt: string, deletedAt?: string | null, tabs?: Array<{ __typename?: 'PageLayoutTab', id: any, title: string, position: number, pageLayoutId: any, createdAt: string, updatedAt: string, widgets?: Array<{ __typename?: 'PageLayoutWidget', id: any, title: string, type: WidgetType, objectMetadataId?: any | null, createdAt: string, updatedAt: string, deletedAt?: string | null, pageLayoutTabId: any, gridPosition: { __typename?: 'GridPosition', column: number, columnSpan: number, row: number, rowSpan: number }, configuration?: { __typename?: 'AggregateChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, label?: string | null, displayDataLabel?: boolean | null, format?: string | null, description?: string | null, filter?: any | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'BarChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, primaryAxisGroupByFieldMetadataId: any, primaryAxisGroupBySubFieldName?: string | null, primaryAxisDateGranularity?: ObjectRecordGroupByDateGranularity | null, primaryAxisOrderBy?: GraphOrderBy | null, secondaryAxisGroupByFieldMetadataId?: any | null, secondaryAxisGroupBySubFieldName?: string | null, secondaryAxisGroupByDateGranularity?: ObjectRecordGroupByDateGranularity | null, secondaryAxisOrderBy?: GraphOrderBy | null, omitNullValues?: boolean | null, axisNameDisplay?: AxisNameDisplay | null, displayDataLabel?: boolean | null, rangeMin?: number | null, rangeMax?: number | null, color?: string | null, description?: string | null, filter?: any | null, groupMode?: BarChartGroupMode | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'GaugeChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, displayDataLabel?: boolean | null, color?: string | null, description?: string | null, filter?: any | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'IframeConfiguration', url?: string | null } | { __typename?: 'LineChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, primaryAxisGroupByFieldMetadataId: any, primaryAxisGroupBySubFieldName?: string | null, primaryAxisDateGranularity?: ObjectRecordGroupByDateGranularity | null, primaryAxisOrderBy?: GraphOrderBy | null, secondaryAxisGroupByFieldMetadataId?: any | null, secondaryAxisGroupBySubFieldName?: string | null, secondaryAxisGroupByDateGranularity?: ObjectRecordGroupByDateGranularity | null, secondaryAxisOrderBy?: GraphOrderBy | null, omitNullValues?: boolean | null, axisNameDisplay?: AxisNameDisplay | null, displayDataLabel?: boolean | null, rangeMin?: number | null, rangeMax?: number | null, color?: string | null, description?: string | null, filter?: any | null, isStacked?: boolean | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'PieChartConfiguration', graphType: GraphType, groupByFieldMetadataId: any, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, groupBySubFieldName?: string | null, dateGranularity?: ObjectRecordGroupByDateGranularity | null, orderBy?: GraphOrderBy | null, displayDataLabel?: boolean | null, color?: string | null, description?: string | null, filter?: any | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | null }> | null }> | null } };
|
||||
export type UpdatePageLayoutWithTabsAndWidgetsMutation = { __typename?: 'Mutation', updatePageLayoutWithTabsAndWidgets: { __typename?: 'PageLayout', id: any, name: string, type: PageLayoutType, objectMetadataId?: any | null, createdAt: string, updatedAt: string, deletedAt?: string | null, tabs?: Array<{ __typename?: 'PageLayoutTab', id: any, title: string, position: number, pageLayoutId: any, createdAt: string, updatedAt: string, widgets?: Array<{ __typename?: 'PageLayoutWidget', id: any, title: string, type: WidgetType, objectMetadataId?: any | null, createdAt: string, updatedAt: string, deletedAt?: string | null, pageLayoutTabId: any, gridPosition: { __typename?: 'GridPosition', column: number, columnSpan: number, row: number, rowSpan: number }, configuration?: { __typename?: 'AggregateChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, label?: string | null, displayDataLabel?: boolean | null, format?: string | null, description?: string | null, filter?: any | null, prefix?: string | null, suffix?: string | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'BarChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, primaryAxisGroupByFieldMetadataId: any, primaryAxisGroupBySubFieldName?: string | null, primaryAxisDateGranularity?: ObjectRecordGroupByDateGranularity | null, primaryAxisOrderBy?: GraphOrderBy | null, secondaryAxisGroupByFieldMetadataId?: any | null, secondaryAxisGroupBySubFieldName?: string | null, secondaryAxisGroupByDateGranularity?: ObjectRecordGroupByDateGranularity | null, secondaryAxisOrderBy?: GraphOrderBy | null, omitNullValues?: boolean | null, axisNameDisplay?: AxisNameDisplay | null, displayDataLabel?: boolean | null, displayLegend?: boolean | null, rangeMin?: number | null, rangeMax?: number | null, color?: string | null, description?: string | null, filter?: any | null, groupMode?: BarChartGroupMode | null, isCumulative?: boolean | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'GaugeChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, displayDataLabel?: boolean | null, color?: string | null, description?: string | null, filter?: any | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'IframeConfiguration', url?: string | null } | { __typename?: 'LineChartConfiguration', graphType: GraphType, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, primaryAxisGroupByFieldMetadataId: any, primaryAxisGroupBySubFieldName?: string | null, primaryAxisDateGranularity?: ObjectRecordGroupByDateGranularity | null, primaryAxisOrderBy?: GraphOrderBy | null, secondaryAxisGroupByFieldMetadataId?: any | null, secondaryAxisGroupBySubFieldName?: string | null, secondaryAxisGroupByDateGranularity?: ObjectRecordGroupByDateGranularity | null, secondaryAxisOrderBy?: GraphOrderBy | null, omitNullValues?: boolean | null, axisNameDisplay?: AxisNameDisplay | null, displayDataLabel?: boolean | null, displayLegend?: boolean | null, rangeMin?: number | null, rangeMax?: number | null, color?: string | null, description?: string | null, filter?: any | null, isStacked?: boolean | null, isCumulative?: boolean | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | { __typename?: 'PieChartConfiguration', graphType: GraphType, groupByFieldMetadataId: any, aggregateFieldMetadataId: any, aggregateOperation: AggregateOperations, groupBySubFieldName?: string | null, dateGranularity?: ObjectRecordGroupByDateGranularity | null, orderBy?: GraphOrderBy | null, displayDataLabel?: boolean | null, showCenterMetric?: boolean | null, displayLegend?: boolean | null, color?: string | null, description?: string | null, filter?: any | null, timezone?: string | null, firstDayOfTheWeek?: number | null } | null }> | null }> | null } };
|
||||
|
||||
export type OnDbEventSubscriptionVariables = Exact<{
|
||||
input: OnDbEventInput;
|
||||
@@ -5137,12 +5126,14 @@ export const PageLayoutWidgetFragmentFragmentDoc = gql`
|
||||
omitNullValues
|
||||
axisNameDisplay
|
||||
displayDataLabel
|
||||
displayLegend
|
||||
rangeMin
|
||||
rangeMax
|
||||
color
|
||||
description
|
||||
filter
|
||||
groupMode
|
||||
isCumulative
|
||||
timezone
|
||||
firstDayOfTheWeek
|
||||
}
|
||||
@@ -5161,12 +5152,14 @@ export const PageLayoutWidgetFragmentFragmentDoc = gql`
|
||||
omitNullValues
|
||||
axisNameDisplay
|
||||
displayDataLabel
|
||||
displayLegend
|
||||
rangeMin
|
||||
rangeMax
|
||||
color
|
||||
description
|
||||
filter
|
||||
isStacked
|
||||
isCumulative
|
||||
timezone
|
||||
firstDayOfTheWeek
|
||||
}
|
||||
@@ -5179,6 +5172,8 @@ export const PageLayoutWidgetFragmentFragmentDoc = gql`
|
||||
dateGranularity
|
||||
orderBy
|
||||
displayDataLabel
|
||||
showCenterMetric
|
||||
displayLegend
|
||||
color
|
||||
description
|
||||
filter
|
||||
@@ -5194,6 +5189,8 @@ export const PageLayoutWidgetFragmentFragmentDoc = gql`
|
||||
format
|
||||
description
|
||||
filter
|
||||
prefix
|
||||
suffix
|
||||
timezone
|
||||
firstDayOfTheWeek
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user