- Imported MAIN_COLOR_NAMES for dynamic color handling.
- Added logic to generate colors for custom objects based on a hash of their names.
- Updated getStandardObjectIconColor to return a color for custom objects when not found in the standard list.
- Added flex display and center alignment to the search container for better layout consistency.
- Adjusted padding to use inline spacing for a more responsive design.
- Increased height of the search container to enhance usability.
- Integrated dynamic icon and color handling for folders in CommandMenuEditFolderPickerSubView.
- Updated folder data structure in related hooks to include icon and color properties for improved visual representation.
- Refactored folder rendering logic to utilize new icon and color attributes, enhancing user experience.
- Added a label for the folder in CommandMenuFolderInfo.
- Capitalized the label for link in CommandMenuLinkInfo.
- Refactored label logic in CommandMenuObjectViewRecordInfo to utilize selected item metadata and improved view handling.
### What this PR do ?
Stops the delay fields from updating the workflow on every keystroke by
keeping values locally and saving them on blur, which fixes the cached
relation error
Fixed#15709
---------
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
- Introduced StyledMenuStyleText for consistent styling of color labels.
- Updated RightComponent to use the new styled component, enhancing visual presentation.
## Context
Command to backfill record page layouts and related entities for legacy
workspaces.
## Test
Set SHOULD_SEED_STANDARD_RECORD_PAGE_LAYOUTS=false, reset DB then run
the command and compare with Set
SHOULD_SEED_STANDARD_RECORD_PAGE_LAYOUTS=true on a different workspace
## Summary
- **Consolidate logic function services**: Remove
`LogicFunctionMetadataService` and consolidate all logic function CRUD
operations into `LogicFunctionFromSourceService`, with a new
`LogicFunctionFromSourceHelperService` for shared validation/migration
logic
- **Introduce typed conversion utils following the skill pattern**: Add
`fromCreateLogicFunctionFromSourceInputToUniversalFlatLogicFunctionToCreate`
and `fromUpdateLogicFunctionFromSourceInputToFlatLogicFunctionToUpdate`
that convert DTO inputs directly to flat entities
(`UniversalFlatLogicFunction` / `FlatLogicFunction`), replacing the
previous intermediate `UpdateLogicFunctionMetadataParams` indirection
- **Simplify `CodeStepBuildService`**: Remove ~100 lines of manual
duplication logic by delegating to
`LogicFunctionFromSourceService.duplicateOneWithSource`
- **Remove completed 1-17 migration**: Delete
`MigrateWorkflowCodeStepsCommand` and associated utils that migrated
workflow code steps from serverless functions to logic functions
## Summary
- Upgrades `@swc/core` from 1.13.3 to **1.15.11** (swc_core v56), which
introduces CBOR-based plugin serialization replacing rkyv, eliminating
strict version-matching between SWC core and Wasm plugins
- Upgrades `@lingui/swc-plugin` from ^5.6.0 to **^5.11.0** (swc_core
50.2.3, built with `--cfg=swc_ast_unknown` for cross-version
compatibility)
- Upgrades `@swc/plugin-emotion` from 10.0.4 to **14.6.0** (swc_core 53,
also with backward-compat feature)
- Upgrades companion packages: `@swc-node/register` 1.8.0 → 1.11.1,
`@swc/helpers` ~0.5.2 → ~0.5.18, `@vitejs/plugin-react-swc` 3.11.0 →
4.2.3
### Why this is safe now
Starting from `@swc/core v1.15.0`, SWC replaced the rkyv serialization
scheme with CBOR (a self-describing format) and added `Unknown` AST enum
variants. Plugins built with `swc_core >= 47` and
`--cfg=swc_ast_unknown` are now forward-compatible across `@swc/core`
versions. Both `@lingui/swc-plugin@5.10.1+` and
`@swc/plugin-emotion@14.0.0+` have this support, meaning the old
version-matching nightmare between Lingui and SWC is largely solved.
Reference: https://github.com/lingui/swc-plugin/issues/179
## Test plan
- [x] `yarn install` resolves without errors
- [x] `npx nx build twenty-shared` succeeds
- [x] `npx nx build twenty-ui` succeeds (validates
@swc/plugin-emotion@14.6.0)
- [x] `npx nx typecheck twenty-front` succeeds
- [x] `npx nx build twenty-front` succeeds (validates vite + swc +
lingui pipeline)
- [x] `npx nx build twenty-emails` succeeds (validates lingui plugin)
- [x] Frontend jest tests pass (validates @swc/jest +
@lingui/swc-plugin)
- [x] Server jest tests pass (validates server-side SWC + lingui)
Made with [Cursor](https://cursor.com)
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
## Description
- Adds support for declaring command menu items directly within
`defineFrontComponent` via an optional command config property
- Introduces a new `CommandMenuItemManifest` type in twenty-shared and
wires it through the manifest build pipeline
## Example Of usage
```tsx
import { defineFrontComponent } from "twenty-sdk";
const TestAction = () => {
return <div>Test Action</div>;
};
export default defineFrontComponent({
universalIdentifier: "6c289461-0007-4a62-a99f-69e5c11a4ce7",
name: "test-action",
description: "Test Action",
component: TestAction,
command: {
universalIdentifier: "c07df864-495f-46f3-9f5b-9d3ce2589e9b",
label: "Run My Action",
icon: "IconBolt",
isPinned: false,
},
});
```
## Video QA
https://github.com/user-attachments/assets/f910fc6a-44a9-45d1-87c5-f0ce64bb3878
Managed to create a many to many app with minimal instructions. File
will need to be enriched with more pitfalls.
---------
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
# Introduction
While preparing the twenty-standard as code migration to twenty-app
through sdk I've faced permanent field enum update as the id was
generated dynamically at each twenty standard app construction
Making them deterministic in order to avoid having this noise
Won't backfill this on existing workspace as it's not critical and that
we will rework the options in the future
# Introduction
Atomically create the field and object to be created
And avoid synchronizing unrelated non up to date object and fields
Followup https://github.com/twentyhq/twenty/pull/17398
- Updated the structure of STANDARD_NAVIGATION_MENU_ITEMS by rearranging the order of items and correcting their universal identifiers and view references.
- Ensured that all items are consistently positioned to enhance navigation experience.
Introduced an error message on twenty-front CI earlier to try and inform
the user that test failure could be a coverage issue if no individual
test was failing. However, it led to the assumption that it must be
coverage failure in all cases even when it was test failure leading to
the CI being red.
This PR reverts the change.
- Replaced null key with ViewKey.INDEX in both computeStandardWorkflowRunViews and computeStandardWorkflowVersionViews functions to enhance consistency in view key handling.
- Updated imports to use the new utility for getting navigation menu item icon styles based on color.
- Introduced constants for default icon color and color shades to enhance maintainability.
- Removed deprecated utility functions and streamlined color handling across components.
# Introduction
## Centralize system field definitions
- Extract a single `PARTIAL_SYSTEM_FLAT_FIELD_METADATAS` constant as the
source of truth for all 8 system fields (`id`, `createdAt`, `updatedAt`,
`deletedAt`, `createdBy`, `updatedBy`, `position`, `searchVector`),
eliminating duplication across custom object and standard app field
builders
- Refactor `buildDefaultFlatFieldMetadatasForCustomObject` to use the
shared constant via a new `buildObjectSystemFlatFieldMetadatas` helper
## Mark system fields as `isSystem: true`
- Fields `id`, `createdAt`, `updatedAt`, `deletedAt`, `createdBy`,
`updatedBy`, `position`, `searchVector` are now properly flagged as
system fields across all standard objects and custom object creation
- Standard app field builders for all ~30 standard objects updated to
set `isSystem: true` on `createdAt`, `updatedAt`, `deletedAt`,
`createdBy`, `updatedBy`
- System-only standard objects (blocklist, calendar channels, message
threads, etc.) now also include `createdBy`, `updatedBy`, `position`,
`searchVector` field definitions that were previously missing
## Validate system fields on object creation
- New transversal validation (`crossEntityTransversalValidation`) runs
after all atomic entity validations in the build orchestrator, ensuring
all 8 system fields are present with correct `type` and `isSystem: true`
when an object is created
- New `buildUniversalFlatObjectFieldByNameAndJoinColumnMaps` utility to
resolve field names to universal identifiers for a given object
- New exception codes: `MISSING_SYSTEM_FIELD` and `INVALID_SYSTEM_FIELD`
on `ObjectMetadataExceptionCode`
## Protect system fields and objects from mutation
- Field validators now block update/delete of `isSystem` fields by
non-system callers (`FIELD_MUTATION_NOT_ALLOWED`)
- Object validators now block update/delete of `isSystem` objects by
non-system callers
- `POSITION` and `TS_VECTOR` field type validators replaced: instead of
rejecting creation outright, they now validate that the field is named
correctly (`position` / `searchVector`) and has `isSystem: true`
## Distinguish `isSystemBuild` from `isCallerTwentyStandardApp`
- New `isCallerTwentyStandardApp` utility checks whether the caller's
`applicationUniversalIdentifier` matches the twenty standard app
- Name-sync logic (`isFlatFieldMetadataNameSyncedWithLabel`,
`areFlatObjectMetadataNamesSyncedWithLabels`) refactored to use
`isCallerTwentyStandardApp` for custom suffix decisions, keeping
`isSystemBuild` for mutation permission checks
- `WorkspaceMigrationBuilderOptions` type updated to include
`applicationUniversalIdentifier`
## Adapt frontend filtering
- New `HIDDEN_SYSTEM_FIELD_NAMES` constant (`id`, `position`,
`searchVector`) and `isHiddenSystemField` utility to only hide truly
internal fields while keeping user-facing system fields (`createdAt`,
`updatedAt`, `deletedAt`, `createdBy`, `updatedBy`) visible in the UI
- ~20 frontend files updated to replace `!field.isSystem` checks with
`!isHiddenSystemField(field)` across record index, settings, data model,
charts, workflows, spreadsheet import, aggregations, and role
permissions
## Add 1.19 upgrade commands
- **`backfill-system-fields-is-system`**: Raw SQL command to set
`isSystem = true` on existing workspace fields matching system field
names, and fix `position` field type from `NUMBER` to `POSITION` for
`favorite`/`favoriteFolder` objects. Includes proper cache invalidation.
- **`add-missing-system-fields-to-standard-objects`**: Codegen'd
workspace migration to create missing `position`, `searchVector`,
`createdBy`, `updatedBy` fields on standard objects that didn't
previously have them. Runs via `WorkspaceMigrationRunnerService` in a
single transaction with idempotency check. **Known limitation**: assumes
all standard objects exist and are valid in the target workspace.
## Add `universalIdentifier` for system fields in standard object
constants
- `standard-object.constant.ts` updated to include `universalIdentifier`
for `createdBy`, `updatedBy`, `position`, and `searchVector` across all
standard objects
- `fieldManifestType.ts` updated to support the new field manifest shape
## System relation
Completely removed and backfilled all `isSystem` relation to be false
false
As we won't require an object to have any relation system fields
## Add integration tests
- New test suite `failing-sync-application-object-system-fields`
covering: missing system fields, wrong field types (`id` as TEXT,
`createdAt` as TEXT, `position` as TEXT), system field deletion
attempts, and system field update attempts
- New test utilities: `buildDefaultObjectManifest` (builds an object
manifest with all 8 system fields) and `setupApplicationForSync`
(centralizes application setup)
- Existing successful sync test updated to verify system fields are
created with correct properties
## Next step
Make the builder scope the compared entity to be the currently built app
+ nor twenty standard app
- Replaced nullish coalescing with default value assignment for objectNameSingular, enhancing readability.
- Simplified logic for determining view overlay visibility and icon usage, improving maintainability.
- Updated color handling to ensure consistent application of styles based on icon presence, aligning with recent updates in navigation components.
- Replaced isNonEmptyString with isDefined for color validation, enhancing clarity and consistency in color handling.
- This change aligns with recent updates in color management across navigation components, improving maintainability.
- Simplified the assignment of properties in the useSaveNavigationMenuItemsDraft hook by removing unnecessary nullish coalescing, enhancing code readability.
- Updated change detection logic to directly compare values, improving maintainability and consistency in handling navigation menu item drafts.
- Moved the import of v4 from 'uuid' to improve code organization.
- Simplified color assignment logic by directly assigning the color variable, enhancing clarity and maintainability in the navigation menu draft management.
- Moved the import of DEFAULT_NAVIGATION_MENU_ITEM_COLOR_FOLDER to improve code organization.
- Updated the color determination logic to use isDefined instead of isNonEmptyString for better validation of folder colors, enhancing maintainability and consistency in color handling across navigation components.
- Changed ViewIcon color from gray11 to gray10 to enhance visual consistency with the theme. This minor adjustment aligns with recent updates in color handling across navigation components.
- Updated StyledViewOverlay to utilize theme.spacing for height and width, enhancing consistency with the theme.
- Adjusted ViewIcon size to use theme.spacing for improved maintainability and alignment with design standards.
- Refactored the StyledIconSlot to utilize theme.spacing for height and width when $hasFixedSize is true, enhancing consistency with the theme and improving maintainability.
## Summary
- Adds an `objectRecordCounts` query on the `/metadata` GraphQL endpoint
that returns approximate record counts for all objects in the workspace
- Uses PostgreSQL's `pg_class.reltuples` catalog stats — a single
instant query instead of N `COUNT(*)` table scans
- Replaces the previous `CombinedFindManyRecords` approach which hit the
server's 20 root resolver limit and silently showed 0 for all counts on
the settings Data Model page
### Server
- `ObjectRecordCountDTO` — GraphQL type with `objectNamePlural` and
`totalCount`
- `ObjectRecordCountService` — reads `pg_class` catalog for the
workspace schema
- Query added to `ObjectMetadataResolver` with `@MetadataResolver()` +
`NoPermissionGuard`
### Frontend
- `OBJECT_RECORD_COUNTS` query added to
`object-metadata/graphql/queries.ts`
- `useCombinedGetTotalCount` simplified to a zero-argument hook using
the new query
- `SettingsObjectTable` simplified to a single hook call
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
with new 'file' FILES field on attachment, UI should display attachment
name from file field value.
Issue with API users updating only 'file' FILES field (and not name
field anymore)
- Introduced a new optional 'color' property in the NavigationMenuItemManifest type to enhance customization of navigation items.
- Updated the fromNavigationMenuItemManifestToUniversalFlatNavigationMenuItem utility function to include the 'color' property, allowing for better visual representation in the navigation menu.
These changes improve the flexibility and visual consistency of navigation items across the application.
- Replaced DEFAULT_NAVIGATION_MENU_ITEM_COLOR_OBJECT constant with a hardcoded fallback color 'gray' for improved clarity in color handling.
- Streamlined the color determination process to enhance maintainability and consistency across navigation items.
These changes contribute to a more robust and straightforward approach to color management in the navigation drawer component.
- Replaced inline color determination logic with the getEffectiveNavigationMenuItemColor utility for improved clarity and maintainability.
- Removed unused default color constants to streamline the code.
These changes enhance the robustness of color handling for navigation menu items, aligning with recent updates in icon management.
- Updated icon theme color logic to utilize isNonEmptyString for better validation of navigation menu item colors.
- Integrated getStandardObjectIconColor and DEFAULT_NAVIGATION_MENU_ITEM_COLOR_OBJECT to ensure fallback options are available for icon rendering.
These changes improve the robustness of color handling for navigation items, enhancing visual consistency across the application.
- Introduced getEffectiveNavigationMenuItemColor utility to determine the appropriate color for navigation menu items based on their type and custom color settings.
- Updated CurrentWorkspaceMemberNavigationMenuItems and CurrentWorkspaceMemberOrphanNavigationMenuItems components to utilize the new color utility for icon rendering.
- Refactored NavigationMenuItemIcon to enhance icon styling logic based on effective color.
These changes improve the visual consistency and customization of navigation menu items across the application.
This PR adds Message folder association for message channel messages,
Currently under testing phase, not ready yet.
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- Added useTheme and useIsFeatureEnabled hooks to manage icon rendering based on theme and feature flags.
- Improved icon rendering logic to conditionally display icons based on navigation menu item editing status.
- Streamlined code for better readability and maintainability.
These changes align with recent updates in icon management and enhance the flexibility of the RecordIndexPageHeaderIcon component.
- Introduced the usePlainIcon prop in NavigationDrawerItem to allow for simplified icon rendering.
- Updated NavigationDrawerSectionForWorkspaceItems to utilize the new usePlainIcon prop, enhancing customization options for menu items.
These changes improve the flexibility and visual consistency of the navigation drawer components.
- Replaced the previous icon rendering logic with the new RecordIndexPageHeaderIcon component, enhancing clarity and maintainability.
- Removed unused imports and streamlined the code for better readability.
These changes align with recent improvements in icon management within the application.
- Updated CommandMenuNewSidebarItemViewObjectPickerSubView and CommandMenuObjectPickerSubView to use NavigationMenuItemStyleIcon for icon rendering, enhancing visual consistency.
- Refactored CommandMenuObjectMenuItem to streamline icon color handling and improve readability by utilizing a styledIcon function.
These changes enhance the maintainability and clarity of the command menu components.
- Eliminated the import of ViewKey from both computeStandardWorkflowRunViews and computeStandardWorkflowVersionViews utilities, as it was no longer needed.
- Updated the key property in the views to null, simplifying the view definitions.
These changes streamline the code and improve clarity in the workflow view utilities.
## Summary
- **File storage (LocalDriver):** Add realpath resolution and symlink
rejection to `writeFile`, `downloadFile`, and `downloadFolder` — brings
them in line with the existing `readFile` protections. Includes unit
tests.
- **JWT:** Pin signing/verification to HS256 explicitly.
- **Auth:** Revoke active refresh tokens when a user changes their
password.
- **Logic functions:** Validate `handlerName` as a safe JS identifier at
both DTO and runtime level, preventing injection into the generated
runner script.
- **User entity:** Remove `passwordHash` from the GraphQL schema
(`@Field` decorator removed, column stays).
- **Query params:** Use `crypto.randomBytes` instead of `Math.random`
for SQL parameter name generation.
- **Exception filter:** Mirror the request `Origin` header instead of
sending `Access-Control-Allow-Origin: *`.
## Test plan
- [x] `local.driver.spec.ts` — writeFile rejects symlinks, downloadFile
rejects paths outside storage
- [ ] Verify JWT auth flow still works (login, token refresh)
- [ ] Verify password change invalidates existing sessions
- [ ] Verify logic function creation with valid/invalid handler names
- [ ] Verify file upload/download in dev environment
Made with [Cursor](https://cursor.com)
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
- Updated the CommandMenuObjectMenuItem component to improve readability by formatting the icon color retrieval.
- Removed the unused useTheme import from NavigationDrawerSectionForWorkspaceItems, streamlining the code.
These changes enhance code clarity and maintainability in the navigation menu components.
- Integrated useIsFeatureEnabled hook to conditionally render icon color based on the IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED feature flag.
- Updated icon rendering logic in NavigationDrawerItem to enhance customization based on feature availability.
These changes improve the flexibility of the navigation menu by allowing dynamic icon color handling based on feature flags.
Issue : With IS_NAVIGATION_MENU_ITEM_ENABLED:true +
IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED:false, nav menu design is
changed after 1.18.0 release : views expansion removed, system object
displayed, position re-ordered
We prefer keeping the same "old" favorite behaviour and design state
- After 1.18.0 all workspaces have up-to-date navigation menu items
(migrated)
- IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED becomes the FF for nav menu
new design
---------
Co-authored-by: Charles Bochet <charles@twenty.com>
When a user's role lacks read permission on the target object (e.g.,
Company) or the intermediate junction object (e.g., EmploymentHistory),
junction relation fields like "Previous Companies" displayed as blank
instead of showing "Not shared."
- In RecordFieldList, junction fields now check the junction object's
read permission and set isForbidden on the field context so FieldDisplay
renders "Not shared" instead of an empty field.
- In RelationFromManyFieldDisplay, if junction records exist but all
nested target records are null (permission-denied by the API), the
component renders "Not shared" instead of an empty list.
---------
Co-authored-by: Félix Malfait <felix@twenty.com>
## Refactor page layout widget types into shared package and expose from
SDK
### Why
Widget configuration types were defined only on the server, forcing SDK
consumer apps to import from deep internal `twenty-shared/dist` paths —
fragile and breaks on structural changes. Server DTOs also had no
compile-time guarantee they matched the canonical types.
### What changed
- **`twenty-shared`**: Migrated `ChartFilter`, `GridPosition`,
`RatioAggregateConfig` and all 20 widget configuration variants into
`twenty-shared/types`. `PageLayoutWidgetConfiguration` (base, with
`SerializedRelation`) and `PageLayoutWidgetUniversalConfiguration`
(derived via `FormatRecordSerializedRelationProperties`) are now the
single source of truth.
- **`twenty-sdk`**: Re-exported `AggregateOperations`,
`ObjectRecordGroupByDateGranularity`, `PageLayoutTabLayoutMode`, and
`PageLayoutWidgetUniversalConfiguration` so consumer apps import from
`twenty-sdk` directly.
- **`twenty-server`**: All widget DTOs now `implements` their shared
type for compile-time enforcement. Added helpers to convert nested
`fieldMetadataId` ↔ `fieldMetadataUniversalIdentifier` inside chart
filters. Removed redundant local type re-exports.
Updating rich app so it also create:
- a many to many relation
- views
- navigation items
The app was built successfully.
Will still be missing front component examples
<img width="1498" height="660" alt="Capture d’écran 2026-02-18 à 17 47
25"
src="https://github.com/user-attachments/assets/acd5193f-3a36-4eb7-8276-3154e4e60f5e"
/>
## Sync page layouts, tabs, and widgets
Adds the ability for SDK applications to synchronize `pageLayout`,
`pageLayoutTab`, and `pageLayoutWidget` entities, following the same
pattern established in #18003 for views and navigation menu items.
### Changes
**`twenty-shared`**
- New `PageLayoutManifest`, `PageLayoutTabManifest`, and
`PageLayoutWidgetManifest` types with a hierarchical structure (page
layout → tabs → widgets)
- Added `pageLayouts: PageLayoutManifest[]` to the `Manifest` type
**`twenty-sdk`**
- New `definePageLayout()` SDK function with validation for
universalIdentifier, name, and nested tabs/widgets
- Wired into the manifest extraction and build pipeline
(`DefinePageLayout` target function, `PageLayouts` entity key)
- Exported from the SDK entry point
**`twenty-server`**
- Added `pageLayout`, `pageLayoutTab`, `pageLayoutWidget` to
`APPLICATION_MANIFEST_METADATA_NAMES`
- New conversion utilities: manifest → universal flat entity for all
three entity types
- Updated `computeApplicationManifestAllUniversalFlatEntity
- add a new optional key `postInstallLogicFunctionUniversalIdentifier`
in applicationConfig
- seed postInstall function in create-twenty-app
- update execute:function options
- update doc
- Update migration command to handle case where workspace logo is
originated from workspace email and point to twenty-icons.com
- Update same logic for new workspaces
- Add feature-flag for all newly created workspaces
## Summary
- Replace the character-stripping approach (`removeSqlDDLInjection`)
with standard PostgreSQL `escapeIdentifier` and `escapeLiteral`
functions across all workspace schema manager services
- Add missing identifier escaping to `createForeignKey` (was the only
method in the FK manager without it)
- Add allowlist validation for index WHERE clauses and FK action types
- Harden tsvector expression builder with proper identifier quoting
## Context
The workspace schema managers build DDL dynamically from metadata (table
names, column names, enum values, etc.). The previous approach stripped
all non-alphanumeric characters — safe but lossy (silently corrupts
values with legitimate special characters). The new approach uses
PostgreSQL's standard escaping:
- **Identifiers**: double internal `"` and wrap → `"my""table"` (same
algorithm as `pg` driver's `escapeIdentifier`)
- **Literals**: double internal `'` and wrap → `'it''s a value'` (same
algorithm as `pg` driver's `escapeLiteral`)
`removeSqlDDLInjection` is kept only for name generation (e.g.,
`computePostgresEnumName`) where stripping to `[a-zA-Z0-9_]` is the
correct behavior.
## Files changed
| File | What |
|------|------|
| `remove-sql-injection.util.ts` | Added `escapeIdentifier` +
`escapeLiteral` |
| `validate-index-where-clause.util.ts` | New — allowlist for partial
index WHERE clauses |
| 5 schema manager services | Replaced strip+manual-quote with
`escapeIdentifier`/`escapeLiteral` |
| `build-sql-column-definition.util.ts` | `escapeIdentifier` for column
names, validated `generatedType` |
| `sanitize-default-value.util.ts` | `escapeLiteral` instead of
stripping |
| `serialize-default-value.util.ts` | `escapeLiteral` for values,
`escapeIdentifier` for enum casts |
| `get-ts-vector-column-expression.util.ts` | `escapeIdentifier` for
field names in expressions |
| `sanitize-default-value.util.spec.ts` | Updated tests for escape
behavior |
## Test plan
- [x] All 64 existing tests pass across 6 test suites
- [x] `lint:diff-with-main` passes
- [x] TypeScript typecheck — no new errors
- [ ] Verify workspace sync-metadata still works end-to-end
- [ ] Verify custom object/field creation works
- [ ] Verify enum field option changes work
Made with [Cursor](https://cursor.com)
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
## Summary
- Replace all generic `"Unknown error"` fallback messages across the
server codebase with messages that include the actual error details
- The most impactful change is in `guard-redirect.service.ts`, which
handles OAuth redirect errors — non-`AuthException` errors (e.g.,
passport state verification failures) now show `"Authentication error:
<actual message>"` instead of the opaque `"Unknown error"`
- Gmail/Google error handler services now include the error message in
the thrown exception instead of discarding it
- Other catch blocks (workflow delay resume, migration runner rollback,
code interpreter, marketplace) now use `String(error)` for non-Error
objects instead of a static fallback
Fixes the class of issues reported in
https://github.com/twentyhq/twenty/issues/17812, where a user saw
"Unknown error" during Google OAuth and had no way to diagnose the root
cause (which turned out to be a session cookie / SSL configuration
issue).
## Test plan
- [ ] Verify OAuth error flows (e.g., Google Auth with misconfigured
callback URL) now display the actual error message on the `/verify` page
instead of "Unknown error"
- [ ] Verify Gmail sync error handling still correctly classifies and
re-throws errors with descriptive messages
- [ ] Verify workflow delay resume failures include the error details in
the workflow run status
Made with [Cursor](https://cursor.com)
Co-authored-by: Cursor <cursoragent@cursor.com>
- Introduced DEFAULT_NAVIGATION_MENU_ITEM_COLOR_FOLDER and DEFAULT_NAVIGATION_MENU_ITEM_COLOR_LINK constants for standardized color management.
- Updated AddToNavigationDragHandle, CurrentWorkspaceMemberNavigationMenuItems, NavigationMenuItemIcon, and WorkspaceNavigationMenuItemsFolder components to utilize the new color constants.
- Refactored icon color logic to improve consistency and maintainability across navigation menu items.
These changes enhance visual consistency and customization options in the navigation menu.
This fixes two edge cases for Gmail
- When policy was set to `SELECTED_FOLDERS` excluding root INBOX, it
missed label changes, so messages with newly applied labels weren't
imported until a full resync.
- Gmail thread replies by default by default do no inherit parent
message's label properties so thread context was also lost because only
individually labeled messages were returned, dropping earlier parts of
the conversation.
Fixed by subscribing to `labelAdded`/`labelRemoved` history events and
fetching full thread context when at least one message in a thread
carries a synced label. `ALL_FOLDERS` path is untouched.
## Summary
https://github.com/user-attachments/assets/1e75cc9d-d9d2-4ef2-99f9-34450f5d8de7
Add background incremental type checking (`tsc --watch`) to the SDK dev
mode, so type regressions are caught when the generated API client
changes — without requiring a full rebuild of source files.
Previously, removing a field from the data model would regenerate the
API client, but existing front components/logic functions referencing
the removed field wouldn't surface type errors (since their source
didn't change, esbuild wouldn't rebuild them).
## What changed
- **Background `tsc --watch`**: a long-lived TypeScript watcher runs
alongside esbuild watchers, incrementally re-checking all files when the
generated client changes. Only logs on state transitions (errors appear
/ errors clear) to stay quiet.
- **Atomic client generation**: API client is now generated into a temp
directory and swapped in atomically, avoiding a race condition where
`tsc --watch` could see an empty `generated/` directory
mid-regeneration.
- **Step decoupling**: orchestrator steps no longer receive
`uploadFilesStep` directly. Instead, they use callbacks (`onFileBuilt`,
`onApiClientGenerated`), and each step manages its own `builtFileInfos`
state.
- **`apiClientChecksum` omitted from `ApplicationConfig`**: it's a
build-time computed value, same as `packageJsonChecksum`.
<img width="327" height="177" alt="image"
src="https://github.com/user-attachments/assets/02bd25bb-fa41-42b0-8d96-01c51bd4580c"
/>
<img width="529" height="452" alt="image"
src="https://github.com/user-attachments/assets/61f6e968-365b-4a5b-8f2b-a8419d6b1bd3"
/>
Create the necessary tooling to listen to metadata events and plug it to
the front components. Now we have a hot reload like experience when we
edit a component in an app.
## Backend
- Split `EventWithQueryIds` into `ObjectRecordEventWithQueryIds` and
`MetadataEventWithQueryIds`
- Publish metadata event batches to active SSE streams in
`MetadataEventsToDbListener`
## Frontend
- Create a metadata event dispatching pipeline: SSE metadata events are
grouped by metadata name, transformed into
`MetadataOperationBrowserEventDetail` objects, and dispatched as browser
`CustomEvents`
- Add `useListenToMetadataOperationBrowserEvent` hook for consuming
metadata operation events filtered by metadata name and operation type
- Rename `useListenToObjectRecordEventsForQuery` to
`useListenToEventsForQuery`, now accepting both
`RecordGqlOperationSignature` and `MetadataGqlOperationSignature`
- Implement `useOnFrontComponentUpdated` which subscribes to front
component metadata events and updates the Apollo cache when the
component is modified
- Add `builtComponentChecksum` to the front component query and appends
it to the component URL for browser cache invalidation
- Imported NavigationMenuItemStyleIcon and getStandardObjectIconColor to enhance icon color handling.
- Refactored icon rendering logic to use a new PageHeaderIcon component that applies the standardized color.
- Improved code readability and maintainability by clarifying icon management within the header.
These changes align with recent enhancements in icon color support across navigation components.
## Context
Introducing "NewFieldDefaultConfiguration" to FIELDS widget
configurations
```typescript
{
isVisible: boolean;
viewFieldGroupId: string | null;
}
```
This configuration will define where a new field should be added (which
section) and its default visibility inside FIELDS widget views.
The new field position should always be at the end (meaning the last
position for the view fields OR the last position of a viewFieldGroup)
See "New fields" on this screenshot
<img width="401" height="724" alt="Layout V1"
src="https://github.com/user-attachments/assets/4969bcaa-f244-4504-8947-778a02c24c47"
/>
Fixes https://github.com/twentyhq/twenty/issues/17138
- Backend should have strict date/dateTime format validation
- FE in import csv is more permissive
---------
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
- Added a search input to filter color options based on user input, enhancing usability.
- Introduced state management for the search value and updated the rendering logic to display filtered color names.
- Included a separator for better visual organization in the dropdown menu.
These changes improve the user experience by allowing quick access to specific colors in the command menu.
- Integrated a new feature to allow users to add menu items directly within the folder component.
- Implemented a context state for managing the insertion of new menu items.
- Added a button for adding items, which triggers a command menu for item creation.
- Updated folder content length calculation to accommodate the new item.
These changes improve user interaction and streamline the process of managing navigation menu items.
- Introduced a new helper function, getColorFromTheme, to streamline the retrieval of theme colors with customizable shades.
- Updated getNavigationMenuItemIconBorderColor to utilize the new helper function, enhancing consistency in color retrieval.
- Modified getNavigationMenuItemIconStyleFromColor to use the new helper for background, icon, and border colors, improving code readability and maintainability.
These changes enhance the flexibility and clarity of color management in navigation menu items.
- Fixed "property entity not found" error when updating/creating a new
field and querying the same object repository just after
- Downgraded log type for unnecessary migration
- Changed the color for the allOpportunities menu item from 'tomato' to 'red' to enhance visual consistency across the navigation menu.
This update aligns with recent enhancements to icon color support in navigation components.
- Integrated getStandardObjectIconColor utility across various components to standardize icon colors based on object type.
- Updated CommandMenuNewSidebarItemObjectFlow and CommandMenuNewSidebarItemViewPickerSubView to utilize the new color utility.
- Modified AddToNavigationDragHandle and hooks to accept and apply icon color.
- Added iconColor property to AddToNavigationDragPayloadObject for better customization.
These changes improve visual consistency and customization options in the navigation menu.
- Introduced getStandardObjectIconColor function to standardize icon colors based on object type.
- Updated CommandMenuNewSidebarItemViewObjectPickerSubView, CommandMenuNewSidebarItemViewSystemSubView, CommandMenuObjectMenuItem, and CommandMenuObjectPickerItem components to utilize the new color utility.
This enhances visual consistency across the command menu items.
- Introduced folderColor prop to allow customization of icon color.
- Updated NavigationDrawerSectionForWorkspaceItems to pass color from item if available.
This enhances the visual customization options for navigation menu items.
- Simplified StyledViewOverlay by removing the border color prop.
- Updated dimensions for the overlay box and icon sizes to fixed pixel values.
- Adjusted the background color to use a theme color directly.
This improves consistency and readability in the component's styling.
- Moved Apollo import to the top of the file for consistency.
- Removed duplicate type definitions for NavigationMenuItemFieldsFragment and related queries/mutations to streamline the code.
## Add API client generation to SDK dev mode and refactor orchestrator
into step-based pipeline
### Why
The SDK dev mode lacked typed API client generation, forcing developers
to work without auto-generated GraphQL types when building applications.
Additionally, the orchestrator was a monolithic class that mixed watcher
management, token handling, and sync logic — making it difficult to
extend with new steps like client generation.
### How
- **Refactored the orchestrator** into a step-based pipeline with
dedicated classes: `CheckServer`, `EnsureValidTokens`,
`ResolveApplication`, `BuildManifest`, `UploadFiles`,
`GenerateApiClient`, `SyncApplication`, and `StartWatchers`. Each step
has typed input/output/status, managed by a new `OrchestratorState`
class.
- **Added `GenerateApiClientOrchestratorStep`** that detects
object/field schema changes and regenerates a typed GraphQL client (via
`@genql/cli`) into `node_modules/twenty-sdk/generated` for seamless
imports.
- **Replaced `checkApplicationExist`** with `findOneApplication` on both
server resolver and SDK API service, returning the entity data instead
of a boolean.
- **Added application token pair mutations**
(`generateApplicationToken`, `renewApplicationToken`) to the API
service, with the server now returning `ApplicationTokenPairDTO`
containing both access and refresh tokens.
- **Restructured the dev UI** into `dev/ui/components/` with dedicated
panel, section, and event log components.
- **Simplified `AppDevCommand`** from ~180 lines of watcher management
down to ~40 lines that delegate entirely to the orchestrator.
Long overdue PR: replacing deprecated country code in workflows.
Will allow to use variables.
We keep storing the country code since it allows to display the right
flag in picker when there are multiple countries for one calling code.
But we do not store country for variables.
<img width="477" height="254" alt="Capture d’écran 2026-02-17 à 17 25
23"
src="https://github.com/user-attachments/assets/dc67c41c-33cf-4021-b7bb-490827b2aa3c"
/>
## Summary
- Refactors SSRF protection from a request-level adapter to
connection-level agents, validating resolved IPs in `createConnection` +
socket `lookup` events
- Sets both `httpAgent` and `httpsAgent` so validation applies
regardless of protocol switches during redirects
- Caps `maxRedirects` to 10 as defense in depth
## Test plan
- [x] All 59 existing + new unit tests pass (agent util, isPrivateIp,
service)
- [x] No linter errors
- [ ] Verify webhook delivery still works with URLs that redirect
- [ ] Verify image upload from external URLs still works (relies on
redirect following)
Made with [Cursor](https://cursor.com)
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Changes core outbound HTTP security behavior and redirect handling,
which could impact webhook/image-fetch flows and connection semantics
despite improved SSRF coverage.
>
> **Overview**
> Refactors outbound SSRF protection from a custom axios `adapter` to
connection-level `httpAgent`/`httpsAgent` created by new
`createSsrfSafeAgent`, which blocks private IP literals up front and
validates DNS-resolved IPs via the socket `lookup` event.
>
> When safe mode is enabled, `SecureHttpClientService.getHttpClient` now
always installs both agents and enforces a capped `maxRedirects`
(default `5`), and the old `getSecureAxiosAdapter`
implementation/tests/types are removed. `isPrivateIp` is
tightened/expanded to treat `0.0.0.0/8` as private and avoid
misclassifying bare IPv4 decimals as IPv6.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
8261da4ff0. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
- Create a common file-by-id download controller
- Create core picture module with resolver and logic to handle
workspaceLogo and workspaceMemberProfilePicture update
- Create workflow file module (same)
- Data migration
fix for #17262
This change ensures that when the record is restored, instead of
emitting a database event of "DELETED", a database event of "RESTORED"
will be emitted, as it is happening in the inner working of TypeORM.
This ensures that the DELETED event are not fired on RESTORED, for
example, triggering a workflow.
The screen recording shows that restoring the soft deleted records does
not trigger the workflow set to to run on "Record Deleted"
https://github.com/user-attachments/assets/90e0184f-2e08-466c-a40d-1592b60e64ff
Fixes https://github.com/twentyhq/core-team-issues/issues/2192
This PR implements what is necessary to re-create the query that we
build on the frontend to obtain the returned object record from a
mutation, but on the backend, which was only partially implemented for
REST API.
Usually we want to have relations with only their id and label
identifier field to have lighter payloads.
In the event we only had depth 0 fields, with this PR we have all events
with depth 1 relations.
We have depth 2 for many-to-many cases, like updateOne or updateMany
result :
- Junction tables
- Activity target tables
## Context
- Add missing fields widget and FIELDS_WIDGET view for workflow run and
workflow version standard objects
- Fix FIELDS_WIDGET configuration fieldId universalIdentifier not being
converted to id when migration is executed.
- Replaced the `IconWithBackground` component with a new `NavigationMenuItemStyleIcon` component for better styling and color management.
- Updated various components to utilize the new icon component, enhancing consistency in icon rendering across the application.
- Removed unused imports and simplified icon color logic by integrating color styles directly into the new component.
- Deleted the `getIconBackgroundColorForPayload` utility as it is no longer needed with the new icon handling approach.
Closes#8305
The Clipboard API (`navigator.clipboard`) requires a secure context
(HTTPS or localhost). Self-hosted deployments on plain HTTP silently
fail when copying.
This PR:
- Adds a `document.execCommand('copy')` fallback for insecure contexts
- Shows a descriptive error message explaining HTTPS is required when
the fallback also fails
- Consolidates 3 components that were using `navigator.clipboard`
directly (without error handling) to use the centralized
`useCopyToClipboard` hook
Generated with [Claude Code](https://claude.ai/code)
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Scoped to frontend clipboard UX with a defensive fallback and clearer
errors; minimal impact outside copy flows.
>
> **Overview**
> Improves copy-to-clipboard behavior in non-HTTPS/self-hosted
deployments by enhancing `useCopyToClipboard` to use
`navigator.clipboard` only in secure contexts and otherwise fall back to
`document.execCommand('copy')`.
>
> Updates 2FA setup screens and the view visibility dropdown to use the
centralized `copyToClipboard` helper (with consistent snackbars), and
shows a more descriptive error (longer duration) when copying fails due
to an insecure context.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
30944e63eb. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
## Summary
Replaces the static "Ask AI" header in the command menu with the
conversation’s auto-generated title once it’s set after the first
message.
## Changes
- **Backend:** Title is generated after the first user message (existing
behavior).
- **Frontend:** After the first stream completes, we fetch the thread
title and sync it to:
- `currentAIChatThreadTitleState` (persists across command menu
close/reopen)
- Command menu page info and navigation stack (so the title survives
back navigation)
- **Entry points:** Opening Ask AI from the left nav or command center
uses the same title resolution (explicit `pageTitle` → current thread
title → "Ask AI" fallback).
- **Race fix:** Title sync only runs when the thread that finished
streaming is still the active thread, so switching threads mid-stream
doesn’t overwrite the current thread’s title.
---------
Co-authored-by: Félix Malfait <felix@twenty.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
## Summary
- Fixes "Target field metadata full object not found" error thrown
during optimistic effects (e.g., bulk delete) on workspaces with custom
objects
- The relation loader was using a simple sort-by-ID to pick the
representative morph field, while `filterMorphRelationDuplicateFields`
uses `pickMorphGroupSurvivor` which prefers active non-system fields.
When a custom object's auto-created morph field (`isSystem: true`)
happened to have the smallest UUID, the two loaders would disagree — the
relation DTO pointed to that system field's ID, but the field metadata
loader filtered it out in favor of a standard field, causing the
frontend lookup to fail.
- Now both code paths use `pickMorphGroupSurvivor` so they always agree
on which morph field represents the group.
## Test plan
- [ ] Create a custom object on a workspace that already has standard
objects with morph relations (e.g., noteTarget, taskTarget)
- [ ] Bulk-select and delete records (e.g., People) — should no longer
throw "Target field metadata full object not found"
Made with [Cursor](https://cursor.com)
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Small, localized change to morph-relation selection logic in a
dataloader; main risk is altered field choice for edge-case morph
groups, but behavior now matches existing deduplication.
>
> **Overview**
> Ensures the relation dataloader picks the representative
morph-relation target field using `pickMorphGroupSurvivor` (preferring
active non-system fields) instead of the previous sort-by-id approach.
>
> This aligns `createRelationLoader` with
`filterMorphRelationDuplicateFields`, preventing mismatches where
relation DTOs could reference a morph field that gets filtered out
elsewhere (e.g., triggering “Target field metadata full object not
found”).
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
c3a6d86126. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Co-authored-by: Cursor <cursoragent@cursor.com>
## Summary
- update AI chat message typography and list line-height for readability
- apply richer markdown-section styling for headings, spacing,
separators, and inline code
- keep links non-underlined by default with underline on hover, using
accent11 for link color
- preserve previous AI chat table design while keeping other markdown
improvements
## Validation
- yarn eslint
packages/twenty-front/src/modules/ai/components/LazyMarkdownRenderer.tsx
packages/twenty-front/src/modules/ai/components/AIChatMessage.tsx
---------
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
When deploying with
```
IS_WORKSPACE_CREATION_LIMITED_TO_SERVER_ADMINS=true
IS_MULTIWORKSPACE_ENABLED=true
```
The first workspace can be created successfully. However, any attempt to
create additional workspaces as admin fails with the error: `Workspace
creation is restricted to admins` because `canAccessFullAdminPanel` is
**false**
If these flags are set to false during the initial deployment and
restarting the Docker container, workspace creation works normally.
Problem is caused by `canAccessFullAdminPanel`
---------
Co-authored-by: ehconitin <nitinkoche03@gmail.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
- Removed the styled component for color label and replaced it with a direct display of the color label in the dropdown.
- Simplified the rendering logic for the color option in the command menu, enhancing readability and maintainability.
# Introduction
In this PR we start returning a workspace migration post sync so it can
committed and provided within the tarball
## Universal aggregators utils
Created two utils
### deleteUniversalFlatEntityForeignKeyAggregators
Used when building a universal create action, a newly created actions
should not contain any aggregated foreign key so they won't be codegen
in the workspace migration but also they are overriden at uninversal to
flat transpilation anw
### resetUniversalFlatEntityForeignKeyAggregators
Used before validating a new flat entity creation, some validator will
consume the fk aggregator in order to validate integrity, but of
optimstically provided it can result to errors. To avoid caller
responsability we override them here
## create-field-action refactor
Refactored the universal and flat field create action to be following
the base actions in order to ease typing
Also it was tailored to handle unlimited amount of flat field metadata
in the same actions whereas in the reality we were always only sending
at max 2 ( for relation fields )
Note: relation field has to be provided at the same as if not optimistic
would fail to retrieve circular universal identifiers
## ObjectManifest
Now always expect a `labelIdentifierFieldMetadataUniversalIdentifier`
## Integration test
Created an integration test that creates an app, sync a first manifest
and a second implying update workspace migration action generation
## Summary
- Add default visible view fields for `timelineActivity`, `attachment`,
`noteTarget`, `taskTarget`, and `workspaceMember` objects so they
display useful columns out of the box
- Standardize morph relation field labels to "Target" with
`IconArrowUpRight` for consistency across all pivot/junction tables
- Mark deprecated fields (`fullPath`, `fileCategory`,
`linkedRecordCachedName`, `linkedRecordId`, `linkedObjectMetadataId`) as
`isSystem` to hide them from the UI column picker
- Fix morph field deduplication logic (`pickMorphGroupSurvivor`) to
prefer active, non-system fields over auto-generated system fields from
custom objects
- Migrate attachment seeds from legacy `fullPath`/`fileCategory` to the
new `FILES` field type, creating proper `FileEntity` records in
`core.file` via `fileStorageService.writeFile()`
- Restore `customDomain` in the user query fragment
<img width="825" height="754" alt="Screenshot 2026-02-15 at 15 44 27"
src="https://github.com/user-attachments/assets/9596a3dd-8d3a-43c0-925a-0adef9ee68a8"
/>
<img width="736" height="731" alt="Screenshot 2026-02-15 at 15 44 13"
src="https://github.com/user-attachments/assets/cd1a66c5-731d-43e6-bbc3-703cbeda1652"
/>
<img width="722" height="757" alt="Screenshot 2026-02-15 at 15 44 03"
src="https://github.com/user-attachments/assets/b5210546-6a40-4940-8e4f-874818a614fb"
/>
<img width="907" height="757" alt="Screenshot 2026-02-15 at 15 43 52"
src="https://github.com/user-attachments/assets/ead5b9a8-1989-4d68-9640-583da6233711"
/>
<img width="1002" height="731" alt="Screenshot 2026-02-15 at 15 43 38"
src="https://github.com/user-attachments/assets/38accb8c-f5d5-4bfc-b245-06389849810b"
/>
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Touches migration/upgrade commands that write to core metadata tables
and adjust field/view definitions, plus changes dev seeding to create
`core.file` records; mistakes could affect UI visibility or seed
integrity across workspaces.
>
> **Overview**
> Adds a new `upgrade:1-18:backfill-standard-views-and-field-metadata`
command that, per workspace, marks specific fields as `isSystem`,
normalizes morph-relation field `label`/`icon` to
`Target`/`IconArrowUpRight`, and backfills missing standard
`view`/`viewField` rows for `attachment`, `noteTarget`, `taskTarget`,
`timelineActivity`, and `workspaceMember`, followed by cache
invalidation + metadata version bump.
>
> Refactors morph-relation deduplication to pick a single survivor per
`morphId` using a new `pickMorphGroupSurvivor` rule (prefer active +
non-system, then smallest id), with new unit tests.
>
> Updates standard metadata generators and snapshots to reflect the new
system flags and default view fields, and rewrites attachment dev
seeding to populate the new `file` (FILES field) JSON and create
corresponding `core.file` entries via `FileStorageService.writeFile`
with workspace-scoped file IDs.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
b1939bbf6f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
- Introduced a new `CommandMenuEditColorOption` component to allow users to select and edit the color of navigation menu items.
- Integrated the color option into existing components: `CommandMenuEditLinkItemView`, `CommandMenuEditObjectViewBase`, and `CommandMenuNavigationMenuItemEditPage`.
- Updated the `useSaveNavigationMenuItemsDraft` and `useUpdateNavigationMenuItemInDraft` hooks to handle color changes in navigation menu items.
- Enhanced the user interface by providing a dropdown for color selection, improving customization options for navigation menu items.
- Changed default colors for `allCompanies`, `allPeople`, `allTasks`, and `allNotes` from indigo and teal to blue and turquoise, respectively.
- This update enhances visual consistency and improves the user interface of the navigation menu.
- Introduced an optional `color` field in the `CreateNavigationMenuItemInput`, `UpdateNavigationMenuItemInput`, and `NavigationMenuItem` types.
- Updated related GraphQL fragments to include the new `color` field for consistency across queries and mutations.
- Ensured that the `color` property is reflected in the `CreateNavigationMenuItemMutation` and `DeleteNavigationMenuItemMutation` responses.
- This change enhances the customization options for navigation menu items.
## Summary
- The `customDomain` field was accidentally removed from the
`currentWorkspace` GraphQL query fragment in #16016 (Nov 2025), when
`workspaceCustomApplication { id }` was added in its place rather than
alongside it.
- This caused the custom domain settings page to never display the
configured domain value, the reload/delete buttons, or the DNS records —
since `currentWorkspace.customDomain` was always `undefined`.
- Restores the missing field in the query fragment.
## Test plan
- [ ] Navigate to Settings > Domains on a workspace with a custom domain
configured
- [ ] Verify the custom domain value appears in the input field
- [ ] Verify the Reload and Delete buttons are visible
- [ ] Verify DNS records are displayed
Made with [Cursor](https://cursor.com)
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
- Introduced a new `color` property in the `NavigationMenuItem` entity and updated the corresponding DTOs and input types to support it.
- Modified migration to add the `color` column to the `navigationMenuItem` table.
- Updated various utility functions and constants to handle the new `color` property.
- Enhanced the `createStandardNavigationMenuItemFlatMetadata` function to assign default colors based on item type.
- Adjusted tests and snapshots to reflect the inclusion of the `color` property.
## Summary
- Add `@mention` support to the AI Chat text input by replacing the
plain textarea with a minimal Tiptap editor and building a shared
`mention` module with reusable Tiptap extensions (`MentionTag`,
`MentionSuggestion`), search hook (`useMentionSearch`), and suggestion
menu — all shared with the existing BlockNote-based Notes mentions to
avoid code duplication
- Mentions are serialized as
`[[record:objectName:recordId:displayName]]` markdown (the format
already understood by the backend and rendered in chat messages), and
displayed using the existing `RecordLink` chip component for visual
consistency
- Fix images in chat messages overflowing their container by
constraining to `max-width: 100%`
- Fix web_search tool display showing literal `{query}` instead of the
actual query (ICU single-quote escaping issue in Lingui `t` tagged
templates)
## Test plan
- [ ] Open AI Chat, type `@` and verify the suggestion menu appears with
searchable records
- [ ] Select a mention from the dropdown (via click or keyboard
Enter/ArrowUp/Down) and verify the record chip renders inline
- [ ] Send a message containing a mention and verify it appears
correctly in the conversation as a clickable `RecordLink`
- [ ] Verify Enter sends the message when the suggestion menu is closed,
and selects a mention when the menu is open
- [ ] Verify images in AI chat responses are constrained to the
container width
- [ ] Verify the web_search tool step shows the actual search query
(e.g. "Searched the web for Salesforce") instead of `{query}`
- [ ] Verify Notes @mentions still work as before
Made with [Cursor](https://cursor.com)
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
- Introduced a new variable `isAddMenuItemButtonVisible` to streamline the visibility logic for the add menu item button based on edit mode and dragging state.
- Updated the rendering condition for the add menu item button to use the new variable for improved clarity and maintainability.
- Introduced `StyledWorkspaceDroppableList` to replace a div for better styling in the Navigation Drawer.
- Updated `StyledFolderDroppableContent` to include flex properties and gap for consistent spacing.
Gmail 429/403 rate-limit responses include an explicit retry-after
timestamp, usually ~15 minutes out.
The exponential backoff starts at 1 minute, so the channel burns through
all 5 retry attempts before the window actually closes and gets marked
as permanently failed.
Adds throttleRetryAfter to the message channel and uses max(backoff,
retryAfter) in isThrottled().
## Context
Creating a new object should now also create its record page layout,
tabs and widgets, including fields widget with its associated views/view
fields.
Custom objects record page layout fields widgets don't have section per
default
Note: I had to enable some widget creation through the custom API but we
should now implement proper validation (which should be minimal since
there is usually only the configuration type in the configuration
(except for FIELDS widget which contains a viewId)
Next step: Create view field should also create a viewField for the
FIELDS_WIDGET view (we should also add in the FIELDS widget
configuration a newFieldDefaults which will contain default visibility
and position to apply to the new view field)
The feature is still gated behind an env variable (this was necessary
for workspace creation, not so much here in this case but I prefer to
keep the same path for consistence)
This PR addresses TODO comments and improves code quality:
### 1. PullRequestItem.tsx
- Replaced `react-tooltip` with `twenty-ui` `AppTooltip` component
- Removed TODO comment
- Uses internal component library for consistency
### 2. MenuItemAvatar.tsx
- Refactored to use `MenuItem` internally, eliminating code duplication
- Removed about 63 lines of duplicate code
- Removed TODO comment as the merge is now complete
---------
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
- moves workspace:* dependencies to dev-dependencies to avoid spreading
them in npm releases
- remove fix on rollup.external
- remove prepublishOnly and postpublish scripts
- set bundle packages to private
- add release-dump-version that update package.json version before
releasing to npm
- add release-verify-build that check no externalized twenty package
exists in `dist` before releasing to npm
- works with new release github action here ->
https://github.com/twentyhq/twenty-infra/pull/397
## Split twenty-sdk build into separate Node and browser targets
The SDK was bundling Node.js code (CLI, SDK API) and browser code (UI
components, front-component renderer) through a single Vite config. This
caused incorrect externalization — Node builtins leaked into browser
bundles and browser-specific chunking logic applied to CLI output.
This PR splits the build into `vite.config.node.ts` and
`vite.config.browser.ts` so each target gets the right externals and
output format.
Also includes a few housekeeping renames:
- `front-component` export path → `front-component-renderer` (matches
what it actually is)
- `front-component-common` merged into `front-component-api` (was a
needless extra module)
#17147 removed the root ./nx script, but wrapper-mode artifacts were
still present (installation in
[nx.json](https://github.com/twentyhq/twenty/blob/main/nx.json) and
tracked
[nxw.js](https://github.com/twentyhq/twenty/blob/main/.nx/nxw.js),
leaving an inconsistent setup.
This PR completes that cleanup by:
- removing installation from nx.json
- deleting tracked nxw.js
- ignoring nxw.js to prevent accidental re-introduction
Validated that Nx still works via yarn nx / npx nx.
Fixes issue where tabs were synchronized when opening two records of the
same type in show page and side panel.
The root cause was that tab instance IDs were only based on
`pageLayoutId`, causing all records using the same page layout to share
the same tab state.
This change includes the record ID in the tab instance ID, making tabs
unique per record while maintaining backward compatibility for cases
where no record ID is available.
Fixes#17522
---------
Co-authored-by: Eruis <github@eruis.example>
# Introduction
Splitting the create syncable entity rule into dedicated scoped skills
in order to favorise multi agent pattern with more granular context
### Multi-Agent Workflow
For parallel development:
1. **Agent 1** (Foundation): Complete Step 1 first - unblocks everyone
2. **Agent 2** (Cache): Can start immediately after Step 1
3. **Agent 3** (Builder): Can work in parallel with Agent 4 after Step 1
4. **Agent 4** (Runner): Can work in parallel with Agent 3 after Step 1
5. **Agent 5** (Integration): Assembles everything after Steps 2-4
## Summary
- Removed `vite-plugin-dts` (which used `tsc` internally) from the Vite
build and replaced DTS generation with `tsgo` as a sequential post-build
step — **~0.7s vs 1-10s**.
- Disabled `reportCompressedSize` to skip gzip computation for 64 output
files.
- Converted the build target to an explicit `nx:run-commands` executor
with sequential `vite build` → `tsgo` commands.
The `twenty-emails:build` step goes from ~22s to ~7s under load.
## Test plan
- [x] `nx build twenty-emails` produces both JS (64 files) and DTS (74
files) correctly
- [x] `dist/index.d.ts` exports match the source `src/index.ts`
- [x] Full `nx build twenty-server` succeeds end-to-end
- [ ] CI build passes
Made with [Cursor](https://cursor.com)
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
# Introduction
Avoid sending flat entity that contains server specific properties such
as foreignKey aggregators and universal properties by transpiling from
flat entity to scalar flat entity
A scalar flat entity is the exact match with the entities columns
Following https://github.com/twentyhq/twenty/pull/17622
## Summary
- **Fix token renewal endpoint**: Use `/metadata` instead of `/graphql`
for token renewal in agent chat, fixing auth issues
- **Improve tool display**: Add `load_skills` support, show formatted
tool names (underscores → spaces) with finish/loading states, display
tool icons during loading, and support custom loading messages from tool
input
- **Refactor workflow agent management**: Replace direct
`AgentRepository` access with `AgentService` for create/delete/find
operations in workflow steps, improving encapsulation and consistency
- **Simplify Apollo client usage**: Remove explicit Apollo client
override in `useGetToolIndex`, add `AgentChatProvider` to
`AppRouterProviders`
- **Fix load-skill tool**: Change parameter type from `string` to `json`
for proper schema parsing
- **Update agent-chat-streaming**: Use `AgentService` for agent
resolution and tool registration instead of direct repository queries
## Test plan
- [ ] Verify AI agent chat works end-to-end (send message, receive
response)
- [ ] Verify tool steps display correctly with icons and proper messages
during loading and after completion
- [ ] Verify workflow AI agent step creation and deletion works
correctly
- [ ] Verify workflow version cloning preserves agent configuration
- [ ] Verify token renewal works when tokens expire during agent chat
Made with [Cursor](https://cursor.com)
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
This PR aims to fix: #17408
Main modification includes adding a new column for dropdown in the
object permission rule table (containing options for editing and
removal). Removal logic is implemented using existing pattern with hook
```useResetObjectPermission``` (relies on existing hooks
```useUpsertFieldPermissionInDraftRole``` and
```useUpsertObjectPermissionInDraftRole```).
Feel free to suggest any necessary changes. Functionality (unrestricted
access is allowed when permission removal is applied) is already tested.
Demo video:
https://drive.google.com/file/d/1M4RYHw-JEhDdJksKkL3MY_VyXAV3aS9I/view?usp=sharing
---------
Co-authored-by: Etienne <45695613+etiennejouan@users.noreply.github.com>
As attachment files have migrated from fullPath to file files field,
need to migrate richText logic to fit to new attachment file handling +
data migration
In this PR
- Content tab for marketplace apps and installed apps: complies with
[figma](https://www.figma.com/design/xt8O9mFeLl46C5InWwoMrN/Twenty?node-id=34845-126856);
addition of field section showing fields added to standard objects;
initiative: arrow opens a sub-table of fields rows. (suggested because
1/ for marketplace apps we cannot redirect to the actual object page in
settings since the object does not exist yet in the workspace 2/ since
we dont have an quick "go back to application page" option, it can be
annoying to be redirected to a different setting page when we just want
to look at the content of the app objects)
- Permission tab for marketplace apps and installed apps
- left to do - settings tab (in another PR)
There are breaking changes but it's behind a feature flag not exposed
(access to marketplace) so not problematic
marketplace apps
https://github.com/user-attachments/assets/4c660101-50fc-47ce-b90a-8d6f17db5e74
installed apps
https://github.com/user-attachments/assets/c9229ee1-e75f-4cad-8766-758b2c5b37b4
## Summary
This PR adds **metadata eventing**: when schema metadata
(objectMetadata, fieldMetadata, view, viewField, etc.) is created,
updated, or deleted, we now emit events that can trigger webhooks and
future audit logs. It also adds **actor context** (`userId`,
`workspaceMemberId`) to those events so subscribers can attribute
changes to a user or API key.
## What changed
### 1. Metadata eventing (first commit)
- **MetadataEventEmitter**
New service that emits batch events after successful workspace
migrations. Event names follow `metadata.{entity}.{action}` (e.g.
`metadata.objectMetadata.created`, `metadata.fieldMetadata.updated`).
- **MetadataEventsToDbListener**
Listens for metadata events and enqueues webhook delivery via
`CallWebhookJobsForMetadataJob`.
- **Event types** (twenty-shared)
`MetadataEventAction`, `MetadataEventBatch`, and record event types for
create/update/delete.
- **WorkspaceMigrationValidateBuildAndRunService**
Calls the metadata event emitter after running migrations so all
metadata changes (from any module) emit events from a single place.
- **Create events**
Sourced from the create action payload (`flatEntity` /
`flatFieldMetadatas`) because `fromToAllFlatEntityMaps` does not provide
a before/after diff for creates. Update/delete events still use the
fromToAllFlatEntityMaps comparison.
### 2. Actor context (second commit)
- **MetadataEventEmitter**
Accepts optional `actorContext` (`userId`, `workspaceMemberId`) and
includes it on emitted batch events.
- **WorkspaceMigrationValidateBuildAndRunService**
Passes `actorContext` from the request into the metadata event emitter.
- **Metadata resolvers & services**
All metadata modules resolve `@AuthUser({ allowUndefined: true })` and
`@AuthUserWorkspaceId()` and pass `userId` and `workspaceMemberId`
through to the migration/event pipeline. Both are optional so
API-key–authenticated requests (no user) still emit events without a
user identity.
Shared some questions on Discord about the PR.
---------
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
Co-authored-by: prastoin <paul@twenty.com>
# Introduction
## Use `flatEntityTranspilers.toScalarFlatEntity` in create action
handler
**Changes:**
- Modified
`BaseWorkspaceMigrationRunnerActionHandlerService.insertFlatEntitiesInRepository()`
to transform flat entities using `toScalarFlatEntity()` before database
insertion
**What it does:**
Strips out TypeORM relation objects and metadata-only properties,
ensuring only scalar values (primitives, IDs, dates) are inserted into
the database.
**Benefits:**
- **Type Safety:** Prevents accidental insertion of nested objects that
TypeORM can't persist
- **Consistency:** All 17+ create action handlers automatically benefit
from proper data transformation
- **Single Source of Truth:** Centralized logic for what constitutes a
database-insertable entity
- **Prevents Errors:** Uses entity configuration schema to ensure only
valid properties are included
## Usage
```ts
protected async insertFlatEntitiesInRepository({
flatEntities,
queryRunner,
}: {
queryRunner: QueryRunner;
flatEntities: MetadataFlatEntity<TMetadataName>[];
}) {
const metadataEntity =
ALL_METADATA_ENTITY_BY_METADATA_NAME[this.metadataName];
const repository = queryRunner.manager.getRepository(metadataEntity);
const scalarFlatEntities = flatEntities.map((flatEntity) =>
flatEntityTranspilers.toScalarFlatEntity({
flatEntity,
metadataName: this.metadataName,
}),
);
await repository.insert(scalarFlatEntities);
}
```
## Upcoming refactor
About to completely split the
`packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-runner/interfaces/workspace-migration-runner-action-handler-service.interface.ts`
into three dedicated boilerplate one for each action type `create`
`delete` `update` will provide a better interfacing and typing + will
allow not requiring the user to provide the metadata execute handler as
required
## Context
Prefill the FIELDS widget configuration in standard page layouts during
workspace creation, linking each widget to a dedicated view with
positioned fields organized into sections (via view field groups)
We wanted something very declarative (by manually setting position and
visibility of each field per standard object).
In this PR I've generated all the compute- utils via AI (😨) for
position/visibility, we'll probably want to confirm with the product
which ordering/visibility we want for each standard object but I feel
like this can be merged as it is since it's behind a feature flag and
this will unblock the work on the frontend
## Summary
Fixes `EMFILE: too many open files, watch` crash that most of the team
is hitting on macOS when running `yarn start` or `npx nx start
twenty-server`.
Adds `rimraf dist` before `nest start --watch` in the `start` and
`start:debug` targets, so the watcher starts with a clean output
directory.
## Root cause
The NestJS SWC compiler (`@nestjs/cli@11`) creates **three overlapping
chokidar watchers** when `nest start --watch` runs:
| Watcher | Watches | Purpose | Handles |
|---|---|---|---|
| SWC CLI (`@swc/cli`) | `src/` | Detects file changes → recompiles |
~1,730 |
| NestJS `watchFilesInSrcDir` | `src/` | Workaround: SWC misses new
files | shared with above |
| NestJS `watchFilesInOutDir` | **`dist/`** | Detects compiled `.js` →
restarts server | **~3,548** |
`@nestjs/cli@11` ships with **chokidar v4**, which dropped macOS
`fsevents` support and uses `fs.watch()` instead — creating **one file
descriptor per directory**. Chokidar v3 used a single `fsevents` kernel
subscription per directory tree.
Total: **~5,000+ `fs.watch()` handles**, far exceeding the default macOS
`ulimit -n` of ~2,560.
### Why it broke now
PR #17851 (`15fc850212`) changed the `start` target from `dependsOn:
["build"]` to `dependsOn: ["^build"]`, removing the `rimraf dist && nest
build` pre-step. Without that cleanup, `dist/` accumulated stale
directories from code reorganizations (e.g. `application-layer/` →
`application/` rename), growing to ~3,548 directories vs ~1,730 in a
clean build.
## What this PR does
Adds `rimraf dist &&` before `nest start --watch` in the `start` and
`start:debug` commands. This ensures `dist/` starts empty and only
contains directories matching the current `src/` structure (~1,730),
keeping watcher count in the ~3,400 range.
We still get the startup speed improvement from #17851 (no redundant
full SWC build), since `rimraf dist` is ~instant while the removed `nest
build` step took 30-60s.
## Future considerations
As the codebase grows, even a clean `dist/` will eventually approach the
macOS default `ulimit -n` (~2,560). Options to consider if that happens:
1. **Yarn resolution to force chokidar 3.6.0** — restores `fsevents`,
reducing watcher count from ~5,000 to ~3-5. This is what Vite 7 does
internally. Simple and effective, but pins to an older major version.
2. **Patch `@nestjs/cli`** to skip the `dist/` watcher — the
`watchFilesInOutDir` watcher accounts for ~65% of all handles and only
exists because NestJS doesn't have a direct hook into SWC's
compilation-complete event. Could be removed via `yarn patch`.
3. **Replace `nest start --watch` entirely** — use `node
--watch-path=src` (Node 22+) with `@swc-node/register` for on-the-fly
compilation. Uses a single native watcher regardless of directory count.
Requires rethinking asset copying (`watchAssets` in `nest-cli.json`).
4. **Wait for upstream fix** — NestJS CLI should either re-add
`fsevents` support or use Node's recursive `fs.watch()` option
(available since Node 20) instead of per-directory watchers.
## Test plan
- [ ] Run `npx nx start twenty-server` on macOS — server starts without
EMFILE error
- [ ] Run `npx nx start:debug twenty-server` — debug mode starts without
EMFILE error
- [ ] Edit a `.ts` file while server is running — hot reload still works
- [ ] Run `yarn start` (frontend + backend + worker) — no crashes
Made with [Cursor](https://cursor.com)
Co-authored-by: Cursor <cursoragent@cursor.com>
## Remove Recoil from twenty-ui
Completely removes the `recoil` dependency from `twenty-ui` by
converting all atoms, hooks, and providers to Jotai equivalents.
### twenty-ui
- `createState` now returns a Jotai `PrimitiveAtom` instead of a Recoil
atom
- `iconsState`, `IconsProvider`, `useIcons` converted to Jotai
(`useSetAtom`, `useAtomValue`)
- `RecoilRootDecorator` now uses Jotai `Provider` (name kept for compat)
- Deleted unused `invalidAvatarUrlsState` (Avatar already uses
`invalidAvatarUrlsAtomV2`)
- Removed `recoil` from `package.json`
### twenty-front
- Created local Recoil `createState` at
`@/ui/utilities/state/utils/createState` for ~112 state files still on
Recoil
- Updated all imports accordingly
- Removed `iconsState` from Recoil snapshot preservation in `useAuth`
(lives in Jotai store now)
This update introduces an icon property for the workflowsFolder in the standard navigation menu items, enhancing the metadata structure. The icon is also integrated into the relevant utility functions to ensure consistency across the navigation menu item representations.
This update introduces a new prop, alignWithCommandMenuTopBar, to the StyledButtonWrapper, allowing the button to adjust its position based on the command menu's state and the navigation menu's edit mode. The changes improve the user interface for mobile users by ensuring better alignment and visibility of the command menu toggle button.
This change standardizes the import statement for the FOLDER_ICON_DEFAULT constant across multiple files, ensuring uniformity in naming conventions and improving code clarity.
This update modifies the PageChangeEffect component to utilize useRecoilCallback, allowing the command menu to close conditionally based on the current page state. The previous logic has been streamlined to enhance readability and maintainability.
This update reorganizes the import statements in the NavigationDrawerSectionForWorkspaceItems.tsx file for improved clarity and consistency. The changes include moving some imports to maintain a logical order and enhance readability.
This update introduces the commandMenuPage state to the PageChangeEffect component, preventing the command menu from closing when editing a navigation menu item. Additionally, the WorkspaceNavigationMenuItems component now utilizes the useNavigate hook for improved navigation handling, ensuring links are only followed if they are non-empty strings.
This update introduces a new feature flag, IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED, to the seedFeatureFlags utility, enabling the editing of navigation menu items within the workspace.
- Updated import statements in `CurrentWorkspaceMemberOrphanNavigationMenuItems` for improved organization.
- Reformatted conditional checks in `WorkspaceNavigationMenuItemsFolder` for enhanced readability.
- Adjusted import statements in `CurrentWorkspaceMemberNavigationMenuItems` and `CurrentWorkspaceMemberOrphanNavigationMenuItems` for consistency.
- Reformatted conditional checks in `CurrentWorkspaceMemberNavigationMenuItems` and `NavigationDrawerItemForObjectMetadataItem` for better clarity.
- Enhanced readability of the `isRecord` and `isView` variable assignments in `NavigationMenuItemIcon` and `NavigationDrawerItemForObjectMetadataItem` components.
- Split the combined hook `useAddFolderAndLinkToNavigationMenu` into two separate hooks: `useAddFolderToNavigationMenu` and `useAddLinkToNavigationMenu`.
- Updated `CommandMenuNewSidebarItemMainMenu` to utilize the new hooks for better modularity and clarity in handling folder and link additions to the navigation menu.
- Added command menu state management to NavigationMenuEditModeBar for improved navigation item handling.
- Implemented logic to close the command menu when specific navigation item pages are active, enhancing user experience during editing.
- Refactored component to utilize new command menu state, ensuring better synchronization between navigation and command menu actions.
- Added addToNavFallbackDestination to NavigationDropTargetContext for improved drag-and-drop functionality.
- Updated NavigationDrawerSectionForWorkspaceItems to utilize the new fallback destination logic, enhancing visibility and handling of orphan navigation items.
- Refactored conditional rendering to accommodate the new drop target behavior.
- Added support for fallback destinations when dragging items from the navigation menu.
- Introduced state management for orphan items and improved handling of drag events.
- Updated drag update logic to accommodate new fallback destination behavior.
- Refactored drag end logic to ensure proper handling of navigation drop actions.
- Added a new component, ObjectIconWithViewOverlay, to display icons with an overlay for navigation menu items.
- Updated CommandMenuNewSidebarItemViewPickerSubView to utilize the new overlay icon feature.
- Refactored NavigationMenuItemIcon to conditionally render the overlay based on item type.
- Modified NavigationDrawerItemForObjectMetadataItem to support the new icon rendering logic.
- Improved AddToNavigationDragHandle to accommodate custom icon content display.
- Introduced an optional `icon` field to the `NavigationMenuItem` type in GraphQL schemas.
- Updated related input types and fragments to include the new `icon` field.
- Refactored components to utilize the new icon feature, including `CommandMenuFolderInfo` and `WorkspaceNavigationMenuItems`.
- Replaced the previous folder name update hook with a more versatile `useUpdateFolderInDraft` hook to handle both name and icon updates.
- Added a default folder icon constant for better management of folder icons across the application.
- Added new scalar type `Upload` to support file uploads.
- Introduced multiple input types for creating and managing various entities, including `ActivateWorkspaceInput`, `CreateAgentInput`, and `CreateApiKeyInput`.
- Expanded the schema with new enums such as `AllMetadataName` and `AnalyticsType` for better categorization of metadata and analytics events.
- Added new mutation inputs for workflow management, including `CreateWorkflowVersionEdgeInput` and `DeleteWorkflowVersionStepInput`.
- Implemented additional filtering capabilities with `DateTimeFilter` to enhance query flexibility.
These changes improve the overall functionality and usability of the GraphQL API, enabling more robust interactions with the backend.
Refactored the logic for determining if the processed item is a view or record by using an array and the includes method for improved readability. Simplified the label assignment logic to enhance clarity. This change contributes to better maintainability and consistency in the CommandMenu components.
Introduced new components for managing sidebar item creation flows, including CommandMenuNewSidebarItemObjectFlow and CommandMenuNewSidebarItemViewFlow. Updated CommandMenuNewSidebarItemMainMenu to utilize the new hooks for adding folders and links, enhancing the overall structure and maintainability of the CommandMenu. This refactor improves user experience by streamlining the process of adding new items to the navigation menu.
Replaced string literals with the NavigationMenuItemType enum in the getObjectMetadataForNavigationMenuItem tests. This change enhances type safety and consistency across the test suite, aligning with recent updates in the codebase.
Introduced new components for managing sidebar item creation flows, including CommandMenuNewSidebarItemObjectFlow and CommandMenuNewSidebarItemViewFlow. Updated CommandMenuNewSidebarItemMainMenu to utilize the new hooks for adding folders and links, enhancing the overall structure and maintainability of the CommandMenu. This refactor improves user experience by streamlining the process of adding new items to the navigation menu.
Replaced string literals with the NavigationMenuItemType enum in the getObjectMetadataForNavigationMenuItem tests. This change enhances type safety and consistency across the test suite, aligning with recent updates in the codebase.
Updated the normalizeUrl function to return an empty string for empty or whitespace-only input. This change improves the function's robustness and ensures it handles edge cases more gracefully. Additionally, variable names were clarified for better readability.
Updated the CommandMenuEditFolderPickerSubView and CommandMenuNavigationMenuItemEditPage components to streamline folder selection handling. Removed the useNavigationMenuItemEditSubView hook and replaced it with local state management for improved clarity and maintainability. The folder picker now directly manages its open/close state, enhancing the user experience and reducing complexity in the component structure.
Updated various CommandMenu components and utilities to replace string literals for item types with the NavigationMenuItemType enum. This change enhances type safety, consistency, and maintainability across the codebase, reducing the risk of errors related to item type handling.
Replaced string literals for item types in CommandMenuFolderInfo and CommandMenuLinkInfo components with the NavigationMenuItemType enum for improved type safety and consistency across the codebase. This change enhances maintainability and reduces the risk of errors related to item type handling.
Deleted outdated test files for getIconBackgroundColorForPayload, getNavigationMenuItemIconColors, and isWorkspaceDroppableId functions to streamline the test suite and eliminate redundancy. These tests are no longer necessary due to recent refactoring and updates in the utility functions.
- Enhanced the formatting of test cases in recordIdentifierToObjectRecordIdentifier, sortNavigationMenuItems, and validateAndExtractWorkspaceFolderId tests for better clarity.
- Added comments to the CommandMenuNewSidebarItemViewPickerSubView component to clarify prop spreading, improving maintainability and understanding of the code.
Refactored the CommandMenuNavigationMenuItemEditPage component to replace multiple if statements with a switch statement for improved readability and maintainability. This change enhances the handling of different navigation menu item types, ensuring clearer logic flow and reducing code duplication.
Updated the validateAndExtractWorkspaceFolderId utility to utilize the isNonEmptyString guard for improved validation of workspace folder IDs. This change enhances error handling by ensuring that only non-empty strings are accepted as valid folder IDs, contributing to better type safety and clarity in the navigation menu item logic.
Refactored navigation menu item components and hooks to replace the deprecated NAVIGATION_MENU_ITEM_TYPE constant with a new NavigationMenuItemType enum for improved type safety and clarity. Updated all relevant imports and usages across the codebase to ensure consistency and maintainability.
Refactored navigation menu item components and hooks to replace the NAVIGATION_MENU_ITEM_DROPPABLE_IDS constant with a new NavigationMenuItemDroppableIds enum for improved type safety and clarity. Updated all relevant imports and usages across the codebase to ensure consistency and maintainability.
Refactored the navigation menu item components to replace the existing NAVIGATION_SECTIONS constant with a new NavigationSections enum for improved type safety and clarity. Updated related components and utility functions to utilize the new enum, ensuring consistency across the codebase. Removed the deprecated NavigationSectionId type as part of this transition.
Refactored navigation menu item components and hooks to replace the old import paths for navigation sections with a new centralized import. Introduced two new utility functions, computeInsertIndexAndPosition and normalizeUrl, to enhance the management of navigation menu items and URL normalization. Added corresponding unit tests to ensure functionality and reliability of the new utilities.
Added a new enum, CommandMenuNavigationItemActions, to centralize action identifiers for the command menu navigation items. Updated CommandMenuEditOrganizeActions and getOrganizeActionsSelectableItemIds to utilize this enum, enhancing code consistency and maintainability across the command menu functionality.
Refactored multiple components and hooks to replace the deprecated useSelectedNavigationMenuItemEditData with more granular hooks: useSelectedNavigationMenuItemEditItem, useSelectedNavigationMenuItemEditItemLabel, and useSelectedNavigationMenuItemEditItemObjectMetadata. This change enhances code clarity and modularity, improving the management of selected navigation menu items across the command menu functionality.
Updated multiple components and hooks to utilize the new useDraftNavigationMenuItems hook, enhancing the management of draft navigation menu items. Removed the deprecated useNavigationMenuItemEditFolderData hook and adjusted related logic to ensure consistency across the command menu functionality.
Introduced two new components, CommandMenuFolderInfo and CommandMenuLinkInfo, to enhance the command menu functionality. These components allow users to edit folder names and link labels directly within the command menu, improving user experience and interaction. Updated CommandMenuPageInfo to integrate these new components based on the selected item type.
Adjusted the coverage thresholds in the Jest configuration to 48% for lines and 48% for functions, reflecting a revised standard for test coverage requirements.
Removed unnecessary checks for drop destination IDs in the useHandleAddToNavigationDrop hook. The logic now directly checks for defined folder IDs, streamlining the drop handling process and improving code readability.
Updated the coverage thresholds in the Jest configuration to 48.6% for lines and 48.4% for functions, reflecting a revised standard for test coverage requirements.
Adjusted the coverage thresholds in the Jest configuration to improve code quality metrics. The new thresholds are set to 49.5% for statements, 49.5% for lines, and 49.4% for functions, reflecting a more stringent requirement for test coverage.
Refactored existing test cases for navigation menu item utilities to improve clarity and consolidate similar assertions. Key changes include:
- Simplified test descriptions for better understanding.
- Combined multiple assertions into single tests where applicable.
- Enhanced coverage for edge cases, ensuring robust validation of utility functions.
These updates aim to maintain the reliability of navigation menu item utilities while improving the overall readability of the test suite.
Introduced a new test suite for the calculateNewPosition function, covering various scenarios including edge cases for moving items in a draggable list. The tests validate the correct position calculations when items are moved to the beginning, end, or within the list, ensuring reliable behavior of the drag-and-drop functionality.
- Updated the component to accept a new `customIconContent` prop for better icon customization.
- Refactored the payload registration logic to ensure it is registered on mouse events, improving drag-and-drop functionality.
- Cleaned up the code structure for better readability and maintainability.
- Introduced AddToNavigationDragHandleIcon to manage custom icon content and standard icons more effectively.
- Removed the AddToNavigationIconSlot component to streamline the codebase.
- Updated CommandMenuNewSidebarItemRecordItem and AddToNavigationDragHandle components to utilize the new icon handling approach.
Introduced new test files for various utility functions related to navigation menu items. The tests cover the following functionalities:
- `getDropTargetIdFromDestination`: Validates the correct drop target ID generation based on different droppable IDs.
- `getIconBackgroundColorForPayload`: Ensures the correct background color is returned for different payload types.
- `getNavigationMenuItemIconColors`: Confirms the correct theme colors are returned for various navigation menu item types.
- `isWorkspaceDroppableId`: Tests the identification of workspace droppable IDs under various conditions.
These tests enhance the reliability of the navigation menu item utilities by ensuring expected behaviors are maintained.
Updated the `useCommandMenu`, `PageDragDropProvider`, and `useHandleAddToNavigationDrop` hooks to utilize the new `getSnapshotValue` utility for improved state access. This change enhances code clarity and consistency by reducing direct interactions with the Recoil state. Additionally, refactored the navigation drop handling logic to encapsulate repetitive code into a new function, `openEditForNewNavItem`, simplifying the process of opening edit modes for new navigation items.
Added a new Recoil atom `addToNavPayloadRegistryState` to manage the state of draggable items in the navigation menu. Updated the `CommandMenuItemWithAddToNavigationDrag` component to utilize this state for handling drag-and-drop operations. Refactored the drag update and drop handling logic in `PageDragDropProvider` and `useHandleAddToNavigationDrop` to leverage the new state management, improving the overall drag-and-drop functionality and ensuring better item tracking during interactions. Removed the deprecated utility functions related to draggable IDs.
Added new components `CommandMenuAddToNavDraggablePlaceholder` and `CommandMenuAddToNavDroppable` to facilitate drag-and-drop interactions within the navigation menu. Updated existing components to integrate these new features, allowing users to rearrange items more intuitively. Enhanced the `CommandMenuItemWithAddToNavigationDrag` to support drag indices for better item positioning during drag operations. Refactored related components to ensure compatibility with the new drag-and-drop context.
Replaced 'objectNameSingular' with 'itemType' in the isLocationMatchingNavigationMenuItem utility to improve clarity and consistency. Updated corresponding tests to reflect this change, ensuring accurate navigation item matching based on item types.
Updated the logic for moving navigation menu items to account for folder structure. The changes ensure that items are moved within their respective folders, enhancing the accuracy of item positioning. This includes adjustments to how siblings are identified and managed during move operations.
Refactored the useWorkspaceSectionItems hook to always push folder items into the accumulator, removing the conditional check for defined folder children. This change streamlines the logic for handling navigation menu items, ensuring that all folder items are consistently processed.
Introduced unit tests for the recordIdentifierToObjectRecordIdentifier function, validating its behavior with various input scenarios. The tests ensure correct mapping of record identifiers to object records, including handling of avatar URLs and link generation for specific object types, enhancing overall code reliability.
Introduced unit tests for the filterWorkspaceNavigationMenuItems and getObjectMetadataForNavigationMenuItem utility functions. These tests validate the filtering of navigation menu items based on userWorkspaceId and ensure correct retrieval of object metadata for various item types, enhancing overall code reliability.
Enhanced the error messages for navigation menu item creation to specify that an external link is now a valid option. This change improves user guidance by clarifying the requirements for creating navigation menu items.
Introduced comprehensive unit tests for utility functions related to navigation menu items, including normalization of URLs, computation of insert indices and positions, and validation of workspace folder IDs. These tests enhance code reliability and ensure correct functionality across various scenarios.
Included a link property set to null in various navigation menu item metadata creation functions. This change ensures that the link attribute is consistently defined across different components, improving data structure integrity and preparing for future enhancements.
Updated the AddToNavigationIconSlot component to check for valid icon types by allowing only strings, numbers, and booleans to return null. This change enhances the component's robustness by ensuring that only appropriate icon types are processed, preventing potential rendering issues.
Added folderUniversalIdentifier to the buildStandardFlatNavigationMenuItemMaps and createStandardNavigationMenuItemFolderFlatMetadata functions. This enhancement ensures that the folder's unique identifier is correctly incorporated into the navigation menu item metadata, improving data integrity and consistency across the application.
Modified the folderContentDropDisabled assignment to use isWorkspaceFolder, ensuring accurate handling of drop disabled states based on the current workspace context. This change improves the component's functionality and responsiveness to workspace conditions.
Updated the AddToNavigationIconSlot component to return null when the icon prop is not a function. This change improves the component's robustness by ensuring that only valid icon components are rendered, preventing potential runtime errors.
Updated the searchRecords assignment to safely access nested properties in searchData, ensuring robust handling of potential undefined values. This change improves the reliability of the component when processing search results.
Updated the comparison logic in the useSaveNavigationMenuItemsDraft hook to include targetRecordId, ensuring accurate detection of changes in navigation menu items. This enhancement improves the functionality of draft saving by considering all relevant identifiers.
Refactored the sorting logic for active non-system object metadata items in both CommandMenuNewSidebarItemPage and useFilteredObjectMetadataItems hooks. The sorting now utilizes the spread operator to create a new array before sorting, improving code clarity and consistency across components.
Modified the logic for displaying the contextual description in the CommandMenuItemWithAddToNavigationDrag component. The description now defaults to the provided description when not hovered, improving clarity and user experience.
Added a key prop using selectedItem.id to the CommandMenuEditLinkItemView component to ensure proper rendering and reconciliation of list items in React. This change enhances performance and prevents potential rendering issues when the selected item changes.
Refactored the CommandMenuNavigationMenuItemEditPage and related hooks to enhance item type checks and streamline component logic. Updated imports for better organization and clarity, ensuring consistent handling of navigation menu item types. This change simplifies the logic for rendering components based on selected item types, improving overall code readability and maintainability.
2026-02-10 14:08:37 +05:30
Abdul RahmanGitHubCopilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
Refactored the CommandMenuEditFolderPickerSubView to utilize a new custom hook, useFolderPickerSelectionData, for improved folder selection management. This change simplifies the component's logic by centralizing folder filtering and selection handling. Additionally, updated other components to use a new utility function for generating selectable item IDs, enhancing code consistency and readability.
Updated various components and hooks to utilize a centralized NAVIGATION_MENU_ITEM_TYPE constant for item type checks. This change enhances code consistency and readability by replacing string literals with a defined type, ensuring better maintainability and reducing the risk of errors in item type handling.
Eliminated the getNavigationMenuItemType utility function and replaced its usage with direct access to itemType properties in relevant components and hooks. This change simplifies the logic for determining navigation menu item types and enhances code clarity.
Updated the CommandMenuEditFolderPickerSubView and CommandMenuNavigationMenuItemEditPage components to replace individual item type flags with a single selectedItemType property. This change streamlines the logic for determining item types and enhances code readability. Additionally, removed unused flags from the useSelectedNavigationMenuItemEditData hook.
- Updated the migration command to include `link` and `icon` properties for navigation menu items, ensuring consistency across various components.
- Enhanced metadata creation utilities to support these properties, improving the overall functionality and representation of navigation menu items.
- Deleted the migration file that added a `link` column to the `navigationMenuItem` table, as it is no longer needed following recent updates to the database schema.
- Created a new migration to add `link` and `icon` columns to the `navigationMenuItem` table in the database.
- This enhancement supports the recent updates to navigation menu item components, allowing for better representation and functionality.
- Introduced `link` and `icon` properties to the `ALL_ENTITY_PROPERTIES_CONFIGURATION_BY_METADATA_NAME` constant, enhancing the metadata structure for better representation and functionality.
- Both properties are set to not be stringified and have undefined universal properties, maintaining consistency with existing configurations.
- Introduced an `icon` property across various navigation menu item components, including input types, DTOs, and entities, to enhance the representation of menu items.
- Updated utility functions to accommodate the new `icon` property, ensuring consistent handling during item creation and transformation.
- Enhanced metadata creation utilities to support the inclusion of icons, improving the overall functionality and user experience of the navigation menu.
- Introduced `CommandMenuObjectViewRecordInfo` component to display information for selected view and record items in the command menu.
- Updated `CommandMenuPageInfo` to integrate the new component, improving the handling of view and record types.
- Enhanced `useSelectedNavigationMenuItemEditData` hook to include a flag for record items, supporting the new component's functionality.
- Introduced `onAddBefore` and `onAddAfter` props in `CommandMenuEditLinkItemView`, `CommandMenuEditObjectViewBase`, and `CommandMenuEditOrganizeActions` to support adding items before and after existing menu items.
- Updated `CommandMenuNavigationMenuItemEditPage` to include new actions for adding items, enhancing the command menu's functionality.
- Implemented context management for item insertion using Recoil, allowing for dynamic placement of new items in the navigation menu.
- Added new icons for the add actions to improve visual representation in the command menu.
- Created `addMenuItemInsertionContextState` and `AddMenuItemInsertionContext` types to manage the state related to item insertion, improving code organization and maintainability.
- Removed unused variables and props in `CommandMenuNewSidebarItemPage` and `CommandMenuNewSidebarItemViewPickerSubView`, streamlining the component logic.
- Simplified filtering logic for available object metadata items, enhancing performance and readability.
- Updated the structure of the components to improve maintainability and user experience in the command menu.
- Updated `StyledFolderDroppableContent` to replace `$isEditMode` and `$isEmpty` props with a single `$compact` prop, simplifying the padding logic based on the editing state and item presence.
- Adjusted the `WorkspaceNavigationMenuItemsFolder` component to utilize the new `$compact` prop, enhancing code clarity and maintainability.
- Updated `StyledFolderDroppableContent` to accept new props `$isEditMode` and `$isEmpty`, allowing for dynamic padding adjustments based on the editing state and item presence.
- Integrated these props into the `WorkspaceNavigationMenuItemsFolder` component to improve layout responsiveness during editing, enhancing user experience.
- Simplified `CommandMenuEditObjectViewBase` by removing unnecessary props and components, enhancing clarity and maintainability.
- Deleted `CommandMenuEditViewPickerSubView` and related hooks to streamline the command menu structure, reducing complexity.
- Updated `CommandMenuNavigationMenuItemEditPage` to reflect changes in the object editing logic, improving overall functionality and user experience.
- Updated `CurrentWorkspaceMemberNavigationMenuItems` and `WorkspaceNavigationMenuItemsFolder` components to utilize `useNavigate` for improved navigation handling.
- Introduced logic to navigate to the first non-link item when the menu is closed, enhancing user experience and streamlining navigation.
- Refactored location handling to improve code clarity and maintainability across components.
- Updated the `NavigationItemDropTarget` component to support a new `compact` prop, allowing for dynamic height adjustment based on the editing state.
- Introduced `handleAddMenuItem` function in `WorkspaceNavigationMenuItems` to facilitate adding new items to the navigation menu.
- Enhanced `NavigationDrawerSectionForWorkspaceItems` to include an `onAddMenuItem` prop, enabling the display of an "Add menu item" option when in edit mode, improving user interaction and navigation management.
- Changed the border color in the StyledSearchContainer from medium to light, enhancing the overall appearance and alignment with the theme's design principles.
- Added a new `hasSubMenu` prop to the `CommandMenuNewSidebarItemViewObjectPickerSubView` component, enabling the display of submenu items for better organization and navigation.
- Updated the component's structure to improve user interaction and enhance the overall functionality of the command menu.
- Added logic to filter object metadata items based on displayable views, improving the selection process in the command menu.
- Introduced a new prop `showSystemObjectsOption` to conditionally render the system objects option in the sidebar, enhancing user experience.
- Updated related components to utilize the new filtering and display logic, ensuring a more intuitive interaction with the command menu items.
- Introduced `NAVIGATION_SECTIONS` constants to categorize navigation items into 'workspace' and 'favorites', improving code clarity and organization.
- Added `NavigationDragSourceContext` to manage the source droppable ID during drag-and-drop operations, enhancing state management.
- Updated various components to utilize the new context and constants, including `NavigationItemDropTarget`, `NavigationMenuItemDroppable`, and others, to improve drag-and-drop handling.
- Implemented logic to disable drop targets based on the current section, enhancing user experience during drag-and-drop interactions.
- These changes collectively improve the structure and functionality of the navigation menu, ensuring a more intuitive drag-and-drop experience.
- Updated the `createAddToNavigationDragPreview` function to wrap the `AddToNavigationDragPreview` component in a `RecoilRoot`, enabling state management for drag-and-drop operations.
- Adjusted the positioning of the drag preview element from off-screen to the top-left corner, improving visibility during drag actions.
- These changes enhance the functionality and user experience of the drag-and-drop feature within the navigation menu.
- Renamed drag event handlers for clarity, changing `handleDocumentDrop` to `handleDocumentDragStart` and introducing `handleDocumentDragEnd` to manage drag state more effectively.
- Enhanced the logic for setting active drop targets based on the current draft items, improving user feedback during drag-and-drop operations.
- Updated event listener management to ensure proper cleanup, contributing to better performance and maintainability of the component.
- These changes collectively enhance the drag-and-drop experience within the navigation sidebar.
- Updated the `StyledIconSlot` component to use a `$hasFixedSize` prop instead of `$hasBackgroundColor`, enhancing the flexibility of the drag handle's appearance.
- Simplified icon size handling in `AddToNavigationDragHandle` and `IconWithBackground` components by standardizing the size to `theme.icon.size.md`, improving consistency across the application.
- These changes enhance the visual coherence of the navigation menu items and streamline icon rendering logic.
- Introduced the `IconWithBackground` component to standardize icon rendering with background colors, improving visual consistency across command menu items.
- Updated `CommandMenuItem`, `CommandMenuObjectMenuItem`, and related components to utilize the new `IconWithBackground`, enhancing their appearance and theming capabilities.
- Integrated theme-based icon color management in `CommandMenuNewSidebarItemViewObjectPickerSubView` and `CommandMenuNewSidebarItemViewSystemSubView`, ensuring better alignment with the overall design.
- These changes collectively improve the user interface and maintainability of the command menu components.
- Updated the `StyledIconSlot` to accept an optional `$backgroundColor` prop, allowing for greater customization of the drag handle's appearance.
- Simplified the cursor handling logic and adjusted padding and width based on the presence of the background color, improving the component's flexibility.
- Enhanced the `AddToNavigationDragHandle` props to include `iconBackgroundColor`, providing more control over the icon's styling during drag operations.
- These changes improve the usability and visual consistency of the drag handle within the navigation menu.
- Integrated the `useLingui` hook to provide internationalization support for the drag-and-drop functionality within the `CommandMenuItemWithAddToNavigationDrag` component.
- Updated the description displayed during hover to show a contextual message, improving user guidance when dragging items to the navigation bar.
- These changes enhance the user experience by providing clearer instructions during drag operations.
- Simplified the icon rendering logic by replacing the custom `isIconComponent` type guard with `isValidElement` to streamline the component's functionality.
- Enhanced the handling of icon components to ensure proper rendering based on their type, improving code clarity and maintainability.
- These changes contribute to a more efficient and understandable implementation of the AddToNavigationIconSlot component.
- Replaced `IconFolderPlus` with `IconFolderSymlink` in the `CommandMenuEditOrganizeActions` component to better represent the action of moving items to a folder.
- Added `IconFolderSymlink` to the `twenty-ui` display module, ensuring it is available for use across the application.
- These changes enhance the visual representation of actions within the command menu, improving user experience and clarity.
- Introduced a new styled component, `StyledFolderExpandableWrapper`, to improve layout management during drag-and-drop operations.
- Updated the rendering logic within `WorkspaceNavigationMenuItemsFolder` to enhance clarity and maintainability by utilizing the new styled component.
- Simplified the handling of navigation menu items by directly integrating the `Droppable` component, ensuring a more efficient drag-and-drop experience.
- These changes collectively enhance the user experience and maintain the integrity of the navigation menu during interactions.
- Introduced the `WorkspaceNavigationMenuItemFolderDragClone` component to enhance the drag-and-drop experience within the workspace navigation menu.
- Integrated the new component into the `WorkspaceNavigationMenuItemsFolder` to render a clone of the draggable item, improving user interaction during drag operations.
- This addition streamlines the drag-and-drop functionality, providing visual feedback and maintaining the integrity of the navigation menu items during dragging.
- Updated the parameter name in the `handleDragStart` function from `_` to `_dragStart` for better clarity and understanding of its purpose.
- This change enhances code readability and maintainability by providing a more descriptive parameter name.
- Removed the unused `NavigationItemDropTarget` import to streamline the component.
- Introduced a new styled component, `StyledFolderDroppableContent`, to enhance layout consistency.
- Simplified the rendering logic by directly using `NavigationDrawerItem` and `DraggableItem`, improving code clarity and maintainability.
- These changes contribute to a more organized and efficient implementation of the workspace navigation menu items.
- Introduced the `NavbarDragProvider` component to manage drag-and-drop context for navigation items, enhancing user interaction capabilities.
- Updated `MainNavigationDrawerScrollableItems` and `CurrentWorkspaceMemberFavoritesFolders` components to utilize the new drag provider, improving the organization of draggable items.
- Refactored navigation menu item components to replace the previous drag provider with a more streamlined approach, enhancing code clarity and maintainability.
- Adjusted constants for droppable IDs to support the new drag-and-drop logic, ensuring consistency across the navigation menu items.
- These changes collectively enhance the user experience by enabling intuitive drag-and-drop functionality within the navigation drawer.
- Added a new prop `alwaysShowRightIcon` to the `NavigationDrawerSectionTitle` component, allowing the right icon to remain visible regardless of mobile state.
- Updated the `StyledRightIcon` component to conditionally render opacity based on the new prop, improving user experience and accessibility.
- These changes enhance the flexibility and usability of the navigation drawer component.
- Adjusted icon sizes in multiple components to use a consistent spacing value of `3.5`, enhancing visual uniformity across the application.
- Updated the dimensions of the `StyledNavigationMenuItemIconContainer` to `4.5`, ensuring alignment with the new icon sizing.
- These changes improve the overall aesthetic and maintainability of the UI components.
- Eliminated the unused `isDefined` import from the `useSelectedNavigationMenuItemEditData` hook, enhancing code cleanliness and maintainability.
- This change contributes to a more organized codebase by removing unnecessary dependencies.
- Updated the `filterWorkspaceNavigationMenuItems` function to utilize the `NavigationMenuItem` type, improving type consistency and clarity in filtering logic.
- This change enhances the maintainability and readability of the code by ensuring that the function operates on a well-defined type.
- Updated various components and hooks to utilize the new `itemType` property for improved clarity in navigation menu item handling.
- Removed unnecessary imports and simplified condition checks, enhancing code readability and maintainability.
- These changes contribute to a more organized and efficient implementation of navigation menu item logic.
- Updated condition checks in `useSelectedNavigationMenuItemEditData`, `WorkspaceNavigationMenuItemsFolder`, and `useWorkspaceSectionItems` to utilize the new `itemType` property for better clarity and consistency.
- Removed unnecessary imports and simplified logic related to navigation menu item types, enhancing code readability and maintainability.
- These changes contribute to a more organized and efficient implementation of navigation menu item handling.
- Introduced a new `NavigationMenuItemType` type to categorize menu items as 'folder', 'link', 'object', 'record', or 'view'.
- Updated the `ProcessedNavigationMenuItem` type to include an `itemType` property, improving clarity in item categorization.
- Refactored the `sortNavigationMenuItems` function to assign the appropriate `itemType` based on the item being processed, enhancing the sorting logic and maintainability.
- Simplified condition checks in `NavigationDrawerItemForObjectMetadataItem` to utilize the new `itemType` property for determining item characteristics, improving code readability.
- Updated the CSS syntax in the `StyledIcon` component to use the `css` template literal for better readability and maintainability.
- This change enhances the clarity of the styling logic within the component, contributing to a more organized codebase.
- Updated the `isIconComponent` function to allow for both function and object types, improving flexibility in icon handling.
- Renamed the local variable from `IconComponent` to `Icon` for clarity in rendering.
- These changes contribute to a more robust and maintainable implementation of the AddToNavigationIconSlot component.
- Replaced the `useNavigationMenuEditModeActions` hook with direct state management using Recoil's `useSetRecoilState` in `NavigationMenuEditModeBar` and `WorkspaceNavigationMenuItems` components, enhancing clarity and modularity.
- Introduced a new `cancelEditMode` function to handle the cancellation of edit mode, improving the organization of state updates.
- Removed the now-unnecessary `useNavigationMenuEditModeActions` hook, streamlining the codebase and reducing complexity.
- These changes contribute to a more efficient and maintainable implementation of navigation menu edit mode functionality.
- Simplified the calculation of new positions in the `useHandleNavigationMenuItemDragAndDrop` hook by removing unnecessary rounding, enhancing code readability.
- Updated the `calculateNewPosition` utility to consistently return rounded values, improving the accuracy of position calculations during drag and drop operations.
- These changes contribute to a more efficient and maintainable implementation of drag and drop functionality in the navigation menu.
- Replaced the `useUpdateNavigationMenuItemsDraft` hook with more specific hooks: `useUpdateFolderNameInDraft`, `useUpdateLinkInDraft`, and `useUpdateObjectInDraft`, enhancing clarity and modularity.
- Updated components to utilize the new hooks, streamlining draft management for folders, links, and objects.
- Introduced new hooks for adding items to the navigation menu draft, improving the organization and maintainability of the codebase.
- These changes contribute to a more efficient and structured implementation of command menu item handling.
- Updated `CommandMenuItemWithAddToNavigationDrag` and related components to replace the `Icon` prop with a unified `icon` prop, allowing for both `IconComponent` and `ReactNode` types.
- Introduced `AddToNavigationIconSlot` to encapsulate icon rendering logic, improving code clarity and reusability.
- These changes enhance the consistency and maintainability of the command menu item components.
- Streamlined the rendering logic by consolidating condition checks for object, link, and folder items, improving code clarity and reducing redundancy.
- Removed unnecessary props and simplified the return statements for better maintainability.
- These changes contribute to a more organized and efficient implementation of the CommandMenuNavigationMenuItemEditPage component.
- Updated `CommandMenuEditViewPickerSubView` to utilize local state for managing `currentDraft` and `objectMetadataItems`, enhancing clarity and reducing reliance on external props.
- Simplified the `CommandMenuNavigationMenuItemEditPage` by removing unnecessary props and streamlining the rendering logic for improved maintainability.
- Enhanced `CommandMenuNewSidebarItemPage` and related components by consolidating draft handling and removing unused imports, contributing to a more organized implementation of the command menu components.
- Simplified the rendering logic in `CommandMenuNewSidebarItemPage` by removing unnecessary props from `CommandMenuNewSidebarItemRecordSubView`, improving clarity.
- Introduced `CommandMenuNewSidebarItemRecordItem` to encapsulate record item rendering, enhancing reusability and maintainability.
- Updated `CommandMenuNewSidebarItemRecordSubView` to utilize the new `CommandMenuNewSidebarItemRecordItem`, streamlining the component structure.
- These changes contribute to a more organized and efficient implementation of the command menu components.
- Simplified the rendering logic in `CommandMenuNavigationMenuItemEditPage` by consolidating the object view rendering into a single inline function, enhancing clarity and reducing redundancy.
- Updated the condition checks for rendering the object view, streamlining the component's structure and improving maintainability.
- These changes contribute to a more organized and efficient implementation of the CommandMenuNavigationMenuItemEditPage component.
- Updated `CommandMenuEditViewPickerSubView` to integrate local handling of view selection, improving clarity and reducing reliance on external props.
- Introduced a new `handleSelectView` function to streamline view selection and state management.
- Utilized `useRecoilValue` for managing the selected navigation menu item in edit mode, enhancing state management and code maintainability.
- These changes contribute to a more organized and efficient implementation of the CommandMenuEditViewPickerSubView component.
- Updated `CommandMenuEditFolderPickerSubView` to integrate folder selection handling directly within the component, improving clarity and reducing reliance on external props.
- Removed the `onSelectFolder` prop and replaced it with a local `handleSelectFolder` function to streamline folder selection and state management.
- These changes enhance the organization and maintainability of the CommandMenuEditFolderPickerSubView component.
- Updated `CommandMenuEditFolderPickerSubView` and `CommandMenuNavigationMenuItemEditPage` to utilize `useRecoilValue` for managing the selected navigation menu item in edit mode, improving state management.
- Simplified the retrieval of selected item data by restructuring the hooks, enhancing code clarity and maintainability.
- These changes contribute to a more organized and efficient implementation of command menu components.
- Simplified the usage of `useNavigationMenuItemEditOrganizeActions` by destructuring its properties directly in the component.
- Updated the component to use the destructured properties for action handling, enhancing code clarity and reducing redundancy.
- These changes contribute to a more organized and maintainable implementation of the CommandMenuNavigationMenuItemEditPage component.
- Updated `CommandMenuNewSidebarItemPage`, `useNavigationMenuItemEditFolderData`, and `NavigationSidebarNativeDropZone` to utilize `useRecoilValue` for improved state management of `navigationMenuItemsDraft`.
- Simplified the retrieval of navigation menu items draft state across components, enhancing code clarity and maintainability.
- These changes contribute to a more organized and efficient implementation of navigation menu item handling.
- Removed unused imports and consolidated rendering logic in `CommandMenuNavigationMenuItemEditPage` and `CommandMenuNewSidebarItemPage` to enhance clarity.
- Introduced `CommandMenuObjectPickerItem` to standardize object menu item rendering across different components, improving code reusability.
- Updated `CommandMenuObjectPickerSubView` and `CommandMenuSystemObjectPickerSubView` to utilize the new `CommandMenuObjectPickerItem`, streamlining the rendering process.
- These changes enhance the organization, maintainability, and readability of the command menu components.
- Introduced hooks `useNavigationMenuItemEditFolderData` and `useSelectedNavigationMenuItemEditData` to streamline data handling in `CommandMenuEditFolderPickerSubView`, `CommandMenuEditOwnerSection`, and `CommandMenuEditViewPickerSubView`.
- Simplified state management and search functionality within `CommandMenuEditFolderPickerSubView` by utilizing local state for search input.
- Improved the logic for determining application IDs in `CommandMenuEditOwnerSection` based on the current draft and selected item.
- These changes enhance the organization, maintainability, and clarity of the command menu components.
- Introduced new hooks for managing navigation menu item edit data, including `useNavigationMenuItemEditFolderData`, `useNavigationMenuItemEditObjectPickerData`, `useNavigationMenuItemEditOrganizeActions`, `useNavigationMenuItemEditSubView`, and `useSelectedNavigationMenuItemEditData`.
- Simplified the CommandMenuNavigationMenuItemEditPage component by removing unused imports and consolidating state management logic.
- These changes improve the organization, maintainability, and clarity of the navigation menu item editing functionality.
- Simplified subViewHandlers by converting them into individual functions for better clarity.
- Updated onBack and onOpen functions to directly reference the new individual handlers, enhancing code organization.
- These changes contribute to a more maintainable and readable implementation of the CommandMenuNavigationMenuItemEditPage component.
- Replaced the reduce method with a for-of loop for better clarity in the getDescendantFolderIds function.
- Enhanced the logic for accumulating descendant folder IDs, improving maintainability and readability.
These changes contribute to a more organized implementation of the CommandMenuEditFolderPickerSubView component.
- Introduced the `filterWorkspaceNavigationMenuItems` utility to streamline the filtering of navigation menu items based on user workspace ID.
- Updated multiple hooks (`useNavigationMenuEditModeActions`, `useNavigationMenuItemsDraftState`, `usePrefetchedNavigationMenuItemsData`, and `useSaveNavigationMenuItemsDraft`) to use the new utility for improved code clarity and maintainability.
- These changes enhance the organization and readability of the navigation menu item handling logic.
- Introduced helper functions `getMaxPosition` and `normalizeUrl` to streamline logic and enhance readability.
- Replaced inline logic with these helper functions in multiple locations to reduce code duplication.
- These changes contribute to a more organized and maintainable implementation of the useAddToNavigationMenuDraft hook.
- Reorganized import statements for better clarity and consistency.
- Simplified the logic for updating open folder IDs to enhance readability.
- Updated the conditional check for edit mode click handling to ensure proper functionality.
These changes contribute to a more organized and maintainable implementation of the WorkspaceNavigationMenuItemsFolder component.
- Reorganized import statements for improved clarity and consistency.
- Updated the conditional check in the handleDrop function for better readability.
These changes contribute to a more structured and maintainable implementation of the NavigationSidebarNativeDropZone component.
- Consolidated conditional rendering into a switch statement for better readability and maintainability.
- Updated the handling of folder and link additions to streamline the logic and enhance code organization.
- Reorganized import statements for improved clarity and consistency.
These changes contribute to a more efficient and structured implementation of the NavigationSidebarNativeDropZone component.
- Consolidated conditional rendering into a switch statement for improved clarity and maintainability.
- Streamlined the rendering logic for various sidebar item views, enhancing code organization.
- These changes contribute to a more efficient and structured implementation of the CommandMenuNewSidebarItemPage component.
- Integrated the `useTheme` hook to dynamically adjust icon sizes based on the theme.
- Updated the icon size assignment to utilize theme values, enhancing consistency in styling.
- These changes contribute to a more organized and visually coherent implementation of the NavigationMenuEditModeBar component.
- Removed unused import statements and consolidated drop target properties directly within the component.
- Simplified the drop target ID generation logic for better readability.
- Updated the drop target attributes to use data attributes directly in the JSX, enhancing clarity.
These changes contribute to a more organized and efficient implementation of the NavigationItemDropTarget and NavigationSidebarNativeDropZone components.
- Reorganized import statements for better code clarity and consistency.
- Simplified the rendering logic by consolidating the object menu item rendering into a dedicated function.
- Updated filtering logic to enhance readability and maintainability.
These changes contribute to a more efficient and organized implementation of the CommandMenuNewSidebarItemPage component.
- Removed redundant imports to streamline the component.
- Updated conditional rendering logic to enhance readability and maintainability.
- Consolidated rendering logic for object and view items into a single function, improving code organization.
These changes contribute to a more efficient and organized implementation of the CommandMenuNavigationMenuItemEditPage component.
- Added the `useRecoilValue` import to manage state more effectively.
- Updated the icon variable name from `PaintIcon` to `IconPaint` for better clarity.
- Reintroduced conditional rendering for the navigation menu edit mode bar to enhance readability.
These changes contribute to a more organized and maintainable implementation of the NavigationMenuEditModeBar component.
- Moved the import statement for `ReactNode`, `useContext`, and `useRef` to enhance code organization.
- Adjusted the import order to maintain consistency with other components.
- These changes contribute to a more efficient and organized implementation of the NavigationItemDropTarget component.
- Removed the `NavigationDrawerItemForLink` component and integrated its functionality directly into the `NavigationDrawerSectionForWorkspaceItems` component, enhancing code clarity and reducing complexity.
- Updated the rendering logic to utilize the `NavigationDrawerItem` component, streamlining the handling of link items and improving maintainability.
- Enhanced icon color handling by incorporating the `getNavigationMenuItemIconColors` utility, ensuring consistent styling across navigation items.
These changes contribute to a more efficient and organized implementation of the navigation drawer components.
- Introduced the `isDefined` utility function to enhance the clarity of icon rendering logic.
- Simplified padding assignments in the styled component for better readability.
- Streamlined the conditional rendering of icons to improve the component structure.
These changes contribute to a more organized and efficient implementation of the AddToNavigationDragPreview component.
- Introduced utility function `isDefined` to enhance the clarity of icon rendering logic.
- Simplified icon size and stroke assignments by storing them in variables, improving code maintainability.
- Updated conditional rendering for icons to streamline the component structure.
These changes contribute to a more organized and efficient implementation of the AddToNavigationDragHandle component.
- Replaced the `CommandMenuSelectObjectForViewMenuItem` component with a more streamlined implementation using `SelectableListItem` and `CommandMenuItem`, improving rendering efficiency and clarity.
- Integrated the `useIcons` hook to manage icon retrieval, enhancing code maintainability.
- Updated the `CommandMenuNewSidebarItemViewObjectPickerSubView` and `CommandMenuNewSidebarItemViewSystemSubView` components to utilize the new rendering approach, ensuring consistency across the command menu.
These changes contribute to a more efficient and organized implementation of the command menu components.
- Simplified the click handling logic by removing unnecessary checks and directly returning if `defaultViewId` is not defined.
- Enhanced the rendering logic for `CommandMenuItem` components by consolidating the payload structure and ensuring the `disabled` prop is set correctly.
These changes contribute to a more efficient and maintainable implementation of the command menu components.
- Integrated the `useFilteredPickerItems` custom hook to streamline filtering logic and enhance code clarity.
- Simplified the handling of no results text and selectable item IDs, improving overall component structure.
These changes contribute to a more efficient and maintainable implementation of the command menu components.
- Replaced manual filtering logic with the `useFilteredPickerItems` custom hook, enhancing code clarity and maintainability.
- Streamlined the handling of no results text and improved the rendering of selectable list items.
These changes contribute to a more efficient and organized implementation of the command menu components.
- Replaced the manual filtering logic with the `useFilteredPickerItems` custom hook, enhancing code clarity and maintainability.
- Streamlined the handling of selectable item IDs and no results text, improving the overall structure of the component.
These changes contribute to a more efficient and organized implementation of the command menu components.
- Simplified the logic for filtering non-readable object metadata items by consolidating the permission check into a single line, enhancing code clarity and maintainability.
- Removed redundant variable assignments to streamline the component structure.
These changes contribute to a more efficient and organized implementation of the command menu components.
- Introduced the `includeCurrentObjectIfMissing` utility function to streamline the inclusion of the current object in object pickers, enhancing code clarity and maintainability.
- Refactored the rendering logic for object menu items to utilize a dedicated `renderObjectMenuItem` function, improving readability and reducing redundancy.
- Updated sorting logic for object arrays to ensure consistent ordering based on `labelPlural`.
These changes contribute to a more efficient and organized implementation of the command menu components.
- Introduced the `getAbsoluteUrl` utility function to streamline URL normalization when updating links.
- Simplified the logic for setting the link URL by directly using `selectedItem.link`, improving code clarity and maintainability.
- Removed redundant variables to enhance the overall structure of the component.
These changes contribute to a more efficient and readable implementation of the command menu components.
- Changed the `disabled` prop in `CommandMenuEditOwnerSection` to a shorthand boolean syntax for improved clarity.
- Removed the redundant `true` value assignment, enhancing code readability and maintainability.
These changes contribute to a cleaner implementation of the command menu components.
- Updated `CommandMenuEditLinkItemView` and `CommandMenuEditObjectViewBase` components to simplify prop usage by removing redundant `true` values for boolean props.
- Enhanced code readability and maintainability by streamlining the component structure.
These changes contribute to a cleaner and more efficient command menu implementation.
- Introduced utility functions `getDescendantFolderIds` and `excludeCurrentFolder` to enhance the logic for managing folder selections.
- Simplified the logic for determining which folders to display based on the current selection and search query, improving code clarity and maintainability.
- Updated the rendering logic to ensure consistent handling of folder options, enhancing the user experience within the command menu.
These changes streamline the folder selection process, improving the overall functionality and readability of the command menu component.
- Deleted the `CommandMenuEditFolderItemView` component to streamline the codebase.
- Integrated its functionality directly into `CommandMenuNavigationMenuItemEditPage`, enhancing component cohesion and reducing dependencies.
These changes improve maintainability by consolidating related logic within a single component, simplifying the overall structure of the command menu.
- Deleted the `CommandMenuEditDefaultView` component to streamline the codebase.
- Integrated its functionality directly into `CommandMenuNavigationMenuItemEditPage`, enhancing component cohesion and reducing dependencies.
These changes improve maintainability by consolidating related logic within a single component, simplifying the overall structure of the command menu.
- Deleted the `CommandMenuSharedStyles` file to streamline the codebase.
- Moved the styled components `StyledCommandMenuPlaceholder` and `StyledCommandMenuPageContainer` directly into `CommandMenuNavigationMenuItemEditPage`, enhancing component encapsulation and reducing dependencies.
These changes improve maintainability by consolidating styles within the relevant component, simplifying the overall structure of the command menu.
- Replaced the `CommandMenuNavigationMenuItemIcon` component with a direct implementation of `StyledNavigationMenuItemIconContainer` in `CommandMenuFolderLinkInfo`, enhancing code clarity and reducing component complexity.
- Removed the now-unnecessary `CommandMenuNavigationMenuItemIcon` file to streamline the codebase.
These changes improve the maintainability of the command menu components by simplifying the icon rendering logic.
- Introduced `CommandMenuFolderLinkInfo` to consolidate folder and link item handling within the command menu, improving code organization and reducing redundancy.
- Removed the deprecated `CommandMenuLinkInfo` component to streamline the codebase.
- Updated `CommandMenuPageInfo` to utilize the new `CommandMenuFolderLinkInfo` for rendering, enhancing maintainability and clarity.
These changes enhance the command menu's functionality by simplifying the component structure and improving item management.
- Renamed `selectedId` to `selectedNavigationMenuItemInEditMode` for better understanding of its purpose.
- Updated the logic for retrieving the selected link to enhance readability and maintainability.
- Ensured consistent return statements for null checks, improving overall code structure.
These changes streamline the handling of navigation items within the command menu, enhancing code clarity and functionality.
- Updated `CommandMenuFolderInfo` to improve variable naming, changing `selectedId` to `selectedNavigationMenuItemInEditMode` for clarity.
- Simplified conditional checks in `CommandMenuPageInfo` for rendering folder and link components, enhancing code readability.
- Ensured consistent return statements for null checks, improving overall code structure.
These changes enhance the maintainability and clarity of the command menu components, streamlining the logic for item handling.
- Updated `CommandMenuFolderInfo` and `CommandMenuLinkInfo` to utilize direct IDs for selected items, enhancing clarity and maintainability.
- Simplified the logic for retrieving selected folder and link items by using a unified `selectedId` variable.
- Refactored save functions to improve naming consistency and ensure default values are correctly applied.
These changes streamline the command menu components, improving overall code readability and functionality.
- Replaced the deprecated `useFlattenedWorkspaceSectionItemsForLookup` hook with `useWorkspaceSectionItems` across multiple components, including `CommandMenuFolderInfo`, `CommandMenuLinkInfo`, and `CommandMenuPageInfo`, to streamline item retrieval.
- Introduced `getNavigationMenuItemType` utility to enhance clarity in determining item types, improving the readability of conditional checks.
- Updated related components and hooks to ensure consistency with the new item handling approach, enhancing maintainability and code structure.
These changes simplify the navigation menu item management, improving overall code clarity and functionality.
- Removed the `getWorkspaceSectionItemId` utility function and updated components to directly access item IDs, simplifying the logic for identifying navigation menu items.
- Adjusted various components, including `CommandMenuFolderInfo`, `CommandMenuLinkInfo`, and `CommandMenuNavigationMenuItemEditPage`, to utilize the new ID structure, enhancing code clarity and maintainability.
- Updated related hooks and types to reflect the changes in item ID handling, ensuring consistency across the navigation menu item management.
These changes streamline the navigation item handling process, improving the overall structure and readability of the codebase.
- Renamed `selectedFolder` to `selectedNavItem` for clarity in distinguishing between folder and link types.
- Updated conditional checks to use the new `selectedNavItem` variable, enhancing readability and maintainability of the component's logic.
These changes streamline the handling of navigation items within the command menu, improving code clarity and functionality.
- Added `applicationId` prop to `CommandMenuEditFolderItemView`, `CommandMenuEditLinkItemView`, and `CommandMenuEditOwnerSection` for improved context handling.
- Updated rendering logic in `CommandMenuNavigationMenuItemEditPage` to pass the correct `applicationId` to folder items.
- Removed unused selectable item IDs in `CommandMenuEditFolderItemView` and `CommandMenuEditLinkItemView` for cleaner code.
These changes improve the modularity and functionality of command menu components, enhancing the user experience by providing relevant application context.
- Introduced `enableOnFormTags` option in the `useCommandMenuHotKeys` hook to control hotkey activation within form elements, enhancing flexibility in user interactions.
- Updated the options for focused element hotkeys to include the same `enableOnFormTags` setting, ensuring consistent behavior across different contexts.
These changes improve the usability of hotkeys in the command menu, allowing for better integration with form elements.
- Introduced the `useFilteredPickerItems` hook to streamline the filtering of items based on a search query, enhancing reusability across command menu components.
- Deleted several outdated components, including `CommandMenuEditObjectPickerSubView`, `CommandMenuEditObjectPickerSystemSubView`, and `CommandMenuEditViewItemView`, to simplify the codebase.
- Added `CommandMenuEditObjectViewBase`, `CommandMenuObjectPickerSubView`, and `CommandMenuSystemObjectPickerSubView` to improve the organization and functionality of object selection within the command menu.
- Updated `CommandMenuNavigationMenuItemEditPage` and `CommandMenuNewSidebarItemPage` to utilize the new picker components, enhancing the user experience and maintaining consistency.
These changes improve the structure and maintainability of the command menu, providing a more efficient interface for object selection and management.
- Introduced a new helper function, `swapPositionsInDraft`, to streamline the logic for swapping positions of navigation menu items in the draft state.
- Replaced inline position swapping logic with the new helper function for better readability and maintainability.
These changes enhance the clarity of the `useNavigationMenuItemMoveRemove` hook, making it easier to manage item positions within the navigation menu.
- Replaced the custom back button with the `SidePanelSubPageNavigationHeader` component for improved navigation consistency.
- Removed unused styled components related to the back button, streamlining the code and enhancing maintainability.
These changes enhance the user experience by providing a more cohesive navigation interface within the command menu.
- Removed the `preventDefault` option from the `useMouseDownNavigation` hook to streamline the API and ensure consistent behavior.
- Updated event handling to always prevent default actions for regular clicks, enhancing navigation reliability.
These changes improve the clarity and usability of the `useMouseDownNavigation` hook, ensuring a more predictable user experience.
- Updated `CommandMenuEditFolderPickerSubView` to include `currentFolderId` for improved folder selection logic, ensuring that the current folder is excluded from the options when applicable.
- Replaced `IconFolder` with `IconFolderPlus` in both `CommandMenuEditFolderPickerSubView` and `CommandMenuEditOrganizeActions` for a more intuitive icon representation.
- Refactored folder filtering logic to enhance clarity and maintainability, improving the user experience when selecting folders.
These changes streamline the folder selection process and enhance the visual consistency of the command menu components.
- Replaced hardcoded owner items in `CommandMenuEditFolderItemView` and `CommandMenuEditLinkItemView` with a new `CommandMenuEditOwnerSection` component for better modularity and reusability.
- Cleaned up imports and removed unused code to enhance readability and maintainability across multiple command menu components.
- Streamlined the rendering logic in `CommandMenuEditObjectPickerSubView` and `CommandMenuEditViewPickerSubView` for improved clarity.
These changes improve the structure of the command menu components, making them more maintainable and enhancing the overall user experience.
- Replaced instances of `useWorkspaceSectionItems` with `useFlattenedWorkspaceSectionItemsForLookup` in multiple command menu components, including `CommandMenuFolderInfo`, `CommandMenuLinkInfo`, and `CommandMenuPageInfo`, to streamline data retrieval.
- Enhanced drag-and-drop functionality in `CommandMenuItemWithAddToNavigationDrag` by introducing a new constant for folder drag types and updating event handling.
- Added `NavigationDropTargetContext` to manage drag-and-drop states, improving the user experience when interacting with navigation items.
- Introduced `NavigationItemDropTarget` component to facilitate drop target behavior for navigation items, enhancing the overall drag-and-drop interface.
These changes improve code maintainability and enhance the user experience by providing a more efficient and intuitive command menu interface.
- Moved the Apollo import statement to the top of the file for consistency.
- Removed duplicate type definition for `NavigationMenuItemFieldsFragment`, ensuring clarity and reducing redundancy.
- Ensured proper formatting and consistency in type definitions throughout the file.
These changes enhance code readability and maintainability in the generated GraphQL metadata.
- Deleted the `CommandMenuEditFolderRenameSubView` component from the command menu, streamlining the editing interface.
- Updated `CommandMenuNavigationMenuItemEditPage` to remove references to the deleted component, enhancing code clarity and maintainability.
These changes simplify the command menu structure and improve overall code organization.
- Updated `CommandMenuNavigationMenuItemIcon` to utilize `StyledNavigationMenuItemIconContainer` for consistent icon styling based on theme colors.
- Introduced `CommandMenuSharedStyles` for shared styles across command menu components, enhancing maintainability and reducing redundancy.
- Refactored `CommandMenuNavigationMenuItemEditPage` and other components to leverage new shared styles, improving code clarity and user interface consistency.
These changes enhance the user experience by providing a more cohesive and visually appealing command menu interface.
- Introduced several new components including `CommandMenuEditDefaultView`, `CommandMenuEditFolderItemView`, `CommandMenuEditFolderPickerSubView`, `CommandMenuEditFolderRenameSubView`, `CommandMenuEditLinkItemView`, `CommandMenuEditObjectItemView`, `CommandMenuEditObjectPickerSubView`, `CommandMenuEditObjectPickerSystemSubView`, `CommandMenuEditViewItemView`, and `CommandMenuEditViewPickerSubView` to improve the editing capabilities within the command menu.
- Refactored `CommandMenuNavigationMenuItemEditPage` to utilize these new components, enhancing the organization and functionality of the editing interface.
- Streamlined the search functionality and improved user feedback through better handling of selectable items and no results scenarios.
These changes significantly enhance the user experience by providing a more intuitive and flexible interface for editing navigation items within the command menu.
- Updated the `CommandMenuNavigationMenuItemEditPage` to enhance the search functionality by introducing clearer handling of empty search results.
- Refactored the logic for generating selectable item IDs to improve clarity and maintainability.
- Added conditional rendering for no results text, providing better user feedback when no system objects are found.
These changes enhance the user experience by making the search interface more intuitive and responsive to user input.
- Added `CommandMenuNewSidebarItemMainMenu` and `CommandMenuNewSidebarItemRecordSubView` components to enhance the command menu's sidebar item functionality.
- Refactored `CommandMenuNewSidebarItemPage` to utilize the new components, streamlining the process of adding new items and managing records.
- Optimized existing logic by removing unnecessary hooks and simplifying state management, improving code clarity and maintainability.
These changes significantly enhance the user experience by providing a more intuitive interface for adding and managing sidebar items within the command menu.
- Introduced several new components including `CommandMenuEditOrganizeActions`, `CommandMenuObjectMenuItem`, `CommandMenuSelectObjectForEditMenuItem`, `CommandMenuSelectObjectForViewMenuItem`, and hooks for managing navigation menu object metadata from drafts.
- Refactored `CommandMenuNavigationMenuItemEditPage` and `CommandMenuNewSidebarItemPage` to utilize these new components, improving the organization and functionality of the command menu.
- Removed redundant code and optimized existing logic for better maintainability and clarity.
These changes significantly enhance the user experience by providing a more intuitive and flexible interface for managing navigation items within the command menu.
- Updated `CommandMenuSubViewWithSearch` to accept optional `searchInputProps` and made `children` prop optional for improved flexibility.
- Refactored `CommandMenuNavigationMenuItemEditPage` to utilize `CommandMenuSubViewWithSearch`, streamlining the search functionality and enhancing the user interface.
- Removed redundant styled components from `CommandMenuNavigationMenuItemEditPage`, improving code clarity and maintainability.
These changes improve the overall user experience by providing a more consistent and flexible search interface within the command menu.
- Introduced `CommandMenuNavigationMenuItemIcon` component to standardize icon rendering for folder and link items in the command menu.
- Updated `CommandMenuFolderInfo` and `CommandMenuLinkInfo` to utilize the new icon component, enhancing code reusability and maintainability.
- Added `CommandMenuSubViewWithSearch` component to streamline search functionality within the command menu, replacing custom search implementations in `CommandMenuNewSidebarItemPage`.
- Refactored utility functions for workspace section item ID retrieval, improving clarity and reducing redundancy.
These changes enhance the user experience by providing a consistent interface for icons and improving search capabilities within the command menu.
- Introduced `CommandMenuItemWithAddToNavigationDrag` component to facilitate drag-and-drop interactions within the command menu.
- Updated `CommandMenuNewSidebarItemPage` to utilize the new component, streamlining the addition of navigation items.
- Refactored existing drag-and-drop logic into the new component, improving code organization and maintainability.
- Enhanced visual feedback during drag operations by integrating drag preview functionality.
These changes significantly improve the user experience by making it easier to add items to the navigation menu through intuitive drag-and-drop actions.
- Introduced new components for drag-and-drop functionality within the navigation menu, including `AddToNavigationDragHandle`, `NavigationItemDropTarget`, and `NavigationSidebarNativeDropZone`.
- Updated existing components to support drag-and-drop interactions, allowing users to easily rearrange navigation items and add new items through drag events.
- Enhanced the `useAddToNavigationMenuDraft` hook to manage the addition of items at specific positions based on drag-and-drop actions.
- Improved the user experience by providing visual feedback during drag operations and ensuring seamless integration with existing navigation menu functionalities.
These changes significantly enhance the usability of the navigation menu, making it more intuitive for users to manage their navigation items.
- Introduced `CommandMenuLinkInfo` component to manage link-specific interactions within the command menu.
- Updated `CommandMenuPageInfo` to conditionally render `CommandMenuLinkInfo` when editing a navigation menu item of type link.
- Enhanced navigation menu item editing capabilities by allowing users to manage links directly within the command menu.
These changes improve the user experience by providing a dedicated interface for link management, streamlining navigation and editing processes.
- Introduced a new optional `link` field in the `NavigationMenuItem` type, allowing for external links to be associated with navigation items.
- Updated the `CreateNavigationMenuItemInput`, `UpdateNavigationMenuItemInput`, and related DTOs to include the `link` field.
- Modified the database schema with a migration to add the `link` column to the `navigationMenuItem` table.
- Enhanced validation logic to accommodate the new `link` field, ensuring proper handling during navigation menu item creation and updates.
These changes improve the flexibility of navigation menu items by enabling the inclusion of external links, enhancing user navigation capabilities.
- Introduced `CommandMenuFolderInfo` component to manage folder-specific interactions within the command menu.
- Updated `CommandMenuPageInfo` to conditionally render `CommandMenuFolderInfo` when editing a navigation menu item in folder mode.
- Enhanced folder management capabilities by adding folder creation and editing functionalities in the command menu.
These changes improve the user experience by providing a dedicated interface for folder management within the command menu, streamlining navigation and editing processes.
- Added `useCommandMenu` hook to manage command menu interactions.
- Updated save draft logic to close the command menu upon successful save, enhancing user experience during navigation menu edits.
This change improves the responsiveness of the navigation menu editing process by ensuring the command menu closes automatically after saving changes.
- Added a `secondaryLabel` prop to `NavigationDrawerItemForObjectMetadataItem` component.
- The `secondaryLabel` is conditionally set based on whether the item is a record or a view with a custom name, improving the clarity of displayed metadata.
This change enhances the user interface by providing additional context for object metadata items in the navigation drawer.
- Introduced `CommandMenuSelectObjectForViewEditMenuItem` component to facilitate object selection for view editing.
- Enhanced state management in `CommandMenuNavigationMenuItemEditPage` to track selected object metadata for view editing.
- Updated logic to filter and sort objects based on their association with views, improving the user experience during object selection.
- Adjusted rendering logic to differentiate between object and view editing modes, ensuring clarity in user interactions.
These changes enhance the command menu's functionality, providing users with a more intuitive experience when managing object views.
- Updated the `WorkspaceNavigationMenuItemsFolder` component to conditionally render secondary labels based on the view key, improving clarity in navigation item representation.
- Simplified the logic in `sortNavigationMenuItems` to ensure consistent handling of object names, enhancing the accuracy of displayed labels.
These changes enhance the user experience by providing clearer navigation item details and improving the overall sorting logic.
- Updated the `CommandMenuNavigationMenuItemEditPage` to handle empty folder states more gracefully, displaying a custom message when no folders are available.
- Refactored the logic for generating selectable item IDs to include a fallback for empty states.
- Improved the sorting logic in `sortNavigationMenuItems` to correctly handle index views and associated metadata, ensuring accurate display of labels and icons.
- Adjusted test cases to reflect changes in object naming conventions and ensure consistency in expected outcomes.
These changes improve the user experience by providing clearer feedback and more accurate representations of navigation items in the command menu.
- Consolidated multiple hooks for adding items to the navigation menu draft into a single `useAddToNavigationMenuDraft` hook, streamlining the process for adding objects, views, and records.
- Removed outdated hooks `useAddObjectToNavigationMenuDraft`, `useAddViewToNavigationMenuDraft`, and refactored related components to utilize the new consolidated hook.
- Introduced `useUpdateNavigationMenuItemsDraft` hook to manage updates to navigation menu items in draft state, enhancing item editing capabilities.
- Enhanced the `CommandMenuNavigationMenuItemEditPage` with improved state management and additional functionality for object selection and navigation item manipulation.
- Updated the `useNavigationMenuItemMoveRemove` hook to include a new `moveToFolder` function, allowing for better organization of navigation items.
These changes improve the overall efficiency and usability of the command menu, providing users with a more cohesive experience when managing navigation items.
- Updated the back navigation logic in the `CommandMenuNewSidebarItemPage` to handle system object selections more effectively.
- Introduced a check for system object metadata to set the appropriate navigation option when returning to the view object list.
- Improved user experience by ensuring the correct state is maintained during navigation actions.
These changes enhance the functionality of the command menu, providing users with a more intuitive navigation experience when dealing with system objects.
- Added a new `noResultsText` prop to the `CommandMenuList` component, allowing for customizable no results messages.
- Updated the `CommandMenuNewSidebarItemPage` to utilize the new prop, providing context-specific messages based on user input.
- Refactored the logic for displaying results to improve clarity and user experience when no views are found.
These changes enhance the flexibility of the command menu, improving user feedback during navigation item searches.
- Integrated functionality for adding views to the navigation menu draft within the `CommandMenuNewSidebarItemPage`.
- Introduced a new hook, `useAddViewToNavigationMenuDraft`, to manage view additions effectively.
- Updated state management to accommodate view selection and search inputs, enhancing user interaction.
- Refactored related components and utilities to support view handling, improving overall command menu functionality.
These changes enhance the command menu's capabilities, allowing users to manage views alongside other navigation items seamlessly.
- Added support for system objects in the `CommandMenuNewSidebarItemPage`, allowing users to filter and select system-related items.
- Introduced new state management for system object search input and updated the back navigation logic for improved user experience.
- Refactored object metadata filtering to include system objects, enhancing the overall functionality of the command menu.
- Improved search functionality by implementing a dedicated search input for objects, streamlining the selection process.
These changes enhance the command menu's capabilities, providing users with more comprehensive options for managing navigation items.
- Eliminated the assignment of targetObjectMetadataId to undefined when viewId is defined, streamlining the input handling logic.
- This change improves the clarity and efficiency of the hook's functionality, ensuring only relevant data is processed.
- Introduced the `CommandMenuNewSidebarItemPage` component to facilitate the addition of new items to the navigation menu.
- Updated the `CommandMenuPagesConfig` to include the new sidebar item page, enhancing navigation options.
- Implemented hooks for adding objects and records to the navigation menu draft, improving item management.
- Refactored the `NavigationMenuEditModeBar` to support saving drafts and handling loading states, streamlining the editing process.
These changes enhance the command menu's functionality, providing users with more options for managing navigation items effectively.
- Introduced the ability to move navigation menu items up and down within the command menu, improving item organization.
- Added a remove option to delete selected navigation menu items, streamlining item management.
- Refactored the `CommandMenuNavigationMenuItemEditPage` component to utilize new hooks for item manipulation and state management.
- Updated related components and hooks to ensure consistent handling of navigation menu items.
These changes enhance the user experience by providing more control over navigation menu item arrangements and management.
- Adjusted the width calculation in the `NavigationDrawerItem` component to account for additional spacing when right options are present.
- Improved the responsiveness of the navigation drawer by refining the width logic for both expanded and collapsed states.
These changes enhance the visual consistency and usability of the navigation drawer items.
- Replaced the `selectedWorkspaceObjectMetadataItemIdInEditModeState` with `selectedNavigationMenuItemInEditModeState` to streamline state management for navigation menu items.
- Updated components to utilize the new state, enhancing clarity and consistency across the navigation menu.
- Refactored hooks and component logic to improve handling of navigation menu item selection and editing, ensuring a more intuitive user experience.
- Introduced new utility functions and styled components to support the updated navigation structure.
These changes enhance the overall functionality and maintainability of the navigation menu system.
- Updated the navigation menu item components to utilize user-specific navigation items, enhancing the organization of workspace-related views.
- Introduced a new `WorkspaceNavigationMenuItemsFolder` component to manage folder items within the workspace navigation.
- Refactored hooks to separate workspace and user navigation items, improving data handling and clarity.
- Added utility functions to identify navigation menu item folders, streamlining the integration of folder items in the navigation structure.
These changes enhance the user experience by providing a more structured and intuitive navigation menu for workspace items.
- Introduced a new 'workflowsFolder' item in the standard navigation menu, enhancing organization of workflow-related views.
- Added new entries for 'workflowsFolderAllWorkflows', 'workflowsFolderAllWorkflowRuns', and 'workflowsFolderAllWorkflowVersions' to improve navigation and access to workflow data.
- Created utility functions for generating flat metadata for folder items, streamlining the integration of new navigation items.
- Updated existing view and view field utilities to include support for workflow versions, ensuring comprehensive coverage in the navigation structure.
These changes enhance the user experience by providing a clearer and more structured navigation menu for workflows and their associated views.
- Removed unused imports and state management related to views and context store, streamlining the component.
- Simplified the rendering logic by eliminating the collapsible container and directly rendering the `NavigationDrawerItem`.
- This refactor enhances readability and maintainability of the code while preserving existing functionality.
- Added support for handling active item clicks in the `WorkspaceNavigationMenuItems` component, allowing users to interact with items even when not in edit mode.
- Introduced a new styled container for right icons to improve layout and spacing.
- Updated `NavigationDrawerItemForObjectMetadataItem` and `NavigationDrawerSectionForObjectMetadataItems` components to accommodate the new click handling logic, enhancing user experience and interaction consistency.
These changes improve the functionality and usability of the navigation menu, making it more intuitive for users.
- Introduced `CommandMenuNavigationMenuItemEditPage` for editing navigation menu items.
- Updated `COMMAND_MENU_PAGES_CONFIG` to include the new edit page.
- Added state management for selected navigation menu item in edit mode.
- Enhanced `WorkspaceNavigationMenuItems` to support opening the edit page and handling edit mode interactions.
These changes improve the user experience by allowing direct editing of navigation menu items within the command menu.
- Added an `inverted` prop to `CancelButton`, allowing for a tertiary button style.
- Updated `SaveButton` to support an `inverted` prop, changing its appearance based on the prop value.
- Modified `SaveAndCancelButtons` to pass the `inverted` prop to both buttons, ensuring consistent styling.
These changes improve the visual flexibility of the buttons in the settings module, enhancing user experience.
- Introduced `useNavigationMenuEditModeActions` for managing edit mode actions, including entering and canceling edit mode.
- Added `useNavigationMenuItemsDraftState` to handle draft state of navigation menu items, determining workspace items based on edit mode.
- Created `isNavigationMenuInEditModeState` and `navigationMenuItemsDraftState` atoms for managing edit mode status and draft items.
These additions enhance the functionality for editing navigation menu items, improving user experience and customization options.
- Introduced the IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED flag across the GraphQL schema and server-side enums.
- Updated the workspace entity manager tests to include the new feature flag.
- Enhanced the seed feature flags utility to support the new flag.
These changes enable editing capabilities for navigation menu items, improving customization options.
- Added `IconColor` to the `useGetStandardObjectIcon` hook for improved icon color customization.
- Simplified logic for determining icon background color based on the presence of `targetRecordId` and `viewId`.
- Consolidated avatar rendering logic to reduce redundancy and improve readability.
These changes enhance the visual consistency and flexibility of navigation menu items.
- Introduced `getNavigationMenuItemIconColors` utility to manage icon colors based on the theme.
- Updated `CurrentWorkspaceMemberNavigationMenuItems` and `NavigationDrawerItemForObjectMetadataItem` to utilize the new icon color utility.
- Refactored `NavigationMenuItemIcon` to include a styled background for icons, improving visual consistency.
- Adjusted `NavigationDrawerItem` and `NavigationDrawerSubItem` to accept and apply background colors for icons.
These changes improve the visual representation of navigation items and ensure consistent theming across the application.
2026-02-02 07:33:35 +05:30
2592 changed files with 99573 additions and 40154 deletions
description:Create validation logic and migration action builders for syncable entities in Twenty. Use when implementing business rule validation, uniqueness checks, foreign key validation, or building workspace migration actions for syncable entities. Validators never throw and never mutate.
description:Create cache services and transformation utilities for syncable entities in Twenty. Use when implementing entity-to-flat conversions, input DTO transpilation to universal flat entities, or cache recomputation for syncable entities.
---
# Syncable Entity: Cache & Transform (Step 2/6)
**Purpose**: Create cache layer and transformation utilities to convert between different entity representations.
**When to use**: After completing Step 1 (Types & Constants). Required before building validators and action handlers.
description:Wire syncable entity services into NestJS modules, create service layer and resolvers for Twenty entities. Use when registering builders, validators, and action handlers in modules, creating business services, or exposing entities via GraphQL API with proper exception handling.
---
# Syncable Entity: Integration (Step 5/6)
**Purpose**: Wire everything together, register in modules, create services and resolvers.
**When to use**: After completing Steps 1-4 (all previous steps). Required before testing.
description:Implement action handlers for executing workspace migrations in Twenty. Use when creating database operations for syncable entities, implementing universal-to-flat entity transpilation, or handling create/update/delete actions in the runner layer.
---
# Syncable Entity: Runner & Actions (Step 4/6)
**Purpose**: Execute migration actions against the database with proper transpilation from universal to flat entities.
**When to use**: After completing Steps 1-3 (Types, Cache, Builder). Required before integration.
description:Create comprehensive integration tests for syncable entities in Twenty. Use when writing integration tests for metadata entities, covering validator exceptions, input transpilation errors, and CRUD operations. Tests are MANDATORY for all syncable entities.
description:Define types, entities, and central constant registrations for syncable entities in Twenty's workspace migration system. Use when creating new syncable entities, defining TypeORM entities, flat entity types, or registering in central constants (ALL_ENTITY_PROPERTIES_CONFIGURATION_BY_METADATA_NAME, ALL_ONE_TO_MANY_METADATA_RELATIONS, ALL_MANY_TO_ONE_METADATA_FOREIGN_KEY, ALL_MANY_TO_ONE_METADATA_RELATIONS).
---
# Syncable Entity: Types & Constants (Step 1/6)
**Purpose**: Define all types, entities, and register in central constants. This is the foundation - everything else depends on these types being correct.
**When to use**: First step when creating any new syncable entity. Must be completed before other steps.
This constant is **type-checked** — values for `metadataName`, `flatEntityForeignKeyAggregator`, and `universalFlatEntityForeignKeyAggregator` are derived from entity type definitions. The aggregator names follow the pattern: remove trailing `'s'` from the relation property name, then append `Ids` or `UniversalIdentifiers`.
```typescript
exportconstALL_ONE_TO_MANY_METADATA_RELATIONS={
// ... existing entries
myEntity:{
// If myEntity has a `childEntities: ChildEntityEntity[]` property:
Low-level primitive constant. Only contains `foreignKey` — the column name ending in `Id` that stores the foreign key. Type-checked against entity properties.
Derived from both `ALL_MANY_TO_ONE_METADATA_FOREIGN_KEY` (for `foreignKey` type and `universalForeignKey` derivation) and `ALL_ONE_TO_MANY_METADATA_RELATIONS` (for `inverseOneToManyProperty` key constraint). This is the main constant consumed by utils and optimistic tooling.
```typescript
exportconstALL_MANY_TO_ONE_METADATA_RELATIONS={
// ... existing entries
myEntity:{
workspace: null,
application: null,
parentEntity:{
metadataName:'parentEntity',
foreignKey:'parentEntityId',
inverseOneToManyProperty:'myEntities',// key in ALL_ONE_TO_MANY_METADATA_RELATIONS['parentEntity'], or null if no inverse
-`inverseOneToManyProperty` — must be a key in `ALL_ONE_TO_MANY_METADATA_RELATIONS[targetMetadataName]`, or `null` if the target entity doesn't expose an inverse one-to-many relation
-`universalForeignKey` — derived from `foreignKey` by replacing the `Id` suffix with `UniversalIdentifier`
- Optimistic utils resolve `flatEntityForeignKeyAggregator` / `universalFlatEntityForeignKeyAggregator` at runtime by looking up `inverseOneToManyProperty` in `ALL_ONE_TO_MANY_METADATA_RELATIONS`
---
## Checklist
Before moving to Step 2:
- [ ] Metadata name added to `ALL_METADATA_NAME`
- [ ] TypeORM entity created (extends `SyncableEntity`)
- [ ]`isCustom` column added
- [ ] Flat entity type defined
- [ ] Flat entity maps type defined (if needed)
- [ ] Editable properties constant defined
- [ ] Universal and flat action types defined
- [ ] Registered in `AllFlatEntityTypesByMetadataName`
- [ ] Registered in `ALL_ENTITY_PROPERTIES_CONFIGURATION_BY_METADATA_NAME`
- [ ] Registered in `ALL_ONE_TO_MANY_METADATA_RELATIONS` (if entity has one-to-many relations)
- [ ] Registered in `ALL_MANY_TO_ONE_METADATA_FOREIGN_KEY`
- [ ] Registered in `ALL_MANY_TO_ONE_METADATA_RELATIONS`
- [ ] TypeScript compiles without errors
---
## Next Step
Once all types and constants are defined, proceed to:
console.error('[NX]: The "installation" entry in the "nx.json" file is required when running the nx wrapper. See https://nx.dev/recipes/installation/install-non-javascript');
process.exit(1);
}
}
catch{
console.error('[NX]: The "nx.json" file is required when running the nx wrapper. See https://nx.dev/recipes/installation/install-non-javascript');
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, dev mode (watch & sync), generate, uninstall, and function management
- Preconfigured scripts for auth, dev mode (watch & sync), uninstall, and function management
- Strong TypeScript support and typed client generation
## Documentation
@@ -35,45 +35,84 @@ cd my-twenty-app
corepack enable
yarn install
# Get help
yarn runhelp
# Get help and list all available commands
yarn twentyhelp
# Authenticate using your API key (you'll be prompted)
yarn auth:login
yarn twenty auth:login
# Add a new entity to your application (guided)
yarn entity:add
# Generate a typed Twenty client and workspace entity types
yarn app:generate
yarn twenty entity:add
# Start dev mode: watches, builds, and syncs local changes to your workspace
yarn app:dev
# (also auto-generates a typed API client in node_modules/twenty-sdk/generated)
-A prewired`twenty` script that delegates to the `twenty` CLI from twenty-sdk
**Example files (controlled by scaffolding mode):**
-`objects/example-object.ts` — Example custom object with a text field
-`fields/example-field.ts` — Example standalone field extending the example object
-`logic-functions/hello-world.ts` — Example logic function with HTTP trigger
-`front-components/hello-world.tsx` — Example front component
-`views/example-view.ts` — Example saved view for the example object
-`navigation-menu-items/example-navigation-menu-item.ts` — Example sidebar navigation link
## Next steps
-Use`yarn auth:login` to authenticate with your Twenty workspace.
-Explore the generated project and add your first entity with `yarn entity:add` (logic functions, front components, objects, roles).
-Use `yarn app:dev` while you iterate — it watches, builds, and syncs changes to your workspace in real time.
-Keep your types up‑to‑date using `yarn app:generate`.
-Run`yarn twenty help` to see all available commands.
-Use `yarn twenty auth:login` to authenticate with your Twenty workspace.
-Explore the generated project and add your first entity with `yarn twenty entity:add` (logic functions, front components, objects, roles, views, navigation menu items).
-Use `yarn twenty app:dev` while you iterate — it watches, builds, and syncs changes to your workspace in real time.
- Types are auto‑generated by `yarn twenty app:dev` and stored in `node_modules/twenty-sdk/generated`.
## Publish your application
@@ -101,8 +140,8 @@ git push
Our team reviews contributions for quality, security, and reusability before merging.
## Troubleshooting
- Auth prompts not appearing: run `yarn auth:login` again and verify the API key permissions.
- Types not generated: ensure `yarn app:generate` runs without errors, then re‑start `yarn app:dev`.
- Auth prompts not appearing: run `yarn twenty auth:login` again and verify the API key permissions.
- Types not generated: ensure `yarn twenty app:dev` is running — it auto‑generates the typed client.
## Contributing
- See our [GitHub](https://github.com/twentyhq/twenty)
# Uninstall the application from the current workspace
yarn app:uninstall
yarn twenty app:uninstall
# Display commands' help
yarn help
yarn twenty help
```
See also: the CLI reference pages for [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) and [twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk).
@@ -72,9 +85,9 @@ When you run `npx create-twenty-app@latest my-twenty-app`, the scaffolder:
- Copies a minimal base application into `my-twenty-app/`
- Adds a local `twenty-sdk` dependency and Yarn 4 configuration
- Creates config files and scripts wired to the `twenty` CLI
- Generates a default application config and a default function role
- Generates core files (application config, default function role, post-install function) plus example files based on the scaffolding mode
A freshly scaffolded app looks like this:
A freshly scaffolded app with the default `--exhaustive` mode looks like this:
```text filename="my-twenty-app/"
my-twenty-app/
@@ -93,15 +106,26 @@ my-twenty-app/
├── application-config.ts # Required - main application configuration
├── roles/
│ └── default-role.ts # Default role for logic functions
├── objects/
│ └── example-object.ts # Example custom object definition
├── fields/
│ └── example-field.ts # Example standalone field definition
├── logic-functions/
│ └── hello-world.ts # Example logic function
└── front-components/
└── hello-world.tsx # Example frontcomponent
│ ├── hello-world.ts # Example logic function
│ └── post-install.ts # Post-install logic function
├── front-components/
│ └── hello-world.tsx # Example front component
├── views/
│ └── example-view.ts # Example saved view definition
└── navigation-menu-items/
└── example-navigation-menu-item.ts # Example sidebar navigation link
```
With `--minimal`, only the core files are created (`application-config.ts`, `roles/default-role.ts`, and `logic-functions/post-install.ts`). With `--interactive`, you choose which example files to include.
At a high level:
- **package.json**: Declares the app name, version, engines (Node 24+, Yarn 4), and adds `twenty-sdk` plus scripts like `app:dev`, `app:generate`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall`, and authentication commands that delegate to the local `twenty` CLI.
- **package.json**: Declares the app name, version, engines (Node 24+, Yarn 4), and adds `twenty-sdk` plus a `twenty` script that delegates to the local `twenty` CLI. Run `yarn twenty help` to list all available commands.
- **.gitignore**: Ignores common artifacts such as `node_modules`, `.yarn`, `generated/` (typed client), `dist/`, `build/`, coverage folders, log files, and `.env*` files.
- **yarn.lock**, **.yarnrc.yml**, **.yarn/**: Lock and configure the Yarn 4 toolchain used by the project.
- **.nvmrc**: Pins the Node.js version expected by the project.
@@ -121,6 +145,8 @@ The SDK detects entities by parsing your TypeScript files for **`export default
| `defineFrontComponent()` | Front component definitions |
| `defineRole()` | Role definitions |
| `defineField()` | Field extensions for existing objects |
| `defineView()` | Saved view definitions |
| `defineNavigationMenuItem()` | Navigation menu item definitions |
<Note>
**File naming is flexible.** Entity detection is AST-based — the SDK scans your source files for the `export default define<Entity>({...})` pattern. You can organize your files and folders however you like. Grouping by entity type (e.g., `logic-functions/`, `roles/`) is just a convention for code organization, not a requirement.
Once you've switched workspaces with `auth:switch`, all subsequent commands will use that workspace by default. You can still override it temporarily with `--workspace <name>`.
Once you've switched workspaces with `yarn twenty auth:switch`, all subsequent commands will use that workspace by default. You can still override it temporarily with `--workspace <name>`.
## Use the SDK resources (types & config)
@@ -192,6 +218,8 @@ The SDK provides helper functions for defining your app entities. As described i
| `defineFrontComponent()` | Define front components for custom UI |
| `defineRole()` | Configure role permissions and object access |
| `defineField()` | Extend existing objects with additional fields |
| `defineView()` | Define saved views for objects |
These functions validate your configuration at build time and provide IDE autocompletion and type safety.
@@ -274,10 +302,14 @@ Key points:
- The `universalIdentifier` must be unique and stable across deployments.
- Each field requires a `name`, `type`, `label`, and its own stable `universalIdentifier`.
- The `fields` array is optional — you can define objects without custom fields.
- You can scaffold new objects using `yarn entity:add`, which guides you through naming, fields, and relationships.
- You can scaffold new objects using `yarn twenty entity:add`, which guides you through naming, fields, and relationships.
<Note>
**Base fields are created automatically.** When you define a custom object, Twenty automatically adds standard fields such as `name`, `createdAt`, `updatedAt`, `createdBy`, `position`, and `deletedAt`. You don't need to define these in your `fields` array — only add your custom fields.
**Base fields are created automatically.** When you define a custom object, Twenty automatically adds standard fields
such as `id`, `name`, `createdAt`, `updatedAt`, `createdBy`, `updatedBy` and `deletedAt`.
You don't need to define these in your `fields` array — only add your custom fields.
You can override default fields by defining a field with the same name in your `fields` array,
but this is not recommended.
</Note>
@@ -288,6 +320,7 @@ Every app has a single `application-config.ts` file that describes:
- **Who the app is**: identifiers, display name, and description.
- **How its functions run**: which role they use for permissions.
- **(Optional) variables**: key–value pairs exposed to your functions as environment variables.
- **(Optional) post-install function**: a logic function that runs after the app is installed.
Use `defineApplication()` to define your application configuration:
@@ -295,6 +328,7 @@ Use `defineApplication()` to define your application configuration:
// src/application-config.ts
import { defineApplication } from 'twenty-sdk';
import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role';
import { POST_INSTALL_UNIVERSAL_IDENTIFIER } from 'src/logic-functions/post-install';
- `universalIdentifier` fields are deterministic IDs you own; generate them once and keep them stable across syncs.
- `applicationVariables` become environment variables for your functions (for example, `DEFAULT_RECIPIENT_NAME` is available as `process.env.DEFAULT_RECIPIENT_NAME`).
- `defaultRoleUniversalIdentifier` must match the role file (see below).
- `postInstallLogicFunctionUniversalIdentifier` (optional) points to a logic function that runs automatically after the app is installed. See [Post-install functions](#post-install-functions).
#### Roles and permissions
@@ -449,6 +485,54 @@ Notes:
- The `triggers` array is optional. Functions without triggers can be used as utility functions called by other functions.
- You can mix multiple trigger types in a single function.
### Post-install functions
A post-install function is a logic function that runs automatically after your app is installed on a workspace. This is useful for one-time setup tasks such as seeding default data, creating initial records, or configuring workspace settings.
When you scaffold a new app with `create-twenty-app`, a post-install function is generated for you at `src/logic-functions/post-install.ts`:
- **Scaffolded**: Run `yarn entity:add` and choose the option to add a new logic function. This generates a starter file with a handler and config.
- **Scaffolded**: Run `yarn twenty entity:add` and choose the option to add a new logic function. This generates a starter file with a handler and config.
- **Manual**: Create a new `*.logic-function.ts` file and use `defineLogicFunction()`, following the same pattern.
### Marking a logic function as a tool
Logic functions can be exposed as **tools** for AI agents and workflows. When a function is marked as a tool, it becomes discoverable by Twenty's AI features and can be selected as a step in workflow automations.
To mark a logic function as a tool, set `isTool: true` and provide a `toolInputSchema` describing the expected input parameters using [JSON Schema](https://json-schema.org/):
description: 'Enrich a company record with external data',
timeoutSeconds: 10,
handler,
isTool: true,
toolInputSchema: {
type: 'object',
properties: {
companyName: {
type: 'string',
description: 'The name of the company to enrich',
},
domain: {
type: 'string',
description: 'The company website domain (optional)',
},
},
required: ['companyName'],
},
});
```
Key points:
- **`isTool`** (`boolean`, default: `false`): When set to `true`, the function is registered as a tool and becomes available to AI agents and workflow automations.
- **`toolInputSchema`** (`object`, optional): A JSON Schema object that describes the parameters your function accepts. AI agents use this schema to understand what inputs the tool expects and to validate calls. If omitted, the schema defaults to `{ type: 'object', properties: {} }` (no parameters).
- Functions with `isTool: false` (or unset) are **not** exposed as tools. They can still be executed directly or called by other functions, but will not appear in tool discovery.
- **Tool naming**: When exposed as a tool, the function name is automatically normalized to `logic_function_<name>` (lowercased, non-alphanumeric characters replaced with underscores). For example, `enrich-company` becomes `logic_function_enrich_company`.
- You can combine `isTool` with triggers — a function can be both a tool (callable by AI agents) and triggered by events (cron, database events, routes) at the same time.
<Note>
**Write a good `description`.** AI agents rely on the function's `description` field to decide when to use the tool. Be specific about what the tool does and when it should be called.
</Note>
### Front components
Front components let you build custom React components that render within Twenty's UI. Use `defineFrontComponent()` to define components with built-in validation:
@@ -573,16 +722,16 @@ Key points:
- Front components are React components that render in isolated contexts within Twenty.
- Use the `*.front-component.tsx` file suffix for automatic detection.
- The `component` field references your React component.
- Components are built and synced automatically during `yarn app:dev`.
- Components are built and synced automatically during `yarn twenty app:dev`.
You can create new front components in two ways:
- **Scaffolded**: Run `yarn entity:add` and choose the option to add a new front component.
- **Scaffolded**: Run `yarn twenty entity:add` and choose the option to add a new front component.
- **Manual**: Create a new `*.front-component.tsx` file and use `defineFrontComponent()`.
### Generated typed client
Run yarn app:generate to create a local typed client in generated/ based on your workspace schema. Use it in your functions:
The typed client is auto-generated by `yarn twenty app:dev` and stored in `node_modules/twenty-sdk/generated` based on your workspace schema. Use it in your functions:
The client is re-generated by `yarn app:generate`. Re-run after changing your objects or when onboarding to a new workspace.
The client is re-generated automatically by `yarn twenty app:dev` whenever your objects or fields change.
#### Runtime credentials in logic functions
@@ -612,40 +761,29 @@ Explore a minimal, end-to-end example that demonstrates objects, logic functions
## Manual setup (without the scaffolder)
While we recommend using `create-twenty-app` for the best getting-started experience, you can also set up a project manually. Do not install the CLI globally. Instead, add `twenty-sdk` as a local dependency and wire scripts in your package.json:
While we recommend using `create-twenty-app` for the best getting-started experience, you can also set up a project manually. Do not install the CLI globally. Instead, add `twenty-sdk` as a local dependency and wire a single script in your package.json:
```bash filename="Terminal"
yarn add -D twenty-sdk
```
Then add scripts like these:
Then add a `twenty` script:
```json filename="package.json"
{
"scripts": {
"auth:login": "twenty auth:login",
"auth:logout": "twenty auth:logout",
"auth:status": "twenty auth:status",
"auth:switch": "twenty auth:switch",
"auth:list": "twenty auth:list",
"app:dev": "twenty app:dev",
"app:generate": "twenty app:generate",
"app:uninstall": "twenty app:uninstall",
"entity:add": "twenty entity:add",
"function:logs": "twenty function:logs",
"function:execute": "twenty function:execute",
"help": "twenty help"
"twenty": "twenty"
}
}
```
Now you can run the same commands via Yarn, e.g. `yarn app:dev`, `yarn app:generate`, etc.
Now you can run all commands via `yarn twenty <command>`, e.g. `yarn twenty app:dev`, `yarn twenty help`, etc.
## Troubleshooting
- Authentication errors: run `yarn auth:login` and ensure your API key has the required permissions.
- Authentication errors: run `yarn twenty auth:login` and ensure your API key has the required permissions.
- Cannot connect to server: verify the API URL and that the Twenty server is reachable.
- Types or client missing/outdated: run `yarn app:generate`.
- Dev mode not syncing: ensure `yarn app:dev` is running and that changes are not ignored by your environment.
- Types or client missing/outdated: restart `yarn twenty app:dev` — it auto-generates the typed client.
- Dev mode not syncing: ensure `yarn twenty app:dev` is running and that changes are not ignored by your environment.
Discord Help Channel: https://discord.com/channels/1130383047699738754/1130386664812982322
* يُنشئ الملفات الأساسية (تهيئة التطبيق، دور الدالة الافتراضي، دالة ما بعد التثبيت) بالإضافة إلى ملفات الأمثلة بحسب وضع الإنشاء
يبدو التطبيق المُنشأ حديثًا بالقالب كما يلي:
يبدو التطبيق المُنشأ حديثًا باستخدام الوضع الافتراضي `--exhaustive` كما يلي:
```text filename="my-twenty-app/"
my-twenty-app/
@@ -91,18 +104,29 @@ my-twenty-app/
README.md
public/ # مجلد الأصول العامة (صور، خطوط، إلخ)
src/
├── application-config.ts # مطلوب - التكوين الرئيسي للتطبيق
├── application-config.ts # مطلوب - إعدادات التطبيق الرئيسية
├── roles/
│ └── default-role.ts # الدور الافتراضي لوظائف المنطق
│ └── default-role.ts # الدور الافتراضي للدوال المنطقية
├── objects/
│ └── example-object.ts # تعريف كائن مخصص — مثال
├── fields/
│ └── example-field.ts # تعريف حقل مستقل — مثال
├── logic-functions/
│ └── hello-world.ts # مثال لوظيفة منطقية
└── front-components/
└── hello-world.tsx # مثال لمكوّن الواجهة الأمامية
│ ├── hello-world.ts # دالة منطقية — مثال
│ └── post-install.ts # دالة منطقية لما بعد التثبيت
├── front-components/
│ └── hello-world.tsx # مكوّن واجهة أمامية — مثال
├── views/
│ └── example-view.ts # تعريف عرض محفوظ — مثال
└── navigation-menu-items/
└── example-navigation-menu-item.ts # رابط تنقّل في الشريط الجانبي — مثال
```
مع `--minimal`، سيتم إنشاء الملفات الأساسية فقط (`application-config.ts` و`roles/default-role.ts` و`logic-functions/post-install.ts`). مع `--interactive`، تختار ملفات الأمثلة التي تريد تضمينها.
بشكل عام:
* **package.json**: يصرّح باسم التطبيق والإصدار والمحرّكات (Node 24+، Yarn 4)، ويضيف `twenty-sdk` فضلًا عن نصوص مثل `app:dev` و`app:generate` و`entity:add` و`function:logs` و`function:execute` و`app:uninstall` وأوامر المصادقة التي تُفوِّض إلى `twenty` CLI المحلي.
* **package.json**: يصرّح باسم التطبيق والإصدار والمحرّكات (Node 24+، Yarn 4)، ويضيف `twenty-sdk` بالإضافة إلى نص برمجي `twenty` يفوِّض إلى `twenty` CLI المحلي. شغِّل `yarn twenty help` لعرض جميع الأوامر المتاحة.
* **.gitignore**: يتجاهل العناصر الشائعة مثل `node_modules` و`.yarn` و`generated/` (عميل مضبوط الأنواع) و`dist/` و`build/` ومجلدات التغطية وملفات السجلات وملفات `.env*`.
* **yarn.lock**، **.yarnrc.yml**، **.yarn/**: تقوم بقفل وتكوين حزمة أدوات Yarn 4 المستخدمة في المشروع.
* **.nvmrc**: يثبّت إصدار Node.js المتوقع للمشروع.
@@ -115,13 +139,15 @@ my-twenty-app/
يكتشف SDK الكيانات عبر تحليل ملفات TypeScript الخاصة بك بحثًا عن استدعاءات **`export default define<Entity>({...})`**. يحتوي كل نوع كيان على دالة مساعدة مقابلة يتم تصديرها من `twenty-sdk`:
| `defineFrontComponent()` | Front component definitions |
| `defineRole()` | تعريفات الأدوار |
| `defineField()` | امتدادات الحقول للكائنات الموجودة |
| `defineView()` | تعريفات العروض المحفوظة |
| `defineNavigationMenuItem()` | تعريفات عناصر قائمة التنقل |
<Note>
**تسمية الملفات مرنة.** يعتمد اكتشاف الكيانات على بنية الشجرة المجردة (AST) — إذ يقوم SDK بفحص ملفات المصدر لديك بحثًا عن النمط `export default define<Entity>({...})`. يمكنك تنظيم ملفاتك ومجلداتك كيفما تشاء. التجميع حسب نوع الكيان (مثلًا، `logic-functions/` و`roles/`) هو مجرد عرف لتنظيم الشيفرة، وليس مطلبًا إلزاميًا.
Once you've switched workspaces with `auth:switch`, all subsequent commands will use that workspace by default. You can still override it temporarily with `--workspace <name>`.
بمجرد أن تقوم بالتبديل بين مساحات العمل باستخدام `yarn twenty auth:switch`، ستستخدم جميع الأوامر اللاحقة تلك المساحة افتراضيًا. You can still override it temporarily with `--workspace <name>`.
## استخدم موارد SDK (الأنواع والتكوين)
@@ -186,14 +212,16 @@ Once you've switched workspaces with `auth:switch`, all subsequent commands will
يوفّر SDK دوالًا مساعدة لتعريف كيانات تطبيقك. كما هو موضح في [اكتشاف الكيانات](#entity-detection)، يجب استخدام `export default define<Entity>({...})` كي يتم اكتشاف كياناتك:
* `universalIdentifier` يجب أن يكون فريدًا وثابتًا عبر عمليات النشر.
* يتطلب كل حقل `name` و`type` و`label` ومعرّف `universalIdentifier` ثابتًا خاصًا به.
* المصفوفة `fields` اختيارية — يمكنك تعريف كائنات بدون حقول مخصصة.
* يمكنك إنشاء كائنات جديدة باستخدام `yarn entity:add`، والذي يرشدك خلال التسمية والحقول والعلاقات.
* يمكنك إنشاء كائنات جديدة باستخدام `yarn twenty entity:add`، والذي يرشدك خلال التسمية والحقول والعلاقات.
<Note>
**يتم إنشاء الحقول الأساسية تلقائيًا.** عند تعريف كائن مخصص، يضيف Twenty تلقائيًا حقولًا قياسية مثل `name` و`createdAt` و`updatedAt` و`createdBy` و`position` و`deletedAt`. لا تحتاج إلى تعريف هذه في مصفوفة `fields` — أضف فقط حقولك المخصصة.
**يتم إنشاء الحقول الأساسية تلقائيًا.** عند تعريف كائن مخصص، يضيف Twenty تلقائيًا حقولًا قياسية
مثل `id` و`name` و`createdAt` و`updatedAt` و`createdBy` و`updatedBy` و`deletedAt`.
لا تحتاج إلى تعريف هذه في مصفوفة `fields` — أضف فقط حقولك المخصصة.
يمكنك تجاوز الحقول الافتراضية من خلال تعريف حقل بالاسم نفسه في مصفوفة `fields` الخاصة بك،
لكن هذا غير مستحسن.
</Note>
### تكوين التطبيق (application-config.ts)
@@ -289,6 +321,7 @@ export default defineObject({
* **هوية التطبيق**: المعرفات، اسم العرض، والوصف.
* **كيفية تشغيل وظائفه**: الدور الذي تستخدمه للأذونات.
* حقول `universalIdentifier` هي معرّفات حتمية تخصك؛ أنشئها مرة واحدة واحتفظ بها ثابتة عبر عمليات المزامنة.
* `applicationVariables` تصبح متغيرات بيئة لوظائفك (على سبيل المثال، `DEFAULT_RECIPIENT_NAME` متاح كـ `process.env.DEFAULT_RECIPIENT_NAME`).
* `defaultRoleUniversalIdentifier` يجب أن يطابق ملف الدور (انظر أدناه).
* `postInstallLogicFunctionUniversalIdentifier` (optional) points to a logic function that runs automatically after the app is installed. See [Post-install functions](#post-install-functions).
* المصفوفة `triggers` اختيارية. يمكن استخدام الوظائف بدون مشغلات كوظائف مساعدة تُستدعى بواسطة وظائف أخرى.
* يمكنك مزج أنواع متعددة من المشغلات في وظيفة واحدة.
### Post-install functions
A post-install function is a logic function that runs automatically after your app is installed on a workspace. This is useful for one-time setup tasks such as seeding default data, creating initial records, or configuring workspace settings.
عند إنشاء هيكل تطبيق جديد باستخدام `create-twenty-app`، يتم إنشاء دالة ما بعد التثبيت لك في `src/logic-functions/post-install.ts`:
* **مُنشأ بالقالب**: شغّل `yarn entity:add` واختر خيار إضافة وظيفة منطقية جديدة. يُولّد هذا ملفًا مبدئيًا مع معالج وتكوين.
* **مُنشأ بالقالب**: شغّل `yarn twenty entity:add` واختر خيار إضافة وظيفة منطقية جديدة. يُولّد هذا ملفًا مبدئيًا مع معالج وتكوين.
* **يدوي**: أنشئ ملفًا جديدًا `*.logic-function.ts` واستخدم `defineLogicFunction()` مع اتباع النمط نفسه.
### تمييز دالة منطقية كأداة
يمكن إتاحة الدوال المنطقية بوصفها **أدوات** لوكلاء الذكاء الاصطناعي وسير العمل. عندما يتم تمييز دالة كأداة، تصبح قابلة للاكتشاف بواسطة ميزات الذكاء الاصطناعي الخاصة بـ Twenty ويمكن اختيارها كخطوة في أتمتة سير العمل.
description: 'Enrich a company record with external data',
timeoutSeconds: 10,
handler,
isTool: true,
toolInputSchema: {
type: 'object',
properties: {
companyName: {
type: 'string',
description: 'The name of the company to enrich',
},
domain: {
type: 'string',
description: 'The company website domain (optional)',
},
},
required: ['companyName'],
},
});
```
النقاط الرئيسية:
* **`isTool`** (`boolean`, الافتراضي: `false`): عند ضبطه على `true`، يتم تسجيل الدالة كأداة وتصبح متاحة لوكلاء الذكاء الاصطناعي ولأتمتة سير العمل.
* **`toolInputSchema`** (`object`, اختياري): كائن JSON Schema يصف المعلمات التي تقبلها دالتك. يستخدم وكلاء الذكاء الاصطناعي هذا المخطط لفهم المدخلات التي تتوقعها الأداة وللتحقق من صحة الاستدعاءات. إذا تم إغفاله، فالقيمة الافتراضية للمخطط هي `{ type: 'object', properties: {} }` (من دون معلمات).
* الدوال التي لديها `isTool: false` (أو غير معيَّنة) **غير** معروضة كأدوات. لا يزال بالإمكان تنفيذها مباشرةً أو استدعاؤها بواسطة دوال أخرى، لكنها لن تظهر في اكتشاف الأدوات.
* **تسمية الأداة**: عند كشفها كأداة، يتم تطبيع اسم الدالة تلقائيًا إلى `logic_function_<name>` (تحويله إلى أحرف صغيرة، واستبدال المحارف غير الأبجدية الرقمية بشرطات سفلية). على سبيل المثال، `enrich-company` تصبح `logic_function_enrich_company`.
* يمكنك دمج `isTool` مع المشغِّلات — إذ يمكن للدالة أن تكون أداة (قابلة للاستدعاء من قِبل وكلاء الذكاء الاصطناعي) وأن تُشغَّل بواسطة أحداث (cron، وأحداث قاعدة البيانات، والمسارات) في الوقت نفسه.
<Note>
**اكتب `description` جيدًا.** يعتمد وكلاء الذكاء الاصطناعي على حقل `description` الخاص بالدالة لتحديد وقت استخدام الأداة. كن محددًا بشأن ما تفعله الأداة ومتى ينبغي استدعاؤها.
</Note>
### المكوّنات الأمامية
تتيح لك المكوّنات الأمامية إنشاء مكوّنات React مخصّصة تُعرَض داخل واجهة مستخدم Twenty. استخدم `defineFrontComponent()` لتعريف مكوّنات مع تحقّق مدمج:
شغّل yarn app:generate لإنشاء عميل محلي مضبوط الأنواع في generated/ استنادًا إلى مخطط مساحة العمل لديك. استخدمه في وظائفك:
يُولَّد العميل مضبوط الأنواع تلقائيًا بواسطة `yarn twenty app:dev` ويُخزَّن في `node_modules/twenty-sdk/generated` استنادًا إلى مخطط مساحة العمل لديك. استخدمه في وظائفك:
بينما نوصي باستخدام `create-twenty-app` للحصول على أفضل تجربة للبدء، يمكنك أيضًا إعداد مشروع يدويًا. لا تثبّت CLI عالميًا. بدل ذلك، أضف `twenty-sdk` كاعتماد محلي ووصل السكربتات في ملف package.json لديك:
بينما نوصي باستخدام `create-twenty-app` للحصول على أفضل تجربة للبدء، يمكنك أيضًا إعداد مشروع يدويًا. لا تثبّت CLI عالميًا. بدل ذلك، أضف `twenty-sdk` كاعتماد محلي واربط سكربتًا واحدًا في ملف package.json لديك:
```bash filename="Terminal"
yarn add -D twenty-sdk
```
ثم أضف نصوصًا مثل هذه:
ثم أضف سكربتًا باسم `twenty`:
```json filename="package.json"
{
"scripts": {
"auth:login": "twenty auth:login",
"auth:logout": "twenty auth:logout",
"auth:status": "twenty auth:status",
"auth:switch": "twenty auth:switch",
"auth:list": "twenty auth:list",
"app:dev": "twenty app:dev",
"app:generate": "twenty app:generate",
"app:uninstall": "twenty app:uninstall",
"entity:add": "twenty entity:add",
"function:logs": "twenty function:logs",
"function:execute": "twenty function:execute",
"help": "twenty help"
"twenty": "twenty"
}
}
```
يمكنك الآن تشغيل الأوامر نفسها عبر Yarn، مثل `yarn app:dev` و`yarn app:generate`، إلخ.
الآن يمكنك تشغيل جميع الأوامر عبر `yarn twenty <command>`، مثلًا: `yarn twenty app:dev`، `yarn twenty help`، إلخ.
## استكشاف الأخطاء وإصلاحها
* أخطاء المصادقة: شغّل `yarn auth:login` وتأكد من أن مفتاح واجهة برمجة التطبيقات لديك يمتلك الأذونات المطلوبة.
* أخطاء المصادقة: شغّل `yarn twenty auth:login` وتأكد من أن مفتاح واجهة برمجة التطبيقات لديك يمتلك الأذونات المطلوبة.
* يتعذّر الاتصال بالخادم: تحقق من عنوان URL لواجهة البرمجة وأن خادم Twenty قابل للوصول.
* الأنواع أو العميل مفقود/قديم: شغّل `yarn app:generate`.
* وضع التطوير لا يزامن: تأكد من أن `yarn app:dev` قيد التشغيل وأن التغييرات ليست متجاهلة من بيئتك.
* الأنواع أو العميل مفقود/قديم: أعد تشغيل `yarn twenty app:dev` — فهو ينشئ العميل مضبوط الأنواع بشكل تلقائي.
* وضع التطوير لا يزامن: تأكد من أن `yarn twenty app:dev` قيد التشغيل وأن التغييرات ليست متجاهلة من بيئتك.
قناة المساعدة على Discord: https://discord.com/channels/1130383047699738754/1130386664812982322
# Odinstalujte aplikaci z aktuálního pracovního prostoru
yarn app:uninstall
yarn twenty app:uninstall
# Zobrazte nápovědu k příkazům
yarn help
yarn twenty help
```
Viz také: referenční stránky CLI pro [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) a [twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk).
@@ -73,9 +86,9 @@ Když spustíte `npx create-twenty-app@latest my-twenty-app`, scaffolder:
* Zkopíruje minimální základní aplikaci do `my-twenty-app/`
* Přidá lokální závislost `twenty-sdk` a konfiguraci pro Yarn 4
* Vytvoří konfigurační soubory a skripty napojené na `twenty` CLI
* Vygeneruje výchozí konfiguraci aplikace a výchozí roli funkcí
* Vygeneruje základní soubory (konfigurace aplikace, výchozí role funkcí, postinstalační funkce) a k nim ukázkové soubory podle zvoleného režimu generování kostry
Čerstvě vytvořená aplikace vypadá takto:
Čerstvě vygenerovaná aplikace s výchozím režimem `--exhaustive` vypadá takto:
```text filename="my-twenty-app/"
my-twenty-app/
@@ -94,15 +107,26 @@ my-twenty-app/
├── application-config.ts # Povinné – hlavní konfigurace aplikace
├── roles/
│ └── default-role.ts # Výchozí role pro logické funkce
├── objects/
│ └── example-object.ts # Ukázková definice vlastního objektu
├── fields/
│ └── example-field.ts # Ukázková samostatná definice pole
S volbou `--minimal` se vytvoří pouze základní soubory (`application-config.ts`, `roles/default-role.ts` a `logic-functions/post-install.ts`). S volbou `--interactive` si vyberete, které ukázkové soubory chcete zahrnout.
V kostce:
* **package.json**: Deklaruje název aplikace, verzi, engines (Node 24+, Yarn 4) a přidává `twenty-sdk` plus skripty jako `app:dev`, `app:generate`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall` a autentizační příkazy, které delegují na lokální `twenty` CLI.
* **package.json**: Deklaruje název aplikace, verzi, engines (Node 24+, Yarn 4) a přidává `twenty-sdk` plus skript `twenty`, který deleguje na lokální `twenty` CLI. Spusťte `yarn twenty help` pro výpis všech dostupných příkazů.
* **.gitignore**: Ignoruje běžné artefakty jako `node_modules`, `.yarn`, `generated/` (typovaný klient), `dist/`, `build/`, složky s coverage, logy a soubory `.env*`.
* **yarn.lock**, **.yarnrc.yml**, **.yarn/**: Zamykají a konfigurují nástrojový řetězec Yarn 4 používaný projektem.
* **.nvmrc**: Fixuje verzi Node.js požadovanou projektem.
@@ -115,13 +139,15 @@ V kostce:
SDK detekuje entity analýzou vašich souborů TypeScript a hledá volání **`export default define<Entity>({...})`**. Každý typ entity má odpovídající pomocnou funkci exportovanou z `twenty-sdk`:
**Pojmenování souborů je flexibilní.** Detekce entit je založená na AST — SDK prochází vaše zdrojové soubory a hledá vzor `export default define<Entity>({...})`. Soubory a složky můžete organizovat, jak chcete. Seskupování podle typu entity (např. `logic-functions/`, `roles/`) je pouze konvence pro organizaci kódu, nikoli požadavek.
* `yarn entity:add` přidá soubory s definicemi entit do `src/` pro vaše vlastní objekty, funkce, frontové komponenty nebo role.
* `yarn twenty app:dev` automaticky vygeneruje typovaného klienta API v `node_modules/twenty-sdk/generated` (typovaný klient Twenty + typy pracovního prostoru).
* `yarn twenty entity:add` přidá soubory s definicemi entit do `src/` pro vaše vlastní objekty, funkce, frontové komponenty nebo role.
## Ověření
Při prvním spuštění `yarn auth:login` budete vyzváni k zadání:
Při prvním spuštění `yarn twenty auth:login` budete vyzváni k zadání:
* URL API (výchozí je http://localhost:3000 nebo váš aktuální profil pracovního prostoru)
* Klíč API
@@ -158,25 +184,25 @@ Vaše přihlašovací údaje se ukládají pro jednotlivé uživatele do `~/.twe
Jakmile přepnete pracovní prostor pomocí `auth:switch`, všechny následující příkazy budou tento pracovní prostor používat jako výchozí. Můžete jej stále dočasně přepsat pomocí `--workspace <name>`.
Jakmile přepnete pracovní prostor pomocí `yarn twenty auth:switch`, všechny následující příkazy budou tento pracovní prostor používat jako výchozí. Můžete jej stále dočasně přepsat pomocí `--workspace <name>`.
## Používejte zdroje SDK (typy a konfiguraci)
@@ -186,14 +212,16 @@ twenty-sdk poskytuje typované stavební bloky a pomocné funkce, které použí
SDK poskytuje pomocné funkce pro definování entit vaší aplikace. Jak je popsáno v [Detekce entit](#entity-detection), musíte použít `export default define<Entity>({...})`, aby byly vaše entity detekovány:
Tyto funkce validují vaši konfiguraci v době sestavení a poskytují automatické doplňování v IDE a typovou bezpečnost.
@@ -276,10 +304,14 @@ Hlavní body:
* Hodnota `universalIdentifier` musí být jedinečná a stabilní napříč nasazeními.
* Každé pole vyžaduje `name`, `type`, `label` a svůj vlastní stabilní `universalIdentifier`.
* Pole `fields` je volitelné — objekty můžete definovat i bez vlastních polí.
* Nové objekty můžete vygenerovat pomocí `yarn entity:add`, který vás provede pojmenováním, poli a vztahy.
* Nové objekty můžete vygenerovat pomocí `yarn twenty entity:add`, který vás provede pojmenováním, poli a vztahy.
<Note>
**Základní pole jsou vytvořena automaticky.** Když definujete vlastní objekt, Twenty automaticky přidá standardní pole jako `name`, `createdAt`, `updatedAt`, `createdBy`, `position` a `deletedAt`. Nemusíte je definovat v poli `fields` — přidejte pouze svá vlastní pole.
**Základní pole jsou vytvořena automaticky.** Když definujete vlastní objekt, Twenty automaticky přidá standardní pole
jako `id`, `name`, `createdAt`, `updatedAt`, `createdBy`, `updatedBy` a `deletedAt`.
Nemusíte je definovat v poli `fields` — přidejte pouze svá vlastní pole.
Výchozí pole můžete přepsat definováním pole se stejným názvem v poli `fields`,
ale to se nedoporučuje.
</Note>
### Konfigurace aplikace (application-config.ts)
@@ -289,6 +321,7 @@ Každá aplikace má jeden soubor `application-config.ts`, který popisuje:
* **Identitu aplikace**: identifikátory, zobrazovaný název a popis.
* **Jak běží její funkce**: kterou roli používají pro oprávnění.
* **(Volitelné) proměnné**: dvojice klíč–hodnota zpřístupněné vašim funkcím jako proměnné prostředí.
* **(Volitelná) postinstalační funkce**: logická funkce, která se spouští po instalaci aplikace.
Use `defineApplication()` to define your application configuration:
@@ -296,6 +329,7 @@ Use `defineApplication()` to define your application configuration:
// src/application-config.ts
import { defineApplication } from 'twenty-sdk';
import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role';
import { POST_INSTALL_UNIVERSAL_IDENTIFIER } from 'src/logic-functions/post-install';
* Pole `universalIdentifier` jsou deterministická ID, která vlastníte; vygenerujte je jednou a udržujte je stabilní napříč synchronizacemi.
* `applicationVariables` se stanou proměnnými prostředí pro vaše funkce (například `DEFAULT_RECIPIENT_NAME` je dostupné jako `process.env.DEFAULT_RECIPIENT_NAME`).
* `defaultRoleUniversalIdentifier` se musí shodovat se souborem role (viz níže).
* `postInstallLogicFunctionUniversalIdentifier` (volitelné) odkazuje na logickou funkci, která se automaticky spustí po instalaci aplikace. Viz [Postinstalační funkce](#post-install-functions).
#### Role a oprávnění
@@ -457,6 +493,55 @@ Poznámky:
* Pole `triggers` je volitelné. Funkce bez spouštěčů lze použít jako pomocné funkce volané jinými funkcemi.
* V jedné funkci můžete kombinovat více typů spouštěčů.
### Postinstalační funkce
Postinstalační funkce je logická funkce, která se automaticky spouští po instalaci vaší aplikace do pracovního prostoru. To je užitečné pro jednorázové úlohy nastavení, jako je naplnění výchozími daty, vytvoření počátečních záznamů nebo konfigurace nastavení pracovního prostoru.
Když vygenerujete kostru nové aplikace pomocí `create-twenty-app`, vytvoří se pro vás postinstalační funkce v `src/logic-functions/post-install.ts`:
* **Vygenerované**: Spusťte `yarn entity:add` a zvolte možnost přidat novou logickou funkci. Tím se vygeneruje startovací soubor s obslužnou funkcí a konfigurací.
* **Vygenerované**: Spusťte `yarn twenty entity:add` a zvolte možnost přidat novou logickou funkci. Tím se vygeneruje startovací soubor s obslužnou funkcí a konfigurací.
* **Ruční**: Vytvořte nový soubor `*.logic-function.ts` a použijte `defineLogicFunction()` podle stejného vzoru.
### Označení logické funkce jako nástroje
Logické funkce lze zpřístupnit jako **nástroje** pro agenty AI a pracovní postupy. Když je funkce označena jako nástroj, stane se dohledatelnou funkcemi AI produktu Twenty a lze ji vybrat jako krok v automatizacích pracovních postupů.
Chcete-li označit logickou funkci jako nástroj, nastavte `isTool: true` a poskytněte `toolInputSchema` popisující očekávané vstupní parametry pomocí [JSON Schema](https://json-schema.org/):
description: 'Enrich a company record with external data',
timeoutSeconds: 10,
handler,
isTool: true,
toolInputSchema: {
type: 'object',
properties: {
companyName: {
type: 'string',
description: 'The name of the company to enrich',
},
domain: {
type: 'string',
description: 'The company website domain (optional)',
},
},
required: ['companyName'],
},
});
```
Hlavní body:
* **`isTool`** (`boolean`, výchozí: `false`): Když je nastaveno na `true`, funkce je zaregistrována jako nástroj a zpřístupní se agentům AI a automatizacím pracovních postupů.
* **`toolInputSchema`** (`object`, volitelné): Objekt JSON Schema, který popisuje parametry, jež vaše funkce přijímá. Agenti AI používají toto schéma k pochopení toho, jaké vstupy nástroj očekává, a k ověřování volání. Pokud je vynecháno, schéma má výchozí podobu `{ type: 'object', properties: {} }` (žádné parametry).
* Funkce s `isTool: false` (nebo není nastaveno) **nejsou** zpřístupněny jako nástroje. Stále je lze spouštět přímo nebo volat z jiných funkcí, ale neobjeví se ve vyhledávání nástrojů.
* **Pojmenování nástrojů**: Když je funkce zpřístupněna jako nástroj, její název se automaticky normalizuje na `logic_function_<name>` (převedeno na malá písmena, nealfanumerické znaky jsou nahrazeny podtržítky). Například `enrich-company` se změní na `logic_function_enrich_company`.
* Můžete kombinovat `isTool` se spouštěči — funkce může být zároveň nástrojem (volatelným agenty AI) i spouštěna událostmi (cron, databázové události, routes).
<Note>
**Napište kvalitní `description`.** Agenti AI se spoléhají na pole funkce `description` při rozhodování, kdy nástroj použít. Buďte konkrétní ohledně toho, co nástroj dělá a kdy se má volat.
</Note>
### Frontendové komponenty
Frontendové komponenty vám umožňují vytvářet vlastní React komponenty, které se vykreslují v rozhraní Twenty. K definování komponent s vestavěnou validací použijte `defineFrontComponent()`:
@@ -584,16 +734,16 @@ Hlavní body:
* Frontendové komponenty jsou React komponenty, které se vykreslují v izolovaných kontextech v rámci Twenty.
* Pro automatickou detekci použijte příponu souboru `*.front-component.tsx`.
* Pole `component` odkazuje na vaši React komponentu.
* Komponenty se během `yarn app:dev` automaticky sestaví a synchronizují.
* Komponenty se během `yarn twenty app:dev` automaticky sestaví a synchronizují.
Nové frontendové komponenty můžete vytvořit dvěma způsoby:
* **Vygenerované**: Spusťte `yarn entity:add` a zvolte možnost přidat novou frontendovou komponentu.
* **Vygenerované**: Spusťte `yarn twenty entity:add` a zvolte možnost přidat novou frontendovou komponentu.
* **Ruční**: Vytvořte nový soubor `*.front-component.tsx` a použijte `defineFrontComponent()`.
### Generovaný typovaný klient
Spusťte yarn app:generate a vytvořte lokálního typovaného klienta v generated/ na základě schématu vašeho pracovního prostoru. Použijte jej ve svých funkcích:
Typovaný klient je automaticky generován pomocí `yarn twenty app:dev` a ukládá se do `node_modules/twenty-sdk/generated` podle schématu vašeho pracovního prostoru. Použijte jej ve svých funkcích:
Klient je znovu generován příkazem `yarn app:generate`. Spusťte znovu po změně vašich objektů nebo při připojování k novému pracovnímu prostoru.
Klient se automaticky znovu generuje pomocí `yarn twenty app:dev` kdykoli se změní vaše objekty nebo pole.
#### Běhové přihlašovací údaje v logických funkcích
@@ -623,40 +773,29 @@ Prozkoumejte minimalistický end-to-end příklad, který demonstruje objekty, l
## Ruční nastavení (bez scaffolderu)
Ačkoli pro nejlepší začátky doporučujeme použít `create-twenty-app`, projekt můžete nastavit i ručně. Neinstalujte CLI globálně. Místo toho přidejte `twenty-sdk` jako lokální závislost a propojte skripty v souboru package.json:
Ačkoli pro nejlepší začátky doporučujeme použít `create-twenty-app`, projekt můžete nastavit i ručně. Neinstalujte CLI globálně. Místo toho přidejte `twenty-sdk` jako lokální závislost a přidejte jeden skript do souboru package.json:
```bash filename="Terminal"
yarn add -D twenty-sdk
```
Poté přidejte skripty jako tyto:
Poté přidejte skript `twenty`:
```json filename="package.json"
{
"scripts": {
"auth:login": "twenty auth:login",
"auth:logout": "twenty auth:logout",
"auth:status": "twenty auth:status",
"auth:switch": "twenty auth:switch",
"auth:list": "twenty auth:list",
"app:dev": "twenty app:dev",
"app:generate": "twenty app:generate",
"app:uninstall": "twenty app:uninstall",
"entity:add": "twenty entity:add",
"function:logs": "twenty function:logs",
"function:execute": "twenty function:execute",
"help": "twenty help"
"twenty": "twenty"
}
}
```
Nyní můžete spouštět stejné příkazy přes Yarn, např. `yarn app:dev`, `yarn app:generate` atd.
Nyní můžete spouštět všechny příkazy přes `yarn twenty <command>`, např. `yarn twenty app:dev`, `yarn twenty help` atd.
## Řešení potíží
* Chyby ověření: spusťte `yarn auth:login` a ujistěte se, že váš klíč API má požadovaná oprávnění.
* Chyby ověření: spusťte `yarn twenty auth:login` a ujistěte se, že váš klíč API má požadovaná oprávnění.
* Nelze se připojit k serveru: ověřte URL API a že je server Twenty dosažitelný.
* Typy nebo klient chybí nebo jsou zastaralé: spusťte `yarn app:generate`.
* Režim vývoje nesynchronizuje: ujistěte se, že běží `yarn app:dev` a že vaše prostředí změny neignoruje.
* Types or client missing/outdated: restart `yarn twenty app:dev` — it auto-generates the typed client.
* Režim vývoje se nesynchronizuje: ujistěte se, že běží `yarn twenty app:dev` a že vaše prostředí změny neignoruje.
Kanál podpory na Discordu: https://discord.com/channels/1130383047699738754/1130386664812982322
# Die Anwendung aus dem aktuellen Arbeitsbereich deinstallieren
yarn app:uninstall
yarn twenty app:uninstall
# Hilfe zu Befehlen anzeigen
yarn help
yarn twenty help
```
Siehe auch: die CLI-Referenzseiten für [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) und [twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk).
@@ -73,9 +86,9 @@ Wenn Sie `npx create-twenty-app@latest my-twenty-app` ausführen, erledigt der S
* Kopiert eine minimale Basisanwendung nach `my-twenty-app/`
* Fügt eine lokale `twenty-sdk`-Abhängigkeit und die Yarn-4-Konfiguration hinzu
* Erstellt Konfigurationsdateien und Skripte, die an die `twenty`-CLI angebunden sind
* Generiert eine Standard-Anwendungskonfiguration und eine Standard-Funktionsrolle
* Erzeugt Kerndateien (Anwendungskonfiguration, Standardrolle für Logikfunktionen, Post-Installationsfunktion) sowie Beispieldateien entsprechend dem Scaffolding-Modus
Eine frisch erzeugte App sieht so aus:
Eine frisch erstellte App mit dem Standardmodus `--exhaustive` sieht so aus:
```text filename="my-twenty-app/"
my-twenty-app/
@@ -89,20 +102,31 @@ my-twenty-app/
eslint.config.mjs
tsconfig.json
README.md
public/ # Public assets folder (images, fonts, etc.)
public/ # Ordner für öffentliche Assets (Bilder, Schriftarten usw.)
src/
├── application-config.ts # Required - main application configuration
├── roles/
│ └── default-role.ts # Default role for logic functions
├── logic-functions/
│ └── hello-world.ts # Example logic function
└── front-components/
└── hello-world.tsx # Example front component
application-config.ts # Erforderlich Hauptkonfiguration der Anwendung
roles/
default-role.ts # Standardrolle für Logikfunktionen
objects/
example-object.ts # Beispiel für eine benutzerdefinierte Objektdefinition
fields/
example-field.ts # Beispiel für eine eigenständige Felddefinition
hello-world.tsx # Beispiel für eine Frontend-Komponente
views/
example-view.ts # Beispiel für eine gespeicherte View-Definition
navigation-menu-items/
example-navigation-menu-item.ts # Beispiel für einen Navigationslink in der Seitenleiste
```
Mit `--minimal` werden nur die Kerndateien erstellt (`application-config.ts`, `roles/default-role.ts` und `logic-functions/post-install.ts`). Mit `--interactive` wählst du aus, welche Beispieldateien enthalten sein sollen.
Auf hoher Ebene:
* **package.json**: Deklariert den App-Namen, die Version, Engines (Node 24+, Yarn 4) und fügt `twenty-sdk` sowie Skripte wie `app:dev`, `app:generate`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall` sowie Authentifizierungsbefehle hinzu, die an die lokale `twenty`-CLI delegieren.
* **package.json**: Deklariert den App-Namen, die Version und die Engines (Node 24+, Yarn 4) und fügt `twenty-sdk` sowie ein `twenty`-Skript hinzu, das an die lokale `twenty`-CLI delegiert. Führe `yarn twenty help` aus, um alle verfügbaren Befehle aufzulisten.
* **.gitignore**: Ignoriert übliche Artefakte wie `node_modules`, `.yarn`, `generated/` (typisierter Client), `dist/`, `build/`, Coverage-Ordner, Logdateien und `.env*`-Dateien.
* **yarn.lock**, **.yarnrc.yml**, **.yarn/**: Fixieren und konfigurieren die vom Projekt verwendete Yarn-4-Toolchain.
* **.nvmrc**: Legt die vom Projekt erwartete Node.js-Version fest.
@@ -115,13 +139,15 @@ Auf hoher Ebene:
Das SDK erkennt Entitäten, indem es Ihre TypeScript-Dateien nach Aufrufen von **`export default define<Entity>({...})`** parst. Für jeden Entitätstyp gibt es eine entsprechende Hilfsfunktion, die aus `twenty-sdk` exportiert wird:
| `defineNavigationMenuItem()` | Definitionen von Navigationsmenüeinträgen |
<Note>
**Dateibenennung ist flexibel.** Die Entitätserkennung ist AST-basiert — das SDK durchsucht Ihre Quelldateien nach dem Muster `export default define<Entity>({...})`. Sie können Ihre Dateien und Ordner nach Belieben organisieren. Die Gruppierung nach Entitätstyp (z. B. `logic-functions/`, `roles/`) ist lediglich eine Konvention zur Codeorganisation, keine Voraussetzung.
Spätere Befehle fügen weitere Dateien und Ordner hinzu:
* `yarn app:generate` erstellt einen `generated/`-Ordner (typisierter Twenty-Client + Workspace-Typen).
* `yarn entity:add` fügt unter `src/` Entitätsdefinitionsdateien für Ihre benutzerdefinierten Objekte, Funktionen, Front-Komponenten oder Rollen hinzu.
* `yarn twenty app:dev` generiert automatisch einen typisierten API-Client in `node_modules/twenty-sdk/generated` (typisierter Twenty-Client + Arbeitsbereichs-Typen).
* `yarn twenty entity:add` fügt unter `src/` Entitätsdefinitionsdateien für benutzerdefinierte Objekte, Funktionen, Frontend-Komponenten oder Rollen hinzu.
## Authentifizierung
Wenn Sie `yarn auth:login` zum ersten Mal ausführen, werden Sie nach Folgendem gefragt:
Wenn Sie `yarn twenty auth:login` zum ersten Mal ausführen, werden Sie nach Folgendem gefragt:
* API-URL (standardmäßig http://localhost:3000 oder Ihr aktuelles Workspace-Profil)
* API-Schlüssel
@@ -158,25 +184,25 @@ Ihre Anmeldedaten werden pro Benutzer in `~/.twenty/config.json` gespeichert. Si
Sobald Sie mit `auth:switch` den Arbeitsbereich gewechselt haben, verwenden alle nachfolgenden Befehle standardmäßig diesen Arbeitsbereich. Sie können es weiterhin vorübergehend mit `--workspace <name>` überschreiben.
Sobald Sie mit `yarn twenty auth:switch` den Arbeitsbereich gewechselt haben, verwenden alle nachfolgenden Befehle standardmäßig diesen Arbeitsbereich. Sie können es weiterhin vorübergehend mit `--workspace <name>` überschreiben.
@@ -186,14 +212,16 @@ Das twenty-sdk stellt typisierte Bausteine und Hilfsfunktionen bereit, die Sie i
Das SDK stellt Hilfsfunktionen bereit, um die Entitäten Ihrer App zu definieren. Wie in [Entitätserkennung](#entity-detection) beschrieben, müssen Sie `export default define<Entity>({...})` verwenden, damit Ihre Entitäten erkannt werden:
Diese Funktionen validieren Ihre Konfiguration zur Build-Zeit und bieten IDE-Autovervollständigung sowie Typsicherheit.
@@ -276,10 +304,14 @@ Hauptpunkte:
* Der `universalIdentifier` muss eindeutig und über Deployments hinweg stabil sein.
* Jedes Feld benötigt `name`, `type`, `label` und einen eigenen stabilen `universalIdentifier`.
* Das Array `fields` ist optional — Sie können Objekte ohne benutzerdefinierte Felder definieren.
* Sie können mit `yarn entity:add` neue Objekte erzeugen; der Assistent führt Sie durch Benennung, Felder und Beziehungen.
* Sie können mit `yarn twenty entity:add` neue Objekte erzeugen; der Assistent führt Sie durch Benennung, Felder und Beziehungen.
<Note>
**Basisfelder werden automatisch erstellt.** Wenn Sie ein benutzerdefiniertes Objekt definieren, fügt Twenty automatisch Standardfelder wie `name`, `createdAt`, `updatedAt`, `createdBy`, `position` und `deletedAt` hinzu. Sie müssen diese nicht in Ihrem `fields`-Array definieren — fügen Sie nur Ihre benutzerdefinierten Felder hinzu.
**Basisfelder werden automatisch erstellt.** Wenn Sie ein benutzerdefiniertes Objekt definieren, fügt Twenty automatisch Standardfelder hinzu
wie `id`, `name`, `createdAt`, `updatedAt`, `createdBy`, `updatedBy` und `deletedAt`.
Sie müssen diese nicht in Ihrem `fields`-Array definieren — fügen Sie nur Ihre benutzerdefinierten Felder hinzu.
Sie können Standardfelder überschreiben, indem Sie in Ihrem `fields`-Array ein Feld mit demselben Namen definieren,
* `universalIdentifier`-Felder sind deterministische IDs, die Sie besitzen; generieren Sie sie einmal und halten Sie sie über Synchronisierungen hinweg stabil.
* `applicationVariables` werden zu Umgebungsvariablen für Ihre Funktionen (zum Beispiel ist `DEFAULT_RECIPIENT_NAME` als `process.env.DEFAULT_RECIPIENT_NAME` verfügbar).
* `defaultRoleUniversalIdentifier` muss mit der Rollendatei übereinstimmen (siehe unten).
* `postInstallLogicFunctionUniversalIdentifier` (optional) verweist auf eine Logikfunktion, die nach der Installation der App automatisch ausgeführt wird. Siehe [Post-Installationsfunktionen](#post-install-functions).
#### Rollen und Berechtigungen
@@ -457,6 +493,55 @@ Notizen:
* Das Array `triggers` ist optional. Funktionen ohne Trigger können als von anderen Funktionen aufgerufene Utility-Funktionen verwendet werden.
* Sie können mehrere Trigger-Typen in einer Funktion kombinieren.
### Post-Installationsfunktionen
Eine Post-Installationsfunktion ist eine Logikfunktion, die automatisch ausgeführt wird, nachdem Ihre App in einem Arbeitsbereich installiert wurde. Dies ist nützlich für einmalige Einrichtungsvorgänge wie das Befüllen mit Standarddaten, das Erstellen erster Datensätze oder das Konfigurieren von Arbeitsbereichseinstellungen.
Wenn du mit `create-twenty-app` eine neue App erstellst, wird für dich eine Post-Installationsfunktion unter `src/logic-functions/post-install.ts` erzeugt:
Du kannst die Post-Installationsfunktion auch jederzeit manuell über die CLI ausführen:
```bash filename="Terminal"
yarn twenty function:execute --postInstall
```
Hauptpunkte:
* Post-Installationsfunktionen sind Standard-Logikfunktionen — sie verwenden `defineLogicFunction()` wie jede andere Funktion.
* Das Feld `postInstallLogicFunctionUniversalIdentifier` in `defineApplication()` ist optional. Wenn es weggelassen wird, wird nach der Installation keine Funktion ausgeführt.
* Das standardmäßige Timeout ist auf 300 Sekunden (5 Minuten) festgelegt, um längere Einrichtungsvorgänge wie Daten-Seeding zu ermöglichen.
* Post-Installationsfunktionen benötigen keine Trigger — sie werden von der Plattform während der Installation oder manuell über `function:execute --postInstall` aufgerufen.
Sie können neue Funktionen auf zwei Arten erstellen:
* **Generiert**: Führen Sie `yarn entity:add` aus und wählen Sie die Option zum Hinzufügen einer neuen Logikfunktion. Dadurch wird eine Starterdatei mit Handler und Konfiguration erzeugt.
* **Generiert**: Führen Sie `yarn twenty entity:add` aus und wählen Sie die Option zum Hinzufügen einer neuen Logikfunktion. Dadurch wird eine Starterdatei mit Handler und Konfiguration erzeugt.
* **Manuell**: Erstellen Sie eine neue `*.logic-function.ts`-Datei und verwenden Sie `defineLogicFunction()` nach demselben Muster.
### Eine Logikfunktion als Tool markieren
Logikfunktionen können als **Tools** für KI-Agenten und Workflows verfügbar gemacht werden. Wenn eine Funktion als Tool markiert ist, wird sie von den KI-Funktionen von Twenty auffindbar und kann als Schritt in Workflow-Automatisierungen ausgewählt werden.
Um eine Logikfunktion als Tool zu markieren, setzen Sie `isTool: true` und geben Sie ein `toolInputSchema` an, das die erwarteten Eingabeparameter mithilfe von [JSON Schema](https://json-schema.org/) beschreibt:
description: 'Enrich a company record with external data',
timeoutSeconds: 10,
handler,
isTool: true,
toolInputSchema: {
type: 'object',
properties: {
companyName: {
type: 'string',
description: 'The name of the company to enrich',
},
domain: {
type: 'string',
description: 'The company website domain (optional)',
},
},
required: ['companyName'],
},
});
```
Hauptpunkte:
* **`isTool`** (`boolean`, Standard: `false`): Wenn auf `true` gesetzt, wird die Funktion als Tool registriert und steht KI-Agenten und Workflow-Automatisierungen zur Verfügung.
* **`toolInputSchema`** (`object`, optional): Ein JSON-Schema-Objekt, das die Parameter beschreibt, die Ihre Funktion akzeptiert. KI-Agenten verwenden dieses Schema, um zu verstehen, welche Eingaben das Tool erwartet, und um Aufrufe zu validieren. Falls weggelassen, lautet der Standardwert für das Schema `{ type: 'object', properties: {} }` (keine Parameter).
* Funktionen mit `isTool: false` (oder nicht gesetzt) werden **nicht** als Tools bereitgestellt. Sie können weiterhin direkt ausgeführt oder von anderen Funktionen aufgerufen werden, erscheinen jedoch nicht in der Tool-Erkennung.
* **Tool-Benennung**: Wenn als Tool bereitgestellt, wird der Funktionsname automatisch zu `logic_function_<name>` normalisiert (in Kleinbuchstaben umgewandelt, nicht alphanumerische Zeichen durch Unterstriche ersetzt). Beispielsweise wird `enrich-company` zu `logic_function_enrich_company`.
* Sie können `isTool` mit Triggern kombinieren — eine Funktion kann gleichzeitig sowohl ein Tool (von KI-Agenten aufrufbar) als auch durch Ereignisse (Cron, Datenbankereignisse, Routen) ausgelöst werden.
<Note>
**Schreiben Sie eine gute `description`.** KI-Agenten verlassen sich auf das `description`-Feld der Funktion, um zu entscheiden, wann das Tool verwendet werden soll. Seien Sie konkret darin, was das Tool tut und wann es aufgerufen werden soll.
</Note>
### Frontend-Komponenten
Frontend-Komponenten ermöglichen es Ihnen, benutzerdefinierte React-Komponenten zu erstellen, die innerhalb der Twenty-UI gerendert werden. Verwenden Sie `defineFrontComponent()`, um Komponenten mit eingebauter Validierung zu definieren:
@@ -584,16 +734,16 @@ Hauptpunkte:
* Frontend-Komponenten sind React-Komponenten, die in isolierten Kontexten innerhalb von Twenty gerendert werden.
* Verwenden Sie die Dateiendung `*.front-component.tsx` für die automatische Erkennung.
* Das Feld `component` verweist auf Ihre React-Komponente.
* Komponenten werden während `yarn app:dev` automatisch gebaut und synchronisiert.
* Komponenten werden während `yarn twenty app:dev` automatisch gebaut und synchronisiert.
Sie können neue Frontend-Komponenten auf zwei Arten erstellen:
* **Generiert**: Führen Sie `yarn entity:add` aus und wählen Sie die Option zum Hinzufügen einer neuen Frontend-Komponente.
* **Generiert**: Führen Sie `yarn twenty entity:add` aus und wählen Sie die Option zum Hinzufügen einer neuen Frontend-Komponente.
* **Manuell**: Erstellen Sie eine neue `*.front-component.tsx`-Datei und verwenden Sie `defineFrontComponent()`.
### Generierter typisierter Client
Führen Sie yarn app:generate aus, um einen lokalen typisierten Client in generated/ basierend auf Ihrem Workspace-Schema zu erstellen. Verwenden Sie ihn in Ihren Funktionen:
Der typisierte Client wird von `yarn twenty app:dev` automatisch generiert und basierend auf Ihrem Arbeitsbereichs-Schema in `node_modules/twenty-sdk/generated` gespeichert. Verwenden Sie ihn in Ihren Funktionen:
Der Client wird durch `yarn app:generate` erneut generiert. Führen Sie ihn nach Änderungen an Ihren Objekten oder beim Onboarding in einen neuen Workspace erneut aus.
Der Client wird von `yarn twenty app:dev` automatisch neu generiert, sobald sich Ihre Objekte oder Felder ändern.
#### Laufzeit-Anmeldedaten in Logikfunktionen
@@ -623,40 +773,29 @@ Ein minimales End-to-End-Beispiel, das Objekte, Logikfunktionen, Frontend-Kompon
## Manuelle Einrichtung (ohne Scaffolder)
Wir empfehlen zwar `create-twenty-app` für das beste Einstiegserlebnis, Sie können ein Projekt aber auch manuell einrichten. Installieren Sie die CLI nicht global. Fügen Sie stattdessen `twenty-sdk` als lokale Abhängigkeit hinzu und binden Sie Skripte in Ihrer package.json ein:
Wir empfehlen zwar `create-twenty-app` für das beste Einstiegserlebnis, Sie können ein Projekt aber auch manuell einrichten. Installieren Sie die CLI nicht global. Fügen Sie stattdessen `twenty-sdk` als lokale Abhängigkeit hinzu und binden Sie ein einzelnes Skript in Ihrer package.json ein:
```bash filename="Terminal"
yarn add -D twenty-sdk
```
Fügen Sie dann Skripte wie diese hinzu:
Fügen Sie dann ein `twenty`-Skript hinzu:
```json filename="package.json"
{
"scripts": {
"auth:login": "twenty auth:login",
"auth:logout": "twenty auth:logout",
"auth:status": "twenty auth:status",
"auth:switch": "twenty auth:switch",
"auth:list": "twenty auth:list",
"app:dev": "twenty app:dev",
"app:generate": "twenty app:generate",
"app:uninstall": "twenty app:uninstall",
"entity:add": "twenty entity:add",
"function:logs": "twenty function:logs",
"function:execute": "twenty function:execute",
"help": "twenty help"
"twenty": "twenty"
}
}
```
Jetzt können Sie dieselben Befehle über Yarn ausführen, z. B. `yarn app:dev`, `yarn app:generate` usw.
Jetzt können Sie alle Befehle über `yarn twenty <command>` ausführen, z. B. `yarn twenty app:dev`, `yarn twenty help` usw.
## Fehlerbehebung
* Authentifizierungsfehler: Führen Sie `yarn auth:login` aus und stellen Sie sicher, dass Ihr API-Schlüssel die erforderlichen Berechtigungen hat.
* Authentifizierungsfehler: Führen Sie `yarn twenty auth:login` aus und stellen Sie sicher, dass Ihr API-Schlüssel die erforderlichen Berechtigungen hat.
* Verbindung zum Server nicht möglich: Überprüfen Sie die API-URL und dass der Twenty-Server erreichbar ist.
* Typen oder Client fehlen/veraltet: Führen Sie `yarn app:generate` aus.
* Dev-Modus synchronisiert nicht: Stellen Sie sicher, dass `yarn app:dev` läuft und dass Änderungen von Ihrer Umgebung nicht ignoriert werden.
* Typen oder Client fehlen/veraltet: Starten Sie `yarn twenty app:dev` neu — der typisierte Client wird automatisch generiert.
* Dev-Modus synchronisiert nicht: Stellen Sie sicher, dass `yarn twenty app:dev` läuft und dass Änderungen von Ihrer Umgebung nicht ignoriert werden.
# Añade una nueva entidad a tu aplicación (guiado)
yarn entity:add
# Genera un cliente tipado de Twenty y tipos de entidad del espacio de trabajo
yarn app:generate
# Supervisa los registros de funciones de tu aplicación
yarn function:logs
@@ -157,7 +154,7 @@ src/
A grandes rasgos:
* **package.json**: Declara el nombre de la aplicación, la versión, los entornos (Node 24+, Yarn 4) y agrega `twenty-sdk` además de scripts como `app:dev`, `app:generate`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall` y `auth:login` que delegan en la CLI local `twenty`.
* **package.json**: Declara el nombre de la aplicación, la versión, los entornos (Node 24+, Yarn 4) y agrega `twenty-sdk` además de scripts como `app:dev`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall` y `auth:login` que delegan en la CLI local `twenty`.
* **.gitignore**: Ignora artefactos comunes como `node_modules`, `.yarn`, `generated/` (cliente tipado), `dist/`, `build/`, carpetas de cobertura, archivos de registro y archivos `.env*`.
* **yarn.lock**, **.yarnrc.yml**, **.yarn/**: Bloquean y configuran la cadena de herramientas Yarn 4 utilizada por el proyecto.
* **.nvmrc**: Fija la versión de Node.js esperada por el proyecto.
@@ -173,7 +170,7 @@ A grandes rasgos:
Comandos posteriores añadirán más archivos y carpetas:
* `yarn app:generate` creará una carpeta `generated/` (cliente tipado de Twenty + tipos del espacio de trabajo).
* `yarn app:dev` genera automáticamente el cliente Twenty tipado en `node_modules/twenty-sdk/generated`.
* `yarn entity:add` añadirá archivos de definición de entidades en `src/` para tus objetos, funciones, componentes de interfaz o roles personalizados.
## Autenticación
@@ -585,7 +582,7 @@ Puedes crear funciones nuevas de dos maneras:
### Cliente tipado generado
Ejecuta yarn app:generate para crear un cliente tipado local en generated/ basado en el esquema de tu espacio de trabajo. Úsalo en tus funciones:
`yarn app:dev` genera automáticamente el cliente Twenty tipado en `node_modules/twenty-sdk/generated`. Úsalo en tus funciones:
El cliente se vuelve a generar con `yarn app:generate`. Vuelve a ejecutarlo después de cambiar tus objetos o al incorporarte a un nuevo espacio de trabajo.
El cliente se regenera automáticamente durante la ejecución de `app:dev`. Reinicia `app:dev` después de cambiar tus objetos o al incorporarte a un nuevo espacio de trabajo.
#### Credenciales en tiempo de ejecución en funciones de lógica
@@ -632,7 +629,6 @@ Luego agrega scripts como estos:
"auth:switch": "twenty auth:switch",
"auth:list": "twenty auth:list",
"app:dev": "twenty app:dev",
"app:generate": "twenty app:generate",
"app:uninstall": "twenty app:uninstall",
"entity:add": "twenty entity:add",
"function:logs": "twenty function:logs",
@@ -642,13 +638,13 @@ Luego agrega scripts como estos:
}
```
Ahora puedes ejecutar los mismos comandos mediante Yarn, p. ej., `yarn app:dev`, `yarn app:generate`, etc.
Ahora puedes ejecutar los mismos comandos mediante Yarn, p. ej., `yarn app:dev`, etc.
## Solución de problemas
* Errores de autenticación: ejecuta `yarn auth:login` y asegúrate de que tu clave de API tenga los permisos necesarios.
* No se puede conectar al servidor: verifica la URL de la API y que el servidor de Twenty sea accesible.
* Tipos o cliente faltantes/obsoletos: ejecuta `yarn app:generate`.
* Tipos o cliente faltantes/obsoletos: reinicia `yarn app:dev`.
* El modo de desarrollo no sincroniza: asegúrate de que `yarn app:dev` esté ejecutándose y de que los cambios no sean ignorados por tu entorno.
Canal de ayuda en Discord: https://discord.com/channels/1130383047699738754/1130386664812982322
# Ajouter une nouvelle entité à votre application (assisté)
yarn entity:add
# Générer un client Twenty typé et les types d'entité de l'espace de travail
yarn app:generate
# Surveiller les journaux des fonctions de votre application
yarn function:logs
@@ -157,7 +154,7 @@ src/
Dans les grandes lignes :
* **package.json** : Déclare le nom de l’application, la version, les moteurs (Node 24+, Yarn 4), et ajoute `twenty-sdk` ainsi que des scripts comme `app:dev`, `app:generate`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall` et `auth:login` qui délèguent à la CLI locale `twenty`.
* **package.json** : Déclare le nom de l’application, la version, les moteurs (Node 24+, Yarn 4), et ajoute `twenty-sdk` ainsi que des scripts comme `app:dev`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall` et `auth:login` qui délèguent à la CLI locale `twenty`.
* **.gitignore** : Ignore les artefacts courants tels que `node_modules`, `.yarn`, `generated/` (client typé), `dist/`, `build/`, les dossiers de couverture, les fichiers journaux et les fichiers `.env*`.
* **yarn.lock**, **.yarnrc.yml**, **.yarn/** : Verrouillent et configurent la chaîne d’outils Yarn 4 utilisée par le projet.
* **.nvmrc** : Fige la version de Node.js attendue par le projet.
@@ -173,7 +170,7 @@ Dans les grandes lignes :
Des commandes ultérieures ajouteront d’autres fichiers et dossiers :
* `yarn app:generate` créera un dossier `generated/` (client Twenty typé + types de l’espace de travail).
* `yarn app:dev` génère automatiquement le client Twenty typé dans `node_modules/twenty-sdk/generated`.
* `yarn entity:add` ajoutera des fichiers de définition d’entité sous `src/` pour vos objets, fonctions, composants front-end ou rôles personnalisés.
## Authentification
@@ -585,7 +582,7 @@ Vous pouvez créer de nouvelles fonctions de deux façons :
### Client typé généré
Exécutez yarn app:generate pour créer un client typé local dans generated/ basé sur le schéma de votre espace de travail. Utilisez-le dans vos fonctions :
`yarn app:dev` génère automatiquement le client Twenty typé dans `node_modules/twenty-sdk/generated`. Utilisez-le dans vos fonctions :
Le client est régénéré par `yarn app:generate`. Relancez après avoir modifié vos objets ou lors de l’intégration à un nouvel espace de travail.
Le client est régénéré automatiquement pendant l'exécution de `app:dev`. Redémarrez `app:dev` après avoir modifié vos objets ou lors de l’intégration à un nouvel espace de travail.
#### Identifiants d’exécution dans les fonctions logiques
@@ -632,7 +629,6 @@ Ajoutez ensuite des scripts comme ceux-ci :
"auth:switch": "twenty auth:switch",
"auth:list": "twenty auth:list",
"app:dev": "twenty app:dev",
"app:generate": "twenty app:generate",
"app:uninstall": "twenty app:uninstall",
"entity:add": "twenty entity:add",
"function:logs": "twenty function:logs",
@@ -642,13 +638,13 @@ Ajoutez ensuite des scripts comme ceux-ci :
}
```
Vous pouvez désormais exécuter les mêmes commandes via Yarn, par exemple `yarn app:dev`, `yarn app:generate`, etc.
Vous pouvez désormais exécuter les mêmes commandes via Yarn, par exemple `yarn app:dev`, etc.
## Résolution des problèmes
* Erreurs d’authentification : exécutez `yarn auth:login` et assurez-vous que votre clé API dispose des autorisations requises.
* Impossible de se connecter au serveur : vérifiez l’URL de l’API et que le serveur Twenty est accessible.
* Types ou client manquants/obsolètes : exécutez `yarn app:generate`.
* Types ou client manquants/obsolètes : redémarrez `yarn app:dev`.
* Le mode dev ne se synchronise pas : assurez-vous que `yarn app:dev` est en cours d’exécution et que les modifications ne sont pas ignorées par votre environnement.
# Disinstalla l'applicazione dallo spazio di lavoro corrente
yarn app:uninstall
yarn twenty app:uninstall
# Mostra l'aiuto dei comandi
yarn help
yarn twenty help
```
Vedi anche: le pagine di riferimento della CLI per [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) e [twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk).
@@ -73,9 +86,9 @@ Quando esegui `npx create-twenty-app@latest my-twenty-app`, lo scaffolder:
* Copia un'applicazione base minimale in `my-twenty-app/`
* Aggiunge una dipendenza locale `twenty-sdk` e la configurazione di Yarn 4
* Crea file di configurazione e script collegati alla CLI `twenty`
* Genera una configurazione applicativa predefinita e un ruolo funzione predefinito
* Genera i file principali (configurazione dell'applicazione, ruolo predefinito per le funzioni logiche, funzione di post-installazione) più i file di esempio in base alla modalità di scaffolding
Un'app appena generata dallo scaffolder si presenta così:
Un'app appena creata con la modalità predefinita `--exhaustive` si presenta così:
```text filename="my-twenty-app/"
my-twenty-app/
@@ -94,15 +107,26 @@ my-twenty-app/
├── application-config.ts # Obbligatorio - configurazione principale dell'applicazione
├── roles/
│ └── default-role.ts # Ruolo predefinito per le funzioni logiche
├── objects/
│ └── example-object.ts # Definizione di oggetto personalizzato di esempio
├── fields/
│ └── example-field.ts # Definizione di campo autonomo di esempio
├── logic-functions/
│ └── hello-world.ts # Funzione logica di esempio
└── front-components/
└── hello-world.tsx # Componente front-end di esempio
│ ├── hello-world.ts # Funzione logica di esempio
│ └── post-install.ts # Funzione logica post-installazione
├── front-components/
│ └── hello-world.tsx # Componente front-end di esempio
├── views/
│ └── example-view.ts # Definizione di vista salvata di esempio
└── navigation-menu-items/
└── example-navigation-menu-item.ts # Link di navigazione della barra laterale di esempio
```
Con `--minimal`, vengono creati solo i file principali (`application-config.ts`, `roles/default-role.ts` e `logic-functions/post-install.ts`). Con `--interactive`, scegli quali file di esempio includere.
A livello generale:
* **package.json**: Dichiara il nome dell'app, la versione, i motori (Node 24+, Yarn 4) e aggiunge `twenty-sdk`, oltre a script come `app:dev`, `app:generate`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall` e comandi di autenticazione che delegano alla CLI locale `twenty`.
* **package.json**: Dichiara il nome dell'app, la versione, i motori (Node 24+, Yarn 4) e aggiunge `twenty-sdk` più uno script `twenty` che delega alla CLI locale `twenty`. Esegui `yarn twenty help` per elencare tutti i comandi disponibili.
* **.gitignore**: Ignora i file generati comuni come `node_modules`, `.yarn`, `generated/` (client tipizzato), `dist/`, `build/`, cartelle di coverage, file di log e file `.env*`.
* **yarn.lock**, **.yarnrc.yml**, **.yarn/**: Bloccano e configurano la toolchain Yarn 4 utilizzata dal progetto.
* **.nvmrc**: Fissa la versione di Node.js prevista dal progetto.
@@ -115,13 +139,15 @@ A livello generale:
L'SDK rileva le entità analizzando i tuoi file TypeScript alla ricerca di chiamate **`export default define<Entity>({...})`**. Ogni tipo di entità ha una corrispondente funzione helper esportata da `twenty-sdk`:
| `defineObject()` | Definizioni di oggetti personalizzati |
| `defineLogicFunction()` | Definizioni di funzioni logiche |
| `defineFrontComponent()` | Definizioni dei componenti front-end |
| `defineRole()` | Definizioni di ruoli |
| `defineField()` | Estensioni di campo per oggetti esistenti |
| `defineView()` | Definizioni di viste salvate |
| `defineNavigationMenuItem()` | Definizioni delle voci del menu di navigazione |
<Note>
**La denominazione dei file è flessibile.** Il rilevamento delle entità è basato sull'AST — l'SDK esegue la scansione dei file sorgente alla ricerca del pattern `export default define<Entity>({...})`. Puoi organizzare file e cartelle come preferisci. Raggruppare per tipo di entità (ad es., `logic-functions/`, `roles/`) è solo una convenzione per l'organizzazione del codice, non un requisito.
Comandi successivi aggiungeranno altri file e cartelle:
* `yarn app:generate` creerà una cartella `generated/` (client Twenty tipizzato + tipi dello spazio di lavoro).
* `yarn entity:add` aggiungerà file di definizione delle entità sotto `src/` per i tuoi oggetti, funzioni, componenti front-end o ruoli personalizzati.
* `yarn twenty app:dev` genererà automaticamente un client API tipizzato in `node_modules/twenty-sdk/generated` (client Twenty tipizzato + tipi dell'area di lavoro).
* `yarn twenty entity:add` aggiungerà file di definizione delle entità sotto `src/` per i tuoi oggetti, funzioni, componenti front-end o ruoli personalizzati.
## Autenticazione
La prima volta che esegui `yarn auth:login`, ti verranno richiesti:
La prima volta che esegui `yarn twenty auth:login`, ti verranno richiesti:
* URL dell'API (predefinito a http://localhost:3000 o al profilo dello spazio di lavoro corrente)
* Chiave API
@@ -158,25 +184,25 @@ Le tue credenziali sono archiviate per utente in `~/.twenty/config.json`. Puoi m
Una volta che hai cambiato area di lavoro con `auth:switch`, tutti i comandi successivi utilizzeranno quell'area di lavoro per impostazione predefinita. Puoi comunque sovrascriverla temporaneamente con `--workspace <name>`.
Una volta che hai cambiato area di lavoro con `yarn twenty auth:switch`, tutti i comandi successivi utilizzeranno quell'area di lavoro per impostazione predefinita. Puoi comunque sovrascriverla temporaneamente con `--workspace <name>`.
## Usa le risorse dell'SDK (tipi e configurazione)
@@ -186,14 +212,16 @@ Il pacchetto twenty-sdk fornisce blocchi tipizzati e funzioni helper da usare ne
L'SDK fornisce funzioni helper per definire le entità della tua app. Come descritto in [Rilevamento delle entità](#entity-detection), devi usare `export default define<Entity>({...})` affinché le tue entità vengano rilevate:
| `defineRole()` | Configura i permessi dei ruoli e l'accesso agli oggetti |
| `defineField()` | Estendi gli oggetti esistenti con campi aggiuntivi |
| `defineView()` | Definisce viste salvate per gli oggetti |
| `defineNavigationMenuItem()` | Definisce i link di navigazione della barra laterale |
Queste funzioni convalidano la configurazione in fase di build e offrono il completamento automatico nell'IDE e la sicurezza dei tipi.
@@ -276,10 +304,14 @@ Punti chiave:
* Il `universalIdentifier` deve essere univoco e stabile tra i deployment.
* Ogni campo richiede un `name`, `type`, `label` e il proprio `universalIdentifier` stabile.
* L'array `fields` è facoltativo: puoi definire oggetti senza campi personalizzati.
* Puoi generare nuovi oggetti con `yarn entity:add`, che ti guida nella denominazione, nei campi e nelle relazioni.
* Puoi generare nuovi oggetti con `yarn twenty entity:add`, che ti guida nella denominazione, nei campi e nelle relazioni.
<Note>
**I campi base vengono creati automaticamente.** Quando definisci un oggetto personalizzato, Twenty aggiunge automaticamente i campi standard come `name`, `createdAt`, `updatedAt`, `createdBy`, `position` e `deletedAt`. Non è necessario definirli nel tuo array `fields` — aggiungi solo i tuoi campi personalizzati.
**I campi base vengono creati automaticamente.** Quando definisci un oggetto personalizzato, Twenty aggiunge automaticamente i campi standard
come `id`, `name`, `createdAt`, `updatedAt`, `createdBy`, `updatedBy` e `deletedAt`.
Non è necessario definirli nel tuo array `fields` — aggiungi solo i tuoi campi personalizzati.
Puoi sovrascrivere i campi predefiniti definendo un campo con lo stesso nome nel tuo array `fields`,
* I campi `universalIdentifier` sono ID deterministici sotto il tuo controllo; generali una volta e mantienili stabili tra le sincronizzazioni.
* `applicationVariables` diventano variabili d'ambiente per le tue funzioni (ad esempio, `DEFAULT_RECIPIENT_NAME` è disponibile come `process.env.DEFAULT_RECIPIENT_NAME`).
* `defaultRoleUniversalIdentifier` deve corrispondere al file del ruolo (vedi sotto).
* `postInstallLogicFunctionUniversalIdentifier` (opzionale) fa riferimento a una funzione logica che viene eseguita automaticamente dopo l'installazione dell'app. Vedi [Funzioni post-installazione](#post-install-functions).
#### Ruoli e permessi
@@ -457,6 +493,55 @@ Note:
* L'array `triggers` è facoltativo. Le funzioni senza trigger possono essere utilizzate come funzioni di utilità richiamate da altre funzioni.
* Puoi combinare più tipi di trigger in un'unica funzione.
### Funzioni post-installazione
Una funzione post-installazione è una funzione logica che viene eseguita automaticamente dopo che la tua app è stata installata in uno spazio di lavoro. Questo è utile per attività di configurazione una tantum come il popolamento di dati predefiniti, la creazione di record iniziali o la configurazione delle impostazioni dello spazio di lavoro.
Quando esegui lo scaffolding di una nuova app con `create-twenty-app`, viene generata automaticamente una funzione di post-installazione in `src/logic-functions/post-install.ts`:
Puoi anche eseguire manualmente la funzione di post-installazione in qualsiasi momento utilizzando la CLI:
```bash filename="Terminal"
yarn twenty function:execute --postInstall
```
Punti chiave:
* Le funzioni di post-installazione sono funzioni logiche standard — usano `defineLogicFunction()` come qualsiasi altra funzione.
* Il campo `postInstallLogicFunctionUniversalIdentifier` in `defineApplication()` è facoltativo. Se omesso, nessuna funzione viene eseguita dopo l'installazione.
* Il timeout predefinito è impostato a 300 secondi (5 minuti) per consentire attività di configurazione più lunghe, come il popolamento dei dati.
* Le funzioni di post-installazione non necessitano di trigger — vengono invocate dalla piattaforma durante l'installazione o manualmente tramite `function:execute --postInstall`.
* **Generata dallo scaffolder**: Esegui `yarn entity:add` e scegli l'opzione per aggiungere una nuova funzione logica. Questo genera un file iniziale con un handler e una configurazione.
* **Generata dallo scaffolder**: Esegui `yarn twenty entity:add` e scegli l'opzione per aggiungere una nuova funzione logica. Questo genera un file iniziale con un handler e una configurazione.
* **Manuale**: Crea un nuovo file `*.logic-function.ts` e usa `defineLogicFunction()`, seguendo lo stesso schema.
### Contrassegnare una funzione logica come strumento
Le funzioni logiche possono essere esposte come **strumenti** per gli agenti di IA e i flussi di lavoro. Quando una funzione è contrassegnata come strumento, diventa individuabile dalle funzionalità di IA di Twenty e può essere selezionata come passaggio nelle automazioni dei flussi di lavoro.
Per contrassegnare una funzione logica come strumento, imposta `isTool: true` e fornisci un `toolInputSchema` che descriva i parametri di input attesi utilizzando [JSON Schema](https://json-schema.org/):
description: 'Enrich a company record with external data',
timeoutSeconds: 10,
handler,
isTool: true,
toolInputSchema: {
type: 'object',
properties: {
companyName: {
type: 'string',
description: 'The name of the company to enrich',
},
domain: {
type: 'string',
description: 'The company website domain (optional)',
},
},
required: ['companyName'],
},
});
```
Punti chiave:
* **`isTool`** (`boolean`, predefinito: `false`): Quando impostato su `true`, la funzione viene registrata come strumento e diventa disponibile per gli agenti IA e le automazioni dei flussi di lavoro.
* **`toolInputSchema`** (`object`, opzionale): Un oggetto JSON Schema che descrive i parametri accettati dalla funzione. Gli agenti IA utilizzano questo schema per capire quali input si aspetta lo strumento e per convalidare le chiamate. Se omesso, lo schema assume il valore predefinito `{ type: 'object', properties: {} }` (nessun parametro).
* Le funzioni con `isTool: false` (o non impostato) **non** vengono esposte come strumenti. Possono comunque essere eseguite direttamente o chiamate da altre funzioni, ma non compariranno nell'individuazione degli strumenti.
* **Denominazione dello strumento**: Quando esposta come strumento, il nome della funzione viene normalizzato automaticamente in `logic_function_<name>` (in minuscolo, i caratteri non alfanumerici vengono sostituiti da trattini bassi). Ad esempio, `enrich-company` diventa `logic_function_enrich_company`.
* È possibile combinare `isTool` con i trigger — una funzione può essere sia uno strumento (invocabile dagli agenti IA) sia attivata da eventi (cron, eventi del database, routes) contemporaneamente.
<Note>
**Scrivi una buona `description`.** Gli agenti IA fanno affidamento sul campo `description` della funzione per decidere quando usare lo strumento. Sii specifico su cosa fa lo strumento e quando dovrebbe essere invocato.
</Note>
### Componenti front-end
I componenti front-end ti consentono di creare componenti React personalizzati che vengono renderizzati all'interno dell'interfaccia di Twenty. Usa `defineFrontComponent()` per definire componenti con convalida integrata:
@@ -584,16 +734,16 @@ Punti chiave:
* I componenti front-end sono componenti React che eseguono il rendering in contesti isolati all'interno di Twenty.
* Usa il suffisso di file `*.front-component.tsx` per il rilevamento automatico.
* Il campo `component` fa riferimento al tuo componente React.
* I componenti vengono compilati e sincronizzati automaticamente durante `yarn app:dev`.
* I componenti vengono compilati e sincronizzati automaticamente durante `yarn twenty app:dev`.
Puoi creare nuovi componenti front-end in due modi:
* **Generata dallo scaffolder**: Esegui `yarn entity:add` e scegli l'opzione per aggiungere un nuovo componente front-end.
* **Generata dallo scaffolder**: Esegui `yarn twenty entity:add` e scegli l'opzione per aggiungere un nuovo componente front-end.
* **Manuale**: Crea un nuovo file `*.front-component.tsx` e usa `defineFrontComponent()`.
### Client tipizzato generato
Esegui yarn app:generate per creare un client tipizzato locale in generated/ basato sullo schema del tuo spazio di lavoro. Usalo nelle tue funzioni:
Il client tipizzato è generato automaticamente da `yarn twenty app:dev` e salvato in `node_modules/twenty-sdk/generated` in base allo schema della tua area di lavoro. Usalo nelle tue funzioni:
Il client viene rigenerato da `yarn app:generate`. Eseguilo nuovamente dopo aver modificato i tuoi oggetti oppure quando effettui l'onboarding su un nuovo spazio di lavoro.
Il client viene rigenerato automaticamente da `yarn twenty app:dev` ogni volta che i tuoi oggetti o campi cambiano.
#### Credenziali di runtime nelle funzioni logiche
@@ -623,40 +773,29 @@ Esplora un esempio minimale end-to-end che dimostra oggetti, funzioni logiche, c
## Configurazione manuale (senza lo scaffolder)
Sebbene consigliamo di utilizzare `create-twenty-app` per la migliore esperienza iniziale, puoi anche configurare un progetto manualmente. Non installare la CLI globalmente. Invece, aggiungi `twenty-sdk` come dipendenza locale e collega gli script nel tuo package.json:
Sebbene consigliamo di utilizzare `create-twenty-app` per la migliore esperienza iniziale, puoi anche configurare un progetto manualmente. Non installare la CLI globalmente. Invece, aggiungi `twenty-sdk` come dipendenza locale e collega un unico script nel tuo package.json:
```bash filename="Terminal"
yarn add -D twenty-sdk
```
Quindi aggiungi script come questi:
Quindi aggiungi uno script `twenty`:
```json filename="package.json"
{
"scripts": {
"auth:login": "twenty auth:login",
"auth:logout": "twenty auth:logout",
"auth:status": "twenty auth:status",
"auth:switch": "twenty auth:switch",
"auth:list": "twenty auth:list",
"app:dev": "twenty app:dev",
"app:generate": "twenty app:generate",
"app:uninstall": "twenty app:uninstall",
"entity:add": "twenty entity:add",
"function:logs": "twenty function:logs",
"function:execute": "twenty function:execute",
"help": "twenty help"
"twenty": "twenty"
}
}
```
Ora puoi eseguire gli stessi comandi tramite Yarn, ad esempio `yarn app:dev`, `yarn app:generate`, ecc.
Ora puoi eseguire tutti i comandi tramite `yarn twenty <command>`, ad es. `yarn twenty app:dev`, `yarn twenty help`, ecc.
## Risoluzione dei problemi
* Errori di autenticazione: esegui `yarn auth:login` e assicurati che la tua chiave API abbia i permessi richiesti.
* Errori di autenticazione: esegui `yarn twenty auth:login` e assicurati che la tua chiave API abbia i permessi richiesti.
* Impossibile connettersi al server: verifica l'URL dell'API e che il server Twenty sia raggiungibile.
* Tipi o client mancanti/obsoleti: esegui `yarn app:generate`.
* Modalità di sviluppo non in sincronizzazione: assicurati che `yarn app:dev` sia in esecuzione e che le modifiche non vengano ignorate dal tuo ambiente.
* Types or client missing/outdated: restart `yarn twenty app:dev` — it auto-generates the typed client.
* Modalità di sviluppo non sincronizzata: assicurati che `yarn twenty app:dev` sia in esecuzione e che le modifiche non vengano ignorate dal tuo ambiente.
Canale di supporto su Discord: https://discord.com/channels/1130383047699738754/1130386664812982322
* **package.json**: Declares the app name, version, engines (Node 24+, Yarn 4), and adds `twenty-sdk` plus scripts like `app:dev`, `app:generate`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall`, and `auth:login` that delegate to the local `twenty` CLI.
* **package.json**: Declares the app name, version, engines (Node 24+, Yarn 4), and adds `twenty-sdk` plus scripts like `app:dev`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall`, and `auth:login` that delegate to the local `twenty` CLI.
# Desinstalar a aplicação do espaço de trabalho atual
yarn app:uninstall
yarn twenty app:uninstall
# Exibir a ajuda dos comandos
yarn help
yarn twenty help
```
Veja também: as páginas de referência da CLI para [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) e [twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk).
@@ -73,9 +86,9 @@ Ao executar `npx create-twenty-app@latest my-twenty-app`, o gerador:
* Copia um aplicativo base mínimo para `my-twenty-app/`
* Adiciona uma dependência local `twenty-sdk` e a configuração do Yarn 4
* Cria arquivos de configuração e scripts conectados à CLI `twenty`
* Gera uma configuração de aplicativo padrão e um papel padrão para as funções
* Gera arquivos principais (configuração da aplicação, papel padrão para funções de lógica, função de pós-instalação) além de arquivos de exemplo com base no modo de geração de estrutura
Um aplicativo recém-criado pelo scaffold fica assim:
Um app recém-criado com o modo padrão `--exhaustive` fica assim:
```text filename="my-twenty-app/"
my-twenty-app/
@@ -94,15 +107,26 @@ my-twenty-app/
├── application-config.ts # Obrigatório - configuração principal da aplicação
├── roles/
│ └── default-role.ts # Papel padrão para funções de lógica
├── objects/
│ └── example-object.ts # Exemplo de definição de objeto personalizado
├── fields/
│ └── example-field.ts # Exemplo de definição de campo independente
├── logic-functions/
│ └── hello-world.ts # Exemplo de função de lógica
└── front-components/
└── hello-world.tsx # Exemplo de componente de front-end
│ ├── hello-world.ts # Exemplo de função de lógica
│ └── post-install.ts # Função de lógica de pós-instalação
├── front-components/
│ └── hello-world.tsx # Exemplo de componente de front-end
├── views/
│ └── example-view.ts # Exemplo de definição de visualização salva
└── navigation-menu-items/
└── example-navigation-menu-item.ts # Exemplo de link de navegação da barra lateral
```
Com `--minimal`, apenas os arquivos principais são criados (`application-config.ts`, `roles/default-role.ts` e `logic-functions/post-install.ts`). Com `--interactive`, você escolhe quais arquivos de exemplo incluir.
Em alto nível:
* **package.json**: Declara o nome do app, versão, engines (Node 24+, Yarn 4) e adiciona `twenty-sdk`, além de scripts como `app:dev`, `app:generate`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall` e comandos de autenticação que delegam para a CLI local `twenty`.
* **package.json**: Declara o nome do app, versão, engines (Node 24+, Yarn 4), e adiciona `twenty-sdk` além de um script `twenty` que delega para a CLI `twenty` local. Execute `yarn twenty help` para listar todos os comandos disponíveis.
* **.gitignore**: Ignora artefatos comuns como `node_modules`, `.yarn`, `generated/` (cliente tipado), `dist/`, `build/`, pastas de cobertura, arquivos de log e arquivos `.env*`.
* **yarn.lock**, **.yarnrc.yml**, **.yarn/**: Bloqueiam e configuram a ferramenta Yarn 4 usada pelo projeto.
* **.nvmrc**: Fixa a versão do Node.js esperada pelo projeto.
@@ -115,13 +139,15 @@ Em alto nível:
O SDK detecta entidades analisando seus arquivos TypeScript em busca de chamadas **`export default define<Entity>({...})`**. Cada tipo de entidade tem uma função utilitária correspondente exportada de `twenty-sdk`:
| `defineObject()` | Definições de objetos personalizados |
| `defineLogicFunction()` | Definições de funções de lógica |
| `defineFrontComponent()` | Definições de componentes de front-end |
| `defineRole()` | Definições de papéis |
| `defineField()` | Extensões de campos para objetos existentes |
| `defineView()` | Definições de visualizações salvas |
| `defineNavigationMenuItem()` | Definições de itens do menu de navegação |
<Note>
**A nomeação de arquivos é flexível.** A detecção de entidades é baseada em AST — o SDK varre seus arquivos fonte em busca do padrão `export default define<Entity>({...})`. Você pode organizar seus arquivos e pastas como quiser. Agrupar por tipo de entidade (por exemplo, `logic-functions/`, `roles/`) é apenas uma convenção para organização do código, não um requisito.
Comandos posteriores adicionarão mais arquivos e pastas:
* `yarn app:generate` criará uma pasta `generated/` (cliente tipado do Twenty + tipos do workspace).
* `yarn entity:add` adicionará arquivos de definição de entidade em `src/` para seus objetos, funções, componentes de front-end ou papéis personalizados.
* `yarn twenty app:dev` vai gerar automaticamente um cliente de API tipado em `node_modules/twenty-sdk/generated` (cliente Twenty tipado + tipos do espaço de trabalho).
* `yarn twenty entity:add` adicionará arquivos de definição de entidade em `src/` para seus objetos, funções, componentes de front-end ou papéis personalizados.
## Autenticação
Na primeira vez que você executar `yarn auth:login`, será solicitado o seguinte:
Na primeira vez que você executar `yarn twenty auth:login`, será solicitado o seguinte:
* URL da API (padrão: http://localhost:3000 ou o perfil do seu espaço de trabalho atual)
* Chave de API
@@ -158,25 +184,25 @@ Suas credenciais são armazenadas por usuário em `~/.twenty/config.json`. Você
```bash filename="Terminal"
# Fazer login interativamente (recomendado)
yarn auth:login
yarn twenty auth:login
# Fazer login em um perfil de espaço de trabalho específico
# Listar todos os espaços de trabalho configurados
yarn auth:list
yarn twenty auth:list
# Alterar o espaço de trabalho padrão (interativo)
yarn auth:switch
yarn twenty auth:switch
# Alternar para um espaço de trabalho específico
yarn auth:switch production
yarn twenty auth:switch production
# Verificar o status atual da autenticação
yarn auth:status
yarn twenty auth:status
```
Depois que você alternar os espaços de trabalho com `auth:switch`, todos os comandos subsequentes usarão esse espaço de trabalho por padrão. Você ainda pode substituí-lo temporariamente com `--workspace <name>`.
Depois que você alternar os espaços de trabalho com `yarn twenty auth:switch`, todos os comandos subsequentes usarão esse espaço de trabalho por padrão. Você ainda pode substituí-lo temporariamente com `--workspace <name>`.
## Use os recursos do SDK (tipos e configuração)
@@ -186,14 +212,16 @@ O twenty-sdk fornece blocos de construção tipados e funções utilitárias que
O SDK fornece funções utilitárias para definir as entidades do seu app. Conforme descrito em [Detecção de entidades](#entity-detection), você deve usar `export default define<Entity>({...})` para que suas entidades sejam detectadas:
| `defineApplication()` | Configurar metadados do aplicativo (obrigatório, um por app) |
| `defineObject()` | Define objetos personalizados com campos |
| `defineLogicFunction()` | Defina funções de lógica com handlers |
| `defineFrontComponent()` | Definir componentes de front-end para UI personalizada |
| `defineRole()` | Configura permissões de papéis e acesso a objetos |
| `defineField()` | Estender objetos existentes com campos adicionais |
| `defineView()` | Define visualizações salvas para objetos |
| `defineNavigationMenuItem()` | Define links de navegação da barra lateral |
Essas funções validam sua configuração em tempo de compilação e oferecem autocompletar na IDE e segurança de tipos.
@@ -276,10 +304,14 @@ Pontos-chave:
* O `universalIdentifier` deve ser exclusivo e estável entre implantações.
* Cada campo requer `name`, `type`, `label` e seu próprio `universalIdentifier` estável.
* O array `fields` é opcional — você pode definir objetos sem campos personalizados.
* Você pode criar novos objetos usando `yarn entity:add`, que orienta você sobre nomeação, campos e relacionamentos.
* Você pode criar novos objetos usando `yarn twenty entity:add`, que orienta você sobre nomeação, campos e relacionamentos.
<Note>
**Os campos base são criados automaticamente.** Quando você define um objeto personalizado, o Twenty adiciona automaticamente campos padrão como `name`, `createdAt`, `updatedAt`, `createdBy`, `position` e `deletedAt`. Você não precisa definir esses no seu array `fields` — adicione apenas seus campos personalizados.
**Os campos base são criados automaticamente.** Quando você define um objeto personalizado, o Twenty adiciona automaticamente campos padrão
como `id`, `name`, `createdAt`, `updatedAt`, `createdBy`, `updatedBy` e `deletedAt`.
Você não precisa definir esses no seu array `fields` — adicione apenas seus campos personalizados.
Você pode substituir os campos padrão definindo um campo com o mesmo nome no seu array `fields`,
mas isso não é recomendado.
</Note>
### Configuração do aplicativo (application-config.ts)
@@ -289,6 +321,7 @@ Todo aplicativo tem um único arquivo `application-config.ts` que descreve:
* **O que é o aplicativo**: identificadores, nome de exibição e descrição.
* **Como suas funções são executadas**: qual papel usam para permissões.
* **Variáveis (opcional)**: pares chave–valor expostos às suas funções como variáveis de ambiente.
* **(Opcional) função de pós-instalação**: uma função de lógica que é executada após a instalação da aplicação.
Use `defineApplication()` to define your application configuration:
@@ -296,6 +329,7 @@ Use `defineApplication()` to define your application configuration:
// src/application-config.ts
import { defineApplication } from 'twenty-sdk';
import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role';
import { POST_INSTALL_UNIVERSAL_IDENTIFIER } from 'src/logic-functions/post-install';
* `universalIdentifier` são IDs determinísticos que você controla; gere-os uma vez e mantenha-os estáveis entre sincronizações.
* `applicationVariables` tornam-se variáveis de ambiente para suas funções (por exemplo, `DEFAULT_RECIPIENT_NAME` fica disponível como `process.env.DEFAULT_RECIPIENT_NAME`).
* `defaultRoleUniversalIdentifier` deve corresponder ao arquivo do papel (veja abaixo).
* `postInstallLogicFunctionUniversalIdentifier` (opcional) aponta para uma função de lógica que é executada automaticamente após a instalação da aplicação. Consulte [Funções de pós-instalação](#post-install-functions).
#### Papéis e permissões
@@ -457,6 +493,55 @@ Notas:
* O array `triggers` é opcional. Funções sem gatilhos podem ser usadas como funções utilitárias chamadas por outras funções.
* Você pode misturar vários tipos de gatilho em uma única função.
### Funções de pós-instalação
Uma função de pós-instalação é uma função de lógica que é executada automaticamente após a sua aplicação ser instalada em um espaço de trabalho. Isso é útil para tarefas de configuração únicas, como preencher dados padrão, criar registros iniciais ou configurar as configurações do espaço de trabalho.
Ao criar a estrutura de um novo app com `create-twenty-app`, uma função de pós-instalação é gerada para você em `src/logic-functions/post-install.ts`:
Você também pode executar manualmente a função de pós-instalação a qualquer momento usando a CLI:
```bash filename="Terminal"
yarn twenty function:execute --postInstall
```
Pontos-chave:
* As funções de pós-instalação são funções de lógica padrão — elas usam `defineLogicFunction()` como qualquer outra função.
* O campo `postInstallLogicFunctionUniversalIdentifier` em `defineApplication()` é opcional. Se omitido, nenhuma função é executada após a instalação.
* O tempo limite padrão é definido como 300 segundos (5 minutos) para permitir tarefas de configuração mais longas, como o pré-carregamento de dados.
* As funções de pós-instalação não precisam de gatilhos — elas são invocadas pela plataforma durante a instalação ou manualmente via `function:execute --postInstall`.
* **Gerado automaticamente**: Execute `yarn entity:add` e escolha a opção para adicionar uma nova função de lógica. Isso gera um arquivo inicial com um handler e configuração.
* **Gerado automaticamente**: Execute `yarn twenty entity:add` e escolha a opção para adicionar uma nova função de lógica. Isso gera um arquivo inicial com um handler e configuração.
* **Manual**: Crie um novo arquivo `*.logic-function.ts` e use `defineLogicFunction()`, seguindo o mesmo padrão.
### Marcar uma função lógica como ferramenta
Funções lógicas podem ser expostas como **ferramentas** para agentes de IA e fluxos de trabalho. Quando uma função é marcada como ferramenta, ela fica disponível para os recursos de IA do Twenty e pode ser selecionada como uma etapa em automações de fluxos de trabalho.
Para marcar uma função lógica como ferramenta, defina `isTool: true` e forneça um `toolInputSchema` descrevendo os parâmetros de entrada esperados usando [JSON Schema](https://json-schema.org/):
description: 'Enrich a company record with external data',
timeoutSeconds: 10,
handler,
isTool: true,
toolInputSchema: {
type: 'object',
properties: {
companyName: {
type: 'string',
description: 'The name of the company to enrich',
},
domain: {
type: 'string',
description: 'The company website domain (optional)',
},
},
required: ['companyName'],
},
});
```
Pontos-chave:
* **`isTool`** (`boolean`, padrão: `false`): Quando definido como `true`, a função é registrada como uma ferramenta e fica disponível para agentes de IA e automações de fluxos de trabalho.
* **`toolInputSchema`** (`object`, opcional): Um objeto JSON Schema que descreve os parâmetros que sua função aceita. Os agentes de IA usam esse esquema para entender quais entradas a ferramenta espera e para validar as chamadas. Se omitido, o esquema tem como padrão `{ type: 'object', properties: {} }` (sem parâmetros).
* Funções com `isTool: false` (ou não definido) **não** são expostas como ferramentas. Elas ainda podem ser executadas diretamente ou chamadas por outras funções, mas não aparecerão na descoberta de ferramentas.
* **Nomenclatura de ferramentas**: Quando exposta como uma ferramenta, o nome da função é automaticamente normalizado para `logic_function_<name>` (em minúsculas, caracteres não alfanuméricos substituídos por sublinhados). Por exemplo, `enrich-company` torna-se `logic_function_enrich_company`.
* Você pode combinar `isTool` com gatilhos — uma função pode ser ao mesmo tempo uma ferramenta (chamável por agentes de IA) e acionada por eventos (cron, eventos de banco de dados, rotas) simultaneamente.
<Note>
**Escreva uma boa `description`.** Os agentes de IA dependem do campo `description` da função para decidir quando usar a ferramenta. Seja específico sobre o que a ferramenta faz e quando ela deve ser chamada.
</Note>
### Componentes de front-end
Componentes de front-end permitem criar componentes React personalizados que são renderizados na UI do Twenty. Use `defineFrontComponent()` para definir componentes com validação integrada:
@@ -584,16 +734,16 @@ Pontos-chave:
* Componentes de front-end são componentes React que renderizam em contextos isolados dentro do Twenty.
* Use o sufixo de arquivo `*.front-component.tsx` para detecção automática.
* O campo `component` faz referência ao seu componente React.
* Os componentes são compilados e sincronizados automaticamente durante `yarn app:dev`.
* Os componentes são compilados e sincronizados automaticamente durante `yarn twenty app:dev`.
Você pode criar novos componentes de front-end de duas formas:
* **Gerado automaticamente**: Execute `yarn entity:add` e escolha a opção para adicionar um novo componente de front-end.
* **Gerado automaticamente**: Execute `yarn twenty entity:add` e escolha a opção para adicionar um novo componente de front-end.
* **Manual**: Crie um novo arquivo `*.front-component.tsx` e use `defineFrontComponent()`.
### Cliente tipado gerado
Execute yarn app:generate para criar um cliente tipado local em generated/ com base no esquema do seu workspace. Use-o em suas funções:
O cliente tipado é gerado automaticamente pelo `yarn twenty app:dev` e armazenado em `node_modules/twenty-sdk/generated` com base no esquema do seu espaço de trabalho. Use-o em suas funções:
O cliente é regenerado pelo `yarn app:generate`. Execute novamente após alterar seus objetos ou ao ingressar em um novo workspace.
O cliente é regenerado automaticamente pelo `yarn twenty app:dev` sempre que seus objetos ou campos forem alterados.
#### Credenciais em tempo de execução em funções de lógica
@@ -623,40 +773,29 @@ Explore um exemplo mínimo de ponta a ponta que demonstra objetos, funções de
## Configuração manual (sem o gerador)
Embora recomendemos usar `create-twenty-app` para a melhor experiência inicial, você também pode configurar um projeto manualmente. Não instale a CLI globalmente. Em vez disso, adicione `twenty-sdk` como uma dependência local e conecte scripts no seu package.json:
Embora recomendemos usar `create-twenty-app` para a melhor experiência inicial, você também pode configurar um projeto manualmente. Não instale a CLI globalmente. Em vez disso, adicione `twenty-sdk` como uma dependência local e configure um único script no seu package.json:
```bash filename="Terminal"
yarn add -D twenty-sdk
```
Em seguida, adicione scripts como estes:
Em seguida, adicione um script `twenty`:
```json filename="package.json"
{
"scripts": {
"auth:login": "twenty auth:login",
"auth:logout": "twenty auth:logout",
"auth:status": "twenty auth:status",
"auth:switch": "twenty auth:switch",
"auth:list": "twenty auth:list",
"app:dev": "twenty app:dev",
"app:generate": "twenty app:generate",
"app:uninstall": "twenty app:uninstall",
"entity:add": "twenty entity:add",
"function:logs": "twenty function:logs",
"function:execute": "twenty function:execute",
"help": "twenty help"
"twenty": "twenty"
}
}
```
Agora você pode executar os mesmos comandos via Yarn, por exemplo, `yarn app:dev`, `yarn app:generate`, etc.
Agora você pode executar todos os comandos via `yarn twenty <command>`, por exemplo, `yarn twenty app:dev`, `yarn twenty help`, etc.
## Resolução de Problemas
* Erros de autenticação: execute `yarn auth:login` e certifique-se de que sua chave de API tenha as permissões necessárias.
* Erros de autenticação: execute `yarn twenty auth:login` e certifique-se de que sua chave de API tenha as permissões necessárias.
* Não é possível conectar ao servidor: verifique a URL da API e se o servidor do Twenty está acessível.
* Tipos ou cliente ausentes/desatualizados: execute `yarn app:generate`.
* Modo de desenvolvimento não sincronizando: certifique-se de que `yarn app:dev` esteja em execução e de que as alterações não estejam sendo ignoradas pelo seu ambiente.
* Tipos ou cliente ausentes/desatualizados: reinicie `yarn twenty app:dev` — ele gera automaticamente o cliente tipado.
* Modo de desenvolvimento não sincronizando: certifique-se de que `yarn twenty app:dev` esteja em execução e de que as alterações não estejam sendo ignoradas pelo seu ambiente.
Canal de ajuda no Discord: https://discord.com/channels/1130383047699738754/1130386664812982322
# Dezinstalează aplicația din spațiul de lucru curent
yarn app:uninstall
yarn twenty app:uninstall
# Afișează ajutorul pentru comenzi
yarn help},{
yarn twenty help
```
Consultați și: paginile de referință CLI pentru [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) și [twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk).
@@ -73,9 +86,9 @@ Când rulați `npx create-twenty-app@latest my-twenty-app`, generatorul:
* Copiază o aplicație de bază minimală în `my-twenty-app/`
* Adaugă o dependență locală `twenty-sdk` și configurația Yarn 4
* Creează fișiere de configurare și scripturi conectate la CLI-ul `twenty`
* Generează o configurație implicită a aplicației și un rol implicit pentru funcții
* Generează fișierele de bază (configurația aplicației, rolul implicit al funcțiilor, funcția post-instalare) plus fișiere de exemplu în funcție de modul de generare a scheletului
O aplicație nou generată arată astfel:
O aplicație proaspăt generată cu modul implicit `--exhaustive` arată astfel:
```text filename="my-twenty-app/"
my-twenty-app/
@@ -89,20 +102,31 @@ my-twenty-app/
eslint.config.mjs
tsconfig.json
README.md
public/ # Public assets folder (images, fonts, etc.)
public/ # Director pentru resurse publice (imagini, fonturi etc.)
src/
├── application-config.ts # Required - main application configuration
├── application-config.ts # Obligatoriu - configurația principală a aplicației
├── roles/
│ └── default-role.ts # Default role for logic functions
│ └── default-role.ts # Rol implicit pentru funcțiile logice
├── objects/
│ └── example-object.ts # Exemplu de definiție a unui obiect personalizat
├── fields/
│ └── example-field.ts # Exemplu de definiție de câmp independent
├── logic-functions/
│ └── hello-world.ts # Example logic function
└── front-components/
└── hello-world.tsx # Example frontcomponent
│ ├── hello-world.ts # Exemplu de funcție logică
│ └── post-install.ts # Funcție logică post-instalare
├── front-components/
│ └── hello-world.tsx # Exemplu de componentă de interfață
├── views/
│ └── example-view.ts # Exemplu de definiție a unei vizualizări salvate
└── navigation-menu-items/
└── example-navigation-menu-item.ts # Exemplu de link de navigare în bara laterală
```
Cu `--minimal`, sunt create doar fișierele de bază (`application-config.ts`, `roles/default-role.ts` și `logic-functions/post-install.ts`). Cu `--interactive`, alegi ce fișiere de exemplu să incluzi.
Pe scurt:
* **package.json**: Declară numele aplicației, versiunea, motoarele (Node 24+, Yarn 4) și adaugă `twenty-sdk` plus scripturi precum `app:dev`, `app:generate`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall`, precum și comenzi de autentificare care deleagă către CLI-ul local `twenty`.
* **package.json**: Declară numele aplicației, versiunea, motoarele (Node 24+, Yarn 4) și adaugă `twenty-sdk` plus un script `twenty` care deleagă către CLI-ul local `twenty`. Rulează `yarn twenty help` pentru a lista toate comenzile disponibile.
* **.gitignore**: Ignoră artefacte comune precum `node_modules`, `.yarn`, `generated/` (client tipizat), `dist/`, `build/`, foldere de coverage, fișiere jurnal și fișiere `.env*`.
* **yarn.lock**, **.yarnrc.yml**, **.yarn/**: Blochează și configurează lanțul de instrumente Yarn 4 folosit de proiect.
* **.nvmrc**: Fixează versiunea Node.js așteptată de proiect.
@@ -115,13 +139,15 @@ Pe scurt:
SDK-ul detectează entitățile analizând fișierele TypeScript pentru apeluri **`export default define<Entity>({...})`**. Fiecare tip de entitate are o funcție ajutătoare corespunzătoare, exportată din `twenty-sdk`:
| `defineObject()` | Definiții de obiecte personalizate |
| `defineLogicFunction()` | Definiții de funcții de logică |
| `defineFrontComponent()` | Definiții ale componentelor de interfață |
| `defineRole()` | Definiții de rol |
| `defineField()` | Extensii de câmp pentru obiectele existente |
| `defineView()` | Definiții pentru vizualizări salvate |
| `defineNavigationMenuItem()` | Definiții pentru elemente de meniu de navigare |
<Note>
**Denumirea fișierelor este flexibilă.** Detectarea entităților se bazează pe AST — SDK-ul scanează fișierele sursă pentru tiparul `export default define<Entity>({...})`. Puteți organiza fișierele și folderele cum doriți. Gruparea după tipul de entitate (de exemplu, `logic-functions/`, `roles/`) este doar o convenție pentru organizarea codului, nu o cerință.
Comenzile ulterioare vor adăuga mai multe fișiere și foldere:
* `yarn app:generate` va crea un folder `generated/` (client Twenty tipizat + tipuri pentru spațiul de lucru).
* `yarn entity:add` va adăuga fișiere de definire a entităților în `src/` pentru obiectele, funcțiile, componentele front-end sau rolurile personalizate.
* `yarn twenty app:dev` va genera automat un client API tipizat în `node_modules/twenty-sdk/generated` (client Twenty tipizat + tipuri ale spațiului de lucru).
* `yarn twenty entity:add` va adăuga fișiere de definire a entităților în `src/` pentru obiectele, funcțiile, componentele front-end sau rolurile personalizate.
## Autentificare
Prima dată când rulați `yarn auth:login`, vi se vor solicita:
Prima dată când rulați `yarn twenty auth:login`, vi se vor solicita:
* URL-ul API (implicit http://localhost:3000 sau profilul spațiului de lucru curent)
* Cheie API
@@ -158,25 +184,25 @@ Acreditările dvs. sunt stocate per utilizator în `~/.twenty/config.json`. Pute
După ce ați schimbat spațiul de lucru cu `auth:switch`, toate comenzile ulterioare vor folosi implicit acel spațiu de lucru. Îl puteți totuși suprascrie temporar cu `--workspace <name>`.
După ce ați schimbat spațiul de lucru cu `yarn twenty auth:switch`, toate comenzile ulterioare vor folosi implicit acel spațiu de lucru. Îl puteți totuși suprascrie temporar cu `--workspace <name>`.
## Utilizați resursele SDK (tipuri și configurare)
@@ -186,14 +212,16 @@ Biblioteca twenty-sdk oferă blocuri de bază tipizate și funcții ajutătoare
SDK-ul oferă funcții ajutătoare pentru definirea entităților aplicației. După cum este descris în [Detectarea entităților](#entity-detection), trebuie să folosiți `export default define<Entity>({...})` pentru ca entitățile să fie detectate:
| `defineApplication()` | Configurați metadatele aplicației (obligatoriu, una per aplicație) |
| `defineObject()` | Definiți obiecte personalizate cu câmpuri |
| `defineLogicFunction()` | Definiți funcții de logică cu handleri |
| `defineFrontComponent()` | Definiți componente Front pentru interfața de utilizator personalizată |
| `defineRole()` | Configurați permisiunile rolurilor și accesul la obiecte |
| `defineField()` | Extindeți obiectele existente cu câmpuri suplimentare |
| `defineView()` | Definește vizualizări salvate pentru obiecte |
| `defineNavigationMenuItem()` | Definește linkuri de navigare în bara laterală |
Aceste funcții validează configurația în timpul build-ului și oferă completare automată în IDE și siguranța tipurilor.
@@ -276,10 +304,14 @@ Puncte cheie:
* `universalIdentifier` trebuie să fie unic și stabil între implementări.
* Fiecare câmp necesită un `name`, un `type`, un `label` și propriul `universalIdentifier` stabil.
* Matricea `fields` este opțională — puteți defini obiecte fără câmpuri personalizate.
* Puteți genera obiecte noi folosind `yarn entity:add`, care vă ghidează prin denumire, câmpuri și relații.
* Puteți genera obiecte noi folosind `yarn twenty entity:add`, care vă ghidează prin denumire, câmpuri și relații.
<Note>
**Câmpurile de bază sunt create automat.** Când definiți un obiect personalizat, Twenty adaugă automat câmpuri standard precum `name`, `createdAt`, `updatedAt`, `createdBy`, `position` și `deletedAt`. Nu trebuie să le definiți în tabloul `fields` — adăugați doar câmpurile personalizate proprii.
**Câmpurile de bază sunt create automat.** Când definiți un obiect personalizat, Twenty adaugă automat câmpuri standard
precum `id`, `name`, `createdAt`, `updatedAt`, `createdBy`, `updatedBy` și `deletedAt`.
Nu trebuie să le definiți în tabloul `fields` — adăugați doar câmpurile personalizate proprii.
Puteți suprascrie câmpurile implicite definind un câmp cu același nume în tabloul `fields`,
* Câmpurile `universalIdentifier` sunt ID-uri deterministe pe care le dețineți; generați-le o singură dată și păstrați-le stabile între sincronizări.
* `applicationVariables` devin variabile de mediu pentru funcțiile dvs. (de exemplu, `DEFAULT_RECIPIENT_NAME` este disponibil ca `process.env.DEFAULT_RECIPIENT_NAME`).
* `defaultRoleUniversalIdentifier` trebuie să corespundă fișierului de rol (vedeți mai jos).
* `postInstallLogicFunctionUniversalIdentifier` (opțional) indică o funcție logică care rulează automat după instalarea aplicației. Vezi [Funcții post-instalare](#post-install-functions).
#### Roluri și permisiuni
@@ -457,6 +493,55 @@ Notițe:
* Matricea `triggers` este opțională. Funcțiile fără declanșatoare pot fi folosite ca funcții utilitare apelate de alte funcții.
* Puteți combina mai multe tipuri de declanșatoare într-o singură funcție.
### Funcții post-instalare
O funcție post-instalare este o funcție logică care rulează automat după instalarea aplicației într-un spațiu de lucru. Aceasta este utilă pentru sarcini de configurare unice, cum ar fi popularea cu date implicite, crearea înregistrărilor inițiale sau configurarea setărilor spațiului de lucru.
Când creezi scheletul unei aplicații noi cu `create-twenty-app`, este generată o funcție post-instalare la `src/logic-functions/post-install.ts`:
Poți, de asemenea, să execuți manual funcția post-instalare oricând folosind CLI:
```bash filename="Terminal"
yarn twenty function:execute --postInstall
```
Puncte cheie:
* Funcțiile post-instalare sunt funcții logice standard — folosesc `defineLogicFunction()` la fel ca orice altă funcție.
* Câmpul `postInstallLogicFunctionUniversalIdentifier` din `defineApplication()` este opțional. Dacă este omis, nu rulează nicio funcție după instalare.
* Timpul de expirare implicit este setat la 300 de secunde (5 minute) pentru a permite sarcini de configurare mai lungi, cum ar fi popularea datelor.
* Funcțiile post-instalare nu au nevoie de declanșatoare — sunt invocate de platformă în timpul instalării sau manual prin `function:execute --postInstall`.
* **Generat**: Rulați `yarn entity:add` și alegeți opțiunea de a adăuga o funcție de logică nouă. Aceasta generează un fișier inițial cu un handler și o configurație.
* **Generat**: Rulați `yarn twenty entity:add` și alegeți opțiunea de a adăuga o funcție logică nouă. Aceasta generează un fișier inițial cu un handler și o configurație.
* **Manual**: Creați un fișier nou `*.logic-function.ts` și folosiți `defineLogicFunction()`, urmând același model.
### Marcarea unei funcții logice drept instrument
Funcțiile logice pot fi expuse ca **instrumente** pentru agenți de IA și fluxuri de lucru. Când o funcție este marcată ca instrument, poate fi descoperită de funcționalitățile de IA ale Twenty și poate fi selectată ca pas în automatizări ale fluxurilor de lucru.
Pentru a marca o funcție logică drept instrument, setați `isTool: true` și furnizați un `toolInputSchema` care descrie parametrii de intrare așteptați folosind [JSON Schema](https://json-schema.org/):
description: 'Enrich a company record with external data',
timeoutSeconds: 10,
handler,
isTool: true,
toolInputSchema: {
type: 'object',
properties: {
companyName: {
type: 'string',
description: 'The name of the company to enrich',
},
domain: {
type: 'string',
description: 'The company website domain (optional)',
},
},
required: ['companyName'],
},
});
```
Puncte cheie:
* **`isTool`** (`boolean`, implicit: `false`): Când este setat la `true`, funcția este înregistrată ca instrument și devine disponibilă pentru agenții AI și automatizările de fluxuri de lucru.
* **`toolInputSchema`** (`object`, opțional): Un obiect JSON Schema care descrie parametrii pe care îi acceptă funcția dvs. Agenții AI folosesc această schemă pentru a înțelege ce intrări așteaptă instrumentul și pentru a valida apelurile. Dacă este omisă, schema are implicit valoarea `{ type: 'object', properties: {} }` (fără parametri).
* Funcțiile cu `isTool: false` (sau nedefinit) **nu** sunt expuse ca instrumente. Pot totuși fi executate direct sau apelate de alte funcții, dar nu vor apărea în descoperirea instrumentelor.
* **Denumierea instrumentelor**: Când este expusă ca instrument, denumirea funcției este normalizată automat la `logic_function_<name>` (convertită la litere mici, iar caracterele non-alfanumerice sunt înlocuite cu caractere de subliniere). De exemplu, `enrich-company` devine `logic_function_enrich_company`.
* Puteți combina `isTool` cu declanșatoare — o funcție poate fi atât un instrument (apelabilă de agenții AI), cât și declanșată de evenimente (cron, evenimente de bază de date, rute) în același timp.
<Note>
**Scrieți o `description` bună.** Agenții AI se bazează pe câmpul `description` al funcției pentru a decide când să folosească instrumentul. Fiți specifici cu privire la ceea ce face instrumentul și când ar trebui apelat.
</Note>
### Componente Front
Componentele Front vă permit să construiți componente React personalizate care sunt randate în interfața Twenty. Utilizați `defineFrontComponent()` pentru a defini componente cu validare încorporată:
@@ -584,16 +734,16 @@ Puncte cheie:
* Componentele Front sunt componente React care sunt randate în contexte izolate în cadrul Twenty.
* Folosiți sufixul de fișier `*.front-component.tsx` pentru detectare automată.
* Câmpul `component` face referire la componenta React.
* Componentele sunt construite și sincronizate automat în timpul `yarn app:dev`.
* Componentele sunt construite și sincronizate automat în timpul `yarn twenty app:dev`.
Puteți crea componente Front noi în două moduri:
* **Generat**: Rulați `yarn entity:add` și alegeți opțiunea de a adăuga o componentă Front nouă.
* **Generat**: Rulați `yarn twenty entity:add` și alegeți opțiunea de a adăuga o componentă frontend nouă.
* **Manual**: Creați un fișier nou `*.front-component.tsx` și folosiți `defineFrontComponent()`.
### Client tipizat generat
Rulați yarn app:generate pentru a crea un client tipizat local în generated/, pe baza schemei spațiului de lucru. Folosiți-l în funcțiile dvs.:
Clientul tipizat este generat automat de `yarn twenty app:dev` și stocat în `node_modules/twenty-sdk/generated`, pe baza schemei spațiului tău de lucru. Folosiți-l în funcțiile dvs.:
Clientul este regenerat de `yarn app:generate`. Rulați din nou după ce vă modificați obiectele sau când vă integrați într-un spațiu de lucru nou.
Clientul este regenerat automat de `yarn twenty app:dev` ori de câte ori obiectele sau câmpurile tale se schimbă.
#### Acreditări la runtime în funcțiile de logică
@@ -623,40 +773,29 @@ Explorați un exemplu minim, cap la cap, care demonstrează obiecte, funcții de
## Configurare manuală (fără generator)
Deși recomandăm utilizarea `create-twenty-app` pentru cea mai bună experiență de început, puteți configura și un proiect manual. Nu instalați CLI-ul global. În schimb, adăugați `twenty-sdk` ca dependență locală și conectați scripturile în package.json-ul dvs.:
Deși recomandăm utilizarea `create-twenty-app` pentru cea mai bună experiență de început, puteți configura și un proiect manual. Nu instalați CLI-ul global. În schimb, adăugați `twenty-sdk` ca dependență locală și conectați un singur script în package.json-ul dvs.:
```bash filename="Terminal"
yarn add -D twenty-sdk
```
Apoi adăugați scripturi ca acestea:
Apoi adăugați un script `twenty`:
```json filename="package.json"
{
"scripts": {
"auth:login": "twenty auth:login",
"auth:logout": "twenty auth:logout",
"auth:status": "twenty auth:status",
"auth:switch": "twenty auth:switch",
"auth:list": "twenty auth:list",
"app:dev": "twenty app:dev",
"app:generate": "twenty app:generate",
"app:uninstall": "twenty app:uninstall",
"entity:add": "twenty entity:add",
"function:logs": "twenty function:logs",
"function:execute": "twenty function:execute",
"help": "twenty help"
"twenty": "twenty"
}
}
```
Acum puteți rula aceleași comenzi prin Yarn, de ex. `yarn app:dev`, `yarn app:generate`, etc.
Acum poți rula toate comenzile prin `yarn twenty <command>`, de ex. `yarn twenty app:dev`, `yarn twenty help`, etc.
## Depanare
* Erori de autentificare: rulați `yarn auth:login` și asigurați-vă că cheia API are permisiunile necesare.
* Erori de autentificare: rulați `yarn twenty auth:login` și asigurați-vă că cheia API are permisiunile necesare.
* Nu se poate conecta la server: verificați URL-ul API și că serverul Twenty este accesibil.
* Tipuri sau client lipsă/învechite: rulați `yarn app:generate`.
* Modul dev nu sincronizează: asigurați-vă că `yarn app:dev` rulează și că modificările nu sunt ignorate de mediul dvs.
* Types or client missing/outdated: restart `yarn twenty app:dev` — it auto-generates the typed client.
* Modul dev nu sincronizează: asigurați-vă că `yarn twenty app:dev` rulează și că modificările nu sunt ignorate de mediul dvs.
Canal de ajutor pe Discord: https://discord.com/channels/1130383047699738754/1130386664812982322
# Удалить приложение из текущего рабочего пространства
yarn app:uninstall
yarn twenty app:uninstall
# Показать справку по командам
yarn help
yarn twenty help
```
Смотрите также: страницы справки CLI для [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) и [twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk).
@@ -73,9 +86,9 @@ yarn help
* Копирует минимальное базовое приложение в `my-twenty-app/`
* Добавляет локальную зависимость `twenty-sdk` и конфигурацию Yarn 4
* Создаёт файлы конфигурации и скрипты, подключённые к CLI `twenty`
* Генерирует конфигурацию приложения по умолчанию и роль функции по умолчанию
* Генерирует основные файлы (конфигурацию приложения, роль функций по умолчанию, постустановочную функцию), а также примерные файлы в зависимости от выбранного режима создания каркаса
Свежесгенерированное приложение выглядит так:
Сгенерированное с помощью каркаса приложение с режимом по умолчанию `--exhaustive` выглядит так:
```text filename="my-twenty-app/"
my-twenty-app/
@@ -89,20 +102,31 @@ my-twenty-app/
eslint.config.mjs
tsconfig.json
README.md
public/ # Папка общедоступных ресурсов (изображения, шрифты и т. п.)
public/ # Папка публичных ресурсов (изображения, шрифты и т. д.)
src/
├── application-config.ts # Обязательный — основная конфигурация приложения
├── roles/
│ └── default-role.ts # Роль по умолчанию для логических функций
├── objects/
│ └── example-object.ts # Пример определения пользовательского объекта
├── fields/
│ └── example-field.ts # Пример определения отдельного поля
├── logic-functions/
│ └── hello-world.ts # Пример логической функции
└── front-components/
└── hello-world.tsx # Пример фронтенд-компонента
│ ├── hello-world.ts # Пример логической функции
│ └── post-install.ts # Постустановочная логическая функция
├── front-components/
│ └── hello-world.tsx # Пример фронтенд-компонента
├── views/
│ └── example-view.ts # Пример определения сохранённого представления
└── navigation-menu-items/
└── example-navigation-menu-item.ts # Пример ссылки боковой панели навигации
```
С `--minimal` создаются только основные файлы (`application-config.ts`, `roles/default-role.ts` и `logic-functions/post-install.ts`). С `--interactive` вы выбираете, какие примерные файлы включить.
В общих чертах:
* **package.json**: Объявляет имя приложения, версию, движки (Node 24+, Yarn 4) и добавляет `twenty-sdk`, а также скрипты вроде `app:dev`, `app:generate`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall` и команды аутентификации, которые делегируют выполнение локальному CLI `twenty`.
* **package.json**: Объявляет имя приложения, версию, движки (Node 24+, Yarn 4) и добавляет `twenty-sdk`, а также скрипт `twenty`, который делегирует выполнение локальному CLI `twenty`. Выполните `yarn twenty help`, чтобы вывести список всех доступных команд.
* **.gitignore**: Игнорирует распространённые артефакты, такие как `node_modules`, `.yarn`, `generated/` (типизированный клиент), `dist/`, `build/`, каталоги coverage, файлы журналов и файлы `.env*`.
* **yarn.lock**, **.yarnrc.yml**, **.yarn/**: Фиксируют и настраивают используемый в проекте инструментарий Yarn 4.
* **.nvmrc**: Фиксирует версию Node.js, ожидаемую проектом.
@@ -115,13 +139,15 @@ my-twenty-app/
SDK обнаруживает сущности, разбирая ваши файлы TypeScript в поисках вызовов **`export default define<Entity>({...})`**. Для каждого типа сущности существует соответствующая вспомогательная функция, экспортируемая из `twenty-sdk`:
| `defineObject()` | Определения пользовательских объектов |
| `defineLogicFunction()` | Определения логических функций |
| `defineFrontComponent()` | Определения компонентов фронтенда |
| `defineRole()` | Определения ролей |
| `defineField()` | Расширения полей для существующих объектов |
| `defineView()` | Определения сохранённых представлений |
| `defineNavigationMenuItem()` | Определения пунктов меню навигации |
<Note>
**Имена файлов заданы гибко.** Обнаружение сущностей основано на AST — SDK сканирует ваши исходные файлы в поисках шаблона `export default define<Entity>({...})`. Вы можете организовывать файлы и папки как угодно. Группировка по типу сущности (например, `logic-functions/`, `roles/`) — это лишь соглашение для организации кода, а не требование.
* `yarn entity:add` добавит файлы определений сущностей в `src/` для ваших пользовательских объектов, функций, фронтенд-компонентов или ролей.
* `yarn twenty app:dev` автоматически сгенерирует типизированный клиент API в `node_modules/twenty-sdk/generated` (типизированный клиент Twenty + типы рабочего пространства).
* `yarn twenty entity:add` добавит файлы определений сущностей в `src/` для ваших пользовательских объектов, функций, фронтенд-компонентов или ролей.
## Аутентификация
При первом запуске `yarn auth:login` вам будет предложено указать:
При первом запуске `yarn twenty auth:login` вам будет предложено указать:
* URL API (по умолчанию http://localhost:3000 или текущий профиль рабочего пространства)
# Показать список всех настроенных рабочих пространств
yarn auth:list
yarn twenty auth:list
# Переключить рабочее пространство по умолчанию (в интерактивном режиме)
yarn auth:switch
yarn twenty auth:switch
# Переключиться на определённое рабочее пространство
yarn auth:switch production
yarn twenty auth:switch production
# Проверить текущий статус аутентификации
yarn auth:status
yarn twenty auth:status
```
После переключения рабочего пространства с помощью `auth:switch` все последующие команды по умолчанию будут использовать это рабочее пространство. Вы по-прежнему можете временно переопределить это с помощью `--workspace <name>`.
После переключения рабочего пространства с помощью `yarn twenty auth:switch` все последующие команды по умолчанию будут использовать это рабочее пространство. Вы по-прежнему можете временно переопределить это с помощью `--workspace <name>`.
## Используйте ресурсы SDK (типы и конфигурация)
@@ -186,14 +212,16 @@ yarn auth:status
SDK предоставляет вспомогательные функции для определения сущностей вашего приложения. Как описано в [Обнаружение сущностей](#entity-detection), вы должны использовать `export default define<Entity>({...})`, чтобы ваши сущности были обнаружены:
* `universalIdentifier` должен быть уникальным и стабильным между развёртываниями.
* Каждому полю требуются `name`, `type`, `label` и собственный стабильный `universalIdentifier`.
* Массив `fields` необязателен — вы можете определять объекты без пользовательских полей.
* Вы можете сгенерировать новые объекты с помощью `yarn entity:add`, который проведёт вас через выбор именования, полей и связей.
* Вы можете сгенерировать новые объекты с помощью `yarn twenty entity:add`, который проведёт вас через настройку имени, полей и связей.
<Note>
**Базовые поля создаются автоматически.** Когда вы определяете пользовательский объект, Twenty автоматически добавляет стандартные поля, такие как `name`, `createdAt`, `updatedAt`, `createdBy`, `position` и `deletedAt`. Вам не нужно определять их в массиве `fields` — добавляйте только свои пользовательские поля.
**Базовые поля создаются автоматически.** Когда вы определяете пользовательский объект, Twenty автоматически добавляет стандартные поля,
такие как `id`, `name`, `createdAt`, `updatedAt`, `createdBy`, `updatedBy` и `deletedAt`.
Вам не нужно определять их в массиве `fields` — добавляйте только свои пользовательские поля.
Вы можете переопределить поля по умолчанию, определив поле с тем же именем в массиве `fields`,
* `universalIdentifier` — это детерминированные идентификаторы, которыми вы управляете; сгенерируйте их один раз и сохраняйте стабильными между синхронизациями.
* `applicationVariables` становятся переменными окружения для ваших функций (например, `DEFAULT_RECIPIENT_NAME` доступна как `process.env.DEFAULT_RECIPIENT_NAME`).
* `defaultRoleUniversalIdentifier` должен соответствовать файлу роли (см. ниже).
* `postInstallLogicFunctionUniversalIdentifier` (необязательно) указывает на логическую функцию, которая автоматически выполняется после установки приложения. См. [Послеустановочные функции](#post-install-functions).
* Массив `triggers` необязателен. Функции без триггеров можно использовать как вспомогательные, вызываемые другими функциями.
* Вы можете сочетать несколько типов триггеров в одной функции.
### Послеустановочные функции
Послеустановочная функция — это функция логики, которая автоматически выполняется после установки вашего приложения в рабочем пространстве. Это полезно для одноразовых задач настройки, таких как инициализация данных по умолчанию, создание начальных записей или настройка параметров рабочего пространства.
Когда вы создаёте каркас нового приложения с помощью `create-twenty-app`, для вас генерируется постустановочная функция по пути `src/logic-functions/post-install.ts`:
Вы также можете вручную выполнить постустановочную функцию в любое время с помощью CLI:
```bash filename="Terminal"
yarn twenty function:execute --postInstall
```
Основные моменты:
* Постустановочные функции — это стандартные логические функции: они используют `defineLogicFunction()` как и любые другие функции.
* Поле `postInstallLogicFunctionUniversalIdentifier` в `defineApplication()` является необязательным. Если его опустить, после установки никакая функция выполняться не будет.
* Тайм-аут по умолчанию установлен на 300 секунд (5 минут), чтобы позволить выполнять более длительные задачи настройки, такие как инициализация данных.
* Постустановочным функциям не нужны триггеры — платформа вызывает их во время установки или вручную через `function:execute --postInstall`.
* **Сгенерировано**: Запустите `yarn entity:add` и выберите опцию добавления новой логической функции. Это создаёт стартовый файл с обработчиком и конфигурацией.
* **Сгенерировано**: Запустите `yarn twenty entity:add` и выберите опцию добавления новой функции логики. Это создаёт стартовый файл с обработчиком и конфигурацией.
* **Вручную**: Создайте новый файл `*.logic-function.ts` и используйте `defineLogicFunction()`, следуя тому же шаблону.
### Пометка логической функции как инструмента
Логические функции можно предоставлять как **инструменты** для ИИ-агентов и рабочих процессов. Когда функция помечена как инструмент, она становится доступной для ИИ Twenty и может быть выбрана в качестве шага в автоматизациях рабочих процессов.
Чтобы пометить логическую функцию как инструмент, установите `isTool: true` и укажите `toolInputSchema` для описания ожидаемых входных параметров с помощью [схемы JSON](https://json-schema.org/):
description: 'Enrich a company record with external data',
timeoutSeconds: 10,
handler,
isTool: true,
toolInputSchema: {
type: 'object',
properties: {
companyName: {
type: 'string',
description: 'The name of the company to enrich',
},
domain: {
type: 'string',
description: 'The company website domain (optional)',
},
},
required: ['companyName'],
},
});
```
Основные моменты:
* **`isTool`** (`boolean`, по умолчанию: `false`): Если значение равно `true`, функция регистрируется как инструмент и становится доступной агентам ИИ и автоматизациям рабочих процессов.
* **`toolInputSchema`** (`object`, необязательно): Объект JSON Schema, который описывает параметры, которые принимает ваша функция. Агенты ИИ используют эту схему, чтобы понять, какие входные данные ожидает инструмент, и проверять корректность вызовов. Если опущено, по умолчанию используется схема `{ type: 'object', properties: {} }` (без параметров).
* Функции с `isTool: false` (или без указания) **не** выставляются как инструменты. Их по-прежнему можно выполнять напрямую или вызывать из других функций, но они не будут отображаться при обнаружении инструментов.
* **Именование инструмента**: При публикации как инструмента имя функции автоматически нормализуется до `logic_function_<name>` (в нижнем регистре, небуквенно-цифровые символы заменяются на подчёркивания). Например, `enrich-company` становится `logic_function_enrich_company`.
* Вы можете комбинировать `isTool` с триггерами — функция может одновременно быть инструментом (вызываемым агентами ИИ) и запускаться событиями (cron, события базы данных, маршруты).
<Note>
**Напишите хорошее описание в поле `description`.** Агенты ИИ опираются на поле `description` функции, чтобы решить, когда использовать инструмент. Чётко опишите, что делает инструмент и когда его следует вызывать.
</Note>
### Фронт-компоненты
Фронт-компоненты позволяют создавать пользовательские компоненты React, которые рендерятся внутри интерфейса Twenty. Используйте `defineFrontComponent()` для определения компонентов со встроенной валидацией:
* Фронт-компоненты — это компоненты React, которые рендерятся в изолированных контекстах внутри Twenty.
* Используйте суффикс файла `*.front-component.tsx` для автоматического обнаружения.
* Поле `component` ссылается на ваш компонент React.
* Компоненты автоматически собираются и синхронизируются во время `yarn app:dev`.
* Компоненты автоматически собираются и синхронизируются во время `yarn twenty app:dev`.
Вы можете создать новые фронт-компоненты двумя способами:
* **Сгенерировано**: Запустите `yarn entity:add` и выберите опцию добавления нового фронт-компонента.
* **Сгенерировано**: Запустите `yarn twenty entity:add` и выберите опцию добавления нового фронтенд-компонента.
* **Вручную**: Создайте новый файл `*.front-component.tsx` и используйте `defineFrontComponent()`.
### Сгенерированный типизированный клиент
Запустите yarn app:generate, чтобы создать локальный типизированный клиент в generated/ на основе схемы вашего рабочего пространства. Используйте его в своих функциях:
Типизированный клиент автоматически генерируется с помощью `yarn twenty app:dev` и сохраняется в `node_modules/twenty-sdk/generated` на основе схемы вашего рабочего пространства. Используйте его в своих функциях:
Клиент повторно генерируется командой `yarn app:generate`. Запускайте повторно после изменения ваших объектов или при подключении к новому рабочему пространству.
Клиент автоматически перегенерируется с помощью `yarn twenty app:dev` при изменении ваших объектов или полей.
#### Учётные данные времени выполнения в логических функциях
Хотя мы рекомендуем использовать `create-twenty-app` для наилучшего старта, вы также можете настроить проект вручную. Не устанавливайте CLI глобально. Вместо этого добавьте `twenty-sdk` как локальную зависимость и настройте скрипты в вашем package.json:
Хотя мы рекомендуем использовать `create-twenty-app` для наилучшего старта, вы также можете настроить проект вручную. Не устанавливайте CLI глобально. Вместо этого добавьте `twenty-sdk` как локальную зависимость и настройте один скрипт в вашем package.json:
```bash filename="Terminal"
yarn add -D twenty-sdk
```
Затем добавьте скрипты, подобные этим:
Затем добавьте скрипт `twenty`:
```json filename="package.json"
{
"scripts": {
"auth:login": "twenty auth:login",
"auth:logout": "twenty auth:logout",
"auth:status": "twenty auth:status",
"auth:switch": "twenty auth:switch",
"auth:list": "twenty auth:list",
"app:dev": "twenty app:dev",
"app:generate": "twenty app:generate",
"app:uninstall": "twenty app:uninstall",
"entity:add": "twenty entity:add",
"function:logs": "twenty function:logs",
"function:execute": "twenty function:execute",
"help": "twenty help"
"twenty": "twenty"
}
}
```
Теперь вы можете запускать те же команды через Yarn, например, `yarn app:dev`, `yarn app:generate` и т. д.
Теперь вы можете запускать все команды через `yarn twenty <command>`, например, `yarn twenty app:dev`, `yarn twenty help` и т. д.
## Устранение неполадок
* Ошибки аутентификации: выполните `yarn auth:login` и убедитесь, что у вашего ключа API есть необходимые права.
* Ошибки аутентификации: выполните `yarn twenty auth:login` и убедитесь, что у вашего ключа API есть необходимые права.
* Не удаётся подключиться к серверу: проверьте URL API и доступность сервера Twenty.
* Типы или клиент отсутствуют/устарели: выполните `yarn app:generate`.
* Режим разработки не синхронизируется: убедитесь, что запущен `yarn app:dev`, и что ваша среда не игнорирует изменения.
* Types or client missing/outdated: restart `yarn twenty app:dev` — it auto-generates the typed client.
* Режим разработки не синхронизируется: убедитесь, что запущен `yarn twenty app:dev`, и что ваша среда не игнорирует изменения.
Канал помощи в Discord: https://discord.com/channels/1130383047699738754/1130386664812982322
# Uninstall the application from the current workspace
yarn app:uninstall
yarn twenty app:uninstall
# Display commands' help
yarn help
yarn twenty help
```
Ayrıca bkz.: [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) ve [twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk) için CLI başvuru sayfaları.
@@ -73,9 +86,9 @@ Ayrıca bkz.: [create-twenty-app](https://www.npmjs.com/package/create-twenty-ap
* Minimal bir temel uygulamayı `my-twenty-app/` içine kopyalar
* Yerel bir `twenty-sdk` bağımlılığı ve Yarn 4 yapılandırması ekler
* `twenty` CLI ile bağlantılı yapılandırma dosyaları ve betikler oluşturur
* Varsayılan bir uygulama yapılandırması ve varsayılan bir fonksiyon rolü üretir
* İskelet oluşturma moduna bağlı olarak çekirdek dosyaları (uygulama yapılandırması, varsayılan işlev rolü, kurulum sonrası işlev) ile örnek dosyaları üretir
Yeni şablondan oluşturulan bir uygulama şöyle görünür:
Varsayılan `--exhaustive` moduyla yeni oluşturulmuş bir uygulama şu şekilde görünür:
```text filename="my-twenty-app/"
my-twenty-app/
@@ -89,20 +102,31 @@ my-twenty-app/
eslint.config.mjs
tsconfig.json
README.md
public/ # Genel varlıklar klasörü (görseller, yazı tipleri vb.)
public/ # Public assets folder (images, fonts, etc.)
src/
├── application-config.ts # Gerekli - ana uygulama yapılandırması
├── application-config.ts # Required - main application configuration
├── roles/
│ └── default-role.ts # Mantık işlevleri için varsayılan rol
│ └── default-role.ts # Default role for logic functions
├── objects/
│ └── example-object.ts # Example custom object definition
├── fields/
│ └── example-field.ts # Example standalone field definition
├── logic-functions/
│ └── hello-world.ts # Örnek mantık işlevi
└── front-components/
└── hello-world.tsx # Örnek ön uç bileşeni
│ ├── hello-world.ts # Example logic function
│ └── post-install.ts # Post-install logic function
├── front-components/
│ └── hello-world.tsx # Example front component
├── views/
│ └── example-view.ts # Example saved view definition
└── navigation-menu-items/
└── example-navigation-menu-item.ts # Example sidebar navigation link
```
`--minimal` ile yalnızca çekirdek dosyalar oluşturulur (`application-config.ts`, `roles/default-role.ts` ve `logic-functions/post-install.ts`). `--interactive` ile hangi örnek dosyaların dahil edileceğini siz seçersiniz.
Genel hatlarıyla:
* **package.json**: Uygulama adını, sürümünü, motorları (Node 24+, Yarn 4) bildirir ve `twenty-sdk` ile `app:dev`, `app:generate`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall` gibi betikleri ve yerel `twenty` CLI’sine yetki devreden kimlik doğrulama komutlarını ekler.
* **package.json**: Uygulama adını, sürümünü, motorları (Node 24+, Yarn 4) bildirir ve `twenty-sdk` ile yerel `twenty` CLI'sine yetki devreden bir `twenty` betiği ekler. Tüm mevcut komutları listelemek için `yarn twenty help` komutunu çalıştırın.
* **.gitignore**: `node_modules`, `.yarn`, `generated/` (türlendirilmiş istemci), `dist/`, `build/`, kapsam klasörleri, günlük dosyaları ve `.env*` dosyaları gibi yaygın artifaktları yok sayar.
* **yarn.lock**, **.yarnrc.yml**, **.yarn/**: Proje tarafından kullanılan Yarn 4 araç zincirini kilitler ve yapılandırır.
SDK, TypeScript dosyalarınızı **`export default define<Entity>({...})`** çağrılarını arayarak ayrıştırıp varlıkları algılar. Her varlık türünün, `twenty-sdk` tarafından dışa aktarılan karşılık gelen bir yardımcı fonksiyonu vardır:
**Dosya adlandırma esnektir.** Varlık algılama AST tabanlıdır — SDK, kaynak dosyalarınızı `export default define<Entity>({...})` desenini bulmak için tarar. Dosyalarınızı ve klasörlerinizi dilediğiniz gibi düzenleyebilirsiniz. Varlık türüne göre gruplama (örn. `logic-functions/`, `roles/`) bir gereklilik değil, yalnızca kod organizasyonu için bir gelenektir.
İlerideki komutlar daha fazla dosya ve klasör ekleyecektir:
* `yarn app:generate`, `generated/` klasörünü oluşturur (türlendirilmiş Twenty istemcisi + çalışma alanı türleri).
* `yarn entity:add`, özel nesneleriniz, fonksiyonlarınız, ön bileşenleriniz veya rolleriniz için `src/` altında varlık tanım dosyaları ekler.
* `yarn twenty app:dev`, `node_modules/twenty-sdk/generated` içinde tipli bir API istemcisini otomatik olarak oluşturur (tipli Twenty istemcisi + çalışma alanı türleri).
* `yarn twenty entity:add`, özel nesneleriniz, fonksiyonlarınız, ön bileşenleriniz veya rolleriniz için `src/` altında varlık tanım dosyaları ekler.
## Kimlik Doğrulama
`yarn auth:login` komutunu ilk kez çalıştırdığınızda, sizden şunlar istenir:
`yarn twenty auth:login` komutunu ilk kez çalıştırdığınızda, sizden şunlar istenir:
* API URL’si (varsayılan: http://localhost:3000 veya mevcut çalışma alanı profiliniz)
* API anahtarı
@@ -157,26 +183,26 @@ Kimlik bilgileriniz kullanıcı başına `~/.twenty/config.json` içinde saklan
# Yapılandırılmış tüm çalışma alanlarını listeleyin
yarn twenty auth:list
# Switch the default workspace (interactive)
yarn auth:switch
# Varsayılan çalışma alanını değiştirin (etkileşimli)
yarn twenty auth:switch
# Switch to a specific workspace
yarn auth:switch production
# Belirli bir çalışma alanına geçin
yarn twenty auth:switch production
# Check current authentication status
yarn auth:status
# Mevcut kimlik doğrulama durumunu kontrol edin
yarn twenty auth:status
```
Once you've switched workspaces with `auth:switch`, all subsequent commands will use that workspace by default. You can still override it temporarily with `--workspace <name>`.
`yarn twenty auth:switch` ile çalışma alanlarını değiştirdikten sonra, sonraki tüm komutlar varsayılan olarak o çalışma alanını kullanacaktır. You can still override it temporarily with `--workspace <name>`.
## SDK kaynaklarını kullanın (türler ve yapılandırma)
@@ -186,14 +212,16 @@ twenty-sdk, uygulamanız içinde kullandığınız türlendirilmiş yapı taşla
SDK, uygulama varlıklarınızı tanımlamak için yardımcı fonksiyonlar sağlar. [Varlık algılama](#entity-detection) bölümünde açıklandığı gibi, varlıklarınızın algılanması için `export default define<Entity>({...})` kullanmalısınız:
* `universalIdentifier` dağıtımlar arasında benzersiz ve kararlı olmalıdır.
* Her alan bir `name`, `type`, `label` ve kendi kararlı `universalIdentifier` değerini gerektirir.
* `fields` dizisi isteğe bağlıdır — özel alanlar olmadan da nesneler tanımlayabilirsiniz.
* `yarn entity:add` kullanarak, adlandırma, alanlar ve ilişkiler konusunda sizi yönlendirerek yeni nesneler oluşturabilirsiniz.
* `yarn twenty entity:add` kullanarak, adlandırma, alanlar ve ilişkiler konusunda sizi yönlendirerek yeni nesneler oluşturabilirsiniz.
<Note>
**Temel alanlar otomatik olarak oluşturulur.** Özel bir nesne tanımladığınızda Twenty, `name`, `createdAt`, `updatedAt`, `createdBy`, `position` ve `deletedAt` gibi standart alanları otomatik olarak ekler. Bunları `fields` dizinizde tanımlamanız gerekmez — yalnızca özel alanlarınızı ekleyin.
**Temel alanlar otomatik olarak oluşturulur.** Özel bir nesne tanımladığınızda Twenty, standart alanları otomatik olarak ekler
örneğin `id`, `name`, `createdAt`, `updatedAt`, `createdBy`, `updatedBy` ve `deletedAt`.
Bunları `fields` dizinizde tanımlamanız gerekmez — yalnızca özel alanlarınızı ekleyin.
`fields` dizinizde aynı ada sahip bir alan tanımlayarak varsayılan alanları geçersiz kılabilirsiniz,
ancak bu önerilmez.
</Note>
### Uygulama yapılandırması (application-config.ts)
@@ -289,6 +321,7 @@ Her uygulamanın aşağıdakileri açıklayan tek bir `application-config.ts` do
* **Uygulamanın kim olduğu**: tanımlayıcılar, görünen ad ve açıklama.
* **Fonksiyonlarının nasıl çalıştığı**: izinler için hangi rolü kullandıkları.
* `universalIdentifier` alanları size ait belirleyici kimliklerdir; bunları bir kez oluşturun ve eşitlemeler boyunca kararlı tutun.
* `applicationVariables`, fonksiyonlarınız için ortam değişkenlerine dönüşür (örneğin, `DEFAULT_RECIPIENT_NAME` değeri `process.env.DEFAULT_RECIPIENT_NAME` olarak kullanılabilir).
* `defaultRoleUniversalIdentifier`, rol dosyasıyla eşleşmelidir (aşağıya bakın).
* `postInstallLogicFunctionUniversalIdentifier` (isteğe bağlı), uygulama yüklendikten sonra otomatik olarak çalışan bir mantık işlevine işaret eder. Bkz. [Kurulum sonrası işlevler](#post-install-functions).
#### Roller ve izinler
@@ -457,6 +493,55 @@ Notlar:
* `triggers` dizisi isteğe bağlıdır. Tetikleyicisi olmayan fonksiyonlar, diğer fonksiyonlar tarafından çağrılan yardımcı fonksiyonlar olarak kullanılabilir.
* Tek bir fonksiyonda birden çok tetikleyici türünü birleştirebilirsiniz.
### Kurulum sonrası işlevler
Kurulum sonrası işlev, uygulamanız bir çalışma alanına yüklendikten sonra otomatik olarak çalışan bir mantık işlevidir. Bu, varsayılan verileri tohumlama, ilk kayıtları oluşturma veya çalışma alanı ayarlarını yapılandırma gibi tek seferlik kurulum görevleri için yararlıdır.
`create-twenty-app` ile yeni bir uygulama iskeleti oluşturduğunuzda, `src/logic-functions/post-install.ts` konumunda sizin için bir kurulum sonrası işlevi oluşturulur:
Ayrıca kurulum sonrası işlevi istediğiniz zaman CLI kullanarak manuel olarak çalıştırabilirsiniz:
```bash filename="Terminal"
yarn twenty function:execute --postInstall
```
Önemli noktalar:
* Kurulum sonrası işlevleri standart mantık işlevleridir — diğer herhangi bir işlev gibi `defineLogicFunction()` kullanırlar.
* `defineApplication()` içindeki `postInstallLogicFunctionUniversalIdentifier` alanı isteğe bağlıdır. Atlanırsa, kurulumdan sonra hiçbir işlev çalıştırılmaz.
* Varsayılan zaman aşımı, veri tohumlama gibi daha uzun kurulum görevlerine izin vermek için 300 saniye (5 dakika) olarak ayarlanmıştır.
* Kurulum sonrası işlevlerin tetikleyicilere ihtiyacı yoktur — kurulum sırasında platform tarafından veya `function:execute --postInstall` aracılığıyla manuel olarak çağrılırlar.
Yeni fonksiyonları iki şekilde oluşturabilirsiniz:
* **Şablondan**: `yarn entity:add` çalıştırın ve yeni bir mantık fonksiyonu ekleme seçeneğini seçin. Bu, bir işleyici ve yapılandırma içeren bir başlangıç dosyası oluşturur.
* **Şablondan**: `yarn twenty entity:add` çalıştırın ve yeni bir mantık fonksiyonu ekleme seçeneğini seçin. Bu, bir işleyici ve yapılandırma içeren bir başlangıç dosyası oluşturur.
* **Manuel**: Yeni bir `*.logic-function.ts` dosyası oluşturun ve aynı deseni izleyerek `defineLogicFunction()` kullanın.
### Bir mantık işlevini araç olarak işaretleme
Mantık işlevleri, yapay zeka ajanları ve iş akışları için **araçlar** olarak sunulabilir. Bir işlev bir araç olarak işaretlendiğinde, Twenty'nin yapay zeka özellikleri tarafından keşfedilebilir hâle gelir ve iş akışı otomasyonlarında bir adım olarak seçilebilir.
Bir mantık işlevini bir araç olarak işaretlemek için `isTool: true` olarak ayarlayın ve beklenen giriş parametrelerini açıklayan bir `toolInputSchema`yı [JSON Şeması](https://json-schema.org/) kullanarak sağlayın:
description: 'Enrich a company record with external data',
timeoutSeconds: 10,
handler,
isTool: true,
toolInputSchema: {
type: 'object',
properties: {
companyName: {
type: 'string',
description: 'The name of the company to enrich',
},
domain: {
type: 'string',
description: 'The company website domain (optional)',
},
},
required: ['companyName'],
},
});
```
Önemli noktalar:
* **`isTool`** (`boolean`, varsayılan: `false`): `true` olarak ayarlandığında, işlev bir araç olarak kaydedilir ve AI ajanları ile iş akışı otomasyonları tarafından kullanılabilir hale gelir.
* **`toolInputSchema`** (`object`, isteğe bağlı): İşlevinizin kabul ettiği parametreleri tanımlayan bir JSON Schema nesnesi. AI ajanları, aracın hangi girdileri beklediğini anlamak ve çağrıları doğrulamak için bu şemayı kullanır. Atlanırsa, şema varsayılan olarak `{ type: 'object', properties: {} }` olur (parametre yok).
* `isTool: false` (veya ayarlanmamış) olan işlevler araç olarak **sunulmaz**. Yine de doğrudan yürütülebilir veya diğer işlevler tarafından çağrılabilirler, ancak araç keşfinde görünmezler.
* **Araç adlandırma**: Bir araç olarak sunulduğunda, işlev adı otomatik olarak `logic_function_<name>` biçimine dönüştürülür (küçük harfe çevrilir, alfasayısal olmayan karakterler alt çizgi ile değiştirilir). Örneğin, `enrich-company` `logic_function_enrich_company` haline gelir.
* `isTool` özelliğini tetikleyicilerle birleştirebilirsiniz — bir işlev aynı anda hem bir araç (AI ajanları tarafından çağrılabilir) olabilir hem de olaylar tarafından tetiklenebilir (cron, veritabanı olayları, routes).
<Note>
**İyi bir `description` yazın.** AI ajanları, aracı ne zaman kullanacaklarına karar vermek için işlevin `description` alanına güvenir. Aracın ne yaptığını ve ne zaman çağrılması gerektiğini açıkça belirtin.
</Note>
### Ön uç bileşenleri
Ön uç bileşenleri, Twenty'nin kullanıcı arayüzünde görüntülenen özel React bileşenleri oluşturmanıza olanak tanır. Yerleşik doğrulamayla bileşenleri tanımlamak için `defineFrontComponent()` kullanın:
* Ön uç bileşenleri, Twenty içinde yalıtılmış bağlamlarda görüntülenen React bileşenleridir.
* Otomatik algılama için `*.front-component.tsx` dosya soneğini kullanın.
* `component` alanı, React bileşeninize referans verir.
* Bileşenler, `yarn app:dev` sırasında otomatik olarak oluşturulur ve senkronize edilir.
* Bileşenler, `yarn twenty app:dev` sırasında otomatik olarak oluşturulur ve senkronize edilir.
Yeni ön uç bileşenlerini iki şekilde oluşturabilirsiniz:
* **Şablondan**: `yarn entity:add` çalıştırın ve yeni bir ön uç bileşeni ekleme seçeneğini seçin.
* **Şablondan**: `yarn twenty entity:add` çalıştırın ve yeni bir ön uç bileşeni ekleme seçeneğini seçin.
* **Manuel**: Yeni bir `*.front-component.tsx` dosyası oluşturun ve `defineFrontComponent()` kullanın.
### Oluşturulmuş türlendirilmiş istemci
Çalışma alanı şemanıza göre generated/ içinde yerel bir türlendirilmiş istemci oluşturmak için yarn app:generate çalıştırın. Fonksiyonlarınızda kullanın:
Tipli istemci, `yarn twenty app:dev` tarafından otomatik olarak oluşturulur ve çalışma alanı şemanıza göre `node_modules/twenty-sdk/generated` içine kaydedilir. Fonksiyonlarınızda kullanın:
İstemci `yarn app:generate` tarafından yeniden oluşturulur. Nesnelerinizi değiştirdikten sonra veya yeni bir çalışma alanına katılırken yeniden çalıştırın.
Nesneleriniz veya alanlarınız değiştiğinde, istemci `yarn twenty app:dev` tarafından otomatik olarak yeniden oluşturulur.
#### Mantık fonksiyonlarında çalışma zamanı kimlik bilgileri
@@ -623,40 +773,29 @@ Nesneleri, mantık fonksiyonlarını, ön uç bileşenlerini ve birden çok teti
## Manuel kurulum (scaffolder olmadan)
En iyi başlangıç deneyimi için `create-twenty-app` kullanmanızı önersek de, bir projeyi manuel olarak da kurabilirsiniz. CLI'yi global olarak kurmayın. Bunun yerine `twenty-sdk`'yi yerel bir bağımlılık olarak ekleyin ve package.json içinde betikleri bağlayın:
En iyi başlangıç deneyimi için `create-twenty-app` kullanmanızı önersek de, bir projeyi manuel olarak da kurabilirsiniz. CLI'yi global olarak kurmayın. Bunun yerine `twenty-sdk`'yi yerel bir bağımlılık olarak ekleyin ve package.json içinde tek bir betik tanımlayın:
```bash filename="Terminal"
yarn add -D twenty-sdk
```
Ardından şu gibi betikler ekleyin:
Ardından bir `twenty` betiği ekleyin:
```json filename="package.json"
{
"scripts": {
"auth:login": "twenty auth:login",
"auth:logout": "twenty auth:logout",
"auth:status": "twenty auth:status",
"auth:switch": "twenty auth:switch",
"auth:list": "twenty auth:list",
"app:dev": "twenty app:dev",
"app:generate": "twenty app:generate",
"app:uninstall": "twenty app:uninstall",
"entity:add": "twenty entity:add",
"function:logs": "twenty function:logs",
"function:execute": "twenty function:execute",
"help": "twenty help"
"twenty": "twenty"
}
}
```
Artık aynı komutlarıYarn üzerinden çalıştırabilirsiniz; örn. `yarn app:dev`, `yarn app:generate` vb.
Artık tüm komutları`yarn twenty <command>` üzerinden çalıştırabilirsiniz; örn. `yarn twenty app:dev`, `yarn twenty help` vb.
## Sorun Giderme
* Kimlik doğrulama hataları: `yarn auth:login` çalıştırın ve API anahtarınızın gerekli izinlere sahip olduğundan emin olun.
* Kimlik doğrulama hataları: `yarn twenty auth:login` çalıştırın ve API anahtarınızın gerekli izinlere sahip olduğundan emin olun.
* Sunucuya bağlanılamıyor: API URL’sini ve Twenty sunucusunun erişilebilir olduğunu doğrulayın.
* Türler veya istemci eksik/eski: `yarn app:generate` çalıştırın.
* Geliştirme modu eşitlenmiyor: `yarn app:dev`'in çalıştığından ve değişikliklerin ortamınız tarafından yok sayılmadığından emin olun.
* Türler veya istemci eksik/eski: `yarn twenty app:dev` komutunu yeniden çalıştırın — tip tanımlı istemciyi otomatik olarak oluşturur.
* Geliştirme modu eşitlenmiyor: `yarn twenty app:dev`'in çalıştığından ve değişikliklerin ortamınız tarafından yok sayılmadığından emin olun.
Discord Yardım Kanalı: https://discord.com/channels/1130383047699738754/1130386664812982322
* Generates core files (application config, default function role, post-install function) plus example files based on the scaffolding mode
一个新生成的脚手架应用如下所示:
A freshly scaffolded app with the default `--exhaustive` mode looks like this:
```text filename="my-twenty-app/"
my-twenty-app/
@@ -89,20 +102,31 @@ my-twenty-app/
eslint.config.mjs
tsconfig.json
README.md
public/ # 公共资源文件夹(图像、字体等)
public/ # Public assets folder (images, fonts, etc.)
src/
├── application-config.ts # 必需 - 主应用程序配置
├── application-config.ts # Required - main application configuration
├── roles/
│ └── default-role.ts # 用于逻辑函数的默认角色
│ └── default-role.ts # Default role for logic functions
├── objects/
│ └── example-object.ts # Example custom object definition
├── fields/
│ └── example-field.ts # Example standalone field definition
├── logic-functions/
│ └── hello-world.ts # 示例逻辑函数
└── front-components/
└── hello-world.tsx # 示例前端组件
│ ├── hello-world.ts # Example logic function
│ └── post-install.ts # Post-install logic function
├── front-components/
│ └── hello-world.tsx # Example front component
├── views/
│ └── example-view.ts # Example saved view definition
└── navigation-menu-items/
└── example-navigation-menu-item.ts # Example sidebar navigation link
```
With `--minimal`, only the core files are created (`application-config.ts`, `roles/default-role.ts`, and `logic-functions/post-install.ts`). With `--interactive`, you choose which example files to include.
'REST API endpoints should have authentication guards (UserAuthGuard, WorkspaceAuthGuard, FilePathGuard, or FilesFieldGuard) or be explicitly marked as public (PublicEndpointGuard) and permission guards (SettingsPermissionsGuard or CustomPermissionGuard) to maintain our security model.',
'REST API endpoints should have authentication guards (UserAuthGuard, WorkspaceAuthGuard, FilePathGuard, FileByIdGuard) or be explicitly marked as public (PublicEndpointGuard) and permission guards (SettingsPermissionsGuard or CustomPermissionGuard) to maintain our security model.',
},
messages:{
restApiMethodsShouldBeGuarded:
'All REST API controller endpoints must have authentication guards (@UseGuards(UserAuthGuard/WorkspaceAuthGuard/FilePathGuard/FileIdGuard/FilesFieldGuard/PublicEndpointGuard)) and permission guards (@UseGuards(..., SettingsPermissionsGuard(PermissionFlagType.XXX)), CustomPermissionGuard for custom logic, or NoPermissionGuard for special cases).',
'All REST API controller endpoints must have authentication guards (@UseGuards(UserAuthGuard/WorkspaceAuthGuard/FilePathGuard/FileByIdGuard/PublicEndpointGuard)) and permission guards (@UseGuards(..., SettingsPermissionsGuard(PermissionFlagType.XXX)), CustomPermissionGuard for custom logic, or NoPermissionGuard for special cases).',
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
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.