Skip to content

Commit

Permalink
enhancement(database)!: shorten db identifies and add internal migration
Browse files Browse the repository at this point in the history
  • Loading branch information
innerdvations committed Mar 25, 2024
1 parent d362bf2 commit fd7c075
Show file tree
Hide file tree
Showing 25 changed files with 4,859 additions and 20,533 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { Core } from '@strapi/types';
import { filter, forEach, pipe, map, stubTrue, cond, defaultsDeep } from 'lodash/fp';
import { getService } from '../../utils';
import { getVisibleContentTypesUID, hasStageAttribute } from '../../utils/review-workflows';
Expand All @@ -14,14 +15,6 @@ import {
import { persistTables, removePersistedTablesWithSuffix } from '../../utils/persisted-tables';
import webhookEvents from '../../constants/webhookEvents';

import type { Core } from '@strapi/types';

const MAX_DB_TABLE_NAME_LEN = 63; // Postgres limit
// The longest index name that Strapi can create is prefixed with '_strapi_stage_links_inv_fk', so the content type name should be no longer than this.
const MAX_JOIN_TABLE_NAME_SUFFIX =
1 /* _ */ + ENTITY_STAGE_ATTRIBUTE.length + '_links_inv_fk'.length;
const MAX_CONTENT_TYPE_NAME_LEN = MAX_DB_TABLE_NAME_LEN - MAX_JOIN_TABLE_NAME_SUFFIX;

const DEFAULT_OPTIONS = {
numberOfWorkflows: MAX_WORKFLOWS,
stagesPerWorkflow: MAX_STAGES_PER_WORKFLOW,
Expand Down Expand Up @@ -71,22 +64,7 @@ const setReviewWorkflowAttributes = (contentType: any) => {

function extendReviewWorkflowContentTypes({ strapi }: { strapi: Core.LoadedStrapi }) {
const extendContentType = (contentTypeUID: any) => {
const assertContentTypeCompatibility = (contentType: any) =>
contentType.collectionName.length <= MAX_CONTENT_TYPE_NAME_LEN;

const incompatibleContentTypeAlert = (contentType: any) => {
strapi.log.warn(
`Review Workflow cannot be activated for the content type with the name '${contentType.info.displayName}' because the name exceeds the maximum length of ${MAX_CONTENT_TYPE_NAME_LEN} characters.`
);
return contentType;
};

const extendContentTypeIfCompatible = cond([
[assertContentTypeCompatibility, setReviewWorkflowAttributes],
[stubTrue, incompatibleContentTypeAlert],
]);

strapi.get('content-types').extend(contentTypeUID, extendContentTypeIfCompatible);
strapi.get('content-types').extend(contentTypeUID, setReviewWorkflowAttributes);
};

pipe([
Expand All @@ -102,7 +80,10 @@ function persistStagesJoinTables({ strapi }: { strapi: Core.LoadedStrapi }) {
// Persist the stage join table
const { attributes, tableName } = strapi.db.metadata.get(contentTypeUID) as any;
const joinTableName = attributes[ENTITY_STAGE_ATTRIBUTE].joinTable.name;
return { name: joinTableName, dependsOn: [{ name: tableName }] };
return {
name: joinTableName,
dependsOn: [{ name: tableName }],
};
};

const joinTablesToPersist = pipe([
Expand Down
8 changes: 4 additions & 4 deletions packages/core/core/src/Strapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -495,10 +495,10 @@ class Strapi extends Container implements Core.Strapi {

async bootstrap() {
const models = [
...utils.transformContentTypesToModels([
...Object.values(this.contentTypes),
...Object.values(this.components),
]),
...utils.transformContentTypesToModels(
[...Object.values(this.contentTypes), ...Object.values(this.components)],
this.db.metadata.identifiers
),
...this.get('models').get(),
];

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,25 @@
import { cloneDeep, merge } from 'lodash';
import { Database } from '@strapi/database';
import { transformContentTypesToModels } from '..';
import { LoadedContentTypeModel } from '../transform-content-types-to-models';

const db = new Database({
settings: {
migrations: {
dir: 'fakedir',
},
},
connection: {
client: 'sqlite',
useNullAsDefault: true,
connection: {
filename: 'fake.db',
},
},
});

const identifiers = db.metadata.identifiers;

// We want to match exactly with the exception that document_id.default should be any function
expect.extend({
toMatchModels(received, expected) {
Expand Down Expand Up @@ -263,41 +281,48 @@ function patchContentTypes(
}

describe('transformContentTypesToModels', () => {
test('converts valid content types to models', () => {
const models = transformContentTypesToModels(contentTypes);
describe('full length identifiers', () => {
// mock the options so that the 'global' identifiers created for use by createMetadata uses 0 for maxLength
Object.defineProperty(identifiers, 'options', {
get: jest.fn(() => ({ maxLength: 0 })),
});

expect(models).toMatchModels(expectedModels);
});
test('converts valid content types to models', () => {
const models = transformContentTypesToModels(contentTypes, identifiers);

expect(models).toMatchModels(expectedModels);
});

test.each(['id', 'document_id', 'ID', 'documentId'])(
'throws on restricted attribute name: %s',
(restrictedName) => {
const changes = {
attributes: {
[restrictedName]: {
type: 'string',
test.each(['id', 'document_id', 'ID', 'documentId'])(
'throws on restricted attribute name: %s',
(restrictedName) => {
const changes = {
attributes: {
[restrictedName]: {
type: 'string',
},
},
},
};
const modifiedContentTypes = patchContentTypes('countries', changes);
};
const modifiedContentTypes = patchContentTypes('countries', changes);

expect(() => transformContentTypesToModels(modifiedContentTypes)).toThrow(
`The attribute "${restrictedName}" is reserved`
);
}
);
expect(() => transformContentTypesToModels(modifiedContentTypes, identifiers)).toThrow(
`The attribute "${restrictedName}" is reserved`
);
}
);

test.each(['collectionName', 'uid', 'modelName'])(
'throws on missing name: %s',
(restrictedName) => {
const changes = {
[restrictedName]: null,
};
const modifiedContentTypes = patchContentTypes('countries', changes);
test.each(['collectionName', 'uid', 'modelName'])(
'throws on missing name: %s',
(restrictedName) => {
const changes = {
[restrictedName]: null,
};
const modifiedContentTypes = patchContentTypes('countries', changes);

expect(() => transformContentTypesToModels(modifiedContentTypes)).toThrow(
`"${restrictedName}" is required`
);
}
);
expect(() => transformContentTypesToModels(modifiedContentTypes, identifiers)).toThrow(
`"${restrictedName}" is required`
);
}
);
});
});

0 comments on commit fd7c075

Please sign in to comment.