Commit Graph

55 Commits

Author SHA1 Message Date
Charles Bochet a121d00ddd feat: add color property to ObjectMetadata for object icon customization (#18672)
## Summary

- Adds a `color` column to `ObjectMetadataEntity` with full GraphQL
support so object icon colors are persisted at the metadata level
- Adds a `type` column to `NavigationMenuItemEntity` (enum: `OBJECT`,
`VIEW`, `FOLDER`, `LINK`, `RECORD`) replacing field-based type inference
- Updates frontend to read object colors from `objectMetadata.color`
(falling back to standard defaults) in the sidebar nav, record index
header, and record show breadcrumb
- Simplifies `NavigationMenuItemIcon` color resolution via
`getEffectiveNavigationMenuItemColor` util

## Color rules

| Item type | Color source | Editable in sidebar? |
|-----------|-------------|---------------------|
| **Object** | `objectMetadata.color` | Yes — persisted to
`objectMetadata.color` on Save |
| **Folder** | `navigationMenuItem.color` | Yes |
| **Link** | Fixed default (`DEFAULT_NAVIGATION_MENU_ITEM_COLOR_LINK`) |
No |
| **View** | `objectMetadata.color` (from the parent object) | No |
| **Record** | None | No |

- **Object** items represent the whole object (e.g. "Companies") and
point to the INDEX view. Changing their color updates
`objectMetadata.color` via `useSaveObjectMetadataColorsFromDraft`.
- **View** items represent specific non-INDEX views. Their color comes
from the parent object's metadata (read-only).
- Only **folders** store their color on `navigationMenuItem.color` —
enforced by `hasNavigationMenuItemOwnColor` util.
- `getEffectiveNavigationMenuItemColor` returns `objectColor` for both
OBJECT and VIEW items, folder's own color for folders, and the fixed
default for links.

## NavigationMenuItemType enum

- Shared enum created in `twenty-shared` with values: `OBJECT`, `VIEW`,
`FOLDER`, `LINK`, `RECORD`
- Registered as a GraphQL enum on the backend
- Replaces string literals across entity, DTOs, input, converters, and
frontend hooks
- Migration backfills existing rows: INDEX views → `OBJECT`, non-INDEX
views → `VIEW`, based on join with the view table

## Design decisions

- **OBJECT vs VIEW distinction**: Items pointing to INDEX views are
typed as `OBJECT` (represent the whole object, color editable). Items
pointing to non-INDEX views are typed as `VIEW` (specific view, color
read-only from parent object).
- **Dual color storage**: `navigationMenuItem.color` is preserved for
folders only. Objects use `objectMetadata.color` as their source of
truth.
- **Type discriminator**: The `type` column replaces field-based
inference (checking `viewId`, `link`, `targetRecordId` presence) with an
explicit enum, simplifying `isNavigationMenuItemLink` /
`isNavigationMenuItemFolder` to simple `item.type ===` checks.
- **No settings page color picker**: Object color editing is done from
the sidebar edit panel, not the data model settings page.

## Test plan

- [ ] Verify objects display their default standard colors in the
sidebar
- [ ] Verify object color editing works in the sidebar edit panel
(persists to objectMetadata.color)
- [ ] Verify folder color editing works in the sidebar edit panel
- [ ] Verify views, links, and records do NOT show a color picker in the
sidebar edit panel
- [ ] Run `npx nx typecheck twenty-front` and `npx nx typecheck
twenty-server`
- [ ] Verify the database migrations add `color` to `objectMetadata` and
`type` to `navigationMenuItem`


Made with [Cursor](https://cursor.com)
2026-03-16 23:54:56 +01:00
Félix Malfait 621962e049 Move fixture apps from twenty-sdk to twenty-apps/fixtures (#18531)
## Summary

- Move 4 test fixture apps from `twenty-sdk/src/cli/__tests__/apps/` to
`twenty-apps/fixtures/` with meaningful names (`rich-app` →
`postcard-app`, `root-app` → `minimal-app`)
- Replace all `from '@/sdk'` imports with `from 'twenty-sdk'` so fixture
apps are proper, portable twenty-sdk apps
- Remove the fragile `"@/*": ["../../../../../src/*"]` tsconfig hack and
replace with standard `"src/*": ["./src/*"]` paths
- Create a centralized `fixture-paths.ts` utility in twenty-sdk tests
for clean app path resolution

## Why

The fixture apps were deeply nested in twenty-sdk's test directory and
tightly coupled to its internal source layout via a tsconfig path alias
hack. This made them:
- Impossible to reuse outside of SDK CLI tests (e.g., for server-side
dev seeding with `DevSeederService`)
- Fragile — moving any twenty-sdk source file could break the path alias
- Poorly discoverable — buried 5 directories deep in test infrastructure

Moving them to `twenty-apps/fixtures/` makes them first-class portable
apps that can be imported by `twenty-server` for seeding, used in E2E
testing, and serve as canonical examples alongside `hello-world`.

## Test plan

- [x] All 8 twenty-sdk integration tests pass (3 suites: postcard-app,
minimal-app, invalid-app)
- [x] Prettier formatting verified on all changed files
- [ ] CI should confirm E2E tests also pass (these require a running
server)

Made with [Cursor](https://cursor.com)
2026-03-10 17:29:53 +01:00
Paul Rastoin 75bb3a904d [SDK] Refactor clients (#18433)
# Intoduction

Closes https://github.com/twentyhq/core-team-issues/issues/2289

In this PR all the clients becomes available under `twenty-sdk/clients`,
this is a breaking change but generated was too vague and thats still
the now or never best timing to do so

## CoreClient
The core client is now shipped with a default stub empty class for both
the schema and the client
Allowing its import, will still raises typescript errors when consumed
as generated but not generated

## MetadataClient
The metadata client is workspace agnostic, it's now generated and
commited in the repo. added a ci that prevents any schema desync due to
twenty-server additions

Same behavior than for the twenty-front generated graphql schema
2026-03-09 15:32:13 +00:00
Paul Rastoin 06bdb5ad6a [SDK] Agent in manifest (#18431)
# Introduction
Adding agent in the manifest, required for twenty standard app
extraction out of twenty-server
2026-03-09 11:10:14 +00:00
Félix Malfait 66d93c4d28 Fix app:dev CLI by removing deleted createOneApplication mutation (#18460)
## Summary
- The `createOneApplication` GraphQL mutation was removed from the
server during the application architecture refactor (#18432), but the
SDK CLI (`app:dev`, `app:build --sync`) still called it, causing
failures.
- Simplified the SDK to use `syncApplication` (which now internally
creates the `ApplicationEntity` via `ensureApplicationExists`) instead
of a separate create step.
- On first run (clean install), the orchestrator now runs an initial
sync before initializing the file uploader, so file uploads can proceed
(they require the `ApplicationEntity` to exist).

## Test plan
- [x] Typecheck passes for both `twenty-sdk` and `twenty-server`
- [x] `app:dev` tested locally with existing app (finds app, uploads,
syncs)
- [x] `app:dev` tested locally after `app:uninstall` (creates app via
sync, uploads, syncs)
- [x] SDK unit tests pass (23/26 files, 3 pre-existing failures
unrelated)

Made with [Cursor](https://cursor.com)
2026-03-06 18:37:54 +01:00
martmull 403db7ad3f Add default viewField when creating object (#18441)
as title
2026-03-06 14:59:31 +01:00
Paul Rastoin 57d8954973 [SDK] Pure ESM (#18427)
# Introduction
While testing the sdk and overall apps in
https://github.com/prastoin/twenty-app-hello-world
Faced a lot of pure `CJS` external dependencies import issue

Replaced all the cjs deps to either esm equivalent or node native
replacement
2026-03-05 17:19:01 +01:00
Félix Malfait 0e89c96170 feat: add npm and tarball app distribution with upgrade mechanism (#18358)
## Summary

- **npm + tarball app distribution**: Apps can be installed from the npm
registry (public or private) or uploaded as `.tar.gz` tarballs, with
`AppRegistrationSourceType` tracking the origin
- **Upgrade mechanism**: `AppUpgradeService` checks for newer versions,
supports rollback for npm-sourced apps, and a cron job runs every 6
hours to update `latestAvailableVersion` on registrations
- **Security hardening**: Tarball extraction uses path traversal
protection, and `enableScripts: false` in `.yarnrc.yml` disables all
lifecycle scripts during `yarn install` to prevent RCE
- **Frontend**: "Install from npm" and "Upload tarball" modals, upgrade
button on app detail page, blue "Update" badge on installed apps table
when a newer version is available
- **Marketplace catalog sync**: Hourly cron job syncs a hardcoded
catalog index into `ApplicationRegistration` entities
- **Integration tests**: Coverage for install, upgrade, tarball upload,
and catalog sync flows

## Backend changes

| Area | Files |
|------|-------|
| Entity & migration | `ApplicationRegistrationEntity` (sourceType,
sourcePackage, latestAvailableVersion), `ApplicationEntity`
(applicationRegistrationId), migration |
| Services | `AppPackageResolverService`, `ApplicationInstallService`,
`AppUpgradeService`, `MarketplaceCatalogSyncService` |
| Cron jobs | `MarketplaceCatalogSyncCronJob` (hourly),
`AppVersionCheckCronJob` (every 6h) |
| REST endpoint | `AppRegistrationUploadController` — tarball upload
with secure extraction |
| Resolver | `MarketplaceResolver` — simplified `installMarketplaceApp`
(removed redundant `sourcePackage` arg) |
| Security | `.yarnrc.yml` — `enableScripts: false` to block postinstall
RCE |

## Frontend changes

| Area | Files |
|------|-------|
| Modals | `SettingsInstallNpmAppModal`, `SettingsUploadTarballModal`,
`SettingsAppModalLayout` |
| Hooks | `useUploadAppTarball`, `useInstallMarketplaceApp` (cleaned up)
|
| Upgrade UI | `SettingsApplicationVersionContainer`,
`SettingsApplicationDetailAboutTab` |
| Badge | `SettingsApplicationTableRow` — blue "Update" tag,
`SettingsApplicationsInstalledTab` — fetches registrations for version
comparison |
| Styling | Migrated to Linaria (matching main) |

## Test plan

- [ ] Install an app from npm via the "Install from npm" modal
- [ ] Upload a `.tar.gz` tarball via the "Upload tarball" modal
- [ ] Verify upgrade badge appears when `latestAvailableVersion >
version`
- [ ] Verify upgrade flow from app detail page
- [ ] Run integration tests: `app-distribution.integration-spec.ts`,
`marketplace-catalog-sync.integration-spec.ts`
- [ ] Verify `enableScripts: false` blocks postinstall scripts during
yarn install


Made with [Cursor](https://cursor.com)
2026-03-05 10:34:08 +01:00
Paul Rastoin 005223de8c [SDK] Make public-operations non throw (#18343)
Followup https://github.com/twentyhq/twenty/pull/18320
2026-03-03 14:04:13 +01:00
Paul Rastoin 2f09fb8c04 SDK Split command and cli logic (#18320)
# Introduction

Allow a consumer call the commands programmatically instead of passing
by the exec
To do so extract from the command definition all the core logic, created
a new error api that allow keeping same error logs granularity than
before

## Usage
```ts
import { authLogin, appUninstall, functionExecute } from 'twenty-sdk/cli';

const result = await authLogin({
  apiKey: 'my-key',
  apiUrl: 'https://my-twenty.com',
});

if (!result.success) {
  throw new Error(result.error);
}
```

## `app:build`
Introduced a new command that will allow building the whole project
without any watch setup
- Build and validate manifest
- Get or create app
- Synchronize manifest with twenty-sdk stub and no typecheck
- generate client
- Run typecheck
- Synchronize manifest again
2026-03-03 12:24:49 +01:00
Félix Malfait 012d819557 OAuth Client — Unified ApplicationRegistration, OAuth server, and frontend (#18267)
## Summary

Consolidates three separate PRs (#18260, #18261, #18262) into a single
unified branch with all review feedback addressed:

### New features
- **ApplicationRegistration entity** — server-level registration for
OAuth apps with encrypted server variables
- **OAuth 2.0 server** — authorization code, client credentials, refresh
token grants with PKCE support
- **OAuth discovery endpoint** —
`.well-known/oauth-authorization-server` metadata
- **Frontend UI** — app registration details page with credential
management, redirect URI editing, and server variable configuration
- **CLI integration** — `twenty dev` auto-registers apps and stores
OAuth credentials locally
- **Authorize consent screen** — OAuth consent page at `/authorize`
showing requested scopes

### Review feedback addressed

**Renames (PR #18260):**
- `appRegistration` → `applicationRegistration` (entity, tables, files,
imports, GraphQL types)
- `appRegistrationVariable` → `applicationRegistrationVariable`
- `clientId` → `oAuthClientId`, `clientSecretHash` →
`oAuthClientSecretHash`, `redirectUris` → `oAuthRedirectUris`, `scopes`
→ `oAuthScopes`

**Security fixes (PR #18261):**
- Fixed redirect URI validation bypass when `oAuthRedirectUris` is an
empty array
- Fixed workspace isolation in `clientCredentialsGrant` — now uses
`find()` with explicit handling for multiple installations
- Added error logging in refresh token `catch` block instead of silently
swallowing

**Code quality (PR #18262):**
- Split `VersionDistributionEntry` into its own file (one export per
file)
- Split GraphQL queries and mutations into individual files with a
shared fragment
- Removed unused `OAuth` entry from `AuthProviderEnum`
- Added loading state to `handleRotateSecret`
- Removed 27 narration-style comments from test files
- Added proper guards (`PublicEndpointGuard`, `NoPermissionGuard`) to
controllers and resolvers

## Test plan

- [ ] Verify `twenty dev` registers an app and stores OAuth credentials
- [ ] Test OAuth authorization code flow end-to-end (authorize → token →
API call)
- [ ] Test client credentials grant
- [ ] Verify redirect URI validation rejects requests when no URIs are
registered
- [ ] Verify app registration detail page renders correctly
- [ ] Test secret rotation with loading state
- [ ] Verify server variable editing and saving
- [ ] Run `npx nx database:reset twenty-server` to validate migration

Closes #18260, #18261, #18262


Made with [Cursor](https://cursor.com)

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
2026-02-28 14:07:49 +01:00
Charles Bochet 0d4fe4575b Various SDK improvements (#18115)
## Summary

- **Refactor frontend metadata loading architecture**: Split the
monolithic `EagerMetadataLoadEffect` into focused provider effects
(`UserMetadataProviderEffect`, `ObjectMetadataProviderEffect`,
`ViewMetadataProviderEffect`) orchestrated by `MetadataProviderEffects`.
Replaced `UserProvider` + `ObjectMetadataItemsProvider` with a single
`MetadataGater` that gates rendering on `isAppMetadataReadyState`. The
metadata store now validates view-object consistency before promoting
views, and `updateDraft` skips no-op updates via deep equality checks.

- **SDK CLI improvements**: Added `app:typecheck` command, improved
error handling in API sync (extracts GraphQL error messages), added
`serializeError` utility for human-readable error output, added `error`
file status to dev mode orchestrator with UI support, and fixed
ClickHouse migration/seed commands to use `transpile-only`.
2026-02-23 19:57:02 +01:00
Thomas Trompette 932adf8e4b Create view and navigation item on add-object command - to be tested (#18134)
<img width="580" height="141" alt="Capture d’écran 2026-02-20 à 15 52
11"
src="https://github.com/user-attachments/assets/40254d3a-f7f9-4f2a-a51f-c37dc1f5d167"
/>
2026-02-20 16:41:16 +00:00
Paul Rastoin 175df59c21 Support Skill in manifest (#18092)
# Introduction
Support skill in manifest, pre-requisite for the twenty standard app
migration
2026-02-20 11:45:42 +01:00
martmull 2cc3c75c7e Add example in create-twenty-app (#18043)
- add interactive mode to create-twenty-app
- by default create an example for each entities

<img width="1181" height="168" alt="image"
src="https://github.com/user-attachments/assets/a2490d8f-66a1-4cd5-bf41-57166cc20a1e"
/>
2026-02-18 18:04:19 +00:00
Charles Bochet c3781e87cc Sync page Layout (#18034)
## 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
2026-02-18 17:55:04 +01:00
martmull 53c314d0fa 2094 extensibility define postinstall orand preinstall function to run in application (#18037)
- add a new optional key `postInstallLogicFunctionUniversalIdentifier`
in applicationConfig
- seed postInstall function in create-twenty-app
- update execute:function options
- update doc
2026-02-18 15:38:22 +00:00
Charles Bochet c0cc0689d6 Add Client Api generation (#17961)
## 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.
2026-02-17 18:45:52 +01:00
martmull 52fe21c04b Fix ci + improvements (#17795)
as title
2026-02-10 11:48:10 +01:00
martmull 9162685b2e Reorganize logic function files (#17766)
reorganize according to

<img width="1243" height="725" alt="Pasted Graphic"
src="https://github.com/user-attachments/assets/ba65dd10-8eec-4b13-ad49-9726edd3b79c"
/>

Not working yet
2026-02-09 12:36:39 +01:00
martmull 65678ed99f Upload files instead ofsources (#17608) 2026-02-03 12:11:10 +01:00
martmull f46da3eefd Update manifest structure (#17547)
Move all sync entities in an `entities` key. Rename functions to
logicFunctions

```json
{
  application: {
    ...
  },
  entities: {
    objects: [],
    logicFunctions: [],
    ...
  }
}
```
2026-01-30 16:26:45 +01:00
martmull 3412992e99 2162 Add asset watcher in twenty-sdk dev mode (#17513)
- assets are pushed in .twenty/output
- assets are uploaded in FileFolder.Assets
- not handled yet by the sync-manifest endpoint
2026-01-29 09:08:44 +00:00
Charles Bochet da6f1bbef3 Rename serverlessFunction to logicFunction (#17494)
## Summary

Rename "Serverless Function" to "Logic Function" across the codebase for
clearer naming.

### Environment Variable Changes

| Old | New |
|-----|-----|
| `SERVERLESS_TYPE` | `LOGIC_FUNCTION_TYPE` |
| `SERVERLESS_LAMBDA_REGION` | `LOGIC_FUNCTION_LAMBDA_REGION` |
| `SERVERLESS_LAMBDA_ROLE` | `LOGIC_FUNCTION_LAMBDA_ROLE` |
| `SERVERLESS_LAMBDA_SUBHOSTING_URL` |
`LOGIC_FUNCTION_LAMBDA_SUBHOSTING_URL` |
| `SERVERLESS_LAMBDA_ACCESS_KEY_ID` |
`LOGIC_FUNCTION_LAMBDA_ACCESS_KEY_ID` |
| `SERVERLESS_LAMBDA_SECRET_ACCESS_KEY` |
`LOGIC_FUNCTION_LAMBDA_SECRET_ACCESS_KEY` |

### Breaking Changes

- Environment variables must be updated in production deployments
- Database migration renames `serverlessFunction` → `logicFunction`
tables
2026-01-28 01:42:19 +01:00
martmull b9586769b9 2081 extensibility publish cli tools and update doc with recent changes (#17495)
- increase to 0.4.0
- update READMEs and doc
2026-01-27 20:49:33 +00:00
martmull f4ca69a474 Implement dev mode nice UI (#17471)
Implement a nice terminal UI for dev mode using INK

<img width="1512" height="721" alt="image"
src="https://github.com/user-attachments/assets/79a71f37-1b31-4761-9e8d-718ef029ceb8"
/>
2026-01-27 15:34:28 +00:00
martmull 41d470e687 Implement sync in dev mode (#17405)
implement orchestrator to sync application in dev mode

Log example when starting dev mode, delete and add back functions

```bash
👩‍💻 Workspace - default
[init] 🚀 Starting Twenty Application Development Mode
[init] 📁 App Path: /Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto

[dev-mode] File changed: /Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/.gitignore
[dev-mode] File changed: /Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/.nvmrc
[dev-mode] File changed: /Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/.yarnrc.yml
[dev-mode] File changed: /Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/README.md
[dev-mode] File changed: /Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/eslint.config.mjs
[dev-mode] File changed: /Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/package.json
[dev-mode] File changed: /Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/tsconfig.json
[dev-mode] File changed: /Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/yarn.lock
[dev-mode] File changed: /Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/.yarn/install-state.gz
[dev-mode] File changed: /Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/src/ooo.front-component.tsx
[dev-mode] File changed: /Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/src/tata.object.ts
[dev-mode] File changed: /Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/src/app/application.config.ts
[dev-mode] File changed: /Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/src/app/default-function.role.ts
[dev-mode] File changed: /Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/src/app/hello-world-2.function.ts
[dev-mode] File changed: /Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/src/app/hello-world-3.function.ts
[dev-mode] File changed: /Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/src/app/hello-world.front-component.tsx
[dev-mode] File changed: /Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/src/app/hello-world.function.ts
[dev-mode] File changed: /Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/src/app/myObject.object.ts
[dev-mode] File changed: /Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/src/utils/toto.ts
[dev-mode] Building manifest...
[dev-mode] Successfully built manifest
[dev-mode] Syncing...
[dev-mode] ✓ Successfully built src/ooo.front-component.tsx
[dev-mode] Uploading .twenty/output/src/ooo.front-component.mjs...
[dev-mode] ✓ Successfully built src/app/hello-world-2.function.ts
[dev-mode] Uploading .twenty/output/src/app/hello-world-2.function.mjs...
[dev-mode] ✓ Successfully built src/app/hello-world.front-component.tsx
[dev-mode] Uploading .twenty/output/src/app/hello-world.front-component.mjs...
[dev-mode] ✓ Successfully built src/app/hello-world-3.function.ts
[dev-mode] Uploading .twenty/output/src/app/hello-world-3.function.mjs...
[dev-mode] ✓ Successfully built src/app/hello-world.function.ts
[dev-mode] Uploading .twenty/output/src/app/hello-world.function.mjs...
[dev-mode] Successfully uploaded .twenty/output/src/ooo.front-component.mjs
[dev-mode] Successfully uploaded .twenty/output/src/app/hello-world-3.function.mjs
[dev-mode] Successfully uploaded .twenty/output/src/app/hello-world.front-component.mjs
[dev-mode] Successfully uploaded .twenty/output/src/app/hello-world.function.mjs
[dev-mode] Successfully uploaded .twenty/output/src/app/hello-world-2.function.mjs
[dev-mode] ✓ Synced

[dev-mode] ✓ Successfully built src/app/hello-world-2.function.ts
[dev-mode] Uploading .twenty/output/src/app/hello-world-2.function.mjs...
[dev-mode] Successfully uploaded .twenty/output/src/app/hello-world-2.function.mjs
[dev-mode] File changed: /Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/src/app/hello-world-2.function.ts
[dev-mode] Building manifest...
[dev-mode] Successfully built manifest
[dev-mode] Syncing...
[dev-mode] ✓ Synced
[dev-mode] Build failed:
[dev-mode]   Could not resolve "/Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/src/app/hello-world.function.ts"
[dev-mode]   Could not resolve "/Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/src/app/hello-world-3.function.ts"
[dev-mode]   Could not resolve "/Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/src/app/hello-world-2.function.ts"
[dev-mode] File changed: /Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/src/app/hello-world.function.ts
[dev-mode] File changed: /Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/src/app/hello-world-2.function.ts
[dev-mode] File changed: /Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/src/app/hello-world-3.function.ts
[dev-mode] Building manifest...
[dev-mode] ⚠ No functions defined
[dev-mode] Successfully built manifest
[dev-mode] Syncing...
  🗑️  Removed src/app/hello-world-2.function.mjs
  🗑️  Removed src/app/hello-world-3.function.mjs
  🗑️  Removed src/app/hello-world.function.mjs
[dev-mode] ✓ Synced
[dev-mode] File changed: /Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/src/app/hello-world-2.function.ts
[dev-mode] File changed: /Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/src/app/hello-world-3.function.ts
[dev-mode] File changed: /Users/martinmuller/Desktop/twenty/packages/twenty-apps/toto/src/app/hello-world.function.ts
[dev-mode] Building manifest...
[dev-mode] Successfully built manifest
[dev-mode] Syncing...
[dev-mode] ✓ Successfully built src/app/hello-world-2.function.ts
[dev-mode] Uploading .twenty/output/src/app/hello-world-2.function.mjs...
[dev-mode] ✓ Successfully built src/app/hello-world-3.function.ts
[dev-mode] Uploading .twenty/output/src/app/hello-world-3.function.mjs...
[dev-mode] ✓ Successfully built src/app/hello-world.function.ts
[dev-mode] Uploading .twenty/output/src/app/hello-world.function.mjs...
[dev-mode] Successfully uploaded .twenty/output/src/app/hello-world.function.mjs
[dev-mode] Successfully uploaded .twenty/output/src/app/hello-world-2.function.mjs
[dev-mode] Successfully uploaded .twenty/output/src/app/hello-world-3.function.mjs
[dev-mode] ✓ Synced
```
2026-01-26 19:32:13 +00:00
martmull 0091ef5f6c Sync built files (#17379)
as title, upload built files to local storage

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2026-01-23 13:43:53 +01:00
Charles Bochet 210c66b5dd Add checksum to manifest (#17368)
## Refactor app-dev state management and build utilities

- Store only `manifest` in `AppDevState` instead of full
`ManifestBuildResult`; add `sourcePath` to `FileStatus`
- Pass `sourcePaths` directly to watchers instead of
`ManifestBuildResult`
- Only reset `fileUploadStatus` for functions/components when their
source paths change
- Add pure `updateManifestChecksum` utility that returns a new manifest
without side effects
- Extract `processEsbuildResult` to deduplicate build result processing
between watchers
- Rename `serverlessFunctions` → `functions` in SDK code (API unchanged)
- Extract `writeManifestToOutput` to shared `manifest-writer.ts`
2026-01-22 18:16:55 +01:00
Charles Bochet d537d941a7 Add sdk build (#17335)
## Summary

Adds `app:build` command as a one-shot version of `app:dev` - builds
manifest, functions, and front components once then exits (no watching).

**Changes:**
- Added `watch` option to `FunctionsWatcher` and
`FrontComponentsWatcher` to support both watch and one-shot modes
- Created `AppBuildCommand` reusing the same build logic as `app:dev`
with `watch: false`
- Added integration tests for `app:build` on both `rich-app` and
`root-app`
- Updated manifest types: `handlerPath` → `sourceHandlerPath` +
`builtHandlerPath`, `componentPath` → `sourceComponentPath` +
`builtComponentPath`
- Updated test app `package.json` scripts to match `create-twenty-app`
template
2026-01-22 14:36:40 +01:00
Charles Bochet 5a94ef7dbb Move sdk watcher back to esbuild (#17316)
Demo of current state


https://github.com/user-attachments/assets/034aff50-9981-4c81-b5ce-410a07b8dbc9
2026-01-22 13:04:43 +01:00
Charles Bochet 006be18f19 More improvements on SDK watch (#17314)
Refactor manifest build and remove src folder assumptions


- Unified entity builder interface: All entity builders now return
EntityBuildResult<T> with both manifests and filePaths
- Always return build result: runManifestBuild now always returns {
manifest, filePaths } instead of null on failure
- Return all entity paths: EntityFilePaths includes paths for all entity
types (application, objects, functions, etc.)
- Remove src folder assumptions: Applications can now have entities at
root level - removed hasSrcFolder checks
- Simplify watchers: Removed entries caching, compute lazily with map()
- Stabilize tests: Replaced flaky console output snapshots with key
message assertions; replaced inline snapshots with array comparisons
-
2026-01-21 21:49:50 +01:00
Charles Bochet cb4110e894 Enhance tests on SDK (#17312)
![20260121_180621](https://github.com/user-attachments/assets/9284f2b1-6b4e-40fb-abf1-9c981fcb7166)
2026-01-21 19:27:04 +01:00
Charles Bochet 5ee6853d7e Rework SDK watcher (#17305) 2026-01-21 16:18:54 +01:00
Charles Bochet d74d74da4c Improvements on SDK watcher (#17291)
# Improve cross-entity duplicate detection in manifest validation

- Refactored findDuplicates to receive the full manifest, enabling
cross-entity duplicate checks
-ObjectExtensionEntityBuilder now validates that extension field IDs
don't conflict with object field IDs
- Renamed DuplicateId type to EntityIdWithLocation for clarity
- Updated all entity builders to use the new signature
2026-01-21 15:31:38 +01:00
Charles Bochet 351e2030ff Rework watcher (#17284)
Heavy Refactoring of the watcher, sorry about this one, I'll keep
iterating on it.

In a nutshell:
- app-dev.ts is maintaining 3 watchers in parallel: manifest, function
and frontComponent
2026-01-20 17:25:44 +01:00
martmull 579c59bd11 2093 extensibility add twenty auth switch command (#17286)
add auth:switch and auth:list commands
2026-01-20 15:12:59 +00:00
martmull 801878cb2b 2091 extensibility twenty sdk add command twenty app function logs and twenty app function test (#17278)
add `function:logs` and `function:execute` cli commands
2026-01-20 14:10:01 +00:00
Charles Bochet 29c0c952e7 Add Front components to SDK (#17259)
## Add `frontComponent` entity type to SDK

This PR adds a new `frontComponent` entity type at parity with
`serverlessFunction`. Front components are React components that can be
defined and bundled as part of Twenty applications.

### Changes

#### New Entity Type
- Added `FRONT_COMPONENT` to `SyncableEntity` enum
- Front components use `*.front-component.tsx` file naming convention
- CLI command `twenty app:add` now includes `front-component` as an
option

#### SDK Application Layer (`twenty-sdk`)
- Added `defineFrontComponent()` function for defining front component
configurations with validation
- Added `FrontComponentConfig` type for component configuration
- Added `getFrontComponentBaseFile()` template generator for scaffolding
new front components
- Added `loadFrontComponentModule()` to load front component modules and
extract component metadata

#### Shared Types (`twenty-shared`)
- Added `FrontComponentManifest` type with `universalIdentifier`,
`name`, `description`, `componentPath`, and `componentName` fields
- Updated `ApplicationManifest` to include optional `frontComponents`
array

#### Manifest Build System
- Updated `manifest-build.ts` to discover and load
`*.front-component.tsx` files
- Updated `manifest-validate.ts` to validate front components and check
for duplicate IDs
- Updated `manifest-display.ts` to display front component count in
build summary
- Updated `manifest-plugin.ts` to display front component entry points
and watch `.tsx` files

#### Template (`create-twenty-app`)
- New applications now include a sample
`hello-world.front-component.tsx` file

#### Tests
- Added unit tests for `defineFrontComponent()`
- Added unit tests for `getFrontComponentBaseFile()`
2026-01-20 05:54:14 +00:00
Charles Bochet 70582d063e Twenty SDK watch build of functions (#17252)
## Summary

This PR adds function build support to the `twenty dev` command,
enabling tree-shaken production builds of serverless functions during
development with Vite's incremental build capabilities.

## Changes

### New Features
- **Function building in dev mode**: Serverless functions are now
compiled to tree-shaken bundles in `.twenty/functions/` during
development
- **Automatic restart on entry point changes**: When functions are added
or removed, the watcher automatically restarts with the new
configuration
- **Function entry point logging**: Dev mode now displays detected
function entry points with their names and paths
2026-01-19 17:43:40 +00:00
Charles Bochet 5a5e9eeb9e Watch command skeleton (#17246)
Summary

Rewrites the app:dev command to use Vite's dev server instead of manual
file watching with chokidar. This provides better file watching
capabilities and aligns with the existing build tooling.

<img width="1588" height="822" alt="image"
src="https://github.com/user-attachments/assets/7c54bd39-4905-456f-8e3d-64e97b031de0"
/>
2026-01-19 16:05:49 +00:00
Charles Bochet 905898d109 Twenty SDK command renaming and dev mode (#17245)
## Description

This PR improves the developer experience for the `twenty-sdk` and
`create-twenty-app` packages by reorganizing commands, adding
development tooling, and improving documentation.

## Changes

### twenty-sdk

#### Command Refactoring
- **Renamed `app-watch` → `app-dev`**: Renamed `AppWatchCommand` to
`AppDevCommand` and moved to `app-dev.ts` for consistent naming with the
CLI command `app:dev`
- **Moved `app-add` → `entity-add`**: Relocated entity creation logic
from `app/app-add.ts` to `entity/entity-add.ts` and renamed
`AppAddCommand` to `EntityAddCommand` for better separation of concerns

#### Development Tooling
- **Added `dev` target**: New Nx target `npx nx run twenty-sdk:dev` that
runs the build in watch mode for faster development iteration

### create-twenty-app

#### Improved Scaffolded Project
- **Enhanced base-application README** with:
  - Updated Getting Started to recommend `yarn dev` for development
  - Added "Available Commands" section listing all available scripts
  
#### Better Onboarding
- **Improved success message** after app creation with formatted next
steps:
2026-01-19 16:02:12 +01:00
Charles Bochet e61b92132c Rework folder structure (#17230)
<img width="700" height="771" alt="image"
src="https://github.com/user-attachments/assets/b784fbe6-f976-4c9a-84c1-3d90a9010665"
/>

Second one :)
2026-01-19 14:08:05 +00:00
Charles Bochet 7c713577f1 Rework folder structure (#17229)
<img width="700" height="771" alt="image"
src="https://github.com/user-attachments/assets/509b95b5-9c4f-474d-a47f-f950dee189ea"
/>
2026-01-19 09:36:40 +00:00
Charles Bochet 5cef07af45 Twenty SDK iteration (#17223)
Opening a PR to merge the wip work by @martmull 
We will re-organize twenty-sdk in an upcoming PR

---------

Co-authored-by: martmull <martmull@hotmail.fr>
2026-01-19 09:41:54 +01:00
martmull d55b83375d Allow app to extend object (#17116)
- exports `extendObject` utils from `twenty-sdk`
- define `*.object-extension.ts` filename pattern to extend and object
- handle object-extension configs in manifest
2026-01-13 15:07:14 +00:00
martmull ead846d57f Fix logs (#17090)
as title
2026-01-12 10:11:51 +00:00
martmull 936ec06fe8 Improve application ast 3 (#17061)
- fix should generate
- fix errors not displayed properly
2026-01-10 14:52:28 +00:00
martmull 3509838a3a Improve application ast 2 (#17045)
fix some issues with cli tools
2026-01-09 14:54:13 +00:00
martmull 40eef5c464 Improve application ast (#17016)
# Summary

- Introduces a new, flexible folder structure for Twenty SDK
applications using file suffix-based entity detection
- Adds defineApp, defineFunction, defineObject, and defineRole helper
functions with built-in validation
- Refactors manifest loading to use jiti runtime evaluation for
TypeScript config files
- Separates validation logic into dedicated module with comprehensive
error reporting

  # New Application Folder Structure

Applications now use a convention-over-configuration approach where
entities are detected by their file suffix, allowing flexible
organization within the src/app/ folder.

  # Required Structure

    my-app/
    ├── package.json
    ├── yarn.lock
    └── src/
        ├── app/
│ └── application.config.ts # Required - main application configuration
└── utils/ # Optional - handler implementations & utilities

  # Entity Detection by File Suffix

    - *.object.ts - Custom object definitions
    - *.function.ts - Serverless function definitions
    - *.role.ts - Role definitions

  # Supported Folder Organizations

  ## Traditional (by type):
    src/app/
    ├── application.config.ts
    ├── objects/
    │   └── postCard.object.ts
    ├── functions/
    │   └── createPostCard.function.ts
    └── roles/
        └── admin.role.ts

  ## Feature-based:
    src/app/
    ├── application.config.ts
    └── post-card/
        ├── postCard.object.ts
        ├── createPostCard.function.ts
        └── postCardAdmin.role.ts

  ## Flat:
    src/app/
    ├── application.config.ts
    ├── postCard.object.ts
    ├── createPostCard.function.ts
    └── admin.role.ts

  # New Helper Functions

  ## defineApp(config)

    import { defineApp } from 'twenty-sdk';

    export default defineApp({
      universalIdentifier: '4ec0391d-...',
      displayName: 'My App',
      description: 'App description',
      icon: 'IconWorld',
    });

  ## defineObject(config)

    import { defineObject, FieldType } from 'twenty-sdk';

    export default defineObject({
      universalIdentifier: '54b589ca-...',
      nameSingular: 'postCard',
      namePlural: 'postCards',
      labelSingular: 'Post Card',
      labelPlural: 'Post Cards',
      icon: 'IconMail',
      fields: [
        {
          universalIdentifier: '58a0a314-...',
          type: FieldType.TEXT,
          name: 'content',
          label: 'Content',
        },
      ],
    });

  ## defineFunction(config)

    import { defineFunction } from 'twenty-sdk';
    import { myHandler } from '../utils/my-handler';

    export default defineFunction({
      universalIdentifier: 'e56d363b-...',
      name: 'My Function',
      handler: myHandler,
      triggers: [
        {
          universalIdentifier: 'c9f84c8d-...',
          type: 'route',
          path: '/my-route',
          httpMethod: 'POST',
        },
      ],
    });

  ## defineRole(config)

    import { defineRole, PermissionFlag } from 'twenty-sdk';

    export default defineRole({
      universalIdentifier: 'b648f87b-...',
      label: 'App User',
      objectPermissions: [
        {
          objectNameSingular: 'postCard',
          canReadObjectRecords: true,
        },
      ],
      permissionFlags: [PermissionFlag.UPLOAD_FILE],
    });

  # Test plan

    - Verify npx twenty app sync works with new folder structure
    - Verify npx twenty app dev works with new folder structure
    - Verify validation errors display correctly for invalid configs
- Verify all three folder organization styles work (traditional,
feature-based, flat)
    - Run existing E2E tests to ensure backward compatibility
2026-01-09 13:06:30 +00:00