isCustom deprecation for Objects and Fields (#21228)

## Context

`isCustom` was a legacy denormalized boolean on `ObjectMetadataEntity`
and `FieldMetadataEntity`.
Now that every metadata row carries `applicationId` (via
`SyncableEntity`), "is this custom" is fully derivable, and the stored
boolean was a redundant second source of truth that could drift.

The real meaning of `isCustom` is **"the owning application is not the
twenty-standard application"** — i.e. `!belongsToTwentyStandardApp`.
Note this is *not* "belongs to the workspace custom app" as I initially
thought: third-party-application
objects/fields are custom too. 
The standard application has a globally stable `universalIdentifier`, so
the value derives with no per-workspace lookup.

## Changed
## `isCustom` checks — before → after

`isCustom` is no longer a stored column. The table below lists every
site that branched on it and how it resolves now. The unifying rule:
`isCustom ≡
!isTwentyStandardApplicationUniversalIdentifier(applicationUniversalIdentifier)`.

### Server — behavioural checks

| Location | Purpose | Before | Now |
|---|---|---|---|
| `utils/compute-object-target-table.util.ts` | Physical table name `_`
prefix | `computeTableName(nameSingular, objectMetadata.isCustom)` |
derives from `applicationUniversalIdentifier` (single source for all
table-name callers) |
| `twenty-orm/factories/entity-schema.factory.ts` +
`…/entity-schema-metadata.type.ts` | ORM table name (hot path) |
`object.isCustom` | `object.applicationId !== standardApplicationId`
(computed in `buildEntitySchemaMetadataMaps`) |
|
`twenty-orm/repository/workspace-{delete,soft-delete,update}-query-builder.ts`
| Table name for mutations | `computeTableName(nameSingular,
objectMetadata.isCustom)` | `computeObjectTargetTable(objectMetadata)` |
| `index-metadata/utils/generate-deterministic-index-name-v2.ts` | Index
name hash (must stay bit-identical) | `flatObjectMetadata.isCustom` |
derives from `applicationUniversalIdentifier` |
| `object-metadata/object-record-count.service.ts` | Table name for
record count | `computeTableName(nameSingular, isCustom)` |
`computeObjectTargetTable(flatObjectMetadata)` |
|
`workspace-manager/dev-seeder/data/services/dev-seeder-data.service.ts`
| Match seed config by table name | `computeTableName(item.nameSingular,
item.isCustom)` | `computeObjectTargetTable(item)` |
| `commands/workspace-export/workspace-export.service.ts` +
`…/utils/generate-workspace-schema-ddl.util.ts` | Export table name (raw
entity) | `objectMetadata.isCustom` |
`!isTwentyStandard…(objectMetadata.application?.universalIdentifier)` |
|
`flat-field-metadata/services/flat-field-metadata-type-validator.service.ts`
| Block users creating reserved field types |
`args.flatEntityToValidate.isCustom` |
`!args.flatEntityToValidate.isSystem` |
| `api/common/.../common-create-many-query-runner.service.ts` | Don't
let client overwrite system `createdBy` |
`createdByFieldMetadata.isCustom === false` |
`createdByFieldMetadata.isSystem === true` |
|
`field-metadata/utils/resolve-field-metadata-standard-override.util.ts`
| Skip i18n/overrides for custom fields | `if (fieldMetadata.isCustom)
return raw` | **removed** — falls through on
`isDefined(standardOverrides)` |
|
`object-metadata/utils/resolve-object-metadata-standard-override.util.ts`
| Skip i18n/overrides for custom objects | `if (objectMetadata.isCustom)
return raw` | **removed** — same fall-through |
|
`command-menu-item/utils/build-navigation-interpolation-context.util.ts`
| Override context for nav labels | passed `isCustom` into resolver |
dropped (resolver no longer needs it) |
| `api/common/.../data-arg-processor.service.ts` | `isCustom` for
record-position table name | `flatObjectMetadata.isCustom` | derives
from `applicationUniversalIdentifier` |
| `metadata-modules/minimal-metadata/minimal-metadata.service.ts` |
Minimal DTO + override context | `flatObjectMetadata.isCustom` | derives
from `applicationUniversalIdentifier` |
|
`commands/upgrade-version-command/1-23/…backfill-record-page-layouts.command.ts`
| Filter to custom objects | `objectMetadata.isCustom` |
`!isTwentyStandard…(applicationUniversalIdentifier)` |

### Server — DTO / API population

| Location | Before | Now |
|---|---|---|
|
`flat-object-metadata/utils/from-flat-object-metadata-to-object-metadata-dto.util.ts`
| passthrough `isCustom` | derives from `applicationUniversalIdentifier`
|
|
`flat-field-metadata/utils/from-flat-field-metadata-to-field-metadata-dto.util.ts`
| passthrough `isCustom` | derives from `applicationUniversalIdentifier`
|
|
`object-metadata/utils/from-object-metadata-entity-to-object-metadata-dto.util.ts`
(REST) | `entity.isCustom` | `entity.applicationId !==
standardApplicationId` |
|
`field-metadata/utils/from-field-metadata-entity-to-field-metadata-dto.util.ts`
(REST) | `entity.isCustom` | `entity.applicationId !==
standardApplicationId` |
| `dataloaders/dataloader.service.ts` | passed
`flatFieldMetadata.isCustom` into override resolver | dropped (resolver
no longer needs it) |

> REST controllers (`object-metadata.controller.ts`,
`field-metadata.controller.ts`) resolve `standardApplicationId` once per
request from the cached `flatApplicationMaps`.

### Frontend

| Location | Purpose | Before | Now |
|---|---|---|---|
| `settings/.../SettingsObjectFieldDisabledActionDropdown.tsx` | Whether
an inactive field is deletable | `isDeletable = isCustomField` |
`isDeletable = isCustomField && !isSystemField` |

### Unchanged (out of scope)

`isCustom` on `IndexMetadata` / `View` / `Skill` / `Agent` and their
guards still read the persisted column.

Breaking change is on the isCustom filter on field and object APIs, this
is never used in the FE and unlikely used by external consumers
This commit is contained in:
Weiko
2026-06-09 15:57:19 +02:00
committed by GitHub
parent 7530775dc1
commit 9c66975520
129 changed files with 502 additions and 538 deletions
@@ -1,5 +1,5 @@
import { MetadataApiClient } from 'twenty-client-sdk/metadata';
import { APPLICATION_UNIVERSAL_IDENTIFIER } from 'src/application.config';
import { MetadataApiClient } from 'twenty-client-sdk/metadata';
import { describe, expect, it } from 'vitest';
describe('App installation', () => {
@@ -7,11 +7,7 @@ describe('App installation', () => {
const client = new MetadataApiClient();
const result = await client.query({
findManyApplications: {
id: true,
name: true,
universalIdentifier: true,
},
findManyApplications: { id: true, name: true, universalIdentifier: true },
});
const app = result.findManyApplications.find(
@@ -29,10 +25,7 @@ describe('PostCard object', () => {
const { objects } = await client.query({
objects: {
__args: {
filter: { isCustom: { is: true } },
paging: { first: 50 },
},
__args: { paging: { first: 50 } },
edges: {
node: {
nameSingular: true,
@@ -59,5 +52,4 @@ describe('PostCard object', () => {
expect(names).toContain('deliveredAt');
expect(names).toContain('recipient');
});
});
@@ -476,7 +476,7 @@ type Field {
description: String
icon: String
standardOverrides: StandardOverrides
isCustom: Boolean
isCustom: Boolean @deprecated(reason: "isCustom is derived from the owning application and will be removed; a field is custom when it does not belong to the twenty-standard application.")
isActive: Boolean
isSystem: Boolean
isUIReadOnly: Boolean
@@ -587,7 +587,6 @@ input ObjectFilter {
and: [ObjectFilter!]
or: [ObjectFilter!]
id: UUIDFilterComparison
isCustom: BooleanFieldComparison
isRemote: BooleanFieldComparison
isActive: BooleanFieldComparison
isSystem: BooleanFieldComparison
@@ -645,7 +644,7 @@ type Object {
standardOverrides: ObjectStandardOverrides
shortcut: String
color: String
isCustom: Boolean!
isCustom: Boolean! @deprecated(reason: "isCustom is derived from the owning application and will be removed; an object is custom when it does not belong to the twenty-standard application.")
isRemote: Boolean!
isActive: Boolean!
isSystem: Boolean!
@@ -680,7 +679,6 @@ input FieldFilter {
and: [FieldFilter!]
or: [FieldFilter!]
id: UUIDFilterComparison
isCustom: BooleanFieldComparison
isActive: BooleanFieldComparison
isSystem: BooleanFieldComparison
isUIReadOnly: BooleanFieldComparison
@@ -360,6 +360,7 @@ export interface Field {
description?: Scalars['String']
icon?: Scalars['String']
standardOverrides?: StandardOverrides
/** @deprecated isCustom is derived from the owning application and will be removed; a field is custom when it does not belong to the twenty-standard application. */
isCustom?: Scalars['Boolean']
isActive?: Scalars['Boolean']
isSystem?: Scalars['Boolean']
@@ -436,6 +437,7 @@ export interface Object {
standardOverrides?: ObjectStandardOverrides
shortcut?: Scalars['String']
color?: Scalars['String']
/** @deprecated isCustom is derived from the owning application and will be removed; an object is custom when it does not belong to the twenty-standard application. */
isCustom: Scalars['Boolean']
isRemote: Scalars['Boolean']
isActive: Scalars['Boolean']
@@ -3261,6 +3263,7 @@ export interface FieldGenqlSelection{
description?: boolean | number
icon?: boolean | number
standardOverrides?: StandardOverridesGenqlSelection
/** @deprecated isCustom is derived from the owning application and will be removed; a field is custom when it does not belong to the twenty-standard application. */
isCustom?: boolean | number
isActive?: boolean | number
isSystem?: boolean | number
@@ -3328,7 +3331,7 @@ first?: (Scalars['Int'] | null),
/** Paginate last */
last?: (Scalars['Int'] | null)}
export interface ObjectFilter {and?: (ObjectFilter[] | null),or?: (ObjectFilter[] | null),id?: (UUIDFilterComparison | null),isCustom?: (BooleanFieldComparison | null),isRemote?: (BooleanFieldComparison | null),isActive?: (BooleanFieldComparison | null),isSystem?: (BooleanFieldComparison | null),isUIReadOnly?: (BooleanFieldComparison | null),isSearchable?: (BooleanFieldComparison | null)}
export interface ObjectFilter {and?: (ObjectFilter[] | null),or?: (ObjectFilter[] | null),id?: (UUIDFilterComparison | null),isRemote?: (BooleanFieldComparison | null),isActive?: (BooleanFieldComparison | null),isSystem?: (BooleanFieldComparison | null),isUIReadOnly?: (BooleanFieldComparison | null),isSearchable?: (BooleanFieldComparison | null)}
export interface UUIDFilterComparison {is?: (Scalars['Boolean'] | null),isNot?: (Scalars['Boolean'] | null),eq?: (Scalars['UUID'] | null),neq?: (Scalars['UUID'] | null),gt?: (Scalars['UUID'] | null),gte?: (Scalars['UUID'] | null),lt?: (Scalars['UUID'] | null),lte?: (Scalars['UUID'] | null),like?: (Scalars['UUID'] | null),notLike?: (Scalars['UUID'] | null),iLike?: (Scalars['UUID'] | null),notILike?: (Scalars['UUID'] | null),in?: (Scalars['UUID'][] | null),notIn?: (Scalars['UUID'][] | null)}
@@ -3359,6 +3362,7 @@ export interface ObjectGenqlSelection{
standardOverrides?: ObjectStandardOverridesGenqlSelection
shortcut?: boolean | number
color?: boolean | number
/** @deprecated isCustom is derived from the owning application and will be removed; an object is custom when it does not belong to the twenty-standard application. */
isCustom?: boolean | number
isRemote?: boolean | number
isActive?: boolean | number
@@ -3388,7 +3392,7 @@ export interface ObjectGenqlSelection{
__scalar?: boolean | number
}
export interface FieldFilter {and?: (FieldFilter[] | null),or?: (FieldFilter[] | null),id?: (UUIDFilterComparison | null),isCustom?: (BooleanFieldComparison | null),isActive?: (BooleanFieldComparison | null),isSystem?: (BooleanFieldComparison | null),isUIReadOnly?: (BooleanFieldComparison | null),objectMetadataId?: (UUIDFilterComparison | null)}
export interface FieldFilter {and?: (FieldFilter[] | null),or?: (FieldFilter[] | null),id?: (UUIDFilterComparison | null),isActive?: (BooleanFieldComparison | null),isSystem?: (BooleanFieldComparison | null),isUIReadOnly?: (BooleanFieldComparison | null),objectMetadataId?: (UUIDFilterComparison | null)}
export interface IndexFilter {and?: (IndexFilter[] | null),or?: (IndexFilter[] | null),id?: (UUIDFilterComparison | null),isCustom?: (BooleanFieldComparison | null)}
@@ -1076,9 +1076,6 @@ export default {
"id": [
52
],
"isCustom": [
53
],
"isRemote": [
53
],
@@ -1315,9 +1312,6 @@ export default {
"id": [
52
],
"isCustom": [
53
],
"isActive": [
53
],
@@ -1664,6 +1664,7 @@ export type Field = {
icon?: Maybe<Scalars['String']>;
id: Scalars['UUID'];
isActive?: Maybe<Scalars['Boolean']>;
/** @deprecated isCustom is derived from the owning application and will be removed; a field is custom when it does not belong to the twenty-standard application. */
isCustom?: Maybe<Scalars['Boolean']>;
isLabelSyncedWithName?: Maybe<Scalars['Boolean']>;
isNullable?: Maybe<Scalars['Boolean']>;
@@ -1722,7 +1723,6 @@ export type FieldFilter = {
and?: InputMaybe<Array<FieldFilter>>;
id?: InputMaybe<UuidFilterComparison>;
isActive?: InputMaybe<BooleanFieldComparison>;
isCustom?: InputMaybe<BooleanFieldComparison>;
isSystem?: InputMaybe<BooleanFieldComparison>;
isUIReadOnly?: InputMaybe<BooleanFieldComparison>;
objectMetadataId?: InputMaybe<UuidFilterComparison>;
@@ -3711,6 +3711,7 @@ export type Object = {
indexMetadataList: Array<Index>;
indexMetadatas: ObjectIndexMetadatasConnection;
isActive: Scalars['Boolean'];
/** @deprecated isCustom is derived from the owning application and will be removed; an object is custom when it does not belong to the twenty-standard application. */
isCustom: Scalars['Boolean'];
isLabelSyncedWithName: Scalars['Boolean'];
isRemote: Scalars['Boolean'];
@@ -3768,7 +3769,6 @@ export type ObjectFilter = {
and?: InputMaybe<Array<ObjectFilter>>;
id?: InputMaybe<UuidFilterComparison>;
isActive?: InputMaybe<BooleanFieldComparison>;
isCustom?: InputMaybe<BooleanFieldComparison>;
isRemote?: InputMaybe<BooleanFieldComparison>;
isSearchable?: InputMaybe<BooleanFieldComparison>;
isSystem?: InputMaybe<BooleanFieldComparison>;
@@ -17,6 +17,7 @@ import { type FieldMetadataType } from '~/generated-metadata/graphql';
type SettingsObjectFieldInactiveActionDropdownProps = {
isCustomField?: boolean;
isSystemField?: boolean;
fieldType?: FieldMetadataType;
onActivate: () => void;
onEdit: () => void;
@@ -32,6 +33,7 @@ export const SettingsObjectFieldInactiveActionDropdown = ({
onDelete,
onEdit,
isCustomField,
isSystemField,
}: SettingsObjectFieldInactiveActionDropdownProps) => {
const dropdownId = `${fieldMetadataItemId}-settings-field-disabled-action-dropdown`;
@@ -52,7 +54,7 @@ export const SettingsObjectFieldInactiveActionDropdown = ({
closeDropdown(dropdownId);
};
const isDeletable = isCustomField;
const isDeletable = isCustomField && !isSystemField;
return (
<Dropdown
@@ -261,6 +261,7 @@ export const SettingsObjectFieldItemTableRow = ({
) : mode === 'view' ? (
<SettingsObjectFieldInactiveActionDropdown
isCustomField={fieldMetadataItem.isCustom === true}
isSystemField={fieldMetadataItem.isSystem === true}
readonly={readonly}
fieldMetadataItemId={fieldMetadataItem.id}
onEdit={navigateToFieldEdit}
@@ -0,0 +1,44 @@
import { QueryRunner } from 'typeorm';
import { RegisteredInstanceCommand } from 'src/engine/core-modules/upgrade/decorators/registered-instance-command.decorator';
import { FastInstanceCommand } from 'src/engine/core-modules/upgrade/interfaces/fast-instance-command.interface';
const TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER =
'20202020-64aa-4b6f-b003-9c74b97cee20';
@RegisteredInstanceCommand('2.12.0', 1780579070012)
export class DropIsCustomFromObjectAndFieldMetadataFastInstanceCommand
implements FastInstanceCommand
{
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
'ALTER TABLE "core"."fieldMetadata" DROP COLUMN IF EXISTS "isCustom"',
);
await queryRunner.query(
'ALTER TABLE "core"."objectMetadata" DROP COLUMN IF EXISTS "isCustom"',
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
'ALTER TABLE "core"."objectMetadata" ADD COLUMN IF NOT EXISTS "isCustom" boolean NOT NULL DEFAULT false',
);
await queryRunner.query(
'ALTER TABLE "core"."fieldMetadata" ADD COLUMN IF NOT EXISTS "isCustom" boolean NOT NULL DEFAULT false',
);
await queryRunner.query(
`UPDATE "core"."objectMetadata" "objectMetadata"
SET "isCustom" = ("objectMetadata"."applicationId" <> "standardApplication"."id")
FROM "core"."application" "standardApplication"
WHERE "standardApplication"."workspaceId" = "objectMetadata"."workspaceId"
AND "standardApplication"."universalIdentifier" = '${TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER}'`,
);
await queryRunner.query(
`UPDATE "core"."fieldMetadata" "fieldMetadata"
SET "isCustom" = ("fieldMetadata"."applicationId" <> "standardApplication"."id")
FROM "core"."application" "standardApplication"
WHERE "standardApplication"."workspaceId" = "fieldMetadata"."workspaceId"
AND "standardApplication"."universalIdentifier" = '${TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER}'`,
);
}
}
@@ -59,6 +59,7 @@ import { EmailingDomainTenantStatusAndGlobalUniquenessFastInstanceCommand } from
import { AddLogicFunctionExecutionModeFastInstanceCommand } from 'src/database/commands/upgrade-version-command/2-9/2-9-instance-command-fast-1799000030000-add-logic-function-execution-mode';
import { EncryptNonSecretApplicationVariableSlowInstanceCommand } from 'src/database/commands/upgrade-version-command/2-9/2-9-instance-command-slow-1798400000000-encrypt-non-secret-application-variable';
import { MigrateAiModelPreferencesSlowInstanceCommand } from 'src/database/commands/upgrade-version-command/2-9/2-9-instance-command-slow-1799000010000-migrate-ai-model-preferences';
import { DropIsCustomFromObjectAndFieldMetadataFastInstanceCommand } from 'src/database/commands/upgrade-version-command/2-12/2-12-instance-command-fast-1780579070012-drop-is-custom-from-object-and-field-metadata';
import { DropEmailingDomainDriverColumnFastInstanceCommand } from 'src/database/commands/upgrade-version-command/2-11/2-11-instance-command-fast-1780926908000-drop-emailing-domain-driver-column';
export const INSTANCE_COMMANDS = [
@@ -121,5 +122,6 @@ export const INSTANCE_COMMANDS = [
AddLogicFunctionExecutionModeFastInstanceCommand,
MigrateAiModelPreferencesSlowInstanceCommand,
EncryptNonSecretApplicationVariableSlowInstanceCommand,
DropIsCustomFromObjectAndFieldMetadataFastInstanceCommand,
DropEmailingDomainDriverColumnFastInstanceCommand,
];
@@ -9,6 +9,7 @@ import {
escapeLiteral,
} from 'src/engine/workspace-manager/workspace-migration/utils/remove-sql-injection.util';
import { generateColumnDefinitions } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/utils/generate-column-definitions.util';
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications';
import {
type CreateEnumOperationSpec,
EnumOperation,
@@ -28,7 +29,8 @@ export const generateWorkspaceSchemaDdl = (
const tableName = computeTableName(
objectMetadata.nameSingular,
objectMetadata.isCustom,
objectMetadata.application?.universalIdentifier !==
TWENTY_STANDARD_APPLICATION.universalIdentifier,
);
const fieldMetadatas = fieldsByObjectId.get(objectMetadata.id) ?? [];
@@ -14,6 +14,7 @@ import {
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications';
import { getWorkspaceSchemaName } from 'src/engine/workspace-datasource/utils/get-workspace-schema-name.util';
import { computeTableName } from 'src/engine/utils/compute-table-name.util';
import { escapeIdentifier } from 'src/engine/workspace-manager/workspace-migration/utils/remove-sql-injection.util';
@@ -77,6 +78,7 @@ export class WorkspaceExportService {
const objectMetadatas = await this.objectMetadataRepository.find({
where: { workspaceId },
relations: { application: true },
});
const fieldMetadatas = await this.fieldMetadataRepository.find({
@@ -359,7 +361,8 @@ export class WorkspaceExportService {
const tableName = computeTableName(
objectMetadata.nameSingular,
objectMetadata.isCustom,
objectMetadata.application?.universalIdentifier !==
TWENTY_STANDARD_APPLICATION.universalIdentifier,
);
if (tableFilter && !tableFilter.includes(objectMetadata.nameSingular)) {
@@ -436,7 +436,6 @@ export const objectMetadataItemMock: ObjectMetadataEntity = {
description: 'Object description',
icon: 'Icon123',
targetTableName: 'DEPRECATED',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: false,
@@ -76,7 +76,6 @@ describe('DataArgProcessorService', () => {
id: 'object-id',
nameSingular: 'testObject',
namePlural: 'testObjects',
isCustom: false,
fieldIds: fieldNames.map((name) => `${name}-id`),
universalIdentifier: 'test-object-universal-id',
labelIdentifierFieldMetadataUniversalIdentifier: null,
@@ -161,7 +160,6 @@ describe('DataArgProcessorService', () => {
id: 'object-id',
nameSingular: 'testObject',
namePlural: 'testObjects',
isCustom: false,
fieldIds: ['company-id'],
universalIdentifier: 'test-object-universal-id',
labelIdentifierFieldMetadataUniversalIdentifier: null,
@@ -174,7 +172,6 @@ describe('DataArgProcessorService', () => {
id: 'target-company-object-id',
nameSingular: 'company',
namePlural: 'companies',
isCustom: false,
fieldIds: ['emails-id', 'domainName-id'],
universalIdentifier: 'target-company-universal-id',
labelIdentifierFieldMetadataUniversalIdentifier: null,
@@ -15,6 +15,7 @@ import {
} from 'twenty-shared/utils';
import { computeMorphOrRelationFieldJoinColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-morph-or-relation-field-join-column-name.util';
import { belongsToTwentyStandardApp } from 'src/engine/metadata-modules/utils/belongs-to-twenty-standard-app.util';
import { transformActorField } from 'src/engine/api/common/common-args-processors/data-arg-processor/transformer-utils/transform-actor-field.util';
import { transformAddressField } from 'src/engine/api/common/common-args-processors/data-arg-processor/transformer-utils/transform-address-field.util';
import { transformArrayField } from 'src/engine/api/common/common-args-processors/data-arg-processor/transformer-utils/transform-array-field.util';
@@ -101,7 +102,7 @@ export class DataArgProcessorService {
partialRecordInputs: partialRecordInputs,
workspaceId: workspace.id,
objectMetadata: {
isCustom: flatObjectMetadata.isCustom,
isCustom: !belongsToTwentyStandardApp(flatObjectMetadata),
nameSingular: flatObjectMetadata.nameSingular,
fieldIdByName,
},
@@ -57,7 +57,6 @@ describe('FilterArgProcessorService', () => {
id: 'object-id',
nameSingular: 'testObject',
namePlural: 'testObjects',
isCustom: false,
fieldIds: fieldNames.map((name) => `${name}-id`),
universalIdentifier: 'test-object-universal-id',
labelIdentifierFieldMetadataUniversalIdentifier: null,
@@ -338,7 +337,6 @@ describe('FilterArgProcessorService', () => {
id: sourceObjectId,
nameSingular: 'sourceObject',
namePlural: 'sourceObjects',
isCustom: false,
fieldIds: [relationFieldId],
universalIdentifier: sourceUniversalId,
labelIdentifierFieldMetadataUniversalIdentifier: null,
@@ -349,7 +347,6 @@ describe('FilterArgProcessorService', () => {
id: targetObjectId,
nameSingular: 'targetObject',
namePlural: 'targetObjects',
isCustom: false,
fieldIds: [targetTextFieldId, targetCurrencyFieldId],
universalIdentifier: targetUniversalId,
labelIdentifierFieldMetadataUniversalIdentifier: null,
@@ -490,7 +490,7 @@ export class CommonCreateManyQueryRunnerService extends CommonBaseQueryRunnerSer
);
}
if ('createdBy' in record && createdByFieldMetadata.isCustom === false) {
if ('createdBy' in record && createdByFieldMetadata.isSystem === true) {
const { createdBy: _createdBy, ...recordWithoutCreatedBy } = record;
recordWithoutCreatedByUpdate = recordWithoutCreatedBy;
@@ -85,7 +85,6 @@ describe('getConflictingFields', () => {
namePlural: 'testObjects',
labelSingular: 'Test Object',
labelPlural: 'Test Objects',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: false,
@@ -60,7 +60,6 @@ describe('getAllSelectableFields', () => {
namePlural: 'testObjects',
labelSingular: 'Test Object',
labelPlural: 'Test Objects',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: false,
@@ -141,7 +141,6 @@ export const mockPersonFlatObjectMetadata = (
labelSingular: 'Person',
labelPlural: 'People',
targetTableName: 'person',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: false,
@@ -36,7 +36,6 @@ describe('buildColumnsToSelect', () => {
calendarViewIds: [],
applicationId: null,
label: overrides.name,
isCustom: false,
isActive: true,
isSystem: false,
isUnique: false,
@@ -87,7 +86,6 @@ describe('buildColumnsToSelect', () => {
description: 'A person',
icon: 'IconUser',
targetTableName: 'DEPRECATED',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: false,
@@ -59,7 +59,6 @@ const flatObjectMetadata: FlatObjectMetadata = {
labelSingular: 'Person',
labelPlural: 'People',
targetTableName: 'person',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: false,
@@ -56,7 +56,6 @@ describe('RestToCommonSelectedFieldsHandler', () => {
namePlural: `${overrides.nameSingular}s`,
labelSingular: overrides.nameSingular,
labelPlural: `${overrides.nameSingular}s`,
isCustom: false,
isRemote: false,
isActive: true,
isSystem: false,
@@ -91,7 +91,6 @@ describe('computeCursorArgFilter', () => {
labelSingular: 'Person',
labelPlural: 'People',
targetTableName: 'person',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: false,
@@ -23,7 +23,6 @@ export const mockFlatObjectMetadatas: FlatObjectMetadata[] = [
labelPlural: 'People',
description: 'A person',
icon: 'test-person-icon',
isCustom: false,
isSearchable: true,
labelIdentifierFieldMetadataId: personNameFieldId,
imageIdentifierFieldMetadataId: null,
@@ -40,7 +39,6 @@ export const mockFlatObjectMetadatas: FlatObjectMetadata[] = [
labelPlural: 'Companies',
description: 'A company',
icon: 'test-company-icon',
isCustom: false,
isSearchable: true,
labelIdentifierFieldMetadataId: companyNameFieldId,
imageIdentifierFieldMetadataId: null,
@@ -57,7 +55,6 @@ export const mockFlatObjectMetadatas: FlatObjectMetadata[] = [
labelPlural: 'Regular Custom Objects',
description: 'A regular custom object',
icon: 'test-regular-custom-object-icon',
isCustom: true,
isSearchable: true,
labelIdentifierFieldMetadataId: customObjectNameFieldId,
imageIdentifierFieldMetadataId: customObjectImageFieldId,
@@ -74,7 +71,6 @@ export const mockFlatObjectMetadatas: FlatObjectMetadata[] = [
labelPlural: '',
description: '',
icon: 'test-non-searchable-object-icon',
isCustom: false,
isSystem: true,
isSearchable: false,
labelIdentifierFieldMetadataId: null,
@@ -92,7 +88,6 @@ export const mockFlatObjectMetadatas: FlatObjectMetadata[] = [
labelPlural: 'Messages',
description: 'Message',
icon: 'IconMessage',
isCustom: false,
isSystem: true,
isSearchable: false,
labelIdentifierFieldMetadataId: null,
@@ -113,7 +108,6 @@ export const mockFlatFieldMetadataMaps: FlatEntityMaps<FlatFieldMetadata> = {
name: 'name',
label: 'Name',
description: "Contact's name",
isCustom: false,
defaultValue: { lastName: "''", firstName: "''" },
objectMetadataId: '20202020-8dec-43d5-b2ff-6eef05095bec',
workspaceId,
@@ -127,7 +121,6 @@ export const mockFlatFieldMetadataMaps: FlatEntityMaps<FlatFieldMetadata> = {
name: 'name',
label: 'Name',
description: null,
isCustom: false,
defaultValue: '',
objectMetadataId: '20202020-c03c-45d6-a4b0-04afe1357c5c',
workspaceId,
@@ -141,7 +134,6 @@ export const mockFlatFieldMetadataMaps: FlatEntityMaps<FlatFieldMetadata> = {
name: 'domainName',
label: 'Domain Name',
description: null,
isCustom: false,
defaultValue: {
primaryLinkLabel: '',
primaryLinkUrl: '',
@@ -159,7 +151,6 @@ export const mockFlatFieldMetadataMaps: FlatEntityMaps<FlatFieldMetadata> = {
name: 'name',
label: 'Name',
description: null,
isCustom: false,
defaultValue: '',
objectMetadataId: '20202020-3d75-4aab-bacd-ee176c5f63ca',
workspaceId,
@@ -173,7 +164,6 @@ export const mockFlatFieldMetadataMaps: FlatEntityMaps<FlatFieldMetadata> = {
name: 'imageIdentifierFieldName',
label: 'Image Identifier Field Name',
description: null,
isCustom: false,
defaultValue: '',
objectMetadataId: '20202020-3d75-4aab-bacd-ee176c5f63ca',
workspaceId,
@@ -26,7 +26,6 @@ const personFlatObject = getFlatObjectMetadataMock({
description: 'A person',
icon: 'test-person-icon',
targetTableName: 'DEPRECATED',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: false,
@@ -50,7 +49,6 @@ const companyFlatObject = getFlatObjectMetadataMock({
description: 'A company',
icon: 'test-company-icon',
targetTableName: 'DEPRECATED',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: false,
@@ -74,7 +72,6 @@ const customObjectFlatObject = getFlatObjectMetadataMock({
description: 'A regular custom object',
icon: 'test-regular-custom-object-icon',
targetTableName: 'DEPRECATED',
isCustom: true,
isRemote: false,
isActive: true,
isSystem: false,
@@ -98,7 +95,6 @@ const nonSearchableFlatObject = getFlatObjectMetadataMock({
description: '',
icon: 'test-non-searchable-object-icon',
targetTableName: 'DEPRECATED',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: true,
@@ -125,7 +121,6 @@ const personNameField = getFlatFieldMetadataMock({
firstName: "''",
},
description: "Contact's name",
isCustom: false,
isNullable: true,
isUnique: false,
isLabelSyncedWithName: true,
@@ -141,7 +136,6 @@ const companyNameField = getFlatFieldMetadataMock({
name: 'name',
label: 'Name',
defaultValue: '',
isCustom: false,
isNullable: true,
isUnique: false,
isLabelSyncedWithName: true,
@@ -161,7 +155,6 @@ const companyDomainNameField = getFlatFieldMetadataMock({
primaryLinkUrl: '',
secondaryLinks: [],
},
isCustom: false,
isNullable: true,
isUnique: false,
isLabelSyncedWithName: true,
@@ -177,7 +170,6 @@ const customObjectNameField = getFlatFieldMetadataMock({
name: 'name',
label: 'Name',
defaultValue: '',
isCustom: false,
isNullable: true,
isUnique: false,
isLabelSyncedWithName: true,
@@ -193,7 +185,6 @@ const customObjectImageField = getFlatFieldMetadataMock({
name: 'imageIdentifierFieldName',
label: 'Image Identifier Field Name',
defaultValue: '',
isCustom: false,
isNullable: true,
isUnique: false,
isLabelSyncedWithName: true,
@@ -12,7 +12,6 @@ describe('fromIndexManifestToUniversalFlatIndex', () => {
const flatObjectMetadata = {
universalIdentifier: 'obj-uuid-1',
nameSingular: 'company',
isCustom: false,
} as UniversalFlatObjectMetadata;
const scalarField = {
@@ -92,7 +92,6 @@ export const fromFieldManifestToUniversalFlatFieldMetadata = ({
options: fieldManifest.options ?? null,
defaultValue,
universalSettings: fieldManifest.universalSettings ?? null,
isCustom: true,
isActive: true,
isSystem: fieldManifest.name in PARTIAL_SYSTEM_FLAT_FIELD_METADATAS,
isUIReadOnly: false,
@@ -23,7 +23,6 @@ export const fromObjectManifestToUniversalFlatObjectMetadata = ({
icon: objectManifest.icon ?? null,
standardOverrides: null,
targetTableName: 'DEPRECATED',
isCustom: true,
isRemote: false,
isActive: true,
isSystem: false,
@@ -0,0 +1,67 @@
import {
type ArgumentsHost,
Catch,
type ExceptionFilter,
Injectable,
} from '@nestjs/common';
import { type Response } from 'express';
import { assertUnreachable } from 'twenty-shared/utils';
import {
ApplicationException,
ApplicationExceptionCode,
} from 'src/engine/core-modules/application/application.exception';
import { HttpExceptionHandlerService } from 'src/engine/core-modules/exception-handler/http-exception-handler.service';
import { type CustomException } from 'src/utils/custom-exception';
const applicationExceptionCodeToHttpStatus = (
code: ApplicationExceptionCode,
): number => {
switch (code) {
case ApplicationExceptionCode.OBJECT_NOT_FOUND:
case ApplicationExceptionCode.FIELD_NOT_FOUND:
case ApplicationExceptionCode.ENTITY_NOT_FOUND:
case ApplicationExceptionCode.APPLICATION_NOT_FOUND:
case ApplicationExceptionCode.APP_NOT_INSTALLED:
case ApplicationExceptionCode.LOGIC_FUNCTION_NOT_FOUND:
case ApplicationExceptionCode.FRONT_COMPONENT_NOT_FOUND:
return 404;
case ApplicationExceptionCode.FORBIDDEN:
return 403;
case ApplicationExceptionCode.INVALID_INPUT:
case ApplicationExceptionCode.SOURCE_CHANNEL_MISMATCH:
case ApplicationExceptionCode.APP_ALREADY_INSTALLED:
case ApplicationExceptionCode.CANNOT_DOWNGRADE_APPLICATION:
case ApplicationExceptionCode.SERVER_VERSION_INCOMPATIBLE:
case ApplicationExceptionCode.INVALID_APP_ENGINE_REQUIREMENT:
return 400;
case ApplicationExceptionCode.PACKAGE_RESOLUTION_FAILED:
case ApplicationExceptionCode.POST_INSTALL_ERROR:
case ApplicationExceptionCode.PRE_INSTALL_ERROR:
case ApplicationExceptionCode.TARBALL_EXTRACTION_FAILED:
case ApplicationExceptionCode.UPGRADE_FAILED:
case ApplicationExceptionCode.INVALID_SERVER_VERSION:
return 500;
default:
return assertUnreachable(code);
}
};
@Injectable()
@Catch(ApplicationException)
export class ApplicationRestApiExceptionFilter implements ExceptionFilter {
constructor(
private readonly httpExceptionHandlerService: HttpExceptionHandlerService,
) {}
catch(exception: ApplicationException, host: ArgumentsHost) {
const response = host.switchToHttp().getResponse<Response>();
return this.httpExceptionHandlerService.handleError(
exception as CustomException,
response,
applicationExceptionCodeToHttpStatus(exception.code),
);
}
}
@@ -17,7 +17,6 @@ const mockObjectMetadata: FlatObjectMetadata = {
workspaceId: '1',
universalIdentifier: '1',
isSystem: false,
isCustom: false,
isActive: true,
isRemote: false,
isAuditLogged: true,
@@ -6,6 +6,24 @@ export type WasRemovedInUpgradeOptions = {
upgradeCommandName: string;
};
declare const wasRemovedInUpgradeBrand: unique symbol;
export type WasRemovedInUpgrade<T> = T & {
readonly [wasRemovedInUpgradeBrand]?: true;
};
type WasRemovedInUpgradeKeys<TEntity> = {
[K in keyof TEntity]: typeof wasRemovedInUpgradeBrand extends keyof TEntity[K]
? K
: never;
}[keyof TEntity];
export type MakeWasRemovedInUpgradePropertiesOptional<TEntity> = Omit<
TEntity,
WasRemovedInUpgradeKeys<TEntity>
> &
Partial<Pick<TEntity, WasRemovedInUpgradeKeys<TEntity>>>;
export const WAS_REMOVED_IN_UPGRADE_CLASS_METADATA_KEY =
'WAS_REMOVED_IN_UPGRADE_CLASS';
@@ -5,6 +5,7 @@ import {
type IndexFieldMetadataLoaderPayload,
type IndexMetadataLoaderPayload,
type IsConfiguredLoaderPayload,
type IsCustomLoaderPayload,
type MorphRelationLoaderPayload,
type ObjectMetadataLoaderPayload,
type RelationLoaderPayload,
@@ -92,4 +93,6 @@ export interface IDataloaders {
>;
isConfiguredLoader: DataLoader<IsConfiguredLoaderPayload, boolean>;
isCustomLoader: DataLoader<IsCustomLoaderPayload, boolean>;
}
@@ -37,6 +37,7 @@ import { type IndexFieldMetadataDTO } from 'src/engine/metadata-modules/index-me
import { type IndexMetadataDTO } from 'src/engine/metadata-modules/index-metadata/dtos/index-metadata.dto';
import { ObjectMetadataDTO } from 'src/engine/metadata-modules/object-metadata/dtos/object-metadata.dto';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { getTwentyStandardApplicationIdOrThrow } from 'src/engine/metadata-modules/utils/get-twenty-standard-application-id-or-throw.util';
export type RelationMetadataLoaderPayload = {
workspaceId: string;
@@ -116,6 +117,11 @@ export type IsConfiguredLoaderPayload = {
applicationRegistrationId: string;
};
export type IsCustomLoaderPayload = {
workspaceId: string;
applicationId: string;
};
@Injectable()
export class DataloaderService {
constructor(
@@ -142,6 +148,7 @@ export class DataloaderService {
const viewFilterGroupsByViewIdLoader =
this.createViewFilterGroupsByViewIdLoader();
const isConfiguredLoader = this.createIsConfiguredLoader();
const isCustomLoader = this.createIsCustomLoader();
return {
relationLoader,
@@ -158,6 +165,7 @@ export class DataloaderService {
viewGroupsByViewIdLoader,
viewFilterGroupsByViewIdLoader,
isConfiguredLoader,
isCustomLoader,
};
}
@@ -328,7 +336,6 @@ export class DataloaderService {
label: flatFieldMetadata.label,
description: flatFieldMetadata.description ?? undefined,
icon: flatFieldMetadata.icon ?? undefined,
isCustom: flatFieldMetadata.isCustom,
standardOverrides:
flatFieldMetadata.standardOverrides ?? undefined,
},
@@ -759,4 +766,27 @@ export class DataloaderService {
},
);
}
private createIsCustomLoader() {
return new DataLoader<IsCustomLoaderPayload, boolean>(
async (dataLoaderParams: IsCustomLoaderPayload[]) => {
const workspaceId = dataLoaderParams[0].workspaceId;
const { flatApplicationMaps } =
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
{
workspaceId,
flatMapsKeys: ['flatApplicationMaps'],
},
);
const twentyStandardApplicationId =
getTwentyStandardApplicationIdOrThrow(flatApplicationMaps);
return dataLoaderParams.map(
({ applicationId }) => applicationId !== twentyStandardApplicationId,
);
},
);
}
}
@@ -20,7 +20,6 @@ const mockObjectMetadata = {
labelSingular: 'Person',
description: 'A person',
icon: 'IconUser',
isCustom: false,
standardOverrides: undefined,
} as unknown as ObjectMetadataDTO;
@@ -127,7 +126,6 @@ describe('interpolateNavigationCommandMenuItemField', () => {
it('should resolve label for custom object metadata', () => {
const customObjectMetadata = {
...mockObjectMetadata,
isCustom: true,
labelPlural: 'Custom Objects',
icon: 'IconCustom',
} as unknown as ObjectMetadataDTO;
@@ -146,7 +144,6 @@ describe('interpolateNavigationCommandMenuItemField', () => {
it('should resolve icon for custom object metadata', () => {
const customObjectMetadata = {
...mockObjectMetadata,
isCustom: true,
icon: 'IconCustom',
} as unknown as ObjectMetadataDTO;
@@ -9,7 +9,6 @@ export type NavigationInterpolationObjectMetadata = {
labelSingular: string;
description?: string | null;
icon?: string | null;
isCustom: boolean;
standardOverrides?: ObjectStandardOverridesDTO | null;
};
@@ -27,7 +26,6 @@ export const buildNavigationInterpolationContext = ({
labelSingular: objectMetadata.labelSingular,
description: objectMetadata.description ?? undefined,
icon: objectMetadata.icon ?? undefined,
isCustom: objectMetadata.isCustom,
standardOverrides: objectMetadata.standardOverrides ?? undefined,
};
@@ -16,9 +16,9 @@ import {
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { PermissionFlagType } from 'twenty-shared/constants';
import { FeatureFlagKey } from 'twenty-shared/types';
import { Repository } from 'typeorm';
import { parseEndingBeforeRestRequest } from 'src/engine/api/rest/input-request-parsers/ending-before-parser-utils/parse-ending-before-rest-request.util';
import { parseLimitRestRequest } from 'src/engine/api/rest/input-request-parsers/limit-parser-utils/parse-limit-rest-request.util';
@@ -28,6 +28,7 @@ import {
type RestCursorPageInfo,
} from 'src/engine/api/rest/metadata/utils/paginate-by-id-cursor.util';
import { type AuthenticatedRequest } from 'src/engine/api/rest/types/authenticated-request';
import { ApplicationRestApiExceptionFilter } from 'src/engine/core-modules/application/application-rest-api-exception.filter';
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
@@ -45,8 +46,6 @@ import {
import { FieldMetadataRestApiExceptionFilter } from 'src/engine/metadata-modules/field-metadata/filters/field-metadata-rest-api-exception.filter';
import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata/services/field-metadata.service';
import { fromFieldMetadataEntityToFieldMetadataDto } from 'src/engine/metadata-modules/field-metadata/utils/from-field-metadata-entity-to-field-metadata-dto.util';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
import { computeUniqueFieldMetadataIdsFromFlatIndexMaps } from 'src/engine/metadata-modules/index-metadata/utils/compute-unique-field-metadata-ids-from-flat-index-maps.util';
import {
toLegacyFieldMetadataCreateResponse,
toLegacyFieldMetadataDeleteResponse,
@@ -54,8 +53,11 @@ import {
toLegacyFieldMetadataListResponse,
toLegacyFieldMetadataUpdateResponse,
} from 'src/engine/metadata-modules/field-metadata/utils/to-legacy-field-metadata-response.util';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
import { fromFlatFieldMetadataToFieldMetadataDto } from 'src/engine/metadata-modules/flat-field-metadata/utils/from-flat-field-metadata-to-field-metadata-dto.util';
import { computeUniqueFieldMetadataIdsFromFlatIndexMaps } from 'src/engine/metadata-modules/index-metadata/utils/compute-unique-field-metadata-ids-from-flat-index-maps.util';
import { PermissionsRestApiExceptionFilter } from 'src/engine/metadata-modules/permissions/utils/permissions-rest-api-exception.filter';
import { getTwentyStandardApplicationIdOrThrow } from 'src/engine/metadata-modules/utils/get-twenty-standard-application-id-or-throw.util';
@Controller('rest/metadata/fields')
@UseGuards(
@@ -66,6 +68,7 @@ import { PermissionsRestApiExceptionFilter } from 'src/engine/metadata-modules/p
@UseFilters(
PermissionsRestApiExceptionFilter,
FieldMetadataRestApiExceptionFilter,
ApplicationRestApiExceptionFilter,
)
@UsePipes(new ValidationPipe())
export class FieldMetadataController {
@@ -88,6 +91,17 @@ export class FieldMetadataController {
return computeUniqueFieldMetadataIdsFromFlatIndexMaps(flatIndexMaps);
}
private async loadStandardApplicationId(
workspaceId: string,
): Promise<string> {
const { flatApplicationMaps } =
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
{ workspaceId, flatMapsKeys: ['flatApplicationMaps'] },
);
return getTwentyStandardApplicationIdOrThrow(flatApplicationMaps);
}
@Get()
async findMany(
@Req() request: AuthenticatedRequest,
@@ -101,8 +115,10 @@ export class FieldMetadataController {
endingBefore: parseEndingBeforeRestRequest(request),
});
const uniqueFieldMetadataIds =
await this.loadUniqueFieldMetadataIds(workspaceId);
const [uniqueFieldMetadataIds, standardApplicationId] = await Promise.all([
this.loadUniqueFieldMetadataIds(workspaceId),
this.loadStandardApplicationId(workspaceId),
]);
const result: {
data: FieldMetadataDTO[];
@@ -110,7 +126,11 @@ export class FieldMetadataController {
totalCount: number;
} = {
data: items.map((item) =>
fromFieldMetadataEntityToFieldMetadataDto(item, uniqueFieldMetadataIds),
fromFieldMetadataEntityToFieldMetadataDto(
item,
standardApplicationId,
uniqueFieldMetadataIds,
),
),
pageInfo,
totalCount,
@@ -137,10 +157,13 @@ export class FieldMetadataController {
);
}
const uniqueFieldMetadataIds =
await this.loadUniqueFieldMetadataIds(workspaceId);
const [uniqueFieldMetadataIds, standardApplicationId] = await Promise.all([
this.loadUniqueFieldMetadataIds(workspaceId),
this.loadStandardApplicationId(workspaceId),
]);
const result = fromFieldMetadataEntityToFieldMetadataDto(
field,
standardApplicationId,
uniqueFieldMetadataIds,
);
@@ -100,7 +100,11 @@ export class FieldMetadataDTO<T extends FieldMetadataType = FieldMetadataType> {
@IsBoolean()
@IsOptional()
@FilterableField({ nullable: true })
@Field({
nullable: true,
deprecationReason:
'isCustom is derived from the owning application and will be removed; a field is custom when it does not belong to the twenty-standard application.',
})
isCustom?: boolean;
@IsBoolean()
@@ -20,6 +20,7 @@ import {
UpdateDateColumn,
} from 'typeorm';
import { WasRemovedInUpgrade } from 'src/engine/core-modules/upgrade/decorators/was-removed-in-upgrade.decorator';
import { type FieldStandardOverridesDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-standard-overrides.dto';
import { AssignIfIsGivenFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/types/assign-if-is-given-field-metadata-type.type';
import { AssignTypeIfIsMorphOrRelationFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/types/assign-type-if-is-morph-or-relation-field-metadata-type.type';
@@ -106,8 +107,12 @@ export class FieldMetadataEntity<
@Column('jsonb', { nullable: true })
settings: JsonbProperty<FieldMetadataSettings<TFieldMetadataType>>;
@Column({ default: false })
isCustom: boolean;
@WasRemovedInUpgrade({
upgradeCommandName:
'2.12.0_DropIsCustomFromObjectAndFieldMetadataFastInstanceCommand_1780579070012',
})
@Column({ type: 'boolean', default: false })
isCustom: WasRemovedInUpgrade<boolean>;
@Column({ default: false })
isActive: boolean;
@@ -41,6 +41,7 @@ import { UpdateFieldInput } from './dtos/update-field.input';
@Module({
imports: [
ApplicationModule,
TokenModule,
WorkspaceCacheStorageModule,
FeatureFlagModule,
@@ -45,6 +45,22 @@ export class FieldMetadataResolver {
private readonly i18nService: I18nService,
) {}
@ResolveField(() => Boolean, {
nullable: true,
deprecationReason:
'isCustom is derived from the owning application and will be removed; a field is custom when it does not belong to the twenty-standard application.',
})
async isCustom(
@Parent() fieldMetadata: Pick<FieldMetadataDTO, 'applicationId'>,
@AuthWorkspace() { id: workspaceId }: WorkspaceEntity,
@Context() context: { loaders: IDataloaders },
): Promise<boolean> {
return context.loaders.isCustomLoader.load({
workspaceId,
applicationId: fieldMetadata.applicationId,
});
}
@ResolveField(() => String, { nullable: true })
async label(
@Parent() fieldMetadata: FieldMetadataStandardOverrideParent,
@@ -26,7 +26,6 @@ describe('resolveFieldMetadataStandardOverride', () => {
label: 'Custom Label',
description: 'Custom Description',
icon: 'custom-icon',
isCustom: true,
standardOverrides: undefined,
};
@@ -45,7 +44,6 @@ describe('resolveFieldMetadataStandardOverride', () => {
label: 'Custom Label',
description: 'Custom Description',
icon: 'custom-icon',
isCustom: true,
standardOverrides: undefined,
};
@@ -64,7 +62,6 @@ describe('resolveFieldMetadataStandardOverride', () => {
label: 'Custom Label',
description: 'Custom Description',
icon: 'custom-icon',
isCustom: true,
standardOverrides: undefined,
};
@@ -85,7 +82,6 @@ describe('resolveFieldMetadataStandardOverride', () => {
label: 'Standard Label',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: {
icon: 'override-icon',
},
@@ -108,7 +104,6 @@ describe('resolveFieldMetadataStandardOverride', () => {
label: 'Standard Label',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: {
translations: {
'fr-FR': {
@@ -142,7 +137,6 @@ describe('resolveFieldMetadataStandardOverride', () => {
label: 'Standard Label',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: {
translations: {
'es-ES': {
@@ -170,7 +164,6 @@ describe('resolveFieldMetadataStandardOverride', () => {
label: 'Standard Label',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: {
translations: {
'fr-FR': {
@@ -198,7 +191,6 @@ describe('resolveFieldMetadataStandardOverride', () => {
label: 'Standard Label',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: {
translations: {
'fr-FR': {
@@ -228,7 +220,6 @@ describe('resolveFieldMetadataStandardOverride', () => {
label: 'Standard Label',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: {
label: 'Overridden Label',
description: 'Overridden Description',
@@ -267,7 +258,6 @@ describe('resolveFieldMetadataStandardOverride', () => {
label: 'Standard Label',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: {
label: 'Overridden Label',
},
@@ -293,7 +283,6 @@ describe('resolveFieldMetadataStandardOverride', () => {
label: 'Standard Label',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: {
label: '',
},
@@ -317,7 +306,6 @@ describe('resolveFieldMetadataStandardOverride', () => {
label: 'Standard Label',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: {
label: undefined,
},
@@ -343,7 +331,6 @@ describe('resolveFieldMetadataStandardOverride', () => {
label: 'Standard Label',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: undefined,
};
@@ -367,7 +354,6 @@ describe('resolveFieldMetadataStandardOverride', () => {
label: 'Standard Label',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: undefined,
};
@@ -393,7 +379,6 @@ describe('resolveFieldMetadataStandardOverride', () => {
label: 'Standard Label',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: {
label: 'Source Override',
translations: {
@@ -421,7 +406,6 @@ describe('resolveFieldMetadataStandardOverride', () => {
label: 'Standard Label',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: {
label: 'Source Override',
},
@@ -444,7 +428,6 @@ describe('resolveFieldMetadataStandardOverride', () => {
label: 'Standard Label',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: {},
};
@@ -7,6 +7,7 @@ import { type FieldMetadataEntity } from 'src/engine/metadata-modules/field-meta
// contexts that don't care about uniqueness can omit it.
export const fromFieldMetadataEntityToFieldMetadataDto = (
entity: FieldMetadataEntity,
standardApplicationId: string,
uniqueFieldMetadataIds?: ReadonlySet<string>,
): FieldMetadataDTO => ({
id: entity.id,
@@ -18,7 +19,7 @@ export const fromFieldMetadataEntityToFieldMetadataDto = (
description: entity.description ?? undefined,
icon: entity.icon ?? undefined,
standardOverrides: entity.standardOverrides ?? undefined,
isCustom: entity.isCustom,
isCustom: entity.applicationId !== standardApplicationId,
isActive: entity.isActive,
isSystem: entity.isSystem,
isUIReadOnly: entity.isUIReadOnly,
@@ -10,7 +10,7 @@ import { type FieldMetadataDTO } from 'src/engine/metadata-modules/field-metadat
export const resolveFieldMetadataStandardOverride = (
fieldMetadata: Pick<
FieldMetadataDTO,
'label' | 'description' | 'icon' | 'isCustom' | 'standardOverrides'
'label' | 'description' | 'icon' | 'standardOverrides'
>,
labelKey: 'label' | 'description' | 'icon',
locale: keyof typeof APP_LOCALES | undefined,
@@ -18,10 +18,6 @@ export const resolveFieldMetadataStandardOverride = (
): string => {
const safeLocale = locale ?? SOURCE_LOCALE;
if (fieldMetadata.isCustom) {
return fieldMetadata[labelKey] ?? '';
}
if (labelKey === 'icon' && isDefined(fieldMetadata.standardOverrides?.icon)) {
return fieldMetadata.standardOverrides.icon;
}
@@ -103,11 +103,6 @@ export const ALL_ENTITY_PROPERTIES_CONFIGURATION_BY_METADATA_NAME = {
toStringify: false,
universalProperty: undefined,
},
isCustom: {
toCompare: false,
toStringify: false,
universalProperty: undefined,
},
isSystem: {
toCompare: false,
toStringify: false,
@@ -207,11 +202,6 @@ export const ALL_ENTITY_PROPERTIES_CONFIGURATION_BY_METADATA_NAME = {
toStringify: true,
universalProperty: undefined,
},
isCustom: {
toCompare: false,
toStringify: false,
universalProperty: undefined,
},
isRemote: {
toCompare: false,
toStringify: false,
@@ -1,8 +1,9 @@
import { type MakeWasRemovedInUpgradePropertiesOptional } from 'src/engine/core-modules/upgrade/decorators/was-removed-in-upgrade.decorator';
import { type CastRecordTypeOrmDatePropertiesToString } from 'src/engine/metadata-modules/flat-entity/types/cast-record-typeorm-date-properties-to-string.type';
import { type ExtractEntityRelatedEntityProperties } from 'src/engine/metadata-modules/flat-entity/types/extract-entity-related-entity-properties.type';
export type ScalarFlatEntity<TEntity> = Omit<
TEntity,
MakeWasRemovedInUpgradePropertiesOptional<TEntity>,
| ExtractEntityRelatedEntityProperties<TEntity>
| keyof CastRecordTypeOrmDatePropertiesToString<TEntity>
> &
@@ -22,7 +22,6 @@ export const ATTACHMENT_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -45,7 +44,6 @@ export const ATTACHMENT_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -68,7 +66,6 @@ export const ATTACHMENT_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -91,7 +88,6 @@ export const ATTACHMENT_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: true,
isNullable: false,
@@ -114,7 +110,6 @@ export const ATTACHMENT_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -137,7 +132,6 @@ export const ATTACHMENT_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -160,7 +154,6 @@ export const ATTACHMENT_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -187,7 +180,6 @@ export const ATTACHMENT_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'authorId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -214,7 +206,6 @@ export const ATTACHMENT_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'taskId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -241,7 +232,6 @@ export const ATTACHMENT_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'noteId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -268,7 +258,6 @@ export const ATTACHMENT_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'personId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -295,7 +284,6 @@ export const ATTACHMENT_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'companyId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -322,7 +310,6 @@ export const ATTACHMENT_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'opportunityId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -349,7 +336,6 @@ export const ATTACHMENT_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'rocketId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -376,7 +362,6 @@ export const ATTACHMENT_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'petId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -403,7 +388,6 @@ export const ATTACHMENT_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'surveyResultId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -22,7 +22,6 @@ export const COMPANY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -50,7 +49,6 @@ export const COMPANY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -77,7 +75,6 @@ export const COMPANY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -100,7 +97,6 @@ export const COMPANY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -132,7 +128,6 @@ export const COMPANY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -155,7 +150,6 @@ export const COMPANY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: true,
isNullable: false,
@@ -182,7 +176,6 @@ export const COMPANY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -205,7 +198,6 @@ export const COMPANY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -228,7 +220,6 @@ export const COMPANY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: true,
isNullable: false,
@@ -251,7 +242,6 @@ export const COMPANY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -274,7 +264,6 @@ export const COMPANY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -297,7 +286,6 @@ export const COMPANY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -320,7 +308,6 @@ export const COMPANY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -348,7 +335,6 @@ export const COMPANY_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'accountOwnerId',
},
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -371,7 +357,6 @@ export const COMPANY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -394,7 +379,6 @@ export const COMPANY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -417,7 +401,6 @@ export const COMPANY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -440,7 +423,6 @@ export const COMPANY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -463,7 +445,6 @@ export const COMPANY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -486,7 +467,6 @@ export const COMPANY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: true,
isActive: true,
isSystem: false,
isNullable: false,
@@ -513,7 +493,6 @@ export const COMPANY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: true,
isActive: true,
isSystem: false,
isNullable: true,
@@ -558,7 +537,6 @@ export const COMPANY_FLAT_FIELDS_MOCK = {
},
],
settings: null,
isCustom: true,
isActive: true,
isSystem: false,
isNullable: true,
@@ -581,7 +559,6 @@ export const COMPANY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: true,
isActive: true,
isSystem: false,
isNullable: true,
@@ -32,7 +32,6 @@ export const getFlatFieldMetadataMock = <T extends FieldMetadataType>(
icon: 'icon',
id: faker.string.uuid(),
isActive: true,
isCustom: true,
name: 'flatFieldMetadataName',
label: 'flat field metadata label',
isNullable: true,
@@ -67,7 +66,6 @@ export const getStandardFlatFieldMetadataMock = (
) => {
return getFlatFieldMetadataMock({
standardOverrides: {},
isCustom: false,
isSystem: true,
...overrides,
});
@@ -45,7 +45,6 @@ export const getRelationTargetFlatFieldMetadataMock = ({
icon: 'icon',
id: faker.string.uuid(),
isActive: true,
isCustom: true,
name: 'flatFieldMetadataName',
label: 'flat field metadata label',
isNullable: true,
@@ -18,7 +18,6 @@ export const NOTE_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: true,
isNullable: false,
@@ -41,7 +40,6 @@ export const NOTE_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -64,7 +62,6 @@ export const NOTE_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -91,7 +88,6 @@ export const NOTE_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -114,7 +110,6 @@ export const NOTE_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -137,7 +132,6 @@ export const NOTE_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: true,
isNullable: false,
@@ -160,7 +154,6 @@ export const NOTE_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -183,7 +176,6 @@ export const NOTE_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -206,7 +198,6 @@ export const NOTE_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -229,7 +220,6 @@ export const NOTE_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -252,7 +242,6 @@ export const NOTE_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -275,7 +264,6 @@ export const NOTE_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -22,7 +22,6 @@ export const NOTETARGET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: true,
isNullable: false,
@@ -45,7 +44,6 @@ export const NOTETARGET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -68,7 +66,6 @@ export const NOTETARGET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -91,7 +88,6 @@ export const NOTETARGET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -118,7 +114,6 @@ export const NOTETARGET_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'noteId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -145,7 +140,6 @@ export const NOTETARGET_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'personId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -172,7 +166,6 @@ export const NOTETARGET_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'companyId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -199,7 +192,6 @@ export const NOTETARGET_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'opportunityId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -226,7 +218,6 @@ export const NOTETARGET_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'rocketId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -253,7 +244,6 @@ export const NOTETARGET_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'petId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -280,7 +270,6 @@ export const NOTETARGET_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'surveyResultId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -22,7 +22,6 @@ export const OPPORTUNITY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -45,7 +44,6 @@ export const OPPORTUNITY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -68,7 +66,6 @@ export const OPPORTUNITY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -127,7 +124,6 @@ export const OPPORTUNITY_FLAT_FIELDS_MOCK = {
},
],
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -150,7 +146,6 @@ export const OPPORTUNITY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: true,
isNullable: false,
@@ -177,7 +172,6 @@ export const OPPORTUNITY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -200,7 +194,6 @@ export const OPPORTUNITY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -223,7 +216,6 @@ export const OPPORTUNITY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: true,
isNullable: false,
@@ -246,7 +238,6 @@ export const OPPORTUNITY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -269,7 +260,6 @@ export const OPPORTUNITY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -292,7 +282,6 @@ export const OPPORTUNITY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -319,7 +308,6 @@ export const OPPORTUNITY_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'pointOfContactId',
},
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -346,7 +334,6 @@ export const OPPORTUNITY_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'companyId',
},
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -369,7 +356,6 @@ export const OPPORTUNITY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -392,7 +378,6 @@ export const OPPORTUNITY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -415,7 +400,6 @@ export const OPPORTUNITY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -438,7 +422,6 @@ export const OPPORTUNITY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -22,7 +22,6 @@ export const PERSON_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -45,7 +44,6 @@ export const PERSON_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -72,7 +70,6 @@ export const PERSON_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -95,7 +92,6 @@ export const PERSON_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -123,7 +119,6 @@ export const PERSON_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -146,7 +141,6 @@ export const PERSON_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: true,
isNullable: false,
@@ -169,7 +163,6 @@ export const PERSON_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: true,
isNullable: false,
@@ -196,7 +189,6 @@ export const PERSON_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -219,7 +211,6 @@ export const PERSON_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -242,7 +233,6 @@ export const PERSON_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: true,
isNullable: false,
@@ -265,7 +255,6 @@ export const PERSON_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -288,7 +277,6 @@ export const PERSON_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -311,7 +299,6 @@ export const PERSON_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -338,7 +325,6 @@ export const PERSON_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'companyId',
},
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -362,7 +348,6 @@ export const PERSON_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -385,7 +370,6 @@ export const PERSON_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -408,7 +392,6 @@ export const PERSON_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -431,7 +414,6 @@ export const PERSON_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -454,7 +436,6 @@ export const PERSON_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -477,7 +458,6 @@ export const PERSON_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -500,7 +480,6 @@ export const PERSON_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -523,7 +502,6 @@ export const PERSON_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: true,
isActive: true,
isSystem: false,
isNullable: false,
@@ -551,7 +529,6 @@ export const PERSON_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: true,
isActive: true,
isSystem: false,
isNullable: false,
@@ -596,7 +573,6 @@ export const PERSON_FLAT_FIELDS_MOCK = {
},
],
settings: null,
isCustom: true,
isActive: true,
isSystem: false,
isNullable: true,
@@ -650,7 +626,6 @@ export const PERSON_FLAT_FIELDS_MOCK = {
},
],
settings: null,
isCustom: true,
isActive: true,
isSystem: false,
isNullable: true,
@@ -18,7 +18,6 @@ export const PET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -41,7 +40,6 @@ export const PET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: true,
isNullable: false,
@@ -64,7 +62,6 @@ export const PET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -87,7 +84,6 @@ export const PET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -110,7 +106,6 @@ export const PET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -133,7 +128,6 @@ export const PET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -156,7 +150,6 @@ export const PET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -179,7 +172,6 @@ export const PET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: true,
isNullable: false,
@@ -202,7 +194,6 @@ export const PET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -225,7 +216,6 @@ export const PET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -248,7 +238,6 @@ export const PET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -271,7 +260,6 @@ export const PET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: false,
isSystem: true,
isNullable: true,
@@ -337,7 +325,6 @@ export const PET_FLAT_FIELDS_MOCK = {
},
],
settings: null,
isCustom: true,
isActive: true,
isSystem: false,
isNullable: true,
@@ -403,7 +390,6 @@ export const PET_FLAT_FIELDS_MOCK = {
},
],
settings: null,
isCustom: true,
isActive: true,
isSystem: false,
isNullable: true,
@@ -426,7 +412,6 @@ export const PET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: true,
isActive: true,
isSystem: false,
isNullable: false,
@@ -449,7 +434,6 @@ export const PET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: true,
isActive: true,
isSystem: false,
isNullable: true,
@@ -481,7 +465,6 @@ export const PET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: true,
isActive: true,
isSystem: false,
isNullable: true,
@@ -509,7 +492,6 @@ export const PET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: true,
isActive: true,
isSystem: false,
isNullable: true,
@@ -532,7 +514,6 @@ export const PET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: true,
isActive: true,
isSystem: false,
isNullable: true,
@@ -555,7 +536,6 @@ export const PET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: true,
isActive: true,
isSystem: false,
isNullable: true,
@@ -578,7 +558,6 @@ export const PET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: true,
isActive: true,
isSystem: false,
isNullable: true,
@@ -605,7 +584,6 @@ export const PET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: true,
isActive: true,
isSystem: false,
isNullable: true,
@@ -628,7 +606,6 @@ export const PET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: true,
isActive: true,
isSystem: false,
isNullable: true,
@@ -651,7 +628,6 @@ export const PET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: true,
isActive: true,
isSystem: false,
isNullable: true,
@@ -705,7 +681,6 @@ export const PET_FLAT_FIELDS_MOCK = {
},
],
settings: null,
isCustom: true,
isActive: true,
isSystem: false,
isNullable: true,
@@ -728,7 +703,6 @@ export const PET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: true,
isActive: true,
isSystem: false,
isNullable: true,
@@ -751,7 +725,6 @@ export const PET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: true,
isActive: true,
isSystem: false,
isNullable: true,
@@ -774,7 +747,6 @@ export const PET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: true,
isActive: true,
isSystem: false,
isNullable: true,
@@ -18,7 +18,6 @@ export const ROCKET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: true,
isNullable: false,
@@ -41,7 +40,6 @@ export const ROCKET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -64,7 +62,6 @@ export const ROCKET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -87,7 +84,6 @@ export const ROCKET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -110,7 +106,6 @@ export const ROCKET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -133,7 +128,6 @@ export const ROCKET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -156,7 +150,6 @@ export const ROCKET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: true,
isNullable: false,
@@ -179,7 +172,6 @@ export const ROCKET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -202,7 +194,6 @@ export const ROCKET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -225,7 +216,6 @@ export const ROCKET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -248,7 +238,6 @@ export const ROCKET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -271,7 +260,6 @@ export const ROCKET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: false,
isSystem: true,
isNullable: true,
@@ -22,7 +22,6 @@ export const TASK_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: true,
isNullable: false,
@@ -45,7 +44,6 @@ export const TASK_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -68,7 +66,6 @@ export const TASK_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -91,7 +88,6 @@ export const TASK_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -136,7 +132,6 @@ export const TASK_FLAT_FIELDS_MOCK = {
},
],
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -163,7 +158,6 @@ export const TASK_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -186,7 +180,6 @@ export const TASK_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -209,7 +202,6 @@ export const TASK_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: true,
isNullable: false,
@@ -232,7 +224,6 @@ export const TASK_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -255,7 +246,6 @@ export const TASK_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -278,7 +268,6 @@ export const TASK_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -301,7 +290,6 @@ export const TASK_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -324,7 +312,6 @@ export const TASK_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -351,7 +338,6 @@ export const TASK_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'assigneeId',
},
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -374,7 +360,6 @@ export const TASK_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { relationType: RelationType.ONE_TO_MANY },
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -22,7 +22,6 @@ export const TASKTARGET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: true,
isNullable: false,
@@ -45,7 +44,6 @@ export const TASKTARGET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -68,7 +66,6 @@ export const TASKTARGET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -91,7 +88,6 @@ export const TASKTARGET_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -118,7 +114,6 @@ export const TASKTARGET_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'taskId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -145,7 +140,6 @@ export const TASKTARGET_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'personId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -172,7 +166,6 @@ export const TASKTARGET_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'companyId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -199,7 +192,6 @@ export const TASKTARGET_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'opportunityId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -226,7 +218,6 @@ export const TASKTARGET_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'rocketId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -253,7 +244,6 @@ export const TASKTARGET_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'petId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -280,7 +270,6 @@ export const TASKTARGET_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'surveyResultId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -22,7 +22,6 @@ export const TIMELINEACTIVITY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -45,7 +44,6 @@ export const TIMELINEACTIVITY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -68,7 +66,6 @@ export const TIMELINEACTIVITY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -91,7 +88,6 @@ export const TIMELINEACTIVITY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -114,7 +110,6 @@ export const TIMELINEACTIVITY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -137,7 +132,6 @@ export const TIMELINEACTIVITY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -160,7 +154,6 @@ export const TIMELINEACTIVITY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: null,
isCustom: false,
isActive: true,
isSystem: true,
isNullable: false,
@@ -183,7 +176,6 @@ export const TIMELINEACTIVITY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -206,7 +198,6 @@ export const TIMELINEACTIVITY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: false,
@@ -229,7 +220,6 @@ export const TIMELINEACTIVITY_FLAT_FIELDS_MOCK = {
standardOverrides: null,
options: null,
settings: { displayFormat: DateDisplayFormat.RELATIVE },
isCustom: false,
isActive: true,
isSystem: false,
isNullable: true,
@@ -256,7 +246,6 @@ export const TIMELINEACTIVITY_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'workspaceMemberId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -283,7 +272,6 @@ export const TIMELINEACTIVITY_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'personId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -310,7 +298,6 @@ export const TIMELINEACTIVITY_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'companyId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -337,7 +324,6 @@ export const TIMELINEACTIVITY_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'opportunityId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -364,7 +350,6 @@ export const TIMELINEACTIVITY_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'noteId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -391,7 +376,6 @@ export const TIMELINEACTIVITY_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'taskId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -418,7 +402,6 @@ export const TIMELINEACTIVITY_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'workflowId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -445,7 +428,6 @@ export const TIMELINEACTIVITY_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'workflowVersionId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -472,7 +454,6 @@ export const TIMELINEACTIVITY_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'workflowRunId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -499,7 +480,6 @@ export const TIMELINEACTIVITY_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'rocketId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -526,7 +506,6 @@ export const TIMELINEACTIVITY_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'petId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -553,7 +532,6 @@ export const TIMELINEACTIVITY_FLAT_FIELDS_MOCK = {
relationType: RelationType.MANY_TO_ONE,
joinColumnName: 'surveyResultId',
},
isCustom: false,
isActive: true,
isSystem: true,
isNullable: true,
@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test suite Failure cases should fail when morphRelationsCreationPayload has different relation types 1`] = `
{
@@ -124,7 +124,6 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
"fieldPermissionUniversalIdentifiers": [],
"icon": "IconRelationOneToMany",
"isActive": true,
"isCustom": true,
"isLabelSyncedWithName": false,
"isNullable": true,
"isSystem": false,
@@ -159,7 +158,6 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
"fieldPermissionUniversalIdentifiers": [],
"icon": "IconPet",
"isActive": true,
"isCustom": true,
"isLabelSyncedWithName": false,
"isNullable": true,
"isSystem": false,
@@ -196,7 +194,6 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
"fieldPermissionUniversalIdentifiers": [],
"icon": "IconRelationOneToMany",
"isActive": true,
"isCustom": true,
"isLabelSyncedWithName": false,
"isNullable": true,
"isSystem": false,
@@ -231,7 +228,6 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
"fieldPermissionUniversalIdentifiers": [],
"icon": "IconBuilding",
"isActive": true,
"isCustom": true,
"isLabelSyncedWithName": false,
"isNullable": true,
"isSystem": false,
@@ -16,6 +16,7 @@ import { validateMorphOrRelationFlatFieldMetadata } from 'src/engine/metadata-mo
import { validateMorphRelationFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-morph-relation-flat-field-metadata.util';
import { validatePositionFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-position-flat-field-metadata.util';
import { validateTsVectorFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-ts-vector-flat-field-metadata.util';
import { belongsToTwentyStandardApp } from 'src/engine/metadata-modules/utils/belongs-to-twenty-standard-app.util';
const DEFAULT_NO_VALIDATION = (): FlatFieldMetadataValidationError[] => [];
@@ -28,7 +29,9 @@ const rejectUserCreation = (
args: FlatFieldMetadataTypeValidationArgs<FieldMetadataType>,
): FlatFieldMetadataValidationError[] => {
const isCreation = !isDefined(args.update);
const isCustomField = args.flatEntityToValidate.isCustom;
const isCustomField = !belongsToTwentyStandardApp(
args.flatEntityToValidate,
);
if (isCreation && isCustomField) {
return [
@@ -74,7 +74,6 @@ describe('generate Morph Or Relation Flat Field Metadata Pair test suite', () =>
description: 'Company pets',
icon: 'IconCat',
type: FieldMetadataType.RELATION,
isCustom: true,
isSystem: false,
isUnique: false,
relationCreationPayload: {
@@ -109,7 +108,6 @@ describe('generate Morph Or Relation Flat Field Metadata Pair test suite', () =>
description: 'Company pets',
icon: 'IconCat',
type: FieldMetadataType.RELATION,
isCustom: true,
isSystem: false,
isUnique: false,
relationCreationPayload: {
@@ -144,7 +142,6 @@ describe('generate Morph Or Relation Flat Field Metadata Pair test suite', () =>
description: 'Company pets',
icon: 'IconCat',
type: FieldMetadataType.RELATION,
isCustom: false,
isSystem: true,
isUnique: true,
relationCreationPayload: {
@@ -180,7 +177,6 @@ describe('generate Morph Or Relation Flat Field Metadata Pair test suite', () =>
description: 'Morph relation to pet',
icon: 'IconCat',
type: FieldMetadataType.MORPH_RELATION,
isCustom: false,
isSystem: true,
isUnique: false,
relationCreationPayload: {
@@ -216,7 +212,6 @@ describe('generate Morph Or Relation Flat Field Metadata Pair test suite', () =>
description: 'Morph relation to pet',
icon: 'IconCat',
type: FieldMetadataType.MORPH_RELATION,
isCustom: false,
isSystem: true,
isUnique: false,
relationCreationPayload: {
@@ -252,7 +247,6 @@ describe('generate Morph Or Relation Flat Field Metadata Pair test suite', () =>
description: 'Morph relation to pet',
icon: 'IconCat',
type: FieldMetadataType.RELATION,
isCustom: false,
isSystem: true,
isUnique: false,
relationCreationPayload: {
@@ -363,7 +357,6 @@ describe('generate Morph Or Relation Flat Field Metadata Pair test suite', () =>
description: 'Company pets',
icon: 'IconCat',
type: FieldMetadataType.RELATION,
isCustom: true,
isSystem: false,
isUnique: false,
universalIdentifier: sourceUniversalIdentifier,
@@ -1,5 +1,6 @@
import { type FieldMetadataDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto';
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
import { belongsToTwentyStandardApp } from 'src/engine/metadata-modules/utils/belongs-to-twenty-standard-app.util';
export const fromFlatFieldMetadataToFieldMetadataDto = (
flatFieldMetadata: FlatFieldMetadata,
@@ -22,7 +23,6 @@ export const fromFlatFieldMetadataToFieldMetadataDto = (
workspaceId,
defaultValue,
isActive,
isCustom,
isLabelSyncedWithName,
isSystem,
isUIReadOnly,
@@ -41,7 +41,7 @@ export const fromFlatFieldMetadataToFieldMetadataDto = (
workspaceId,
defaultValue,
isActive,
isCustom,
isCustom: !belongsToTwentyStandardApp(flatFieldMetadata),
isLabelSyncedWithName,
isSystem,
isUIReadOnly,
@@ -32,7 +32,6 @@ export const getDefaultFlatFieldMetadata = ({
description: createFieldInput.description ?? null,
icon: createFieldInput.icon ?? null,
isActive: true,
isCustom: true,
isLabelSyncedWithName: createFieldInput.isLabelSyncedWithName ?? false,
isNullable: generateNullable(
createFieldInput.isNullable,
@@ -1,8 +1,12 @@
import { TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER } from 'twenty-shared/application';
import { getFlatObjectMetadataMock } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock';
export const ATTACHMENT_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
id: '819ed5ff-312f-4423-8e95-02a691cf5c27',
nameSingular: 'attachment',
applicationUniversalIdentifier:
TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER,
namePlural: 'attachments',
labelSingular: 'Attachment',
labelPlural: 'Attachments',
@@ -10,7 +14,6 @@ export const ATTACHMENT_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
icon: 'IconFileImport',
standardOverrides: null,
targetTableName: 'DEPRECATED',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: true,
@@ -1,8 +1,12 @@
import { TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER } from 'twenty-shared/application';
import { getFlatObjectMetadataMock } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock';
export const COMPANY_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
id: '7f5c2c7a-bb23-46fb-b59d-9b7a52a8d1cc',
nameSingular: 'company',
applicationUniversalIdentifier:
TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER,
namePlural: 'companies',
labelSingular: 'Company',
labelPlural: 'Companies',
@@ -10,7 +14,6 @@ export const COMPANY_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
icon: 'IconBuildingSkyscraper',
standardOverrides: null,
targetTableName: 'DEPRECATED',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: false,
@@ -1,4 +1,5 @@
import { faker } from '@faker-js/faker';
import { TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER } from 'twenty-shared/application';
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
@@ -29,7 +30,6 @@ export const getFlatObjectMetadataMock = (
imageIdentifierFieldMetadataId,
isActive: true,
isAuditLogged: true,
isCustom: true,
isLabelSyncedWithName: false,
isRemote: false,
isSearchable: true,
@@ -67,8 +67,9 @@ export const getStandardFlatObjectMetadataMock = (
) => {
return getFlatObjectMetadataMock({
standardOverrides: {},
isCustom: false,
isSystem: true,
applicationUniversalIdentifier:
TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER,
...overrides,
});
};
@@ -1,8 +1,12 @@
import { TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER } from 'twenty-shared/application';
import { getFlatObjectMetadataMock } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock';
export const NOTE_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
id: '1253e3e5-5b00-4a34-93b8-02f3dc6e2b7c',
nameSingular: 'note',
applicationUniversalIdentifier:
TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER,
namePlural: 'notes',
labelSingular: 'Note',
labelPlural: 'Notes',
@@ -10,7 +14,6 @@ export const NOTE_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
icon: 'IconNotes',
standardOverrides: null,
targetTableName: 'DEPRECATED',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: false,
@@ -1,8 +1,12 @@
import { TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER } from 'twenty-shared/application';
import { getFlatObjectMetadataMock } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock';
export const NOTE_TARGET_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
id: '12e3cb51-c3de-4192-b0d5-965d48d001c0',
nameSingular: 'noteTarget',
applicationUniversalIdentifier:
TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER,
namePlural: 'noteTargets',
labelSingular: 'Note Target',
labelPlural: 'Note Targets',
@@ -10,7 +14,6 @@ export const NOTE_TARGET_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
icon: 'IconCheckbox',
standardOverrides: null,
targetTableName: 'DEPRECATED',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: true,
@@ -1,8 +1,12 @@
import { TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER } from 'twenty-shared/application';
import { getFlatObjectMetadataMock } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock';
export const OPPORTUNITY_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
id: 'e6996bbf-dd41-423a-9324-8546f5b22fa7',
nameSingular: 'opportunity',
applicationUniversalIdentifier:
TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER,
namePlural: 'opportunities',
labelSingular: 'Opportunity',
labelPlural: 'Opportunities',
@@ -10,7 +14,6 @@ export const OPPORTUNITY_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
icon: 'IconTargetArrow',
standardOverrides: null,
targetTableName: 'DEPRECATED',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: false,
@@ -1,8 +1,12 @@
import { TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER } from 'twenty-shared/application';
import { getFlatObjectMetadataMock } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock';
export const PERSON_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
id: '843e0b67-9619-4628-91c4-2fa62256a611',
nameSingular: 'person',
applicationUniversalIdentifier:
TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER,
namePlural: 'people',
labelSingular: 'Person',
labelPlural: 'People',
@@ -10,7 +14,6 @@ export const PERSON_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
icon: 'IconUser',
standardOverrides: null,
targetTableName: 'DEPRECATED',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: false,
@@ -10,7 +10,6 @@ export const PET_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
icon: 'IconCat',
standardOverrides: null,
targetTableName: 'DEPRECATED',
isCustom: true,
isRemote: false,
isActive: true,
isSystem: false,
@@ -10,7 +10,6 @@ export const ROCKET_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
icon: 'IconRocket',
standardOverrides: null,
targetTableName: 'DEPRECATED',
isCustom: true,
isRemote: false,
isActive: true,
isSystem: false,
@@ -1,8 +1,12 @@
import { TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER } from 'twenty-shared/application';
import { getFlatObjectMetadataMock } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock';
export const TASK_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
id: '3186920d-2a15-4b5f-96c7-2bf6567024b0',
nameSingular: 'task',
applicationUniversalIdentifier:
TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER,
namePlural: 'tasks',
labelSingular: 'Task',
labelPlural: 'Tasks',
@@ -10,7 +14,6 @@ export const TASK_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
icon: 'IconCheckbox',
standardOverrides: null,
targetTableName: 'DEPRECATED',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: false,
@@ -1,8 +1,12 @@
import { TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER } from 'twenty-shared/application';
import { getFlatObjectMetadataMock } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock';
export const TASK_TARGET_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
id: 'bb2b29b8-7f46-4106-a8ae-3a32df9c9166',
nameSingular: 'taskTarget',
applicationUniversalIdentifier:
TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER,
namePlural: 'taskTargets',
labelSingular: 'Task Target',
labelPlural: 'Task Targets',
@@ -10,7 +14,6 @@ export const TASK_TARGET_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
icon: 'IconCheckbox',
standardOverrides: null,
targetTableName: 'DEPRECATED',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: true,
@@ -1,8 +1,12 @@
import { TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER } from 'twenty-shared/application';
import { getFlatObjectMetadataMock } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock';
export const TIMELINE_ACTIVITY_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
id: '3090f830-c4b1-41a1-8e18-815760830bec',
nameSingular: 'timelineActivity',
applicationUniversalIdentifier:
TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER,
namePlural: 'timelineActivities',
labelSingular: 'Timeline Activity',
labelPlural: 'Timeline Activities',
@@ -10,7 +14,6 @@ export const TIMELINE_ACTIVITY_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
icon: 'IconTimelineEvent',
standardOverrides: null,
targetTableName: 'DEPRECATED',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: true,
@@ -75,7 +75,6 @@ export const fromCreateObjectInputToFlatObjectMetadataAndFlatFieldMetadatasToCre
icon: createObjectInput.icon ?? null,
isActive: true,
isAuditLogged: true,
isCustom: true,
isLabelSyncedWithName: createObjectInput.isLabelSyncedWithName ?? false,
isRemote: createObjectInput.isRemote ?? false,
isSearchable: true,
@@ -1,5 +1,6 @@
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
import { type ObjectMetadataDTO } from 'src/engine/metadata-modules/object-metadata/dtos/object-metadata.dto';
import { belongsToTwentyStandardApp } from 'src/engine/metadata-modules/utils/belongs-to-twenty-standard-app.util';
export const fromFlatObjectMetadataToObjectMetadataDto = (
flatObjectMetadata: FlatObjectMetadata,
@@ -16,7 +17,6 @@ export const fromFlatObjectMetadataToObjectMetadataDto = (
id,
universalIdentifier,
isActive,
isCustom,
isLabelSyncedWithName,
isRemote,
isSearchable,
@@ -36,7 +36,7 @@ export const fromFlatObjectMetadataToObjectMetadataDto = (
id,
universalIdentifier,
isActive,
isCustom,
isCustom: !belongsToTwentyStandardApp(flatObjectMetadata),
isLabelSyncedWithName,
isRemote,
isSearchable,
@@ -1,3 +1,4 @@
import { TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER } from 'twenty-shared/application';
import { FieldMetadataType, RelationType } from 'twenty-shared/types';
import { IndexType } from 'src/engine/metadata-modules/index-metadata/types/indexType.types';
@@ -15,7 +16,8 @@ describe('generateFlatIndexMetadataWithNameOrThrow', () => {
const companyObject = {
universalIdentifier: 'obj-company',
nameSingular: 'company',
isCustom: false,
applicationUniversalIdentifier:
TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER,
} as UniversalFlatObjectMetadata;
const scalarUniqueField = {
@@ -61,8 +63,8 @@ describe('generateFlatIndexMetadataWithNameOrThrow', () => {
objectMetadataUniversalIdentifier: companyObject.universalIdentifier,
indexType: overrides.indexType,
indexWhereClause: overrides.indexWhereClause ?? null,
isCustom: false,
isUnique: overrides.isUnique,
isCustom: false,
universalFlatIndexFieldMetadatas: overrides.fieldIds.map((id, order) => ({
createdAt: now,
updatedAt: now,
@@ -1,13 +1,11 @@
import { createHash } from 'crypto';
import { belongsToTwentyStandardApp } from 'src/engine/metadata-modules/utils/belongs-to-twenty-standard-app.util';
import { type UniversalFlatObjectMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-object-metadata.type';
import { computeTableName } from 'src/engine/utils/compute-table-name.util';
type GenerateDeterministicIndexNameArgs = {
flatObjectMetadata: Pick<
UniversalFlatObjectMetadata,
'nameSingular' | 'isCustom'
>;
flatObjectMetadata: UniversalFlatObjectMetadata;
isUnique?: boolean;
orderedIndexColumnNames: string[];
// Include the WHERE clause in the hash so a partial index on the same
@@ -25,7 +23,7 @@ export const generateDeterministicIndexNameV2 = ({
const tableName = computeTableName(
flatObjectMetadata.nameSingular,
flatObjectMetadata.isCustom,
!belongsToTwentyStandardApp(flatObjectMetadata),
);
[tableName, ...orderedIndexColumnNames].forEach((column) => {
@@ -16,6 +16,7 @@ import { MinimalMetadataDTO } from 'src/engine/metadata-modules/minimal-metadata
import { MinimalObjectMetadataDTO } from 'src/engine/metadata-modules/minimal-metadata/dtos/minimal-object-metadata.dto';
import { MinimalViewDTO } from 'src/engine/metadata-modules/minimal-metadata/dtos/minimal-view.dto';
import { resolveObjectMetadataStandardOverride } from 'src/engine/metadata-modules/object-metadata/utils/resolve-object-metadata-standard-override.util';
import { belongsToTwentyStandardApp } from 'src/engine/metadata-modules/utils/belongs-to-twenty-standard-app.util';
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
import { type WorkspaceCacheKeyName } from 'src/engine/workspace-cache/types/workspace-cache-key.type';
@@ -83,7 +84,6 @@ export class MinimalMetadataService {
description: flatObjectMetadata.description ?? undefined,
icon: flatObjectMetadata.icon ?? undefined,
color: flatObjectMetadata.color ?? undefined,
isCustom: flatObjectMetadata.isCustom,
standardOverrides: flatObjectMetadata.standardOverrides ?? undefined,
};
@@ -104,7 +104,7 @@ export class MinimalMetadataService {
i18nInstance,
),
icon: flatObjectMetadata.icon ?? undefined,
isCustom: flatObjectMetadata.isCustom,
isCustom: !belongsToTwentyStandardApp(flatObjectMetadata),
isActive: flatObjectMetadata.isActive,
isSystem: flatObjectMetadata.isSystem,
isRemote: flatObjectMetadata.isRemote,
@@ -22,7 +22,6 @@ const PARTIAL_ID_FIELD = {
isNullable: false,
isUnique: true,
isActive: true,
isCustom: false,
isSystem: true,
isUIReadOnly: true,
isLabelSyncedWithName: false,
@@ -51,7 +50,6 @@ const PARTIAL_CREATED_AT_FIELD = {
isNullable: false,
isUnique: false,
isActive: true,
isCustom: false,
isSystem: true,
isUIReadOnly: true,
isLabelSyncedWithName: false,
@@ -80,7 +78,6 @@ const PARTIAL_UPDATED_AT_FIELD = {
isNullable: false,
isUnique: false,
isActive: true,
isCustom: false,
isSystem: true,
isUIReadOnly: true,
isLabelSyncedWithName: false,
@@ -109,7 +106,6 @@ const PARTIAL_DELETED_AT_FIELD = {
isNullable: true,
isUnique: false,
isActive: true,
isCustom: false,
isSystem: true,
isUIReadOnly: true,
isLabelSyncedWithName: false,
@@ -138,7 +134,6 @@ const PARTIAL_CREATED_BY_FIELD = {
isNullable: false,
isUnique: false,
isActive: true,
isCustom: false,
isSystem: true,
isUIReadOnly: true,
isLabelSyncedWithName: false,
@@ -167,7 +162,6 @@ const PARTIAL_UPDATED_BY_FIELD = {
isNullable: false,
isUnique: false,
isActive: true,
isCustom: false,
isSystem: true,
isUIReadOnly: true,
isLabelSyncedWithName: false,
@@ -196,7 +190,6 @@ const PARTIAL_POSITION_FIELD = {
isNullable: false,
isUnique: false,
isActive: true,
isCustom: false,
isSystem: true,
isUIReadOnly: true,
isLabelSyncedWithName: false,
@@ -225,7 +218,6 @@ const PARTIAL_SEARCH_VECTOR_FIELD = {
isNullable: true,
isUnique: false,
isActive: true,
isCustom: false,
isSystem: true,
isUIReadOnly: true,
isLabelSyncedWithName: false,
@@ -16,9 +16,9 @@ import {
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { In, Repository } from 'typeorm';
import { PermissionFlagType } from 'twenty-shared/constants';
import { FeatureFlagKey } from 'twenty-shared/types';
import { In, Repository } from 'typeorm';
import { parseEndingBeforeRestRequest } from 'src/engine/api/rest/input-request-parsers/ending-before-parser-utils/parse-ending-before-rest-request.util';
import { parseLimitRestRequest } from 'src/engine/api/rest/input-request-parsers/limit-parser-utils/parse-limit-rest-request.util';
@@ -28,6 +28,7 @@ import {
type RestCursorPageInfo,
} from 'src/engine/api/rest/metadata/utils/paginate-by-id-cursor.util';
import { type AuthenticatedRequest } from 'src/engine/api/rest/types/authenticated-request';
import { ApplicationRestApiExceptionFilter } from 'src/engine/core-modules/application/application-rest-api-exception.filter';
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
@@ -37,8 +38,8 @@ import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { fromFieldMetadataEntityToFieldMetadataDto } from 'src/engine/metadata-modules/field-metadata/utils/from-field-metadata-entity-to-field-metadata-dto.util';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
import { computeUniqueFieldMetadataIdsFromFlatIndexMaps } from 'src/engine/metadata-modules/index-metadata/utils/compute-unique-field-metadata-ids-from-flat-index-maps.util';
import { fromFlatObjectMetadataToObjectMetadataDto } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-to-object-metadata-dto.util';
import { computeUniqueFieldMetadataIdsFromFlatIndexMaps } from 'src/engine/metadata-modules/index-metadata/utils/compute-unique-field-metadata-ids-from-flat-index-maps.util';
import { CreateObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/create-object.input';
import { type ObjectMetadataWithFieldsDTO } from 'src/engine/metadata-modules/object-metadata/dtos/object-metadata-with-fields.dto';
import { UpdateObjectPayload } from 'src/engine/metadata-modules/object-metadata/dtos/update-object.input';
@@ -58,6 +59,7 @@ import {
toLegacyObjectMetadataUpdateResponse,
} from 'src/engine/metadata-modules/object-metadata/utils/to-legacy-object-metadata-response.util';
import { PermissionsRestApiExceptionFilter } from 'src/engine/metadata-modules/permissions/utils/permissions-rest-api-exception.filter';
import { getTwentyStandardApplicationIdOrThrow } from 'src/engine/metadata-modules/utils/get-twenty-standard-application-id-or-throw.util';
@Controller('rest/metadata/objects')
@UseGuards(
@@ -68,6 +70,7 @@ import { PermissionsRestApiExceptionFilter } from 'src/engine/metadata-modules/p
@UseFilters(
PermissionsRestApiExceptionFilter,
ObjectMetadataRestApiExceptionFilter,
ApplicationRestApiExceptionFilter,
)
@UsePipes(new ValidationPipe())
export class ObjectMetadataController {
@@ -92,6 +95,17 @@ export class ObjectMetadataController {
return computeUniqueFieldMetadataIdsFromFlatIndexMaps(flatIndexMaps);
}
private async loadStandardApplicationId(
workspaceId: string,
): Promise<string> {
const { flatApplicationMaps } =
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
{ workspaceId, flatMapsKeys: ['flatApplicationMaps'] },
);
return getTwentyStandardApplicationIdOrThrow(flatApplicationMaps);
}
@Get()
async findMany(
@Req() request: AuthenticatedRequest,
@@ -105,19 +119,22 @@ export class ObjectMetadataController {
endingBefore: parseEndingBeforeRestRequest(request),
});
const [fields, uniqueFieldMetadataIds] = await Promise.all([
this.findFieldsForObjectIds(
workspaceId,
items.map((object) => object.id),
),
this.loadUniqueFieldMetadataIds(workspaceId),
]);
const [fields, uniqueFieldMetadataIds, standardApplicationId] =
await Promise.all([
this.findFieldsForObjectIds(
workspaceId,
items.map((object) => object.id),
),
this.loadUniqueFieldMetadataIds(workspaceId),
this.loadStandardApplicationId(workspaceId),
]);
const data = items.map((object) =>
this.toObjectWithFieldsDto(
object,
fields.get(object.id) ?? [],
uniqueFieldMetadataIds,
standardApplicationId,
),
);
@@ -148,17 +165,20 @@ export class ObjectMetadataController {
);
}
const [fields, uniqueFieldMetadataIds] = await Promise.all([
this.fieldMetadataRepository.find({
where: { objectMetadataId: object.id, workspaceId },
}),
this.loadUniqueFieldMetadataIds(workspaceId),
]);
const [fields, uniqueFieldMetadataIds, standardApplicationId] =
await Promise.all([
this.fieldMetadataRepository.find({
where: { objectMetadataId: object.id, workspaceId },
}),
this.loadUniqueFieldMetadataIds(workspaceId),
this.loadStandardApplicationId(workspaceId),
]);
const result = this.toObjectWithFieldsDto(
object,
fields,
uniqueFieldMetadataIds,
standardApplicationId,
);
return (await this.isNewMetadataFormat(workspaceId))
@@ -176,18 +196,21 @@ export class ObjectMetadataController {
workspaceId,
});
const [fields, uniqueFieldMetadataIds] = await Promise.all([
this.fieldMetadataRepository.find({
where: { objectMetadataId: flatObject.id, workspaceId },
}),
this.loadUniqueFieldMetadataIds(workspaceId),
]);
const [fields, uniqueFieldMetadataIds, standardApplicationId] =
await Promise.all([
this.fieldMetadataRepository.find({
where: { objectMetadataId: flatObject.id, workspaceId },
}),
this.loadUniqueFieldMetadataIds(workspaceId),
this.loadStandardApplicationId(workspaceId),
]);
const result: ObjectMetadataWithFieldsDTO = {
...fromFlatObjectMetadataToObjectMetadataDto(flatObject),
fields: fields.map((field) =>
fromFieldMetadataEntityToFieldMetadataDto(
field,
standardApplicationId,
uniqueFieldMetadataIds,
),
),
@@ -247,18 +270,21 @@ export class ObjectMetadataController {
workspaceId,
});
const [fields, uniqueFieldMetadataIds] = await Promise.all([
this.fieldMetadataRepository.find({
where: { objectMetadataId: flatObject.id, workspaceId },
}),
this.loadUniqueFieldMetadataIds(workspaceId),
]);
const [fields, uniqueFieldMetadataIds, standardApplicationId] =
await Promise.all([
this.fieldMetadataRepository.find({
where: { objectMetadataId: flatObject.id, workspaceId },
}),
this.loadUniqueFieldMetadataIds(workspaceId),
this.loadStandardApplicationId(workspaceId),
]);
const result: ObjectMetadataWithFieldsDTO = {
...fromFlatObjectMetadataToObjectMetadataDto(flatObject),
fields: fields.map((field) =>
fromFieldMetadataEntityToFieldMetadataDto(
field,
standardApplicationId,
uniqueFieldMetadataIds,
),
),
@@ -307,12 +333,17 @@ export class ObjectMetadataController {
object: ObjectMetadataEntity,
fields: FieldMetadataEntity[],
uniqueFieldMetadataIds: ReadonlySet<string>,
standardApplicationId: string,
): ObjectMetadataWithFieldsDTO {
return {
...fromObjectMetadataEntityToObjectMetadataDto(object),
...fromObjectMetadataEntityToObjectMetadataDto(
object,
standardApplicationId,
),
fields: fields.map((field) =>
fromFieldMetadataEntityToFieldMetadataDto(
field,
standardApplicationId,
uniqueFieldMetadataIds,
),
),
@@ -62,7 +62,10 @@ export class ObjectMetadataDTO {
@Field({ nullable: true })
color?: string;
@FilterableField()
@Field({
deprecationReason:
'isCustom is derived from the owning application and will be removed; an object is custom when it does not belong to the twenty-standard application.',
})
isCustom: boolean;
@FilterableField()
@@ -16,6 +16,7 @@ import { type ObjectStandardOverridesDTO } from 'src/engine/metadata-modules/obj
import { FieldPermissionEntity } from 'src/engine/metadata-modules/object-permission/field-permission/field-permission.entity';
import { ObjectPermissionEntity } from 'src/engine/metadata-modules/object-permission/object-permission.entity';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { WasRemovedInUpgrade } from 'src/engine/core-modules/upgrade/decorators/was-removed-in-upgrade.decorator';
import { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface';
import { type JsonbProperty } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/jsonb-property.type';
@@ -69,8 +70,12 @@ export class ObjectMetadataEntity
@Column({ nullable: false })
targetTableName: string;
@Column({ default: false })
isCustom: boolean;
@WasRemovedInUpgrade({
upgradeCommandName:
'2.12.0_DropIsCustomFromObjectAndFieldMetadataFastInstanceCommand_1780579070012',
})
@Column({ type: 'boolean', default: false })
isCustom: WasRemovedInUpgrade<boolean>;
@Column({ default: false })
isRemote: boolean;
@@ -45,6 +45,7 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace
TokenModule,
WorkspaceCacheStorageModule,
FeatureFlagModule,
ApplicationModule,
NestjsQueryGraphQLModule.forFeature({
imports: [
TypeORMModule,
@@ -48,6 +48,21 @@ export class ObjectMetadataResolver {
private readonly i18nService: I18nService,
) {}
@ResolveField(() => Boolean, {
deprecationReason:
'isCustom is derived from the owning application and will be removed; an object is custom when it does not belong to the twenty-standard application.',
})
async isCustom(
@Parent() objectMetadata: ObjectMetadataDTO,
@AuthWorkspace() { id: workspaceId }: WorkspaceEntity,
@Context() context: { loaders: IDataloaders },
): Promise<boolean> {
return context.loaders.isCustomLoader.load({
workspaceId,
applicationId: objectMetadata.applicationId,
});
}
@UseGuards(SettingsPermissionGuard(PermissionFlagType.DATA_MODEL))
@Query(() => [ObjectRecordCountDTO])
async objectRecordCounts(
@@ -5,7 +5,7 @@ import { isDefined } from 'twenty-shared/utils';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
import { type ObjectRecordCountDTO } from 'src/engine/metadata-modules/object-metadata/dtos/object-record-count.dto';
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
import { computeTableName } from 'src/engine/utils/compute-table-name.util';
import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util';
import { getWorkspaceSchemaName } from 'src/engine/workspace-datasource/utils/get-workspace-schema-name.util';
@Injectable()
@@ -57,12 +57,7 @@ export class ObjectRecordCountService {
return flatObjectMetadatas.map((flatObjectMetadata) => ({
objectNamePlural: flatObjectMetadata.namePlural,
totalCount:
countByTableName.get(
computeTableName(
flatObjectMetadata.nameSingular,
flatObjectMetadata.isCustom,
),
) ?? 0,
countByTableName.get(computeObjectTargetTable(flatObjectMetadata)) ?? 0,
}));
}
}
@@ -20,7 +20,6 @@ const makeFieldMetadata = (
name: overrides.name,
label: overrides.label ?? overrides.name,
type: overrides.type,
isCustom: overrides.isCustom ?? false,
isActive: true,
isSystem: false,
isUIReadOnly: false,
@@ -29,7 +29,6 @@ describe('resolveObjectMetadataStandardOverride', () => {
description: 'Custom Description',
icon: 'custom-icon',
color: 'blue',
isCustom: true,
standardOverrides: undefined,
} satisfies Pick<
ObjectMetadataDTO,
@@ -38,7 +37,6 @@ describe('resolveObjectMetadataStandardOverride', () => {
| 'labelSingular'
| 'description'
| 'icon'
| 'isCustom'
| 'standardOverrides'
>;
@@ -59,7 +57,6 @@ describe('resolveObjectMetadataStandardOverride', () => {
description: 'Custom Description',
icon: 'custom-icon',
color: 'blue',
isCustom: true,
standardOverrides: undefined,
} satisfies Pick<
ObjectMetadataDTO,
@@ -68,7 +65,6 @@ describe('resolveObjectMetadataStandardOverride', () => {
| 'labelSingular'
| 'description'
| 'icon'
| 'isCustom'
| 'standardOverrides'
>;
@@ -89,7 +85,6 @@ describe('resolveObjectMetadataStandardOverride', () => {
description: 'Custom Description',
icon: 'custom-icon',
color: 'blue',
isCustom: true,
standardOverrides: undefined,
} satisfies Pick<
ObjectMetadataDTO,
@@ -98,7 +93,6 @@ describe('resolveObjectMetadataStandardOverride', () => {
| 'labelSingular'
| 'description'
| 'icon'
| 'isCustom'
| 'standardOverrides'
>;
@@ -119,7 +113,6 @@ describe('resolveObjectMetadataStandardOverride', () => {
description: 'Custom Description',
icon: 'custom-icon',
color: 'green',
isCustom: true,
standardOverrides: undefined,
} satisfies Pick<
ObjectMetadataDTO,
@@ -128,7 +121,6 @@ describe('resolveObjectMetadataStandardOverride', () => {
| 'labelSingular'
| 'description'
| 'icon'
| 'isCustom'
| 'standardOverrides'
>;
@@ -150,7 +142,6 @@ describe('resolveObjectMetadataStandardOverride', () => {
labelPlural: 'My Customs',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: {
icon: 'override-icon',
},
@@ -175,7 +166,6 @@ describe('resolveObjectMetadataStandardOverride', () => {
description: 'Standard Description',
icon: 'default-icon',
color: 'blue',
isCustom: false,
standardOverrides: {
color: 'red',
},
@@ -198,7 +188,6 @@ describe('resolveObjectMetadataStandardOverride', () => {
description: 'Standard Description',
icon: 'default-icon',
color: 'blue',
isCustom: false,
standardOverrides: undefined,
};
@@ -223,7 +212,6 @@ describe('resolveObjectMetadataStandardOverride', () => {
labelPlural: 'Standard Labels',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: {
translations: {
'fr-FR': {
@@ -267,7 +255,6 @@ describe('resolveObjectMetadataStandardOverride', () => {
labelPlural: 'Standard Labels',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: {
translations: {
'es-ES': {
@@ -298,7 +285,6 @@ describe('resolveObjectMetadataStandardOverride', () => {
labelPlural: 'Standard Labels',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: {
translations: {
'fr-FR': {
@@ -328,7 +314,6 @@ describe('resolveObjectMetadataStandardOverride', () => {
labelPlural: 'Standard Labels',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: {
translations: {
'fr-FR': {
@@ -361,7 +346,6 @@ describe('resolveObjectMetadataStandardOverride', () => {
labelPlural: 'Standard Labels',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: {
labelSingular: 'Overridden Label',
labelPlural: 'Overridden Labels',
@@ -410,7 +394,6 @@ describe('resolveObjectMetadataStandardOverride', () => {
labelPlural: 'Standard Labels',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: {
labelSingular: 'Overridden Label',
labelPlural: 'Overridden Labels',
@@ -433,7 +416,6 @@ describe('resolveObjectMetadataStandardOverride', () => {
labelPlural: 'Standard Labels',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: {
labelSingular: undefined,
},
@@ -460,7 +442,6 @@ describe('resolveObjectMetadataStandardOverride', () => {
labelPlural: 'Standard Labels',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: undefined,
};
@@ -485,7 +466,6 @@ describe('resolveObjectMetadataStandardOverride', () => {
labelPlural: 'Standard Labels',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: undefined,
};
@@ -512,7 +492,6 @@ describe('resolveObjectMetadataStandardOverride', () => {
labelPlural: 'Standard Labels',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: {
labelSingular: 'Source Override',
labelPlural: 'Source Overrides',
@@ -543,7 +522,6 @@ describe('resolveObjectMetadataStandardOverride', () => {
labelPlural: 'Standard Labels',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: {
labelSingular: 'Source Override',
labelPlural: 'Source Overrides',
@@ -568,7 +546,6 @@ describe('resolveObjectMetadataStandardOverride', () => {
labelPlural: 'Standard Labels',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: {},
};
@@ -595,7 +572,6 @@ describe('resolveObjectMetadataStandardOverride', () => {
labelPlural: 'Standard Labels',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: {
labelSingular: 'Source Override',
},
@@ -622,7 +598,6 @@ describe('resolveObjectMetadataStandardOverride', () => {
labelPlural: 'Standard Labels',
description: 'Standard Description',
icon: 'default-icon',
isCustom: false,
standardOverrides: undefined,
};
@@ -133,7 +133,6 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
description: 'Name',
isNullable: true,
isActive: true,
isCustom: false,
isSystem: false,
isUIReadOnly: false,
defaultValue: null,
@@ -3,6 +3,7 @@ import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-me
export const fromObjectMetadataEntityToObjectMetadataDto = (
entity: ObjectMetadataEntity,
standardApplicationId: string,
): ObjectMetadataDTO => ({
id: entity.id,
universalIdentifier: entity.universalIdentifier,
@@ -16,7 +17,7 @@ export const fromObjectMetadataEntityToObjectMetadataDto = (
color: entity.color ?? undefined,
shortcut: entity.shortcut ?? undefined,
standardOverrides: entity.standardOverrides ?? undefined,
isCustom: entity.isCustom,
isCustom: entity.applicationId !== standardApplicationId,
isRemote: entity.isRemote,
isActive: entity.isActive,
isSystem: entity.isSystem,
@@ -14,7 +14,6 @@ export const resolveObjectMetadataStandardOverride = (
| 'labelSingular'
| 'description'
| 'icon'
| 'isCustom'
| 'standardOverrides'
>,
labelKey: 'color' | 'labelPlural' | 'labelSingular' | 'description' | 'icon',
@@ -23,10 +22,6 @@ export const resolveObjectMetadataStandardOverride = (
): string => {
const safeLocale = locale ?? SOURCE_LOCALE;
if (objectMetadata.isCustom) {
return objectMetadata[labelKey] ?? '';
}
if (
(labelKey === 'icon' || labelKey === 'color') &&
isDefined(objectMetadata.standardOverrides?.[labelKey])
@@ -0,0 +1,26 @@
import { TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER } from 'twenty-shared/application';
import { isDefined } from 'twenty-shared/utils';
import {
ApplicationException,
ApplicationExceptionCode,
} from 'src/engine/core-modules/application/application.exception';
import { type FlatApplicationCacheMaps } from 'src/engine/core-modules/application/types/flat-application-cache-maps.type';
export const getTwentyStandardApplicationIdOrThrow = (
flatApplicationMaps: FlatApplicationCacheMaps,
): string => {
const twentyStandardApplicationId =
flatApplicationMaps.idByUniversalIdentifier[
TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER
];
if (!isDefined(twentyStandardApplicationId)) {
throw new ApplicationException(
'Could not find the twenty-standard application in the workspace cache',
ApplicationExceptionCode.APPLICATION_NOT_FOUND,
);
}
return twentyStandardApplicationId;
};
@@ -216,7 +216,6 @@ export class ViewController {
labelSingular: objectMetadata.labelSingular,
description: objectMetadata.description ?? undefined,
icon: objectMetadata.icon ?? undefined,
isCustom: objectMetadata.isCustom,
standardOverrides: objectMetadata.standardOverrides ?? undefined,
},
'labelPlural',
@@ -74,7 +74,6 @@ export class ViewResolver {
labelSingular: objectMetadata.labelSingular,
description: objectMetadata.description ?? undefined,
icon: objectMetadata.icon ?? undefined,
isCustom: objectMetadata.isCustom,
standardOverrides: objectMetadata.standardOverrides ?? undefined,
},
'labelPlural',
@@ -12,7 +12,6 @@ const mockObjectMetadata: FlatObjectMetadata = {
workspaceId: 'workspaceId',
labelSingular: 'Label Singular',
labelPlural: 'Label Plural',
isCustom: false,
isRemote: false,
isActive: true,
isSystem: false,
@@ -29,7 +29,6 @@ const makeFlatObjectMetadata = (
labelPlural: 'People',
labelSingular: 'Person',
icon: 'IconUser',
isCustom: false,
standardOverrides: null,
...overrides,
}) as unknown as FlatObjectMetadata;
@@ -101,7 +101,6 @@ describe('WorkspaceEntityManager', () => {
workspaceId: 'test-workspace-id',
icon: 'test-icon',
color: null,
isCustom: false,
isRemote: false,
isAuditLogged: false,
isSearchable: false,
@@ -154,7 +153,6 @@ describe('WorkspaceEntityManager', () => {
description: null,
icon: null,
isActive: true,
isCustom: false,
isSystem: false,
isUIReadOnly: false,
isUnique: false,
@@ -1,6 +1,7 @@
import { Global, Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
@@ -25,6 +26,7 @@ import { WorkspaceEventEmitterModule } from 'src/engine/workspace-event-emitter/
WorkspaceEntity,
ObjectMetadataEntity,
FieldMetadataEntity,
ApplicationEntity,
]),
WorkspaceCacheStorageModule,
WorkspaceManyOrAllFlatEntityMapsCacheModule,
@@ -5,8 +5,9 @@ import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-me
export type EntitySchemaObjectMetadata = Pick<
ObjectMetadataEntity,
'id' | 'nameSingular' | 'isCustom'
'id' | 'nameSingular'
> & {
isCustom: boolean;
fieldIds: string[];
};
@@ -38,6 +39,7 @@ export type EntitySchemaFieldMetadataMaps = {
export const buildEntitySchemaMetadataMaps = (
objectMetadatas: ObjectMetadataEntity[],
fieldMetadatas: FieldMetadataEntity[],
standardApplicationId: string | undefined,
): {
objectMetadataMaps: EntitySchemaObjectMetadataMaps;
fieldMetadataMaps: EntitySchemaFieldMetadataMaps;
@@ -60,7 +62,7 @@ export const buildEntitySchemaMetadataMaps = (
objectMetadataMaps.byId[object.id] = {
id: object.id,
nameSingular: object.nameSingular,
isCustom: object.isCustom,
isCustom: object.applicationId !== standardApplicationId,
fieldIds: fieldIdsByObjectId.get(object.id) ?? [],
};
}

Some files were not shown because too many files have changed in this diff Show More