2019-09-20 12:44:24 +02:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
const _ = require('lodash');
|
|
|
|
|
|
|
|
const requireConnector = require('./require-connector');
|
|
|
|
const { createQuery } = require('./queries');
|
|
|
|
|
|
|
|
class DatabaseManager {
|
|
|
|
constructor(strapi) {
|
|
|
|
this.strapi = strapi;
|
|
|
|
|
|
|
|
this.initialized = false;
|
2019-12-10 14:21:20 +01:00
|
|
|
|
2019-09-20 12:44:24 +02:00
|
|
|
this.queries = new Map();
|
|
|
|
this.connectors = new Map();
|
2019-11-15 11:49:32 +01:00
|
|
|
this.models = new Map();
|
2019-09-20 12:44:24 +02:00
|
|
|
}
|
|
|
|
|
2020-03-30 12:50:32 +02:00
|
|
|
// Check if all collection names are unique
|
|
|
|
checkForDuplicates() {
|
|
|
|
const createErrorMessage = (
|
|
|
|
collectionA,
|
|
|
|
collectionB
|
|
|
|
) => `Duplicated collection name: \`${collectionA.collectionName}\`.
|
|
|
|
The same collection name can't be used for two different models.
|
|
|
|
First found in ${collectionA.origin} \`${collectionA.apiOrPluginName}\`, model \`${collectionA.modelName}\`.
|
|
|
|
Second found in ${collectionB.origin} \`${collectionB.apiOrPluginName}\`, model \`${collectionB.modelName}\`.`;
|
|
|
|
|
|
|
|
const collections = [];
|
|
|
|
_.forIn(this.strapi.admin.models, (model, modelName) => {
|
|
|
|
collections.push({
|
|
|
|
origin: 'Strapi internal',
|
|
|
|
collectionName: model.collectionName || `${modelName}`.toLocaleLowerCase(),
|
|
|
|
apiOrPluginName: 'admin',
|
|
|
|
modelName,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
_.forIn(this.strapi.api, (api, apiName) => {
|
|
|
|
_.forIn(api.models, (model, modelName) => {
|
|
|
|
collections.push({
|
|
|
|
origin: 'API',
|
|
|
|
collectionName: model.collectionName || `${modelName}`.toLocaleLowerCase(),
|
|
|
|
apiOrPluginName: apiName,
|
|
|
|
modelName,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
_.forIn(this.strapi.plugins, (plugin, pluginName) => {
|
|
|
|
_.forIn(plugin.models, (model, modelName) => {
|
|
|
|
collections.push({
|
|
|
|
origin: 'Plugin',
|
|
|
|
collectionName: model.collectionName || `${modelName}`.toLocaleLowerCase(),
|
|
|
|
apiOrPluginName: pluginName,
|
|
|
|
modelName,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
collections.forEach((collectionA, indexA) => {
|
|
|
|
const similarCollectionFound = collections
|
|
|
|
.slice(indexA + 1)
|
|
|
|
.find(colB => colB.collectionName === collectionA.collectionName);
|
|
|
|
|
|
|
|
if (similarCollectionFound) {
|
|
|
|
strapi.stopWithError(new Error(createErrorMessage(collectionA, similarCollectionFound)));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-09-20 12:44:24 +02:00
|
|
|
async initialize() {
|
|
|
|
if (this.initialized === true) {
|
|
|
|
throw new Error('Database manager already initialized');
|
|
|
|
}
|
|
|
|
|
|
|
|
this.initialized = true;
|
|
|
|
|
|
|
|
const connectorsToInitialize = [];
|
|
|
|
for (const connection of Object.values(this.strapi.config.connections)) {
|
|
|
|
const { connector } = connection;
|
|
|
|
if (!connectorsToInitialize.includes(connector)) {
|
|
|
|
connectorsToInitialize.push(connector);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-30 12:50:32 +02:00
|
|
|
this.checkForDuplicates();
|
|
|
|
|
2019-09-20 12:44:24 +02:00
|
|
|
for (const connectorToInitialize of connectorsToInitialize) {
|
|
|
|
const connector = requireConnector(connectorToInitialize)(strapi);
|
|
|
|
|
|
|
|
this.connectors.set(connectorToInitialize, connector);
|
|
|
|
|
|
|
|
await connector.initialize();
|
|
|
|
}
|
|
|
|
|
2019-11-15 11:49:32 +01:00
|
|
|
this.initializeModelsMap();
|
|
|
|
|
2019-09-20 12:44:24 +02:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2019-11-15 11:49:32 +01:00
|
|
|
initializeModelsMap() {
|
|
|
|
Object.keys(this.strapi.models).forEach(modelKey => {
|
|
|
|
const model = this.strapi.models[modelKey];
|
|
|
|
this.models.set(model.uid, model);
|
|
|
|
});
|
|
|
|
|
|
|
|
Object.keys(this.strapi.admin.models).forEach(modelKey => {
|
|
|
|
const model = this.strapi.admin.models[modelKey];
|
|
|
|
this.models.set(model.uid, model);
|
|
|
|
});
|
|
|
|
|
|
|
|
Object.keys(this.strapi.plugins).forEach(pluginKey => {
|
|
|
|
Object.keys(this.strapi.plugins[pluginKey].models).forEach(modelKey => {
|
|
|
|
const model = this.strapi.plugins[pluginKey].models[modelKey];
|
|
|
|
this.models.set(model.uid, model);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-09-20 12:44:24 +02:00
|
|
|
query(entity, plugin) {
|
|
|
|
if (!entity) {
|
|
|
|
throw new Error(`argument entity is required`);
|
|
|
|
}
|
|
|
|
|
|
|
|
const normalizedName = entity.toLowerCase();
|
|
|
|
|
2019-11-15 11:49:32 +01:00
|
|
|
// get by uid or name / plugin
|
|
|
|
const model = this.models.has(entity)
|
|
|
|
? this.models.get(entity)
|
|
|
|
: this.getModel(normalizedName, plugin);
|
2019-09-20 12:44:24 +02:00
|
|
|
|
|
|
|
if (!model) {
|
|
|
|
throw new Error(`The model ${entity} can't be found.`);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.queries.has(model.uid)) {
|
|
|
|
return this.queries.get(model.uid);
|
|
|
|
}
|
|
|
|
|
|
|
|
const connectorQuery = this.connectors
|
|
|
|
.get(model.orm)
|
2019-12-17 14:05:15 +01:00
|
|
|
.queries({ model, modelKey: model.modelName, strapi });
|
2019-09-20 12:44:24 +02:00
|
|
|
|
2019-12-17 20:59:57 +01:00
|
|
|
const query = createQuery({
|
|
|
|
connectorQuery,
|
|
|
|
model,
|
|
|
|
});
|
|
|
|
|
2019-09-20 12:44:24 +02:00
|
|
|
this.queries.set(model.uid, query);
|
|
|
|
return query;
|
|
|
|
}
|
|
|
|
|
|
|
|
getModel(name, plugin) {
|
|
|
|
const key = _.toLower(name);
|
|
|
|
|
2019-11-15 11:49:32 +01:00
|
|
|
if (this.models.has(key)) return this.models.get(key);
|
|
|
|
|
2019-09-20 12:44:24 +02:00
|
|
|
if (plugin === 'admin') {
|
|
|
|
return _.get(strapi.admin, ['models', key]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
_.get(strapi.plugins, [plugin, 'models', key]) ||
|
|
|
|
_.get(strapi, ['models', key]) ||
|
2019-10-22 18:01:03 +02:00
|
|
|
_.get(strapi, ['components', key])
|
2019-09-20 12:44:24 +02:00
|
|
|
);
|
|
|
|
}
|
2019-12-10 16:21:21 +01:00
|
|
|
|
|
|
|
getModelByCollectionName(collectionName) {
|
|
|
|
return Array.from(this.models.values()).find(model => {
|
|
|
|
return model.collectionName === collectionName;
|
|
|
|
});
|
|
|
|
}
|
2019-09-20 12:44:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function createDatabaseManager(strapi) {
|
|
|
|
return new DatabaseManager(strapi);
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
createDatabaseManager,
|
|
|
|
};
|