1630 extensibility twenty cli ability to create edit and delete fields (#15501)
As title - adds decorators in twenty-sdk - update twenty-cli load-manifest to it gets @FieldMetadata infos + testing - update twenty-server so it CRUD fields properly, using universalIdentifier - Fix UI so we can update managed objects records - move FieldMetadata items from twenty-server to twenty-shared
This commit is contained in:
+1
-1
@@ -60,7 +60,7 @@ export default [
|
||||
},
|
||||
{
|
||||
sourceTag: 'scope:sdk',
|
||||
onlyDependOnLibsWithTags: ['scope:sdk'],
|
||||
onlyDependOnLibsWithTags: ['scope:sdk', 'scope:shared'],
|
||||
},
|
||||
{
|
||||
sourceTag: 'scope:shared',
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
import { ObjectMetadata } from 'twenty-sdk/application';
|
||||
import {
|
||||
BaseObjectMetadata,
|
||||
FieldMetadata,
|
||||
ObjectMetadata,
|
||||
FieldMetadataType,
|
||||
} from 'twenty-sdk/application';
|
||||
|
||||
enum PostCardStatus {
|
||||
DRAFT = 'DRAFT',
|
||||
SENT = 'SENT',
|
||||
DELIVERED = 'DELIVERED',
|
||||
RETURNED = 'RETURNED',
|
||||
}
|
||||
|
||||
@ObjectMetadata({
|
||||
universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
|
||||
@@ -9,4 +21,76 @@ import { ObjectMetadata } from 'twenty-sdk/application';
|
||||
description: ' A post card object',
|
||||
icon: 'IconMail',
|
||||
})
|
||||
export class PostCard {}
|
||||
export class PostCard extends BaseObjectMetadata {
|
||||
@FieldMetadata({
|
||||
universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b',
|
||||
type: FieldMetadataType.TEXT,
|
||||
label: 'Content',
|
||||
description: "Postcard's content",
|
||||
icon: 'IconAbc',
|
||||
})
|
||||
content: string;
|
||||
|
||||
@FieldMetadata({
|
||||
universalIdentifier: 'c6aa31f3-da76-4ac6-889f-475e226009ac',
|
||||
type: FieldMetadataType.FULL_NAME,
|
||||
label: 'Recipient name',
|
||||
icon: 'IconUser',
|
||||
})
|
||||
recipientName: string;
|
||||
|
||||
@FieldMetadata({
|
||||
universalIdentifier: '95045777-a0ad-49ec-98f9-22f9fc0c8266',
|
||||
type: FieldMetadataType.ADDRESS,
|
||||
label: 'Recipient address',
|
||||
icon: 'IconHome',
|
||||
})
|
||||
recipientAddress: string;
|
||||
|
||||
@FieldMetadata({
|
||||
universalIdentifier: '87b675b8-dd8c-4448-b4ca-20e5a2234a1e',
|
||||
type: FieldMetadataType.SELECT,
|
||||
label: 'Status',
|
||||
icon: 'IconSend',
|
||||
defaultValue: `'${PostCardStatus.DRAFT}'`,
|
||||
options: [
|
||||
{
|
||||
value: PostCardStatus.DRAFT,
|
||||
label: 'Draft',
|
||||
position: 0,
|
||||
color: 'gray',
|
||||
},
|
||||
{
|
||||
value: PostCardStatus.SENT,
|
||||
label: 'Sent',
|
||||
position: 1,
|
||||
color: 'orange',
|
||||
},
|
||||
{
|
||||
value: PostCardStatus.DELIVERED,
|
||||
label: 'Delivered',
|
||||
position: 2,
|
||||
color: 'green',
|
||||
},
|
||||
{
|
||||
value: PostCardStatus.RETURNED,
|
||||
label: 'Returned',
|
||||
position: 3,
|
||||
color: 'orange',
|
||||
},
|
||||
],
|
||||
})
|
||||
status: PostCardStatus;
|
||||
|
||||
// notes?: string // optional internal notes or comments
|
||||
|
||||
@FieldMetadata({
|
||||
universalIdentifier: 'e06abe72-5b44-4e7f-93be-afc185a3c433',
|
||||
type: FieldMetadataType.DATE_TIME,
|
||||
label: 'Delivered at',
|
||||
icon: 'IconCheck',
|
||||
isNullable: true,
|
||||
defaultValue: null,
|
||||
})
|
||||
deliveredAt?: Date;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,11 @@
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"importHelpers": true,
|
||||
"strict": true,
|
||||
"allowUnreachableCode": false,
|
||||
"strictNullChecks": true,
|
||||
"alwaysStrict": true,
|
||||
"noImplicitAny": true,
|
||||
"strictBindCallApply": false,
|
||||
"target": "es2018",
|
||||
"module": "esnext",
|
||||
"lib": ["es2020", "dom"],
|
||||
|
||||
@@ -10,7 +10,11 @@
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"importHelpers": true,
|
||||
"strict": true,
|
||||
"allowUnreachableCode": false,
|
||||
"strictNullChecks": true,
|
||||
"alwaysStrict": true,
|
||||
"noImplicitAny": true,
|
||||
"strictBindCallApply": false,
|
||||
"target": "es2018",
|
||||
"module": "esnext",
|
||||
"lib": ["es2020", "dom"],
|
||||
|
||||
@@ -73,6 +73,19 @@ export type ServerlessFunctionTriggerManifest = {
|
||||
|
||||
export type Sources = { [key: string]: string | Sources };
|
||||
|
||||
export type FieldMetadata = {
|
||||
universalIdentifier: string;
|
||||
type: string;
|
||||
label: string;
|
||||
description?: string;
|
||||
icon?: string;
|
||||
defaultValue?: any;
|
||||
options?: any;
|
||||
settings?: any;
|
||||
isNullable?: boolean;
|
||||
isFieldUiReadOnly?: boolean;
|
||||
};
|
||||
|
||||
export type ObjectManifest = {
|
||||
universalIdentifier: string;
|
||||
nameSingular: string;
|
||||
@@ -81,6 +94,7 @@ export type ObjectManifest = {
|
||||
labelPlural: string;
|
||||
description?: string;
|
||||
icon?: string;
|
||||
fields: FieldMetadata[];
|
||||
};
|
||||
|
||||
export interface ApiResponse<T = any> {
|
||||
|
||||
@@ -20,6 +20,7 @@ const tsLibMock = `declare module 'tslib' {
|
||||
export const __spreadArray: any;
|
||||
export const __assign: any;
|
||||
}`;
|
||||
|
||||
const twentySdkTypesMock = `
|
||||
declare module 'twenty-sdk/application' {
|
||||
export type SyncableEntityOptions = { universalIdentifier: string };
|
||||
@@ -76,6 +77,18 @@ declare module 'twenty-sdk/application' {
|
||||
export const ObjectMetadata = (_: ObjectMetadataOptions): ClassDecorator => {
|
||||
return () => {};
|
||||
};
|
||||
|
||||
export class BaseObjectMetadata {}
|
||||
|
||||
export enum FieldMetadataType {
|
||||
TEXT = 'TEXT',
|
||||
FULL_NAME = 'FULL_NAME',
|
||||
ADDRESS = 'ADDRESS',
|
||||
SELECT = 'SELECT',
|
||||
DATE_TIME = 'DATE_TIME',
|
||||
}
|
||||
|
||||
export const FieldMetadata: (_: any) => PropertyDecorator;
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -111,7 +124,19 @@ export const config: ServerlessFunctionConfig = {
|
||||
]
|
||||
};`;
|
||||
|
||||
const objectMock = `import { ObjectMetadata } from 'twenty-sdk/application';
|
||||
const objectMock = `import {
|
||||
ObjectMetadata,
|
||||
BaseObjectMetadata,
|
||||
FieldMetadata,
|
||||
FieldMetadataType
|
||||
} from 'twenty-sdk/application';
|
||||
|
||||
enum PostCardStatus {
|
||||
DRAFT = 'DRAFT',
|
||||
SENT = 'SENT',
|
||||
DELIVERED = 'DELIVERED',
|
||||
RETURNED = 'RETURNED',
|
||||
}
|
||||
|
||||
@ObjectMetadata({
|
||||
universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
|
||||
@@ -122,7 +147,72 @@ const objectMock = `import { ObjectMetadata } from 'twenty-sdk/application';
|
||||
description: ' A post card object',
|
||||
icon: 'IconMail',
|
||||
})
|
||||
export class PostCard {}
|
||||
export class PostCard extends BaseObjectMetadata {
|
||||
@FieldMetadata({
|
||||
universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b',
|
||||
type: FieldMetadataType.TEXT,
|
||||
label: 'Content',
|
||||
description: "Postcard's content",
|
||||
})
|
||||
content: string;
|
||||
|
||||
@FieldMetadata({
|
||||
universalIdentifier: 'c6aa31f3-da76-4ac6-889f-475e226009ac',
|
||||
type: FieldMetadataType.FULL_NAME,
|
||||
label: 'Recipient name',
|
||||
})
|
||||
recipientName: string;
|
||||
|
||||
@FieldMetadata({
|
||||
universalIdentifier: '95045777-a0ad-49ec-98f9-22f9fc0c8266',
|
||||
type: FieldMetadataType.ADDRESS,
|
||||
label: 'Recipient address',
|
||||
})
|
||||
recipientAddress: string;
|
||||
|
||||
@FieldMetadata({
|
||||
universalIdentifier: '87b675b8-dd8c-4448-b4ca-20e5a2234a1e',
|
||||
type: FieldMetadataType.SELECT,
|
||||
label: 'Status',
|
||||
defaultValue: \`'\${PostCardStatus.DRAFT}'\`,
|
||||
options: [
|
||||
{
|
||||
value: PostCardStatus.DRAFT,
|
||||
label: 'Draft',
|
||||
position: 0,
|
||||
color: 'gray',
|
||||
},
|
||||
{
|
||||
value: PostCardStatus.SENT,
|
||||
label: 'Sent',
|
||||
position: 1,
|
||||
color: 'orange',
|
||||
},
|
||||
{
|
||||
value: PostCardStatus.DELIVERED,
|
||||
label: 'Delivered',
|
||||
position: 2,
|
||||
color: 'green',
|
||||
},
|
||||
{
|
||||
value: PostCardStatus.RETURNED,
|
||||
label: 'Returned',
|
||||
position: 3,
|
||||
color: 'orange',
|
||||
},
|
||||
],
|
||||
})
|
||||
status: 'draft' | 'sent' | 'delivered' | 'returned';
|
||||
|
||||
@FieldMetadata({
|
||||
universalIdentifier: 'e06abe72-5b44-4e7f-93be-afc185a3c433',
|
||||
type: FieldMetadataType.DATE_TIME,
|
||||
label: 'Delivered at',
|
||||
isNullable: true,
|
||||
defaultValue: null,
|
||||
})
|
||||
deliveredAt?: Date;
|
||||
}
|
||||
`;
|
||||
|
||||
describe('loadManifest (integration)', () => {
|
||||
@@ -178,10 +268,11 @@ describe('loadManifest (integration)', () => {
|
||||
description: 'My app description',
|
||||
});
|
||||
|
||||
// objects collected from @ObjectMetadata
|
||||
expect(manifest.objects.length).toBe(1);
|
||||
|
||||
for (const object of manifest.objects) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const { universalIdentifier: _, ...otherInfo } = object;
|
||||
const { universalIdentifier: _, fields, ...otherInfo } = object;
|
||||
expect(otherInfo).toEqual({
|
||||
description: ' A post card object',
|
||||
icon: 'IconMail',
|
||||
@@ -190,6 +281,61 @@ describe('loadManifest (integration)', () => {
|
||||
namePlural: 'postCards',
|
||||
nameSingular: 'postCard',
|
||||
});
|
||||
|
||||
expect(Array.isArray(fields)).toBe(true);
|
||||
|
||||
expect(fields).toEqual([
|
||||
{
|
||||
universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b',
|
||||
type: 'TEXT',
|
||||
label: 'Content',
|
||||
description: "Postcard's content",
|
||||
name: 'content',
|
||||
},
|
||||
{
|
||||
universalIdentifier: 'c6aa31f3-da76-4ac6-889f-475e226009ac',
|
||||
type: 'FULL_NAME',
|
||||
label: 'Recipient name',
|
||||
name: 'recipientName',
|
||||
},
|
||||
{
|
||||
universalIdentifier: '95045777-a0ad-49ec-98f9-22f9fc0c8266',
|
||||
type: 'ADDRESS',
|
||||
label: 'Recipient address',
|
||||
name: 'recipientAddress',
|
||||
},
|
||||
{
|
||||
universalIdentifier: '87b675b8-dd8c-4448-b4ca-20e5a2234a1e',
|
||||
type: 'SELECT',
|
||||
label: 'Status',
|
||||
defaultValue: "'DRAFT'",
|
||||
options: [
|
||||
{ value: 'DRAFT', label: 'Draft', position: 0, color: 'gray' },
|
||||
{ value: 'SENT', label: 'Sent', position: 1, color: 'orange' },
|
||||
{
|
||||
value: 'DELIVERED',
|
||||
label: 'Delivered',
|
||||
position: 2,
|
||||
color: 'green',
|
||||
},
|
||||
{
|
||||
value: 'RETURNED',
|
||||
label: 'Returned',
|
||||
position: 3,
|
||||
color: 'orange',
|
||||
},
|
||||
],
|
||||
name: 'status',
|
||||
},
|
||||
{
|
||||
universalIdentifier: 'e06abe72-5b44-4e7f-93be-afc185a3c433',
|
||||
type: 'DATE_TIME',
|
||||
label: 'Delivered at',
|
||||
isNullable: true,
|
||||
defaultValue: null,
|
||||
name: 'deliveredAt',
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
// serverless functions
|
||||
|
||||
@@ -31,6 +31,9 @@ import {
|
||||
isFunctionExpression,
|
||||
isExportAssignment,
|
||||
Modifier,
|
||||
isPropertyDeclaration,
|
||||
isNoSubstitutionTemplateLiteral,
|
||||
isTemplateExpression,
|
||||
} from 'typescript';
|
||||
import {
|
||||
AppManifest,
|
||||
@@ -39,6 +42,7 @@ import {
|
||||
PackageJson,
|
||||
ServerlessFunctionManifest,
|
||||
Sources,
|
||||
FieldMetadata,
|
||||
} from '../types/config.types';
|
||||
import { posix, relative, sep, resolve, join } from 'path';
|
||||
import { parseJsoncFile, parseTextFile } from '../utils/jsonc-parser';
|
||||
@@ -96,6 +100,25 @@ const exprToValue = (expr: Expression): JSONValue => {
|
||||
if (expr.kind === SyntaxKind.FalseKeyword) return false;
|
||||
if (expr.kind === SyntaxKind.NullKeyword) return null;
|
||||
|
||||
if (isPropertyAccessExpression(expr)) {
|
||||
if (isIdentifier(expr.expression) && isIdentifier(expr.name)) {
|
||||
return expr.name.text;
|
||||
}
|
||||
return String(expr.getText());
|
||||
}
|
||||
|
||||
if (isNoSubstitutionTemplateLiteral(expr)) {
|
||||
return expr.text;
|
||||
}
|
||||
if (isTemplateExpression(expr)) {
|
||||
let out = expr.head.text;
|
||||
for (const span of expr.templateSpans) {
|
||||
const v = exprToValue(span.expression);
|
||||
out += String(v) + span.literal.text;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
if (isArrayLiteralExpression(expr)) {
|
||||
return expr.elements.map((e) =>
|
||||
e.kind === SyntaxKind.SpreadElement ? [] : exprToValue(e),
|
||||
@@ -155,7 +178,42 @@ const collectObjects = (program: Program) => {
|
||||
if (objectDec) {
|
||||
const cfg = getFirstArgObject(objectDec);
|
||||
if (cfg && typeof cfg === 'object' && !Array.isArray(cfg)) {
|
||||
manifest.push({ ...(cfg as any) } as ObjectManifest);
|
||||
const fields: Array<Record<string, JSONValue>> = [];
|
||||
|
||||
for (const member of node.members) {
|
||||
if (!isPropertyDeclaration(member)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const fieldDec = getDecorators(member)?.find((d) =>
|
||||
isDecoratorNamed(d, 'FieldMetadata'),
|
||||
);
|
||||
|
||||
if (!fieldDec) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const fieldCfg = getFirstArgObject(fieldDec);
|
||||
|
||||
if (!fieldCfg) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Try to attach the TypeScript property name as "name"
|
||||
let name: string | undefined;
|
||||
if (member.name && isIdentifier(member.name)) {
|
||||
name = member.name.text;
|
||||
} else {
|
||||
// fallback to AST text if not a simple identifier
|
||||
name = member.name?.getText?.() ?? undefined;
|
||||
}
|
||||
|
||||
fields.push({
|
||||
...(fieldCfg as FieldMetadata),
|
||||
...(name ? { name } : {}),
|
||||
});
|
||||
}
|
||||
manifest.push({ ...(cfg as any), fields } as ObjectManifest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -65,7 +65,7 @@ describe('isObjectMetadataReadOnly', () => {
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true if object is managed by application', () => {
|
||||
it('should return false if object is managed by application', () => {
|
||||
const result = isObjectMetadataReadOnly({
|
||||
objectMetadataItem: {
|
||||
applicationId: 'applicationId',
|
||||
@@ -74,7 +74,7 @@ describe('isObjectMetadataReadOnly', () => {
|
||||
},
|
||||
});
|
||||
|
||||
expect(result).toBe(true);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if object is custom', () => {
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
import { isObjectMetadataSettingsReadOnly } from '@/object-record/read-only/utils/isObjectMetadataSettingsReadOnly';
|
||||
|
||||
describe('isObjectMetadataSettingsReadOnly', () => {
|
||||
it('should return false if object can be updated and is not UI read only and is not remote', () => {
|
||||
const result = isObjectMetadataSettingsReadOnly({
|
||||
objectPermissions: {
|
||||
canUpdateObjectRecords: true,
|
||||
objectMetadataId: '123',
|
||||
restrictedFields: {},
|
||||
},
|
||||
objectMetadataItem: {
|
||||
isUIReadOnly: false,
|
||||
isRemote: false,
|
||||
},
|
||||
});
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true if object is managed by application', () => {
|
||||
const result = isObjectMetadataSettingsReadOnly({
|
||||
objectPermissions: {
|
||||
canUpdateObjectRecords: true,
|
||||
objectMetadataId: '123',
|
||||
restrictedFields: {},
|
||||
},
|
||||
objectMetadataItem: {
|
||||
applicationId: 'applicationId',
|
||||
isUIReadOnly: false,
|
||||
isRemote: false,
|
||||
},
|
||||
});
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
});
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { isFieldMetadataReadOnlyByPermissions } from '@/object-record/read-only/utils/internal/isFieldMetadataReadOnlyByPermissions';
|
||||
import { isObjectMetadataReadOnly } from '@/object-record/read-only/utils/isObjectMetadataReadOnly';
|
||||
import { type ObjectPermission } from '~/generated/graphql';
|
||||
|
||||
type IsFieldMetadataReadOnlyParams = {
|
||||
objectPermissions: ObjectPermission;
|
||||
objectMetadataItem: Pick<ObjectMetadataItem, 'isUIReadOnly' | 'isRemote'>;
|
||||
fieldMetadataItem: Pick<FieldMetadataItem, 'id' | 'isUIReadOnly'>;
|
||||
};
|
||||
|
||||
export const isFieldMetadataReadOnly = ({
|
||||
objectPermissions,
|
||||
objectMetadataItem,
|
||||
fieldMetadataItem,
|
||||
}: IsFieldMetadataReadOnlyParams) => {
|
||||
const objectMetadataReadOnly = isObjectMetadataReadOnly({
|
||||
objectPermissions,
|
||||
objectMetadataItem,
|
||||
});
|
||||
|
||||
const fieldReadOnlyByPermissions = isFieldMetadataReadOnlyByPermissions({
|
||||
objectPermissions,
|
||||
fieldMetadataId: fieldMetadataItem.id,
|
||||
});
|
||||
|
||||
return (
|
||||
objectMetadataReadOnly ||
|
||||
fieldMetadataItem.isUIReadOnly ||
|
||||
fieldReadOnlyByPermissions
|
||||
);
|
||||
};
|
||||
+2
-3
@@ -17,8 +17,7 @@ export const isObjectMetadataReadOnly = ({
|
||||
return (
|
||||
(isDefined(objectPermissions) &&
|
||||
!objectPermissions.canUpdateObjectRecords) ||
|
||||
objectMetadataItem?.isUIReadOnly ||
|
||||
objectMetadataItem?.isRemote ||
|
||||
isDefined(objectMetadataItem?.applicationId)
|
||||
(isDefined(objectMetadataItem) &&
|
||||
(objectMetadataItem.isUIReadOnly || objectMetadataItem.isRemote))
|
||||
);
|
||||
};
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { type ObjectPermission } from '~/generated/graphql';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { isObjectMetadataReadOnly } from '@/object-record/read-only/utils/isObjectMetadataReadOnly';
|
||||
|
||||
type IsObjectMetadataReadOnlyParams = {
|
||||
objectPermissions?: ObjectPermission;
|
||||
objectMetadataItem?: Pick<
|
||||
ObjectMetadataItem,
|
||||
'isUIReadOnly' | 'isRemote' | 'applicationId'
|
||||
>;
|
||||
};
|
||||
|
||||
export const isObjectMetadataSettingsReadOnly = ({
|
||||
objectPermissions,
|
||||
objectMetadataItem,
|
||||
}: IsObjectMetadataReadOnlyParams) => {
|
||||
return (
|
||||
isObjectMetadataReadOnly({ objectPermissions, objectMetadataItem }) ||
|
||||
isDefined(objectMetadataItem?.applicationId)
|
||||
);
|
||||
};
|
||||
+2
-2
@@ -4,7 +4,6 @@ import { useGetRelationMetadata } from '@/object-metadata/hooks/useGetRelationMe
|
||||
import { useUpdateOneObjectMetadataItem } from '@/object-metadata/hooks/useUpdateOneObjectMetadataItem';
|
||||
import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { isLabelIdentifierField } from '@/object-metadata/utils/isLabelIdentifierField';
|
||||
import { isObjectMetadataReadOnly } from '@/object-record/read-only/utils/isObjectMetadataReadOnly';
|
||||
import { SettingsObjectFieldActiveActionDropdown } from '@/settings/data-model/object-details/components/SettingsObjectFieldActiveActionDropdown';
|
||||
import { SettingsObjectFieldInactiveActionDropdown } from '@/settings/data-model/object-details/components/SettingsObjectFieldDisabledActionDropdown';
|
||||
import { settingsObjectFieldsFamilyState } from '@/settings/data-model/object-details/states/settingsObjectFieldsFamilyState';
|
||||
@@ -31,6 +30,7 @@ import { type SettingsObjectDetailTableItem } from '~/pages/settings/data-model/
|
||||
|
||||
import { RELATION_TYPES } from '../../constants/RelationTypes';
|
||||
import { SettingsObjectFieldDataType } from './SettingsObjectFieldDataType';
|
||||
import { isObjectMetadataSettingsReadOnly } from '@/object-record/read-only/utils/isObjectMetadataSettingsReadOnly';
|
||||
|
||||
type SettingsObjectFieldItemTableRowProps = {
|
||||
settingsObjectDetailTableItem: SettingsObjectDetailTableItem;
|
||||
@@ -66,7 +66,7 @@ export const SettingsObjectFieldItemTableRow = ({
|
||||
const { fieldMetadataItem, identifierType, objectMetadataItem } =
|
||||
settingsObjectDetailTableItem;
|
||||
|
||||
const readonly = isObjectMetadataReadOnly({
|
||||
const readonly = isObjectMetadataSettingsReadOnly({
|
||||
objectMetadataItem,
|
||||
});
|
||||
|
||||
|
||||
+2
-2
@@ -1,6 +1,5 @@
|
||||
import { useUpdateOneObjectMetadataItem } from '@/object-metadata/hooks/useUpdateOneObjectMetadataItem';
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { isObjectMetadataReadOnly } from '@/object-record/read-only/utils/isObjectMetadataReadOnly';
|
||||
import { SettingsDataModelObjectAboutForm } from '@/settings/data-model/objects/forms/components/SettingsDataModelObjectAboutForm';
|
||||
import {
|
||||
type SettingsDataModelObjectAboutFormValues,
|
||||
@@ -12,6 +11,7 @@ import { useSetRecoilState } from 'recoil';
|
||||
import { SettingsPath } from 'twenty-shared/types';
|
||||
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
|
||||
import { updatedObjectNamePluralState } from '~/pages/settings/data-model/states/updatedObjectNamePluralState';
|
||||
import { isObjectMetadataSettingsReadOnly } from '@/object-record/read-only/utils/isObjectMetadataSettingsReadOnly';
|
||||
|
||||
type SettingsUpdateDataModelObjectAboutFormProps = {
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
@@ -20,7 +20,7 @@ type SettingsUpdateDataModelObjectAboutFormProps = {
|
||||
export const SettingsUpdateDataModelObjectAboutForm = ({
|
||||
objectMetadataItem,
|
||||
}: SettingsUpdateDataModelObjectAboutFormProps) => {
|
||||
const readonly = isObjectMetadataReadOnly({ objectMetadataItem });
|
||||
const readonly = isObjectMetadataSettingsReadOnly({ objectMetadataItem });
|
||||
const navigate = useNavigateSettings();
|
||||
const setUpdatedObjectNamePlural = useSetRecoilState(
|
||||
updatedObjectNamePluralState,
|
||||
|
||||
+2
-2
@@ -9,7 +9,7 @@ import { H2Title, IconPlus } from 'twenty-ui/display';
|
||||
import { Button } from 'twenty-ui/input';
|
||||
import { Section } from 'twenty-ui/layout';
|
||||
import { UndecoratedLink } from 'twenty-ui/navigation';
|
||||
import { isObjectMetadataReadOnly } from '@/object-record/read-only/utils/isObjectMetadataReadOnly';
|
||||
import { isObjectMetadataSettingsReadOnly } from '@/object-record/read-only/utils/isObjectMetadataSettingsReadOnly';
|
||||
|
||||
const StyledDiv = styled.div`
|
||||
display: flex;
|
||||
@@ -22,7 +22,7 @@ type ObjectFieldsProps = {
|
||||
};
|
||||
|
||||
export const ObjectFields = ({ objectMetadataItem }: ObjectFieldsProps) => {
|
||||
const readonly = isObjectMetadataReadOnly({
|
||||
const readonly = isObjectMetadataSettingsReadOnly({
|
||||
objectMetadataItem,
|
||||
});
|
||||
|
||||
|
||||
+2
-2
@@ -1,7 +1,6 @@
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
|
||||
import { useUpdateOneObjectMetadataItem } from '@/object-metadata/hooks/useUpdateOneObjectMetadataItem';
|
||||
import { isObjectMetadataReadOnly } from '@/object-record/read-only/utils/isObjectMetadataReadOnly';
|
||||
import { SettingsUpdateDataModelObjectAboutForm } from '@/settings/data-model/object-details/components/SettingsUpdateDataModelObjectAboutForm';
|
||||
import { SettingsDataModelObjectSettingsFormCard } from '@/settings/data-model/objects/forms/components/SettingsDataModelObjectSettingsFormCard';
|
||||
import styled from '@emotion/styled';
|
||||
@@ -11,6 +10,7 @@ import { H2Title, IconArchive } from 'twenty-ui/display';
|
||||
import { Button } from 'twenty-ui/input';
|
||||
import { Section } from 'twenty-ui/layout';
|
||||
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
|
||||
import { isObjectMetadataSettingsReadOnly } from '@/object-record/read-only/utils/isObjectMetadataSettingsReadOnly';
|
||||
|
||||
type ObjectSettingsProps = {
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
@@ -28,7 +28,7 @@ const StyledFormSection = styled(Section)`
|
||||
|
||||
export const ObjectSettings = ({ objectMetadataItem }: ObjectSettingsProps) => {
|
||||
const { t } = useLingui();
|
||||
const readonly = isObjectMetadataReadOnly({ objectMetadataItem });
|
||||
const readonly = isObjectMetadataSettingsReadOnly({ objectMetadataItem });
|
||||
const navigate = useNavigateSettings();
|
||||
const { updateOneObjectMetadataItem } = useUpdateOneObjectMetadataItem();
|
||||
|
||||
|
||||
+2
-2
@@ -2,7 +2,6 @@ import { useUpdateOneObjectMetadataItem } from '@/object-metadata/hooks/useUpdat
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { getActiveFieldMetadataItems } from '@/object-metadata/utils/getActiveFieldMetadataItems';
|
||||
import { objectMetadataItemSchema } from '@/object-metadata/validation-schemas/objectMetadataItemSchema';
|
||||
import { isObjectMetadataReadOnly } from '@/object-record/read-only/utils/isObjectMetadataReadOnly';
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
import styled from '@emotion/styled';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
@@ -14,6 +13,7 @@ import { isLabelIdentifierFieldMetadataTypes } from 'twenty-shared/utils';
|
||||
import { IconCircleOff, IconPlus, useIcons } from 'twenty-ui/display';
|
||||
import { type SelectOption } from 'twenty-ui/input';
|
||||
import { type z } from 'zod';
|
||||
import { isObjectMetadataSettingsReadOnly } from '@/object-record/read-only/utils/isObjectMetadataSettingsReadOnly';
|
||||
|
||||
export const settingsDataModelObjectIdentifiersFormSchema =
|
||||
objectMetadataItemSchema.pick({
|
||||
@@ -42,7 +42,7 @@ const StyledContainer = styled.div`
|
||||
export const SettingsDataModelObjectIdentifiersForm = ({
|
||||
objectMetadataItem,
|
||||
}: SettingsDataModelObjectIdentifiersFormProps) => {
|
||||
const readonly = isObjectMetadataReadOnly({ objectMetadataItem });
|
||||
const readonly = isObjectMetadataSettingsReadOnly({ objectMetadataItem });
|
||||
const formConfig = useForm<SettingsDataModelObjectIdentifiersFormValues>({
|
||||
mode: 'onTouched',
|
||||
resolver: zodResolver(settingsDataModelObjectIdentifiersFormSchema),
|
||||
|
||||
@@ -14,7 +14,6 @@ import styled from '@emotion/styled';
|
||||
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||
import { AppPath, SettingsPath } from 'twenty-shared/types';
|
||||
|
||||
import { isObjectMetadataReadOnly } from '@/object-record/read-only/utils/isObjectMetadataReadOnly';
|
||||
import { SettingsItemTypeTag } from '@/settings/components/SettingsItemTypeTag';
|
||||
import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
@@ -35,6 +34,7 @@ import { FeatureFlagKey } from '~/generated/graphql';
|
||||
import { useNavigateApp } from '~/hooks/useNavigateApp';
|
||||
import { SETTINGS_OBJECT_DETAIL_TABS } from '~/pages/settings/data-model/constants/SettingsObjectDetailTabs';
|
||||
import { updatedObjectNamePluralState } from '~/pages/settings/data-model/states/updatedObjectNamePluralState';
|
||||
import { isObjectMetadataSettingsReadOnly } from '@/object-record/read-only/utils/isObjectMetadataSettingsReadOnly';
|
||||
|
||||
const StyledContentContainer = styled.div`
|
||||
flex: 1;
|
||||
@@ -67,7 +67,7 @@ export const SettingsObjectDetailPage = () => {
|
||||
findActiveObjectMetadataItemByNamePlural(objectNamePlural) ??
|
||||
findActiveObjectMetadataItemByNamePlural(updatedObjectNamePlural);
|
||||
|
||||
const readonly = isObjectMetadataReadOnly({ objectMetadataItem });
|
||||
const readonly = isObjectMetadataSettingsReadOnly({ objectMetadataItem });
|
||||
|
||||
const activeTabId = useRecoilComponentValue(
|
||||
activeTabIdComponentState,
|
||||
|
||||
@@ -12,7 +12,6 @@ import { useUpdateOneFieldMetadataItem } from '@/object-metadata/hooks/useUpdate
|
||||
import { CoreObjectNamePlural } from '@/object-metadata/types/CoreObjectNamePlural';
|
||||
import { formatFieldMetadataItemInput } from '@/object-metadata/utils/formatFieldMetadataItemInput';
|
||||
import { isLabelIdentifierField } from '@/object-metadata/utils/isLabelIdentifierField';
|
||||
import { isObjectMetadataReadOnly } from '@/object-record/read-only/utils/isObjectMetadataReadOnly';
|
||||
import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons';
|
||||
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
||||
import { FIELD_NAME_MAXIMUM_LENGTH } from '@/settings/data-model/constants/FieldNameMaximumLength';
|
||||
@@ -34,6 +33,7 @@ import { Section } from 'twenty-ui/layout';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
import { useNavigateApp } from '~/hooks/useNavigateApp';
|
||||
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
|
||||
import { isObjectMetadataSettingsReadOnly } from '@/object-record/read-only/utils/isObjectMetadataSettingsReadOnly';
|
||||
|
||||
//TODO: fix this type
|
||||
export type SettingsDataModelFieldEditFormValues = z.infer<
|
||||
@@ -64,7 +64,7 @@ export const SettingsObjectFieldEdit = () => {
|
||||
const objectMetadataItem =
|
||||
findObjectMetadataItemByNamePlural(objectNamePlural);
|
||||
|
||||
const readonly = isObjectMetadataReadOnly({ objectMetadataItem });
|
||||
const readonly = isObjectMetadataSettingsReadOnly({ objectMetadataItem });
|
||||
|
||||
const { deactivateMetadataField, activateMetadataField } =
|
||||
useFieldMetadataItem();
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { type SyncableEntityOptions } from '@/application/types/syncable-entity-options.type';
|
||||
import { type SyncableEntityOptions } from '@/application/syncable-entity-options.type';
|
||||
|
||||
type ApplicationVariable = SyncableEntityOptions & {
|
||||
value?: string;
|
||||
@@ -0,0 +1,23 @@
|
||||
export abstract class BaseObjectMetadata {
|
||||
id: string;
|
||||
|
||||
name: string;
|
||||
|
||||
createdBy: string;
|
||||
|
||||
position: number;
|
||||
|
||||
searchVector: string | null;
|
||||
|
||||
//taskTargets
|
||||
//noteTargets
|
||||
//attachments
|
||||
//favorites
|
||||
//timelineActivities
|
||||
|
||||
createdAt: string;
|
||||
|
||||
updatedAt: string;
|
||||
|
||||
deletedAt: string | null;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { FieldMetadataType } from 'twenty-shared/types';
|
||||
@@ -0,0 +1,31 @@
|
||||
import { type SyncableEntityOptions } from '@/application/syncable-entity-options.type';
|
||||
|
||||
import {
|
||||
type FieldMetadataType,
|
||||
type FieldMetadataSettings,
|
||||
type FieldMetadataOptions,
|
||||
type FieldMetadataDefaultValue,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
type FieldOptions<
|
||||
T extends FieldMetadataType = Exclude<
|
||||
FieldMetadataType,
|
||||
// Use @WorkspaceRelation or @WorkspaceDynamicRelation for relation fields
|
||||
FieldMetadataType.RELATION
|
||||
>,
|
||||
> = SyncableEntityOptions & {
|
||||
type: T;
|
||||
label: string;
|
||||
description?: string;
|
||||
icon?: string;
|
||||
defaultValue?: FieldMetadataDefaultValue<T>;
|
||||
options?: FieldMetadataOptions<T>;
|
||||
settings?: FieldMetadataSettings<T>;
|
||||
isNullable?: boolean;
|
||||
};
|
||||
|
||||
export const FieldMetadata = <T extends FieldMetadataType>(
|
||||
_: FieldOptions<T>,
|
||||
): PropertyDecorator => {
|
||||
return () => {};
|
||||
};
|
||||
@@ -7,7 +7,10 @@
|
||||
* |___/
|
||||
*/
|
||||
|
||||
export { ObjectMetadata } from './decorators/object-metadata.decorator';
|
||||
export type { ApplicationConfig } from './types/application-config';
|
||||
export type { ServerlessFunctionConfig } from './types/serverless-function-config';
|
||||
export type { SyncableEntityOptions } from './types/syncable-entity-options.type';
|
||||
export type { ApplicationConfig } from './application-config';
|
||||
export { BaseObjectMetadata } from './base-object-metadata';
|
||||
export { FieldMetadataType } from './field-metadata-type';
|
||||
export { FieldMetadata } from './field-metadata.decorator';
|
||||
export { ObjectMetadata } from './object-metadata.decorator';
|
||||
export type { ServerlessFunctionConfig } from './serverless-function-config';
|
||||
export type { SyncableEntityOptions } from './syncable-entity-options.type';
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { type SyncableEntityOptions } from '@/application/types/syncable-entity-options.type';
|
||||
import { type SyncableEntityOptions } from '@/application/syncable-entity-options.type';
|
||||
|
||||
type ObjectMetadataOptions = SyncableEntityOptions & {
|
||||
nameSingular: string;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { type SyncableEntityOptions } from '@/application/types/syncable-entity-options.type';
|
||||
import { type SyncableEntityOptions } from '@/application/syncable-entity-options.type';
|
||||
|
||||
type RouteTrigger = {
|
||||
type: 'route';
|
||||
@@ -8,8 +8,12 @@
|
||||
"moduleResolution": "node",
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"strict": true,
|
||||
"importHelpers": true,
|
||||
"allowUnreachableCode": false,
|
||||
"strictNullChecks": true,
|
||||
"alwaysStrict": true,
|
||||
"noImplicitAny": true,
|
||||
"strictBindCallApply": false,
|
||||
"target": "es2018",
|
||||
"module": "esnext",
|
||||
"lib": ["es2020", "dom"],
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
import { FieldActorSource } from 'src/engine/metadata-modules/field-metadata/composite-types/actor.composite-type';
|
||||
|
||||
+1
-1
@@ -8,13 +8,13 @@ import {
|
||||
FieldMetadataType,
|
||||
ObjectRecord,
|
||||
RelationType,
|
||||
FieldMetadataRelationSettings,
|
||||
} from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { FindOptionsRelations, In, ObjectLiteral } from 'typeorm';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
import { WorkspaceAuthContext } from 'src/engine/api/common/interfaces/workspace-auth-context.interface';
|
||||
import { FieldMetadataRelationSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
|
||||
import { CommonBaseQueryRunnerService } from 'src/engine/api/common/common-query-runners/common-base-query-runner.service';
|
||||
import {
|
||||
|
||||
+4
-4
@@ -14,14 +14,14 @@ import {
|
||||
type GraphQLType,
|
||||
} from 'graphql';
|
||||
import GraphQLJSON from 'graphql-type-json';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { FieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
|
||||
import {
|
||||
FieldMetadataType,
|
||||
type FieldMetadataSettings,
|
||||
NumberDataType,
|
||||
} from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { FieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
|
||||
|
||||
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
|
||||
import { OrderByDirectionType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/enum';
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
import { type GraphQLInputObjectType } from 'graphql';
|
||||
|
||||
import { NumberDataType } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
import { NumberDataType } from 'twenty-shared/types';
|
||||
|
||||
import {
|
||||
BigIntFilterType,
|
||||
|
||||
+1
-2
@@ -1,7 +1,6 @@
|
||||
import { GraphQLInt, GraphQLFloat, type GraphQLScalarType } from 'graphql';
|
||||
import { GraphQLBigInt } from 'graphql-scalars';
|
||||
|
||||
import { NumberDataType } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
import { NumberDataType } from 'twenty-shared/types';
|
||||
|
||||
export const getNumberScalarType = (
|
||||
dataType: NumberDataType,
|
||||
|
||||
+1
@@ -13,6 +13,7 @@ export class ApplicationExceptionFilter implements ExceptionFilter {
|
||||
catch(exception: ApplicationException) {
|
||||
switch (exception.code) {
|
||||
case ApplicationExceptionCode.OBJECT_NOT_FOUND:
|
||||
case ApplicationExceptionCode.FIELD_NOT_FOUND:
|
||||
case ApplicationExceptionCode.ENTITY_NOT_FOUND:
|
||||
case ApplicationExceptionCode.APPLICATION_NOT_FOUND:
|
||||
case ApplicationExceptionCode.SERVERLESS_FUNCTION_NOT_FOUND:
|
||||
|
||||
+147
-2
@@ -13,12 +13,12 @@ import {
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { ApplicationInput } from 'src/engine/core-modules/application/dtos/application.input';
|
||||
import {
|
||||
FieldManifest,
|
||||
ObjectManifest,
|
||||
ServerlessFunctionManifest,
|
||||
ServerlessFunctionTriggerManifest,
|
||||
} from 'src/engine/core-modules/application/types/application.types';
|
||||
import { ApplicationVariableEntityService } from 'src/engine/core-modules/applicationVariable/application-variable.service';
|
||||
import { Sources } from 'src/engine/core-modules/file-storage/types/source.type';
|
||||
import { CronTriggerV2Service } from 'src/engine/metadata-modules/cron-trigger/services/cron-trigger-v2.service';
|
||||
import { FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type';
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
@@ -35,6 +35,11 @@ import { ServerlessFunctionLayerService } from 'src/engine/metadata-modules/serv
|
||||
import { ServerlessFunctionV2Service } from 'src/engine/metadata-modules/serverless-function/services/serverless-function-v2.service';
|
||||
import { FlatServerlessFunction } from 'src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type';
|
||||
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-validate-build-and-run-service';
|
||||
import { Sources } from 'src/engine/core-modules/file-storage/types/source.type';
|
||||
import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { FieldMetadataServiceV2 } from 'src/engine/metadata-modules/field-metadata/services/field-metadata.service-v2';
|
||||
import { CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
||||
import { computeMetadataNameFromLabel } from 'src/engine/metadata-modules/utils/validate-name-and-label-are-sync-or-throw.util';
|
||||
|
||||
@Injectable()
|
||||
export class ApplicationSyncService {
|
||||
@@ -45,6 +50,7 @@ export class ApplicationSyncService {
|
||||
private readonly applicationVariableService: ApplicationVariableEntityService,
|
||||
private readonly serverlessFunctionLayerService: ServerlessFunctionLayerService,
|
||||
private readonly objectMetadataServiceV2: ObjectMetadataServiceV2,
|
||||
private readonly fieldMetadataServiceV2: FieldMetadataServiceV2,
|
||||
private readonly serverlessFunctionV2Service: ServerlessFunctionV2Service,
|
||||
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly dataSourceService: DataSourceService,
|
||||
@@ -155,6 +161,131 @@ export class ApplicationSyncService {
|
||||
return application;
|
||||
}
|
||||
|
||||
private async syncFields({
|
||||
objectId,
|
||||
fieldsToSync,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
}: {
|
||||
objectId: string;
|
||||
workspaceId: string;
|
||||
applicationId: string;
|
||||
fieldsToSync?: FieldManifest[];
|
||||
}) {
|
||||
if (!isDefined(fieldsToSync)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { flatFieldMetadataMaps: existingFlatFieldMetadataMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatFieldMetadataMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const existingFields = Object.values(
|
||||
existingFlatFieldMetadataMaps.byId,
|
||||
).filter(
|
||||
(field) => isDefined(field) && field.objectMetadataId === objectId,
|
||||
) as FlatFieldMetadata[];
|
||||
|
||||
const fieldsToSyncUniversalIds = fieldsToSync.map(
|
||||
(field) => field.universalIdentifier,
|
||||
);
|
||||
|
||||
const existingFieldsStandardIds = existingFields.map(
|
||||
(field) => field.universalIdentifier,
|
||||
);
|
||||
|
||||
const fieldsToDelete = existingFields.filter(
|
||||
(field) =>
|
||||
isDefined(field.universalIdentifier) &&
|
||||
!fieldsToSyncUniversalIds.includes(field.universalIdentifier) &&
|
||||
field.isCustom === true,
|
||||
);
|
||||
|
||||
const fieldsToUpdate = existingFields.filter(
|
||||
(field) =>
|
||||
isDefined(field.universalIdentifier) &&
|
||||
fieldsToSyncUniversalIds.includes(field.universalIdentifier),
|
||||
);
|
||||
|
||||
const fieldsToCreate = fieldsToSync.filter(
|
||||
(fieldToSync) =>
|
||||
!existingFieldsStandardIds.includes(fieldToSync.universalIdentifier),
|
||||
);
|
||||
|
||||
for (const fieldToDelete of fieldsToDelete) {
|
||||
await this.fieldMetadataServiceV2.updateOne({
|
||||
updateFieldInput: {
|
||||
id: fieldToDelete.id,
|
||||
isActive: false,
|
||||
},
|
||||
workspaceId,
|
||||
});
|
||||
await this.fieldMetadataServiceV2.deleteOneField({
|
||||
deleteOneFieldInput: { id: fieldToDelete.id },
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
|
||||
for (const fieldToUpdate of fieldsToUpdate) {
|
||||
const fieldToSync = fieldsToSync.find(
|
||||
(field) =>
|
||||
field.universalIdentifier === fieldToUpdate.universalIdentifier,
|
||||
);
|
||||
|
||||
if (!fieldToSync) {
|
||||
throw new ApplicationException(
|
||||
`Failed to find field to sync with universalIdentifier ${fieldToUpdate.universalIdentifier}`,
|
||||
ApplicationExceptionCode.FIELD_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const updateFieldInput = {
|
||||
id: fieldToUpdate.id,
|
||||
label: fieldToSync.label,
|
||||
description: fieldToSync.description ?? undefined,
|
||||
icon: fieldToSync.icon ?? undefined,
|
||||
defaultValue: fieldToSync.defaultValue ?? undefined,
|
||||
options: fieldToSync.options ?? undefined,
|
||||
settings: fieldToSync.settings ?? undefined,
|
||||
isNullable: fieldToSync.isNullable ?? true,
|
||||
};
|
||||
|
||||
await this.fieldMetadataServiceV2.updateOne({
|
||||
updateFieldInput,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
|
||||
for (const fieldToCreate of fieldsToCreate) {
|
||||
const createFieldInput: CreateFieldInput = {
|
||||
name: computeMetadataNameFromLabel(fieldToCreate.label),
|
||||
type: fieldToCreate.type,
|
||||
label: fieldToCreate.label,
|
||||
description: fieldToCreate.description ?? undefined,
|
||||
icon: fieldToCreate.icon ?? undefined,
|
||||
defaultValue: fieldToCreate.defaultValue ?? undefined,
|
||||
options: fieldToCreate.options ?? undefined,
|
||||
settings: fieldToCreate.settings ?? undefined,
|
||||
isNullable: fieldToCreate.isNullable ?? true,
|
||||
objectMetadataId: objectId,
|
||||
universalIdentifier: fieldToCreate.universalIdentifier,
|
||||
standardId: fieldToCreate.universalIdentifier,
|
||||
applicationId,
|
||||
isCustom: true,
|
||||
workspaceId,
|
||||
};
|
||||
|
||||
await this.fieldMetadataServiceV2.createOne({
|
||||
createFieldInput,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async syncObjects({
|
||||
objectsToSync,
|
||||
workspaceId,
|
||||
@@ -243,6 +374,13 @@ export class ApplicationSyncService {
|
||||
updateObjectInput,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
await this.syncFields({
|
||||
fieldsToSync: objectToSync.fields,
|
||||
objectId: objectToUpdate.id,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
});
|
||||
}
|
||||
|
||||
const dataSourceMetadata =
|
||||
@@ -264,10 +402,17 @@ export class ApplicationSyncService {
|
||||
applicationId,
|
||||
};
|
||||
|
||||
await this.objectMetadataServiceV2.createOne({
|
||||
const createdObject = await this.objectMetadataServiceV2.createOne({
|
||||
createObjectInput,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
await this.syncFields({
|
||||
fieldsToSync: objectToCreate.fields,
|
||||
objectId: createdObject.id,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ export class ApplicationException extends CustomException<ApplicationExceptionCo
|
||||
|
||||
export enum ApplicationExceptionCode {
|
||||
OBJECT_NOT_FOUND = 'OBJECT_NOT_FOUND',
|
||||
FIELD_NOT_FOUND = 'FIELD_NOT_FOUND',
|
||||
SERVERLESS_FUNCTION_NOT_FOUND = 'SERVERLESS_FUNCTION_NOT_FOUND',
|
||||
ENTITY_NOT_FOUND = 'ENTITY_NOT_FOUND',
|
||||
APPLICATION_NOT_FOUND = 'APPLICATION_NOT_FOUND',
|
||||
|
||||
@@ -17,12 +17,14 @@ import { RouteTriggerModule } from 'src/engine/metadata-modules/route-trigger/ro
|
||||
import { ServerlessFunctionLayerModule } from 'src/engine/metadata-modules/serverless-function-layer/serverless-function-layer.module';
|
||||
import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless-function/serverless-function.module';
|
||||
import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-v2.module';
|
||||
import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/field-metadata.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([ApplicationEntity, AgentEntity, WorkspaceEntity]),
|
||||
WorkspaceManyOrAllFlatEntityMapsCacheModule,
|
||||
ObjectMetadataModule,
|
||||
FieldMetadataModule,
|
||||
DataSourceModule,
|
||||
ApplicationVariableEntityModule,
|
||||
ServerlessFunctionLayerModule,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { type FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { type HTTPMethod } from 'src/engine/metadata-modules/route-trigger/route-trigger.entity';
|
||||
|
||||
export type PackageJson = {
|
||||
@@ -66,6 +68,22 @@ export type ServerlessFunctionTriggerManifest = (
|
||||
universalIdentifier: string;
|
||||
};
|
||||
|
||||
export type FieldManifest = {
|
||||
universalIdentifier: string;
|
||||
type: FieldMetadataType;
|
||||
label: string;
|
||||
description?: string;
|
||||
icon?: string;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
defaultValue?: any;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
options?: any;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
settings?: any;
|
||||
isNullable?: boolean;
|
||||
isFieldUiReadOnly?: boolean;
|
||||
};
|
||||
|
||||
export type ObjectManifest = {
|
||||
universalIdentifier: string;
|
||||
nameSingular: string;
|
||||
@@ -74,6 +92,7 @@ export type ObjectManifest = {
|
||||
labelPlural: string;
|
||||
description?: string;
|
||||
icon?: string;
|
||||
fields?: FieldManifest[];
|
||||
};
|
||||
|
||||
interface AgentResponseFormat {
|
||||
|
||||
+1
-3
@@ -1,8 +1,6 @@
|
||||
import { faker } from '@faker-js/faker';
|
||||
import { type EachTestingContext } from 'twenty-shared/testing';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { NumberDataType } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
import { FieldMetadataType, NumberDataType } from 'twenty-shared/types';
|
||||
|
||||
import { objectMetadataItemMock } from 'src/engine/api/__mocks__/object-metadata-item.mock';
|
||||
import { computeSchemaComponents } from 'src/engine/core-modules/open-api/utils/components.utils';
|
||||
|
||||
+2
-4
@@ -1,14 +1,12 @@
|
||||
import {
|
||||
FieldMetadataType,
|
||||
type RestrictedFieldsPermissions,
|
||||
type FieldMetadataSettings,
|
||||
NumberDataType,
|
||||
} from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { z } from 'zod';
|
||||
|
||||
import {
|
||||
type FieldMetadataSettings,
|
||||
NumberDataType,
|
||||
} from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
import { type FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
|
||||
+10
-1
@@ -1,4 +1,4 @@
|
||||
import { Field, InputType, OmitType } from '@nestjs/graphql';
|
||||
import { Field, HideField, InputType, OmitType } from '@nestjs/graphql';
|
||||
|
||||
import { Type } from 'class-transformer';
|
||||
import { IsOptional, IsUUID, ValidateNested } from 'class-validator';
|
||||
@@ -18,6 +18,15 @@ export class CreateFieldInput extends OmitType(
|
||||
@Field(() => UUIDScalarType)
|
||||
objectMetadataId: string;
|
||||
|
||||
@HideField()
|
||||
universalIdentifier?: string;
|
||||
|
||||
@HideField()
|
||||
standardId?: string;
|
||||
|
||||
@HideField()
|
||||
applicationId?: string;
|
||||
|
||||
@Field(() => Boolean, { nullable: true })
|
||||
@IsOptional()
|
||||
isRemoteCreation?: boolean;
|
||||
|
||||
+5
-3
@@ -23,11 +23,13 @@ import {
|
||||
IsUUID,
|
||||
} from 'class-validator';
|
||||
import { GraphQLJSON } from 'graphql-type-json';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import {
|
||||
FieldMetadataType,
|
||||
FieldMetadataSettings,
|
||||
FieldMetadataOptions,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { FieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
|
||||
import { FieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface';
|
||||
import { FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { IsValidMetadataName } from 'src/engine/decorators/metadata/is-valid-metadata-name.decorator';
|
||||
|
||||
+5
-3
@@ -1,4 +1,8 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import {
|
||||
FieldMetadataType,
|
||||
FieldMetadataSettings,
|
||||
FieldMetadataOptions,
|
||||
} from 'twenty-shared/types';
|
||||
import {
|
||||
Check,
|
||||
Column,
|
||||
@@ -16,8 +20,6 @@ import {
|
||||
} from 'typeorm';
|
||||
|
||||
import { FieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
|
||||
import { FieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface';
|
||||
import { FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
import { SyncableEntity } from 'src/engine/workspace-manager/workspace-sync/interfaces/syncable-entity.interface';
|
||||
|
||||
import { type FieldStandardOverridesDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-standard-overrides.dto';
|
||||
|
||||
+4
-3
@@ -1,6 +1,7 @@
|
||||
import { type FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { type FieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface';
|
||||
import {
|
||||
type FieldMetadataType,
|
||||
type FieldMetadataOptions,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
export interface CompositeProperty<
|
||||
Type extends FieldMetadataType = FieldMetadataType,
|
||||
|
||||
+1
-2
@@ -6,12 +6,11 @@ import { isNonEmptyString } from '@sniptt/guards';
|
||||
import {
|
||||
type EnumFieldMetadataType,
|
||||
FieldMetadataType,
|
||||
type FieldMetadataOptions,
|
||||
} from 'twenty-shared/types';
|
||||
import { assertUnreachable, isDefined } from 'twenty-shared/utils';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { type FieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface';
|
||||
|
||||
import { type CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
||||
import {
|
||||
type FieldMetadataComplexOption,
|
||||
|
||||
+6
-4
@@ -2,12 +2,15 @@ import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { IsEnum, IsString, IsUUID } from 'class-validator';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
type FieldMetadataSettings,
|
||||
FieldMetadataType,
|
||||
RelationOnDeleteAction,
|
||||
} from 'twenty-shared/types';
|
||||
import { type Repository } from 'typeorm';
|
||||
import { v4 } from 'uuid';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
import { type CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
||||
@@ -20,7 +23,6 @@ import {
|
||||
import { computeMorphOrRelationFieldJoinColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-morph-or-relation-field-join-column-name.util';
|
||||
import { prepareCustomFieldMetadataForCreation } from 'src/engine/metadata-modules/field-metadata/utils/prepare-field-metadata-for-creation.util';
|
||||
import { validateRelationCreationPayloadOrThrow } from 'src/engine/metadata-modules/field-metadata/utils/validate-relation-creation-payload-or-throw.util';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
|
||||
import { type ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
|
||||
import { type ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
|
||||
import { validateFieldNameAvailabilityOrThrow } from 'src/engine/metadata-modules/utils/validate-field-name-availability.utils';
|
||||
|
||||
+1
-2
@@ -17,11 +17,10 @@ import {
|
||||
ALLOWED_ADDRESS_SUBFIELDS,
|
||||
type AllowedAddressSubField,
|
||||
FieldMetadataType,
|
||||
type FieldMetadataSettings,
|
||||
} from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
|
||||
import { type CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
||||
import { type UpdateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/update-field.input';
|
||||
import { type FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
|
||||
+5
-3
@@ -57,9 +57,11 @@ export class FieldMetadataServiceV2 {
|
||||
public async deleteOneField({
|
||||
deleteOneFieldInput,
|
||||
workspaceId,
|
||||
isSystemBuild = false,
|
||||
}: {
|
||||
deleteOneFieldInput: DeleteOneFieldInput;
|
||||
workspaceId: string;
|
||||
isSystemBuild?: boolean;
|
||||
}): Promise<FieldMetadataDTO> {
|
||||
const {
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
@@ -94,7 +96,7 @@ export class FieldMetadataServiceV2 {
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
},
|
||||
buildOptions: {
|
||||
isSystemBuild: false,
|
||||
isSystemBuild,
|
||||
inferDeletionFromMissingEntities: {
|
||||
fieldMetadata: true,
|
||||
index: true,
|
||||
@@ -134,7 +136,7 @@ export class FieldMetadataServiceV2 {
|
||||
updateFieldInput,
|
||||
workspaceId,
|
||||
}: {
|
||||
updateFieldInput: UpdateFieldInput;
|
||||
updateFieldInput: Omit<UpdateFieldInput, 'workspaceId'>;
|
||||
workspaceId: string;
|
||||
}): Promise<FieldMetadataEntity> {
|
||||
const {
|
||||
@@ -164,7 +166,7 @@ export class FieldMetadataServiceV2 {
|
||||
flatFieldMetadataMaps: existingFlatFieldMetadataMaps,
|
||||
flatIndexMaps: existingFlatIndexMaps,
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
updateFieldInput,
|
||||
updateFieldInput: { ...updateFieldInput, workspaceId },
|
||||
flatViewFilterMaps: existingFlatViewFilterMaps,
|
||||
flatViewGroupMaps: existingFlatViewGroupMaps,
|
||||
flatViewMaps: existingFlatViewMaps,
|
||||
|
||||
+6
-8
@@ -3,6 +3,12 @@ import {
|
||||
type FieldMetadataMultiItemSettings,
|
||||
type FieldMetadataType,
|
||||
type NullablePartial,
|
||||
type AllFieldMetadataSettings,
|
||||
type FieldMetadataDateSettings,
|
||||
type FieldMetadataDateTimeSettings,
|
||||
type FieldMetadataNumberSettings,
|
||||
type FieldMetadataRelationSettings,
|
||||
type FieldMetadataTextSettings,
|
||||
} from 'twenty-shared/types';
|
||||
import { type Relation as TypeOrmRelation } from 'typeorm';
|
||||
|
||||
@@ -10,14 +16,6 @@ import {
|
||||
type FieldMetadataDefaultValueForAnyType,
|
||||
type FieldMetadataDefaultValueForType,
|
||||
} from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
|
||||
import {
|
||||
type AllFieldMetadataSettings,
|
||||
type FieldMetadataDateSettings,
|
||||
type FieldMetadataDateTimeSettings,
|
||||
type FieldMetadataNumberSettings,
|
||||
type FieldMetadataRelationSettings,
|
||||
type FieldMetadataTextSettings,
|
||||
} from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
|
||||
import {
|
||||
type FieldMetadataComplexOption,
|
||||
|
||||
+4
-3
@@ -1,8 +1,9 @@
|
||||
import { Test, type TestingModule } from '@nestjs/testing';
|
||||
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { type FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
import {
|
||||
type FieldMetadataSettings,
|
||||
FieldMetadataType,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { FieldMetadataException } from 'src/engine/metadata-modules/field-metadata/field-metadata.exception';
|
||||
import { FieldMetadataEnumValidationService } from 'src/engine/metadata-modules/field-metadata/services/field-metadata-enum-validation.service';
|
||||
|
||||
+4
-3
@@ -1,8 +1,9 @@
|
||||
import { plainToInstance } from 'class-transformer';
|
||||
import { validateSync } from 'class-validator';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { type FieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface';
|
||||
import {
|
||||
FieldMetadataType,
|
||||
type FieldMetadataOptions,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import {
|
||||
FieldMetadataComplexOption,
|
||||
|
||||
+4
-3
@@ -2,11 +2,12 @@ import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { type ValidationArguments, ValidatorConstraint } from 'class-validator';
|
||||
import { type FieldMetadataType } from 'twenty-shared/types';
|
||||
import {
|
||||
type FieldMetadataType,
|
||||
type FieldMetadataOptions,
|
||||
} from 'twenty-shared/types';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { type FieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface';
|
||||
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { validateOptionsForType } from 'src/engine/metadata-modules/field-metadata/utils/validate-options-for-type.util';
|
||||
|
||||
|
||||
+5
-3
@@ -1,11 +1,13 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import {
|
||||
FieldMetadataType,
|
||||
DateDisplayFormat,
|
||||
RelationOnDeleteAction,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { DateDisplayFormat } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
|
||||
|
||||
export const ATTACHMENT_FLAT_FIELDS_MOCK = {
|
||||
name: getFlatFieldMetadataMock({
|
||||
|
||||
+5
-3
@@ -1,11 +1,13 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import {
|
||||
FieldMetadataType,
|
||||
DateDisplayFormat,
|
||||
RelationOnDeleteAction,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { DateDisplayFormat } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
|
||||
|
||||
export const COMPANY_FLAT_FIELDS_MOCK = {
|
||||
name: getFlatFieldMetadataMock({
|
||||
|
||||
+5
-3
@@ -1,11 +1,13 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import {
|
||||
FieldMetadataType,
|
||||
DateDisplayFormat,
|
||||
RelationOnDeleteAction,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { DateDisplayFormat } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
|
||||
|
||||
export const FAVORITE_FLAT_FIELDS_MOCK = {
|
||||
position: getFlatFieldMetadataMock({
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { FieldMetadataType, DateDisplayFormat } from 'twenty-shared/types';
|
||||
|
||||
import { DateDisplayFormat } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { FieldMetadataType, DateDisplayFormat } from 'twenty-shared/types';
|
||||
|
||||
import { DateDisplayFormat } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
|
||||
|
||||
+5
-3
@@ -1,11 +1,13 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import {
|
||||
FieldMetadataType,
|
||||
DateDisplayFormat,
|
||||
RelationOnDeleteAction,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { DateDisplayFormat } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
|
||||
|
||||
export const NOTETARGET_FLAT_FIELDS_MOCK = {
|
||||
id: getFlatFieldMetadataMock({
|
||||
|
||||
+5
-3
@@ -1,11 +1,13 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import {
|
||||
FieldMetadataType,
|
||||
DateDisplayFormat,
|
||||
RelationOnDeleteAction,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { DateDisplayFormat } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
|
||||
|
||||
export const OPPORTUNITY_FLAT_FIELDS_MOCK = {
|
||||
name: getFlatFieldMetadataMock({
|
||||
|
||||
+5
-3
@@ -1,11 +1,13 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import {
|
||||
FieldMetadataType,
|
||||
DateDisplayFormat,
|
||||
RelationOnDeleteAction,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { DateDisplayFormat } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
|
||||
|
||||
export const PERSON_FLAT_FIELDS_MOCK = {
|
||||
name: getFlatFieldMetadataMock({
|
||||
|
||||
+5
-3
@@ -1,11 +1,13 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import {
|
||||
FieldMetadataType,
|
||||
DateDisplayFormat,
|
||||
RelationOnDeleteAction,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { DateDisplayFormat } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
|
||||
|
||||
export const TASK_FLAT_FIELDS_MOCK = {
|
||||
position: getFlatFieldMetadataMock({
|
||||
|
||||
+5
-3
@@ -1,11 +1,13 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import {
|
||||
FieldMetadataType,
|
||||
DateDisplayFormat,
|
||||
RelationOnDeleteAction,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { DateDisplayFormat } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
|
||||
|
||||
export const TASKTARGET_FLAT_FIELDS_MOCK = {
|
||||
id: getFlatFieldMetadataMock({
|
||||
|
||||
+5
-3
@@ -1,11 +1,13 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import {
|
||||
FieldMetadataType,
|
||||
DateDisplayFormat,
|
||||
RelationOnDeleteAction,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { DateDisplayFormat } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
|
||||
|
||||
export const TIMELINEACTIVITY_FLAT_FIELDS_MOCK = {
|
||||
happensAt: getFlatFieldMetadataMock({
|
||||
|
||||
+4
-3
@@ -1,5 +1,8 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import {
|
||||
FieldMetadataType,
|
||||
type FieldMetadataOptions,
|
||||
} from 'twenty-shared/types';
|
||||
import {
|
||||
assertUnreachable,
|
||||
isDefined,
|
||||
@@ -7,8 +10,6 @@ import {
|
||||
} from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type FieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface';
|
||||
|
||||
import { type CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
||||
import { FieldMetadataExceptionCode } from 'src/engine/metadata-modules/field-metadata/field-metadata.exception';
|
||||
import { generateRatingOptions } from 'src/engine/metadata-modules/field-metadata/utils/generate-rating-optionts.util';
|
||||
|
||||
+5
-2
@@ -1,4 +1,8 @@
|
||||
import { FieldMetadataType, RelationType } from 'twenty-shared/types';
|
||||
import {
|
||||
FieldMetadataType,
|
||||
RelationType,
|
||||
RelationOnDeleteAction,
|
||||
} from 'twenty-shared/types';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
||||
@@ -9,7 +13,6 @@ import { generateIndexForFlatFieldMetadata } from 'src/engine/metadata-modules/f
|
||||
import { getDefaultFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/get-default-flat-field-metadata-from-create-field-input.util';
|
||||
import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
|
||||
import { computeMetadataNameFromLabel } from 'src/engine/metadata-modules/utils/validate-name-and-label-are-sync-or-throw.util';
|
||||
|
||||
type ComputeFieldMetadataRelationSettingsForRelationTypeArgs = {
|
||||
|
||||
+5
-4
@@ -43,19 +43,20 @@ export const getDefaultFlatFieldMetadata = ({
|
||||
objectMetadataId: createFieldInput.objectMetadataId,
|
||||
relationTargetFieldMetadataId: null,
|
||||
relationTargetObjectMetadataId: null,
|
||||
standardId: null,
|
||||
standardId: createFieldInput.standardId ?? null,
|
||||
standardOverrides: null,
|
||||
type: createFieldInput.type,
|
||||
universalIdentifier: fieldMetadataId,
|
||||
universalIdentifier:
|
||||
createFieldInput.universalIdentifier ?? fieldMetadataId,
|
||||
workspaceId,
|
||||
options: null,
|
||||
options: createFieldInput.options ?? null,
|
||||
defaultValue: defaultValue ?? generateDefaultValue(createFieldInput.type),
|
||||
settings: settings ?? null,
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
isUIReadOnly: createFieldInput.isUIReadOnly ?? false,
|
||||
morphId: null,
|
||||
applicationId: null,
|
||||
applicationId: createFieldInput.applicationId ?? null,
|
||||
viewFilterIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
|
||||
+1
-2
@@ -5,12 +5,11 @@ import {
|
||||
FieldMetadataType,
|
||||
type EnumFieldMetadataType,
|
||||
type NonNullableRequired,
|
||||
type FieldMetadataOptions,
|
||||
} from 'twenty-shared/types';
|
||||
import { assertUnreachable, isDefined } from 'twenty-shared/utils';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { type FieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface';
|
||||
|
||||
import {
|
||||
type FieldMetadataComplexOption,
|
||||
type FieldMetadataDefaultOption,
|
||||
|
||||
+4
-3
@@ -3,9 +3,10 @@ import { Field, HideField, InputType } from '@nestjs/graphql';
|
||||
import { BeforeCreateOne } from '@ptc-org/nestjs-query-graphql';
|
||||
import { IsBoolean, IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
||||
import GraphQLJSON from 'graphql-type-json';
|
||||
import { type FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
import {
|
||||
type FieldMetadataType,
|
||||
type FieldMetadataSettings,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { IsValidMetadataName } from 'src/engine/decorators/metadata/is-valid-metadata-name.decorator';
|
||||
import { BeforeCreateOneObject } from 'src/engine/metadata-modules/object-metadata/hooks/before-create-one-object.hook';
|
||||
|
||||
+1
-2
@@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
import { capitalize, isDefined } from 'twenty-shared/utils';
|
||||
import { type QueryRunner, Repository } from 'typeorm';
|
||||
import { v4 as uuidV4 } from 'uuid';
|
||||
@@ -18,7 +18,6 @@ import {
|
||||
} from 'src/engine/metadata-modules/object-metadata/object-metadata.exception';
|
||||
import { buildDescriptionForRelationFieldMetadataOnFromField } from 'src/engine/metadata-modules/object-metadata/utils/build-description-for-relation-field-on-from-field.util';
|
||||
import { buildDescriptionForRelationFieldMetadataOnToField } from 'src/engine/metadata-modules/object-metadata/utils/build-description-for-relation-field-on-to-field.util';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
|
||||
import { type FieldMetadataMap } from 'src/engine/metadata-modules/types/field-metadata-map';
|
||||
import { type ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
|
||||
import { type ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
|
||||
|
||||
+1
-2
@@ -1,4 +1,4 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
import { capitalize, isDefined } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
} from 'src/engine/metadata-modules/object-metadata/object-metadata.exception';
|
||||
import { buildDescriptionForRelationFieldMetadataOnFromField } from 'src/engine/metadata-modules/object-metadata/utils/build-description-for-relation-field-on-from-field.util';
|
||||
import { buildDescriptionForRelationFieldMetadataOnToField } from 'src/engine/metadata-modules/object-metadata/utils/build-description-for-relation-field-on-to-field.util';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
|
||||
import {
|
||||
CUSTOM_OBJECT_STANDARD_FIELD_IDS,
|
||||
STANDARD_OBJECT_FIELD_IDS,
|
||||
|
||||
+2
-1
@@ -1,5 +1,6 @@
|
||||
import { RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
|
||||
import { computeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
|
||||
import { type ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
|
||||
import {
|
||||
WorkspaceMigrationColumnActionType,
|
||||
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
export enum RelationOnDeleteAction {
|
||||
CASCADE = 'CASCADE',
|
||||
RESTRICT = 'RESTRICT',
|
||||
SET_NULL = 'SET_NULL',
|
||||
NO_ACTION = 'NO_ACTION',
|
||||
}
|
||||
+4
-3
@@ -1,12 +1,13 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { type FieldMetadataType } from 'twenty-shared/types';
|
||||
import {
|
||||
type FieldMetadataType,
|
||||
type FieldMetadataSettings,
|
||||
} from 'twenty-shared/types';
|
||||
import { In, Repository } from 'typeorm';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
|
||||
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 { buildMigrationsToCreateRemoteTableRelations } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table-relations/utils/build-migrations-to-create-remote-table-relations.util';
|
||||
|
||||
+2
-3
@@ -1,9 +1,8 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import {
|
||||
FieldMetadataType,
|
||||
type FieldMetadataSettings,
|
||||
NumberDataType,
|
||||
} from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
export const mapUdtNameToFieldType = (udtName: string): FieldMetadataType => {
|
||||
switch (udtName) {
|
||||
|
||||
+1
-1
@@ -4,9 +4,9 @@ import {
|
||||
Entity,
|
||||
PrimaryGeneratedColumn,
|
||||
} from 'typeorm';
|
||||
import { type RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
|
||||
import { type IndexType } from 'src/engine/metadata-modules/index-metadata/types/indexType.types';
|
||||
import { type RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
|
||||
|
||||
export enum WorkspaceMigrationColumnActionType {
|
||||
CREATE = 'CREATE',
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { DateDisplayFormat } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
import { FieldMetadataType, DateDisplayFormat } from 'twenty-shared/types';
|
||||
|
||||
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
|
||||
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
import { SEARCH_VECTOR_FIELD } from 'src/engine/metadata-modules/constants/search-vector-field.constants';
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { type ObjectType } from 'typeorm';
|
||||
import { type RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
|
||||
import { type RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
import { type RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { type WorkspaceDynamicRelationMetadataArgsFactory } from 'src/engine/twenty-orm/interfaces/workspace-dynamic-relation-metadata-args.interface';
|
||||
|
||||
|
||||
+5
-3
@@ -1,9 +1,11 @@
|
||||
import { type MessageDescriptor } from '@lingui/core';
|
||||
import { type FieldMetadataType } from 'twenty-shared/types';
|
||||
import {
|
||||
type FieldMetadataType,
|
||||
type FieldMetadataSettings,
|
||||
type FieldMetadataOptions,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { type FieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
|
||||
import { type FieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface';
|
||||
import { type FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
|
||||
import { generateDefaultValue } from 'src/engine/metadata-modules/field-metadata/utils/generate-default-value';
|
||||
import { computeMetadataNameFromLabel } from 'src/engine/metadata-modules/utils/validate-name-and-label-are-sync-or-throw.util';
|
||||
|
||||
+1
-1
@@ -2,8 +2,8 @@ import { type MessageDescriptor } from '@lingui/core';
|
||||
import { isDefined, isUUID } from 'class-validator';
|
||||
import { CustomError } from 'twenty-shared/utils';
|
||||
import { type ObjectType } from 'typeorm';
|
||||
import { type RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
|
||||
import { type RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
import { type RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { type ObjectType } from 'typeorm';
|
||||
import { type RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
|
||||
import { type RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
import { type RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { type Gate } from 'src/engine/twenty-orm/interfaces/gate.interface';
|
||||
|
||||
|
||||
+5
-3
@@ -1,8 +1,10 @@
|
||||
import { type FieldMetadataType } from 'twenty-shared/types';
|
||||
import {
|
||||
type FieldMetadataType,
|
||||
type FieldMetadataSettings,
|
||||
type FieldMetadataOptions,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { type FieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
|
||||
import { type FieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface';
|
||||
import { type FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
import { type Gate } from 'src/engine/twenty-orm/interfaces/gate.interface';
|
||||
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { type ObjectType } from 'typeorm';
|
||||
import { type RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
|
||||
import { type RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
import { type RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { type Gate } from 'src/engine/twenty-orm/interfaces/gate.interface';
|
||||
|
||||
|
||||
+4
-3
@@ -1,8 +1,9 @@
|
||||
import { RelationType } from 'twenty-shared/types';
|
||||
import {
|
||||
type FieldMetadataRelationSettings,
|
||||
RelationType,
|
||||
} from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type FieldMetadataRelationSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
|
||||
export const formatColumnNameForRelationField = (
|
||||
fieldName: string,
|
||||
fieldMetadataSettings: FieldMetadataRelationSettings,
|
||||
|
||||
+2
-1
@@ -1,5 +1,6 @@
|
||||
import { type FieldMetadataRelationSettings } from 'twenty-shared/types';
|
||||
|
||||
import { type CompositeType } from 'src/engine/metadata-modules/field-metadata/interfaces/composite-type.interface';
|
||||
import { type FieldMetadataRelationSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
import { extractGraphQLRelationFieldNames } from 'src/engine/api/graphql/workspace-schema-builder/utils/extract-graphql-relation-field-names.util';
|
||||
|
||||
+4
-4
@@ -1,10 +1,10 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FieldMetadataType,
|
||||
type FieldMetadataSettings,
|
||||
NumberDataType,
|
||||
} from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
} from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
import { type FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
|
||||
+1
-3
@@ -1,6 +1,4 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { NumberDataType } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
import { FieldMetadataType, NumberDataType } from 'twenty-shared/types';
|
||||
|
||||
import { type FieldMetadataDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto';
|
||||
import { type FieldMetadataSeed } from 'src/engine/workspace-manager/dev-seeder/metadata/types/field-metadata-seed.type';
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { type RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
|
||||
import { type RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
|
||||
export const convertOnDeleteActionToOnDelete = (
|
||||
onDeleteAction: RelationOnDeleteAction | undefined,
|
||||
|
||||
+4
-2
@@ -1,9 +1,11 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import diff, { type DifferenceChange, type DifferenceRemove } from 'microdiff';
|
||||
import { type FieldMetadataType } from 'twenty-shared/types';
|
||||
import {
|
||||
type FieldMetadataType,
|
||||
type FieldMetadataRelationSettings,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { type FieldMetadataRelationSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
import {
|
||||
ComparatorAction,
|
||||
type FieldRelationComparatorResult,
|
||||
|
||||
+1
-2
@@ -1,7 +1,6 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
|
||||
|
||||
|
||||
+1
-2
@@ -1,7 +1,6 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
|
||||
|
||||
|
||||
+1
-2
@@ -1,7 +1,6 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
|
||||
|
||||
|
||||
+1
-2
@@ -1,9 +1,8 @@
|
||||
import { registerEnumType } from '@nestjs/graphql';
|
||||
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
|
||||
|
||||
|
||||
+1
-2
@@ -1,9 +1,8 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
|
||||
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
|
||||
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
|
||||
|
||||
+1
-2
@@ -1,7 +1,6 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
|
||||
|
||||
|
||||
+1
-2
@@ -1,7 +1,6 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
|
||||
|
||||
|
||||
+1
-1
@@ -2,9 +2,9 @@ import { msg } from '@lingui/core/macro';
|
||||
import {
|
||||
ConnectedAccountProvider,
|
||||
FieldMetadataType,
|
||||
RelationOnDeleteAction,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
|
||||
|
||||
|
||||
+1
-2
@@ -1,7 +1,6 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
|
||||
|
||||
|
||||
+1
-2
@@ -1,7 +1,6 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
|
||||
|
||||
|
||||
+1
-2
@@ -1,10 +1,9 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
|
||||
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
|
||||
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
|
||||
import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
|
||||
import { WorkspaceDynamicRelation } from 'src/engine/twenty-orm/decorators/workspace-dynamic-relation.decorator';
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user