# Introduction
Verified for multi select record picker and it's already working
Also works for both single and multi after record deletion
Fixes https://github.com/twentyhq/twenty/issues/12544
# Introduction
In a nutshell this PR introduces a `workspaceMemberEntity` to
`workspaceMemberDto` transpilation which was not done but commented as
`// TODO` across the `user resolver`.
Also passed on the `Roles` and `UserWorkspacePermissions` transpilation
We now also compute the roles for the `workspaceMember` resolver ( not
only the `workspaceMembers` )
Some refactor
In the following days about to create a PR that introduces integration
testing on the user resolver
## Conclusion
As always any suggestions are more than welcomed ! Please let me know !
## Misc
Following https://github.com/twentyhq/twenty/pull/11914
closing https://github.com/twentyhq/core-team-issues/issues/1011
# Introduction
Introducing jest sharding along github actions matrix in order to
fluidify the process
Note in case we will compute and guard coverage metrics we will need to
merge coverages reports such as we do for the frontend storybooks
integrations tests, from now this is overkill as unused
Related successful run
https://github.com/twentyhq/twenty/actions/runs/15585113583/job/43889477889
# Introdution
Reverting introduced bug by
https://github.com/twentyhq/twenty/pull/12082
We need to address the bug that was "fixed" by this in order to refresh
the recordFilters state, will have a look with @lucasbordeau 🙏
# Introduction
Diff description: ~500 tests and +500 additions
close https://github.com/twentyhq/core-team-issues/issues/731
## What has been done here
In a nutshell on a field metadata type ( `SELECT MULTI_SELECT` ) update,
we will be browsing all `ViewFilters` in a post hook searching for some
referencing related updated `fieldMetadata` select. In order to update
or delete the `viewFilter` depending on the associated mutations.
## How to test:
- Add FieldMetadata `SELECT | MULTI_SELECT` to an existing or a new
`objectMetadata`
- Create a filtered view on created `fieldMetadata` with any options you
would like
- Remove some options ( in the best of the world some that are selected
by the filter ) from the `fieldMetadata` settings page
- Go back to the filtered view, removed or updated options should have
been hydrated in the `displayValue` and the filtered data should make
sense
## All filtered options are deleted edge case
If an update implies that a viewFilter does not have any existing
related options anymore, then we remove the viewFilter
## Testing
```sh
PASS test/integration/metadata/suites/field-metadata/update-one-field-metadata-related-record.integration-spec.ts (27 s)
update-one-field-metadata-related-record
SELECT
✓ should delete related view filter if all select field options got deleted (2799 ms)
✓ should update related multi selected options view filter (1244 ms)
✓ should update related solo selected option view filter (1235 ms)
✓ should handle partial deletion of selected options in view filter (1210 ms)
✓ should handle reordering of options while maintaining view filter values (1487 ms)
✓ should handle no changes update of options while maintaining existing view filter values (1174 ms)
✓ should handle adding new options while maintaining existing view filter (1174 ms)
✓ should update display value with options label if less than 3 options are selected (1249 ms)
✓ should throw error if view filter value is not a stringified JSON array (1300 ms)
MULTI_SELECT
✓ should delete related view filter if all select field options got deleted (1127 ms)
✓ should update related multi selected options view filter (1215 ms)
✓ should update related solo selected option view filter (1404 ms)
✓ should handle partial deletion of selected options in view filter (1936 ms)
✓ should handle reordering of options while maintaining view filter values (1261 ms)
✓ should handle no changes update of options while maintaining existing view filter values (1831 ms)
✓ should handle adding new options while maintaining existing view filter (1610 ms)
✓ should update display value with options label if less than 3 options are selected (1889 ms)
✓ should throw error if view filter value is not a stringified JSON array (1365 ms)
Test Suites: 1 passed, 1 total
Tests: 18 passed, 18 total
Snapshots: 18 passed, 18 total
Time: 27.039 s
```
## Out of scope
- We should handle ViewFilter validation when extracting its definition
from the metadata
https://github.com/twentyhq/core-team-issues/issues/1009
## Concerns
- Are we able through the api to update an RATING fieldMetadata ? ( if
yes than that's an issue and we should handle RATING the same way than
for SELECT and MULTI_SELECT )
- It's not possible to group a view from a MULTI_SELECT field
The above points create a double nor a triple "lecture" to the post hook
effect:
- ViewGroup -> only SELECT
- VIewFilter -> only SELECT || MULTI_SELECT
- Rating nothing
I think we should determine the scope of all of that
---------
Co-authored-by: Charles Bochet <charles@twenty.com>
# Introduction
Big diff a lot of tests and snapshots ( real diff < 500+ )
close https://github.com/twentyhq/twenty/issues/12117
close https://github.com/twentyhq/twenty/issues/12133
## What has been done here
Implemented a strong integration coverage on both fieldmetadata`SELECT`
`UPDATE` and `CREATE`.
Implemented server side validation for the options `value` `label` `id`
and collision issue with also `position`
We could improve:
- Position validation
- DefaultValue validation
## Update
```ts
PASS test/integration/metadata/suites/field-metadata/update-one-field-metadata-select.integration-spec.ts (41.054 s)
Field metadata select update tests group
✓ Update should succeed with provided option id (2565 ms)
✓ Update should succeed with valid default value (1469 ms)
✓ Update should succeed with various options id (1257 ms)
✓ Update should succeed without option id (1286 ms)
✓ Update should trim option values (1366 ms)
✓ Update should succeed with default value and no options (1122 ms)
✓ Update should fail with unknown default value and no options (1075 ms)
✓ Update should fail with only white spaces id (1195 ms)
✓ Update should fail with empty string id (1058 ms)
✓ Update should fail with null id (1066 ms)
✓ Update should fail with not a string id (1098 ms)
✓ Update should fail with too long id (1373 ms)
✓ Update should fail with only white spaces label (1034 ms)
✓ Update should fail with empty string label (1057 ms)
✓ Update should fail with null label (1100 ms)
✓ Update should fail with not a string label (1144 ms)
✓ Update should fail with too long label (1273 ms)
✓ Update should fail with only white spaces value (1385 ms)
✓ Update should fail with empty string value (1035 ms)
✓ Update should fail with null value (1068 ms)
✓ Update should fail with not a string value (1021 ms)
✓ Update should fail with too long value (1134 ms)
✓ Update should fail with invalid option id (1137 ms)
✓ Update should fail with empty options (1238 ms)
✓ Update should fail with invalid option value format (1104 ms)
✓ Update should fail with comma in option label (1004 ms)
✓ Update should fail with duplicated option values (1015 ms)
✓ Update should fail with duplicated option ids (1079 ms)
✓ Update should fail with duplicated option positions (1266 ms)
✓ Update should fail with duplicated trimmed option values (1220 ms)
✓ Update should fail with undefined option label (1029 ms)
✓ Update should fail with an invalid default value (1142 ms)
✓ Update should fail with an unknown default value (1081 ms)
✓ Update should fail with undefined option value (1086 ms)
Test Suites: 1 passed, 1 total
Tests: 34 passed, 34 total
Snapshots: 28 passed, 28 total
Time: 41.079 s
```
## Create
```ts
PASS test/integration/metadata/suites/field-metadata/create-one-field-metadata-select.integration-spec.ts (38.292 s)
Field metadata select creation tests group
✓ Create should succeed with provided option id (2096 ms)
✓ Create should succeed with valid default value (1316 ms)
✓ Create should succeed with various options id (1113 ms)
✓ Create should succeed without option id (1378 ms)
✓ Create should trim option values (1296 ms)
✓ Create should fail with only white spaces id (1000 ms)
✓ Create should fail with empty string id (1325 ms)
✓ Create should fail with null id (1060 ms)
✓ Create should fail with not a string id (1142 ms)
✓ Create should fail with too long id (1321 ms)
✓ Create should fail with only white spaces label (999 ms)
✓ Create should fail with empty string label (1163 ms)
✓ Create should fail with null label (1198 ms)
✓ Create should fail with not a string label (1678 ms)
✓ Create should fail with too long label (1527 ms)
✓ Create should fail with only white spaces value (1200 ms)
✓ Create should fail with empty string value (1102 ms)
✓ Create should fail with null value (1037 ms)
✓ Create should fail with not a string value (1462 ms)
✓ Create should fail with too long value (896 ms)
✓ Create should fail with invalid option id (997 ms)
✓ Create should fail with empty options (1058 ms)
✓ Create should fail with invalid option value format (1190 ms)
✓ Create should fail with comma in option label (1142 ms)
✓ Create should fail with duplicated option values (872 ms)
✓ Create should fail with duplicated option ids (860 ms)
✓ Create should fail with duplicated option positions (1002 ms)
✓ Create should fail with duplicated trimmed option values (1336 ms)
✓ Create should fail with undefined option label (754 ms)
✓ Create should fail with an invalid default value (696 ms)
✓ Create should fail with an unknown default value (678 ms)
✓ Create should fail with undefined option value (699 ms)
✓ Create should fail with null options (720 ms)
✓ Create should fail with undefined options (686 ms)
Test Suites: 1 passed, 1 total
Tests: 34 passed, 34 total
Snapshots: 29 passed, 29 total
Time: 38.314 s
```
## Conclusion
As always any suggestions are welcomed ! Please let me know
## Discussion about validation governance
### Front
Front side will be dealing with zod validations schema that he will
handle and maintain by himself
### Back validation instances
- Validation hold through DTO declarations ( run by yoga through the
resolvers )
- Server programmatic validation and exceptions handling ( run through
the services )
For this refactor/fix we decided to stick to the current implementation
only touching the `Server programmatic validation and exceptions
handling` we will handle validation centralization when we will onboard
the `nestjs-query` deprecation/integration refactor.
### Vision
In the best of the world we could think of an intermediary model that
will handle and take responsibility of the validation decorators that
would be run programmatically through the service, Yoga would still
consume it ? then we would need to have enough grain in the service to
know the input has already validated
## Notes
Introduced zod back side in order to handle very atomic and primitive
validation
# Introduction
Added a no-explicit-any rule to the twenty-server, not applicable to
tests and integration tests folder
Related to https://github.com/twentyhq/core-team-issues/issues/975
Discussed with Charles
## In case of conflicts
Until this is approved I won't rebased and handle conflict, just need to
drop two latest commits and re run the scripts etc
## Legacy
We decided not to handle the existing lint error occurrences and
programmatically ignored them through a disable next line rule comment
## Open question
We might wanna activate the
[no-explicit-any](https://typescript-eslint.io/rules/no-explicit-any/)
`ignoreRestArgs` for our use case ?
```
ignoreRestArgs?: boolean;
```
---------
Co-authored-by: etiennejouan <jouan.etienne@gmail.com>
# Introduction
Encountering a blocking issue due to legacy upgrade history in staging
due to relation refactor
For the moment ( release 0.53 ) swallowing
@charlesBochet
## How to test
```ts
checkout v0.52.11
yarn
database:reset
checkout 0.53
yarn
build server
migrate
upgrade
```
# Introduction
From my understand we're kinda hacking through the options parser by
defining class properties within them whereas we should be consuming the
return type value ? Have no time for this right now
Anw for some reason nestjs-commander enters several time the option
parse which result in duplicating the given workspaceId in the array
Added a Set to fix
close https://github.com/twentyhq/twenty/issues/11707
# Introduction
This PR refactors the way we previously manually handled the upgrade
command `versionTo` and `versionFrom` values to be replaced by a
programmatic inferring using the `APP_VERSION` env variable. It raises
new invariant edge cases that are covered by new tests and so on
Please keep in mind that an upgrade will run agnostically of any `patch`
semver value as it should be done only when releasing a `major/minor`
version update
[Related discord
thread](https://discord.com/channels/1130383047699738754/1368953221921505280)
## Testing in local
In order to test in local we have to define an `APP_VERSION` value in
`packages/twenty-server/.env` following semver ( or not 🙃 )
## Logs example
```ts
Computing new Datasource for cacheKey: 20202020-1c25-4d02-bf25-6aeccf7ea419-8 out of 0
query: SELECT * FROM current_schema()
query: SELECT version();
[Nest] 37872 - 05/06/2025, 4:07:21 PM LOG [UpgradeCommand] Initialized upgrade context with:
- currentVersion (migrating to): 0.53.0
- fromWorkspaceVersion: 0.52.0
- 2 commands
[Nest] 37872 - 05/06/2025, 4:07:21 PM LOG [UpgradeCommand] Upgrading workspace 20202020-1c25-4d02-bf25-6aeccf7ea419 from=0.52.0 to=0.53.0 1/2
[Nest] 37872 - 05/06/2025, 4:07:21 PM LOG [UpgradeCommand] Upgrade for workspace 20202020-1c25-4d02-bf25-6aeccf7ea419 ignored as is already at a higher version.
[Nest] 37872 - 05/06/2025, 4:07:21 PM LOG [UpgradeCommand] Running command on workspace 3b8e6458-5fc1-4e63-8563-008ccddaa6db 2/2
Computing new Datasource for cacheKey: 3b8e6458-5fc1-4e63-8563-008ccddaa6db-8 out of 0
query: SELECT * FROM current_schema()
query: SELECT version();
[Nest] 37872 - 05/06/2025, 4:07:21 PM LOG [UpgradeCommand] Upgrading workspace 3b8e6458-5fc1-4e63-8563-008ccddaa6db from=0.52.0 to=0.53.0 2/2
[Nest] 37872 - 05/06/2025, 4:07:21 PM LOG [UpgradeCommand] Upgrade for workspace 3b8e6458-5fc1-4e63-8563-008ccddaa6db ignored as is already at a higher version.
[Nest] 37872 - 05/06/2025, 4:07:21 PM LOG [UpgradeCommand] Command completed!
```
## Misc
Related to https://github.com/twentyhq/twenty/issues/11780
# Introduction
`upgrade` and `migrate` are not run every time even, but only once on
database creation, tho we're suggesting users they do as not requiring
manual run anymore since `0.50`
close https://github.com/twentyhq/twenty/issues/11671
# Introduction
Followup of https://github.com/twentyhq/twenty/pull/11784
Again some propaganda for the
[noUncheckedIndexedAccess](https://www.typescriptlang.org/tsconfig/#noUncheckedIndexedAccess)
that involved this @charlesBochet 👀
That's very risky to have this setup to false especially in the backend
regarding the twenty-server metadata nature
Also suggested that we do some integration testing ( e2e nestsJs tests )
on a related endpoint that could related we always retrieve the same
form result output
We could also do some unit testing of the method but like the idea to
ship it through the api itself
# Introduction
Fixes https://github.com/twentyhq/twenty/issues/11718
From having
[noUncheckedIndexedAccess](https://www.typescriptlang.org/tsconfig/#noUncheckedIndexedAccess)
set to false we have a flakiness resulting in a such bug right here as
the below operation can return `undefined` but not type as it should:
```ts
const recordId = allRecordIds[position.row];
```
About to create a Tech project about the topic, activating the flag ends
in 1500 typescript erros from the style solution compilation ( which
means can contains several duplicated errors )
# Introduction
Closes https://github.com/twentyhq/core-team-issues/issues/874
`TimeLineActivity` fields `` and `` were typed as required whereas in
reality are nullable, resulting in the related sentry error.
Refactored the type then the related components in order to handle
nullable use case
# Introduction
closes https://github.com/twentyhq/core-team-issues/issues/591
Same than for `twenty-shared` made in
https://github.com/twentyhq/twenty/pull/11083.
## TODO
- [x] Manual migrate twenty-website twenty-ui imports
## What's next:
- Generate barrel and migration script factorization within own package
+ tests
- Refactoring using preconstruct ? TimeBox
- Lint circular dependencies
- Lint import from barrel and forbid them
### Preconstruct
We need custom rollup plugins addition, but preconstruct does not expose
its rollup configuration. It might be possible to handle this using the
babel overrides. But was a big tunnel.
We could give it a try afterwards ! ( allowing cjs interop and stuff
like that )
Stuck to vite lib app
Closed related PRs:
- https://github.com/twentyhq/twenty/pull/11294
- https://github.com/twentyhq/twenty/pull/11203
# Introduction
Lately encountering a lot of out of memory error when running
twenty-front in watch mode with both TypeScript and lint checkers
```ts
Error: Worker terminated due to reaching memory limit: JS heap out of memory
at new NodeError (node:internal/errors:405:5)
at [kOnExit] (node:internal/worker:287:26)
at Worker.<computed>.onexit (node:internal/worker:209:20)
```
The existing configuration looks like this:
```ts
// packages/twenty-front/vite.config.ts
'cd ../.. && eslint packages/twenty-front --report-unused-disable-directives --max-warnings 0 --config .eslintrc.cjs',
```
This is wrong as computing the root eslintrc completely omitting
twenty-front's one ***and its ignorePattern*** so will be checking in
`node_modules` etc checking for project-structure :).
For example this a
[snippet](https://gist.github.com/prastoin/d7f8ad4ef5eb2f7732209b756a38094c)
of the above commands errors. We can see rule that should be disabled by
`eslintrc.react.cjs` extension made from twenty-front `eslintrc` :
```ts
/Users/paulrastoin/ws/twenty-two/packages/twenty-front/src/modules/settings/data-model/fields/forms/components/__stories__/SettingsDataModelFieldSettingsFormCard.stories.tsx
23:27 warning Forbidden non-null assertion @typescript-eslint/no-non-null-assertion
```
## Fixes
- consume the `twenty-front` package eslint configuration within the
vite lint checker
- eslint overrides extends are getting merged based on glob inclusion of
their files declarations
- any linted files should be included in one of our `tsconfig`
- removed redundant and counter-productive negative `ignorePatterns`, as
eslint will naturally only lint files within configuration file
directory by default which will result making it go through local
`node_modules` project structure
## Now
Less cpu usage <3.5 gb and faster
```ts
// from packages/twenty-front
TIMING=1 npx eslint . --report-unused-disable-directives --max-warnings 0 --config .eslintrc.cjs --debug
#...
Rule | Time (ms) | Relative
:-----------------------------------------------|----------:|--------:
project-structure/folder-structure | 19578.927 | 20.2%
prettier/prettier | 13746.156 | 14.2%
no-redeclare | 9546.570 | 9.9%
@nx/workspace-explicit-boolean-predicates-in-if | 8167.805 | 8.4%
@typescript-eslint/no-unused-vars | 6872.803 | 7.1%
import/no-relative-packages | 6577.273 | 6.8%
@nx/enforce-module-boundaries | 6520.945 | 6.7%
import/no-duplicates | 4987.476 | 5.2%
react/no-direct-mutation-state | 2323.082 | 2.4%
react/require-render-return | 1155.261 | 1.2%
```
## Conclusion
Please note that `nx linter` might not be as strict as vite config
eslint runner
---------
Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
# Introduction
As we deploy patch from the main branch we've ship the upgrade for the
`0.51` within the `0.50`.
We should only do that when about to release
We should find a way for this not to occur again
# Introduction
Due to winter to summer timezone update, it shown that we have some unit
tests flakiness due to both mocked and unmocked date.now invokation
between app bootstrap and test bootstrap
This PR does not refactor this behavior
Just fix the currently failing test
## Note
Removed a duplicated file
# Introduction
In this PR using the Ts AST dynamically compute what to export,
gathering non-runtime types and interface in an `export type`
[Export type TypeScript
documentation](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html)
From
```ts
// index.ts
export * from "submodule"
```
To
```ts
export type { SomeType } from "submodule";
export { SomeFunction, SomeConst } from "submodule";
```
close https://github.com/twentyhq/core-team-issues/issues/644
## Motivations
- Most explicit and maintainable
- Best for tree-shaking
- Clear dependency tracking
- Prevents name collisions
## Important note
Please keep in mind that I will create, very soon, a dedicated
`generate-barrel` package in our yarn workspaces in order to:
- Make it reusable for twenty-ui
- Split in several files
- Setup lint + tsconfig
- Add tests
## Conclusion
As usual any suggestions are more than welcomed !
# Introduction
In this PR we've migrated `twenty-shared` from a `vite` app
[libary-mode](https://vite.dev/guide/build#library-mode) to a
[preconstruct](https://preconstruct.tools/) "atomic" application ( in
the future would like to introduce preconstruct to handle of all our
atomic dependencies such as `twenty-emails` `twenty-ui` etc it will be
integrated at the monorepo's root directly, would be to invasive in the
first, starting incremental via `twenty-shared`)
For more information regarding the motivations please refer to nor:
- https://github.com/twentyhq/core-team-issues/issues/587
-
https://github.com/twentyhq/core-team-issues/issues/281#issuecomment-2630949682
close https://github.com/twentyhq/core-team-issues/issues/589
close https://github.com/twentyhq/core-team-issues/issues/590
## How to test
In order to ease the review this PR will ship all the codegen at the
very end, the actual meaning full diff is `+2,411 −114`
In order to migrate existing dependent packages to `twenty-shared` multi
barrel new arch you need to run in local:
```sh
yarn tsx packages/twenty-shared/scripts/migrateFromSingleToMultiBarrelImport.ts && \
npx nx run-many -t lint --fix -p twenty-front twenty-ui twenty-server twenty-emails twenty-shared twenty-zapier
```
Note that `migrateFromSingleToMultiBarrelImport` is idempotent, it's atm
included in the PR but should not be merged. ( such as codegen will be
added before merging this script will be removed )
## Misc
- related opened issue preconstruct
https://github.com/preconstruct/preconstruct/issues/617
## Closed related PR
- https://github.com/twentyhq/twenty/pull/11028
- https://github.com/twentyhq/twenty/pull/10993
- https://github.com/twentyhq/twenty/pull/10960
## Upcoming enhancement: ( in others dedicated PRs )
- 1/ refactor generate barrel to export atomic module instead of `*`
- 2/ generate barrel own package with several files and tests
- 3/ Migration twenty-ui the same way
- 4/ Use `preconstruct` at monorepo global level
## Conclusion
As always any suggestions are welcomed !
# Introduction
While running https://github.com/twentyhq/twenty/pull/10960 scripts
discovers few issues:
- Invalid named folder `pre-hooks.ts`
- Mock consuming outbound imported module resulting in consumed before
initialization
# Introduction
We want theses configurations to be strictly typed but needed as in
https://github.com/twentyhq/twenty/pull/10960 will browse through all
TypeScript files within the codebase
# Introduction
close https://github.com/twentyhq/core-team-issues/issues/487
Updated the seeders to infer the workspace's version from the
`APP_VERSION` env var
To test in local run: `npx nx database:reset twenty-server` with either
a defined or not defined `APP_VERSION` in your `.env`
( note that invalid semver values will throw an error and stop the
process ) ( valid version ex: `APP_VERSION=1.0.0`)
# Introduction
We want the APP_VERSION to be able to contains pre-release options, in a
nutshell to be semVer compatible.
But we want to have workspace, at least for the moment, that only store
`x.y.z` and not `vx.y.z` or `x.y.z-alpha` version in database
Explaining this refactor
Related https://github.com/twentyhq/twenty/pull/10907
# Introduction
Under the hood class-validator isSemver uses
https://github.com/validatorjs/validator.js/blob/master/src/lib/isSemVer.js
which does not cover all semVer use cases
## Even tho
Had a discussion with @charles was about to store in db ws version as
`vx.y.z`. We felt like we wanted it to be stored as `x.y.z`, in my
opinion `APP_VERSION` should reflect the tag used to be build the
instance and not be updated
But we could extract only `x.y.z` from it at runtime
Also handling the `v` extraction in CD is IMO not the most reliable
## Env var logging refactor
Now not stopping on first error log
```ts
Successfully compiled: 2128 files with swc (185.34ms)
Watching for file changes.
[Nest] 52686 - 03/14/2025, 6:28:33 PM ERROR PG_DATABASE_URL should not be null or undefined
PG_DATABASE_URL must be a URL address
[Nest] 52686 - 03/14/2025, 6:28:33 PM ERROR APP_VERSION must be a valid semantic version (e.g., 1.0.0)
/Users/paulrastoin/ws/twenty/packages/twenty-server/src/engine/core-modules/environment/environment-variables.ts:1019
throw new Error("Environment variables validation failed")
^
Error: Environment variables validation failed
at Object.validate (/Users/paulrastoin/ws/twenty/packages/twenty-server/src/engine/core-modules/environment/environment-variables.ts:1019:11)
at Function.forRoot (/Users/paulrastoin/ws/twenty/node_modules/@nestjs/config/dist/config.module.js:67:45)
at Object.<anonymous> (/Users/paulrastoin/ws/twenty/packages/twenty-server/src/engine/core-modules/environment/environment.module.ts:11:18)
at Module._compile (node:internal/modules/cjs/loader:1256:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1310:10)
at Module.load (node:internal/modules/cjs/loader:1119:32)
at Function.Module._load (node:internal/modules/cjs/loader:960:12)
at Module.require (node:internal/modules/cjs/loader:1143:19)
at require (node:internal/modules/cjs/helpers:121:18)
at Object.<anonymous> (/Users/paulrastoin/ws/twenty/packages/twenty-server/dist/src/database/typeorm/typeorm.module.js:14:28)
```
# Introduction
We want any new activated workspace to be filled with a version equal to
the current `APP_VERSION`
Please note that in a workspace lifecycle this operation will be run
only once, discussed with @charlesBochet in front of `3 fois plus de
piments`
Going straightforward in this PR in order to release asap
Started et will continue to implem new integrations regarding `SignUp`
and `ActivateWorkspace` happy and expections path in
https://github.com/twentyhq/twenty/tree/prastoin-new-workspace-has-version-integrations-tests
# Introduction
In https://github.com/twentyhq/twenty/pull/10751 we decided not to put
`APP_VERSION` references in `.env.example` as it's programmatically
defined by our CD and should not be override by any manual interaction.
Still, as a dev testing the upgrade command in local, if you do not set
the `APP_VERSION` in local you will encounter the following error:
```ts
'Cannot run upgrade command when APP_VERSION is not defined'
```
@guillim currently doing the release legitimately raised that it was not
very intuitive
## Levers
- Improve error message such as adding reference to checking env
variables
- App local upgrade command dev dedicated documentation ?
## Conclusion
Any suggestions are more than welcomed !
# Introduction
Refactored the upgrade command to be more intuitive to anyone wanting to
add a command to the next relase upgrade instance
Also updated the upgrade command for the next 0.44 release
# Introduction
This PR contains a big test file and few snapshots
Related to https://github.com/twentyhq/core-team-issues/issues/487
## New env var `APP_VERSION`
Now will be injected directly in a built docker image the twenty's built
version. Inferred from the build git tag name.
Which mean on main or other `not a tag version` built APP_VERSION will
be `null`
## New upgrade-commander-runner
Refactored the upgrade command to be more strict regarding:
- Version management
- Sync metadata command always run
- Added failing workspaces aggregator + logs on cleanup
From now on the `upgrade` command will compare the `WORKSPACE_VERSION`
to the `APP_VERSION` in order to bypass any workspace version != than
the upgrade version `fromVersion`
## Existing commands
Note that the version validation will be done only when passing by the
`upgrade` command.
Which means that running the following command
`upgrade:x.y-some-specific-command` won't result in workspace version
mutation
This is to enforce that all an upgrade commands + sync-metadata has been
run on a workspace
## Will do in other PR but related
### New workspace
New workspace will now be inserted with version equal to the APP_VERSION
they've been created by
### Old workspace
Will create a command that should be ran outside of any `upgrade-runner`
extending command, the command will have to be ran on every workspace
before making the next release upgrade
This command iterates over any active and suspended workspace that has
`version` to `NULL` in order to update it `APP_VERSION` -1 minor
### SENTRY_RELEASE
- Either deprecate SENTRY_RELEASE in favor of `APP_VERSION` => What
about main with null version ? or create a new env var that would be
`APP_COMMIT_SHA` instead of SENTRY third party ref
### Update CD to inject APP_VERSION from branch name
### Update docs and release logs
Adding documentation for `APP_VERSION`
## Related PRs:
https://github.com/twentyhq/twenty-infra/pull/181
# Introduction
This PR contains several SNAPSHOT files explaining big +
While refactoring the Object Model settings page in
https://github.com/twentyhq/twenty/pull/10653, encountered a critical
issue when submitting either one or both names with `""` empty string
hard corrupting a workspace.
This motivate this PR reviewing server side validation
I feel like we could share zod schema between front and back
## Refactored server validation
What to expect from Names:
- Plural and singular have to be different ( case insensitive and
trimmed check )
- Contains only a-z A-Z and 0-9
- Follows camelCase
- Is not empty => Is not too short ( 1 )
- Is not too long ( 63 )
- Is case insensitive( fooBar and fOoBar now rejected )
What to expect from Labels:
- Plural and singular have to be different ( case insensitive and
trimmed check )
- Is not empty => Is not too short ( 1 )
- Is not too long ( 63 )
- Is case insensitive ( fooBar and fOoBar now rejected )
close https://github.com/twentyhq/twenty/issues/10694
## Creation integrations tests
Created new integrations tests, following
[EachTesting](https://jestjs.io/docs/api#testeachtablename-fn-timeout)
pattern and uses snapshot to assert errors message. These tests cover
several failing use cases and started to implement ones for the happy
path but object metadata item deletion is currently broken unless I'm
mistaken @Weiko is on it
## Notes
- [ ] As we've added new validation rules towards names and labels we
should scan db in order to standardize existing values using either a
migration command or manual check
- [ ] Will review in an other PR the update path, adding integrations
tests and so on
# Introduction
This PR contains around ~+300 tests + snapshot additions
Please check both object model creation and edition
Closes https://github.com/twentyhq/core-team-issues/issues/355
Refactored into two agnostic forms the Object Model settings page for
instance `/settings/objects/notes#settings`.
## `SettingsDataModelObjectAboutForm`
Added a new abstraction `SettingsUpdateDataModelObjectAboutForm` to wrap
`SettingsDataModelObjectAboutForm` in an `update` context

Schema:
```ts
const requiredFormFields = objectMetadataItemSchema.pick({
description: true,
icon: true,
labelPlural: true,
labelSingular: true,
});
const optionalFormFields = objectMetadataItemSchema
.pick({
nameSingular: true,
namePlural: true,
isLabelSyncedWithName: true,
})
.partial();
export const settingsDataModelObjectAboutFormSchema =
requiredFormFields.merge(optionalFormFields);
```
## `SettingsDataModelObjectSettingsFormCard`
Update on change

Schema:
```ts
export const settingsDataModelObjectIdentifiersFormSchema =
objectMetadataItemSchema.pick({
labelIdentifierFieldMetadataId: true,
imageIdentifierFieldMetadataId: true,
});
```
## Error management and validation schema
Improved the frontend validation form in order to attest that:
- Names are in camelCase
- Names are differents
- Names are not empty string ***SHOULD BE DONE SERVER SIDE TOO*** ( will
in a next PR, atm it literally breaks any workspace )
- Labels are differents
- Labels aren't empty strings
Hide the error messages as we need to decide what kind of styling we
want for our errors with forms
( Example with error labels )

# Introduction
close#9965
When landing on twenty you should be able to see a white screen
flickering if you had setup dark mode.
This is because before the SPA has been loaded we're not displaying
anything, which in a white screen from the browser.
During this period we should display a background color following the
user's device theme.
## Reproduction
In order to reproduce this behavior define a fast 4G connection from
your network console.
## Cons
Device mode might not the one chosen afterwards when the user has been
authenticated
=> We should store appearance settings in the local storage in order to
optimistically render the default "loading" background ( wouldn't be
100% bullet proof for instance if the user is now unauth for some reason
)
Body background will be override by theme after app bootstrap
## Introduction
Added coverage on the `useDeleteOneRecord` hooks, especially its
optimistic behavior feature.
Introduced a new testing tool `InMemoryTestingCacheInstance` that has
builtin very basic expectors in order to avoid future duplication when
covering others record hooks `update, create, destroy` etc etc
## Notes
Added few comments in this PR regarding some builtin functions I've
created around companies and people mocked object model and that I think
could be cool to spread and centralize within a dedicated "class
template"
Also put in light that unless I'm mistaken some tests are running on
`RecordNode` and not `RecordObject`
Took few directions on my own that as I always I would suggestion nor
remarks on them !
Let me know
## Misc
- Should we refactor `useDeleteOneRecord` tests to follow `eachTesting`
pattern ? => I feel like this is inappropriate as this hooks is already
high level, the only plus value would be less tests code despite
readability IMO
# Introduction
Historically we've been programmatically running sync metadata just
after all upgrade command's migration.
Adding back this behavior as default to the new dynamic modules
Duplicated already existing synchronize metadata logic as a quick fix as
we're about to iterate over commands next sprint
## Introduction
This is PR is a suggestion ! And should be discussed
With yarn `^4`, during installation won't raise an error if current dev
env does not satisfies the `engines` policy.
We have usually 10+ contributors support request regarding higher node
version issue per week
I would have preferred a very declarative integration using npm
[engines](https://docs.npmjs.com/cli/v11/configuring-npm/package-json#engines)
but this does not seems to be natively supported by `yarn`
We should keep in mind that this might block any machines from our CICD
if they have diff node version installed ( such as running the project
on a different node version could result in bugs too )
## Implem
Created a yarn [constraints](https://yarnpkg.com/features/constraints)
run after each installation that checking if current node version
satisfies defined engines range ( might also be done for others engines
entries )
I assume we will always have the same engines policy for every packages,
at least that's not a consideration from now
## Further
We could refactor our package.json engines into only one using
`Yarn.set` etc
## Resource
- https://yarnpkg.com/configuration/yarnrc
- https://yarnpkg.com/features/constraints
## Note
- Not running constraints in `preInstall` hook as won't be effective on
fresh install
-
[engine-strict](https://docs.npmjs.com/cli/v8/using-npm/config#engine-strict)
is an npm-config
-
[devEngines](https://docs.npmjs.com/cli/v11/configuring-npm/package-json#devengines)
are npm feature too ( for instance pnpm current PR
https://github.com/pnpm/pnpm/issues/8153 )
## Conclusion
As always any suggestions are more than welcomed !
# Introduction
In this PR https://github.com/twentyhq/twenty/pull/10493 introduced a
regression on optimistic cache for record creation, by expecting a
`position` `fieldMetadataItem` on every `ObjectMetadataItem` which is a
wrong assertion
Some `Tasks` and `ApiKeys` do not have one
## Fix
Dynamically compute optimistic record input position depending on
current `ObjectMetadataItem`
## Refactor
Refactored a failing test following [jest
each](https://jestjs.io/docs/api#describeeachtablename-fn-timeout)
pattern to avoid error prone duplicated env tests. Created a "standard'
and applied it to an other test also using `it.each`.
## Introduction
This refactor results from this
https://github.com/twentyhq/twenty/pull/10493 review
Introduced a new abstraction to the extinsting
`generateDepthOneRecordGqlFields` that was accepting an optional record
in arg in order to map generated `recordGqlFields` to the keys in the
record
1/ Created a dedicated util method
`generateDepthOneRecordGqlFieldsFromRecord` to do so
2/ Updated each previous `generateDepthOneRecordGqlFields` passing a
record to call new `generateDepthOneRecordGqlFieldsFromRecord`
# Introduction
The record does not appear in the table because the optimistic record
input cached does not fulfill the mutation response fields, which result
in it being considered as invalid response
close#10199
close https://github.com/twentyhq/twenty/issues/10153
# Introduction
closes#10196
Initially fixing the `Account Owner` record field value should not be
clickable and redirects on current page bug.
This has been fixed computing whereas the current filed is a workspace
member dynamically rendering a stale Chip components instead of an
interactive one
## Refactor
Refactored the `AvatarChip` `to` props logic to be scoped to lower level
scope `Chip`.
Now we have `LinkChip` `Chip`, `LinkAvatarChip` and `AvatarChip` all
exported from twenty-ui.
The caller has to determine which one to call from the design system
## New rule regarding chip links
As discussed with @charlesBochet and @FelixMalfait
A chip link will now ***always*** have `to` defined. ( and optionally an
`onClick` ).
`ChipLinks` cannot be used as buttons anymore
## Factorization
Deleted the `RecordIndexRecordChip.tsx` file ( aka
`RecordIdentifierChip` component ) that was duplicating some logic,
refactored the `RecordChip` in order to handle what was covered by
`RecordIdentifierChip`
## Conclusion
As always any suggestions are more than welcomed ! Took few opinionated
decision/refactor regarding nested long ternaries rendering `ReactNode`
elements
## Misc
https://github.com/user-attachments/assets/8ef11fb2-7ba6-4e96-bd59-b0be5a425156
---------
Co-authored-by: Mohammed Razak <mohammedrazak2001@gmail.com>
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
# Introduction
Encountered in issue in production where we have a lot of records that
has RICH_TEXT_FIELD set to `{}`
```sh
[Nest] 20106 - 02/19/2025, 12:43:08 PM LOG [MigrateRichTextFieldCommand] Generating markdown for 1 records
[Nest] 20106 - 02/19/2025, 12:43:09 PM LOG [MigrateRichTextFieldCommand] Error in workspace 3b8e6458-5fc1-4e63-8563-008ccddaa6db: TypeError: o is not iterable
```
## Fix
While reading `fieldValue` definition also strictly check if it's `{}` +
checking after JSON parse if it's an iterable to pass to the
`serverBlockNoteEditor` in order to be 100 bullet proof for prod
migration command
## Refactor Dry run
Implemented dry run
## Refactor to Idempotency
Made the script idempotent in order to avoid issues with re-running
commands
## Error repro
- In local checkout on v0.41.5 run `yarn && npx nx reset && npx nx
start`
- Create record manually in db that has a RICH_TEXT body to `{}`
- Checkout to main, `yarn && npx nx reset && npx nx build twenty-server
&& yarn command:prod upgrade-0.42:migrate-rich-text-field -d`
# Introduction
Just a nitpick resulting from
https://github.com/twentyhq/twenty/pull/10205
Avoid any possible race condition between competing event handlers by
closing dropdown before opening modal
# Introduction
Upgrade guide from 0.41.0 to 0.42.0
## Note
@guillim I've been searching for references to the new `env vars` added
in the Microsoft scope to the version to the `setup.mdx` page, unless
I'm mistaken `IS_MICROSOFT_SYNC_ENABLED` seems to be missing ? I'm not
sure if it's required or not and on where to add it within the page,
could you please give it a look 🙏 ?
# Introduction
While importing records encountering missing expected fields when
writting a fragment from apollo cache
## Updates
### 1/ `createdBy` Default value
When inserting in cache in create single or many we will now make
optimistic behavior on the createdBy value
### 2/ `createRecordInCache` dynamically create `recordGrqlFields`
When creating an entry in cache, we will now dynamically generate fields
to be written in the fragment instead of expecting all of them. As by
nature record could be partial
### 3/ Strictly typed `RecordGqlFields`
# Conclusion
closes#9927
# Introduction
At the moment when updating any record cache occurence, we will build a
fragment that will expect all of the object metadata item fields to be
provided.
Which result in the following traces: ( in the video companies aren't
fetch with companyId and other missing fields )
https://github.com/user-attachments/assets/56eab7c1-8f01-45ff-8f5d-78737b788b92
By definition as we're using graphql we might not request every record's
fields each time we wanna consume them.
In this way we will now dynamically compute or expect depending on the
CRUD operation specific fields to be written in the cache, and not all
of them
Tested all optimistic and failure management use cases
## Covering cache
Added coverage only for the `deleteOne` and `deleteMany` hooks, it cover
only the record record cache and not its relations hydratation ( for the
moment )
## Why not closing #9927
Unless I'm mistaken everything done here have fixed the same logs/traces
issue for updates and deletion but not creation.
Which means we still need to investigate the mass upload from import and
prefillRecord behavior
In a nutshell: went over each `updateRecordFromCache` calls, still need
to do all `createRecordInCache` calls
related to #9927
## Conlusion
Sorry for the big PR should have ejected into a specific one for the
`MinimalRecord` refactor
Will also continue covering others hooks later in my week as for the
`deleteOne`
As always any suggestions are welcomed !
# Introduction
Disabled backfilling position process on single record update
It might be a too global solution ? feels a bit too easy tbh
Please let me know, could not think of other side-effects
close [#9925](https://github.com/twentyhq/twenty/issues/9925)
# Introduction Nitpick
Action's record has two entries with `position: 0`
Unless I'm mistaken I could not find any place where the `position`
property is consumed
So this is just for sake of the +1 suite
# Introduction
Added destroy many records to the `WorkflowActionConfig`
## Repro:
- Filter by deleted workflow
- Select mulitple rows
- Click on destroy
# Pinned action standardization
After discussion with @Bonapara and @bosiraphael we landed on a
standardization of the pinned actions between `DefaultActionsConfigV2`
and `WorkflowActionConfig` which means that now are pinned the `DELETE`
and `DESTROY` for both `single/multiple` modes for both features
Related to https://github.com/twentyhq/twenty/pull/9991
# Introduction
When we create a new `view` from record table that has relation such as
opportunities.
Encountered invariant conditions:
## Unknown fiel `__typename`
`Should never occur, encountered unknown fields __typename in
objectMetadaItem viewGroup`,
### Fixed by ignoring unknown internal fields
## Provided both relation `view` and `viewId`
`Should never provide relation mutation through anything else than the
fieldId e.g companyId and not company, encountered: view`
### Fixed by sending only `viewId` to `createManyRecords` in
`usePersistViewGroupRecords.ts`
# Introduction
Added the `RecordAction` destroy multiple record
## Repro
Select multiples `deletedRecords`, you should be able to see the
`Destroy` pinned CTA ( iso short label with the destroy one ), open
control panel and fin new CTA `Permanently delete records`
https://github.com/user-attachments/assets/31ee8738-9d61-4dec-9a1f-41bb6785e018
## TODO
- [ ] Gain granularity within tests to assert the action should be
registered only when filtering by deleted
## Conclusion
Closes https://github.com/twentyhq/core-team-issues/issues/110
# Introduction
Defined `dependsOn` for each nx project's configuration that has a
dependency to another local package ( ui, shared ).
As follows:
```json
"dependsOn": ["^build"]
```
Where the `^` symbol means "all dependencies of this project"
Now on a fresh repo, no built or install deps after install dependencies
you can directly hit `npx nx build PROJECT_NAME`
closes https://github.com/twentyhq/core-team-issues/issues/371
Related what was failing
[run](https://github.com/twentyhq/twenty-infra/actions/runs/13141544809/job/36669643182)
Cancelled before deploy, attested build was correct within the publish
and digest
# Introduction
Avoid having multiple `isDefined` definition across our pacakges
Also avoid importing `isDefined` from `twenty-ui` which exposes a huge
barrel for a such little util function
## In a nutshell
Removed own `isDefined.ts` definition from `twenty-ui` `twenty-front`
and `twenty-server` to move it to `twenty-shared`.
Updated imports for each packages, and added explicit dependencies to
`twenty-shared` if not already in place
Related PR https://github.com/twentyhq/twenty/pull/9941
# Introduction
This PR is highly related to previous optimistic cache refactor:
https://github.com/twentyhq/twenty/pull/9881
Here we've added some logic within the
`triggerUpdateRelationsOptimisticEffect` which will now run if given
recordInput `deletedAt` field is defined.
If deletion, we will iterate over all the fields searching for
`RELATION` for which deletion might implies necessity to detach the
relation
## Known troubleshooting ( also on main )

We might have to refactor the `prefillRecord` to spread and
overrides`inputValue` over defaultOne as inputValue could be a partial
one for more info please a look to
# Conclusion
Any suggestions are welcomed !
fixes https://github.com/twentyhq/twenty/issues/9580
---------
Co-authored-by: Charles Bochet <charles@twenty.com>
# Introduction
~~this could be cool for the updateRecordFromCache to return the updated
record, so we could consume its return value more explicitly such as
`updatedRecordValue`~~
In fact this is nitpick as it would really be the same than returning
the received params
## Fixes duplicated optimistic cache upsert
<img
src="https://github.com/user-attachments/assets/289f4801-5b67-4e4e-a87b-a512deb5180c"
width="300px" height="300px">
We were before comparing the previously `cachedRecord` which is now, not
the latest as the optimistic is (should) be working successfully since
https://github.com/twentyhq/twenty/pull/9881
## Reproduction
1- Open any Company
2- Attach an Opportunity it should appears only once
3bis- If you revert the last branch commit it will appear duplicated
Related to #9580