From 73a7a83a758815c20865367bbde4aedd1d02f120 Mon Sep 17 00:00:00 2001 From: Romain Gilliotte Date: Mon, 13 Jun 2022 20:22:45 +0200 Subject: [PATCH 1/3] feat: mark relations as read only when the fk they depend on is readonly --- .../src/agent/utils/forest-schema/generator-fields.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/agent/src/agent/utils/forest-schema/generator-fields.ts b/packages/agent/src/agent/utils/forest-schema/generator-fields.ts index f07b77fc48..2ccbb7f0cc 100644 --- a/packages/agent/src/agent/utils/forest-schema/generator-fields.ts +++ b/packages/agent/src/agent/utils/forest-schema/generator-fields.ts @@ -107,6 +107,7 @@ export default class SchemaGeneratorFields { } return { + ...baseSchema, type: [keySchema.columnType as PrimitiveTypes], defaultValue: null, isFilterable: false, @@ -115,7 +116,6 @@ export default class SchemaGeneratorFields { isSortable: false, validations: [], reference: `${foreignCollection.name}.${key}`, - ...baseSchema, }; } @@ -137,15 +137,16 @@ export default class SchemaGeneratorFields { const keySchema = collection.schema.fields[key] as ColumnSchema; return { + ...baseSchema, type: keySchema.columnType as PrimitiveTypes, defaultValue: null, isFilterable: SchemaGeneratorFields.isForeignCollectionFilterable(foreignCollection), isPrimaryKey: false, isRequired: false, + isReadOnly: Boolean(keySchema.isReadOnly), isSortable: Boolean(keySchema.isSortable), validations: [], reference: `${foreignCollection.name}.${key}`, - ...baseSchema, }; } @@ -159,15 +160,16 @@ export default class SchemaGeneratorFields { const keySchema = collection.schema.fields[key] as ColumnSchema; return { + ...baseSchema, type: keySchema.columnType as PrimitiveTypes, defaultValue: keySchema.defaultValue ?? null, isFilterable: SchemaGeneratorFields.isForeignCollectionFilterable(foreignCollection), isPrimaryKey: Boolean(keySchema.isPrimaryKey), isRequired: keySchema.validation?.some(v => v.operator === 'Present') ?? false, + isReadOnly: Boolean(keySchema.isReadOnly), isSortable: Boolean(keySchema.isSortable), validations: FrontendValidationUtils.convertValidationList(keySchema.validation), reference: `${foreignCollection.name}.${relation.foreignKeyTarget}`, - ...baseSchema, }; } From e30621c3348549e4b558c167840eb8114b915ded Mon Sep 17 00:00:00 2001 From: Romain Gilliotte Date: Tue, 14 Jun 2022 10:03:28 +0200 Subject: [PATCH 2/3] test: coverage --- .../utils/forest-schema/generator-fields_one-to-many.test.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/agent/test/agent/utils/forest-schema/generator-fields_one-to-many.test.ts b/packages/agent/test/agent/utils/forest-schema/generator-fields_one-to-many.test.ts index 6cecedeffa..95c84b38b3 100644 --- a/packages/agent/test/agent/utils/forest-schema/generator-fields_one-to-many.test.ts +++ b/packages/agent/test/agent/utils/forest-schema/generator-fields_one-to-many.test.ts @@ -16,6 +16,7 @@ describe('SchemaGeneratorFields > One to Many', () => { }), authorId: factories.columnSchema.build({ columnType: 'Uuid', + isReadOnly: true, }), }, }), @@ -47,6 +48,7 @@ describe('SchemaGeneratorFields > One to Many', () => { inverseOf: 'writtenBooks', reference: 'persons.personsPk', relationship: 'BelongsTo', + isReadOnly: true, type: 'Uuid', }); }); From 56efa3e58c9b20336c7d97b95324a1c300f3175d Mon Sep 17 00:00:00 2001 From: Romain Gilliotte Date: Tue, 14 Jun 2022 10:45:29 +0200 Subject: [PATCH 3/3] fix: clean up --- .../utils/forest-schema/generator-fields.ts | 56 +++++++++++-------- .../generator-fields_many-to-many.test.ts | 8 +-- .../generator-fields_one-to-many.test.ts | 2 +- .../generator-fields_one-to-one.test.ts | 5 +- 4 files changed, 40 insertions(+), 31 deletions(-) diff --git a/packages/agent/src/agent/utils/forest-schema/generator-fields.ts b/packages/agent/src/agent/utils/forest-schema/generator-fields.ts index 2ccbb7f0cc..309496abef 100644 --- a/packages/agent/src/agent/utils/forest-schema/generator-fields.ts +++ b/packages/agent/src/agent/utils/forest-schema/generator-fields.ts @@ -95,27 +95,37 @@ export default class SchemaGeneratorFields { foreignCollection: Collection, baseSchema: ForestServerField, ): ForestServerField { - let key: string; - let keySchema: ColumnSchema; + let targetName: string; + let targetField: ColumnSchema; + let isReadOnly: boolean; if (relation.type === 'OneToMany') { - key = relation.originKeyTarget; - keySchema = collection.schema.fields[key] as ColumnSchema; + targetName = relation.originKeyTarget; + targetField = collection.schema.fields[targetName] as ColumnSchema; + + const originKey = foreignCollection.schema.fields[relation.originKey] as ColumnSchema; + isReadOnly = originKey.isReadOnly; } else { - key = relation.foreignKeyTarget; - keySchema = foreignCollection.schema.fields[key] as ColumnSchema; + targetName = relation.foreignKeyTarget; + targetField = foreignCollection.schema.fields[targetName] as ColumnSchema; + + const throughSchema = collection.dataSource.getCollection(relation.throughCollection).schema; + const foreignKey = throughSchema.fields[relation.foreignKey] as ColumnSchema; + const originKey = throughSchema.fields[relation.originKey] as ColumnSchema; + isReadOnly = originKey.isReadOnly || foreignKey.isReadOnly; } return { ...baseSchema, - type: [keySchema.columnType as PrimitiveTypes], + type: [targetField.columnType as PrimitiveTypes], defaultValue: null, isFilterable: false, isPrimaryKey: false, isRequired: false, + isReadOnly: Boolean(isReadOnly), isSortable: false, validations: [], - reference: `${foreignCollection.name}.${key}`, + reference: `${foreignCollection.name}.${targetName}`, }; } @@ -133,20 +143,20 @@ export default class SchemaGeneratorFields { foreignCollection: Collection, baseSchema: ForestServerField, ): ForestServerField { - const key = relation.originKeyTarget; - const keySchema = collection.schema.fields[key] as ColumnSchema; + const targetField = collection.schema.fields[relation.originKeyTarget] as ColumnSchema; + const keyField = foreignCollection.schema.fields[relation.originKey] as ColumnSchema; return { ...baseSchema, - type: keySchema.columnType as PrimitiveTypes, + type: keyField.columnType as PrimitiveTypes, defaultValue: null, isFilterable: SchemaGeneratorFields.isForeignCollectionFilterable(foreignCollection), isPrimaryKey: false, isRequired: false, - isReadOnly: Boolean(keySchema.isReadOnly), - isSortable: Boolean(keySchema.isSortable), + isReadOnly: Boolean(keyField.isReadOnly), + isSortable: Boolean(targetField.isSortable), validations: [], - reference: `${foreignCollection.name}.${key}`, + reference: `${foreignCollection.name}.${relation.originKeyTarget}`, }; } @@ -156,19 +166,18 @@ export default class SchemaGeneratorFields { foreignCollection: Collection, baseSchema: ForestServerField, ): ForestServerField { - const key = relation.foreignKey; - const keySchema = collection.schema.fields[key] as ColumnSchema; + const keyField = collection.schema.fields[relation.foreignKey] as ColumnSchema; return { ...baseSchema, - type: keySchema.columnType as PrimitiveTypes, - defaultValue: keySchema.defaultValue ?? null, + type: keyField.columnType as PrimitiveTypes, + defaultValue: keyField.defaultValue ?? null, isFilterable: SchemaGeneratorFields.isForeignCollectionFilterable(foreignCollection), - isPrimaryKey: Boolean(keySchema.isPrimaryKey), - isRequired: keySchema.validation?.some(v => v.operator === 'Present') ?? false, - isReadOnly: Boolean(keySchema.isReadOnly), - isSortable: Boolean(keySchema.isSortable), - validations: FrontendValidationUtils.convertValidationList(keySchema.validation), + isPrimaryKey: Boolean(keyField.isPrimaryKey), + isRequired: keyField.validation?.some(v => v.operator === 'Present') ?? false, + isReadOnly: Boolean(keyField.isReadOnly), + isSortable: Boolean(keyField.isSortable), + validations: FrontendValidationUtils.convertValidationList(keyField.validation), reference: `${foreignCollection.name}.${relation.foreignKeyTarget}`, }; } @@ -181,7 +190,6 @@ export default class SchemaGeneratorFields { field: name, enums: null, integration: null, - isReadOnly: false, isVirtual: false, inverseOf: CollectionUtils.getInverseRelation(collection, name), relationship: SchemaGeneratorFields.relationMap[relation.type], diff --git a/packages/agent/test/agent/utils/forest-schema/generator-fields_many-to-many.test.ts b/packages/agent/test/agent/utils/forest-schema/generator-fields_many-to-many.test.ts index 44402aad24..0af75b0c88 100644 --- a/packages/agent/test/agent/utils/forest-schema/generator-fields_many-to-many.test.ts +++ b/packages/agent/test/agent/utils/forest-schema/generator-fields_many-to-many.test.ts @@ -26,7 +26,7 @@ describe('SchemaGeneratorFields > Many to Many', () => { fields: { bookId: factories.columnSchema .isPrimaryKey() - .build({ validation: [{ operator: 'Present' }] }), + .build({ isReadOnly: true, validation: [{ operator: 'Present' }] }), book: factories.manyToOneSchema.build({ foreignCollection: 'books', foreignKey: 'bookId', @@ -34,7 +34,7 @@ describe('SchemaGeneratorFields > Many to Many', () => { }), personId: factories.columnSchema .isPrimaryKey() - .build({ validation: [{ operator: 'Present' }] }), + .build({ isReadOnly: true, validation: [{ operator: 'Present' }] }), person: factories.manyToOneSchema.build({ foreignCollection: 'person', foreignKey: 'personId', @@ -80,7 +80,7 @@ describe('SchemaGeneratorFields > Many to Many', () => { integration: null, isFilterable: false, isPrimaryKey: false, - isReadOnly: false, + isReadOnly: true, isRequired: false, isSortable: false, isVirtual: false, @@ -108,7 +108,7 @@ describe('SchemaGeneratorFields > Many to Many', () => { defaultValue: null, enums: null, integration: null, - isReadOnly: false, + isReadOnly: true, isSortable: false, isVirtual: false, }); diff --git a/packages/agent/test/agent/utils/forest-schema/generator-fields_one-to-many.test.ts b/packages/agent/test/agent/utils/forest-schema/generator-fields_one-to-many.test.ts index 95c84b38b3..23a8fba147 100644 --- a/packages/agent/test/agent/utils/forest-schema/generator-fields_one-to-many.test.ts +++ b/packages/agent/test/agent/utils/forest-schema/generator-fields_one-to-many.test.ts @@ -71,7 +71,7 @@ describe('SchemaGeneratorFields > One to Many', () => { integration: null, isFilterable: false, isPrimaryKey: false, - isReadOnly: false, + isReadOnly: true, isRequired: false, isSortable: false, isVirtual: false, diff --git a/packages/agent/test/agent/utils/forest-schema/generator-fields_one-to-one.test.ts b/packages/agent/test/agent/utils/forest-schema/generator-fields_one-to-one.test.ts index dc84dcee9d..1aa9f73b1b 100644 --- a/packages/agent/test/agent/utils/forest-schema/generator-fields_one-to-one.test.ts +++ b/packages/agent/test/agent/utils/forest-schema/generator-fields_one-to-one.test.ts @@ -13,6 +13,7 @@ describe('SchemaGeneratorFields > One to One', () => { }), authorId: factories.columnSchema.build({ columnType: 'String', + isReadOnly: true, isSortable: true, }), author: factories.manyToOneSchema.build({ @@ -62,7 +63,7 @@ describe('SchemaGeneratorFields > One to One', () => { integration: null, isFilterable: false, isPrimaryKey: false, - isReadOnly: false, + isReadOnly: true, isRequired: false, isSortable: false, isVirtual: false, @@ -89,7 +90,7 @@ describe('SchemaGeneratorFields > One to One', () => { integration: null, isFilterable: false, isPrimaryKey: false, - isReadOnly: false, + isReadOnly: true, isRequired: false, isVirtual: false, validations: [],