Commit Graph
10771 Commits
Author SHA1 Message Date
Claude a7ea324dc2 fix: replace useLazyQuery with client.query where hook state is unused
Apollo v4's useLazyQuery aborts in-flight queries when the query document
changes (e.g. during metadata/permissions loading), causing AbortError
rejections. Per Apollo docs, when only the returned result is used and
hook state synchronization is not needed, client.query is the clean
approach. This replaces useLazyQuery with client.query in 9 files that
don't use hook state, and keeps .retain() only in useLazyFindManyRecords
and useLazyFindOneRecord which genuinely need hook state synchronization.

https://claude.ai/code/session_01EA7CMTUTG5zFP132yvUweT
2026-03-13 11:00:33 +00:00
Claude 03183a5fdb fix: handle Apollo v4 useLazyQuery rejection to prevent permanent loading state
In Apollo v4, useLazyQuery's execute function returns a ResultPromise
that can reject on errors (unlike v3 where it resolved with the error
in the result). This caused the first object's list view to stay in
permanent loading after page refresh, because the unhandled rejection
left isRecordTableInitialLoading and isInitializingVirtualTableDataLoading
stuck in their initial states.

Two fixes:
- Add try/catch in findManyRecordsLazy to gracefully handle execute
  rejections (matching v3 behavior of returning errors in the result)
- Add try/finally in triggerInitialRecordTableDataLoad to ensure loading
  states are always cleaned up regardless of errors

https://claude.ai/code/session_01EA7CMTUTG5zFP132yvUweT
2026-03-13 09:25:04 +00:00
Claude 13a5da40a3 fix: memoize useObjectPermissions and remaining query hooks for Apollo v4
Root cause: useObjectPermissions() was calling .reduce() on every render,
creating a new object reference each time. This caused all useMemo
dependency arrays containing objectPermissionsByObjectMetadataId to
invalidate, regenerating query DocumentNodes on every render.

Apollo v4's useQuery uses reference equality (query !== state.query) to
detect query changes. New DocumentNode references cause it to create a
new observable, restarting the query before results arrive — resulting
in infinite loading state on first view load after page refresh.

Fix: memoize the reduce result in useObjectPermissions, and wrap
useFindOneRecordQuery and useFindDuplicatesRecordsQuery with useMemo.

https://claude.ai/code/session_01EA7CMTUTG5zFP132yvUweT
2026-03-13 08:34:28 +00:00
Claude f5b280e7b8 fix: remove invalid addTypename option from InMemoryCache in Apollo v4
Apollo v4 removed addTypename from InMemoryCacheConfig. The option is
not needed because MockLink already normalizes both mock and operation
queries with addTypenameToDocument for matching purposes.

https://claude.ai/code/session_01EA7CMTUTG5zFP132yvUweT
2026-03-13 08:10:55 +00:00
Claude 2409152f44 fix: restore addTypename false for MockedProvider in Apollo v4
Apollo v4 removed the addTypename prop from MockedProvider.
Configure addTypename: false on InMemoryCache instead, which
preserves the original v3 behavior where __typename is not added
to mock queries, preventing mock matching failures in storybook tests.

https://claude.ai/code/session_01EA7CMTUTG5zFP132yvUweT
2026-03-13 08:01:58 +00:00
Claude 3ab9d3134c fix: regenerate metadata graphql types with codegen
Properly regenerate the generated-metadata/graphql.ts file using the
typed-document-node codegen plugin against the running server schema,
ensuring all types and documents are complete and correctly ordered.

https://claude.ai/code/session_01EA7CMTUTG5zFP132yvUweT
2026-03-12 20:24:02 +00:00
Claude cad4226a31 style: format files with prettier
https://claude.ai/code/session_01EA7CMTUTG5zFP132yvUweT
2026-03-12 20:14:03 +00:00
Claude 1dc497e1b1 fix: memoize dynamic query generation for Apollo v4 compatibility
Apollo v4's useQuery uses reference equality for the query DocumentNode.
Without memoization, generateFindManyRecordsQuery and similar functions
create new DocumentNode objects on every render, causing the observable
to be recreated before results are delivered - resulting in infinite
loading state on first view load.

Also fix new enterprise settings files from main for Apollo v4 (import
paths, CombinedGraphQLErrors, typed query hooks).

