Deprecate asExpression from field metadata search_vector (#22287)
## Summary Fully deprecates the cached `asExpression` / `generatedType` settings on `TS_VECTOR` (searchVector) fields. Previously the generated-column expression was stored in `FieldMetadataSettings` and kept in sync via imperative recompute side-effects. It is now **derived at DDL time** from the `searchFieldMetadata` rows that describe which fields feed the search vector, making `searchFieldMetadata` the single source of truth and removing a whole class of cache-drift bugs. This is delivered across the milestones tracked in #2587 and coordinates with the frontend migration (#1428). ## Why - The searchVector expression lived in two places (stored `settings.asExpression` + the actual generated column), kept consistent by bespoke side-effects (`recompute-search-vector-on-field-rename`, label-identifier recompute, etc.). - The frontend reconstructed the searchable-fields list by **regex-parsing** the stored `asExpression`. - Both are brittle. Deriving the expression from `searchFieldMetadata` rows at build/run time removes the cache and the parsing. ## What changed ### Server - data model & derivation - Introduce the `tsVectorFieldMetadata` relation on `searchFieldMetadata` (`tsVectorFieldMetadataId` / universal identifier) linking each searchable-field row to its target `TS_VECTOR` field. - New runtime derivation `deriveSearchVectorAsExpressionForTsVectorField` (`flat-search-field-metadata/utils/...`) used by the create-object and update-field handlers to generate the column expression from `searchFieldMetadata` rows. - Remove `asExpression` / `generatedType` from stored settings: `FieldMetadataSettings.TS_VECTOR` is now `null`; the column builder (`generate-column-definitions.util.ts`) hardcodes `generatedType: 'STORED'` and requires the derived expression. - Delete the imperative recompute side-effects and the `compute-search-vector-universal-settings-from-object-manifest` path; drop the `settings` block from all 28 standard `compute-*-standard-flat-field-metadata` utils. ### Server - migration runner - New `rebuildSearchVector` marker on `update-field` actions: the orchestrator synthesizes targeted column rebuilds (`compute-search-vector-rebuild-target-universal-identifiers.util.ts` + the deprioritize aggregator) only when a searchFieldMetadata change or indexed-field rename actually requires it - instead of rebuilding on every settings touch. - Deferrable FKs + in-flight ID resolution so a `searchFieldMetadata` row and its `TS_VECTOR` field can be created in the same transaction (deterministic UUIDs). ### Frontend (contract change, #1428) - New `SearchFieldMetadataDTO` + dataloader exposing `searchFieldMetadataList` on object metadata. - `SettingsObjectSearchSection` now reads `objectMetadataItem.searchFieldMetadatas` instead of parsing `asExpression`; new `SearchFieldMetadataItem` type, fragment, and mapping updates. ### Upgrade commands (2.18) - `2-18-instance-command-fast-...-add-ts-vector-field-metadata-id-to-search-field-metadata` - `2-18-instance-command-fast-...-make-search-field-metadata-fks-deferrable` - `2-18-instance-command-slow-...-backfill-ts-vector-field-metadata-id-on-search-field-metadata` (These were relocated from 2.16 to 2.18 and re-timestamped into an ordered block - add column -> make FK deferrable -> backfill data - since 2.16/2.17 are released.) ### Tests - Updated search-vector side-effect integration specs to assert behavior (search works) rather than the now-removed `asExpression`; removed the obsolete expression-validation specs; refreshed the application-sync snapshot (`universalSettings: null`). ## Upgrade / compatibility notes - Existing workspaces keep their stored `settings` until a later cleanup; nothing reads it anymore. The new derivation drives all DDL going forward. - Schema changes are gated behind the 2.18 instance commands above. ## Known follow-up (separate PR) https://github.com/twentyhq/core-team-issues/issues/2620 - The column rebuild (`DROP`/`ADD` of the `searchVector` STORED column) cascade-drops its GIN index and does not recreate it - a pre-existing regression on `main` inherited here. A follow-up PR will fix the rebuild handler to recreate the GIN index and add a 2.18 workspace command to recompute every search vector + strip the deprecated settings. (Planned.) ## Test plan - [ ] `npx nx typecheck twenty-server` / `twenty-front` - [ ] `npx nx lint:diff-with-main twenty-server` / `twenty-front` - [ ] Server integration: create/update/delete field, rename indexed field, update object - search returns expected records - [ ] Run the 2.18 instance commands on a seeded DB; verify `tsVectorFieldMetadataId` backfilled and FKs deferrable - [ ] Frontend: object Search settings tab lists the correct searchable fields (no `asExpression` parsing) close https://github.com/twentyhq/core-team-issues/issues/2587 <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/22287?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
This commit is contained in:
+1
@@ -114,6 +114,7 @@ export const fromFieldManifestToUniversalFlatFieldMetadata = ({
|
||||
calendarViewUniversalIdentifiers: [],
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
searchFieldMetadataUniversalIdentifiers: [],
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
|
||||
+4
-17
@@ -2,7 +2,6 @@ import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { type Manifest } from 'twenty-shared/application';
|
||||
import { MAX_CUSTOM_INDEXES_PER_OBJECT } from 'twenty-shared/constants';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { fromApplicationVariableManifestToUniversalFlatApplicationVariable } from 'src/engine/core-modules/application/application-manifest/converters/from-application-variable-manifest-to-universal-flat-application-variable.util';
|
||||
@@ -25,7 +24,6 @@ import { fromRoleManifestToUniversalFlatRole } from 'src/engine/core-modules/app
|
||||
import { fromRowLevelPermissionPredicateGroupManifestToUniversalFlatRowLevelPermissionPredicateGroup } from 'src/engine/core-modules/application/application-manifest/converters/from-row-level-permission-predicate-group-manifest-to-universal-flat-row-level-permission-predicate-group.util';
|
||||
import { fromRowLevelPermissionPredicateManifestToUniversalFlatRowLevelPermissionPredicate } from 'src/engine/core-modules/application/application-manifest/converters/from-row-level-permission-predicate-manifest-to-universal-flat-row-level-permission-predicate.util';
|
||||
import { fromSkillManifestToUniversalFlatSkill } from 'src/engine/core-modules/application/application-manifest/converters/from-skill-manifest-to-universal-flat-skill.util';
|
||||
import { computeSearchVectorUniversalSettingsFromObjectManifest } from 'src/engine/core-modules/application/application-manifest/utils/compute-search-vector-universal-settings-from-object-manifest.util';
|
||||
import { fromViewFieldGroupManifestToUniversalFlatViewFieldGroup } from 'src/engine/core-modules/application/application-manifest/converters/from-view-field-group-manifest-to-universal-flat-view-field-group.util';
|
||||
import { fromViewFieldManifestToUniversalFlatViewField } from 'src/engine/core-modules/application/application-manifest/converters/from-view-field-manifest-to-universal-flat-view-field.util';
|
||||
import { fromViewFilterGroupManifestToUniversalFlatViewFilterGroup } from 'src/engine/core-modules/application/application-manifest/converters/from-view-filter-group-manifest-to-universal-flat-view-filter-group.util';
|
||||
@@ -95,21 +93,10 @@ export class ComputeApplicationManifestAllUniversalFlatEntityMapsService {
|
||||
});
|
||||
|
||||
for (const fieldManifest of objectManifest.fields) {
|
||||
const enrichedFieldManifest =
|
||||
fieldManifest.type === FieldMetadataType.TS_VECTOR &&
|
||||
!isDefined(fieldManifest.universalSettings)
|
||||
? {
|
||||
...fieldManifest,
|
||||
objectUniversalIdentifier: objectManifest.universalIdentifier,
|
||||
universalSettings:
|
||||
computeSearchVectorUniversalSettingsFromObjectManifest({
|
||||
objectManifest,
|
||||
}),
|
||||
}
|
||||
: {
|
||||
...fieldManifest,
|
||||
objectUniversalIdentifier: objectManifest.universalIdentifier,
|
||||
};
|
||||
const enrichedFieldManifest = {
|
||||
...fieldManifest,
|
||||
objectUniversalIdentifier: objectManifest.universalIdentifier,
|
||||
};
|
||||
|
||||
const flatFieldMetadata = fromFieldManifestToUniversalFlatFieldMetadata(
|
||||
{
|
||||
|
||||
-149
@@ -1,149 +0,0 @@
|
||||
import { type ObjectManifest } from 'twenty-shared/application';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { computeSearchVectorUniversalSettingsFromObjectManifest } from 'src/engine/core-modules/application/application-manifest/utils/compute-search-vector-universal-settings-from-object-manifest.util';
|
||||
|
||||
const buildObjectManifest = (
|
||||
overrides: Partial<ObjectManifest> & {
|
||||
fields: ObjectManifest['fields'];
|
||||
labelIdentifierFieldMetadataUniversalIdentifier: string;
|
||||
},
|
||||
): ObjectManifest => ({
|
||||
universalIdentifier: 'obj-uuid-1',
|
||||
nameSingular: 'testObject',
|
||||
namePlural: 'testObjects',
|
||||
labelSingular: 'Test Object',
|
||||
labelPlural: 'Test Objects',
|
||||
...overrides,
|
||||
});
|
||||
|
||||
describe('computeSearchVectorUniversalSettingsFromObjectManifest', () => {
|
||||
it('should return asExpression and generatedType for a TEXT label identifier field', () => {
|
||||
const result = computeSearchVectorUniversalSettingsFromObjectManifest({
|
||||
objectManifest: buildObjectManifest({
|
||||
labelIdentifierFieldMetadataUniversalIdentifier: 'field-uuid-name',
|
||||
fields: [
|
||||
{
|
||||
universalIdentifier: 'field-uuid-name',
|
||||
name: 'name',
|
||||
label: 'Name',
|
||||
type: FieldMetadataType.TEXT,
|
||||
},
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
expect(result?.generatedType).toBe('STORED');
|
||||
expect(result?.asExpression).toContain("to_tsvector('simple'");
|
||||
expect(result?.asExpression).toContain('"name"');
|
||||
});
|
||||
|
||||
it('should return asExpression for a FULL_NAME label identifier field', () => {
|
||||
const result = computeSearchVectorUniversalSettingsFromObjectManifest({
|
||||
objectManifest: buildObjectManifest({
|
||||
labelIdentifierFieldMetadataUniversalIdentifier: 'field-uuid-name',
|
||||
fields: [
|
||||
{
|
||||
universalIdentifier: 'field-uuid-name',
|
||||
name: 'name',
|
||||
label: 'Name',
|
||||
type: FieldMetadataType.FULL_NAME,
|
||||
},
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
expect(result?.generatedType).toBe('STORED');
|
||||
expect(result?.asExpression).toContain("to_tsvector('simple'");
|
||||
expect(result?.asExpression).toContain('"nameFirstName"');
|
||||
expect(result?.asExpression).toContain('"nameLastName"');
|
||||
});
|
||||
|
||||
it('should return asExpression for an EMAILS label identifier field', () => {
|
||||
const result = computeSearchVectorUniversalSettingsFromObjectManifest({
|
||||
objectManifest: buildObjectManifest({
|
||||
labelIdentifierFieldMetadataUniversalIdentifier: 'field-uuid-email',
|
||||
fields: [
|
||||
{
|
||||
universalIdentifier: 'field-uuid-email',
|
||||
name: 'email',
|
||||
label: 'Email',
|
||||
type: FieldMetadataType.EMAILS,
|
||||
},
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
expect(result?.generatedType).toBe('STORED');
|
||||
expect(result?.asExpression).toContain("to_tsvector('simple'");
|
||||
expect(result?.asExpression).toContain('"emailPrimaryEmail"');
|
||||
});
|
||||
|
||||
it('should return asExpression for a UUID label identifier field', () => {
|
||||
const result = computeSearchVectorUniversalSettingsFromObjectManifest({
|
||||
objectManifest: buildObjectManifest({
|
||||
labelIdentifierFieldMetadataUniversalIdentifier: 'field-uuid-id',
|
||||
fields: [
|
||||
{
|
||||
universalIdentifier: 'field-uuid-id',
|
||||
name: 'externalId',
|
||||
label: 'External ID',
|
||||
type: FieldMetadataType.UUID,
|
||||
},
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
expect(result?.generatedType).toBe('STORED');
|
||||
expect(result?.asExpression).toContain("to_tsvector('simple'");
|
||||
expect(result?.asExpression).toContain('"externalId"');
|
||||
});
|
||||
|
||||
it('should return null when label identifier field is not found in fields', () => {
|
||||
const result = computeSearchVectorUniversalSettingsFromObjectManifest({
|
||||
objectManifest: buildObjectManifest({
|
||||
labelIdentifierFieldMetadataUniversalIdentifier:
|
||||
'non-existent-field-uuid',
|
||||
fields: [
|
||||
{
|
||||
universalIdentifier: 'field-uuid-name',
|
||||
name: 'name',
|
||||
label: 'Name',
|
||||
type: FieldMetadataType.TEXT,
|
||||
},
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it('should return null when label identifier field has a non-searchable type', () => {
|
||||
const result = computeSearchVectorUniversalSettingsFromObjectManifest({
|
||||
objectManifest: buildObjectManifest({
|
||||
labelIdentifierFieldMetadataUniversalIdentifier: 'field-uuid-number',
|
||||
fields: [
|
||||
{
|
||||
universalIdentifier: 'field-uuid-number',
|
||||
name: 'amount',
|
||||
label: 'Amount',
|
||||
type: FieldMetadataType.NUMBER,
|
||||
},
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it('should return null when fields array is empty', () => {
|
||||
const result = computeSearchVectorUniversalSettingsFromObjectManifest({
|
||||
objectManifest: buildObjectManifest({
|
||||
labelIdentifierFieldMetadataUniversalIdentifier: 'field-uuid-name',
|
||||
fields: [],
|
||||
}),
|
||||
});
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
import { type ObjectManifest } from 'twenty-shared/application';
|
||||
import {
|
||||
type FieldMetadataUniversalSettings,
|
||||
FieldMetadataType,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { isDefined, isSearchableFieldType } from 'twenty-shared/utils';
|
||||
|
||||
export const computeSearchVectorUniversalSettingsFromObjectManifest = ({
|
||||
objectManifest,
|
||||
}: {
|
||||
objectManifest: ObjectManifest;
|
||||
}): FieldMetadataUniversalSettings<FieldMetadataType.TS_VECTOR> => {
|
||||
const labelIdentifierField = objectManifest.fields.find(
|
||||
(field) =>
|
||||
field.universalIdentifier ===
|
||||
objectManifest.labelIdentifierFieldMetadataUniversalIdentifier,
|
||||
);
|
||||
|
||||
if (
|
||||
!isDefined(labelIdentifierField) ||
|
||||
!isSearchableFieldType(labelIdentifierField.type)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
asExpression: getTsVectorColumnExpressionFromFields([
|
||||
{
|
||||
name: labelIdentifierField.name,
|
||||
type: labelIdentifierField.type,
|
||||
},
|
||||
]),
|
||||
generatedType: 'STORED',
|
||||
};
|
||||
};
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
type FieldMetadataLoaderPayload,
|
||||
type IndexFieldMetadataLoaderPayload,
|
||||
type IndexMetadataLoaderPayload,
|
||||
type SearchFieldMetadataLoaderPayload,
|
||||
type IsConfiguredLoaderPayload,
|
||||
type MorphRelationLoaderPayload,
|
||||
type StandardApplicationIdLoaderPayload,
|
||||
@@ -23,6 +24,7 @@ import { type RelationDTO } from 'src/engine/metadata-modules/field-metadata/dto
|
||||
import { type IndexFieldMetadataDTO } from 'src/engine/metadata-modules/index-metadata/dtos/index-field-metadata.dto';
|
||||
import { type IndexMetadataDTO } from 'src/engine/metadata-modules/index-metadata/dtos/index-metadata.dto';
|
||||
import { type ObjectMetadataDTO } from 'src/engine/metadata-modules/object-metadata/dtos/object-metadata.dto';
|
||||
import { type SearchFieldMetadataDTO } from 'src/engine/metadata-modules/search-field-metadata/dtos/search-field-metadata.dto';
|
||||
import { type ViewFieldGroupDTO } from 'src/engine/metadata-modules/view-field-group/dtos/view-field-group.dto';
|
||||
import { type ViewFieldDTO } from 'src/engine/metadata-modules/view-field/dtos/view-field.dto';
|
||||
import { type ViewFilterGroupDTO } from 'src/engine/metadata-modules/view-filter-group/dtos/view-filter-group.dto';
|
||||
@@ -53,6 +55,11 @@ export interface IDataloaders {
|
||||
IndexFieldMetadataDTO[]
|
||||
>;
|
||||
|
||||
searchFieldMetadataLoader: DataLoader<
|
||||
SearchFieldMetadataLoaderPayload,
|
||||
SearchFieldMetadataDTO[]
|
||||
>;
|
||||
|
||||
objectMetadataLoader: DataLoader<
|
||||
ObjectMetadataLoaderPayload,
|
||||
ObjectMetadataDTO | null
|
||||
|
||||
@@ -31,6 +31,7 @@ import { resolveMorphRelationsFromFlatFieldMetadata } from 'src/engine/metadata-
|
||||
import { resolveRelationFromFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/resolve-relation-from-flat-field-metadata.util';
|
||||
import { fromFlatObjectMetadataToObjectMetadataDto } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-to-object-metadata-dto.util';
|
||||
import { getMorphNameFromMorphFieldMetadataName } from 'src/engine/metadata-modules/flat-object-metadata/utils/get-morph-name-from-morph-field-metadata-name.util';
|
||||
import { fromFlatSearchFieldMetadataToSearchFieldMetadataDto } from 'src/engine/metadata-modules/flat-search-field-metadata/utils/from-flat-search-field-metadata-to-search-field-metadata-dto.util';
|
||||
import { fromFlatViewFieldGroupToViewFieldGroupDto } from 'src/engine/metadata-modules/view-field-group/utils/from-flat-view-field-group-to-view-field-group-dto.util';
|
||||
import { fromFlatViewFieldToViewFieldDto } from 'src/engine/metadata-modules/view-field/utils/from-flat-view-field-to-view-field-dto.util';
|
||||
import { fromFlatViewFilterToViewFilterDto } from 'src/engine/metadata-modules/view-filter/utils/from-flat-view-filter-to-view-filter-dto.util';
|
||||
@@ -41,6 +42,7 @@ import { type IndexFieldMetadataDTO } from 'src/engine/metadata-modules/index-me
|
||||
import { type IndexMetadataDTO } from 'src/engine/metadata-modules/index-metadata/dtos/index-metadata.dto';
|
||||
import { ObjectMetadataDTO } from 'src/engine/metadata-modules/object-metadata/dtos/object-metadata.dto';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type SearchFieldMetadataDTO } from 'src/engine/metadata-modules/search-field-metadata/dtos/search-field-metadata.dto';
|
||||
|
||||
export type RelationMetadataLoaderPayload = {
|
||||
workspaceId: string;
|
||||
@@ -76,6 +78,11 @@ export type IndexFieldMetadataLoaderPayload = {
|
||||
indexMetadata: Pick<IndexMetadataInterface, 'id'>;
|
||||
};
|
||||
|
||||
export type SearchFieldMetadataLoaderPayload = {
|
||||
workspaceId: string;
|
||||
objectMetadata: Pick<ObjectMetadataEntity, 'id'>;
|
||||
};
|
||||
|
||||
export type ObjectMetadataLoaderPayload = {
|
||||
workspaceId: string;
|
||||
objectMetadataId: string;
|
||||
@@ -145,6 +152,7 @@ export class DataloaderService {
|
||||
const fieldMetadataLoader = this.createFieldMetadataLoader();
|
||||
const indexMetadataLoader = this.createIndexMetadataLoader();
|
||||
const indexFieldMetadataLoader = this.createIndexFieldMetadataLoader();
|
||||
const searchFieldMetadataLoader = this.createSearchFieldMetadataLoader();
|
||||
const objectMetadataLoader = this.createObjectMetadataLoader();
|
||||
const viewFieldGroupsByViewIdLoader =
|
||||
this.createViewFieldGroupsByViewIdLoader();
|
||||
@@ -168,6 +176,7 @@ export class DataloaderService {
|
||||
fieldMetadataLoader,
|
||||
indexMetadataLoader,
|
||||
indexFieldMetadataLoader,
|
||||
searchFieldMetadataLoader,
|
||||
objectMetadataLoader,
|
||||
viewFieldGroupsByViewIdLoader,
|
||||
viewFieldsByViewFieldGroupIdLoader,
|
||||
@@ -306,6 +315,46 @@ export class DataloaderService {
|
||||
);
|
||||
}
|
||||
|
||||
private createSearchFieldMetadataLoader() {
|
||||
return new DataLoader<
|
||||
SearchFieldMetadataLoaderPayload,
|
||||
SearchFieldMetadataDTO[]
|
||||
>(async (dataLoaderParams: SearchFieldMetadataLoaderPayload[]) => {
|
||||
const workspaceId = dataLoaderParams[0].workspaceId;
|
||||
const objectMetadataIds = dataLoaderParams.map(
|
||||
(dataLoaderParam) => dataLoaderParam.objectMetadata.id,
|
||||
);
|
||||
|
||||
const { flatSearchFieldMetadataMaps, flatObjectMetadataMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: [
|
||||
'flatSearchFieldMetadataMaps',
|
||||
'flatObjectMetadataMaps',
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
return objectMetadataIds.map((objectMetadataId) => {
|
||||
const flatObjectMetadata = findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityId: objectMetadataId,
|
||||
flatEntityMaps: flatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
const searchFieldMetadatas =
|
||||
findManyFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityIds: flatObjectMetadata.searchFieldMetadataIds,
|
||||
flatEntityMaps: flatSearchFieldMetadataMaps,
|
||||
});
|
||||
|
||||
return searchFieldMetadatas.map(
|
||||
fromFlatSearchFieldMetadataToSearchFieldMetadataDto,
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private createFieldMetadataLoader() {
|
||||
return new DataLoader<FieldMetadataLoaderPayload, FieldMetadataDTO[]>(
|
||||
async (dataLoaderParams: FieldMetadataLoaderPayload[]) => {
|
||||
|
||||
+7
@@ -30,6 +30,7 @@ import { AssignTypeIfIsMorphOrRelationFieldMetadataType } from 'src/engine/metad
|
||||
import { IndexFieldMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-field-metadata.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { FieldPermissionEntity } from 'src/engine/metadata-modules/object-permission/field-permission/field-permission.entity';
|
||||
import { SearchFieldMetadataEntity } from 'src/engine/metadata-modules/search-field-metadata/search-field-metadata.entity';
|
||||
import { ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity';
|
||||
import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity';
|
||||
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
|
||||
@@ -238,4 +239,10 @@ export class FieldMetadataEntity<
|
||||
|
||||
@OneToMany(() => ViewSortEntity, (viewSort) => viewSort.fieldMetadata)
|
||||
viewSorts: Relation<ViewSortEntity[]>;
|
||||
|
||||
@OneToMany(
|
||||
() => SearchFieldMetadataEntity,
|
||||
(searchFieldMetadata) => searchFieldMetadata.fieldMetadata,
|
||||
)
|
||||
searchFieldMetadatas: Relation<SearchFieldMetadataEntity[]>;
|
||||
}
|
||||
|
||||
+3
-8
@@ -16,7 +16,6 @@ import {
|
||||
FieldMetadataExceptionCode,
|
||||
} from 'src/engine/metadata-modules/field-metadata/field-metadata.exception';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
|
||||
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
|
||||
import { findManyFlatEntityByUniversalIdentifierInUniversalFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-many-flat-entity-by-universal-identifier-in-universal-flat-entity-maps-or-throw.util';
|
||||
@@ -114,7 +113,6 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
||||
flatIndexesToDelete,
|
||||
flatIndexesToUpdate,
|
||||
searchFieldMetadatasToDelete,
|
||||
flatSearchVectorFieldsToUpdate,
|
||||
} = fromDeleteFieldInputToFlatFieldMetadatasToDelete({
|
||||
deleteOneFieldInput,
|
||||
flatFieldMetadataMaps: existingFlatFieldMetadataMaps,
|
||||
@@ -162,7 +160,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
||||
fieldMetadata: {
|
||||
flatEntityToCreate: [],
|
||||
flatEntityToDelete: flatFieldMetadatasToDelete,
|
||||
flatEntityToUpdate: flatSearchVectorFieldsToUpdate,
|
||||
flatEntityToUpdate: [],
|
||||
},
|
||||
index: {
|
||||
flatEntityToCreate: [],
|
||||
@@ -228,7 +226,6 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
||||
flatViewGroupMaps: existingFlatViewGroupMaps,
|
||||
flatViewMaps: existingFlatViewMaps,
|
||||
flatViewFieldMaps: existingFlatViewFieldMaps,
|
||||
flatSearchFieldMetadataMaps: existingFlatSearchFieldMetadataMaps,
|
||||
} = await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
@@ -240,7 +237,6 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
||||
'flatViewGroupMaps',
|
||||
'flatViewMaps',
|
||||
'flatViewFieldMaps',
|
||||
'flatSearchFieldMetadataMaps',
|
||||
],
|
||||
},
|
||||
);
|
||||
@@ -254,7 +250,6 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
||||
flatViewGroupMaps: existingFlatViewGroupMaps,
|
||||
flatViewMaps: existingFlatViewMaps,
|
||||
flatViewFieldMaps: existingFlatViewFieldMaps,
|
||||
flatSearchFieldMetadataMaps: existingFlatSearchFieldMetadataMaps,
|
||||
flatApplication: resolvedOwnerFlatApplication,
|
||||
isSystemBuild,
|
||||
});
|
||||
@@ -354,8 +349,8 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
||||
},
|
||||
);
|
||||
|
||||
return findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityId: flatFieldMetadatasToUpdate[0].id,
|
||||
return findFlatEntityByUniversalIdentifierOrThrow({
|
||||
universalIdentifier: flatFieldMetadatasToUpdate[0].universalIdentifier,
|
||||
flatEntityMaps: recomputedFlatFieldMetadataMaps,
|
||||
});
|
||||
}
|
||||
|
||||
+5
@@ -1785,6 +1785,11 @@ export const ALL_ENTITY_PROPERTIES_CONFIGURATION_BY_METADATA_NAME = {
|
||||
toStringify: false,
|
||||
universalProperty: 'fieldMetadataUniversalIdentifier',
|
||||
},
|
||||
tsVectorFieldMetadataId: {
|
||||
toCompare: false,
|
||||
toStringify: false,
|
||||
universalProperty: 'tsVectorFieldMetadataUniversalIdentifier',
|
||||
},
|
||||
position: {
|
||||
toCompare: true,
|
||||
toStringify: false,
|
||||
|
||||
+3
@@ -312,6 +312,9 @@ export const ALL_MANY_TO_ONE_METADATA_FOREIGN_KEY = {
|
||||
fieldMetadata: {
|
||||
foreignKey: 'fieldMetadataId',
|
||||
},
|
||||
tsVectorFieldMetadata: {
|
||||
foreignKey: 'tsVectorFieldMetadataId',
|
||||
},
|
||||
},
|
||||
} as const satisfies ManyToOneMetadataRelationsProperties;
|
||||
|
||||
|
||||
+8
-1
@@ -544,10 +544,17 @@ export const ALL_MANY_TO_ONE_METADATA_RELATIONS = {
|
||||
fieldMetadata: {
|
||||
metadataName: 'fieldMetadata',
|
||||
foreignKey: 'fieldMetadataId',
|
||||
inverseOneToManyProperty: null,
|
||||
inverseOneToManyProperty: 'searchFieldMetadatas',
|
||||
isNullable: false,
|
||||
universalForeignKey: 'fieldMetadataUniversalIdentifier',
|
||||
},
|
||||
tsVectorFieldMetadata: {
|
||||
metadataName: 'fieldMetadata',
|
||||
foreignKey: 'tsVectorFieldMetadataId',
|
||||
inverseOneToManyProperty: null,
|
||||
isNullable: false,
|
||||
universalForeignKey: 'tsVectorFieldMetadataUniversalIdentifier',
|
||||
},
|
||||
},
|
||||
} as const satisfies ManyToOneMetadataRelationsProperties;
|
||||
|
||||
|
||||
+6
@@ -77,6 +77,12 @@ export const ALL_ONE_TO_MANY_METADATA_RELATIONS = {
|
||||
universalFlatEntityForeignKeyAggregator:
|
||||
'mainGroupByFieldMetadataViewUniversalIdentifiers',
|
||||
},
|
||||
searchFieldMetadatas: {
|
||||
metadataName: 'searchFieldMetadata',
|
||||
flatEntityForeignKeyAggregator: 'searchFieldMetadataIds',
|
||||
universalFlatEntityForeignKeyAggregator:
|
||||
'searchFieldMetadataUniversalIdentifiers',
|
||||
},
|
||||
},
|
||||
objectMetadata: {
|
||||
fields: {
|
||||
|
||||
+4
-1
@@ -17,7 +17,8 @@ type FieldMetadataOneToManySyncableRelations =
|
||||
type Assertions = [
|
||||
// FieldMetadataEntity OneToMany relations (all targets):
|
||||
// - indexFieldMetadatas, fieldPermissions, viewFields, viewFilters,
|
||||
// - kanbanAggregateOperationViews, calendarViews, mainGroupByFieldMetadataViews, viewSorts
|
||||
// - kanbanAggregateOperationViews, calendarViews, mainGroupByFieldMetadataViews,
|
||||
// - viewSorts, searchFieldMetadatas
|
||||
Expect<
|
||||
Equal<
|
||||
FieldMetadataOneToManyRelations,
|
||||
@@ -29,6 +30,7 @@ type Assertions = [
|
||||
| 'calendarViews'
|
||||
| 'mainGroupByFieldMetadataViews'
|
||||
| 'viewSorts'
|
||||
| 'searchFieldMetadatas'
|
||||
>
|
||||
>,
|
||||
|
||||
@@ -43,6 +45,7 @@ type Assertions = [
|
||||
| 'calendarViews'
|
||||
| 'mainGroupByFieldMetadataViews'
|
||||
| 'viewSorts'
|
||||
| 'searchFieldMetadatas'
|
||||
>
|
||||
>,
|
||||
];
|
||||
|
||||
+2
-1
@@ -10,7 +10,7 @@ type FieldMetadataRelatedProperties =
|
||||
type Assertions = [
|
||||
// FieldMetadataEntity has both ManyToOne and OneToMany relations
|
||||
// ManyToOne: object, workspace, application, relationTargetFieldMetadata, relationTargetObjectMetadata
|
||||
// OneToMany: indexFieldMetadatas, fieldPermissions, viewFields, viewFilters, kanbanAggregateOperationViews, calendarViews, mainGroupByFieldMetadataViews, viewSorts
|
||||
// OneToMany: indexFieldMetadatas, fieldPermissions, viewFields, viewFilters, kanbanAggregateOperationViews, calendarViews, mainGroupByFieldMetadataViews, viewSorts, searchFieldMetadatas
|
||||
Expect<
|
||||
Equal<
|
||||
FieldMetadataRelatedProperties,
|
||||
@@ -27,6 +27,7 @@ type Assertions = [
|
||||
| 'calendarViews'
|
||||
| 'mainGroupByFieldMetadataViews'
|
||||
| 'viewSorts'
|
||||
| 'searchFieldMetadatas'
|
||||
>
|
||||
>,
|
||||
];
|
||||
|
||||
+1
@@ -23,6 +23,7 @@ exports[`getMetadataRelatedMetadataNames should return related metadata names fo
|
||||
"viewField",
|
||||
"viewFilter",
|
||||
"view",
|
||||
"searchFieldMetadata",
|
||||
]
|
||||
`;
|
||||
|
||||
|
||||
+1
-1
@@ -7,11 +7,11 @@ exports[`sortMetadataNamesChildrenFirst should return metadata names sorted with
|
||||
"viewFilter",
|
||||
"commandMenuItem",
|
||||
"fieldPermission",
|
||||
"searchFieldMetadata",
|
||||
"viewField",
|
||||
"objectPermission",
|
||||
"pageLayoutWidget",
|
||||
"rolePermissionFlag",
|
||||
"searchFieldMetadata",
|
||||
"viewSort",
|
||||
"index",
|
||||
"pageLayout",
|
||||
|
||||
+15
@@ -12,6 +12,7 @@ import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity
|
||||
import { type MetadataRelatedFlatEntityMapsKeys } from 'src/engine/metadata-modules/flat-entity/types/metadata-related-flat-entity-maps-keys.type';
|
||||
import { type MetadataFlatEntityAndRelatedFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-related-types.type';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
|
||||
import { addUniversalFlatEntityToUniversalFlatEntityAndRelatedEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/add-universal-flat-entity-to-universal-flat-entity-and-related-entity-maps-through-mutation-or-throw.util';
|
||||
import { replaceFlatEntityInFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/replace-flat-entity-in-flat-entity-maps-through-mutation-or-throw.util';
|
||||
@@ -22,6 +23,7 @@ type AddFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrowArgs<
|
||||
metadataName: T;
|
||||
flatEntity: MetadataFlatEntity<T>;
|
||||
flatEntityAndRelatedMapsToMutate: MetadataFlatEntityAndRelatedFlatEntityMaps<T>;
|
||||
skipMissingRelatedEntities?: boolean;
|
||||
};
|
||||
|
||||
export const addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow =
|
||||
@@ -29,6 +31,7 @@ export const addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow
|
||||
metadataName,
|
||||
flatEntity,
|
||||
flatEntityAndRelatedMapsToMutate,
|
||||
skipMissingRelatedEntities = false,
|
||||
}: AddFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrowArgs<T>) => {
|
||||
addUniversalFlatEntityToUniversalFlatEntityAndRelatedEntityMapsThroughMutationOrThrow(
|
||||
{
|
||||
@@ -36,6 +39,7 @@ export const addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow
|
||||
universalFlatEntity: flatEntity,
|
||||
universalFlatEntityAndRelatedMapsToMutate:
|
||||
flatEntityAndRelatedMapsToMutate,
|
||||
skipMissingRelatedEntities,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -101,6 +105,17 @@ export const addFlatEntityToFlatEntityAndRelatedEntityMapsThroughMutationOrThrow
|
||||
continue;
|
||||
}
|
||||
|
||||
if (skipMissingRelatedEntities) {
|
||||
const maybeRelatedFlatEntity = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: flatEntityRelatedEntityForeignKeyValue,
|
||||
flatEntityMaps: relatedFlatEntityMetadataMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(maybeRelatedFlatEntity)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
const relatedFlatEntity = findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityId: flatEntityRelatedEntityForeignKeyValue,
|
||||
flatEntityMaps: relatedFlatEntityMetadataMaps,
|
||||
|
||||
+2
@@ -57,6 +57,8 @@ export const getFlatFieldMetadataMock = <T extends FieldMetadataType>(
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
viewSortIds: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
searchFieldMetadataIds: [],
|
||||
searchFieldMetadataUniversalIdentifiers: [],
|
||||
universalSettings: null,
|
||||
...overrides,
|
||||
};
|
||||
|
||||
+2
@@ -77,6 +77,8 @@ export const getRelationTargetFlatFieldMetadataMock = ({
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
viewSortIds: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
searchFieldMetadataIds: [],
|
||||
searchFieldMetadataUniversalIdentifiers: [],
|
||||
universalSettings: settings,
|
||||
};
|
||||
};
|
||||
|
||||
+4
@@ -139,6 +139,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataUniversalIdentifier": Any<String>,
|
||||
"relationTargetObjectMetadataUniversalIdentifier": Any<String>,
|
||||
"searchFieldMetadataUniversalIdentifiers": [],
|
||||
"standardOverrides": null,
|
||||
"type": "MORPH_RELATION",
|
||||
"universalIdentifier": Any<String>,
|
||||
@@ -174,6 +175,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataUniversalIdentifier": Any<String>,
|
||||
"relationTargetObjectMetadataUniversalIdentifier": Any<String>,
|
||||
"searchFieldMetadataUniversalIdentifiers": [],
|
||||
"standardOverrides": null,
|
||||
"type": "RELATION",
|
||||
"universalIdentifier": Any<String>,
|
||||
@@ -211,6 +213,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataUniversalIdentifier": Any<String>,
|
||||
"relationTargetObjectMetadataUniversalIdentifier": Any<String>,
|
||||
"searchFieldMetadataUniversalIdentifiers": [],
|
||||
"standardOverrides": null,
|
||||
"type": "MORPH_RELATION",
|
||||
"universalIdentifier": Any<String>,
|
||||
@@ -246,6 +249,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataUniversalIdentifier": Any<String>,
|
||||
"relationTargetObjectMetadataUniversalIdentifier": Any<String>,
|
||||
"searchFieldMetadataUniversalIdentifiers": [],
|
||||
"standardOverrides": null,
|
||||
"type": "RELATION",
|
||||
"universalIdentifier": Any<String>,
|
||||
|
||||
+14
@@ -14,6 +14,7 @@ import { fromFieldMetadataEntityToFlatFieldMetadata } from 'src/engine/metadata-
|
||||
import { IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity';
|
||||
import { computeUniqueFieldMetadataIdsFromIndexEntities } from 'src/engine/metadata-modules/index-metadata/utils/compute-unique-field-metadata-ids-from-index-entities.util';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { SearchFieldMetadataEntity } from 'src/engine/metadata-modules/search-field-metadata/search-field-metadata.entity';
|
||||
import { ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity';
|
||||
import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity';
|
||||
import { ViewGroupEntity } from 'src/engine/metadata-modules/view-group/entities/view-group.entity';
|
||||
@@ -50,6 +51,8 @@ export class WorkspaceFlatFieldMetadataMapCacheService extends WorkspaceCachePro
|
||||
private readonly viewSortRepository: WorkspaceScopedRepository<ViewSortEntity>,
|
||||
@InjectWorkspaceScopedRepository(ViewEntity)
|
||||
private readonly viewRepository: WorkspaceScopedRepository<ViewEntity>,
|
||||
@InjectWorkspaceScopedRepository(SearchFieldMetadataEntity)
|
||||
private readonly searchFieldMetadataRepository: WorkspaceScopedRepository<SearchFieldMetadataEntity>,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
@@ -66,6 +69,7 @@ export class WorkspaceFlatFieldMetadataMapCacheService extends WorkspaceCachePro
|
||||
viewFilters,
|
||||
viewSorts,
|
||||
views,
|
||||
searchFieldMetadatas,
|
||||
] = await Promise.all([
|
||||
this.fieldMetadataRepository.find({
|
||||
where: { workspaceId },
|
||||
@@ -108,6 +112,9 @@ export class WorkspaceFlatFieldMetadataMapCacheService extends WorkspaceCachePro
|
||||
],
|
||||
withDeleted: true,
|
||||
}),
|
||||
this.searchFieldMetadataRepository.find(workspaceId, {
|
||||
select: ['id', 'universalIdentifier', 'fieldMetadataId'],
|
||||
}),
|
||||
]);
|
||||
|
||||
const [
|
||||
@@ -117,6 +124,7 @@ export class WorkspaceFlatFieldMetadataMapCacheService extends WorkspaceCachePro
|
||||
kanbanViewsByFieldId,
|
||||
mainGroupByFieldMetadataViewsByFieldId,
|
||||
viewSortsByFieldId,
|
||||
searchFieldMetadatasByFieldId,
|
||||
] = (
|
||||
[
|
||||
{
|
||||
@@ -143,6 +151,10 @@ export class WorkspaceFlatFieldMetadataMapCacheService extends WorkspaceCachePro
|
||||
entities: viewSorts,
|
||||
foreignKey: 'fieldMetadataId',
|
||||
},
|
||||
{
|
||||
entities: searchFieldMetadatas,
|
||||
foreignKey: 'fieldMetadataId',
|
||||
},
|
||||
] as const
|
||||
).map(regroupEntitiesByRelatedEntityId);
|
||||
|
||||
@@ -173,6 +185,8 @@ export class WorkspaceFlatFieldMetadataMapCacheService extends WorkspaceCachePro
|
||||
fieldMetadataEntity.id,
|
||||
) || [],
|
||||
viewSorts: viewSortsByFieldId.get(fieldMetadataEntity.id) || [],
|
||||
searchFieldMetadatas:
|
||||
searchFieldMetadatasByFieldId.get(fieldMetadataEntity.id) || [],
|
||||
},
|
||||
fieldMetadataIdToUniversalIdentifierMap,
|
||||
objectMetadataIdToUniversalIdentifierMap,
|
||||
|
||||
+1
-30
@@ -1,29 +1,23 @@
|
||||
import { type FieldMetadataType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { recomputeSearchVectorFieldFromSearchFieldMetadatas } from 'src/engine/metadata-modules/flat-object-metadata/utils/recompute-search-vector-field-from-search-field-metadatas.util';
|
||||
import { type FlatSearchFieldMetadata } from 'src/engine/metadata-modules/flat-search-field-metadata/types/flat-search-field-metadata.type';
|
||||
import { type UniversalFlatSearchFieldMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-search-field-metadata.type';
|
||||
|
||||
export const computeSearchFieldMetadataDeletionForDeletedFields = ({
|
||||
flatFieldMetadatasToDelete,
|
||||
flatObjectMetadataMaps,
|
||||
flatFieldMetadataMaps,
|
||||
flatSearchFieldMetadataMaps,
|
||||
}: {
|
||||
flatFieldMetadatasToDelete: FlatFieldMetadata[];
|
||||
} & Pick<
|
||||
AllFlatEntityMaps,
|
||||
| 'flatObjectMetadataMaps'
|
||||
| 'flatFieldMetadataMaps'
|
||||
| 'flatSearchFieldMetadataMaps'
|
||||
'flatObjectMetadataMaps' | 'flatSearchFieldMetadataMaps'
|
||||
>): {
|
||||
searchFieldMetadatasToDelete: UniversalFlatSearchFieldMetadata[];
|
||||
flatSearchVectorFieldsToUpdate: FlatFieldMetadata<FieldMetadataType.TS_VECTOR>[];
|
||||
} => {
|
||||
const deletedFieldIds = new Set(
|
||||
flatFieldMetadatasToDelete.map((flatFieldMetadata) => flatFieldMetadata.id),
|
||||
@@ -35,8 +29,6 @@ export const computeSearchFieldMetadataDeletionForDeletedFields = ({
|
||||
);
|
||||
|
||||
const searchFieldMetadatasToDelete: UniversalFlatSearchFieldMetadata[] = [];
|
||||
const flatSearchVectorFieldsToUpdate: FlatFieldMetadata<FieldMetadataType.TS_VECTOR>[] =
|
||||
[];
|
||||
|
||||
for (const objectMetadataId of affectedObjectMetadataIds) {
|
||||
const flatObjectMetadata = findFlatEntityByIdInFlatEntityMaps({
|
||||
@@ -59,31 +51,10 @@ export const computeSearchFieldMetadataDeletionForDeletedFields = ({
|
||||
deletedFieldIds.has(searchFieldMetadata.fieldMetadataId),
|
||||
);
|
||||
|
||||
if (rowsToDelete.length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
searchFieldMetadatasToDelete.push(...rowsToDelete);
|
||||
|
||||
const remainingSearchFieldMetadatas = objectSearchFieldMetadatas.filter(
|
||||
(searchFieldMetadata) =>
|
||||
!deletedFieldIds.has(searchFieldMetadata.fieldMetadataId),
|
||||
);
|
||||
|
||||
const flatSearchVectorFieldToUpdate =
|
||||
recomputeSearchVectorFieldFromSearchFieldMetadatas({
|
||||
flatObjectMetadata,
|
||||
flatFieldMetadataMaps,
|
||||
searchFieldMetadatas: remainingSearchFieldMetadatas,
|
||||
});
|
||||
|
||||
if (isDefined(flatSearchVectorFieldToUpdate)) {
|
||||
flatSearchVectorFieldsToUpdate.push(flatSearchVectorFieldToUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
searchFieldMetadatasToDelete,
|
||||
flatSearchVectorFieldsToUpdate,
|
||||
};
|
||||
};
|
||||
|
||||
+1
-6
@@ -1,4 +1,3 @@
|
||||
import { type FieldMetadataType } from 'twenty-shared/types';
|
||||
import {
|
||||
isDefined,
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties,
|
||||
@@ -13,7 +12,6 @@ import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
|
||||
import { findManyFlatEntityByUniversalIdentifierInUniversalFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-many-flat-entity-by-universal-identifier-in-universal-flat-entity-maps-or-throw.util';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { computeFlatFieldMetadataRelatedFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/compute-flat-field-metadata-related-flat-field-metadata.util';
|
||||
import { computeSearchFieldMetadataDeletionForDeletedFields } from 'src/engine/metadata-modules/flat-field-metadata/utils/compute-search-field-metadata-deletion-for-deleted-fields.util';
|
||||
import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
|
||||
@@ -44,7 +42,6 @@ export const fromDeleteFieldInputToFlatFieldMetadatasToDelete = ({
|
||||
flatIndexesToUpdate: UniversalFlatIndexMetadata[];
|
||||
flatIndexesToDelete: UniversalFlatIndexMetadata[];
|
||||
searchFieldMetadatasToDelete: UniversalFlatSearchFieldMetadata[];
|
||||
flatSearchVectorFieldsToUpdate: FlatFieldMetadata<FieldMetadataType.TS_VECTOR>[];
|
||||
} => {
|
||||
const { id: fieldMetadataToDeleteId } =
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
|
||||
@@ -187,11 +184,10 @@ export const fromDeleteFieldInputToFlatFieldMetadatasToDelete = ({
|
||||
},
|
||||
);
|
||||
|
||||
const { searchFieldMetadatasToDelete, flatSearchVectorFieldsToUpdate } =
|
||||
const { searchFieldMetadatasToDelete } =
|
||||
computeSearchFieldMetadataDeletionForDeletedFields({
|
||||
flatFieldMetadatasToDelete,
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
flatFieldMetadataMaps: existingFlatFieldMetadataMaps,
|
||||
flatSearchFieldMetadataMaps: existingFlatSearchFieldMetadataMaps,
|
||||
});
|
||||
|
||||
@@ -200,6 +196,5 @@ export const fromDeleteFieldInputToFlatFieldMetadatasToDelete = ({
|
||||
flatIndexesToDelete,
|
||||
flatIndexesToUpdate,
|
||||
searchFieldMetadatasToDelete,
|
||||
flatSearchVectorFieldsToUpdate,
|
||||
};
|
||||
};
|
||||
|
||||
+6
@@ -78,6 +78,12 @@ export const fromFieldMetadataEntityToFlatFieldMetadata = (
|
||||
fieldMetadataEntity.viewSorts?.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
) ?? [],
|
||||
searchFieldMetadataIds:
|
||||
fieldMetadataEntity.searchFieldMetadatas?.map(({ id }) => id) ?? [],
|
||||
searchFieldMetadataUniversalIdentifiers:
|
||||
fieldMetadataEntity.searchFieldMetadatas?.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
) ?? [],
|
||||
fieldPermissionUniversalIdentifiers:
|
||||
fieldMetadataEntity.fieldPermissions?.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
|
||||
-5
@@ -35,7 +35,6 @@ type FromUpdateFieldInputToFlatFieldMetadataArgs = {
|
||||
| 'flatViewGroupMaps'
|
||||
| 'flatViewMaps'
|
||||
| 'flatViewFieldMaps'
|
||||
| 'flatSearchFieldMetadataMaps'
|
||||
>;
|
||||
|
||||
type FlatFieldMetadataAndIndexToUpdate = {
|
||||
@@ -52,7 +51,6 @@ export const fromUpdateFieldInputToFlatFieldMetadata = ({
|
||||
flatViewGroupMaps,
|
||||
flatViewMaps,
|
||||
flatViewFieldMaps,
|
||||
flatSearchFieldMetadataMaps,
|
||||
isSystemBuild,
|
||||
}: FromUpdateFieldInputToFlatFieldMetadataArgs): FieldInputTranspilationResult<FlatFieldMetadataAndIndexToUpdate> => {
|
||||
const updateFieldInputInformalProperties =
|
||||
@@ -152,7 +150,6 @@ export const fromUpdateFieldInputToFlatFieldMetadata = ({
|
||||
toFlatFieldMetadata,
|
||||
flatViewMaps,
|
||||
flatViewFieldMaps,
|
||||
flatSearchFieldMetadataMaps,
|
||||
flatApplication,
|
||||
});
|
||||
|
||||
@@ -175,14 +172,12 @@ export const fromUpdateFieldInputToFlatFieldMetadata = ({
|
||||
flatViewsToDelete,
|
||||
flatViewFieldsToDelete,
|
||||
flatViewsToUpdate,
|
||||
flatFieldMetadatasToUpdate: flatFieldMetadatasToUpdateFromSideEffect,
|
||||
} = sideEffectResult.result;
|
||||
|
||||
return {
|
||||
flatFieldMetadatasToUpdate: [
|
||||
...accumulator.flatFieldMetadatasToUpdate,
|
||||
toFlatFieldMetadata,
|
||||
...flatFieldMetadatasToUpdateFromSideEffect,
|
||||
],
|
||||
flatIndexMetadatasToUpdate: [
|
||||
...accumulator.flatIndexMetadatasToUpdate,
|
||||
|
||||
+1
@@ -77,5 +77,6 @@ export const getDefaultFlatFieldMetadata = ({
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
universalSettings: settings ?? null,
|
||||
viewSortUniversalIdentifiers: [],
|
||||
searchFieldMetadataUniversalIdentifiers: [],
|
||||
} as const satisfies UniversalFlatFieldMetadata;
|
||||
};
|
||||
|
||||
+1
-28
@@ -1,9 +1,7 @@
|
||||
import { type FromTo } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { type FieldInputTranspilationResult } from 'src/engine/metadata-modules/flat-field-metadata/types/field-input-transpilation-result.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { handleEnumFlatFieldMetadataUpdateSideEffects } from 'src/engine/metadata-modules/flat-field-metadata/utils/handle-enum-flat-field-metadata-update-side-effects.util';
|
||||
@@ -16,7 +14,6 @@ import {
|
||||
handleIndexChangesDuringFieldUpdate,
|
||||
} from 'src/engine/metadata-modules/flat-field-metadata/utils/handle-index-changes-during-field-update.util';
|
||||
import { isEnumFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-enum-flat-field-metadata.util';
|
||||
import { recomputeSearchVectorOnFieldRename } from 'src/engine/metadata-modules/flat-field-metadata/utils/recompute-search-vector-on-field-rename.util';
|
||||
import { type FlatViewFiltersToDeleteAndUpdate } from 'src/engine/metadata-modules/flat-field-metadata/utils/recompute-view-filters-on-flat-field-metadata-options-update.util';
|
||||
import { type FlatViewGroupsToDeleteUpdateAndCreate } from 'src/engine/metadata-modules/flat-field-metadata/utils/recompute-view-groups-on-flat-field-metadata-options-update.util';
|
||||
|
||||
@@ -24,9 +21,7 @@ export type FlatFieldMetadataUpdateSideEffects =
|
||||
FlatViewFiltersToDeleteAndUpdate &
|
||||
FlatViewGroupsToDeleteUpdateAndCreate &
|
||||
FieldMetadataUpdateIndexSideEffect &
|
||||
FieldMetadataDeactivationSideEffect & {
|
||||
flatFieldMetadatasToUpdate: FlatFieldMetadata[];
|
||||
};
|
||||
FieldMetadataDeactivationSideEffect;
|
||||
|
||||
type HandleFlatFieldMetadataUpdateSideEffectArgs = FromTo<
|
||||
FlatFieldMetadata,
|
||||
@@ -41,7 +36,6 @@ type HandleFlatFieldMetadataUpdateSideEffectArgs = FromTo<
|
||||
| 'flatViewGroupMaps'
|
||||
| 'flatViewMaps'
|
||||
| 'flatViewFieldMaps'
|
||||
| 'flatSearchFieldMetadataMaps'
|
||||
> & {
|
||||
flatApplication: FlatApplication;
|
||||
};
|
||||
@@ -59,7 +53,6 @@ export const FLAT_FIELD_METADATA_UPDATE_EMPTY_SIDE_EFFECTS: FlatFieldMetadataUpd
|
||||
flatViewsToDelete: [],
|
||||
flatViewFieldsToDelete: [],
|
||||
flatViewsToUpdate: [],
|
||||
flatFieldMetadatasToUpdate: [],
|
||||
};
|
||||
|
||||
export const handleFlatFieldMetadataUpdateSideEffect = ({
|
||||
@@ -72,7 +65,6 @@ export const handleFlatFieldMetadataUpdateSideEffect = ({
|
||||
flatViewGroupMaps,
|
||||
flatViewMaps,
|
||||
flatViewFieldMaps,
|
||||
flatSearchFieldMetadataMaps,
|
||||
flatApplication,
|
||||
}: HandleFlatFieldMetadataUpdateSideEffectArgs): FieldInputTranspilationResult<FlatFieldMetadataUpdateSideEffects> => {
|
||||
const sideEffectResult = structuredClone(
|
||||
@@ -140,25 +132,6 @@ export const handleFlatFieldMetadataUpdateSideEffect = ({
|
||||
return indexChangesSideEffectResult;
|
||||
}
|
||||
|
||||
const flatObjectMetadata = findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityMaps: flatObjectMetadataMaps,
|
||||
flatEntityId: fromFlatFieldMetadata.objectMetadataId,
|
||||
});
|
||||
|
||||
const { flatSearchVectorFieldToUpdate } = recomputeSearchVectorOnFieldRename({
|
||||
fromFlatFieldMetadata,
|
||||
toFlatFieldMetadata,
|
||||
flatObjectMetadata,
|
||||
flatFieldMetadataMaps,
|
||||
flatSearchFieldMetadataMaps,
|
||||
});
|
||||
|
||||
if (isDefined(flatSearchVectorFieldToUpdate)) {
|
||||
sideEffectResult.flatFieldMetadatasToUpdate.push(
|
||||
flatSearchVectorFieldToUpdate,
|
||||
);
|
||||
}
|
||||
|
||||
const {
|
||||
flatIndexMetadatasToUpdate,
|
||||
flatIndexMetadatasToCreate,
|
||||
|
||||
-68
@@ -1,68 +0,0 @@
|
||||
import { type FieldMetadataType, type FromTo } from 'twenty-shared/types';
|
||||
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { recomputeSearchVectorFieldFromSearchFieldMetadatas } from 'src/engine/metadata-modules/flat-object-metadata/utils/recompute-search-vector-field-from-search-field-metadatas.util';
|
||||
import { type FlatSearchFieldMetadata } from 'src/engine/metadata-modules/flat-search-field-metadata/types/flat-search-field-metadata.type';
|
||||
|
||||
export type FieldMetadataUpdateSearchVectorSideEffect = {
|
||||
flatSearchVectorFieldToUpdate:
|
||||
| FlatFieldMetadata<FieldMetadataType.TS_VECTOR>
|
||||
| undefined;
|
||||
};
|
||||
|
||||
type RecomputeSearchVectorOnFieldRenameArgs = {
|
||||
flatObjectMetadata: FlatObjectMetadata;
|
||||
} & FromTo<FlatFieldMetadata, 'flatFieldMetadata'> &
|
||||
Pick<
|
||||
AllFlatEntityMaps,
|
||||
'flatFieldMetadataMaps' | 'flatSearchFieldMetadataMaps'
|
||||
>;
|
||||
|
||||
const EMPTY_SIDE_EFFECT: FieldMetadataUpdateSearchVectorSideEffect = {
|
||||
flatSearchVectorFieldToUpdate: undefined,
|
||||
};
|
||||
|
||||
export const recomputeSearchVectorOnFieldRename = ({
|
||||
fromFlatFieldMetadata,
|
||||
toFlatFieldMetadata,
|
||||
flatObjectMetadata,
|
||||
flatFieldMetadataMaps,
|
||||
flatSearchFieldMetadataMaps,
|
||||
}: RecomputeSearchVectorOnFieldRenameArgs): FieldMetadataUpdateSearchVectorSideEffect => {
|
||||
if (!flatObjectMetadata.isSearchable) {
|
||||
return EMPTY_SIDE_EFFECT;
|
||||
}
|
||||
|
||||
const objectSearchFieldMetadatas =
|
||||
findManyFlatEntityByIdInFlatEntityMapsOrThrow<FlatSearchFieldMetadata>({
|
||||
flatEntityMaps: flatSearchFieldMetadataMaps,
|
||||
flatEntityIds: flatObjectMetadata.searchFieldMetadataIds,
|
||||
});
|
||||
|
||||
const isIndexedField = objectSearchFieldMetadatas.some(
|
||||
(searchFieldMetadata) =>
|
||||
searchFieldMetadata.fieldMetadataId === toFlatFieldMetadata.id,
|
||||
);
|
||||
|
||||
const hasNameChanged =
|
||||
fromFlatFieldMetadata.name !== toFlatFieldMetadata.name;
|
||||
|
||||
if (!isIndexedField || !hasNameChanged) {
|
||||
return EMPTY_SIDE_EFFECT;
|
||||
}
|
||||
|
||||
return {
|
||||
flatSearchVectorFieldToUpdate:
|
||||
recomputeSearchVectorFieldFromSearchFieldMetadatas({
|
||||
flatObjectMetadata,
|
||||
flatFieldMetadataMaps,
|
||||
searchFieldMetadatas: objectSearchFieldMetadatas,
|
||||
overrideFlatFieldMetadataById: new Map([
|
||||
[toFlatFieldMetadata.id, toFlatFieldMetadata],
|
||||
]),
|
||||
}),
|
||||
};
|
||||
};
|
||||
-19
@@ -1,11 +1,9 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { type FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { FieldMetadataExceptionCode } from 'src/engine/metadata-modules/field-metadata/field-metadata.exception';
|
||||
import { type FlatFieldMetadataTypeValidationArgs } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata-type-validator.type';
|
||||
import { type FlatFieldMetadataValidationError } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata-validation-error.type';
|
||||
import { isSafeTsVectorExpression } from 'src/engine/workspace-manager/workspace-migration/utils/remove-sql-injection.util';
|
||||
|
||||
export const validateTsVectorFlatFieldMetadata = ({
|
||||
flatEntityToValidate,
|
||||
@@ -30,22 +28,5 @@ export const validateTsVectorFlatFieldMetadata = ({
|
||||
});
|
||||
}
|
||||
|
||||
const asExpression = flatEntityToValidate.universalSettings?.asExpression;
|
||||
|
||||
if (!isNonEmptyString(asExpression)) {
|
||||
errors.push({
|
||||
code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT,
|
||||
message:
|
||||
'Field type TS_VECTOR must have an expression. This may have failed to be built because record identifier field does not exist or is not of a searchable type.',
|
||||
userFriendlyMessage: msg`Field type TS_VECTOR must have an expression. This may have failed to be built because record identifier field does not exist or is not of a searchable type.`,
|
||||
});
|
||||
} else if (!isSafeTsVectorExpression(asExpression)) {
|
||||
errors.push({
|
||||
code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT,
|
||||
message: 'Field type TS_VECTOR expression is invalid',
|
||||
userFriendlyMessage: msg`The search field expression is invalid.`,
|
||||
});
|
||||
}
|
||||
|
||||
return errors;
|
||||
};
|
||||
|
||||
+19
-29
@@ -1,24 +1,20 @@
|
||||
import { type FieldMetadataType, type FromTo } from 'twenty-shared/types';
|
||||
import { type FromTo } from 'twenty-shared/types';
|
||||
import { isDefined, isSearchableFieldType } from 'twenty-shared/utils';
|
||||
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { recomputeSearchVectorFieldFromSearchFieldMetadatas } from 'src/engine/metadata-modules/flat-object-metadata/utils/recompute-search-vector-field-from-search-field-metadatas.util';
|
||||
import { type FlatSearchFieldMetadata } from 'src/engine/metadata-modules/flat-search-field-metadata/types/flat-search-field-metadata.type';
|
||||
import { buildFlatSearchFieldMetadataForField } from 'src/engine/metadata-modules/flat-search-field-metadata/utils/build-flat-search-field-metadata-for-field.util';
|
||||
import { findTsVectorFlatFieldMetadataForObject } from 'src/engine/metadata-modules/flat-search-field-metadata/utils/find-ts-vector-flat-field-metadata-for-object.util';
|
||||
import { type UniversalFlatSearchFieldMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-search-field-metadata.type';
|
||||
|
||||
export type LabelIdentifierUpdateSearchVectorSideEffect = {
|
||||
flatSearchVectorFieldToUpdate:
|
||||
| FlatFieldMetadata<FieldMetadataType.TS_VECTOR>
|
||||
| undefined;
|
||||
export type LabelIdentifierUpdateSearchFieldMetadataSideEffect = {
|
||||
searchFieldMetadatasToCreate: UniversalFlatSearchFieldMetadata[];
|
||||
};
|
||||
|
||||
type RecomputeSearchVectorOnLabelIdentifierUpdateArgs = FromTo<
|
||||
type ComputeSearchFieldMetadataToCreateOnLabelIdentifierUpdateArgs = FromTo<
|
||||
FlatObjectMetadata,
|
||||
'flatObjectMetadata'
|
||||
> &
|
||||
@@ -27,21 +23,20 @@ type RecomputeSearchVectorOnLabelIdentifierUpdateArgs = FromTo<
|
||||
'flatFieldMetadataMaps' | 'flatSearchFieldMetadataMaps'
|
||||
>;
|
||||
|
||||
const EMPTY_SIDE_EFFECT: LabelIdentifierUpdateSearchVectorSideEffect = {
|
||||
flatSearchVectorFieldToUpdate: undefined,
|
||||
const EMPTY_SIDE_EFFECT: LabelIdentifierUpdateSearchFieldMetadataSideEffect = {
|
||||
searchFieldMetadatasToCreate: [],
|
||||
};
|
||||
|
||||
// Relabeling is additive: it indexes the new label identifier field while preserving the
|
||||
// existing search surface (e.g. the provisioned name row). We never drop a row here so the
|
||||
// previous label identifier stays searchable. Removal of fields from the search surface is
|
||||
// deferred to a follow-up PR.
|
||||
export const recomputeSearchVectorOnLabelIdentifierUpdate = ({
|
||||
// previous label identifier stays searchable. The searchVector column itself is rebuilt
|
||||
// from the resulting rows by the rebuildSearchVector marker in the migration runner.
|
||||
export const computeSearchFieldMetadataToCreateOnLabelIdentifierUpdate = ({
|
||||
fromFlatObjectMetadata,
|
||||
toFlatObjectMetadata,
|
||||
flatFieldMetadataMaps,
|
||||
flatSearchFieldMetadataMaps,
|
||||
}: RecomputeSearchVectorOnLabelIdentifierUpdateArgs): LabelIdentifierUpdateSearchVectorSideEffect => {
|
||||
}: ComputeSearchFieldMetadataToCreateOnLabelIdentifierUpdateArgs): LabelIdentifierUpdateSearchFieldMetadataSideEffect => {
|
||||
const newLabelIdentifierFieldMetadataId =
|
||||
toFlatObjectMetadata.labelIdentifierFieldMetadataId;
|
||||
|
||||
@@ -79,6 +74,15 @@ export const recomputeSearchVectorOnLabelIdentifierUpdate = ({
|
||||
return EMPTY_SIDE_EFFECT;
|
||||
}
|
||||
|
||||
const tsVectorFlatFieldMetadata = findTsVectorFlatFieldMetadataForObject({
|
||||
fieldUniversalIdentifiers: fromFlatObjectMetadata.fieldUniversalIdentifiers,
|
||||
flatFieldMetadataMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(tsVectorFlatFieldMetadata)) {
|
||||
return EMPTY_SIDE_EFFECT;
|
||||
}
|
||||
|
||||
const newLabelIdentifierPosition =
|
||||
existingSearchFieldMetadatas.reduce(
|
||||
(maxPosition, searchFieldMetadata) =>
|
||||
@@ -89,25 +93,11 @@ export const recomputeSearchVectorOnLabelIdentifierUpdate = ({
|
||||
const newSearchFieldMetadata = buildFlatSearchFieldMetadataForField({
|
||||
flatObjectMetadata: fromFlatObjectMetadata,
|
||||
flatFieldMetadata: newLabelIdentifierField,
|
||||
tsVectorFlatFieldMetadata,
|
||||
position: newLabelIdentifierPosition,
|
||||
});
|
||||
|
||||
const nextSearchFieldMetadatas = [
|
||||
...existingSearchFieldMetadatas,
|
||||
{
|
||||
fieldMetadataId: newLabelIdentifierFieldMetadataId,
|
||||
position: newLabelIdentifierPosition,
|
||||
universalIdentifier: newSearchFieldMetadata.universalIdentifier,
|
||||
},
|
||||
];
|
||||
|
||||
return {
|
||||
flatSearchVectorFieldToUpdate:
|
||||
recomputeSearchVectorFieldFromSearchFieldMetadatas({
|
||||
flatObjectMetadata: fromFlatObjectMetadata,
|
||||
flatFieldMetadataMaps,
|
||||
searchFieldMetadatas: nextSearchFieldMetadatas,
|
||||
}),
|
||||
searchFieldMetadatasToCreate: [newSearchFieldMetadata],
|
||||
};
|
||||
};
|
||||
-2
@@ -102,7 +102,6 @@ export const fromUpdateObjectInputToFlatObjectMetadataAndRelatedFlatEntities =
|
||||
flatViewFieldsToCreate,
|
||||
flatViewFieldsToUpdate,
|
||||
otherObjectFlatFieldMetadatasToUpdate,
|
||||
sameObjectFlatFieldMetadatasToUpdate,
|
||||
searchFieldMetadatasToCreate,
|
||||
} = handleFlatObjectMetadataUpdateSideEffect({
|
||||
fromFlatObjectMetadata: existingFlatObjectMetadata,
|
||||
@@ -121,7 +120,6 @@ export const fromUpdateObjectInputToFlatObjectMetadataAndRelatedFlatEntities =
|
||||
flatViewFieldsToCreate,
|
||||
flatViewFieldsToUpdate,
|
||||
otherObjectFlatFieldMetadatasToUpdate,
|
||||
sameObjectFlatFieldMetadatasToUpdate,
|
||||
searchFieldMetadatasToCreate,
|
||||
};
|
||||
};
|
||||
|
||||
+3
-12
@@ -2,10 +2,9 @@ import { type FromTo } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { computeSearchFieldMetadataToCreateOnLabelIdentifierUpdate } from 'src/engine/metadata-modules/flat-object-metadata/utils/compute-search-field-metadata-to-create-on-label-identifier-update.util';
|
||||
import { recomputeIndexAfterFlatObjectMetadataSingularNameUpdate } from 'src/engine/metadata-modules/flat-object-metadata/utils/recompute-index-after-flat-object-metadata-singular-name-update.util';
|
||||
import { recomputeSearchVectorOnLabelIdentifierUpdate } from 'src/engine/metadata-modules/flat-object-metadata/utils/recompute-search-vector-on-label-identifier-update.util';
|
||||
import { recomputeViewFieldIdentifierAfterFlatObjectIdentifierUpdate } from 'src/engine/metadata-modules/flat-object-metadata/utils/recompute-view-field-identifier-after-flat-object-identifier-update.util';
|
||||
import { renameRelatedMorphFieldOnObjectNamesUpdate } from 'src/engine/metadata-modules/flat-object-metadata/utils/rename-related-morph-field-on-object-names-update.util';
|
||||
import { type UniversalFlatFieldMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-field-metadata.type';
|
||||
@@ -15,7 +14,6 @@ import { type UniversalFlatViewField } from 'src/engine/workspace-manager/worksp
|
||||
|
||||
export type FlatObjectMetadataUpdateSideEffects = {
|
||||
otherObjectFlatFieldMetadatasToUpdate: UniversalFlatFieldMetadata[];
|
||||
sameObjectFlatFieldMetadatasToUpdate: UniversalFlatFieldMetadata[];
|
||||
flatViewFieldsToUpdate: UniversalFlatViewField[];
|
||||
flatViewFieldsToCreate: UniversalFlatViewField[];
|
||||
flatIndexMetadatasToUpdate: UniversalFlatIndexMetadata[];
|
||||
@@ -89,20 +87,14 @@ export const handleFlatObjectMetadataUpdateSideEffect = ({
|
||||
flatViewFieldsToUpdate: [],
|
||||
};
|
||||
|
||||
const sameObjectFlatFieldMetadatasToUpdate: FlatFieldMetadata[] = [];
|
||||
|
||||
const { flatSearchVectorFieldToUpdate, searchFieldMetadatasToCreate } =
|
||||
recomputeSearchVectorOnLabelIdentifierUpdate({
|
||||
const { searchFieldMetadatasToCreate } =
|
||||
computeSearchFieldMetadataToCreateOnLabelIdentifierUpdate({
|
||||
fromFlatObjectMetadata,
|
||||
toFlatObjectMetadata,
|
||||
flatFieldMetadataMaps,
|
||||
flatSearchFieldMetadataMaps,
|
||||
});
|
||||
|
||||
if (isDefined(flatSearchVectorFieldToUpdate)) {
|
||||
sameObjectFlatFieldMetadatasToUpdate.push(flatSearchVectorFieldToUpdate);
|
||||
}
|
||||
|
||||
return {
|
||||
flatIndexMetadatasToUpdate: [
|
||||
...morphRelatedFlatIndexesToUpdate,
|
||||
@@ -111,7 +103,6 @@ export const handleFlatObjectMetadataUpdateSideEffect = ({
|
||||
flatViewFieldsToCreate,
|
||||
flatViewFieldsToUpdate,
|
||||
otherObjectFlatFieldMetadatasToUpdate: morphFlatFieldMetadatasToUpdate,
|
||||
sameObjectFlatFieldMetadatasToUpdate,
|
||||
searchFieldMetadatasToCreate,
|
||||
};
|
||||
};
|
||||
|
||||
-112
@@ -1,112 +0,0 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { isFlatFieldMetadataOfType } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-type.util';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { type FlatSearchFieldMetadata } from 'src/engine/metadata-modules/flat-search-field-metadata/types/flat-search-field-metadata.type';
|
||||
import {
|
||||
ObjectMetadataException,
|
||||
ObjectMetadataExceptionCode,
|
||||
} from 'src/engine/metadata-modules/object-metadata/object-metadata.exception';
|
||||
import {
|
||||
buildSearchVectorTargetField,
|
||||
computeSearchVectorAsExpressionFromSearchFieldMetadatas,
|
||||
} from 'src/engine/metadata-modules/flat-search-field-metadata/utils/compute-search-vector-as-expression-from-search-field-metadatas.util';
|
||||
import { SEARCH_VECTOR_FIELD } from 'src/engine/metadata-modules/search-field-metadata/constants/search-vector-field.constants';
|
||||
|
||||
type RecomputeSearchVectorFieldFromSearchFieldMetadatasArgs = {
|
||||
flatObjectMetadata: FlatObjectMetadata;
|
||||
// Post-change searchFieldMetadata rows for the object, carrying the field id and the
|
||||
// per-object position that drives the deterministic asExpression order.
|
||||
searchFieldMetadatas: Pick<
|
||||
FlatSearchFieldMetadata,
|
||||
'fieldMetadataId' | 'position' | 'universalIdentifier'
|
||||
>[];
|
||||
// Takes precedence over the flat maps when resolving an id — for a field created or
|
||||
// renamed in the same migration, whose maps entry is absent or stale.
|
||||
overrideFlatFieldMetadataById?: Map<string, FlatFieldMetadata>;
|
||||
} & Pick<AllFlatEntityMaps, 'flatFieldMetadataMaps'>;
|
||||
|
||||
export const recomputeSearchVectorFieldFromSearchFieldMetadatas = ({
|
||||
flatObjectMetadata,
|
||||
flatFieldMetadataMaps,
|
||||
searchFieldMetadatas,
|
||||
overrideFlatFieldMetadataById,
|
||||
}: RecomputeSearchVectorFieldFromSearchFieldMetadatasArgs):
|
||||
| FlatFieldMetadata<FieldMetadataType.TS_VECTOR>
|
||||
| undefined => {
|
||||
const objectFlatFieldMetadatas =
|
||||
findManyFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityMaps: flatFieldMetadataMaps,
|
||||
flatEntityIds: flatObjectMetadata.fieldIds,
|
||||
});
|
||||
|
||||
const searchVectorField = objectFlatFieldMetadatas.find(
|
||||
(field) => field.name === SEARCH_VECTOR_FIELD.name,
|
||||
);
|
||||
|
||||
if (
|
||||
!isDefined(searchVectorField) ||
|
||||
!isFlatFieldMetadataOfType(searchVectorField, FieldMetadataType.TS_VECTOR)
|
||||
) {
|
||||
throw new ObjectMetadataException(
|
||||
`Search vector field not found for object metadata ${flatObjectMetadata.id}`,
|
||||
ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT,
|
||||
);
|
||||
}
|
||||
|
||||
const targetSearchableFields = searchFieldMetadatas.map(
|
||||
(searchFieldMetadata) => {
|
||||
const { fieldMetadataId, position, universalIdentifier } =
|
||||
searchFieldMetadata;
|
||||
|
||||
const overriddenFlatFieldMetadata =
|
||||
overrideFlatFieldMetadataById?.get(fieldMetadataId);
|
||||
|
||||
const flatFieldMetadata =
|
||||
overriddenFlatFieldMetadata ??
|
||||
findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: fieldMetadataId,
|
||||
flatEntityMaps: flatFieldMetadataMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(flatFieldMetadata)) {
|
||||
throw new ObjectMetadataException(
|
||||
`Field metadata ${fieldMetadataId} referenced by searchFieldMetadata not found for object metadata ${flatObjectMetadata.id}`,
|
||||
ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT,
|
||||
);
|
||||
}
|
||||
|
||||
return buildSearchVectorTargetField(
|
||||
flatFieldMetadata,
|
||||
position,
|
||||
universalIdentifier,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
try {
|
||||
const newAsExpression =
|
||||
computeSearchVectorAsExpressionFromSearchFieldMetadatas(
|
||||
targetSearchableFields,
|
||||
);
|
||||
|
||||
return {
|
||||
...searchVectorField,
|
||||
universalSettings: {
|
||||
...searchVectorField.universalSettings,
|
||||
asExpression: newAsExpression,
|
||||
generatedType: 'STORED',
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
throw new ObjectMetadataException(
|
||||
`Failed to compute search vector column expression for object metadata ${flatObjectMetadata.id}: ${error instanceof Error ? error.message : String(error)}`,
|
||||
ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT,
|
||||
);
|
||||
}
|
||||
};
|
||||
+41
-2
@@ -1,6 +1,8 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { WorkspaceCacheProvider } from 'src/engine/workspace-cache/interfaces/workspace-cache-provider.service';
|
||||
@@ -11,6 +13,7 @@ import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-enti
|
||||
import { FlatSearchFieldMetadataMaps } from 'src/engine/metadata-modules/flat-search-field-metadata/types/flat-search-field-metadata-maps.type';
|
||||
import { fromSearchFieldMetadataEntityToFlatSearchFieldMetadata } from 'src/engine/metadata-modules/flat-search-field-metadata/utils/from-search-field-metadata-entity-to-flat-search-field-metadata.util';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { SEARCH_VECTOR_FIELD } from 'src/engine/metadata-modules/search-field-metadata/constants/search-vector-field.constants';
|
||||
import { SearchFieldMetadataEntity } from 'src/engine/metadata-modules/search-field-metadata/search-field-metadata.entity';
|
||||
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
|
||||
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
|
||||
@@ -56,7 +59,13 @@ export class WorkspaceFlatSearchFieldMetadataMapCacheService extends WorkspaceCa
|
||||
}),
|
||||
this.fieldMetadataRepository.find({
|
||||
where: { workspaceId },
|
||||
select: ['id', 'universalIdentifier'],
|
||||
select: [
|
||||
'id',
|
||||
'universalIdentifier',
|
||||
'name',
|
||||
'type',
|
||||
'objectMetadataId',
|
||||
],
|
||||
withDeleted: true,
|
||||
}),
|
||||
]);
|
||||
@@ -68,12 +77,42 @@ export class WorkspaceFlatSearchFieldMetadataMapCacheService extends WorkspaceCa
|
||||
const fieldMetadataIdToUniversalIdentifierMap =
|
||||
createIdToUniversalIdentifierMap(fieldMetadatas);
|
||||
|
||||
// Each object's single system TS_VECTOR field, used to backfill the FK for
|
||||
// legacy searchFieldMetadata rows still NULL before the 2.18 slow command runs.
|
||||
// TODO: remove this fallback (and the searchVector map) once the minimum
|
||||
// cross-upgrade supported version is past 2.18 — at which point no instance can
|
||||
// still have NULL tsVectorFieldMetadataId rows.
|
||||
const searchVectorFieldIdByObjectMetadataId = new Map<string, string>();
|
||||
|
||||
for (const fieldMetadata of fieldMetadatas) {
|
||||
if (
|
||||
fieldMetadata.type === FieldMetadataType.TS_VECTOR &&
|
||||
fieldMetadata.name === SEARCH_VECTOR_FIELD.name
|
||||
) {
|
||||
searchVectorFieldIdByObjectMetadataId.set(
|
||||
fieldMetadata.objectMetadataId,
|
||||
fieldMetadata.id,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const flatSearchFieldMetadataMaps = createEmptyFlatEntityMaps();
|
||||
|
||||
for (const searchFieldMetadata of existingSearchFieldMetadatas) {
|
||||
const resolvedTsVectorFieldMetadataId =
|
||||
(searchFieldMetadata.tsVectorFieldMetadataId as string | null) ??
|
||||
searchVectorFieldIdByObjectMetadataId.get(
|
||||
searchFieldMetadata.objectMetadataId,
|
||||
);
|
||||
|
||||
const flatSearchFieldMetadata =
|
||||
fromSearchFieldMetadataEntityToFlatSearchFieldMetadata({
|
||||
entity: searchFieldMetadata,
|
||||
entity: isDefined(resolvedTsVectorFieldMetadataId)
|
||||
? {
|
||||
...searchFieldMetadata,
|
||||
tsVectorFieldMetadataId: resolvedTsVectorFieldMetadataId,
|
||||
}
|
||||
: searchFieldMetadata,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
objectMetadataIdToUniversalIdentifierMap,
|
||||
fieldMetadataIdToUniversalIdentifierMap,
|
||||
|
||||
+4
@@ -6,6 +6,7 @@ import { type UniversalFlatSearchFieldMetadata } from 'src/engine/workspace-mana
|
||||
export const buildFlatSearchFieldMetadataForField = ({
|
||||
flatObjectMetadata,
|
||||
flatFieldMetadata,
|
||||
tsVectorFlatFieldMetadata,
|
||||
position,
|
||||
}: {
|
||||
flatObjectMetadata: Pick<
|
||||
@@ -13,6 +14,7 @@ export const buildFlatSearchFieldMetadataForField = ({
|
||||
'applicationUniversalIdentifier' | 'universalIdentifier'
|
||||
>;
|
||||
flatFieldMetadata: { universalIdentifier: string };
|
||||
tsVectorFlatFieldMetadata: { universalIdentifier: string };
|
||||
position: number;
|
||||
}): UniversalFlatSearchFieldMetadata => {
|
||||
const createdAt = new Date().toISOString();
|
||||
@@ -26,5 +28,7 @@ export const buildFlatSearchFieldMetadataForField = ({
|
||||
flatObjectMetadata.applicationUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier: flatObjectMetadata.universalIdentifier,
|
||||
fieldMetadataUniversalIdentifier: flatFieldMetadata.universalIdentifier,
|
||||
tsVectorFieldMetadataUniversalIdentifier:
|
||||
tsVectorFlatFieldMetadata.universalIdentifier,
|
||||
};
|
||||
};
|
||||
|
||||
+9
-5
@@ -15,11 +15,15 @@ export type SearchVectorTargetField = {
|
||||
sortKey: string;
|
||||
};
|
||||
|
||||
export const buildSearchVectorTargetField = (
|
||||
field: { name: string; type: FieldMetadataType },
|
||||
position: number,
|
||||
sortKey: string,
|
||||
): SearchVectorTargetField => ({
|
||||
export const buildSearchVectorTargetField = ({
|
||||
field,
|
||||
position,
|
||||
sortKey,
|
||||
}: {
|
||||
field: { name: string; type: FieldMetadataType };
|
||||
position: number;
|
||||
sortKey: string;
|
||||
}): SearchVectorTargetField => ({
|
||||
name: field.name,
|
||||
type: field.type,
|
||||
position,
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
import { type FieldMetadataType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import {
|
||||
buildSearchVectorTargetField,
|
||||
computeSearchVectorAsExpressionFromSearchFieldMetadatas,
|
||||
} from 'src/engine/metadata-modules/flat-search-field-metadata/utils/compute-search-vector-as-expression-from-search-field-metadatas.util';
|
||||
import { type FlatSearchFieldMetadata } from 'src/engine/metadata-modules/flat-search-field-metadata/types/flat-search-field-metadata.type';
|
||||
|
||||
export const deriveSearchVectorAsExpressionForTsVectorField = ({
|
||||
tsVectorFieldMetadataId,
|
||||
flatSearchFieldMetadataMaps,
|
||||
indexedFieldById,
|
||||
}: {
|
||||
tsVectorFieldMetadataId: string;
|
||||
flatSearchFieldMetadataMaps: FlatEntityMaps<FlatSearchFieldMetadata>;
|
||||
indexedFieldById: ReadonlyMap<
|
||||
string,
|
||||
{ name: string; type: FieldMetadataType }
|
||||
>;
|
||||
}): string => {
|
||||
const targetSearchableFields = Object.values(
|
||||
flatSearchFieldMetadataMaps.byUniversalIdentifier,
|
||||
)
|
||||
.filter(isDefined)
|
||||
.filter(
|
||||
(flatSearchFieldMetadata) =>
|
||||
flatSearchFieldMetadata.tsVectorFieldMetadataId ===
|
||||
tsVectorFieldMetadataId,
|
||||
)
|
||||
.flatMap((flatSearchFieldMetadata) => {
|
||||
const indexedField = indexedFieldById.get(
|
||||
flatSearchFieldMetadata.fieldMetadataId,
|
||||
);
|
||||
|
||||
if (!isDefined(indexedField)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [
|
||||
buildSearchVectorTargetField({
|
||||
field: indexedField,
|
||||
position: flatSearchFieldMetadata.position,
|
||||
sortKey: flatSearchFieldMetadata.universalIdentifier,
|
||||
}),
|
||||
];
|
||||
});
|
||||
|
||||
return computeSearchVectorAsExpressionFromSearchFieldMetadatas(
|
||||
targetSearchableFields,
|
||||
);
|
||||
};
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { SEARCH_VECTOR_FIELD } from 'src/engine/metadata-modules/search-field-metadata/constants/search-vector-field.constants';
|
||||
|
||||
// Resolves the object's single system TS_VECTOR field (the 'searchVector' field) that
|
||||
// every searchFieldMetadata row contributes to.
|
||||
// Could be refactored once https://github.com/twentyhq/twenty/pull/21949 has been merged.
|
||||
export const findTsVectorFlatFieldMetadataForObject = ({
|
||||
fieldUniversalIdentifiers,
|
||||
flatFieldMetadataMaps,
|
||||
}: {
|
||||
fieldUniversalIdentifiers: string[];
|
||||
flatFieldMetadataMaps: FlatEntityMaps<FlatFieldMetadata>;
|
||||
}): FlatFieldMetadata | undefined =>
|
||||
fieldUniversalIdentifiers
|
||||
.map(
|
||||
(fieldUniversalIdentifier) =>
|
||||
flatFieldMetadataMaps.byUniversalIdentifier[fieldUniversalIdentifier],
|
||||
)
|
||||
.find(
|
||||
(flatFieldMetadata) =>
|
||||
isDefined(flatFieldMetadata) &&
|
||||
flatFieldMetadata.type === FieldMetadataType.TS_VECTOR &&
|
||||
flatFieldMetadata.name === SEARCH_VECTOR_FIELD.name,
|
||||
);
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import { type FlatSearchFieldMetadata } from 'src/engine/metadata-modules/flat-search-field-metadata/types/flat-search-field-metadata.type';
|
||||
import { type SearchFieldMetadataDTO } from 'src/engine/metadata-modules/search-field-metadata/dtos/search-field-metadata.dto';
|
||||
|
||||
export const fromFlatSearchFieldMetadataToSearchFieldMetadataDto = (
|
||||
flatSearchFieldMetadata: FlatSearchFieldMetadata,
|
||||
): SearchFieldMetadataDTO => ({
|
||||
id: flatSearchFieldMetadata.id,
|
||||
objectMetadataId: flatSearchFieldMetadata.objectMetadataId,
|
||||
fieldMetadataId: flatSearchFieldMetadata.fieldMetadataId,
|
||||
tsVectorFieldMetadataId: flatSearchFieldMetadata.tsVectorFieldMetadataId,
|
||||
position: flatSearchFieldMetadata.position,
|
||||
createdAt: new Date(flatSearchFieldMetadata.createdAt),
|
||||
updatedAt: new Date(flatSearchFieldMetadata.updatedAt),
|
||||
workspaceId: flatSearchFieldMetadata.workspaceId,
|
||||
});
|
||||
+13
@@ -55,6 +55,18 @@ export const fromSearchFieldMetadataEntityToFlatSearchFieldMetadata = ({
|
||||
);
|
||||
}
|
||||
|
||||
const tsVectorFieldMetadataUniversalIdentifier =
|
||||
fieldMetadataIdToUniversalIdentifierMap.get(
|
||||
searchFieldMetadataEntity.tsVectorFieldMetadataId,
|
||||
);
|
||||
|
||||
if (!isDefined(tsVectorFieldMetadataUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`TS_VECTOR field metadata with id ${searchFieldMetadataEntity.tsVectorFieldMetadataId} not found for searchFieldMetadata ${searchFieldMetadataEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...searchFieldMetadataEntityWithoutRelations,
|
||||
createdAt: searchFieldMetadataEntity.createdAt.toISOString(),
|
||||
@@ -64,5 +76,6 @@ export const fromSearchFieldMetadataEntityToFlatSearchFieldMetadata = ({
|
||||
applicationUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
fieldMetadataUniversalIdentifier,
|
||||
tsVectorFieldMetadataUniversalIdentifier,
|
||||
};
|
||||
};
|
||||
|
||||
+8
@@ -40,6 +40,7 @@ const PARTIAL_ID_FIELD = {
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
fieldPermissionUniversalIdentifiers: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
searchFieldMetadataUniversalIdentifiers: [],
|
||||
} as const satisfies PartialSystemFlatFieldMetadata<FieldMetadataType.UUID>;
|
||||
|
||||
const PARTIAL_CREATED_AT_FIELD = {
|
||||
@@ -69,6 +70,7 @@ const PARTIAL_CREATED_AT_FIELD = {
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
fieldPermissionUniversalIdentifiers: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
searchFieldMetadataUniversalIdentifiers: [],
|
||||
} as const satisfies PartialSystemFlatFieldMetadata<FieldMetadataType.DATE_TIME>;
|
||||
|
||||
const PARTIAL_UPDATED_AT_FIELD = {
|
||||
@@ -98,6 +100,7 @@ const PARTIAL_UPDATED_AT_FIELD = {
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
fieldPermissionUniversalIdentifiers: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
searchFieldMetadataUniversalIdentifiers: [],
|
||||
} as const satisfies PartialSystemFlatFieldMetadata<FieldMetadataType.DATE_TIME>;
|
||||
|
||||
const PARTIAL_DELETED_AT_FIELD = {
|
||||
@@ -127,6 +130,7 @@ const PARTIAL_DELETED_AT_FIELD = {
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
fieldPermissionUniversalIdentifiers: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
searchFieldMetadataUniversalIdentifiers: [],
|
||||
} as const satisfies PartialSystemFlatFieldMetadata<FieldMetadataType.DATE_TIME>;
|
||||
|
||||
const PARTIAL_CREATED_BY_FIELD = {
|
||||
@@ -156,6 +160,7 @@ const PARTIAL_CREATED_BY_FIELD = {
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
fieldPermissionUniversalIdentifiers: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
searchFieldMetadataUniversalIdentifiers: [],
|
||||
} as const satisfies PartialSystemFlatFieldMetadata<FieldMetadataType.ACTOR>;
|
||||
|
||||
const PARTIAL_UPDATED_BY_FIELD = {
|
||||
@@ -185,6 +190,7 @@ const PARTIAL_UPDATED_BY_FIELD = {
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
fieldPermissionUniversalIdentifiers: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
searchFieldMetadataUniversalIdentifiers: [],
|
||||
} as const satisfies PartialSystemFlatFieldMetadata<FieldMetadataType.ACTOR>;
|
||||
|
||||
const PARTIAL_POSITION_FIELD = {
|
||||
@@ -214,6 +220,7 @@ const PARTIAL_POSITION_FIELD = {
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
fieldPermissionUniversalIdentifiers: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
searchFieldMetadataUniversalIdentifiers: [],
|
||||
} as const satisfies PartialSystemFlatFieldMetadata<FieldMetadataType.POSITION>;
|
||||
|
||||
const PARTIAL_SEARCH_VECTOR_FIELD = {
|
||||
@@ -245,6 +252,7 @@ const PARTIAL_SEARCH_VECTOR_FIELD = {
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
fieldPermissionUniversalIdentifiers: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
searchFieldMetadataUniversalIdentifiers: [],
|
||||
} as const satisfies PartialSystemFlatFieldMetadata<FieldMetadataType.TS_VECTOR>;
|
||||
|
||||
export const PARTIAL_SYSTEM_FLAT_FIELD_METADATAS = {
|
||||
|
||||
+22
@@ -30,6 +30,7 @@ import { ObjectRecordCountDTO } from 'src/engine/metadata-modules/object-metadat
|
||||
import { UpdateOneObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/update-object.input';
|
||||
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
||||
import { ObjectRecordCountService } from 'src/engine/metadata-modules/object-metadata/object-record-count.service';
|
||||
import { SearchFieldMetadataDTO } from 'src/engine/metadata-modules/search-field-metadata/dtos/search-field-metadata.dto';
|
||||
import { objectMetadataGraphqlApiExceptionHandler } from 'src/engine/metadata-modules/object-metadata/utils/object-metadata-graphql-api-exception-handler.util';
|
||||
import { resolveObjectMetadataStandardOverride } from 'src/engine/metadata-modules/object-metadata/utils/resolve-object-metadata-standard-override.util';
|
||||
import { PermissionsGraphqlApiExceptionFilter } from 'src/engine/metadata-modules/permissions/utils/permissions-graphql-api-exception.filter';
|
||||
@@ -273,4 +274,25 @@ export class ObjectMetadataResolver {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
@ResolveField(() => [SearchFieldMetadataDTO], { nullable: false })
|
||||
async searchFieldMetadataList(
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
@Parent() objectMetadata: ObjectMetadataDTO,
|
||||
@Context() context: { loaders: IDataloaders },
|
||||
): Promise<SearchFieldMetadataDTO[]> {
|
||||
try {
|
||||
const searchFieldMetadataItems =
|
||||
await context.loaders.searchFieldMetadataLoader.load({
|
||||
objectMetadata,
|
||||
workspaceId: workspace.id,
|
||||
});
|
||||
|
||||
return searchFieldMetadataItems;
|
||||
} catch (error) {
|
||||
objectMetadataGraphqlApiExceptionHandler(error);
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-5
@@ -107,7 +107,6 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
|
||||
const {
|
||||
otherObjectFlatFieldMetadatasToUpdate,
|
||||
sameObjectFlatFieldMetadatasToUpdate,
|
||||
flatObjectMetadataToUpdate,
|
||||
flatIndexMetadatasToUpdate,
|
||||
flatViewFieldsToCreate,
|
||||
@@ -171,10 +170,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
fieldMetadata: {
|
||||
flatEntityToCreate: [],
|
||||
flatEntityToDelete: [],
|
||||
flatEntityToUpdate: [
|
||||
...otherObjectFlatFieldMetadatasToUpdate,
|
||||
...sameObjectFlatFieldMetadatasToUpdate,
|
||||
],
|
||||
flatEntityToUpdate: [...otherObjectFlatFieldMetadatasToUpdate],
|
||||
},
|
||||
viewField: {
|
||||
flatEntityToCreate: flatViewFieldsToCreate,
|
||||
|
||||
+2
-7
@@ -2,7 +2,6 @@ import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { PARTIAL_SYSTEM_FLAT_FIELD_METADATAS } from 'src/engine/metadata-modules/object-metadata/constants/partial-system-flat-field-metadatas.constant';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { type UniversalFlatFieldMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-field-metadata.type';
|
||||
import { type UniversalFlatObjectMetadata } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-object-metadata.type';
|
||||
|
||||
@@ -154,15 +153,11 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
fieldPermissionUniversalIdentifiers: [],
|
||||
universalSettings: null,
|
||||
viewSortUniversalIdentifiers: [],
|
||||
searchFieldMetadataUniversalIdentifiers: [],
|
||||
};
|
||||
|
||||
const searchVectorUniversalSettings: UniversalFlatFieldMetadata<FieldMetadataType.TS_VECTOR>['universalSettings'] =
|
||||
{
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
nameField ? [nameField] : [],
|
||||
),
|
||||
generatedType: 'STORED',
|
||||
};
|
||||
null;
|
||||
|
||||
return {
|
||||
fields: {
|
||||
|
||||
+2
@@ -27,6 +27,8 @@ export const buildDefaultSearchFieldMetadatasForCustomObject = ({
|
||||
const nameSearchFieldMetadata = buildFlatSearchFieldMetadataForField({
|
||||
flatObjectMetadata,
|
||||
flatFieldMetadata: nameField,
|
||||
tsVectorFlatFieldMetadata:
|
||||
defaultFlatFieldForCustomObjectMaps.fields.searchVector,
|
||||
position: 0,
|
||||
});
|
||||
|
||||
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
import { Field, HideField, ObjectType } from '@nestjs/graphql';
|
||||
|
||||
import {
|
||||
Authorize,
|
||||
IDField,
|
||||
QueryOptions,
|
||||
} from '@ptc-org/nestjs-query-graphql';
|
||||
import { IsDateString, IsNotEmpty, IsNumber, IsUUID } from 'class-validator';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
|
||||
@ObjectType('SearchField')
|
||||
@Authorize({
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
authorize: (context: any) => ({
|
||||
workspaceId: { eq: context?.req?.workspace?.id },
|
||||
}),
|
||||
})
|
||||
@QueryOptions({
|
||||
defaultResultSize: 10,
|
||||
disableSort: true,
|
||||
maxResultsSize: 1000,
|
||||
})
|
||||
export class SearchFieldMetadataDTO {
|
||||
@IsUUID()
|
||||
@IsNotEmpty()
|
||||
@IDField(() => UUIDScalarType)
|
||||
id: string;
|
||||
|
||||
objectMetadataId: string;
|
||||
|
||||
@IsUUID()
|
||||
@IsNotEmpty()
|
||||
@Field(() => UUIDScalarType)
|
||||
fieldMetadataId: string;
|
||||
|
||||
@IsUUID()
|
||||
@IsNotEmpty()
|
||||
@Field(() => UUIDScalarType)
|
||||
tsVectorFieldMetadataId: string;
|
||||
|
||||
@IsNumber()
|
||||
@IsNotEmpty()
|
||||
@Field()
|
||||
position: number;
|
||||
|
||||
@IsDateString()
|
||||
@Field()
|
||||
createdAt: Date;
|
||||
|
||||
@IsDateString()
|
||||
@Field()
|
||||
updatedAt: Date;
|
||||
|
||||
@HideField()
|
||||
workspaceId: string;
|
||||
}
|
||||
+2
@@ -3,4 +3,6 @@ export enum SearchFieldMetadataExceptionCode {
|
||||
INVALID_SEARCH_FIELD_METADATA_DATA = 'INVALID_SEARCH_FIELD_METADATA_DATA',
|
||||
OBJECT_METADATA_NOT_FOUND = 'OBJECT_METADATA_NOT_FOUND',
|
||||
FIELD_METADATA_NOT_FOUND = 'FIELD_METADATA_NOT_FOUND',
|
||||
TS_VECTOR_FIELD_METADATA_NOT_FOUND = 'TS_VECTOR_FIELD_METADATA_NOT_FOUND',
|
||||
INVALID_TS_VECTOR_FIELD_METADATA = 'INVALID_TS_VECTOR_FIELD_METADATA',
|
||||
}
|
||||
|
||||
+17
-1
@@ -12,6 +12,7 @@ import {
|
||||
} from 'typeorm';
|
||||
|
||||
import { ADD_UNIVERSAL_IDENTIFIER_AND_APPLICATION_ID_TO_SEARCH_FIELD_METADATA_UPGRADE_COMMAND_NAME } from 'src/database/commands/upgrade-version-command/2-16/add-universal-identifier-and-application-id-to-search-field-metadata-upgrade-command-name.constant';
|
||||
import { ADD_TS_VECTOR_FIELD_METADATA_ID_TO_SEARCH_FIELD_METADATA_UPGRADE_COMMAND_NAME } from 'src/database/commands/upgrade-version-command/2-18/add-ts-vector-field-metadata-id-to-search-field-metadata-upgrade-command-name.constant';
|
||||
import { WasIntroducedInUpgrade } from 'src/engine/core-modules/upgrade/decorators/was-introduced-in-upgrade.decorator';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
@@ -46,10 +47,25 @@ export class SearchFieldMetadataEntity extends SyncableEntity {
|
||||
@Column({ nullable: false, type: 'uuid' })
|
||||
fieldMetadataId: string;
|
||||
|
||||
@ManyToOne(() => FieldMetadataEntity, { onDelete: 'CASCADE' })
|
||||
@ManyToOne(
|
||||
() => FieldMetadataEntity,
|
||||
(fieldMetadata) => fieldMetadata.searchFieldMetadatas,
|
||||
{ onDelete: 'CASCADE' },
|
||||
)
|
||||
@JoinColumn({ name: 'fieldMetadataId' })
|
||||
fieldMetadata: Relation<FieldMetadataEntity>;
|
||||
|
||||
@WasIntroducedInUpgrade({
|
||||
upgradeCommandName:
|
||||
ADD_TS_VECTOR_FIELD_METADATA_ID_TO_SEARCH_FIELD_METADATA_UPGRADE_COMMAND_NAME,
|
||||
})
|
||||
@Column({ nullable: false, type: 'uuid' })
|
||||
tsVectorFieldMetadataId: string;
|
||||
|
||||
@ManyToOne(() => FieldMetadataEntity, { onDelete: 'CASCADE' })
|
||||
@JoinColumn({ name: 'tsVectorFieldMetadataId' })
|
||||
tsVectorFieldMetadata: Relation<FieldMetadataEntity>;
|
||||
|
||||
@Column({ nullable: false, type: 'float' })
|
||||
position: number;
|
||||
|
||||
|
||||
+2
@@ -186,6 +186,8 @@ describe('WorkspaceEntityManager', () => {
|
||||
fieldPermissionUniversalIdentifiers: [],
|
||||
viewSortIds: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
searchFieldMetadataIds: [],
|
||||
searchFieldMetadataUniversalIdentifiers: [],
|
||||
universalSettings: null,
|
||||
};
|
||||
|
||||
|
||||
+2
@@ -109,6 +109,8 @@ describe('WorkspaceRepository', () => {
|
||||
fieldPermissionUniversalIdentifiers: [],
|
||||
viewSortIds: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
searchFieldMetadataIds: [],
|
||||
searchFieldMetadataUniversalIdentifiers: [],
|
||||
universalSettings: null,
|
||||
};
|
||||
|
||||
|
||||
-9
@@ -15,9 +15,6 @@ import {
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
|
||||
export const buildAttachmentStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
@@ -327,12 +324,6 @@ export const buildAttachmentStandardFlatFieldMetadatas = ({
|
||||
icon: 'IconUser',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
-9
@@ -14,9 +14,6 @@ import {
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
|
||||
export const buildBlocklistStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
@@ -190,12 +187,6 @@ export const buildBlocklistStandardFlatFieldMetadatas = ({
|
||||
icon: 'IconUser',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
-9
@@ -14,9 +14,6 @@ import {
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
|
||||
export const buildCalendarChannelEventAssociationStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
@@ -188,12 +185,6 @@ export const buildCalendarChannelEventAssociationStandardFlatFieldMetadatas = ({
|
||||
icon: 'IconUser',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
-9
@@ -14,9 +14,6 @@ import {
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
|
||||
export const buildCalendarEventParticipantStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
@@ -186,12 +183,6 @@ export const buildCalendarEventParticipantStandardFlatFieldMetadatas = ({
|
||||
icon: 'IconUser',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
-9
@@ -13,9 +13,6 @@ import {
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
|
||||
export const buildCalendarEventStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
@@ -182,12 +179,6 @@ export const buildCalendarEventStandardFlatFieldMetadatas = ({
|
||||
icon: 'IconUser',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
-8
@@ -14,10 +14,8 @@ import {
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { CallRecordingRequestStatus } from 'src/modules/call-recording/common/enums/call-recording-request-status.enum';
|
||||
import { CallRecordingStatus } from 'src/modules/call-recording/common/enums/call-recording-status.enum';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
|
||||
export const buildCallRecordingStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
@@ -486,12 +484,6 @@ export const buildCallRecordingStandardFlatFieldMetadatas = ({
|
||||
icon: 'IconUser',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
-9
@@ -15,9 +15,6 @@ import {
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
|
||||
export const buildCompanyStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
@@ -279,12 +276,6 @@ export const buildCompanyStandardFlatFieldMetadatas = ({
|
||||
icon: 'IconUser',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
-9
@@ -14,9 +14,6 @@ import {
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
|
||||
export const buildDashboardStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
@@ -219,12 +216,6 @@ export const buildDashboardStandardFlatFieldMetadatas = ({
|
||||
icon: 'IconUser',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
-9
@@ -14,9 +14,6 @@ import {
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
|
||||
export const buildMessageCampaignStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
@@ -160,12 +157,6 @@ export const buildMessageCampaignStandardFlatFieldMetadatas = ({
|
||||
icon: 'IconSend',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
}),
|
||||
subject: createStandardFieldFlatMetadata({
|
||||
|
||||
-9
@@ -14,9 +14,6 @@ import {
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
|
||||
export const buildMessageChannelMessageAssociationMessageFolderStandardFlatFieldMetadatas =
|
||||
({
|
||||
now,
|
||||
@@ -192,12 +189,6 @@ export const buildMessageChannelMessageAssociationMessageFolderStandardFlatField
|
||||
icon: 'IconUser',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
-8
@@ -14,8 +14,6 @@ import {
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
import { MessageDirection } from 'src/modules/messaging/common/enums/message-direction.enum';
|
||||
|
||||
export const buildMessageChannelMessageAssociationStandardFlatFieldMetadatas =
|
||||
@@ -193,12 +191,6 @@ export const buildMessageChannelMessageAssociationStandardFlatFieldMetadatas =
|
||||
icon: 'IconUser',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
-9
@@ -14,9 +14,6 @@ import {
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
|
||||
export const buildMessageListMemberStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
@@ -234,12 +231,6 @@ export const buildMessageListMemberStandardFlatFieldMetadatas = ({
|
||||
icon: 'IconUser',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
-9
@@ -15,9 +15,6 @@ import {
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
|
||||
export const buildMessageListStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
@@ -269,12 +266,6 @@ export const buildMessageListStandardFlatFieldMetadatas = ({
|
||||
icon: 'IconUsersGroup',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
-9
@@ -15,9 +15,6 @@ import {
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
|
||||
export const buildMessageParticipantStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
@@ -187,12 +184,6 @@ export const buildMessageParticipantStandardFlatFieldMetadatas = ({
|
||||
icon: 'IconUser',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
-9
@@ -14,9 +14,6 @@ import {
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
|
||||
export const buildMessageStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
@@ -183,12 +180,6 @@ export const buildMessageStandardFlatFieldMetadatas = ({
|
||||
icon: 'IconUser',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
-9
@@ -13,9 +13,6 @@ import {
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
|
||||
export const buildMessageThreadStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
@@ -182,12 +179,6 @@ export const buildMessageThreadStandardFlatFieldMetadatas = ({
|
||||
icon: 'IconUser',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
-9
@@ -14,9 +14,6 @@ import {
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
|
||||
export const buildNoteStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
@@ -224,12 +221,6 @@ export const buildNoteStandardFlatFieldMetadatas = ({
|
||||
icon: 'IconUser',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
-9
@@ -15,9 +15,6 @@ import {
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
|
||||
export const buildNoteTargetStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
@@ -191,12 +188,6 @@ export const buildNoteTargetStandardFlatFieldMetadatas = ({
|
||||
icon: 'IconUser',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
-9
@@ -15,9 +15,6 @@ import {
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
|
||||
export const buildOpportunityStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
@@ -295,12 +292,6 @@ export const buildOpportunityStandardFlatFieldMetadatas = ({
|
||||
icon: 'IconUser',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
-9
@@ -17,9 +17,6 @@ import {
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
|
||||
export const buildPersonStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
@@ -538,12 +535,6 @@ export const buildPersonStandardFlatFieldMetadatas = ({
|
||||
icon: 'IconUser',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
-9
@@ -15,9 +15,6 @@ import {
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
|
||||
export const buildTaskStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
@@ -281,12 +278,6 @@ export const buildTaskStandardFlatFieldMetadatas = ({
|
||||
icon: 'IconUser',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
-9
@@ -15,9 +15,6 @@ import {
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
|
||||
export const buildTaskTargetStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
@@ -191,12 +188,6 @@ export const buildTaskTargetStandardFlatFieldMetadatas = ({
|
||||
icon: 'IconUser',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
-9
@@ -15,9 +15,6 @@ import {
|
||||
type CreateStandardFieldArgs,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
|
||||
export const buildTimelineActivityStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
@@ -597,12 +594,6 @@ export const buildTimelineActivityStandardFlatFieldMetadatas = ({
|
||||
icon: 'IconUser',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
-9
@@ -14,9 +14,6 @@ import {
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
|
||||
export const buildWorkflowAutomatedTriggerStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
@@ -186,12 +183,6 @@ export const buildWorkflowAutomatedTriggerStandardFlatFieldMetadatas = ({
|
||||
icon: 'IconUser',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
-9
@@ -15,9 +15,6 @@ import {
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
|
||||
export const buildWorkflowRunStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
@@ -360,12 +357,6 @@ export const buildWorkflowRunStandardFlatFieldMetadatas = ({
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
isUIEditable: false,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
-9
@@ -14,9 +14,6 @@ import {
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
|
||||
export const buildWorkflowStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
@@ -258,12 +255,6 @@ export const buildWorkflowStandardFlatFieldMetadatas = ({
|
||||
icon: 'IconUser',
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
-9
@@ -15,9 +15,6 @@ import {
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
|
||||
export const buildWorkflowVersionStandardFlatFieldMetadatas = ({
|
||||
now,
|
||||
objectName,
|
||||
@@ -288,12 +285,6 @@ export const buildWorkflowVersionStandardFlatFieldMetadatas = ({
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
isUIEditable: false,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
-8
@@ -14,8 +14,6 @@ import {
|
||||
createStandardFieldFlatMetadata,
|
||||
} from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-field-flat-metadata.util';
|
||||
import { createStandardRelationFieldFlatMetadata } from 'src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/create-standard-relation-field-flat-metadata.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
|
||||
import { SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME } from 'src/engine/workspace-manager/twenty-standard-application/constants/search-fields-by-standard-object-name.constant';
|
||||
import { WorkspaceMemberNumberFormatEnum } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
|
||||
|
||||
export const buildWorkspaceMemberStandardFlatFieldMetadatas = ({
|
||||
@@ -457,12 +455,6 @@ export const buildWorkspaceMemberStandardFlatFieldMetadatas = ({
|
||||
isSystem: true,
|
||||
isNullable: true,
|
||||
isUIEditable: false,
|
||||
settings: {
|
||||
generatedType: 'STORED',
|
||||
asExpression: getTsVectorColumnExpressionFromFields(
|
||||
SEARCH_FIELDS_BY_STANDARD_OBJECT_NAME[objectName],
|
||||
),
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
+2
@@ -117,6 +117,8 @@ export const createStandardFieldFlatMetadata = <
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
viewSortIds: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
searchFieldMetadataIds: [],
|
||||
searchFieldMetadataUniversalIdentifiers: [],
|
||||
universalSettings: settings ?? null,
|
||||
};
|
||||
};
|
||||
|
||||
+2
@@ -138,6 +138,8 @@ export const createStandardRelationFieldFlatMetadata = <
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
viewSortIds: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
searchFieldMetadataIds: [],
|
||||
searchFieldMetadataUniversalIdentifiers: [],
|
||||
universalSettings: {
|
||||
...settings,
|
||||
...(junctionTargetFieldUniversalIdentifier && {
|
||||
|
||||
+11
@@ -3,6 +3,7 @@ import { v4 } from 'uuid';
|
||||
|
||||
import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
|
||||
import { type FlatSearchFieldMetadata } from 'src/engine/metadata-modules/flat-search-field-metadata/types/flat-search-field-metadata.type';
|
||||
import { SEARCH_VECTOR_FIELD } from 'src/engine/metadata-modules/search-field-metadata/constants/search-vector-field.constants';
|
||||
import { type AllStandardObjectFieldName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-field-name.type';
|
||||
import { type AllStandardObjectName } from 'src/engine/workspace-manager/twenty-standard-application/types/all-standard-object-name.type';
|
||||
import { type StandardBuilderArgs } from 'src/engine/workspace-manager/twenty-standard-application/types/metadata-standard-buillder-args.type';
|
||||
@@ -56,6 +57,14 @@ export const createStandardSearchFieldFlatMetadata = <
|
||||
flatEntityMaps: flatFieldMetadataMaps,
|
||||
});
|
||||
|
||||
const tsVectorFieldMetadataId =
|
||||
standardObjectMetadataRelatedEntityIds[objectName].fields[
|
||||
SEARCH_VECTOR_FIELD.name as AllStandardObjectFieldName<O>
|
||||
].id;
|
||||
const tsVectorFieldMetadataUniversalIdentifier =
|
||||
objectFields[SEARCH_VECTOR_FIELD.name as keyof typeof objectFields]
|
||||
.universalIdentifier;
|
||||
|
||||
return {
|
||||
id: v4(),
|
||||
universalIdentifier: v4(),
|
||||
@@ -66,6 +75,8 @@ export const createStandardSearchFieldFlatMetadata = <
|
||||
objectMetadataUniversalIdentifier: flatObjectMetadata.universalIdentifier,
|
||||
fieldMetadataId,
|
||||
fieldMetadataUniversalIdentifier: flatFieldMetadata.universalIdentifier,
|
||||
tsVectorFieldMetadataId,
|
||||
tsVectorFieldMetadataUniversalIdentifier,
|
||||
position,
|
||||
workspaceId,
|
||||
createdAt: now,
|
||||
|
||||
+18
-17
@@ -23,15 +23,14 @@ const buildFieldIdByUniversalIdentifierForObjectAction = ({
|
||||
};
|
||||
|
||||
for (const universalFlatFieldMetadata of action.universalFlatFieldMetadatas) {
|
||||
const { universalIdentifier } = universalFlatFieldMetadata;
|
||||
const providedFieldId =
|
||||
fieldMetadataIdByUniversalIdentifier[
|
||||
universalFlatFieldMetadata.universalIdentifier
|
||||
];
|
||||
fieldMetadataIdByUniversalIdentifier[universalIdentifier];
|
||||
|
||||
if (isDefined(providedFieldId)) {
|
||||
fieldIdByUniversalIdentifier[
|
||||
universalFlatFieldMetadata.universalIdentifier
|
||||
] = providedFieldId;
|
||||
fieldIdByUniversalIdentifier[universalIdentifier] = providedFieldId;
|
||||
} else if (!isDefined(fieldIdByUniversalIdentifier[universalIdentifier])) {
|
||||
fieldIdByUniversalIdentifier[universalIdentifier] = v4();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,6 +199,7 @@ export const enrichCreateWorkspaceMigrationActionsWithIds = ({
|
||||
|
||||
if (
|
||||
action.metadataName !== 'fieldMetadata' &&
|
||||
action.metadataName !== 'objectMetadata' &&
|
||||
!isDefined(idByUniversalIdentifier) &&
|
||||
!isDefined(fieldMetadataIdByUniversalIdentifier) &&
|
||||
!isDefined(pageLayoutTabIdByUniversalIdentifier)
|
||||
@@ -209,17 +209,18 @@ export const enrichCreateWorkspaceMigrationActionsWithIds = ({
|
||||
|
||||
switch (action.metadataName) {
|
||||
case 'objectMetadata': {
|
||||
const id = isDefined(idByUniversalIdentifier)
|
||||
? idByUniversalIdentifier[action.flatEntity.universalIdentifier]
|
||||
: undefined;
|
||||
const objectFieldIdByUniversalIdentifier = isDefined(
|
||||
fieldMetadataIdByUniversalIdentifier,
|
||||
)
|
||||
? buildFieldIdByUniversalIdentifierForObjectAction({
|
||||
action,
|
||||
fieldMetadataIdByUniversalIdentifier,
|
||||
})
|
||||
: undefined;
|
||||
const id =
|
||||
(isDefined(idByUniversalIdentifier)
|
||||
? idByUniversalIdentifier[action.flatEntity.universalIdentifier]
|
||||
: undefined) ??
|
||||
action.id ??
|
||||
v4();
|
||||
const objectFieldIdByUniversalIdentifier =
|
||||
buildFieldIdByUniversalIdentifierForObjectAction({
|
||||
action,
|
||||
fieldMetadataIdByUniversalIdentifier:
|
||||
fieldMetadataIdByUniversalIdentifier ?? {},
|
||||
});
|
||||
|
||||
return {
|
||||
...action,
|
||||
|
||||
+13
@@ -21,6 +21,7 @@ import { AllUniversalFlatEntityMaps } from 'src/engine/workspace-manager/workspa
|
||||
import { type MetadataUniversalFlatEntityMaps } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/metadata-universal-flat-entity-maps.type';
|
||||
import { aggregateOrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration/utils/aggregate-orchestrator-actions-report.util';
|
||||
import { computeOrderedMigrationActions } from 'src/engine/workspace-manager/workspace-migration/utils/compute-ordered-migration-actions.util';
|
||||
import { computeSearchVectorRebuildTargetUniversalIdentifiers } from 'src/engine/workspace-manager/workspace-migration/utils/compute-search-vector-rebuild-target-universal-identifiers.util';
|
||||
import { crossEntityTransversalValidation } from 'src/engine/workspace-manager/workspace-migration/utils/cross-entity-transversal-validation.util';
|
||||
import { mergeOrchestratorFailureReports } from 'src/engine/workspace-manager/workspace-migration/utils/merge-orchestrator-failure-reports.util';
|
||||
import { WorkspaceMigrationAgentActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/agent/workspace-migration-agent-actions-builder.service';
|
||||
@@ -390,11 +391,23 @@ export class WorkspaceMigrationBuildOrchestratorService {
|
||||
};
|
||||
}
|
||||
|
||||
const searchVectorUniversalIdentifiersToRebuild =
|
||||
computeSearchVectorRebuildTargetUniversalIdentifiers({
|
||||
orchestratorActionsReport,
|
||||
fromFlatSearchFieldMetadataMaps:
|
||||
fromToAllFlatEntityMaps.flatSearchFieldMetadataMaps?.from,
|
||||
toFlatSearchFieldMetadataMaps:
|
||||
optimisticAllFlatEntityMaps.flatSearchFieldMetadataMaps,
|
||||
toFlatFieldMetadataMaps:
|
||||
optimisticAllFlatEntityMaps.flatFieldMetadataMaps,
|
||||
});
|
||||
|
||||
const { aggregatedOrchestratorActionsReport } =
|
||||
aggregateOrchestratorActionsReport({
|
||||
orchestratorActionsReport,
|
||||
flatFieldMetadataMaps:
|
||||
optimisticAllFlatEntityMaps.flatFieldMetadataMaps,
|
||||
searchVectorUniversalIdentifiersToRebuild,
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
+1
@@ -4,4 +4,5 @@ import { type MetadataUniversalFlatEntityMaps } from 'src/engine/workspace-manag
|
||||
export type AggregateOrchestratorActionsReportArgs = {
|
||||
orchestratorActionsReport: OrchestratorActionsReport;
|
||||
flatFieldMetadataMaps?: MetadataUniversalFlatEntityMaps<'fieldMetadata'>;
|
||||
searchVectorUniversalIdentifiersToRebuild?: Set<string>;
|
||||
};
|
||||
|
||||
+1
@@ -14,6 +14,7 @@ exports[`ALL_UNIVERSAL_FLAT_ENTITY_FOREIGN_KEY_AGGREGATOR_PROPERTIES should matc
|
||||
"kanbanAggregateOperationViewUniversalIdentifiers",
|
||||
"calendarViewUniversalIdentifiers",
|
||||
"mainGroupByFieldMetadataViewUniversalIdentifiers",
|
||||
"searchFieldMetadataUniversalIdentifiers",
|
||||
],
|
||||
"fieldPermission": [],
|
||||
"frontComponent": [],
|
||||
|
||||
+8
@@ -37,6 +37,8 @@ exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect a crea
|
||||
"relationTargetFieldMetadataUniversalIdentifier": null,
|
||||
"relationTargetObjectMetadataId": null,
|
||||
"relationTargetObjectMetadataUniversalIdentifier": null,
|
||||
"searchFieldMetadataIds": [],
|
||||
"searchFieldMetadataUniversalIdentifiers": [],
|
||||
"settings": null,
|
||||
"standardOverrides": null,
|
||||
"type": "TEXT",
|
||||
@@ -102,6 +104,8 @@ exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect a dele
|
||||
"relationTargetFieldMetadataUniversalIdentifier": null,
|
||||
"relationTargetObjectMetadataId": null,
|
||||
"relationTargetObjectMetadataUniversalIdentifier": null,
|
||||
"searchFieldMetadataIds": [],
|
||||
"searchFieldMetadataUniversalIdentifiers": [],
|
||||
"settings": null,
|
||||
"standardOverrides": null,
|
||||
"type": "TEXT",
|
||||
@@ -181,6 +185,8 @@ exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect create
|
||||
"relationTargetFieldMetadataUniversalIdentifier": null,
|
||||
"relationTargetObjectMetadataId": null,
|
||||
"relationTargetObjectMetadataUniversalIdentifier": null,
|
||||
"searchFieldMetadataIds": [],
|
||||
"searchFieldMetadataUniversalIdentifiers": [],
|
||||
"settings": null,
|
||||
"standardOverrides": null,
|
||||
"type": "TEXT",
|
||||
@@ -232,6 +238,8 @@ exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect create
|
||||
"relationTargetFieldMetadataUniversalIdentifier": null,
|
||||
"relationTargetObjectMetadataId": null,
|
||||
"relationTargetObjectMetadataUniversalIdentifier": null,
|
||||
"searchFieldMetadataIds": [],
|
||||
"searchFieldMetadataUniversalIdentifiers": [],
|
||||
"settings": null,
|
||||
"standardOverrides": null,
|
||||
"type": "TEXT",
|
||||
|
||||
+15
@@ -11,6 +11,7 @@ import { type MetadataRelatedFlatEntityMapsKeys } from 'src/engine/metadata-modu
|
||||
import { type MetadataUniversalFlatEntityAndRelatedUniversalFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-related-types.type';
|
||||
import { type MetadataUniversalFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-universal-flat-entity.type';
|
||||
import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
|
||||
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
|
||||
import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
|
||||
import { type UniversalFlatEntityMaps } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-maps.type';
|
||||
import { addUniversalFlatEntityToUniversalFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/add-universal-flat-entity-to-universal-flat-entity-maps-through-mutation-or-throw.util';
|
||||
@@ -22,6 +23,7 @@ type AddUniversalFlatEntityToUniversalFlatEntityAndRelatedEntityMapsThroughMutat
|
||||
metadataName: T;
|
||||
universalFlatEntity: MetadataUniversalFlatEntity<T>;
|
||||
universalFlatEntityAndRelatedMapsToMutate: MetadataUniversalFlatEntityAndRelatedUniversalFlatEntityMaps<T>;
|
||||
skipMissingRelatedEntities?: boolean;
|
||||
};
|
||||
|
||||
export const addUniversalFlatEntityToUniversalFlatEntityAndRelatedEntityMapsThroughMutationOrThrow =
|
||||
@@ -29,6 +31,7 @@ export const addUniversalFlatEntityToUniversalFlatEntityAndRelatedEntityMapsThro
|
||||
metadataName,
|
||||
universalFlatEntity,
|
||||
universalFlatEntityAndRelatedMapsToMutate,
|
||||
skipMissingRelatedEntities = false,
|
||||
}: AddUniversalFlatEntityToUniversalFlatEntityAndRelatedEntityMapsThroughMutationOrThrowArgs<T>) => {
|
||||
const flatEntityMapsKey = getMetadataFlatEntityMapsKey(metadataName);
|
||||
|
||||
@@ -96,6 +99,18 @@ export const addUniversalFlatEntityToUniversalFlatEntityAndRelatedEntityMapsThro
|
||||
continue;
|
||||
}
|
||||
|
||||
if (skipMissingRelatedEntities) {
|
||||
const maybeRelatedUniversalFlatEntity =
|
||||
findFlatEntityByUniversalIdentifier({
|
||||
universalIdentifier: universalForeignKeyValue,
|
||||
flatEntityMaps: relatedUniversalFlatEntityMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(maybeRelatedUniversalFlatEntity)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
const relatedUniversalFlatEntity =
|
||||
findFlatEntityByUniversalIdentifierOrThrow({
|
||||
universalIdentifier: universalForeignKeyValue,
|
||||
|
||||
+18
@@ -13,6 +13,10 @@ import { type MetadataToFlatEntityMapsKey } from 'src/engine/metadata-modules/fl
|
||||
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
|
||||
import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
|
||||
|
||||
export type PreallocatedIdByUniversalIdentifierByMetadataName = Partial<
|
||||
Record<AllMetadataName, Record<string, string>>
|
||||
>;
|
||||
|
||||
type ManyToOneRelationsConfig<T extends AllMetadataName> =
|
||||
(typeof ALL_MANY_TO_ONE_METADATA_RELATIONS)[T];
|
||||
|
||||
@@ -74,6 +78,7 @@ export const resolveUniversalRelationIdentifiersToIds = <
|
||||
metadataName,
|
||||
universalForeignKeyValues,
|
||||
flatEntityMaps,
|
||||
preallocatedIdByUniversalIdentifierByMetadataName,
|
||||
}: {
|
||||
metadataName: T;
|
||||
universalForeignKeyValues: Record<TProvidedKeys, string | null | undefined>;
|
||||
@@ -81,6 +86,7 @@ export const resolveUniversalRelationIdentifiersToIds = <
|
||||
T,
|
||||
TProvidedKeys
|
||||
>;
|
||||
preallocatedIdByUniversalIdentifierByMetadataName?: PreallocatedIdByUniversalIdentifierByMetadataName;
|
||||
}): ResolvedForeignKeyIds<T, TProvidedKeys> => {
|
||||
const relationEntries = ALL_MANY_TO_ONE_METADATA_RELATIONS[metadataName];
|
||||
const result: Record<string, string | null> = {};
|
||||
@@ -131,6 +137,18 @@ export const resolveUniversalRelationIdentifiersToIds = <
|
||||
continue;
|
||||
}
|
||||
|
||||
const preallocatedId = isDefined(universalIdentifierValue)
|
||||
? preallocatedIdByUniversalIdentifierByMetadataName?.[
|
||||
targetMetadataName
|
||||
]?.[universalIdentifierValue]
|
||||
: undefined;
|
||||
|
||||
if (isDefined(preallocatedId)) {
|
||||
result[foreignKey] = preallocatedId;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
const targetEntity = findFlatEntityByUniversalIdentifier<
|
||||
MetadataFlatEntity<typeof targetMetadataName>
|
||||
>({
|
||||
|
||||
+40
-2
@@ -4,15 +4,22 @@ import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-
|
||||
import { SEARCH_VECTOR_FIELD } from 'src/engine/metadata-modules/search-field-metadata/constants/search-vector-field.constants';
|
||||
import { type AggregateOrchestratorActionsReportArgs } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-aggregate-orchestrator-actions-report-args.type';
|
||||
import { type OrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-orchestrator.type';
|
||||
import { WORKSPACE_MIGRATION_ACTION_TYPE } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/constants/workspace-migration-action-type.constant';
|
||||
import { type UniversalUpdateFieldAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/field/types/workspace-migration-field-action';
|
||||
|
||||
export const aggregateOrchestratorActionsReportDeprioritizeSearchVectorUpdateFieldActions =
|
||||
({
|
||||
orchestratorActionsReport,
|
||||
flatFieldMetadataMaps,
|
||||
searchVectorUniversalIdentifiersToRebuild,
|
||||
}: AggregateOrchestratorActionsReportArgs): OrchestratorActionsReport => {
|
||||
assertIsDefinedOrThrow(flatFieldMetadataMaps);
|
||||
|
||||
const rebuildTargetUniversalIdentifiers =
|
||||
searchVectorUniversalIdentifiersToRebuild ?? new Set<string>();
|
||||
|
||||
const coveredVectorUniversalIdentifiers = new Set<string>();
|
||||
|
||||
const updateFieldActions = orchestratorActionsReport.fieldMetadata.update;
|
||||
|
||||
const { searchVectorUpdateFieldActions, otherUpdateFieldActions } =
|
||||
@@ -30,11 +37,22 @@ export const aggregateOrchestratorActionsReportDeprioritizeSearchVectorUpdateFie
|
||||
flatFieldMetadata.name === SEARCH_VECTOR_FIELD.name;
|
||||
|
||||
if (isSearchVectorUpdateFieldAction) {
|
||||
coveredVectorUniversalIdentifiers.add(
|
||||
updateFieldAction.universalIdentifier,
|
||||
);
|
||||
|
||||
const searchVectorUpdateFieldAction =
|
||||
rebuildTargetUniversalIdentifiers.has(
|
||||
updateFieldAction.universalIdentifier,
|
||||
)
|
||||
? { ...updateFieldAction, rebuildSearchVector: true }
|
||||
: updateFieldAction;
|
||||
|
||||
return {
|
||||
...acc,
|
||||
searchVectorUpdateFieldActions: [
|
||||
...acc.searchVectorUpdateFieldActions,
|
||||
updateFieldAction,
|
||||
searchVectorUpdateFieldAction,
|
||||
],
|
||||
};
|
||||
}
|
||||
@@ -53,11 +71,31 @@ export const aggregateOrchestratorActionsReportDeprioritizeSearchVectorUpdateFie
|
||||
},
|
||||
);
|
||||
|
||||
const synthesizedSearchVectorUpdateFieldActions: UniversalUpdateFieldAction[] =
|
||||
[...rebuildTargetUniversalIdentifiers].flatMap(
|
||||
(vectorUniversalIdentifier) =>
|
||||
coveredVectorUniversalIdentifiers.has(vectorUniversalIdentifier)
|
||||
? []
|
||||
: [
|
||||
{
|
||||
type: WORKSPACE_MIGRATION_ACTION_TYPE.update,
|
||||
metadataName: 'fieldMetadata',
|
||||
universalIdentifier: vectorUniversalIdentifier,
|
||||
update: {},
|
||||
rebuildSearchVector: true,
|
||||
},
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
...orchestratorActionsReport,
|
||||
fieldMetadata: {
|
||||
...orchestratorActionsReport.fieldMetadata,
|
||||
update: [...otherUpdateFieldActions, ...searchVectorUpdateFieldActions],
|
||||
update: [
|
||||
...otherUpdateFieldActions,
|
||||
...searchVectorUpdateFieldActions,
|
||||
...synthesizedSearchVectorUpdateFieldActions,
|
||||
],
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
+2
@@ -6,6 +6,7 @@ import { aggregateRelationFieldPairs } from 'src/engine/workspace-manager/worksp
|
||||
export const aggregateOrchestratorActionsReport = ({
|
||||
orchestratorActionsReport,
|
||||
flatFieldMetadataMaps,
|
||||
searchVectorUniversalIdentifiersToRebuild,
|
||||
}: AggregateOrchestratorActionsReportArgs) => {
|
||||
const aggregatedOrchestratorActionsReport = [
|
||||
aggregateNonRelationFieldsIntoObjectActions,
|
||||
@@ -16,6 +17,7 @@ export const aggregateOrchestratorActionsReport = ({
|
||||
aggregator({
|
||||
orchestratorActionsReport: currentOrchestratorActionsReport,
|
||||
flatFieldMetadataMaps,
|
||||
searchVectorUniversalIdentifiersToRebuild,
|
||||
}),
|
||||
orchestratorActionsReport,
|
||||
);
|
||||
|
||||
+5
-3
@@ -5,8 +5,12 @@ export const computeOrderedMigrationActions = (
|
||||
aggregatedOrchestratorActionsReport: OrchestratorActionsReport,
|
||||
): AllUniversalWorkspaceMigrationAction[] => {
|
||||
return [
|
||||
// Object and fields and indexes
|
||||
...aggregatedOrchestratorActionsReport.searchFieldMetadata.delete,
|
||||
...aggregatedOrchestratorActionsReport.searchFieldMetadata.create,
|
||||
...aggregatedOrchestratorActionsReport.searchFieldMetadata.update,
|
||||
///
|
||||
|
||||
// Object and fields and indexes
|
||||
...aggregatedOrchestratorActionsReport.index.delete,
|
||||
...aggregatedOrchestratorActionsReport.fieldMetadata.delete,
|
||||
...aggregatedOrchestratorActionsReport.objectMetadata.delete,
|
||||
@@ -16,8 +20,6 @@ export const computeOrderedMigrationActions = (
|
||||
...aggregatedOrchestratorActionsReport.fieldMetadata.update,
|
||||
...aggregatedOrchestratorActionsReport.index.create,
|
||||
...aggregatedOrchestratorActionsReport.index.update.flat(),
|
||||
...aggregatedOrchestratorActionsReport.searchFieldMetadata.create,
|
||||
...aggregatedOrchestratorActionsReport.searchFieldMetadata.update,
|
||||
///
|
||||
|
||||
// Views
|
||||
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
|
||||
import { type OrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration/types/workspace-migration-orchestrator.type';
|
||||
import { type MetadataUniversalFlatEntityMaps } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/metadata-universal-flat-entity-maps.type';
|
||||
|
||||
export const computeSearchVectorRebuildTargetUniversalIdentifiers = ({
|
||||
orchestratorActionsReport,
|
||||
fromFlatSearchFieldMetadataMaps,
|
||||
toFlatSearchFieldMetadataMaps,
|
||||
toFlatFieldMetadataMaps,
|
||||
}: {
|
||||
orchestratorActionsReport: OrchestratorActionsReport;
|
||||
fromFlatSearchFieldMetadataMaps?: MetadataUniversalFlatEntityMaps<'searchFieldMetadata'>;
|
||||
toFlatSearchFieldMetadataMaps: MetadataUniversalFlatEntityMaps<'searchFieldMetadata'>;
|
||||
toFlatFieldMetadataMaps: MetadataUniversalFlatEntityMaps<'fieldMetadata'>;
|
||||
}): Set<string> => {
|
||||
const searchFieldMetadataActions =
|
||||
orchestratorActionsReport.searchFieldMetadata;
|
||||
|
||||
const emptyFlatSearchFieldMetadataMaps: MetadataUniversalFlatEntityMaps<'searchFieldMetadata'> =
|
||||
{ byUniversalIdentifier: {} };
|
||||
|
||||
const renamedFieldSearchFieldMetadataUniversalIdentifiers =
|
||||
orchestratorActionsReport.fieldMetadata.update
|
||||
.filter((updateAction) => isDefined(updateAction.update.name))
|
||||
.flatMap(
|
||||
(updateAction) =>
|
||||
findFlatEntityByUniversalIdentifier({
|
||||
flatEntityMaps: toFlatFieldMetadataMaps,
|
||||
universalIdentifier: updateAction.universalIdentifier,
|
||||
})?.searchFieldMetadataUniversalIdentifiers ?? [],
|
||||
);
|
||||
|
||||
const candidateFieldMetadataVectorUniversalIdentifiers = new Set<string>(
|
||||
[
|
||||
...searchFieldMetadataActions.create.map(
|
||||
(createAction) =>
|
||||
createAction.flatEntity.tsVectorFieldMetadataUniversalIdentifier,
|
||||
),
|
||||
...searchFieldMetadataActions.update.map(
|
||||
(updateAction) =>
|
||||
findFlatEntityByUniversalIdentifier({
|
||||
flatEntityMaps: toFlatSearchFieldMetadataMaps,
|
||||
universalIdentifier: updateAction.universalIdentifier,
|
||||
})?.tsVectorFieldMetadataUniversalIdentifier,
|
||||
),
|
||||
...searchFieldMetadataActions.delete.map(
|
||||
(deleteAction) =>
|
||||
findFlatEntityByUniversalIdentifier({
|
||||
flatEntityMaps:
|
||||
fromFlatSearchFieldMetadataMaps ??
|
||||
emptyFlatSearchFieldMetadataMaps,
|
||||
universalIdentifier: deleteAction.universalIdentifier,
|
||||
})?.tsVectorFieldMetadataUniversalIdentifier,
|
||||
),
|
||||
...renamedFieldSearchFieldMetadataUniversalIdentifiers.map(
|
||||
(searchFieldMetadataUniversalIdentifier) =>
|
||||
findFlatEntityByUniversalIdentifier({
|
||||
flatEntityMaps: toFlatSearchFieldMetadataMaps,
|
||||
universalIdentifier: searchFieldMetadataUniversalIdentifier,
|
||||
})?.tsVectorFieldMetadataUniversalIdentifier,
|
||||
),
|
||||
].filter(isDefined),
|
||||
);
|
||||
|
||||
const fieldUniversalIdentifiersBeingCreatedOrDeleted = new Set<string>([
|
||||
...orchestratorActionsReport.fieldMetadata.create.map(
|
||||
(createFieldAction) => createFieldAction.flatEntity.universalIdentifier,
|
||||
),
|
||||
...orchestratorActionsReport.objectMetadata.create.flatMap(
|
||||
(createObjectAction) =>
|
||||
createObjectAction.universalFlatFieldMetadatas.map(
|
||||
(universalFlatFieldMetadata) =>
|
||||
universalFlatFieldMetadata.universalIdentifier,
|
||||
),
|
||||
),
|
||||
...orchestratorActionsReport.fieldMetadata.delete.map(
|
||||
(deleteFieldAction) => deleteFieldAction.universalIdentifier,
|
||||
),
|
||||
]);
|
||||
|
||||
return new Set(
|
||||
[...candidateFieldMetadataVectorUniversalIdentifiers].filter(
|
||||
(vectorUniversalIdentifier) =>
|
||||
!fieldUniversalIdentifiersBeingCreatedOrDeleted.has(
|
||||
vectorUniversalIdentifier,
|
||||
),
|
||||
),
|
||||
);
|
||||
};
|
||||
+6
-2
@@ -23,7 +23,9 @@ export type UniversalCreateFieldAction =
|
||||
};
|
||||
|
||||
export type UniversalUpdateFieldAction =
|
||||
BaseUniversalUpdateWorkspaceMigrationAction<'fieldMetadata'>;
|
||||
BaseUniversalUpdateWorkspaceMigrationAction<'fieldMetadata'> & {
|
||||
rebuildSearchVector?: boolean;
|
||||
};
|
||||
|
||||
export type UniversalDeleteFieldAction =
|
||||
BaseUniversalDeleteWorkspaceMigrationAction<'fieldMetadata'>;
|
||||
@@ -35,7 +37,9 @@ export type FlatCreateFieldAction =
|
||||
};
|
||||
|
||||
export type FlatUpdateFieldAction =
|
||||
BaseFlatUpdateWorkspaceMigrationAction<'fieldMetadata'>;
|
||||
BaseFlatUpdateWorkspaceMigrationAction<'fieldMetadata'> & {
|
||||
rebuildSearchVector?: boolean;
|
||||
};
|
||||
|
||||
export type FlatDeleteFieldAction =
|
||||
BaseFlatDeleteWorkspaceMigrationAction<'fieldMetadata'>;
|
||||
|
||||
+34
@@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { msg, t } from '@lingui/core/macro';
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
|
||||
@@ -70,6 +71,39 @@ export class FlatSearchFieldMetadataValidatorService {
|
||||
});
|
||||
}
|
||||
|
||||
const flatTsVectorFieldMetadata = findFlatEntityByUniversalIdentifier({
|
||||
universalIdentifier:
|
||||
flatSearchFieldMetadataToValidate.tsVectorFieldMetadataUniversalIdentifier,
|
||||
flatEntityMaps: flatFieldMetadataMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(flatTsVectorFieldMetadata)) {
|
||||
validationResult.errors.push({
|
||||
code: SearchFieldMetadataExceptionCode.TS_VECTOR_FIELD_METADATA_NOT_FOUND,
|
||||
message: t`TS_VECTOR field metadata not found`,
|
||||
userFriendlyMessage: msg`Search vector field not found`,
|
||||
});
|
||||
} else {
|
||||
if (flatTsVectorFieldMetadata.type !== FieldMetadataType.TS_VECTOR) {
|
||||
validationResult.errors.push({
|
||||
code: SearchFieldMetadataExceptionCode.INVALID_TS_VECTOR_FIELD_METADATA,
|
||||
message: t`TS_VECTOR field metadata must be of type TS_VECTOR`,
|
||||
userFriendlyMessage: msg`Search vector field must be a search vector`,
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
flatTsVectorFieldMetadata.objectMetadataUniversalIdentifier !==
|
||||
flatSearchFieldMetadataToValidate.objectMetadataUniversalIdentifier
|
||||
) {
|
||||
validationResult.errors.push({
|
||||
code: SearchFieldMetadataExceptionCode.INVALID_TS_VECTOR_FIELD_METADATA,
|
||||
message: t`TS_VECTOR field metadata must belong to the same object`,
|
||||
userFriendlyMessage: msg`Search vector field must belong to the same object`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const flatObjectMetadata = findFlatEntityByUniversalIdentifier({
|
||||
universalIdentifier:
|
||||
flatSearchFieldMetadataToValidate.objectMetadataUniversalIdentifier,
|
||||
|
||||
+56
-44
@@ -15,12 +15,14 @@ import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/
|
||||
import { computeCompositeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util';
|
||||
import { getCompositeTypeOrThrow } from 'src/engine/metadata-modules/field-metadata/utils/get-composite-type-or-throw.util';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { findManyFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-many-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
|
||||
import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { isCompositeFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-composite-flat-field-metadata.util';
|
||||
import { isEnumFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-enum-flat-field-metadata.util';
|
||||
import { isFlatFieldMetadataOfType } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-type.util';
|
||||
import { isMorphOrRelationFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-morph-or-relation-flat-field-metadata.util';
|
||||
import { deriveSearchVectorAsExpressionForTsVectorField } from 'src/engine/metadata-modules/flat-search-field-metadata/utils/derive-search-vector-as-expression-for-ts-vector-field.util';
|
||||
import { FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { WorkspaceSchemaManagerService } from 'src/engine/twenty-orm/workspace-schema-manager/workspace-schema-manager.service';
|
||||
import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util';
|
||||
@@ -124,6 +126,7 @@ export class UpdateFieldActionHandlerService extends WorkspaceMigrationRunnerAct
|
||||
metadataName: 'fieldMetadata',
|
||||
entityId: flatFieldMetadata.id,
|
||||
update,
|
||||
rebuildSearchVector: action.rebuildSearchVector,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -161,7 +164,11 @@ export class UpdateFieldActionHandlerService extends WorkspaceMigrationRunnerAct
|
||||
const {
|
||||
flatAction,
|
||||
queryRunner,
|
||||
allFlatEntityMaps: { flatObjectMetadataMaps, flatFieldMetadataMaps },
|
||||
allFlatEntityMaps: {
|
||||
flatObjectMetadataMaps,
|
||||
flatFieldMetadataMaps,
|
||||
flatSearchFieldMetadataMaps,
|
||||
},
|
||||
workspaceId,
|
||||
} = context;
|
||||
const { entityId, update } = flatAction;
|
||||
@@ -239,49 +246,6 @@ export class UpdateFieldActionHandlerService extends WorkspaceMigrationRunnerAct
|
||||
}
|
||||
|
||||
if (isDefined(update.settings)) {
|
||||
// Handle asExpression/generatedType change (for TS_VECTOR fields)
|
||||
if (
|
||||
isFlatFieldMetadataOfType(
|
||||
optimisticFlatFieldMetadata,
|
||||
FieldMetadataType.TS_VECTOR,
|
||||
)
|
||||
) {
|
||||
const fromSettings =
|
||||
optimisticFlatFieldMetadata.settings as FieldMetadataSettingsMapping['TS_VECTOR'];
|
||||
const toSettings =
|
||||
update.settings as FieldMetadataSettingsMapping['TS_VECTOR'];
|
||||
|
||||
if (
|
||||
isDefined(toSettings?.asExpression) &&
|
||||
(toSettings.asExpression !== fromSettings?.asExpression ||
|
||||
toSettings.generatedType !== fromSettings?.generatedType)
|
||||
) {
|
||||
await this.workspaceSchemaManagerService.columnManager.dropColumns({
|
||||
queryRunner,
|
||||
schemaName,
|
||||
tableName,
|
||||
columnNames: [optimisticFlatFieldMetadata.name],
|
||||
});
|
||||
await this.workspaceSchemaManagerService.columnManager.addColumns({
|
||||
queryRunner,
|
||||
schemaName,
|
||||
tableName,
|
||||
columnDefinitions: [
|
||||
{
|
||||
name: optimisticFlatFieldMetadata.name,
|
||||
type: 'tsvector',
|
||||
...toSettings,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
optimisticFlatFieldMetadata = {
|
||||
...optimisticFlatFieldMetadata,
|
||||
settings: toSettings,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Handle onDelete change (for morph/relation fields) order matters
|
||||
if (isMorphOrRelationFlatFieldMetadata(optimisticFlatFieldMetadata)) {
|
||||
const fromSettings = optimisticFlatFieldMetadata.settings;
|
||||
@@ -357,6 +321,54 @@ export class UpdateFieldActionHandlerService extends WorkspaceMigrationRunnerAct
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
flatAction.rebuildSearchVector === true &&
|
||||
isFlatFieldMetadataOfType(
|
||||
optimisticFlatFieldMetadata,
|
||||
FieldMetadataType.TS_VECTOR,
|
||||
)
|
||||
) {
|
||||
const indexedFieldById = new Map(
|
||||
findManyFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityMaps: flatFieldMetadataMaps,
|
||||
flatEntityIds: flatObjectMetadata.fieldIds,
|
||||
}).map((indexedFlatFieldMetadata) => [
|
||||
indexedFlatFieldMetadata.id,
|
||||
{
|
||||
name: indexedFlatFieldMetadata.name,
|
||||
type: indexedFlatFieldMetadata.type,
|
||||
},
|
||||
]),
|
||||
);
|
||||
|
||||
const searchVectorAsExpression =
|
||||
deriveSearchVectorAsExpressionForTsVectorField({
|
||||
tsVectorFieldMetadataId: optimisticFlatFieldMetadata.id,
|
||||
flatSearchFieldMetadataMaps,
|
||||
indexedFieldById,
|
||||
});
|
||||
|
||||
const columnDefinitions = generateColumnDefinitions({
|
||||
flatFieldMetadata: optimisticFlatFieldMetadata,
|
||||
flatObjectMetadata,
|
||||
workspaceId,
|
||||
searchVectorAsExpression,
|
||||
});
|
||||
|
||||
await this.workspaceSchemaManagerService.columnManager.dropColumns({
|
||||
queryRunner,
|
||||
schemaName,
|
||||
tableName,
|
||||
columnNames: [optimisticFlatFieldMetadata.name],
|
||||
});
|
||||
await this.workspaceSchemaManagerService.columnManager.addColumns({
|
||||
queryRunner,
|
||||
schemaName,
|
||||
tableName,
|
||||
columnDefinitions,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async handleFieldNameUpdate({
|
||||
|
||||
+1
@@ -135,6 +135,7 @@ export const fromUniversalFlatFieldMetadataToFlatFieldMetadata = ({
|
||||
mainGroupByFieldMetadataViewIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
viewSortIds: [],
|
||||
searchFieldMetadataIds: [],
|
||||
...emptyUniversalForeignKeyAggregators,
|
||||
};
|
||||
};
|
||||
|
||||
+22
-1
@@ -1,5 +1,6 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { WorkspaceMigrationRunnerActionHandler } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/interfaces/workspace-migration-runner-action-handler-service.interface';
|
||||
@@ -7,6 +8,8 @@ import { WorkspaceMigrationRunnerActionHandler } from 'src/engine/workspace-mana
|
||||
import { ALL_METADATA_ENTITY_BY_METADATA_NAME } from 'src/engine/metadata-modules/flat-entity/constant/all-metadata-entity-by-metadata-name.constant';
|
||||
import { isCompositeFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-composite-flat-field-metadata.util';
|
||||
import { isEnumFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-enum-flat-field-metadata.util';
|
||||
import { isFlatFieldMetadataOfType } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-type.util';
|
||||
import { deriveSearchVectorAsExpressionForTsVectorField } from 'src/engine/metadata-modules/flat-search-field-metadata/utils/derive-search-vector-as-expression-for-ts-vector-field.util';
|
||||
import { WorkspaceSchemaManagerService } from 'src/engine/twenty-orm/workspace-schema-manager/workspace-schema-manager.service';
|
||||
import {
|
||||
FlatCreateObjectAction,
|
||||
@@ -117,7 +120,7 @@ export class CreateObjectActionHandlerService extends WorkspaceMigrationRunnerAc
|
||||
async executeForWorkspaceSchema(
|
||||
context: WorkspaceMigrationActionRunnerContext<FlatCreateObjectAction>,
|
||||
): Promise<void> {
|
||||
const { flatAction, queryRunner, workspaceId } = context;
|
||||
const { flatAction, queryRunner, workspaceId, allFlatEntityMaps } = context;
|
||||
const { flatEntity: flatObjectMetadata, flatFieldMetadatas } = flatAction;
|
||||
|
||||
const { schemaName, tableName } = getWorkspaceSchemaContextForMigration({
|
||||
@@ -125,11 +128,29 @@ export class CreateObjectActionHandlerService extends WorkspaceMigrationRunnerAc
|
||||
objectMetadata: flatObjectMetadata,
|
||||
});
|
||||
|
||||
const indexedFieldById = new Map(
|
||||
flatFieldMetadatas.map((flatFieldMetadata) => [
|
||||
flatFieldMetadata.id,
|
||||
{ name: flatFieldMetadata.name, type: flatFieldMetadata.type },
|
||||
]),
|
||||
);
|
||||
|
||||
const columnDefinitions = flatFieldMetadatas.flatMap((flatFieldMetadata) =>
|
||||
generateColumnDefinitions({
|
||||
flatFieldMetadata,
|
||||
flatObjectMetadata,
|
||||
workspaceId,
|
||||
searchVectorAsExpression: isFlatFieldMetadataOfType(
|
||||
flatFieldMetadata,
|
||||
FieldMetadataType.TS_VECTOR,
|
||||
)
|
||||
? deriveSearchVectorAsExpressionForTsVectorField({
|
||||
tsVectorFieldMetadataId: flatFieldMetadata.id,
|
||||
flatSearchFieldMetadataMaps:
|
||||
allFlatEntityMaps.flatSearchFieldMetadataMaps,
|
||||
indexedFieldById,
|
||||
})
|
||||
: undefined,
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
+5
-2
@@ -4,11 +4,11 @@ import { v4 } from 'uuid';
|
||||
|
||||
import { WorkspaceMigrationRunnerActionHandler } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/interfaces/workspace-migration-runner-action-handler-service.interface';
|
||||
|
||||
import { resolveUniversalRelationIdentifiersToIds } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-universal-relation-identifiers-to-ids.util';
|
||||
import {
|
||||
FlatCreateSearchFieldMetadataAction,
|
||||
UniversalCreateSearchFieldMetadataAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/search-field-metadata/types/workspace-migration-search-field-metadata-action.type';
|
||||
import { resolveUniversalRelationIdentifiersToIds } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-universal-relation-identifiers-to-ids.util';
|
||||
import {
|
||||
WorkspaceMigrationActionRunnerArgs,
|
||||
WorkspaceMigrationActionRunnerContext,
|
||||
@@ -24,12 +24,14 @@ export class CreateSearchFieldMetadataActionHandlerService extends WorkspaceMigr
|
||||
allFlatEntityMaps,
|
||||
flatApplication,
|
||||
workspaceId,
|
||||
preallocatedIdByUniversalIdentifierByMetadataName,
|
||||
}: WorkspaceMigrationActionRunnerArgs<UniversalCreateSearchFieldMetadataAction>): Promise<FlatCreateSearchFieldMetadataAction> {
|
||||
const { objectMetadataId, fieldMetadataId } =
|
||||
const { objectMetadataId, fieldMetadataId, tsVectorFieldMetadataId } =
|
||||
resolveUniversalRelationIdentifiersToIds({
|
||||
flatEntityMaps: allFlatEntityMaps,
|
||||
metadataName: action.metadataName,
|
||||
universalForeignKeyValues: action.flatEntity,
|
||||
preallocatedIdByUniversalIdentifierByMetadataName,
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -38,6 +40,7 @@ export class CreateSearchFieldMetadataActionHandlerService extends WorkspaceMigr
|
||||
...action.flatEntity,
|
||||
objectMetadataId,
|
||||
fieldMetadataId,
|
||||
tsVectorFieldMetadataId,
|
||||
id: action.id ?? v4(),
|
||||
applicationId: flatApplication.id,
|
||||
workspaceId,
|
||||
|
||||
+5
@@ -23,6 +23,7 @@ import {
|
||||
WorkspaceMigrationRunnerExceptionCode,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/exceptions/workspace-migration-runner.exception';
|
||||
import { WorkspaceMigrationRunnerActionHandlerRegistryService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/registry/workspace-migration-runner-action-handler-registry.service';
|
||||
import { buildPreallocatedIdByUniversalIdentifierFromActions } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/utils/build-preallocated-id-by-universal-identifier-from-actions.util';
|
||||
import { type AfterCommitSideEffect } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/types/after-commit-side-effect.type';
|
||||
import { type MetadataEvent } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/types/metadata-event';
|
||||
|
||||
@@ -281,6 +282,9 @@ export class WorkspaceMigrationRunnerService {
|
||||
});
|
||||
}
|
||||
|
||||
const preallocatedIdByUniversalIdentifierByMetadataName =
|
||||
buildPreallocatedIdByUniversalIdentifierFromActions(actions);
|
||||
|
||||
this.logger.perfTime('Runner', 'Transaction execution');
|
||||
|
||||
await queryRunner.connect();
|
||||
@@ -313,6 +317,7 @@ export class WorkspaceMigrationRunnerService {
|
||||
allFlatEntityMaps,
|
||||
queryRunner,
|
||||
workspaceId,
|
||||
preallocatedIdByUniversalIdentifierByMetadataName,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
+2
@@ -2,6 +2,7 @@ import { type QueryRunner } from 'typeorm';
|
||||
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { type PreallocatedIdByUniversalIdentifierByMetadataName } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-universal-relation-identifiers-to-ids.util';
|
||||
import {
|
||||
type AllFlatWorkspaceMigrationAction,
|
||||
type AllUniversalWorkspaceMigrationAction,
|
||||
@@ -15,6 +16,7 @@ export type WorkspaceMigrationActionRunnerArgs<
|
||||
allFlatEntityMaps: AllFlatEntityMaps;
|
||||
workspaceId: string;
|
||||
flatApplication: FlatApplication;
|
||||
preallocatedIdByUniversalIdentifierByMetadataName?: PreallocatedIdByUniversalIdentifierByMetadataName;
|
||||
};
|
||||
|
||||
export type WorkspaceMigrationActionRunnerContext<
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user