node_modules ignore

This commit is contained in:
oier committed 2025-05-08 23:43:47 +02:00
1 parent e19d52f172
commit 4574544c9f
65041 files changed
+10593536

No files matched your search

@@ -0,0 +1,4 @@
import type { Core } from '@strapi/types';
declare const createEntityQuery: (strapi: Core.Strapi) => any;
export { createEntityQuery };
//# sourceMappingURL=entity.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"entity.d.ts","sourceRoot":"","sources":["../../../src/strapi/queries/entity.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAqB,MAAM,eAAe,CAAC;AAkB7D,QAAA,MAAM,iBAAiB,WAAY,KAAK,MAAM,KAAG,GAiIhD,CAAC;AAEF,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
+125
View File
@@ -0,0 +1,125 @@
'use strict';
var fp = require('lodash/fp');
var components = require('../../utils/components.js');
const sanitizeComponentLikeAttributes = (model, data)=>{
const { attributes } = model;
const componentLikeAttributesKey = Object.entries(attributes).filter(([, attribute])=>attribute.type === 'component' || attribute.type === 'dynamiczone').map(([key])=>key);
return fp.omit(componentLikeAttributesKey, data);
};
const omitInvalidCreationAttributes = fp.omit([
'id'
]);
const createEntityQuery = (strapi)=>{
const components$1 = {
async assignToEntity (uid, data) {
const model = strapi.getModel(uid);
const entityComponents = await components.createComponents(uid, data);
const dataWithoutComponents = sanitizeComponentLikeAttributes(model, data);
return fp.assign(entityComponents, dataWithoutComponents);
},
async get (uid, entity) {
return components.getComponents(uid, entity);
},
delete (uid, componentsToDelete) {
return components.deleteComponents(uid, componentsToDelete, {
loadComponents: false
});
}
};
const query = (uid)=>{
const create = async (params)=>{
const dataWithComponents = await components$1.assignToEntity(uid, params.data);
const sanitizedData = omitInvalidCreationAttributes(dataWithComponents);
return strapi.db.query(uid).create({
...params,
data: sanitizedData
});
};
const createMany = async (params)=>{
return Promise.resolve(params.data)// Create components for each entity
.then(fp.map((data)=>components$1.assignToEntity(uid, data)))// Remove unwanted attributes
.then(fp.map(omitInvalidCreationAttributes))// Execute a strapi db createMany query with all the entities + their created components
.then((data)=>strapi.db.query(uid).createMany({
...params,
data
}));
};
const deleteMany = async (params)=>{
const entitiesToDelete = await strapi.db.query(uid).findMany(params ?? {});
if (!entitiesToDelete.length) {
return null;
}
const componentsToDelete = await Promise.all(entitiesToDelete.map((entityToDelete)=>components$1.get(uid, entityToDelete)));
const deletedEntities = await strapi.db.query(uid).deleteMany(params);
await Promise.all(componentsToDelete.map((compos)=>components$1.delete(uid, compos)));
return deletedEntities;
};
const getDeepPopulateComponentLikeQuery = (contentType, params = {
select: '*'
})=>{
const { attributes } = contentType;
const populate = {};
const entries = Object.entries(attributes);
for (const [key, attribute] of entries){
if (attribute.type === 'component') {
const component = strapi.getModel(attribute.component);
const subPopulate = getDeepPopulateComponentLikeQuery(component, params);
if ((fp.isArray(subPopulate) || fp.isObject(subPopulate)) && fp.size(subPopulate) > 0) {
populate[key] = {
...params,
populate: subPopulate
};
}
if (fp.isArray(subPopulate) && fp.isEmpty(subPopulate)) {
populate[key] = {
...params
};
}
}
if (attribute.type === 'dynamiczone') {
const { components: componentsUID } = attribute;
const on = {};
for (const componentUID of componentsUID){
const component = strapi.getModel(componentUID);
const subPopulate = getDeepPopulateComponentLikeQuery(component, params);
if ((fp.isArray(subPopulate) || fp.isObject(subPopulate)) && fp.size(subPopulate) > 0) {
on[componentUID] = {
...params,
populate: subPopulate
};
}
if (fp.isArray(subPopulate) && fp.isEmpty(subPopulate)) {
on[componentUID] = {
...params
};
}
}
populate[key] = fp.size(on) > 0 ? {
on
} : true;
}
}
const values = Object.values(populate);
if (values.every((value)=>value === true)) {
return Object.keys(populate);
}
return populate;
};
return {
create,
createMany,
deleteMany,
getDeepPopulateComponentLikeQuery,
get deepPopulateComponentLikeQuery () {
const contentType = strapi.getModel(uid);
return getDeepPopulateComponentLikeQuery(contentType);
}
};
};
return query;
};
exports.createEntityQuery = createEntityQuery;
//# sourceMappingURL=entity.js.map
@@ -0,0 +1 @@
{"version":3,"file":"entity.js","sources":["../../../src/strapi/queries/entity.ts"],"sourcesContent":["import { assign, isArray, isEmpty, isObject, map, omit, size } from 'lodash/fp';\n\nimport type { Core, UID, Data, Struct } from '@strapi/types';\nimport * as componentsService from '../../utils/components';\n\nconst sanitizeComponentLikeAttributes = <T extends Struct.Schema>(\n model: T,\n data: Data.Entity<T['uid']>\n) => {\n const { attributes } = model;\n\n const componentLikeAttributesKey = Object.entries(attributes)\n .filter(([, attribute]) => attribute.type === 'component' || attribute.type === 'dynamiczone')\n .map(([key]) => key);\n\n return omit(componentLikeAttributesKey, data);\n};\n\nconst omitInvalidCreationAttributes = omit(['id']);\n\nconst createEntityQuery = (strapi: Core.Strapi): any => {\n const components = {\n async assignToEntity(uid: UID.Schema, data: any) {\n const model = strapi.getModel(uid);\n\n const entityComponents = await componentsService.createComponents(uid, data);\n const dataWithoutComponents = sanitizeComponentLikeAttributes(model, data);\n\n return assign(entityComponents, dataWithoutComponents);\n },\n\n async get<T extends object>(uid: string, entity: T) {\n return componentsService.getComponents(uid as UID.Schema, entity as any);\n },\n\n delete<T extends object>(uid: string, componentsToDelete: T) {\n return componentsService.deleteComponents(uid as UID.Schema, componentsToDelete as any, {\n loadComponents: false,\n });\n },\n };\n\n const query = (uid: UID.Schema) => {\n const create = async <T extends { data: U }, U extends object>(params: T) => {\n const dataWithComponents = await components.assignToEntity(uid, params.data);\n const sanitizedData = omitInvalidCreationAttributes(dataWithComponents);\n\n return strapi.db.query(uid).create({ ...params, data: sanitizedData });\n };\n\n const createMany = async <T extends { data: U[] }, U extends object>(params: T) => {\n return (\n Promise.resolve(params.data)\n // Create components for each entity\n .then(map((data) => components.assignToEntity(uid, data)))\n // Remove unwanted attributes\n .then(map(omitInvalidCreationAttributes))\n // Execute a strapi db createMany query with all the entities + their created components\n .then((data) => strapi.db.query(uid).createMany({ ...params, data }))\n );\n };\n\n const deleteMany = async <T extends object>(params?: T) => {\n const entitiesToDelete = await strapi.db.query(uid).findMany(params ?? {});\n\n if (!entitiesToDelete.length) {\n return null;\n }\n\n const componentsToDelete = await Promise.all(\n entitiesToDelete.map((entityToDelete) => components.get(uid, entityToDelete))\n );\n\n const deletedEntities = await strapi.db.query(uid).deleteMany(params);\n await Promise.all(componentsToDelete.map((compos) => components.delete(uid, compos)));\n\n return deletedEntities;\n };\n\n const getDeepPopulateComponentLikeQuery = (\n contentType: Struct.Schema,\n params = { select: '*' }\n ) => {\n const { attributes } = contentType;\n\n const populate: any = {};\n\n const entries: [string, any][] = Object.entries(attributes);\n\n for (const [key, attribute] of entries) {\n if (attribute.type === 'component') {\n const component = strapi.getModel(attribute.component);\n const subPopulate = getDeepPopulateComponentLikeQuery(component, params);\n\n if ((isArray(subPopulate) || isObject(subPopulate)) && size(subPopulate) > 0) {\n populate[key] = { ...params, populate: subPopulate };\n }\n\n if (isArray(subPopulate) && isEmpty(subPopulate)) {\n populate[key] = { ...params };\n }\n }\n\n if (attribute.type === 'dynamiczone') {\n const { components: componentsUID } = attribute;\n\n const on: any = {};\n\n for (const componentUID of componentsUID) {\n const component = strapi.getModel(componentUID);\n const subPopulate = getDeepPopulateComponentLikeQuery(component, params);\n\n if ((isArray(subPopulate) || isObject(subPopulate)) && size(subPopulate) > 0) {\n on[componentUID] = { ...params, populate: subPopulate };\n }\n\n if (isArray(subPopulate) && isEmpty(subPopulate)) {\n on[componentUID] = { ...params };\n }\n }\n\n populate[key] = size(on) > 0 ? { on } : true;\n }\n }\n\n const values = Object.values(populate);\n\n if (values.every((value) => value === true)) {\n return Object.keys(populate);\n }\n\n return populate;\n };\n\n return {\n create,\n createMany,\n deleteMany,\n getDeepPopulateComponentLikeQuery,\n\n get Line truncated
@@ -0,0 +1,123 @@
import { omit, map, isArray, isObject, size, isEmpty, assign } from 'lodash/fp';
import { createComponents, getComponents, deleteComponents } from '../../utils/components.mjs';
const sanitizeComponentLikeAttributes = (model, data)=>{
const { attributes } = model;
const componentLikeAttributesKey = Object.entries(attributes).filter(([, attribute])=>attribute.type === 'component' || attribute.type === 'dynamiczone').map(([key])=>key);
return omit(componentLikeAttributesKey, data);
};
const omitInvalidCreationAttributes = omit([
'id'
]);
const createEntityQuery = (strapi)=>{
const components = {
async assignToEntity (uid, data) {
const model = strapi.getModel(uid);
const entityComponents = await createComponents(uid, data);
const dataWithoutComponents = sanitizeComponentLikeAttributes(model, data);
return assign(entityComponents, dataWithoutComponents);
},
async get (uid, entity) {
return getComponents(uid, entity);
},
delete (uid, componentsToDelete) {
return deleteComponents(uid, componentsToDelete, {
loadComponents: false
});
}
};
const query = (uid)=>{
const create = async (params)=>{
const dataWithComponents = await components.assignToEntity(uid, params.data);
const sanitizedData = omitInvalidCreationAttributes(dataWithComponents);
return strapi.db.query(uid).create({
...params,
data: sanitizedData
});
};
const createMany = async (params)=>{
return Promise.resolve(params.data)// Create components for each entity
.then(map((data)=>components.assignToEntity(uid, data)))// Remove unwanted attributes
.then(map(omitInvalidCreationAttributes))// Execute a strapi db createMany query with all the entities + their created components
.then((data)=>strapi.db.query(uid).createMany({
...params,
data
}));
};
const deleteMany = async (params)=>{
const entitiesToDelete = await strapi.db.query(uid).findMany(params ?? {});
if (!entitiesToDelete.length) {
return null;
}
const componentsToDelete = await Promise.all(entitiesToDelete.map((entityToDelete)=>components.get(uid, entityToDelete)));
const deletedEntities = await strapi.db.query(uid).deleteMany(params);
await Promise.all(componentsToDelete.map((compos)=>components.delete(uid, compos)));
return deletedEntities;
};
const getDeepPopulateComponentLikeQuery = (contentType, params = {
select: '*'
})=>{
const { attributes } = contentType;
const populate = {};
const entries = Object.entries(attributes);
for (const [key, attribute] of entries){
if (attribute.type === 'component') {
const component = strapi.getModel(attribute.component);
const subPopulate = getDeepPopulateComponentLikeQuery(component, params);
if ((isArray(subPopulate) || isObject(subPopulate)) && size(subPopulate) > 0) {
populate[key] = {
...params,
populate: subPopulate
};
}
if (isArray(subPopulate) && isEmpty(subPopulate)) {
populate[key] = {
...params
};
}
}
if (attribute.type === 'dynamiczone') {
const { components: componentsUID } = attribute;
const on = {};
for (const componentUID of componentsUID){
const component = strapi.getModel(componentUID);
const subPopulate = getDeepPopulateComponentLikeQuery(component, params);
if ((isArray(subPopulate) || isObject(subPopulate)) && size(subPopulate) > 0) {
on[componentUID] = {
...params,
populate: subPopulate
};
}
if (isArray(subPopulate) && isEmpty(subPopulate)) {
on[componentUID] = {
...params
};
}
}
populate[key] = size(on) > 0 ? {
on
} : true;
}
}
const values = Object.values(populate);
if (values.every((value)=>value === true)) {
return Object.keys(populate);
}
return populate;
};
return {
create,
createMany,
deleteMany,
getDeepPopulateComponentLikeQuery,
get deepPopulateComponentLikeQuery () {
const contentType = strapi.getModel(uid);
return getDeepPopulateComponentLikeQuery(contentType);
}
};
};
return query;
};
export { createEntityQuery };
//# sourceMappingURL=entity.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"entity.mjs","sources":["../../../src/strapi/queries/entity.ts"],"sourcesContent":["import { assign, isArray, isEmpty, isObject, map, omit, size } from 'lodash/fp';\n\nimport type { Core, UID, Data, Struct } from '@strapi/types';\nimport * as componentsService from '../../utils/components';\n\nconst sanitizeComponentLikeAttributes = <T extends Struct.Schema>(\n model: T,\n data: Data.Entity<T['uid']>\n) => {\n const { attributes } = model;\n\n const componentLikeAttributesKey = Object.entries(attributes)\n .filter(([, attribute]) => attribute.type === 'component' || attribute.type === 'dynamiczone')\n .map(([key]) => key);\n\n return omit(componentLikeAttributesKey, data);\n};\n\nconst omitInvalidCreationAttributes = omit(['id']);\n\nconst createEntityQuery = (strapi: Core.Strapi): any => {\n const components = {\n async assignToEntity(uid: UID.Schema, data: any) {\n const model = strapi.getModel(uid);\n\n const entityComponents = await componentsService.createComponents(uid, data);\n const dataWithoutComponents = sanitizeComponentLikeAttributes(model, data);\n\n return assign(entityComponents, dataWithoutComponents);\n },\n\n async get<T extends object>(uid: string, entity: T) {\n return componentsService.getComponents(uid as UID.Schema, entity as any);\n },\n\n delete<T extends object>(uid: string, componentsToDelete: T) {\n return componentsService.deleteComponents(uid as UID.Schema, componentsToDelete as any, {\n loadComponents: false,\n });\n },\n };\n\n const query = (uid: UID.Schema) => {\n const create = async <T extends { data: U }, U extends object>(params: T) => {\n const dataWithComponents = await components.assignToEntity(uid, params.data);\n const sanitizedData = omitInvalidCreationAttributes(dataWithComponents);\n\n return strapi.db.query(uid).create({ ...params, data: sanitizedData });\n };\n\n const createMany = async <T extends { data: U[] }, U extends object>(params: T) => {\n return (\n Promise.resolve(params.data)\n // Create components for each entity\n .then(map((data) => components.assignToEntity(uid, data)))\n // Remove unwanted attributes\n .then(map(omitInvalidCreationAttributes))\n // Execute a strapi db createMany query with all the entities + their created components\n .then((data) => strapi.db.query(uid).createMany({ ...params, data }))\n );\n };\n\n const deleteMany = async <T extends object>(params?: T) => {\n const entitiesToDelete = await strapi.db.query(uid).findMany(params ?? {});\n\n if (!entitiesToDelete.length) {\n return null;\n }\n\n const componentsToDelete = await Promise.all(\n entitiesToDelete.map((entityToDelete) => components.get(uid, entityToDelete))\n );\n\n const deletedEntities = await strapi.db.query(uid).deleteMany(params);\n await Promise.all(componentsToDelete.map((compos) => components.delete(uid, compos)));\n\n return deletedEntities;\n };\n\n const getDeepPopulateComponentLikeQuery = (\n contentType: Struct.Schema,\n params = { select: '*' }\n ) => {\n const { attributes } = contentType;\n\n const populate: any = {};\n\n const entries: [string, any][] = Object.entries(attributes);\n\n for (const [key, attribute] of entries) {\n if (attribute.type === 'component') {\n const component = strapi.getModel(attribute.component);\n const subPopulate = getDeepPopulateComponentLikeQuery(component, params);\n\n if ((isArray(subPopulate) || isObject(subPopulate)) && size(subPopulate) > 0) {\n populate[key] = { ...params, populate: subPopulate };\n }\n\n if (isArray(subPopulate) && isEmpty(subPopulate)) {\n populate[key] = { ...params };\n }\n }\n\n if (attribute.type === 'dynamiczone') {\n const { components: componentsUID } = attribute;\n\n const on: any = {};\n\n for (const componentUID of componentsUID) {\n const component = strapi.getModel(componentUID);\n const subPopulate = getDeepPopulateComponentLikeQuery(component, params);\n\n if ((isArray(subPopulate) || isObject(subPopulate)) && size(subPopulate) > 0) {\n on[componentUID] = { ...params, populate: subPopulate };\n }\n\n if (isArray(subPopulate) && isEmpty(subPopulate)) {\n on[componentUID] = { ...params };\n }\n }\n\n populate[key] = size(on) > 0 ? { on } : true;\n }\n }\n\n const values = Object.values(populate);\n\n if (values.every((value) => value === true)) {\n return Object.keys(populate);\n }\n\n return populate;\n };\n\n return {\n create,\n createMany,\n deleteMany,\n getDeepPopulateComponentLikeQuery,\n\n getLine truncated
@@ -0,0 +1,3 @@
export * as entity from './entity';
export * as link from './link';
//# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/strapi/queries/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AACnC,OAAO,KAAK,IAAI,MAAM,QAAQ,CAAC"}
+10
View File
@@ -0,0 +1,10 @@
'use strict';
var entity = require('./entity.js');
var link = require('./link.js');
exports.entity = entity;
exports.link = link;
//# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
@@ -0,0 +1,5 @@
import * as entity from './entity.mjs';
export { entity };
import * as link from './link.mjs';
export { link };
//# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
@@ -0,0 +1,10 @@
import type { Knex } from 'knex';
import type { Core } from '@strapi/types';
import { ILink } from '../../../types';
export declare const createLinkQuery: (strapi: Core.Strapi, trx?: Knex.Transaction) => () => {
generateAll: (uid: string) => AsyncGenerator<ILink>;
generateAllForAttribute: (uid: string, fieldName: string) => AsyncGenerator<ILink>;
insert: (link: ILink) => Promise<void>;
};
export declare const filterValidRelationalAttributes: (attributes: Record<string, any>) => Record<string, any>;
//# sourceMappingURL=link.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../../src/strapi/queries/link.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAEjC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAE1C,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAIvC,eAAO,MAAM,eAAe,WAAY,KAAK,MAAM,QAAQ,KAAK,WAAW;uBAmMtC,MAAM,KAAG,eAAe,KAAK,CAAC;mCAzLlB,MAAM,aAAa,MAAM,KAAG,eAAe,KAAK,CAAC;mBAyMlE,KAAK;CA+GpC,CAAC;AAEF,eAAO,MAAM,+BAA+B,eAAgB,OAAO,MAAM,EAAE,GAAG,CAAC,wBAY9E,CAAC"}
+298
View File
@@ -0,0 +1,298 @@
'use strict';
var fp = require('lodash/fp');
// TODO: Remove any types when we'll have types for DB metadata
const createLinkQuery = (strapi, trx)=>{
const query = ()=>{
const { connection } = strapi.db;
// TODO: Export utils from database and use the addSchema that is already written
const addSchema = (tableName)=>{
const schemaName = connection.client.connectionSettings.schema;
return schemaName ? `${schemaName}.${tableName}` : tableName;
};
async function* generateAllForAttribute(uid, fieldName) {
const metadata = strapi.db.metadata.get(uid);
if (!metadata) {
throw new Error(`No metadata found for ${uid}`);
}
const attributes = filterValidRelationalAttributes(metadata.attributes);
if (!(fieldName in attributes)) {
throw new Error(`${fieldName} is not a valid relational attribute name`);
}
const attribute = attributes[fieldName];
const kind = getLinkKind(attribute, uid);
const { relation, target } = attribute;
// The relation is stored in the same table
// TODO: handle manyToOne joinColumn
if (attribute.joinColumn) {
const joinColumnName = attribute.joinColumn.name;
const qb = connection.queryBuilder().select('id', joinColumnName).from(addSchema(metadata.tableName));
if (trx) {
qb.transacting(trx);
}
// TODO: stream the query to improve performances
const entries = await qb;
for (const entry of entries){
const ref = entry[joinColumnName];
if (ref !== null) {
yield {
kind,
relation,
left: {
type: uid,
ref: entry.id,
field: fieldName
},
right: {
type: target,
ref
}
};
}
}
}
// The relation uses a join table
if (attribute.joinTable) {
const { name, joinColumn, inverseJoinColumn, orderColumnName, morphColumn, inverseOrderColumnName } = attribute.joinTable;
const qb = connection.queryBuilder().from(addSchema(name));
const columns = {
left: {
ref: null
},
right: {
ref: null
}
};
const left = {
type: uid,
field: fieldName
};
const right = {};
if (kind === 'relation.basic' || kind === 'relation.circular') {
right.type = attribute.target;
right.field = attribute.inversedBy;
columns.left.ref = joinColumn.name;
columns.right.ref = inverseJoinColumn.name;
if (orderColumnName) {
columns.left.order = orderColumnName;
}
if (inverseOrderColumnName) {
columns.right.order = inverseOrderColumnName;
}
}
if (kind === 'relation.morph') {
columns.left.ref = joinColumn.name;
columns.right.ref = morphColumn.idColumn.name;
columns.right.type = morphColumn.typeColumn.name;
columns.right.field = 'field';
columns.right.order = 'order';
}
const validColumns = [
// Left
columns.left.ref,
columns.left.order,
// Right
columns.right.ref,
columns.right.type,
columns.right.field,
columns.right.order
].filter((column)=>!fp.isNil(column));
qb.select(validColumns);
if (trx) {
qb.transacting(trx);
}
// TODO: stream the query to improve performances
const entries = await qb;
for (const entry of entries){
if (columns.left.ref) {
left.ref = entry[columns.left.ref];
}
if (columns.right.ref) {
right.ref = entry[columns.right.ref];
}
if (columns.left.order) {
left.pos = entry[columns.left.order];
}
if (columns.right.order) {
right.pos = entry[columns.right.order];
}
if (columns.right.type) {
right.type = entry[columns.right.type];
}
if (columns.right.field) {
right.field = entry[columns.right.field];
}
const link = {
kind,
relation,
left: fp.clone(left),
right: fp.clone(right)
};
yield link;
}
}
if (attribute.morphColumn) {
const { typeColumn, idColumn } = attribute.morphColumn;
const qb = connection.queryBuilder().select('id', typeColumn.name, idColumn.name).from(addSchema(metadata.tableName)).whereNotNull(typeColumn.name).whereNotNull(idColumn.name);
if (trx) {
qb.transacting(trx);
}
const entries = await qb;
for (const entry of entries){
const ref = entry[idColumn.name];
yield {
kind,
relation,
left: {
type: uid,
ref: entry.id,
field: fieldName
},
right: {
type: entry[typeColumn.name],
ref
}
};
}
}
}
async function* generateAll(uid) {
const metadata = strapi.db.metadata.get(uid);
if (!metadata) {
throw new Error(`No metadata found for ${uid}`);
}
const attributes = filterValidRelationalAttributes(metadata.attributes);
for (const fieldName of Object.keys(attributes)){
for await (const link of generateAllForAttribute(uid, fieldName)){
yield link;
}
}
}
const insert = async (link)=>{
const { kind, left, right } = link;
const metadata = strapi.db.metadata.get(left.type);
const attribute = metadata.attributes[left.field];
const payload = {};
/**
* This _should_ only happen for attributes that are added dynamically e.g. review-workflow stages
* and a user is importing EE data into a CE project.
*/ if (!attribute) {
return;
}
if (attribute.type !== 'relation') {
throw new Error(`Attribute ${left.field} is not a relation`);
}
if ('joinColumn' in attribute && attribute.joinColumn) {
const joinColumnName = attribute.joinColumn.name;
// Note: this addSchema may not be necessary, but is added for safety
const qb = connection(addSchema(metadata.tableName)).where('id', left.ref).update({
[joinColumnName]: right.ref
});
if (trx) {
qb.transacting(trx);
}
await qb;
}
if ('joinTable' in attribute && attribute.joinTable) {
const { joinTable } = attribute;
if (joinTable.joinColumn) {
Object.assign(payload, {
[joinTable.joinColumn.name]: left.ref
});
}
const assignInverseColumn = ()=>{
if ('inverseJoinColumn' in joinTable && joinTable.inverseJoinColumn) {
Object.assign(payload, {
[joinTable.inverseJoinColumn.name]: right.ref
});
}
};
const assignOrderColumns = ()=>{
if ('orderColumnName' in joinTable && joinTable.orderColumnName) {
Object.assign(payload, {
[joinTable.orderColumnName]: left.pos ?? null
});
}
if ('inverseOrderColumnName' in joinTable && joinTable.inverseOrderColumnName) {
Object.assign(payload, {
[joinTable.inverseOrderColumnName]: right.pos ?? null
});
}
};
const assignMorphColumns = ()=>{
if ('morphColumn' in joinTable && joinTable.morphColumn) {
const { idColumn, typeColumn } = joinTable.morphColumn ?? {};
if (idColumn) {
Object.assign(payload, {
[idColumn.name]: right.ref
});
}
if (typeColumn) {
Object.assign(payload, {
[typeColumn.name]: right.type
});
}
Object.assign(payload, {
order: right.pos ?? null,
field: right.field ?? null
});
}
};
if (kind === 'relation.basic' || kind === 'relation.circular') {
assignInverseColumn();
}
if (kind === 'relation.morph') {
assignMorphColumns();
}
assignOrderColumns();
const qb = connection.insert(payload).into(addSchema(joinTable.name));
if (trx) {
await qb.transacting(trx);
}
}
if ('morphColumn' in attribute && attribute.morphColumn) {
const { morphColumn } = attribute;
const qb = connection(addSchema(metadata.tableName)).where('id', left.ref).update({
[morphColumn.idColumn.name]: right.ref,
[morphColumn.typeColumn.name]: right.type
});
if (trx) {
qb.transacting(trx);
}
await qb;
}
};
return {
generateAll,
generateAllForAttribute,
insert
};
};
return query;
};
const filterValidRelationalAttributes = (attributes)=>{
const isOwner = (attribute)=>{
return attribute.owner || !attribute.mappedBy && !attribute.morphBy;
};
const isComponentLike = (attribute)=>attribute.joinTable?.name.endsWith('_cmps');
return Object.entries(attributes).filter(([, attribute])=>{
return attribute.type === 'relation' && isOwner(attribute) && !isComponentLike(attribute);
}).reduce((acc, [key, attribute])=>({
...acc,
[key]: attribute
}), {});
};
const getLinkKind = (attribute, uid)=>{
if (attribute.relation.startsWith('morph')) {
return 'relation.morph';
}
if (attribute.target === uid) {
return 'relation.circular';
}
return 'relation.basic';
};
exports.createLinkQuery = createLinkQuery;
exports.filterValidRelationalAttributes = filterValidRelationalAttributes;
//# sourceMappingURL=link.js.map
@@ -0,0 +1 @@
{"version":3,"file":"link.js","sources":["../../../src/strapi/queries/link.ts"],"sourcesContent":["import type { Knex } from 'knex';\nimport { clone, isNil } from 'lodash/fp';\nimport type { Core } from '@strapi/types';\n\nimport { ILink } from '../../../types';\n\n// TODO: Remove any types when we'll have types for DB metadata\n\nexport const createLinkQuery = (strapi: Core.Strapi, trx?: Knex.Transaction) => {\n const query = () => {\n const { connection } = strapi.db;\n\n // TODO: Export utils from database and use the addSchema that is already written\n const addSchema = (tableName: string) => {\n const schemaName = connection.client.connectionSettings.schema;\n return schemaName ? `${schemaName}.${tableName}` : tableName;\n };\n\n async function* generateAllForAttribute(uid: string, fieldName: string): AsyncGenerator<ILink> {\n const metadata = strapi.db.metadata.get(uid);\n\n if (!metadata) {\n throw new Error(`No metadata found for ${uid}`);\n }\n\n const attributes = filterValidRelationalAttributes(metadata.attributes);\n\n if (!(fieldName in attributes)) {\n throw new Error(`${fieldName} is not a valid relational attribute name`);\n }\n\n const attribute = attributes[fieldName];\n\n const kind = getLinkKind(attribute, uid);\n const { relation, target } = attribute;\n\n // The relation is stored in the same table\n // TODO: handle manyToOne joinColumn\n if (attribute.joinColumn) {\n const joinColumnName: string = attribute.joinColumn.name;\n\n const qb = connection\n .queryBuilder()\n .select('id', joinColumnName)\n .from(addSchema(metadata.tableName));\n\n if (trx) {\n qb.transacting(trx);\n }\n\n // TODO: stream the query to improve performances\n const entries = await qb;\n\n for (const entry of entries) {\n const ref = entry[joinColumnName];\n\n if (ref !== null) {\n yield {\n kind,\n relation,\n left: { type: uid, ref: entry.id, field: fieldName },\n right: { type: target, ref },\n };\n }\n }\n }\n\n // The relation uses a join table\n if (attribute.joinTable) {\n const {\n name,\n joinColumn,\n inverseJoinColumn,\n orderColumnName,\n morphColumn,\n inverseOrderColumnName,\n } = attribute.joinTable;\n\n const qb = connection.queryBuilder().from(addSchema(name));\n\n type Columns = {\n left: { ref: string | null; order?: string };\n right: { ref: string | null; order?: string; type?: string; field?: string };\n };\n\n const columns: Columns = {\n left: { ref: null },\n right: { ref: null },\n };\n\n const left: Partial<ILink['left']> = { type: uid, field: fieldName };\n const right: Partial<ILink['right']> = {};\n\n if (kind === 'relation.basic' || kind === 'relation.circular') {\n right.type = attribute.target;\n right.field = attribute.inversedBy;\n\n columns.left.ref = joinColumn.name;\n columns.right.ref = inverseJoinColumn.name;\n\n if (orderColumnName) {\n columns.left.order = orderColumnName as string;\n }\n\n if (inverseOrderColumnName) {\n columns.right.order = inverseOrderColumnName as string;\n }\n }\n\n if (kind === 'relation.morph') {\n columns.left.ref = joinColumn.name;\n\n columns.right.ref = morphColumn.idColumn.name;\n columns.right.type = morphColumn.typeColumn.name;\n columns.right.field = 'field';\n columns.right.order = 'order';\n }\n\n const validColumns = [\n // Left\n columns.left.ref,\n columns.left.order,\n // Right\n columns.right.ref,\n columns.right.type,\n columns.right.field,\n columns.right.order,\n ].filter((column: string | null | undefined) => !isNil(column));\n\n qb.select(validColumns);\n\n if (trx) {\n qb.transacting(trx);\n }\n\n // TODO: stream the query to improve performances\n const entries = await qb;\n\n for (const entry of entries) {\n if (columns.left.ref) {\n left.ref = entry[columns.left.ref];\n }\n\n if (columns.right.ref) {\n right.ref = entry[columns.right.ref];\n }\n\n if (columns.left.order) {\n left.pos = entry[columns.left.order as string];\n }\n\n if (columns.right.order) {\n right.pos = entry[columns.right.order as string];\n }\n\n if (columns.right.type) {\n right.type = entry[columns.right.type as string];\n }\n\n if (columns.right.fiLine truncated
+295
View File
@@ -0,0 +1,295 @@
import { isNil, clone } from 'lodash/fp';
// TODO: Remove any types when we'll have types for DB metadata
const createLinkQuery = (strapi, trx)=>{
const query = ()=>{
const { connection } = strapi.db;
// TODO: Export utils from database and use the addSchema that is already written
const addSchema = (tableName)=>{
const schemaName = connection.client.connectionSettings.schema;
return schemaName ? `${schemaName}.${tableName}` : tableName;
};
async function* generateAllForAttribute(uid, fieldName) {
const metadata = strapi.db.metadata.get(uid);
if (!metadata) {
throw new Error(`No metadata found for ${uid}`);
}
const attributes = filterValidRelationalAttributes(metadata.attributes);
if (!(fieldName in attributes)) {
throw new Error(`${fieldName} is not a valid relational attribute name`);
}
const attribute = attributes[fieldName];
const kind = getLinkKind(attribute, uid);
const { relation, target } = attribute;
// The relation is stored in the same table
// TODO: handle manyToOne joinColumn
if (attribute.joinColumn) {
const joinColumnName = attribute.joinColumn.name;
const qb = connection.queryBuilder().select('id', joinColumnName).from(addSchema(metadata.tableName));
if (trx) {
qb.transacting(trx);
}
// TODO: stream the query to improve performances
const entries = await qb;
for (const entry of entries){
const ref = entry[joinColumnName];
if (ref !== null) {
yield {
kind,
relation,
left: {
type: uid,
ref: entry.id,
field: fieldName
},
right: {
type: target,
ref
}
};
}
}
}
// The relation uses a join table
if (attribute.joinTable) {
const { name, joinColumn, inverseJoinColumn, orderColumnName, morphColumn, inverseOrderColumnName } = attribute.joinTable;
const qb = connection.queryBuilder().from(addSchema(name));
const columns = {
left: {
ref: null
},
right: {
ref: null
}
};
const left = {
type: uid,
field: fieldName
};
const right = {};
if (kind === 'relation.basic' || kind === 'relation.circular') {
right.type = attribute.target;
right.field = attribute.inversedBy;
columns.left.ref = joinColumn.name;
columns.right.ref = inverseJoinColumn.name;
if (orderColumnName) {
columns.left.order = orderColumnName;
}
if (inverseOrderColumnName) {
columns.right.order = inverseOrderColumnName;
}
}
if (kind === 'relation.morph') {
columns.left.ref = joinColumn.name;
columns.right.ref = morphColumn.idColumn.name;
columns.right.type = morphColumn.typeColumn.name;
columns.right.field = 'field';
columns.right.order = 'order';
}
const validColumns = [
// Left
columns.left.ref,
columns.left.order,
// Right
columns.right.ref,
columns.right.type,
columns.right.field,
columns.right.order
].filter((column)=>!isNil(column));
qb.select(validColumns);
if (trx) {
qb.transacting(trx);
}
// TODO: stream the query to improve performances
const entries = await qb;
for (const entry of entries){
if (columns.left.ref) {
left.ref = entry[columns.left.ref];
}
if (columns.right.ref) {
right.ref = entry[columns.right.ref];
}
if (columns.left.order) {
left.pos = entry[columns.left.order];
}
if (columns.right.order) {
right.pos = entry[columns.right.order];
}
if (columns.right.type) {
right.type = entry[columns.right.type];
}
if (columns.right.field) {
right.field = entry[columns.right.field];
}
const link = {
kind,
relation,
left: clone(left),
right: clone(right)
};
yield link;
}
}
if (attribute.morphColumn) {
const { typeColumn, idColumn } = attribute.morphColumn;
const qb = connection.queryBuilder().select('id', typeColumn.name, idColumn.name).from(addSchema(metadata.tableName)).whereNotNull(typeColumn.name).whereNotNull(idColumn.name);
if (trx) {
qb.transacting(trx);
}
const entries = await qb;
for (const entry of entries){
const ref = entry[idColumn.name];
yield {
kind,
relation,
left: {
type: uid,
ref: entry.id,
field: fieldName
},
right: {
type: entry[typeColumn.name],
ref
}
};
}
}
}
async function* generateAll(uid) {
const metadata = strapi.db.metadata.get(uid);
if (!metadata) {
throw new Error(`No metadata found for ${uid}`);
}
const attributes = filterValidRelationalAttributes(metadata.attributes);
for (const fieldName of Object.keys(attributes)){
for await (const link of generateAllForAttribute(uid, fieldName)){
yield link;
}
}
}
const insert = async (link)=>{
const { kind, left, right } = link;
const metadata = strapi.db.metadata.get(left.type);
const attribute = metadata.attributes[left.field];
const payload = {};
/**
* This _should_ only happen for attributes that are added dynamically e.g. review-workflow stages
* and a user is importing EE data into a CE project.
*/ if (!attribute) {
return;
}
if (attribute.type !== 'relation') {
throw new Error(`Attribute ${left.field} is not a relation`);
}
if ('joinColumn' in attribute && attribute.joinColumn) {
const joinColumnName = attribute.joinColumn.name;
// Note: this addSchema may not be necessary, but is added for safety
const qb = connection(addSchema(metadata.tableName)).where('id', left.ref).update({
[joinColumnName]: right.ref
});
if (trx) {
qb.transacting(trx);
}
await qb;
}
if ('joinTable' in attribute && attribute.joinTable) {
const { joinTable } = attribute;
if (joinTable.joinColumn) {
Object.assign(payload, {
[joinTable.joinColumn.name]: left.ref
});
}
const assignInverseColumn = ()=>{
if ('inverseJoinColumn' in joinTable && joinTable.inverseJoinColumn) {
Object.assign(payload, {
[joinTable.inverseJoinColumn.name]: right.ref
});
}
};
const assignOrderColumns = ()=>{
if ('orderColumnName' in joinTable && joinTable.orderColumnName) {
Object.assign(payload, {
[joinTable.orderColumnName]: left.pos ?? null
});
}
if ('inverseOrderColumnName' in joinTable && joinTable.inverseOrderColumnName) {
Object.assign(payload, {
[joinTable.inverseOrderColumnName]: right.pos ?? null
});
}
};
const assignMorphColumns = ()=>{
if ('morphColumn' in joinTable && joinTable.morphColumn) {
const { idColumn, typeColumn } = joinTable.morphColumn ?? {};
if (idColumn) {
Object.assign(payload, {
[idColumn.name]: right.ref
});
}
if (typeColumn) {
Object.assign(payload, {
[typeColumn.name]: right.type
});
}
Object.assign(payload, {
order: right.pos ?? null,
field: right.field ?? null
});
}
};
if (kind === 'relation.basic' || kind === 'relation.circular') {
assignInverseColumn();
}
if (kind === 'relation.morph') {
assignMorphColumns();
}
assignOrderColumns();
const qb = connection.insert(payload).into(addSchema(joinTable.name));
if (trx) {
await qb.transacting(trx);
}
}
if ('morphColumn' in attribute && attribute.morphColumn) {
const { morphColumn } = attribute;
const qb = connection(addSchema(metadata.tableName)).where('id', left.ref).update({
[morphColumn.idColumn.name]: right.ref,
[morphColumn.typeColumn.name]: right.type
});
if (trx) {
qb.transacting(trx);
}
await qb;
}
};
return {
generateAll,
generateAllForAttribute,
insert
};
};
return query;
};
const filterValidRelationalAttributes = (attributes)=>{
const isOwner = (attribute)=>{
return attribute.owner || !attribute.mappedBy && !attribute.morphBy;
};
const isComponentLike = (attribute)=>attribute.joinTable?.name.endsWith('_cmps');
return Object.entries(attributes).filter(([, attribute])=>{
return attribute.type === 'relation' && isOwner(attribute) && !isComponentLike(attribute);
}).reduce((acc, [key, attribute])=>({
...acc,
[key]: attribute
}), {});
};
const getLinkKind = (attribute, uid)=>{
if (attribute.relation.startsWith('morph')) {
return 'relation.morph';
}
if (attribute.target === uid) {
return 'relation.circular';
}
return 'relation.basic';
};
export { createLinkQuery, filterValidRelationalAttributes };
//# sourceMappingURL=link.mjs.map
@@ -0,0 +1 @@
{"version":3,"file":"link.mjs","sources":["../../../src/strapi/queries/link.ts"],"sourcesContent":["import type { Knex } from 'knex';\nimport { clone, isNil } from 'lodash/fp';\nimport type { Core } from '@strapi/types';\n\nimport { ILink } from '../../../types';\n\n// TODO: Remove any types when we'll have types for DB metadata\n\nexport const createLinkQuery = (strapi: Core.Strapi, trx?: Knex.Transaction) => {\n const query = () => {\n const { connection } = strapi.db;\n\n // TODO: Export utils from database and use the addSchema that is already written\n const addSchema = (tableName: string) => {\n const schemaName = connection.client.connectionSettings.schema;\n return schemaName ? `${schemaName}.${tableName}` : tableName;\n };\n\n async function* generateAllForAttribute(uid: string, fieldName: string): AsyncGenerator<ILink> {\n const metadata = strapi.db.metadata.get(uid);\n\n if (!metadata) {\n throw new Error(`No metadata found for ${uid}`);\n }\n\n const attributes = filterValidRelationalAttributes(metadata.attributes);\n\n if (!(fieldName in attributes)) {\n throw new Error(`${fieldName} is not a valid relational attribute name`);\n }\n\n const attribute = attributes[fieldName];\n\n const kind = getLinkKind(attribute, uid);\n const { relation, target } = attribute;\n\n // The relation is stored in the same table\n // TODO: handle manyToOne joinColumn\n if (attribute.joinColumn) {\n const joinColumnName: string = attribute.joinColumn.name;\n\n const qb = connection\n .queryBuilder()\n .select('id', joinColumnName)\n .from(addSchema(metadata.tableName));\n\n if (trx) {\n qb.transacting(trx);\n }\n\n // TODO: stream the query to improve performances\n const entries = await qb;\n\n for (const entry of entries) {\n const ref = entry[joinColumnName];\n\n if (ref !== null) {\n yield {\n kind,\n relation,\n left: { type: uid, ref: entry.id, field: fieldName },\n right: { type: target, ref },\n };\n }\n }\n }\n\n // The relation uses a join table\n if (attribute.joinTable) {\n const {\n name,\n joinColumn,\n inverseJoinColumn,\n orderColumnName,\n morphColumn,\n inverseOrderColumnName,\n } = attribute.joinTable;\n\n const qb = connection.queryBuilder().from(addSchema(name));\n\n type Columns = {\n left: { ref: string | null; order?: string };\n right: { ref: string | null; order?: string; type?: string; field?: string };\n };\n\n const columns: Columns = {\n left: { ref: null },\n right: { ref: null },\n };\n\n const left: Partial<ILink['left']> = { type: uid, field: fieldName };\n const right: Partial<ILink['right']> = {};\n\n if (kind === 'relation.basic' || kind === 'relation.circular') {\n right.type = attribute.target;\n right.field = attribute.inversedBy;\n\n columns.left.ref = joinColumn.name;\n columns.right.ref = inverseJoinColumn.name;\n\n if (orderColumnName) {\n columns.left.order = orderColumnName as string;\n }\n\n if (inverseOrderColumnName) {\n columns.right.order = inverseOrderColumnName as string;\n }\n }\n\n if (kind === 'relation.morph') {\n columns.left.ref = joinColumn.name;\n\n columns.right.ref = morphColumn.idColumn.name;\n columns.right.type = morphColumn.typeColumn.name;\n columns.right.field = 'field';\n columns.right.order = 'order';\n }\n\n const validColumns = [\n // Left\n columns.left.ref,\n columns.left.order,\n // Right\n columns.right.ref,\n columns.right.type,\n columns.right.field,\n columns.right.order,\n ].filter((column: string | null | undefined) => !isNil(column));\n\n qb.select(validColumns);\n\n if (trx) {\n qb.transacting(trx);\n }\n\n // TODO: stream the query to improve performances\n const entries = await qb;\n\n for (const entry of entries) {\n if (columns.left.ref) {\n left.ref = entry[columns.left.ref];\n }\n\n if (columns.right.ref) {\n right.ref = entry[columns.right.ref];\n }\n\n if (columns.left.order) {\n left.pos = entry[columns.left.order as string];\n }\n\n if (columns.right.order) {\n right.pos = entry[columns.right.order as string];\n }\n\n if (columns.right.type) {\n right.type = entry[columns.right.type as string];\n }\n\n if (columns.right.fLine truncated