mirror of
https://github.com/strapi/strapi.git
synced 2025-11-03 03:17:11 +00:00
feat(dts): support models and contentTypes (#19604)
This commit is contained in:
parent
ffe6a1f2e9
commit
b0e5eb2398
@ -59,6 +59,7 @@
|
|||||||
"ws": "8.13.0"
|
"ws": "8.13.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@strapi/database": "workspace:*",
|
||||||
"@strapi/pack-up": "4.20.3",
|
"@strapi/pack-up": "4.20.3",
|
||||||
"@types/fs-extra": "9.0.13",
|
"@types/fs-extra": "9.0.13",
|
||||||
"@types/jest": "29.5.2",
|
"@types/jest": "29.5.2",
|
||||||
|
|||||||
@ -49,6 +49,13 @@ export const getContentTypes = (): {
|
|||||||
bar: { uid: 'bar', attributes: { age: { type: 'number' } } },
|
bar: { uid: 'bar', attributes: { age: { type: 'number' } } },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory to get default strapi models test values
|
||||||
|
*/
|
||||||
|
export const getStrapiModels = () => {
|
||||||
|
return [{ uid: 'model::foo' }, { uid: 'model::bar' }];
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a factory of readable streams (wrapped with a jest mock function)
|
* Create a factory of readable streams (wrapped with a jest mock function)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import {
|
|||||||
getStrapiFactory,
|
getStrapiFactory,
|
||||||
getContentTypes,
|
getContentTypes,
|
||||||
setGlobalStrapi,
|
setGlobalStrapi,
|
||||||
|
getStrapiModels,
|
||||||
} from '../../../../__tests__/test-utils';
|
} from '../../../../__tests__/test-utils';
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -140,15 +141,37 @@ describe('Local Strapi Source Destination', () => {
|
|||||||
entity: { id: 9, age: 0 },
|
entity: { id: 9, age: 0 },
|
||||||
contentType: { uid: 'bar' },
|
contentType: { uid: 'bar' },
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
entity: { id: 10, age: 0 },
|
||||||
|
model: { uid: 'model::foo' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
entity: { id: 11, age: 0 },
|
||||||
|
model: { uid: 'model::bar' },
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const deleteMany = (uid: string) =>
|
const deleteMany = (uid: string) =>
|
||||||
jest.fn(async () => ({
|
jest.fn(async () => ({
|
||||||
count: entities.filter((entity) => entity.contentType.uid === uid).length,
|
count: entities.filter((entity) => {
|
||||||
|
if (entity.model) {
|
||||||
|
return entity.model.uid === uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
return entity.contentType.uid === uid;
|
||||||
|
}).length,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const findMany = (uid: string) => {
|
const findMany = (uid: string) => {
|
||||||
return jest.fn(async () => entities.filter((entity) => entity.contentType.uid === uid));
|
return jest.fn(async () =>
|
||||||
|
entities.filter((entity) => {
|
||||||
|
if (entity.model) {
|
||||||
|
return entity.model.uid === uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
return entity.contentType.uid === uid;
|
||||||
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const query = jest.fn((uid) => {
|
const query = jest.fn((uid) => {
|
||||||
@ -164,6 +187,13 @@ describe('Local Strapi Source Destination', () => {
|
|||||||
contentTypes: getContentTypes(),
|
contentTypes: getContentTypes(),
|
||||||
query,
|
query,
|
||||||
getModel,
|
getModel,
|
||||||
|
get() {
|
||||||
|
return {
|
||||||
|
get() {
|
||||||
|
return getStrapiModels();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
db: {
|
db: {
|
||||||
query,
|
query,
|
||||||
transaction,
|
transaction,
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import {
|
|||||||
getStrapiFactory,
|
getStrapiFactory,
|
||||||
getContentTypes,
|
getContentTypes,
|
||||||
setGlobalStrapi,
|
setGlobalStrapi,
|
||||||
|
getStrapiModels,
|
||||||
} from '../../../../__tests__/test-utils';
|
} from '../../../../__tests__/test-utils';
|
||||||
import { IConfiguration } from '../../../../../types';
|
import { IConfiguration } from '../../../../../types';
|
||||||
|
|
||||||
@ -36,6 +37,14 @@ const entities = [
|
|||||||
entity: { id: 9, age: 0 },
|
entity: { id: 9, age: 0 },
|
||||||
contentType: { uid: 'bar' },
|
contentType: { uid: 'bar' },
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
entity: { id: 10, age: 0 },
|
||||||
|
model: { uid: 'model::foo' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
entity: { id: 11, age: 0 },
|
||||||
|
model: { uid: 'model::bar' },
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -44,11 +53,25 @@ afterEach(() => {
|
|||||||
|
|
||||||
const deleteMany = (uid: string) =>
|
const deleteMany = (uid: string) =>
|
||||||
jest.fn(async () => ({
|
jest.fn(async () => ({
|
||||||
count: entities.filter((entity) => entity.contentType.uid === uid).length,
|
count: entities.filter((entity) => {
|
||||||
|
if (entity.model) {
|
||||||
|
return entity.model.uid === uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
return entity.contentType.uid === uid;
|
||||||
|
}).length,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const findMany = (uid: string) => {
|
const findMany = (uid: string) => {
|
||||||
return jest.fn(async () => entities.filter((entity) => entity.contentType.uid === uid));
|
return jest.fn(async () =>
|
||||||
|
entities.filter((entity) => {
|
||||||
|
if (entity.model) {
|
||||||
|
return entity.model.uid === uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
return entity.contentType.uid === uid;
|
||||||
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const create = jest.fn((data) => data);
|
const create = jest.fn((data) => data);
|
||||||
@ -64,12 +87,21 @@ const query = jest.fn((uid) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('Restore ', () => {
|
describe('Restore ', () => {
|
||||||
test('Should delete all contentTypes', async () => {
|
test('Should delete all models and contentTypes', async () => {
|
||||||
const strapi = getStrapiFactory({
|
const strapi = getStrapiFactory({
|
||||||
contentTypes: getContentTypes(),
|
contentTypes: getContentTypes(),
|
||||||
query,
|
query,
|
||||||
getModel,
|
getModel,
|
||||||
db: { query },
|
get() {
|
||||||
|
return {
|
||||||
|
get() {
|
||||||
|
return getStrapiModels();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
db: {
|
||||||
|
query,
|
||||||
|
},
|
||||||
})();
|
})();
|
||||||
|
|
||||||
setGlobalStrapi(strapi);
|
setGlobalStrapi(strapi);
|
||||||
@ -83,7 +115,16 @@ describe('Restore ', () => {
|
|||||||
contentTypes: getContentTypes(),
|
contentTypes: getContentTypes(),
|
||||||
query,
|
query,
|
||||||
getModel,
|
getModel,
|
||||||
db: { query },
|
get() {
|
||||||
|
return {
|
||||||
|
get() {
|
||||||
|
return getStrapiModels();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
db: {
|
||||||
|
query,
|
||||||
|
},
|
||||||
})();
|
})();
|
||||||
|
|
||||||
setGlobalStrapi(strapi);
|
setGlobalStrapi(strapi);
|
||||||
@ -96,6 +137,34 @@ describe('Restore ', () => {
|
|||||||
expect(count).toBe(3);
|
expect(count).toBe(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Should only delete chosen model ', async () => {
|
||||||
|
const strapi = getStrapiFactory({
|
||||||
|
contentTypes: getContentTypes(),
|
||||||
|
query,
|
||||||
|
getModel,
|
||||||
|
get() {
|
||||||
|
return {
|
||||||
|
get() {
|
||||||
|
return getStrapiModels();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
db: {
|
||||||
|
query,
|
||||||
|
},
|
||||||
|
})();
|
||||||
|
|
||||||
|
setGlobalStrapi(strapi);
|
||||||
|
|
||||||
|
const { count } = await deleteRecords(strapi, {
|
||||||
|
entities: {
|
||||||
|
include: ['model::foo'],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(count).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
test('Should add core store data', async () => {
|
test('Should add core store data', async () => {
|
||||||
const strapi = getStrapiFactory({
|
const strapi = getStrapiFactory({
|
||||||
contentTypes: getContentTypes(),
|
contentTypes: getContentTypes(),
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import type { LoadedStrapi, Schema } from '@strapi/types';
|
import type { LoadedStrapi, Schema, Common } from '@strapi/types';
|
||||||
|
import type { Model } from '@strapi/database';
|
||||||
import { ProviderTransferError } from '../../../../../errors/providers';
|
import { ProviderTransferError } from '../../../../../errors/providers';
|
||||||
import * as queries from '../../../../queries';
|
import * as queries from '../../../../queries';
|
||||||
|
|
||||||
@ -37,44 +38,75 @@ const deleteEntitiesRecords = async (
|
|||||||
options: IRestoreOptions = {}
|
options: IRestoreOptions = {}
|
||||||
): Promise<IDeleteResults> => {
|
): Promise<IDeleteResults> => {
|
||||||
const { entities } = options;
|
const { entities } = options;
|
||||||
const query = queries.entity.createEntityQuery(strapi);
|
|
||||||
const contentTypes = Object.values<Schema.ContentType>(
|
|
||||||
strapi.contentTypes as Record<string, Schema.ContentType>
|
|
||||||
);
|
|
||||||
|
|
||||||
const contentTypesToClear = contentTypes.filter((contentType) => {
|
const models = strapi.get('models').get() as Model[];
|
||||||
let removeThisContentType = true;
|
const contentTypes = Object.values(strapi.contentTypes) as Schema.ContentType[];
|
||||||
|
|
||||||
// include means "only include these types" so if it's not in here, it's not being included
|
const contentTypesToClear = contentTypes
|
||||||
if (entities?.include) {
|
.filter((contentType) => {
|
||||||
removeThisContentType = entities.include.includes(contentType.uid);
|
let removeThisContentType = true;
|
||||||
}
|
|
||||||
|
|
||||||
// if something is excluded, remove it. But lack of being excluded doesn't mean it's kept
|
// include means "only include these types" so if it's not in here, it's not being included
|
||||||
if (entities?.exclude && entities.exclude.includes(contentType.uid)) {
|
if (entities?.include) {
|
||||||
removeThisContentType = false;
|
removeThisContentType = entities.include.includes(contentType.uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entities?.filters) {
|
// if something is excluded, remove it. But lack of being excluded doesn't mean it's kept
|
||||||
removeThisContentType = entities.filters.every((filter) => filter(contentType));
|
if (entities?.exclude && entities.exclude.includes(contentType.uid)) {
|
||||||
}
|
removeThisContentType = false;
|
||||||
|
}
|
||||||
|
|
||||||
return removeThisContentType;
|
if (entities?.filters) {
|
||||||
});
|
removeThisContentType = entities.filters.every((filter) => filter(contentType));
|
||||||
|
}
|
||||||
|
|
||||||
const [results, updateResults] = useResults(
|
return removeThisContentType;
|
||||||
contentTypesToClear.map((contentType) => contentType.uid)
|
})
|
||||||
);
|
.map((contentType) => contentType.uid);
|
||||||
|
|
||||||
const deletePromises = contentTypesToClear.map(async (contentType) => {
|
const modelsToClear = models
|
||||||
const result = await query(contentType.uid).deleteMany(entities?.params);
|
.filter((model) => {
|
||||||
|
if (contentTypesToClear.includes(model.uid as Common.UID.ContentType)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let removeThisModel = true;
|
||||||
|
|
||||||
|
// include means "only include these types" so if it's not in here, it's not being included
|
||||||
|
if (entities?.include) {
|
||||||
|
removeThisModel = entities.include.includes(model.uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if something is excluded, remove it. But lack of being excluded doesn't mean it's kept
|
||||||
|
if (entities?.exclude && entities.exclude.includes(model.uid)) {
|
||||||
|
removeThisModel = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return removeThisModel;
|
||||||
|
})
|
||||||
|
.map((model) => model.uid);
|
||||||
|
|
||||||
|
const [results, updateResults] = useResults([...contentTypesToClear, ...modelsToClear]);
|
||||||
|
|
||||||
|
const contentTypeQuery = queries.entity.createEntityQuery(strapi);
|
||||||
|
|
||||||
|
const contentTypePromises = contentTypesToClear.map(async (uid) => {
|
||||||
|
const result = await contentTypeQuery(uid).deleteMany(entities?.params);
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
updateResults(result.count || 0, contentType.uid);
|
updateResults(result.count || 0, uid);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await Promise.all(deletePromises);
|
const modelsPromises = modelsToClear.map(async (uid) => {
|
||||||
|
const result = await strapi.db.query(uid).deleteMany({});
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
updateResults(result.count || 0, uid);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.all([...contentTypePromises, ...modelsPromises]);
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -7060,6 +7060,7 @@ __metadata:
|
|||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@strapi/data-transfer@workspace:packages/core/data-transfer"
|
resolution: "@strapi/data-transfer@workspace:packages/core/data-transfer"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
"@strapi/database": "workspace:*"
|
||||||
"@strapi/logger": "npm:4.20.3"
|
"@strapi/logger": "npm:4.20.3"
|
||||||
"@strapi/pack-up": "npm:4.20.3"
|
"@strapi/pack-up": "npm:4.20.3"
|
||||||
"@strapi/types": "npm:4.20.3"
|
"@strapi/types": "npm:4.20.3"
|
||||||
@ -7096,7 +7097,7 @@ __metadata:
|
|||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
"@strapi/database@npm:4.20.3, @strapi/database@workspace:packages/core/database":
|
"@strapi/database@npm:4.20.3, @strapi/database@workspace:*, @strapi/database@workspace:packages/core/database":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@strapi/database@workspace:packages/core/database"
|
resolution: "@strapi/database@workspace:packages/core/database"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user