https://claude.ai/code/session_01EA7CMTUTG5zFP132yvUweT
2026-03-12 20:13:24 +00:00
Claude 88a7975d1c merge: resolve conflicts with latest main
https://claude.ai/code/session_01EA7CMTUTG5zFP132yvUweT
2026-03-12 20:03:55 +00:00
WeikoandGitHub 1cb4c98cb3 Add dataloader and read from cache for view entities (#18594)
## Context
Improve view resolution using cache and dataloader

## Performance Comparison

|Run|Main (no DataLoaders/cache)|Feature Branch (DataLoaders +
cache)|Speedup|
|---|---|---|---|
|1 (cold)|418ms|95ms|~4.4x faster|
|2|42ms|19ms|~2.2x faster|
|3|37ms|19ms|~1.9x faster|
|4|39ms|12ms|~3.2x faster|
|5|33ms|13ms|~2.5x faster|

The biggest improvement is to use dataloaders for the multiple relations
associated with views. Cache is a bit less significant since there are
other cache mechanism such as PostgreSQL buffer cache but it will
probably be more meaningful with bigger workspaces
2026-03-12 18:05:30 +00:00
CopilotGitHubcopilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>Devessier
a3c392ce8b Reset selected widget when exiting record page layout edit mode (#18603)
## Before


https://github.com/user-attachments/assets/b9720898-3433-488b-b784-1fa78e4e68f7

## After


https://github.com/user-attachments/assets/8f3fdde5-773d-44c4-a0f5-cca683736782

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Devessier <29370468+Devessier@users.noreply.github.com>
2026-03-12 17:55:01 +00:00
Charles BochetandGitHub ab13020e2b Fix wrong uuid error on field metadata (#18598)
## Summary
- Same fix as #18590 but applied to `FieldMetadataDTO`
- Changed `universalIdentifier` from `UUID` to `String` type since field
metadata universal identifiers are not necessarily valid UUIDs
- Removed `universalIdentifier` from `FieldFilter` (was using
`UUIDFilterComparison`)
- Updated generated SDK and frontend types accordingly
2026-03-12 18:51:42 +01:00
WeikoandGitHub 3f420c84d7 Fix Flow tab missing for workflow run (#18602)
## Context
Conditional tab rendering was recently introduced for system objects
that now have record page layouts. However Workflow run is a system
object and has a specific "Flow" tab that was not displayed anymore

## Before
<img width="1191" height="640" alt="Screenshot 2026-03-12 at 18 10 03"
src="https://github.com/user-attachments/assets/6f2c6319-6ddf-4906-a83c-0db8a27a8267"
/>

## After
<img width="1299" height="802" alt="Screenshot 2026-03-12 at 18 09 35"
src="https://github.com/user-attachments/assets/35e1e356-e995-43a2-9207-adc0f67cc426"
/>
2026-03-12 17:25:12 +00:00
0ef4741473 i18n - translations (#18595)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-03-12 18:17:42 +01:00
WeikoandGitHub b5db955ac8 Fix sdk metadata client codegen (#18599)
## Context
Previous token was tied to a non-existing token and codegen was failing
locally due to the server throwing.
This is due to a regression introduced here
https://github.com/twentyhq/twenty/pull/18590/changes#diff-848fff5d5b6f9858c8e2391212dfa9da5151cd3b1325d410df8a82250a229558L26
where a token is hardcoded instead of using the one from the ENV
2026-03-12 18:13:37 +01:00
Baptiste DevessierandGitHub 2a6fcfcfb3 Side Panel Sub Page Framework® (#18579)
Replace hard-coded implementations for sub pages in the side panel with
a proper framework
2026-03-12 15:17:29 +00:00
5bfa4c5c39 Fix wrong uuid error (#18590)
as title

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2026-03-12 16:12:30 +01:00
1685d066be i18n - translations (#18591)
Created by Github action

Co-authored-by: github-actions <github-actions@twenty.com>
2026-03-12 15:55:51 +01:00
Thomas TrompetteandGitHub 6a3281a18d Bug fix batches (#18588)
- clear sse state on logout
- fix no record not selectable through keyboard
- fix book a call design
- fix error notif design
2026-03-12 15:55:30 +01:00
Raphaël BosiandGitHub 741e9a8f81 Update yarn lock (#18589)
https://github.com/twentyhq/twenty/pull/18075
2026-03-12 15:42:01 +01:00
Charles BochetandGitHub 0897575fd0 Fix flaky return-to-path e2e tests (#18580)
## Summary

Fixes flaky `return-to-path` e2e tests that were failing intermittently
in CI merge queue runs.

**Root cause:** In the multi-workspace environment used by CI
(`IS_MULTIWORKSPACE_ENABLED=true`), navigating to
`localhost:3001/settings/accounts` triggers a full page redirect to
`app.localhost:3001/welcome` via `useRedirectToDefaultDomain`. This
redirect is a hard navigation (not a React Router transition), which
clears all in-memory Jotai state — including the `returnToPathState`
atom that stores the path the user should be redirected to after login.
After the redirect, the app has no memory of the intended destination
and falls back to `/objects/companies`.

**Fix:** Before performing the cross-domain redirect in
`useRedirectToDefaultDomain`, read the `returnToPath` from the Jotai
store and pass it as a URL search parameter. On the new page load,
`useInitializeQueryParamState` picks it up from the URL and re-hydrates
the Jotai atom, preserving the return-to-path across the full page
reload.

## Test plan

- [x] Verified locally against production build (`serve -s build`) with
`IS_MULTIWORKSPACE_ENABLED=true` — 33/33 consecutive passes of
`return-to-path.spec.ts`
- [x] Lint passes (`npx nx lint:diff-with-main twenty-front`)
2026-03-12 15:29:35 +01:00
501fcc737f i18n - translations (#18586)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-03-12 15:18:16 +01:00
Raphaël BosiandGitHub c9deab4373 [COMMAND MENU ITEMS] Remove standard front components (#18581)
All standard command menu items will link to an engine component instead
of standard front components.
2026-03-12 15:18:00 +01:00
Claude 2b259ea44f merge: resolve conflicts with latest main, add EngineComponentKey
- Resolve 4 merge conflicts properly:
  - generated-metadata/graphql.ts: keep typed-document-node format, add
    EngineComponentKey enum and engineComponentKey field to CommandMenuItem
  - useAgentChatData.ts: keep useEffect + useQuery, add useMemo from main
  - useCommandMenuItemFrontComponentCommands.tsx: keep FindManyCommandMenuItemsDocument, add EngineComponentKey
  - CreateWorkspace.tsx: keep result.error (v4 MutateResult API)
- Add TODO to useSnackBarOnQueryError about centralizing error handling

https://claude.ai/code/session_019WGZ6Rd7sEHuBg9sTrXRqJ
2026-03-12 14:13:59 +00:00
MarieandGitHub c1da7be6d7 Billing for self-hosts (#18075)
## Summary

Implements enterprise licensing and per-seat billing for self-hosted
environments, with Stripe as the single source of truth for subscription
data.

### Components

- **twenty-website** hosts the private key to sign `ENTERPRISE_KEY` and
`ENTERPRISE_VALIDITY_TOKEN`. It communicates with Stripe to emit the
daily `ENTERPRISE_VALIDITY_TOKEN` if the subscription is active, based
on the user's Stripe subscription ID stored in `ENTERPRISE_KEY`.
- **Stripe** is the single source of truth for subscription data
(status, seats, billing).
- **The client** (twenty-server + DB + workers) saves `ENTERPRISE_KEY`
in the `keyValuePair` table (or `.env` if
`IS_CONFIG_VARIABLES_IN_DB_ENABLED` is false) and the daily-renewed
`ENTERPRISE_VALIDITY_TOKEN` in the `appToken` table.
`ENTERPRISE_VALIDITY_TOKEN` is verified client-side using a public key
to grant access to enterprise features (RLS, SSO, audit logs, etc.).

### Flow

1. When requesting an upgrade to an enterprise plan (from **Enterprise**
in settings), the user is shown a modal to choose monthly/yearly
billing, then redirected to Stripe to enter payment details. After
checkout, they land on twenty-website where they are exposed to their
`ENTERPRISE_KEY`, which they paste in the UI. It is saved in the
`keyValuePair` table. On activation, a first `ENTERPRISE_VALIDITY_TOKEN`
with 30-day validity is stored in the `appToken` table.

2. **Every day**, a cron job runs and does two things:
- **Refreshes the validity token**: communicates with twenty-website to
get a new `ENTERPRISE_VALIDITY_TOKEN` with 30-day validity if the Stripe
subscription is still active. If the subscription is in cancellation,
the emitted token has a validity equal to the cancellation date. If it's
no longer valid, the token is not replaced. The cron only needs to run
every 30 days in practice, but runs daily so it's resilient to
occasional failures.
- **Reports seat count**: counts active (non-soft-deleted)
`UserWorkspace` entries and sends the count to twenty-website, which
updates the Stripe subscription quantity with proration. Seats are also
reported on first activation. If the subscription is canceled or
scheduled for cancellation, the seat update is skipped.

3. `ENTERPRISE_VALIDITY_TOKEN` is verified server-side via a public key
to grant access to enterprise features.

### Key concepts

Three distinct checks are exposed as GraphQL fields on `Workspace`:

| Field | Meaning |
|---|---|
| `hasValidEnterpriseKey` | Has any valid enterprise key (signed JWT
**or** legacy plain string) |
| `hasValidSignedEnterpriseKey` | `ENTERPRISE_KEY` is a properly signed
JWT (billing portal makes sense) |
| `hasValidEnterpriseValidityToken` | `ENTERPRISE_VALIDITY_TOKEN` is
present and not expired (expiration depends on signed token payload, not
on "expiresAt" on appToken table which is only indicative) |

Feature access is gated by `isValid()` =
`hasValidEnterpriseValidityToken || hasValidEnterpriseKey` (to support
both new and legacy keys during transition). After transition isValid()
= hasValidEnterpriseValidityToken

### Frontend states

The Enterprise settings page handles multiple states:
- **No key**: show "Get Enterprise" with checkout modal
- **Orphaned validity token** (token valid but no signed key): prompt
user to set a valid enterprise key
- **Active/trialing but no validity token**: show subscription status
with a "Reload validity token" action
- **Active/trialing**: show full subscription info, billing portal
access, cancel option
- **Cancellation scheduled**: show cancellation date, billing portal
- **Canceled**: show billing history link and option to start a new
subscription
- **Past due / Incomplete**: prompt to update payment or restart

### Temporary retro-compatibility: legacy plain-text keys

Previously, enterprise features were gated by a simple check: any
non-empty string in `ENTERPRISE_KEY` granted access. With this PR, we
transition to a controlled system relying on signed JWTs.

To avoid breaking existing self-hosted users:
- **Legacy plain-text keys still grant access** to enterprise features.
`hasValidEnterpriseKey` returns `true` for both signed JWTs and plain
strings, and `isValid()` checks `hasValidEnterpriseKey` as a fallback
when no validity token is present.
- **A deprecation banner** is shown at the top of the app when
`hasValidEnterpriseKey` is `true` but `hasValidSignedEnterpriseKey` is
`false`, informing the user that their key format is deprecated and they
should activate a new signed key.
- **No billing portal or subscription management** is available for
legacy keys since there is no Stripe subscription to manage.

This retro-compatibility will be removed in a future version. At that
point, `isValid()` will only check `hasValidEnterpriseValidityToken`.

### Edge cases

- **Air-gapped / production environments**: for self-hosted clients that
block external traffic (or for our own production), provide a long-lived
`ENTERPRISE_VALIDITY_TOKEN` (e.g. 99 years) directly in the `appToken`
table, with no `ENTERPRISE_KEY`. The daily cron will skip the refresh
(no enterprise key to authenticate with), but the pre-seeded validity
token will be used to grant feature access. No billing or seat reporting
occurs in this mode.
- **`IS_CONFIG_VARIABLES_IN_DB_ENABLED` is false**: if the user tries to
activate an enterprise key but DB config writes are disabled, the
backend returns a clear error asking them to add `ENTERPRISE_KEY` to
their `.env` file manually.
- **Canceled subscriptions**: the `/seats` endpoint skips Stripe updates
for canceled or cancellation-scheduled subscriptions to avoid Stripe API
errors.

### How to test
- launch twenty-website on a different url (eg localhost:1002)
- add ENTERPRISE_API_URL=http://localhost:3002/api/enterprise (or else)
in your server .env
- ask me for twenty-website's .env file content (STRIPE_SECRET_KEY;
STRIPE_ENTERPRISE_MONTHLY_PRICE_ID;STRIPE_ENTERPRISE_YEARLY_PRICE_ID;
ENTERPRISE_JWT_PRIVATE_KEY; ENTERPRISE_JWT_PUBLIC_KEY;
NEXT_PUBLIC_WEBSITE_URL)
- visit Admin panel / enterprise
2026-03-12 15:07:53 +01:00
WeikoandGitHub c59f420d21 Hide tabs for system objects (#18583)
<img width="1286" height="793" alt="Screenshot 2026-03-12 at 13 57 16"
src="https://github.com/user-attachments/assets/bebfd23f-3172-424a-95ee-ba95358a6196"
/>
2026-03-12 14:46:15 +01:00
Claude b1ed57ecf9 refactor: replace useEffect patterns with useSnackBarOnQueryError utility
Create useSnackBarOnQueryError utility hook to replace ~15 identical
error→snackbar useEffect patterns with one-liners. Remove onCompleted
callbacks from 5 hooks (useFindOneRecord, useGetOneLogicFunction, etc.)
since Apollo v4 no longer supports them on useQuery - callers now use
returned data directly. Net reduction of ~130 lines.

https://claude.ai/code/session_019WGZ6Rd7sEHuBg9sTrXRqJ
2026-03-12 12:53:01 +00:00
WeikoandGitHub 06d4d62e90 Move 1.19 backfill pagelayout and views to 1.20 (#18582) 2026-03-12 13:46:07 +01:00
WeikoandGitHub eb4665bc98 Create missing standard table and fields widget views (#18543) 2026-03-12 13:28:05 +01:00
f19fcd0010 i18n - translations (#18578)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-03-12 13:23:54 +01:00
Lucas BordeauandGitHub cb3e32df86 Fix AI demo workspace skill (#18575)
This PR fixes what allows to have a working demo workspace skill.

- Skill updated many times into something that works
- Fixed infinite loop in AI chat by memoizing ai-sdk output
- Finished navigateToView implementation
- Increased MAX_STEPS to 300 so the chat don't quit in the middle of a
long running skill
- Added CreateManyRelationFields
2026-03-12 13:19:01 +01:00
Hamza FaidiandGitHub db5b4d9c6c fix: replace unsafe JSON.parse casts with parseJson in filter dropdowns (#18513)
## Problem

Four filter dropdown components were calling `JSON.parse(filter.value)
as string[]` to parse stored filter state. This throws a `SyntaxError`
if the value is malformed (truncated URL, stale localStorage, migration
artifact), crashing the entire dropdown with no recovery.

## Solution

Replace with the existing `parseJson<string[]>` utility from
`twenty-shared`, which wraps `JSON.parse` in a try/catch and returns
`null` on failure. The `?? []` fallback gracefully degrades to an empty
selection instead of crashing.

All four files had an explicit `// TODO: replace by a safe parse`
marking this as a known issue.

## Testing


No new tests — `parseJson` is already tested in `twenty-shared`. No new
logic introduced.

## issue link 
#18514
2026-03-12 13:15:22 +01:00
Charles BochetandGitHub 660536d6bb Fix onboarding flow: workspace creation modal and invite team skip (#18577)
## Summary

- **Fix create-profile modal not showing after workspace creation**:
After activating a workspace, `CreateWorkspace.onSubmit` called
`refreshObjectMetadataItems()` which only updated the
`objectMetadataItemsState` atom but never marked the metadata store as
ready (`metadataStoreState` stayed at `'empty'`). Since `MetadataGater`
excludes `CreateWorkspace` but not `CreateProfile` from its loading
check, navigating to `/create/profile` triggered the skeleton loader
instead of the modal. The fix adds the full metadata pipeline after
refresh — `updateDraft('objectMetadataItems')` + `applyChanges()` for
objects, and `fetchAndLoadIndexViews()` for views — so
`isAppMetadataReady` is `true` before navigation.

- **Fix invite-team "Skip" not persisting to server**: Clicking "Skip"
on the invite-team page called `setNextOnboardingStatus()` which only
updated the local Jotai atom. The early return for empty emails bypassed
`sendInvitation`, so the server never cleared the
`ONBOARDING_INVITE_TEAM_PENDING` user var. On page refresh,
`GetCurrentUser` returned `INVITE_TEAM` and the user was stuck. The fix
removes the early return so `sendInvitation({ emails: [] })` always runs
— the server handles empty arrays fine and clears the pending flag.
2026-03-12 13:15:05 +01:00
e8f8189167 [COMMAND MENU ITEMS] Add engine component key (#18554)
## PR Description

In the process of migrating all the existing commands to the backend, we
stumbled across a couple of problems that made us reconsider the full
migration. This PR introduces a way for command menu items to bypass
front components and to directly reference a frontend component from
twenty front.

It:
- Introduces a `engineFrontComponentKey` field on `CommandMenuItem` as
an alternative to `frontComponentId` and `workflowVersionId`, allowing
command menu items to reference frontend components by key directly
rather than requiring a FrontComponent entity
- Updates the DB constraint to allow exactly one of `workflowVersionId`,
`frontComponentId`, or `engineFrontComponentKey`

### All standard command menu items from the frontend which use
`standardFrontComponentKey`

These are all commands that execute a GraphQL query or a mutation.
Two mains concerned have been raised that made us go with this
(temporary) architecture instead:
- If those commands are part of the standard application, they can only
alter objects from that application and not custom objects.
- We would need to implement a way to trigger optimistic rendering from
the front components, which might take some time to implement.

List:
- Create new record
- Delete (single record)
- Delete records (multiple)
- Restore record
- Restore records (multiple)
- Permanently destroy record
- Permanently destroy records (multiple)
- Add to favorites
- Remove from favorites
- Merge records
- Duplicate Dashboard
- Save Dashboard
- Save Page Layout
- Activate Workflow
- Deactivate Workflow
- Discard Draft (workflow)
- Test Workflow
- Tidy up workflow
- Duplicate Workflow
- Stop (workflow run)
- Use as draft (workflow version)

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2026-03-12 13:14:45 +01:00
Claude 0c6a920bc3 fix: add missing mocks for useFieldMetadataItem test
https://claude.ai/code/session_019WGZ6Rd7sEHuBg9sTrXRqJ
2026-03-12 11:40:17 +00:00
Claude 8a30f5afc5 fix: complete Apollo v4 migration - upgrade deps, fix error handling, fix tests
- Upgrade apollo-link-rest 0.9 → 0.10 (Apollo v4 compatible)
- Upgrade apollo-upload-client 17 → 19 (Apollo v4 compatible)
- Replace createUploadLink with UploadHttpLink
- Replace instanceof CombinedGraphQLErrors with CombinedGraphQLErrors.is()
- Fix test mocks: jest.mock('@apollo/client') → jest.mock('@apollo/client/react')
- Fix inline snapshots: ApolloError → Error (v4 error type changes)
- Fix apollo.factory test for v4 error handling behavior
- Add apollo-upload-client type declarations
- Update jest.config to transform apollo-upload-client .mjs files

https://claude.ai/code/session_019WGZ6Rd7sEHuBg9sTrXRqJ
2026-03-12 11:39:31 +00:00
martmullandGitHub 78473a606a Fix app dev flickering (#18562)
- fix ticker issue
- fix too many rendering
2026-03-12 11:58:44 +01:00
Claude b48572c89c fix: continue Apollo v4 migration - fix remaining type errors
- Fix untyped REST query data with explicit type parameters
- Fix onCompleted/onError in remaining query hooks
- Fix jest.Mock type assertions
- Fix MutateResult.errors -> .error in NameField
- Fix DeepPartialObject type assertions
- Fix addTypename in InMemoryCacheConfig
- Fix missing gql document constant references
2026-03-12 10:38:29 +00:00
neo773andGitHub b21fb4aa6f Fix PDF Upload edge case (#18533)
we were using an older version of `file-type` which has limited support
for PDF as it's a complex spec
Updated to latest version which includes support for plugins and added
`@file-type/pdf` which has extensive spec compliant detection approach

fixes TWENTY-SERVER-FAN
2026-03-12 10:34:24 +00:00
Claude 30d24a26c3 fix: continue Apollo v4 migration - fix view optimistic effects, workflow cache, link types
- Fix Modifier return types by filtering undefined from toReference results
- Fix cache.extract() returning unknown in workflow hooks
- Fix ApolloLink array type compatibility with third-party links
2026-03-12 10:27:10 +00:00
38664249cf i18n - translations (#18576)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-03-12 11:24:07 +01:00
Claude 43be270071 fix: continue Apollo Client v4 migration - fix type errors
- Fix connectToDevTools -> devtools option
- Fix ErrorLike type narrowing in apollo.factory.ts
- Fix ServerError construction in streamingRestLink
- Fix Observable.map -> rxjs pipe(map()) in custom links
- Fix addTypename prop removed from MockedProvider
- Fix FetchMoreQueryOptions -> ObservableQuery.FetchMoreOptions
- Fix duplicate GetChatThreadsDocument import
- Fix mockedApolloClient/mockedApolloCoreClient uri -> HttpLink
- Convert remaining generated hooks to useQuery/useMutation
- Fix useHandleResetPassword test to mock useMutation
2026-03-12 10:18:28 +00:00
Baptiste DevessierandGitHub 69542898a1 Display a single Add a Section button (#18563)
- Display a single Add a Section button at the end of the list
- Move other buttons to the section's dropdown menu


https://github.com/user-attachments/assets/b51d8846-635a-477a-9205-bf3266cfcff4
2026-03-12 10:01:48 +00:00
09beddb63d i18n - docs translations (#18566)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-03-12 10:55:44 +01:00
Claude af1f8d7477 fix: reapply apollo.factory.ts v4 migration and codegen config
The linter keeps reverting these files. Reapplying the changes.

https://claude.ai/code/session_019WGZ6Rd7sEHuBg9sTrXRqJ
2026-03-12 09:52:55 +00:00
Claude 4649a6b2f5 feat: migrate Apollo Client v3 to v4 (WIP)
- Update @apollo/client from ^3.7.17 to ^4.0.0
- Switch codegen from typescript-react-apollo to typed-document-node
- Update ErrorLink to use CombinedGraphQLErrors.is() pattern
- Replace fromPromise with rxjs from/switchMap
- Move hook imports to @apollo/client/react
- Move error imports to @apollo/client/errors
- Move MockedProvider to @apollo/client/testing/react
- Add local getOperationName utility (removed from Apollo 4)
- Replace ApolloError with CombinedGraphQLErrors
- Remove codemod boilerplate (localState, Defer handler)

https://claude.ai/code/session_019WGZ6Rd7sEHuBg9sTrXRqJ
2026-03-12 09:47:18 +00:00
Hamza FaidiandGitHub 2eac82c207 fix(front): stabilize downloadFile unit test and return promise chain (#18484)
# Description

## What this PR fixes
This PR fixes a flaky/skipped unit test for
[downloadFile](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
and aligns the test with the actual implementation.

## Changes made
Updated
[downloadFile](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
test to validate file-saver behavior instead of DOM anchor creation.
Mocked
[saveAs](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
from file-saver and asserted it is called with the fetched blob and
filename.
Added proper async assertions for:
successful file download
failed fetch path ([status !==
200](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html))
rejecting with Failed downloading file
Updated
[downloadFile](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
implementation to return the fetch promise chain so callers/tests can
await it reliably.

## Related Issue
Closes #18485
2026-03-12 09:00:50 +01:00
f262437da6 Refactor dev environment setup with auto-detection and Docker support (#18564)
## Summary
Completely rewrites the development environment setup script to be more
robust, idempotent, and flexible. The new implementation auto-detects
available services (local PostgreSQL/Redis vs Docker), provides multiple
operational modes, and includes comprehensive health checks and error
handling.

## Key Changes

- **Enhanced setup script** (`packages/twenty-utils/setup-dev-env.sh`):
- Added auto-detection logic to prefer local services (PostgreSQL 16,
Redis) over Docker
  - Implemented service health checks with retry logic (30s timeout)
- Added command-line flags: `--docker` (force Docker), `--down` (stop
services), `--reset` (wipe data)
- Improved error handling with `set -euo pipefail` and descriptive
failure messages
- Added helper functions for service detection, startup, and status
checking
  - Fallback to manual `.env` file copying if Nx is unavailable
  - Enhanced output with clear status messages and usage instructions

- **New Docker Compose file**
(`packages/twenty-docker/docker-compose.dev.yml`):
  - Dedicated development infrastructure file (PostgreSQL 16 + Redis 7)
  - Includes health checks for both services
  - Configured with appropriate restart policies and volume management
  - Separate from production compose configuration

- **Updated documentation** (`CLAUDE.md`):
- Clarified that all environments (CI, local, Claude Code, Cursor) use
the same setup script
  - Documented new command-line flags and their purposes
- Noted that CI workflows manage services independently via GitHub
Actions

- **Updated Cursor environment config** (`.cursor/environment.json`):
- Simplified to use the new unified setup script instead of complex
inline commands

## Implementation Details

The script now follows a clear three-phase approach:
1. **Service startup** — Auto-detects and starts PostgreSQL and Redis
(local or Docker)
2. **Database creation** — Creates 'default' and 'test' databases
3. **Environment configuration** — Sets up `.env` files via Nx or direct
file copy

The auto-detection logic prioritizes local services for better
performance while gracefully falling back to Docker if local services
aren't available. All operations are idempotent and safe to run multiple
times.

https://claude.ai/code/session_01UDxa2Kp1ub9tTL3pnpBVFs

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-12 08:43:58 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
15d0970f72 Bump @swc/core from 1.15.11 to 1.15.18 (#18570)
Bumps
[@swc/core](https://github.com/swc-project/swc/tree/HEAD/packages/core)
from 1.15.11 to 1.15.18.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/swc-project/swc/blob/main/CHANGELOG.md"><code>@​swc/core</code>'s
changelog</a>.</em></p>
<blockquote>
<h2>[1.15.18] - 2026-03-01</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>(html/wasm)</strong> Publish <code>@​swc/html-wasm</code>
for nodejs (<a
href="https://redirect.github.com/swc-project/swc/issues/11601">#11601</a>)
(<a
href="https://github.com/swc-project/swc/commit/bd443f582c553e9d898a1d5e7395abaad60b26d2">bd443f5</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>
<p>Add AGENTS note about next-gen ast (<a
href="https://redirect.github.com/swc-project/swc/issues/11592">#11592</a>)
(<a
href="https://github.com/swc-project/swc/commit/80b4be872d85dc82cbb6e84c91fe102d807a2780">80b4be8</a>)</p>
</li>
<li>
<p>Add typescript-eslint AST compatibility note (<a
href="https://redirect.github.com/swc-project/swc/issues/11598">#11598</a>)
(<a
href="https://github.com/swc-project/swc/commit/c7bfebec4fb691e6e49f3c3b7b257be178e7f238">c7bfebe</a>)</p>
</li>
</ul>
<h3>Features</h3>
<ul>
<li>
<p><strong>(es/ast)</strong> Add runtime arena crate and bootstrap
swc_es_ast (<a
href="https://redirect.github.com/swc-project/swc/issues/11588">#11588</a>)
(<a
href="https://github.com/swc-project/swc/commit/7a06d967e43fe2f84078fc241bc655b41450d2c1">7a06d96</a>)</p>
</li>
<li>
<p><strong>(es/parser)</strong> Add <code>swc_es_parser</code> (<a
href="https://redirect.github.com/swc-project/swc/issues/11593">#11593</a>)
(<a
href="https://github.com/swc-project/swc/commit/f11fd705ee84909f6b0f984b1b5fc35abf73ec05">f11fd70</a>)</p>
</li>
</ul>
<h3>Ci</h3>
<ul>
<li>Triage main CI breakage (<a
href="https://redirect.github.com/swc-project/swc/issues/11589">#11589</a>)
(<a
href="https://github.com/swc-project/swc/commit/075af578c46c0bfdb74c450c157d0e1753024a36">075af57</a>)</li>
</ul>
<h2>[1.15.17] - 2026-02-26</h2>
<h3>Documentation</h3>
<ul>
<li>Add submodule update step before test runs (<a
href="https://redirect.github.com/swc-project/swc/issues/11576">#11576</a>)
(<a
href="https://github.com/swc-project/swc/commit/81b22c31d1acb447caae1a2d2bd530b2e6a40c26">81b22c3</a>)</li>
</ul>
<h3>Features</h3>
<ul>
<li>
<p><strong>(bindings)</strong> Add html wasm binding and publish wiring
(<a
href="https://redirect.github.com/swc-project/swc/issues/11587">#11587</a>)
(<a
href="https://github.com/swc-project/swc/commit/b3869c3ae2a592d4539f4cbfbabeaf615e55d69e">b3869c3</a>)</p>
</li>
<li>
<p><strong>(sourcemap)</strong> Support safe scopes round-trip metadata
(<a
href="https://redirect.github.com/swc-project/swc/issues/11581">#11581</a>)
(<a
href="https://github.com/swc-project/swc/commit/de2a348daed80e47c75dabaf2f0ce945d850210a">de2a348</a>)</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/swc-project/swc/commit/7cb1be24a7857a94abd7f3cfe9709d22ac314379"><code>7cb1be2</code></a>
chore: Publish <code>1.15.18</code> with <code>swc_core</code>
<code>v58.0.1</code></li>
<li><a
href="https://github.com/swc-project/swc/commit/2821ed060a6f59a168ab8c60cde08ddc3e5cf0d5"><code>2821ed0</code></a>
chore: Publish <code>1.15.18-nightly-20260301.1</code> with
<code>swc_core</code> <code>v58.0.1</code></li>
<li><a
href="https://github.com/swc-project/swc/commit/08806dfffa4361414f1aad647bc1a9206ac29dbc"><code>08806df</code></a>
chore: Publish <code>1.15.17</code> with <code>swc_core</code>
<code>v58.0.1</code></li>
<li><a
href="https://github.com/swc-project/swc/commit/2fdd5ee6b17733583ba7cf5102534826d0d853bf"><code>2fdd5ee</code></a>
chore: Publish <code>1.15.17-nightly-20260226.1</code> with
<code>swc_core</code> <code>v58.0.1</code></li>
<li><a
href="https://github.com/swc-project/swc/commit/316e5035014020d6430262b4fc5e1b7cf4be9980"><code>316e503</code></a>
chore: Publish <code>1.15.16-nightly-20260226.1</code> with
<code>swc_core</code> <code>v58.0.1</code></li>
<li><a
href="https://github.com/swc-project/swc/commit/fb0ce2af0c6a88cd74bb3e55434f3081e7a5aa75"><code>fb0ce2a</code></a>
chore: Publish <code>1.15.15-nightly-20260226.1</code> with
<code>swc_core</code> <code>v58.0.1</code></li>
<li><a
href="https://github.com/swc-project/swc/commit/5f8fc7bac5be0e25a674455c581cea476aa2f6c7"><code>5f8fc7b</code></a>
chore: Publish <code>1.15.14-nightly-20260225.1</code> with
<code>swc_core</code> <code>v58.0.1</code></li>
<li><a
href="https://github.com/swc-project/swc/commit/2e0ea183f4a92735243a02829d8e02237aa94de3"><code>2e0ea18</code></a>
chore: Publish <code>1.15.13</code> with <code>swc_core</code>
<code>v57.0.1</code></li>
<li><a
href="https://github.com/swc-project/swc/commit/4e7a14c3a28ff667bb1aaac6e4aab83af626b173"><code>4e7a14c</code></a>
chore: Publish <code>1.15.13-nightly-20260223.1</code> with
<code>swc_core</code> <code>v57.0.1</code></li>
<li><a
href="https://github.com/swc-project/swc/commit/efccf48e991f21211377239ece3d7c1475eaae84"><code>efccf48</code></a>
chore: Publish <code>1.15.12-nightly-20260222.1</code> with
<code>swc_core</code> <code>v57.0.1</code></li>
<li>See full diff in <a
href="https://github.com/swc-project/swc/commits/v1.15.18/packages/core">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@swc/core&package-manager=npm_and_yarn&previous-version=1.15.11&new-version=1.15.18)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-12 07:16:45 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
1adc325887 Bump path-to-regexp from 8.2.0 to 8.3.0 (#18571)
Bumps [path-to-regexp](https://github.com/pillarjs/path-to-regexp) from
8.2.0 to 8.3.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pillarjs/path-to-regexp/releases">path-to-regexp's
releases</a>.</em></p>
<blockquote>
<h2>8.3.0</h2>
<p><strong>Changed</strong></p>
<ul>
<li>Add custom error class (<a
href="https://redirect.github.com/pillarjs/path-to-regexp/issues/398">#398</a>)
2a7f2a4</li>
<li>Allow plain objects for <code>TokenData</code> (<a
href="https://redirect.github.com/pillarjs/path-to-regexp/issues/391">#391</a>)
687a9bb</li>
<li>Escape text should escape backslash (<a
href="https://redirect.github.com/pillarjs/path-to-regexp/issues/390">#390</a>)
a4a8552</li>
<li>Improved error messages and stack size (<a
href="https://redirect.github.com/pillarjs/path-to-regexp/issues/363">#363</a>)
a6bdf40</li>
</ul>
<p><strong>Other</strong></p>
<ul>
<li>Minifying the parser
<ul>
<li>PR (<a
href="https://redirect.github.com/pillarjs/path-to-regexp/issues/401">#401</a>)
9df2448</li>
<li>PR (<a
href="https://redirect.github.com/pillarjs/path-to-regexp/issues/395">#395</a>)
4a91505</li>
<li>Shaving some bytes  d63f44b</li>
<li>Remove optional operator  973d15c</li>
</ul>
</li>
</ul>
<p><a
href="https://github.com/pillarjs/path-to-regexp/compare/v8.2.0...v8.3.0">https://github.com/pillarjs/path-to-regexp/compare/v8.2.0...v8.3.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/pillarjs/path-to-regexp/commit/c4f5b3fc10782a5de2bee55c3e40e5af890c9cad"><code>c4f5b3f</code></a>
8.3.0</li>
<li><a
href="https://github.com/pillarjs/path-to-regexp/commit/6587c812746cba94855867612f3a719bb25f794e"><code>6587c81</code></a>
Move parameter name errors up in docs (<a
href="https://redirect.github.com/pillarjs/path-to-regexp/issues/402">#402</a>)</li>
<li><a
href="https://github.com/pillarjs/path-to-regexp/commit/9df2448fdfca9d2957cf47a1777b5deda9be18cf"><code>9df2448</code></a>
Remove more bytes from parser (<a
href="https://redirect.github.com/pillarjs/path-to-regexp/issues/401">#401</a>)</li>
<li><a
href="https://github.com/pillarjs/path-to-regexp/commit/012a54a83c9e7fe77d1ee436c67048bca0512aca"><code>012a54a</code></a>
Bump actions/checkout from 4 to 5 (<a
href="https://redirect.github.com/pillarjs/path-to-regexp/issues/403">#403</a>)</li>
<li><a
href="https://github.com/pillarjs/path-to-regexp/commit/9385f7df7406b4607c3d18dfb276d5371f885418"><code>9385f7d</code></a>
Remove engines from package (<a
href="https://redirect.github.com/pillarjs/path-to-regexp/issues/399">#399</a>)</li>
<li><a
href="https://github.com/pillarjs/path-to-regexp/commit/2a7f2a4e9ba42eee41aa9d7a1a69eddb43b79a61"><code>2a7f2a4</code></a>
Add custom error class (<a
href="https://redirect.github.com/pillarjs/path-to-regexp/issues/398">#398</a>)</li>
<li><a
href="https://github.com/pillarjs/path-to-regexp/commit/265a2a7a26916a18fc6d1c5936c878a32a0fedb7"><code>265a2a7</code></a>
100% test coverage (<a
href="https://redirect.github.com/pillarjs/path-to-regexp/issues/396">#396</a>)</li>
<li><a
href="https://github.com/pillarjs/path-to-regexp/commit/4a915059a843dfdd122a0c4936837c7fdda2d4ee"><code>4a91505</code></a>
Reduce bytes in parse function (<a
href="https://redirect.github.com/pillarjs/path-to-regexp/issues/395">#395</a>)</li>
<li><a
href="https://github.com/pillarjs/path-to-regexp/commit/687a9bbc735245b2688c17db7e9fe86013ea0c77"><code>687a9bb</code></a>
Allow plain objects for <code>TokenData</code> (<a
href="https://redirect.github.com/pillarjs/path-to-regexp/issues/391">#391</a>)</li>
<li><a
href="https://github.com/pillarjs/path-to-regexp/commit/a4a8552c9fb4449c470fb9ead458df1c89cadb72"><code>a4a8552</code></a>
Escape text should escape backslash (<a
href="https://redirect.github.com/pillarjs/path-to-regexp/issues/390">#390</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/pillarjs/path-to-regexp/compare/v8.2.0...v8.3.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=path-to-regexp&package-manager=npm_and_yarn&previous-version=8.2.0&new-version=8.3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-12 06:50:07 +00:00